diff --git a/.forgejo/workflows/format.yaml b/.forgejo/workflows/format.yaml new file mode 100644 index 0000000..804c1ee --- /dev/null +++ b/.forgejo/workflows/format.yaml @@ -0,0 +1,17 @@ +name: Format + +run-name: ${{ github.actor }} is formatting + +on: [ push, pull_request ] + +jobs: + formatting: + runs-on: docker + steps: + - uses: actions/checkout@v4 + - uses: axel-op/googlejavaformat-action@v3 + with: + args: "--replace" + skip-commit: true + - name: Print diffs + run: git --no-pager diff --exit-code \ No newline at end of file diff --git a/README.md b/README.md index afbdc1f..55662c1 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,6 @@ see [docs](https://git.unurled.me/SacredRealms/docs) for more information - [Java 17](https://adoptium.net/temurin/releases/?version=17) - [PaperMC 1.20.6](https://papermc.io/downloads/paper) or any fork of it (purpur, etc) -- a build of the plugin \ No newline at end of file +- a build of the plugin + +spigot plugin development 90 replay plugin - 1:43:02 \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 92660dc..a083649 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ import net.minecrell.pluginyml.bukkit.BukkitPluginDescription plugins { `java-library` - id("io.papermc.paperweight.userdev") version "1.7.2" + id("io.papermc.paperweight.userdev") version "1.7.3" id("org.sonarqube") version "5.1.0.4882" id("net.minecrell.plugin-yml.paper") version "0.6.0" } @@ -36,6 +36,10 @@ repositories { name = "unurled" url = uri("https://repo.unurled.me/releases") } + maven { + name = "cubbossa" + url = uri("https://nexus.leonardbausenwein.de/repository/maven-releases/") + } } dependencies { @@ -47,9 +51,9 @@ dependencies { paperLibrary("redis.clients", "jedis", redisVersion) - paperLibrary("com.github.retrooper", "packetevents-spigot", "2.4.0") + paperLibrary("com.github.retrooper", "packetevents-spigot", "2.5.0") - paperLibrary("me.unurled", "SR-Core", "0.1.0") + compileOnly("me.unurled:SR-Core:0.1.1") } java { @@ -106,7 +110,7 @@ paper { "sr.resetadventure", "sr.treasure.manage", "sr.difficulty.*", - "sr.cutscene" + "sr.cutscene.*" ) description = "Gives access to all Sacred Realms permissions." } @@ -151,6 +155,10 @@ paper { } register("sr.cutscene") { description = "Gives access to the cutscene command." + children = listOf( + "sr.cutscene.create", + "sr.cutscene.replay" + ) } } } \ No newline at end of file diff --git a/src/main/java/me/unurled/sacredrealms/sr/SR.java b/src/main/java/me/unurled/sacredrealms/sr/SR.java index 6959e34..0baf423 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/SR.java +++ b/src/main/java/me/unurled/sacredrealms/sr/SR.java @@ -6,6 +6,9 @@ import java.util.List; import me.unurled.sacredrealms.sr.components.block.BlockManager; import me.unurled.sacredrealms.sr.components.clientbuild.ClientBuildManager; import me.unurled.sacredrealms.sr.components.combat.CombatManager; +import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager; +import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager; +import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager; import me.unurled.sacredrealms.sr.components.entity.EntityManager; import me.unurled.sacredrealms.sr.components.item.ItemManager; import me.unurled.sacredrealms.sr.components.npc.NPCManager; @@ -31,6 +34,7 @@ public final class SR extends JavaPlugin { @Override public void onLoad() { PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); + PacketEvents.getAPI().getSettings().reEncodeByDefault(false).checkForUpdates(true); // On Bukkit, calling this here is essential, hence the name "load" PacketEvents.getAPI().load(); } @@ -39,10 +43,10 @@ public final class SR extends JavaPlugin { public void onEnable() { plugin = this; - SRCore.getInstance().setPlugin(this); - PacketEvents.getAPI().init(); + SRCore.getInstance().setPlugin(this); + InvUI.getInstance().setPlugin(this); SRCore.getInstance() @@ -61,7 +65,10 @@ public final class SR extends JavaPlugin { ClientBuildManager.class, TreasureManager.class, BackgroundManager.class, - ResourcePackManager.class)); + ResourcePackManager.class, + CutsceneManager.class, + RecordingManager.class, + ReplayManager.class)); } @Override diff --git a/src/main/java/me/unurled/sacredrealms/sr/SRLoader.java b/src/main/java/me/unurled/sacredrealms/sr/SRLoader.java index 439162a..07ba1d0 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/SRLoader.java +++ b/src/main/java/me/unurled/sacredrealms/sr/SRLoader.java @@ -25,6 +25,11 @@ public class SRLoader implements PluginLoader { resolver.addRepository( new RemoteRepository.Builder("invui", "default", "https://repo.xenondevs.xyz/releases/") .build()); + + resolver.addDependency(new Dependency(new DefaultArtifact("me.unurled:SR-Core:0.1.1"), null)); + resolver.addRepository( + new RemoteRepository.Builder("srcore", "default", "https://repo.unurled.me/releases") + .build()); classpathBuilder.addLibrary(resolver); PluginLibraries pluginLibraries = load(); diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java index 929c597..aaae323 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java @@ -11,12 +11,14 @@ import java.util.Collection; import java.util.List; import me.unurled.sacredrealms.sr.commands.admin.AttributeCommand; import me.unurled.sacredrealms.sr.commands.admin.ClientBuildCommand; -import me.unurled.sacredrealms.sr.commands.admin.CutsceneCommand; import me.unurled.sacredrealms.sr.commands.admin.EntityTypeCommand; import me.unurled.sacredrealms.sr.commands.admin.ItemCommand; import me.unurled.sacredrealms.sr.commands.admin.LevelCommand; import me.unurled.sacredrealms.sr.commands.admin.SpawnEntityCommand; import me.unurled.sacredrealms.sr.commands.admin.TreasureCommand; +import me.unurled.sacredrealms.sr.commands.admin.cutscene.CreateCutsceneCommand; +import me.unurled.sacredrealms.sr.commands.admin.cutscene.RecordCutsceneCommand; +import me.unurled.sacredrealms.sr.commands.admin.cutscene.StopRecordingCommand; import me.unurled.sacredrealms.sr.commands.player.DifficultyCommand; import me.unurled.sacredrealms.sr.commands.player.ResetAdventureCommand; import me.unurled.srcore.api.Manager; @@ -51,7 +53,6 @@ public class CommandManager extends Manager { } public static void loadCommands(BootstrapContext ctx) { - registerCommand("attributes", "Set the attributes of the player.", ctx, AttributeCommand.class); registerCommand( "clientbuild", "Set the client build of the player.", ctx, ClientBuildCommand.class); @@ -66,6 +67,17 @@ public class CommandManager extends Manager { registerCommand( "difficulty", "Set the difficulty of the player.", ctx, DifficultyCommand.class); - registerCommand("cutscene", "Cutscene commands.", List.of("cs"), ctx, CutsceneCommand.class); + registerCommand("createcustcene", "Create a new Cutscene", ctx, CreateCutsceneCommand.class); + + registerCommand( + "recordcutscene", + "Record a cutscene entity movement and everything", + ctx, + RecordCutsceneCommand.class); + registerCommand( + "stopcutscene", + "stop a record of a cutscene entity movement and everything", + ctx, + StopRecordingCommand.class); } } diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/AttributeCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/AttributeCommand.java index 6b7b180..d251202 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/AttributeCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/AttributeCommand.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.commands.admin; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer; import io.papermc.paper.command.brigadier.BasicCommand; diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ClientBuildCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ClientBuildCommand.java index 4ab0f51..1eacfe9 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ClientBuildCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ClientBuildCommand.java @@ -1,7 +1,7 @@ package me.unurled.sacredrealms.sr.commands.admin; -import static me.unurled.sacredrealms.sr.utils.Component.ERROR; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.ERROR; +import static me.unurled.srcore.utils.Component.textComp; import static me.unurled.sacredrealms.sr.utils.Logger.log; import io.papermc.paper.command.brigadier.BasicCommand; diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/CutsceneCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/CutsceneCommand.java deleted file mode 100644 index 5cc580f..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/CutsceneCommand.java +++ /dev/null @@ -1,166 +0,0 @@ -package me.unurled.sacredrealms.sr.commands.admin; - -import static me.unurled.sacredrealms.sr.utils.Component.textComp; - -import io.papermc.paper.command.brigadier.BasicCommand; -import io.papermc.paper.command.brigadier.CommandSourceStack; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import me.unurled.sacredrealms.sr.components.cutscene.Cutscene; -import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager; -import me.unurled.srcore.api.Manager; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class CutsceneCommand implements BasicCommand { - - private CutsceneManager cutsceneManager; - - /** - * Returns the permission for the root command used in {@link #canUse(CommandSender)} by default. - * - * @return the permission for the root command used in {@link #canUse(CommandSender)} - */ - @Override - public @Nullable String permission() { - return "cutscenes.admin"; - } - - /** - * Executes the command with the given {@link CommandSourceStack} and arguments. - * - * @param sender the commandSourceStack of the command - * @param args the arguments of the command ignoring repeated spaces - */ - @Override - public void execute(@NotNull CommandSourceStack sender, @NotNull String @NotNull [] args) { - if (cutsceneManager == null) { - cutsceneManager = Manager.getInstance(CutsceneManager.class); - } - // /cs stop, list, reload, play, create, remove - if (args.length == 1) { - if (args[0].equals("stop")) { - if (sender.getSender() instanceof Player p) { - cutsceneManager.stopCutscene(p); - } else { - sender - .getSender() - .sendMessage( - textComp("You must be a player to stop a cutscene. Use /cs stop ")); - } - } else if (args[0].equals("list")) { - sender - .getSender() - .sendMessage( - textComp("Cutscenes: " + cutsceneManager.getCutscenesId().toString())); - } else if (args[0].equals("reload")) { - - } - } else if (args.length == 2) { - if (args[0].equals("play")) { - if (sender.getSender() instanceof Player p) { - Cutscene cutscene = cutsceneManager.getCutscene(args[1]); - cutsceneManager.playCutscene(cutscene, p); - } else { - sender - .getSender() - .sendMessage( - textComp( - "You must be a player to play a cutscene. Use /cs play ")); - } - } else if (args[0].equals("stop")) { - Player p = Bukkit.getPlayer(args[1]); - if (p != null) { - cutsceneManager.stopCutscene(p); - } - } else if (args[0].equals("create")) { - String name = args[1]; - cutsceneManager.createCutscene(name); - sender.getSender().sendMessage(textComp("Created cutscene " + name)); - } else if (args[0].equals("remove")) { - String name = args[1]; - cutsceneManager.removeCutscene(name); - sender.getSender().sendMessage(textComp("Removed cutscene " + name)); - } - } else if (args.length == 3) { - if (args[0].equals("play")) { - Player p = Bukkit.getPlayer(args[2]); - if (p != null) { - Cutscene cutscene = cutsceneManager.getCutscene(args[1]); - cutsceneManager.playCutscene(cutscene, p); - } - } - } else { - sender - .getSender() - .sendMessage( - textComp( - "Usage: /cs ")); - } - } - - /** - * Suggests possible completions for the given command {@link CommandSourceStack} and arguments. - * - * @param sender the commandSourceStack of the command - * @param args the arguments of the command including repeated spaces - * @return a collection of suggestions - */ - @Override - public @NotNull Collection suggest( - @NotNull CommandSourceStack sender, @NotNull String[] args) { - if (cutsceneManager == null) { - cutsceneManager = Manager.getInstance(CutsceneManager.class); - } - List complete = new ArrayList<>(); - complete.add("stop"); - if (sender.getSender().hasPermission("cutscenes.admin")) { - complete.add("play"); - complete.add("list"); - complete.add("reload"); - complete.add("create"); - complete.add("remove"); - } - List result = new ArrayList<>(); - if (args.length == 1) { - for (String s : complete) { - if (s.toLowerCase().startsWith(args[0].toLowerCase())) { - result.add(s); - } - } - return result; - } else if (args.length == 2) { - if (sender.getSender().hasPermission("cutscenes.admin")) { - if (args[0].equalsIgnoreCase("stop")) { - for (Player p : Bukkit.getOnlinePlayers()) { - if (p.getName().toLowerCase().startsWith(args[1].toLowerCase())) { - result.add(p.getName()); - } - } - } else if (args[0].equalsIgnoreCase("play") || args[0].equalsIgnoreCase("remove")) { - for (String s : cutsceneManager.getCutscenesId()) { - if (s.toLowerCase().startsWith(args[1].toLowerCase())) { - result.add(s); - } - } - } - } - return result; - } else if (args.length == 3) { - if (sender.getSender().hasPermission("cutscenes.admin")) { - if (args[0].equalsIgnoreCase("play")) { - for (Player p : Bukkit.getOnlinePlayers()) { - if (p.getName().toLowerCase().startsWith(args[2].toLowerCase())) { - result.add(p.getName()); - } - } - } - } - } - return List.of(); - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/EntityTypeCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/EntityTypeCommand.java index 995d798..20b029c 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/EntityTypeCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/EntityTypeCommand.java @@ -1,8 +1,8 @@ package me.unurled.sacredrealms.sr.commands.admin; -import static me.unurled.sacredrealms.sr.utils.Component.NOT_PLAYER; -import static me.unurled.sacredrealms.sr.utils.Component.comp; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.NOT_PLAYER; +import static me.unurled.srcore.utils.Component.comp; +import static me.unurled.srcore.utils.Component.textComp; import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.CommandSourceStack; diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ItemCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ItemCommand.java index b26d54d..4c6f782 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ItemCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ItemCommand.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.commands.admin; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import static me.unurled.sacredrealms.sr.utils.Logger.error; import io.papermc.paper.command.brigadier.BasicCommand; diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/SpawnEntityCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/SpawnEntityCommand.java index d4c2c01..d7edb66 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/SpawnEntityCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/SpawnEntityCommand.java @@ -1,7 +1,7 @@ package me.unurled.sacredrealms.sr.commands.admin; -import static me.unurled.sacredrealms.sr.utils.Component.NO_PERMISSION; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.NO_PERMISSION; +import static me.unurled.srcore.utils.Component.textComp; import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.CommandSourceStack; diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java index aef590a..ebe5beb 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java @@ -1,7 +1,7 @@ package me.unurled.sacredrealms.sr.commands.admin; -import static me.unurled.sacredrealms.sr.utils.Component.NOT_PLAYER; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.NOT_PLAYER; +import static me.unurled.srcore.utils.Component.textComp; import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.CommandSourceStack; diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/CreateCutsceneCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/CreateCutsceneCommand.java new file mode 100644 index 0000000..9522b80 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/CreateCutsceneCommand.java @@ -0,0 +1,53 @@ +package me.unurled.sacredrealms.sr.commands.admin.cutscene; + +import static me.unurled.srcore.utils.Component.NOT_PLAYER; +import static me.unurled.srcore.utils.Component.NO_PERMISSION; +import static me.unurled.srcore.utils.Component.textComp; + +import io.papermc.paper.command.brigadier.BasicCommand; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import java.util.Collection; +import java.util.List; +import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager; +import me.unurled.srcore.api.Manager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class CreateCutsceneCommand implements BasicCommand { + + private CutsceneManager cm; + + @Override + public void execute(@NotNull CommandSourceStack sender, String[] args) { + if (!(sender.getSender() instanceof Player p)) { + sender.getSender().sendMessage(textComp(NOT_PLAYER)); + return; + } + if (!p.hasPermission("sr.cutscene.create")) { + p.sendMessage(textComp(NO_PERMISSION)); + return; + } + // get the name + if (args.length < 1) { + p.sendMessage("Usage: /cs "); + return; + } + String name = args[0]; + // create the cutscene + + if (cm == null) { + cm = Manager.getInstance(CutsceneManager.class); + } + + cm.startCreatingCutscene(p, name); + } + + @Override + public Collection suggest( + CommandSourceStack commandSourceStack, String @NotNull [] args) { + if (args.length == 1) { + return List.of("name"); + } + return BasicCommand.super.suggest(commandSourceStack, args); + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/RecordCutsceneCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/RecordCutsceneCommand.java new file mode 100644 index 0000000..f496017 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/RecordCutsceneCommand.java @@ -0,0 +1,51 @@ +package me.unurled.sacredrealms.sr.commands.admin.cutscene; + +import static me.unurled.srcore.utils.Component.NO_PERMISSION; +import static me.unurled.srcore.utils.Component.textComp; + +import io.papermc.paper.command.brigadier.BasicCommand; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import me.unurled.sacredrealms.sr.components.cutscene.Cutscene; +import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager; +import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording; +import me.unurled.srcore.api.Manager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class RecordCutsceneCommand implements BasicCommand { + + private RecordingManager rm; + + @Override + public void execute(@NotNull CommandSourceStack stack, String[] args) { + if (!(stack.getSender() instanceof Player p)) { + return; + } + + if (!p.hasPermission("sr.cutscene.create")) { + p.sendMessage(textComp(NO_PERMISSION)); + return; + } + + if (rm == null) { + rm = Manager.getInstance(RecordingManager.class); + } + + Recording activeRecording = rm.getPlayerActiveRecording(p); + if (activeRecording != null) { + p.sendMessage("You are already recording a cutscene."); + return; + } + + Cutscene cutscene = + Manager.getInstance(CutsceneManager.class).getCutsceneBeingCreated(p.getUniqueId()); + if (cutscene == null) { + p.sendMessage("You are not creating a cutscene."); + return; + } + activeRecording = new Recording(cutscene, p); + + // open menu for selection cutscene + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/ReplayCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/ReplayCommand.java new file mode 100644 index 0000000..185d14e --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/ReplayCommand.java @@ -0,0 +1,33 @@ +package me.unurled.sacredrealms.sr.commands.admin.cutscene; + +import static me.unurled.srcore.utils.Component.NOT_PLAYER; +import static me.unurled.srcore.utils.Component.NO_PERMISSION; +import static me.unurled.srcore.utils.Component.textComp; + +import io.papermc.paper.command.brigadier.BasicCommand; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import java.util.Collection; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class ReplayCommand implements BasicCommand { + + @Override + public void execute(@NotNull CommandSourceStack stack, String[] args) { + if (!(stack.getSender() instanceof Player p)) { + stack.getSender().sendMessage(textComp(NOT_PLAYER)); + return; + } + + if (!p.hasPermission("sr.cutscene.replay")) { + p.sendMessage(textComp(NO_PERMISSION)); + } + + // aaa + } + + @Override + public Collection suggest(CommandSourceStack stack, String[] args) { + return BasicCommand.super.suggest(stack, args); + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/StopRecordingCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/StopRecordingCommand.java new file mode 100644 index 0000000..33882e0 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/cutscene/StopRecordingCommand.java @@ -0,0 +1,35 @@ +package me.unurled.sacredrealms.sr.commands.admin.cutscene; + +import static me.unurled.srcore.utils.Component.NOT_PLAYER; +import static me.unurled.srcore.utils.Component.NO_PERMISSION; +import static me.unurled.srcore.utils.Component.textComp; + +import io.papermc.paper.command.brigadier.BasicCommand; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import java.util.Collection; +import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager; +import me.unurled.srcore.api.Manager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class StopRecordingCommand implements BasicCommand { + + @Override + public void execute(@NotNull CommandSourceStack stack, String[] args) { + if (!(stack.getSender() instanceof Player p)) { + stack.getSender().sendMessage(textComp(NOT_PLAYER)); + return; + } + if (!p.hasPermission("sr.cutscene.create")) { + p.sendMessage(textComp(NO_PERMISSION)); + return; + } + + Manager.getInstance(RecordingManager.class).stopRecording(p); + } + + @Override + public Collection suggest(CommandSourceStack commandSourceStack, String[] args) { + return BasicCommand.super.suggest(commandSourceStack, args); + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/player/DifficultyCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/player/DifficultyCommand.java index 31f0ec8..200bda9 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/player/DifficultyCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/player/DifficultyCommand.java @@ -1,9 +1,9 @@ package me.unurled.sacredrealms.sr.commands.player; -import static me.unurled.sacredrealms.sr.utils.Component.NOT_PLAYER; -import static me.unurled.sacredrealms.sr.utils.Component.NO_PERMISSION; -import static me.unurled.sacredrealms.sr.utils.Component.PLAYER_NOT_FOUND; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.NOT_PLAYER; +import static me.unurled.srcore.utils.Component.NO_PERMISSION; +import static me.unurled.srcore.utils.Component.PLAYER_NOT_FOUND; +import static me.unurled.srcore.utils.Component.textComp; import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.CommandSourceStack; diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java index 2d69158..923499b 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/player/ResetAdventureCommand.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.commands.player; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.CommandSourceStack; diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/block/BlockItem.java b/src/main/java/me/unurled/sacredrealms/sr/components/block/BlockItem.java index e61443d..8926f4a 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/block/BlockItem.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/block/BlockItem.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.components.block; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import static me.unurled.sacredrealms.sr.utils.Logger.error; import java.util.ArrayList; diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/combat/CombatManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/combat/CombatManager.java index 10ec8f0..cebdb43 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/combat/CombatManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/combat/CombatManager.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.components.combat; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.spawnIndicator; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.updateActionBar; diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Action.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Action.java deleted file mode 100644 index f398c8e..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Action.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene; - -import java.util.List; -import org.bukkit.Location; -import org.bukkit.block.data.BlockData; -import org.bukkit.entity.Entity; - -public enum Action { - IDLE(), - MOVE(Location.class), - TELEPORT(Location.class), - SPAWN(Location.class), - DESPAWN(), - HIT(Entity.class), - SNEAK(), - JUMP(), - PLACE(Location.class, BlockData.class), - INTERACT(Location.class, org.bukkit.event.block.Action.class), - BREAK(Location.class); - - private final List types; - - Action(Class... types) { - this.types = List.of(types); - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/CreationListener.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/CreationListener.java new file mode 100644 index 0000000..12f0023 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/CreationListener.java @@ -0,0 +1,121 @@ +package me.unurled.sacredrealms.sr.components.cutscene; + +import static me.unurled.srcore.utils.Component.textComp; +import static org.bukkit.Material.RED_WOOL; + +import me.unurled.sacredrealms.sr.utils.Region; +import me.unurled.sacredrealms.sr.utils.RegionUtil; +import me.unurled.srcore.api.Manager; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.jetbrains.annotations.NotNull; + +public class CreationListener implements Listener { + + private CutsceneManager cm; + + @EventHandler + public void onInventoryClick(@NotNull InventoryClickEvent e) { + if (e.getWhoClicked() instanceof Player p) { + if (cm == null) { + cm = Manager.getInstance(CutsceneManager.class); + } + + Cutscene cutscene = cm.getCutsceneBeingCreated(p.getUniqueId()); + if (cutscene == null) { + return; + } + + e.setCancelled(true); + } + } + + @EventHandler + public void onRightClick(@NotNull PlayerInteractEvent e) { + if (!e.getAction().isRightClick()) { + return; + } + + Player p = e.getPlayer(); + if (cm == null) { + cm = Manager.getInstance(CutsceneManager.class); + } + + Cutscene cutscene = cm.getCutsceneBeingCreated(p.getUniqueId()); + + if (cutscene == null) { + return; + } + e.setCancelled(true); + + if (e.getItem() == null) { + return; + } + + switch (e.getItem().getType()) { + case BARRIER -> { + RegionUtil.killSelectorsWithTag(cutscene.name()); + cm.cancelCreatingCutscene(p); + } + case EMERALD_BLOCK -> { + if (cutscene.pos1() == null) { + p.sendMessage(textComp("Pos1 not set. Click on Red Wool.")); + return; + } + if (cutscene.pos2() == null) { + p.sendMessage(textComp("Pos2 not set. Click on Blue Wool.")); + return; + } + cm.finishCreatingCutscene(p); + RegionUtil.killSelectorsWithTag(cutscene.name()); + } + case RED_WOOL, BLUE_WOOL -> { + Location loc = null; + if (e.getAction() == Action.RIGHT_CLICK_BLOCK && e.getClickedBlock() != null) { + loc = e.getClickedBlock().getLocation(); + } else if (e.getAction() == Action.RIGHT_CLICK_AIR) { + loc = e.getPlayer().getLocation(); + } + if (e.getItem().getType() == RED_WOOL) { + p.sendMessage(textComp("Pos1 set.")); + cutscene.setPos1(loc); + } else { + p.sendMessage(textComp("Pos2 set.")); + cutscene.setPos2(loc); + } + + if (cutscene.pos1() != null && cutscene.pos2() != null) { + Region region = new Region(); + region.setCorner1(cutscene.pos1()); + region.setCorner2(cutscene.pos2()); + if (loc == null) return; + RegionUtil.killSelectorsWithTag(cutscene.name()); + RegionUtil.drawSelector(region, loc.getWorld(), cutscene.name(), NamedTextColor.GREEN); + p.sendMessage( + textComp( + "You have set both corners! Right click the Emerald block to finish.")); + } else if (cutscene.pos1() != null && cutscene.pos2() == null) { + Region region = new Region(); + region.setCorner1(cutscene.pos1()); + region.setCorner2(cutscene.pos1()); + if (loc == null) return; + RegionUtil.killSelectorsWithTag(cutscene.name()); + RegionUtil.drawSelector(region, loc.getWorld(), cutscene.name(), NamedTextColor.YELLOW); + } else if (cutscene.pos1() == null && cutscene.pos2() != null) { + Region region = new Region(); + region.setCorner1(cutscene.pos2()); + region.setCorner2(cutscene.pos2()); + if (loc == null) return; + RegionUtil.killSelectorsWithTag(cutscene.name()); + RegionUtil.drawSelector(region, loc.getWorld(), cutscene.name(), NamedTextColor.YELLOW); + } + } + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Cutscene.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Cutscene.java index d0e109c..7a0fd07 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Cutscene.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Cutscene.java @@ -1,239 +1,80 @@ package me.unurled.sacredrealms.sr.components.cutscene; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; -import static me.unurled.sacredrealms.sr.utils.CutsceneUtil.showBlackScreen; -import static me.unurled.sacredrealms.sr.utils.Logger.error; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.UUID; -import me.unurled.sacredrealms.sr.SR; -import me.unurled.srcore.api.Manager; -import net.kyori.adventure.text.Component; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; -/** - * Cutscene class - * - *

Represents a cutscene - * - *

{@code
- * {
- *   "id": "cutscene1",
- *   "name": "Cutscene 1",
- *   "markers": [1, 2, 3], // Marker IDs
- *   "start": {
- *      "world": "world",
- *      "x": 0,
- *      "y": 0,
- *      "z": 0,
- *      "yaw": 0,
- *      "pitch": 0
- *   },
- *   "end": {
- *      "world": "world",
- *      "x": 0,
- *      "y": 0,
- *      "z": 0,
- *      "yaw": 0,
- *      "pitch": 0
- *    }
- *    "blackBorders": true,
- *    "startFadeToBlack": true,
- *    "endFadeToBlack": true
- * }
- * }
- */ public class Cutscene { - private final String id; - private final String name; - private final List markers; - private final List markerIds; - private CutsceneManager cutsceneManager; - private Location start; - private Location end; - private Map tasks; - private boolean blackBorders; - private boolean startFadeToBlack; - private boolean endFadeToBlack; + private UUID id = UUID.randomUUID(); + private String name; + private Location pos1; + private Location pos2; - public Cutscene(String id, String name) { + public Cutscene() {} + + public Cutscene(String name) { + this.name = name; + } + + public Cutscene(UUID id, String name, Location pos1, Location pos2) { this.id = id; this.name = name; - this.markers = new ArrayList<>(); - this.markerIds = new ArrayList<>(); - this.tasks = new HashMap<>(); - cutsceneManager = Manager.getInstance(CutsceneManager.class); - if (cutsceneManager == null) { - error("CutsceneManager is null, could not create a Cutscene"); - } + this.pos1 = pos1; + this.pos2 = pos2; } - public Cutscene(@NotNull String id, String name, @NotNull ArrayList markers) { - this.id = id.toUpperCase(); + public boolean isInRegion(@NotNull Location location) { + double x1 = pos1.getX(); + double x2 = pos2.getX(); + double y1 = pos1.getY(); + double y2 = pos2.getY(); + double z1 = pos1.getZ(); + double z2 = pos2.getZ(); + double x = location.getX(); + double y = location.getY(); + double z = location.getZ(); + return x >= Math.min(x1, x2) + && x <= Math.max(x1, x2) + && y >= Math.min(y1, y2) + && y <= Math.max(y1, y2) + && z >= Math.min(z1, z2) + && z <= Math.max(z1, z2); + } + + public UUID id() { + return id; + } + + public Cutscene setId(UUID id) { + this.id = id; + return this; + } + + public String name() { + return name; + } + + public Cutscene setName(String name) { this.name = name; - this.markers = markers; - markerIds = new ArrayList<>(); - for (Marker marker : markers) { - markerIds.add(marker.getId()); - } - if (markers.isEmpty()) return; - if (markers.getFirst().getFrames().isEmpty()) return; - start = markers.getFirst().getFrames().getFirst().getLocation(); - end = markers.getLast().getFrames().getLast().getLocation(); - this.tasks = new HashMap<>(); - cutsceneManager = Manager.getInstance(CutsceneManager.class); - if (cutsceneManager == null) { - error("CutsceneManager is null, could not create a Cutscene"); - } + return this; } - public void setMarkers() { - for (Integer i : markerIds) { - markers.add(Marker.getMarker(i)); - } + public Location pos1() { + return pos1; } - public void addMarker(Marker marker) { - this.markers.add(marker); + public Cutscene setPos1(Location pos1) { + this.pos1 = pos1; + return this; } - public String getId() { - return this.id.toUpperCase(); + public Location pos2() { + return pos2; } - public String getName() { - return this.name; - } - - public List getMarkers() { - return this.markers; - } - - public Location getStart() { - return this.start; - } - - public void setStart(Location start) { - this.start = start; - } - - public Location getEnd() { - return this.end; - } - - public void setEnd(Location end) { - this.end = end; - } - - public void addMarkerId(Integer id) { - this.markerIds.add(id); - } - - public long time() { - long time = 0; - for (Marker marker : this.markers) { - if (marker.getOverAllTime() != null) time += marker.getOverAllTime(); - } - return time; - } - - public void play(@NotNull Player p) { - if (cutsceneManager.isPlayingCutscene(p)) { - p.sendMessage(textComp("You are already playing a cutscene!")); - } - cutsceneManager.addCurrentPlayingCutscene(this, p); - - // hide toolbar and make it spectate entity - p.setGameMode(GameMode.SPECTATOR); - - // set black borders - if (blackBorders) { - p.getInventory().setHelmet(new ItemStack(Material.PUMPKIN)); - p.updateInventory(); - } - - if (startFadeToBlack) { - showBlackScreen(p, 2, 1, 1); - } - - BukkitTask task = - Bukkit.getScheduler() - .runTaskAsynchronously( - SR.getPlugin(), - () -> { - int finalI = 0; - for (Marker marker : markers) { - for (int i = 0; i < marker.getFrames().size(); i++) { - int finalI1 = i; - Bukkit.getScheduler() - .runTaskLater( - SR.getPlugin(), - () -> { - p.teleport(marker.getFrames().get(finalI1).getLocation()); - marker.getFrames().get(finalI1).play(); - }, - (marker.getTimeBetweenFrames() * finalI) / 50); - finalI++; - } - } - if (endFadeToBlack) { - Bukkit.getScheduler() - .runTask(SR.getPlugin(), () -> showBlackScreen(p, 2, 1, 1)); - } - }); - Bukkit.getScheduler() - .runTaskAsynchronously( - SR.getPlugin(), - () -> { - try { - Thread.sleep(time()); - } catch (InterruptedException e) { - error("Error while playing cutscene: " + e.getMessage()); - } - Bukkit.getScheduler().runTask(SR.getPlugin(), () -> stop(p)); - }); - tasks.put(p.getUniqueId(), task); - } - - public void stop(UUID player) { - Player p = Bukkit.getPlayer(player); - if (p == null) return; - stop(p); - } - - public void stop(@NotNull Player p) { - if (cutsceneManager.isPlayingCutscene(p)) { - if (cutsceneManager.getPlayingCutscene(p).equals(this.id)) { - cutsceneManager.removeCurrentPlayingCutscene(this, p); - tasks.get(p.getUniqueId()).cancel(); - p.sendMessage(Component.text("You stopped playing the cutscene!")); - } - } else { - p.sendMessage(Component.text("You are not playing a cutscene!")); - } - } - - public void calculateMarkers() { - if (markers.isEmpty()) return; - for (int i = 0; i < markers.size(); i++) { - if (i < markers.size() - 1) { - markers.get(i).calculateFrames(markers.get(i + 1)); - } else { - ArrayList frames = new ArrayList<>(); - frames.add(new Frame(markers.get(i).getStart())); - markers.get(i).setFrames(frames); - } - } + public Cutscene setPos2(Location pos2) { + this.pos2 = pos2; + return this; } } diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/CutsceneManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/CutsceneManager.java index 7615a98..73ad534 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/CutsceneManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/CutsceneManager.java @@ -1,168 +1,138 @@ package me.unurled.sacredrealms.sr.components.cutscene; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.sacredrealms.sr.utils.Items.cancelItem; +import static me.unurled.srcore.utils.Component.textComp; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.UUID; +import me.unurled.sacredrealms.sr.SR; +import me.unurled.sacredrealms.sr.components.cutscene.tasks.TickTracker; import me.unurled.srcore.api.Manager; -import org.bukkit.Bukkit; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class CutsceneManager extends Manager { - // TODO: spectator to hide toolbar (make it ride an invisible entity to prevent movement) - // TODO: save modifications if any - // TODO: do you set player back to original position ? - // TODO: make a system to easily create cutscenesw + + private static final TextComponent ALREADY_STARTED = + textComp("You are already creating a cutscene."); private List cutscenes; + private Map cutsceneBeingCreated; + private Map savedInventories; - // cutscene id, player uuid - private Map currentPlayingCutscenes; - - private Map playerOrigins; - - private List cutsceneIds; - - /** Load the manager */ @Override public void load() { super.load(); + SR.getPlugin() + .getServer() + .getPluginManager() + .registerEvents(new CreationListener(), SR.getPlugin()); + TickTracker.startTracking(); cutscenes = new ArrayList<>(); - currentPlayingCutscenes = new HashMap<>(); - playerOrigins = new HashMap<>(); - cutsceneIds = new ArrayList<>(); + cutsceneBeingCreated = new HashMap<>(); + savedInventories = new HashMap<>(); } - /** Unload the manager */ @Override public void unload() { super.unload(); cutscenes.clear(); - currentPlayingCutscenes.clear(); - playerOrigins.clear(); - cutsceneIds.clear(); + cutsceneBeingCreated.clear(); + savedInventories.clear(); } - public void createCutscene(String id) { - Cutscene cutscene = new Cutscene(id, id); - addCutscene(cutscene); + @Nullable + public Cutscene getCutsceneBeingCreated(@NotNull UUID uuid) { + return cutsceneBeingCreated.get(uuid); } - public void removeCutscene(String id) { - Cutscene cutscene = getCutscene(id); - removeCutscene(cutscene); - } - - public void addCutscene(Cutscene cutscene) { - cutscenes.add(cutscene); - cutsceneIds.add(cutscene.getId()); - } - - public void removeCutscene(Cutscene cutscene) { - cutscenes.remove(cutscene); - cutsceneIds.remove(cutscene.getId().toUpperCase()); - } - - public void addCurrentPlayingCutscene(@NotNull Cutscene cutscene, @NotNull Player p) { - currentPlayingCutscenes.put(cutscene.getId(), p.getUniqueId()); - } - - public void removeCurrentPlayingCutscene(@NotNull Cutscene cutscene, @NotNull Player p) { - currentPlayingCutscenes.remove(cutscene.getId(), p.getUniqueId()); - } - - public List getCutscenesId() { - return cutsceneIds; - } - - public void stopCutscene(Player p) { - for (String string : currentPlayingCutscenes.keySet()) { - if (currentPlayingCutscenes.get(string).equals(p.getUniqueId())) { - currentPlayingCutscenes.remove(string, p.getUniqueId()); - Cutscene cutscene = getCutscene(string); - if (cutscene != null) { - cutscene.stop(p); - PlayerOrigin.restore(playerOrigins.get(p.getUniqueId()), p); - playerOrigins.remove(p.getUniqueId()); - } - return; - } - } - } - - public void stopCutscenesForAllPlayers() { - for (String string : currentPlayingCutscenes.keySet()) { - Cutscene cutscene = getCutscene(string); - if (cutscene != null) { - UUID uuid = currentPlayingCutscenes.get(string); - cutscene.stop(uuid); - currentPlayingCutscenes.remove(cutscene.getId(), uuid); - Player player = Bukkit.getPlayer(uuid); - if (player == null) return; - PlayerOrigin.restore(playerOrigins.get(uuid), player); - playerOrigins.remove(uuid); - } - } - } - - public void playCutscene(Cutscene cutscene, Player p) { - if (cutscene == null) { - p.sendMessage(textComp("There was an error with the cutscene!")); + public void startCreatingCutscene(@NotNull Player p, String name) { + if (cutsceneBeingCreated.containsKey(p.getUniqueId())) { + p.sendMessage(ALREADY_STARTED); return; } - if (cutscenes.contains(cutscene) && !currentPlayingCutscenes.containsValue(p.getUniqueId())) { - currentPlayingCutscenes.put(cutscene.getId(), p.getUniqueId()); - setPlayerOrigins(p); - cutscene.play(p); + cutsceneBeingCreated.put(p.getUniqueId(), new Cutscene(name)); + + // process to create cutscene + savedInventories.put(p.getUniqueId(), p.getInventory()); + p.getInventory().clear(); + p.sendMessage( + textComp("You are now creating a cutscene. Place the corner blocks.")); + ItemStack cancel = cancelItem(); + ItemStack finish = new ItemStack(Material.EMERALD_BLOCK); + ItemMeta meta = finish.getItemMeta(); + meta.displayName(textComp("Finish")); + finish.setItemMeta(meta); + + ItemStack pos1 = new ItemStack(Material.RED_WOOL); + meta = pos1.getItemMeta(); + meta.displayName(textComp("Pos1")); + pos1.setItemMeta(meta); + + ItemStack pos2 = new ItemStack(Material.BLUE_WOOL); + meta = pos2.getItemMeta(); + meta.displayName(textComp("Pos2")); + pos2.setItemMeta(meta); + + p.getInventory().setItem(8, cancel); + p.getInventory().setItem(0, finish); + p.getInventory().setItem(3, pos1); + p.getInventory().setItem(5, pos2); + + p.updateInventory(); + } + + public void finishCreatingCutscene(@NotNull Player p) { + if (!cutsceneBeingCreated.containsKey(p.getUniqueId())) { + p.sendMessage(textComp("You are not creating a cutscene.")); + return; } + Cutscene cutscene = cutsceneBeingCreated.get(p.getUniqueId()); + + cutscenes.add(cutscene); + p.getInventory().clear(); + p.sendMessage(textComp("Cutscene created.")); + cutsceneBeingCreated.remove(p.getUniqueId()); + PlayerInventory inv = savedInventories.get(p.getUniqueId()); + for (int i = 0; i < inv.getSize(); i++) { + p.getInventory().setItem(i, inv.getItem(i)); + } + p.updateInventory(); + savedInventories.remove(p.getUniqueId()); + } + + public void cancelCreatingCutscene(@NotNull Player p) { + if (!cutsceneBeingCreated.containsKey(p.getUniqueId())) { + p.sendMessage(textComp("You are not creating a cutscene.")); + return; + } + + p.getInventory().clear(); + p.sendMessage(textComp("Canceled creating cutscene.")); + cutsceneBeingCreated.remove(p.getUniqueId()); + PlayerInventory inv = savedInventories.get(p.getUniqueId()); + for (int i = 0; i < inv.getSize(); i++) { + p.getInventory().setItem(i, inv.getItem(i)); + } + p.updateInventory(); + savedInventories.remove(p.getUniqueId()); + } + + public List cutscenes() { + return cutscenes; } @Nullable - public Cutscene getCutscene(Player p) { - for (Entry entry : currentPlayingCutscenes.entrySet()) { - if (entry.getValue().equals(p.getUniqueId())) return getCutscene(entry.getKey()); - } - return null; - } - - @Nullable - public Cutscene getCutscene(@NotNull String id) { - if (!cutsceneIds.contains(id.toUpperCase())) { - return null; - } - for (Cutscene cutscene : cutscenes) { - if (cutscene.getId().equalsIgnoreCase(id.toUpperCase())) return cutscene; - } - return null; - } - - public boolean isPlayingCutscene(@NotNull Player p) { - return currentPlayingCutscenes.containsValue(p.getUniqueId()); - } - - @Nullable - public String getPlayingCutscene(@NotNull Player p) { - for (Entry entry : currentPlayingCutscenes.entrySet()) { - if (entry.getValue().equals(p.getUniqueId())) return entry.getKey(); - } - return null; - } - - public void setPlayerOrigins(@NotNull Player p) { - playerOrigins.put( - p.getUniqueId(), - new PlayerOrigin( - p.getLocation(), - p.getAllowFlight(), - p.isFlying(), - p.getWalkSpeed(), - p.getFlySpeed(), - p.getGameMode())); + public Cutscene findByUUID(UUID uuid) { + return cutscenes.stream().filter(c -> c.id().equals(uuid)).findFirst().orElse(null); } } diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/EntityCinematicAction.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/EntityCinematicAction.java deleted file mode 100644 index edd82b1..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/EntityCinematicAction.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene; - -import org.bukkit.entity.Player; - -public class EntityCinematicAction { - private Player p; -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Frame.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Frame.java deleted file mode 100644 index ff15b51..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Frame.java +++ /dev/null @@ -1,113 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene; - -import static me.unurled.sacredrealms.sr.utils.Logger.error; - -import com.google.gson.JsonElement; -import com.google.gson.JsonPrimitive; -import java.util.Map; -import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer; -import org.bukkit.Location; -import org.bukkit.block.data.BlockData; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Frame class - * - *

example of serializable frame: - * - *

{@code
- * {
- *   "id": 1,
- *   "entities": "entities serializable",
- *   "blocks": "blocks serializable",
- *   "action": "action", // if type is entity
- *   "location": {
- *      "world": "world",
- *      "x": 0,
- *      "y": 0,
- *      "z": 0,
- *      "yaw": 0,
- *      "pitch": 0
- *   }
- * }
- * }
- */ -public class Frame { - private static int idCounter = 0; - private final Location location; - private final int id; - @Nullable private Map blocks; - - public Frame(Location location) { - this.location = location; - id = idCounter; - idCounter++; - blocks = null; - } - - public Frame(Location location, int ID) { - this.location = location; - this.id = ID; - blocks = null; - } - - @Contract("_ -> new") - public static @NotNull Frame deserialize(@NotNull JsonElement jsonElement) { - int id = jsonElement.getAsJsonObject().get("id").getAsInt(); - Location loc = null; - try { - LocationSerializer locationDeserializer = new LocationSerializer(); - loc = - locationDeserializer.deserialize( - jsonElement.getAsJsonObject().get("location"), Location.class, null); - } catch (Exception e) { - error("Error deserializing location in Frame with ID: " + id); - } - - Frame frame = new Frame(loc, id); - - try { - frame.setBlocks((Map) jsonElement.getAsJsonObject().get("blocks")); - } catch (Exception e) { - error("Error deserializing blocks in Frame with ID: " + id); - } - return frame; - } - - public Location getLocation() { - return location; - } - - /** Play the frame aka move stuff around :shrug: */ - public void play() {} - - public int getId() { - return id; - } - - public @Nullable Map getBlocks() { - return blocks; - } - - public void setBlocks(@Nullable Map blocks) { - this.blocks = blocks; - } - - public JsonElement serialize() { - String s = - "{" - + "\"id\":" - + id - + "," - + "," - + "\"blocks\":" - + blocks - + "," - + "\"location\":" - + location.serialize() - + "}"; - return new JsonPrimitive(s); - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Marker.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Marker.java deleted file mode 100644 index f36bb9a..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Marker.java +++ /dev/null @@ -1,146 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene; - -import static me.unurled.sacredrealms.sr.utils.CutsceneUtil.interpolateFrames; - -import java.util.ArrayList; -import java.util.List; -import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Marker class - * - *
{@code
- * {
- *   "id": 1,
- *   "frames": [ 1, 2, 3 ], // Frame IDs
- *   "timeBetweenFrames": 20,
- *   "overAllTime": 60,
- *   "start": {
- *      "world": "world",
- *      "x": 0,
- *      "y": 0,
- *      "z": 0,
- *      "yaw": 0,
- *      "pitch": 0
- *   }
- * }
- * }
- */ -public class Marker { - - private static int idCounter = 0; - private static List markers = new ArrayList<>(); - private final int id; - private List frames; - private Long timeBetweenFrames; - private Long overAllTime; - private Location start; - - public Marker(Integer id) { - frames = new ArrayList<>(); - timeBetweenFrames = 0L; - overAllTime = 0L; - if (id == null) { - this.id = idCounter; - idCounter++; - } else { - this.id = id; - } - } - - public Marker(@NotNull List frames, long timeBetweenFrames, Location start) { - this.frames = frames; - this.timeBetweenFrames = timeBetweenFrames; - this.overAllTime = timeBetweenFrames * frames.size(); - this.start = start; - id = idCounter; - idCounter++; - } - - public static List getMarkers() { - return markers; - } - - public static void setMarkers(List markers) { - Marker.markers = markers; - } - - public static @Nullable Marker getMarker(int ID) { - for (Marker marker : markers) { - if (marker.getId() == ID) { - return marker; - } - } - return null; - } - - public List getFrames() { - return frames; - } - - public void setFrames(List frames) { - this.frames = frames; - } - - public Long getTimeBetweenFrames() { - return timeBetweenFrames; - } - - public void setTimeBetweenFrames(Long timeBetweenFrames) { - this.timeBetweenFrames = timeBetweenFrames; - } - - public Long getOverAllTime() { - return overAllTime; - } - - public void setOverAllTime(Long overAllTime) { - this.overAllTime = overAllTime; - } - - public Location getStart() { - return start; - } - - public void setStart(Location start) { - this.start = start; - } - - public void calculateFrames(Marker endMarker) { - frames = interpolateFrames(this, endMarker, timeBetweenFrames); - } - - public int getId() { - return id; - } - - public void addFrame(Frame frame) { - frames.add(frame); - } - - public void removeFrame(Frame frame) { - frames.remove(frame); - } - - public void removeFrame(int index) { - frames.remove(index); - } - - @Override - public String toString() { - return "Marker{" - + "ID=" - + id - + ", frames=" - + frames - + ", timeBetweenFrames=" - + timeBetweenFrames - + ", overAllTime=" - + overAllTime - + ", start=" - + start - + '}'; - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/PlayerOrigin.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/PlayerOrigin.java deleted file mode 100644 index f61fcd5..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/PlayerOrigin.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene; - -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public record PlayerOrigin( - Location location, - boolean allowFlight, - boolean flying, - float walkSpeed, - float flySpeed, - GameMode gameMode) { - public static void restore(@NotNull PlayerOrigin origin, @NotNull Player p) { - p.teleport(origin.location()); - p.setAllowFlight(origin.allowFlight()); - p.setFlying(origin.flying()); - p.setWalkSpeed(origin.walkSpeed()); - p.setFlySpeed(origin.flySpeed()); - p.setGameMode(origin.gameMode()); - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/PlayerRecording.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/PlayerRecording.java deleted file mode 100644 index 553c999..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/PlayerRecording.java +++ /dev/null @@ -1,82 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene; - -import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose; -import io.papermc.paper.event.player.PlayerArmSwingEvent; -import me.unurled.sacredrealms.sr.components.cutscene.npc.ArmSwing; -import me.unurled.sacredrealms.sr.components.cutscene.npc.EntityFrame; -import org.bukkit.entity.Player; -import org.bukkit.entity.Pose; -import org.bukkit.event.EventHandler; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.PlayerInventory; -import org.jetbrains.annotations.NotNull; - -public class PlayerRecording { - private final Player player; - private final EntityFrame entityFrame; - private ArmSwing swing; - - public PlayerRecording(Player player, EntityFrame entityFrame) { - this.player = player; - this.entityFrame = entityFrame; - } - - private static EntityPose toEntityPose(Pose pose) { - return pose == Pose.SNEAKING ? EntityPose.SITTING : EntityPose.valueOf(pose.name()); - } - - private static Pose toBukkitPose(EntityPose pose) { - return pose == EntityPose.SITTING ? Pose.SNEAKING : Pose.valueOf(pose.name()); - } - - @EventHandler - public void onArmSwing(@NotNull PlayerArmSwingEvent e) { - if (e.getPlayer().getUniqueId() != player.getUniqueId()) { - return; - } - addSwing( - e.getHand() == EquipmentSlot.HAND - ? ArmSwing.RIGHT - : (e.getHand() == EquipmentSlot.OFF_HAND ? ArmSwing.LEFT : ArmSwing.BOTH)); - } - - private void addSwing(ArmSwing swing) { - if (this.swing != null && this.swing != swing) { - this.swing = ArmSwing.BOTH; - return; - } - - this.swing = swing; - } - - public EntityFrame captureFrame() { - PlayerInventory inv = player.getInventory(); - Pose pose = player.isInsideVehicle() ? Pose.SITTING : player.getPose(); - EntityFrame data = - new EntityFrame( - player.getLocation(), - toEntityPose(pose), - swing, - inv.getItemInMainHand().isEmpty() ? null : inv.getItemInMainHand(), - inv.getItemInOffHand().isEmpty() ? null : inv.getItemInOffHand(), - inv.getHelmet(), - inv.getChestplate(), - inv.getLeggings(), - inv.getBoots()); - swing = null; - return data; - } - - public void applyState(@NotNull EntityFrame value) { - player.teleport(value.location()); - player.setPose(toBukkitPose(value.pose())); - PlayerInventory inv = player.getInventory(); - inv.setItemInMainHand(value.mainHand()); - inv.setItemInOffHand(value.offHand()); - inv.setHelmet(value.helmet()); - inv.setChestplate(value.chestplate()); - inv.setLeggings(value.leggings()); - inv.setBoots(value.boots()); - player.updateInventory(); - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/RecordingManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/RecordingManager.java new file mode 100644 index 0000000..7470830 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/RecordingManager.java @@ -0,0 +1,75 @@ +package me.unurled.sacredrealms.sr.components.cutscene; + +import static me.unurled.srcore.utils.Component.textComp; + +import java.util.ArrayList; +import java.util.List; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording; +import me.unurled.sacredrealms.sr.components.cutscene.tasks.TickTracker; +import me.unurled.srcore.api.Manager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class RecordingManager extends Manager { + private List recordings; // existing recordings + private List activeRecordings; // currently recording + + @Override + public void load() { + super.load(); + recordings = new ArrayList<>(); + activeRecordings = new ArrayList<>(); + } + + @Override + public void unload() { + super.unload(); + recordings.clear(); + activeRecordings.clear(); + } + + @Nullable + public Recording getPlayerActiveRecording(Player player) { + return activeRecordings.stream() + .filter(r -> r.recordingPlayer().equals(player)) + .findFirst() + .orElse(null); + } + + public void startRecording(Cutscene cutscene, Player player) { + Recording recording = new Recording(cutscene, player); + player.sendMessage(textComp("Recording started.")); + activeRecordings.add(recording); + } + + public void stopRecording(Player player) { + Recording recording = getPlayerActiveRecording(player); + if (recording == null) { + player.sendMessage(textComp("You are not recording a cutscene.")); + return; + } + activeRecordings.remove(recording); + recording.stopRecording(); + recordings.add(recording); + player.sendMessage(textComp("Recording stopped.")); + } + + public void addRecordable(@NotNull Recording recording, @NotNull Recordable recordable) { + long tick = TickTracker.currentTick(); + + // normalize tick + tick = tick - recording.startTick(); + + recordable.setTick(tick); + + if (recording.recordables().containsKey(tick)) { + recording.recordables().get(tick).add(recordable); + } else { + List recordables = new ArrayList<>(); + recordables.add(recordable); + recording.recordables().put(tick, recordables); + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Replay.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Replay.java new file mode 100644 index 0000000..97a3e75 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/Replay.java @@ -0,0 +1,45 @@ +package me.unurled.sacredrealms.sr.components.cutscene; + +import me.unurled.sacredrealms.sr.SR; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording; +import me.unurled.sacredrealms.sr.components.cutscene.tasks.ReplayTask; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; + +public class Replay { + private final Player viewer; + private final Recording recording; + private final BukkitTask replayTask; + + public Replay(Recording recording, @NotNull Player viewer) { + this.recording = recording; + this.viewer = viewer; + + viewer.getInventory().clear(); + // TODO: control cutscene replay + + replayTask = + Bukkit.getScheduler() + .runTaskTimerAsynchronously(SR.getPlugin(), new ReplayTask(this), 0L, 1L); + } + + public Player viewer() { + return viewer; + } + + public Recording recording() { + return recording; + } + + public BukkitTask replayTask() { + return replayTask; + } + + public void endReplay() { + if (replayTask != null) { + replayTask.cancel(); + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/ReplayManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/ReplayManager.java new file mode 100644 index 0000000..78ab4c7 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/ReplayManager.java @@ -0,0 +1,53 @@ +package me.unurled.sacredrealms.sr.components.cutscene; + +import java.util.HashSet; +import java.util.Set; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording; +import me.unurled.srcore.api.Manager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ReplayManager extends Manager { + + private Set replays; + + @Override + public void load() { + super.load(); + replays = new HashSet<>(); + } + + @Override + public void unload() { + super.unload(); + } + + @Nullable + public Replay getReplayForPlayer(Player player) { + return replays.stream() + .filter(replay -> replay.viewer().equals(player)) + .findFirst() + .orElse(null); + } + + public void replayRecording(Recording recording, Player player) { + if (getReplayForPlayer(player) != null) { + return; + } + + Replay replay = new Replay(recording, player); + replays.add(replay); + } + + public void stopReplay(@NotNull Replay replay) { + // stop replay taskk + replay.endReplay(); + + replays.remove(replay); + } + + public Set replays() { + return replays; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/gson/ActionGson.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/gson/ActionGson.java deleted file mode 100644 index 1259c26..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/gson/ActionGson.java +++ /dev/null @@ -1,63 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene.gson; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import java.lang.reflect.Type; -import me.unurled.sacredrealms.sr.components.cutscene.Action; -import org.jetbrains.annotations.NotNull; - -public class ActionGson { - public class Deserializer implements JsonDeserializer { - - /** - * Gson invokes this call-back method during deserialization when it encounters a field of the - * specified type. - * - *

In the implementation of this call-back method, you should consider invoking {@link - * JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects for any - * non-trivial field of the returned object. However, you should never invoke it on the same - * type passing {@code json} since that will cause an infinite loop (Gson will call your - * call-back method again). - * - * @param json The Json data being deserialized - * @param typeOfT The type of the Object to deserialize to - * @param context - * @return a deserialized object of the specified type typeOfT which is a subclass of {@code T} - * @throws JsonParseException if json is not in the expected format of {@code typeofT} - */ - @Override - public Action deserialize( - @NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - return Action.valueOf(json.getAsString()); - } - } - - public class Serializer implements JsonSerializer { - - /** - * Gson invokes this call-back method during serialization when it encounters a field of the - * specified type. - * - *

In the implementation of this call-back method, you should consider invoking {@link - * JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any - * non-trivial field of the {@code src} object. However, you should never invoke it on the - * {@code src} object itself since that will cause an infinite loop (Gson will call your - * call-back method again). - * - * @param src the object that needs to be converted to Json. - * @param typeOfSrc the actual type (fully genericized version) of the source object. - * @param context - * @return a JsonElement corresponding to the specified object. - */ - @Override - public JsonElement serialize(Action src, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(src.name()); - } - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/gson/EntityActionGson.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/gson/EntityActionGson.java deleted file mode 100644 index 4311514..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/gson/EntityActionGson.java +++ /dev/null @@ -1,64 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene.gson; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import java.lang.reflect.Type; -import java.util.Map; -import me.unurled.sacredrealms.sr.components.cutscene.Action; -import org.bukkit.entity.Entity; - -public class EntityActionGson { - public class Deserializer implements JsonDeserializer> { - - /** - * Gson invokes this call-back method during deserialization when it encounters a field of the - * specified type. - * - *

In the implementation of this call-back method, you should consider invoking {@link - * JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects for any - * non-trivial field of the returned object. However, you should never invoke it on the same - * type passing {@code json} since that will cause an infinite loop (Gson will call your - * call-back method again). - * - * @param json The Json data being deserialized - * @param typeOfT The type of the Object to deserialize to - * @param context - * @return a deserialized object of the specified type typeOfT which is a subclass of {@code T} - * @throws JsonParseException if json is not in the expected format of {@code typeofT} - */ - @Override - public Map deserialize( - JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - return null; - } - } - - public class Serializer implements JsonSerializer> { - - /** - * Gson invokes this call-back method during serialization when it encounters a field of the - * specified type. - * - *

In the implementation of this call-back method, you should consider invoking {@link - * JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any - * non-trivial field of the {@code src} object. However, you should never invoke it on the - * {@code src} object itself since that will cause an infinite loop (Gson will call your - * call-back method again). - * - * @param src the object that needs to be converted to Json. - * @param typeOfSrc the actual type (fully genericized version) of the source object. - * @param context - * @return a JsonElement corresponding to the specified object. - */ - @Override - public JsonElement serialize( - Map src, Type typeOfSrc, JsonSerializationContext context) { - return null; - } - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/npc/ArmSwing.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/npc/ArmSwing.java deleted file mode 100644 index 4e8c93e..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/npc/ArmSwing.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene.npc; - -import static me.unurled.sacredrealms.sr.components.packet.PacketManager.sendPacketTo; - -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation.EntityAnimationType; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -public enum ArmSwing { - LEFT, - RIGHT, - BOTH; - - public static void swingArm(@NotNull ArmSwing arm, Player p, int entityId) { - // Swing the arm - if (arm.isLeft()) { - sendPacketTo( - new WrapperPlayServerEntityAnimation(entityId, EntityAnimationType.SWING_OFF_HAND), p); - } - if (arm.isRight()) { - sendPacketTo( - new WrapperPlayServerEntityAnimation(entityId, EntityAnimationType.SWING_MAIN_ARM), p); - } - } - - @Contract(pure = true) - public @NotNull Boolean isLeft() { - return this == LEFT || this == BOTH; - } - - @Contract(pure = true) - public @NotNull Boolean isRight() { - return this == RIGHT || this == BOTH; - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/npc/EntityFrame.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/npc/EntityFrame.java deleted file mode 100644 index 12abaa0..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/npc/EntityFrame.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.unurled.sacredrealms.sr.components.cutscene.npc; - -import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose; -import com.google.gson.JsonElement; -import com.google.gson.JsonPrimitive; -import me.unurled.sacredrealms.sr.utils.Items; -import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer; -import org.bukkit.Location; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; - -public record EntityFrame( - Location location, - EntityPose pose, - ArmSwing swing, - ItemStack mainHand, - ItemStack offHand, - ItemStack helmet, - ItemStack chestplate, - ItemStack leggings, - ItemStack boots) { - - public static @NotNull EntityFrame deserialize(@NotNull JsonElement jsonElement) { - Location location = - new LocationSerializer() - .deserialize(jsonElement.getAsJsonObject().get("location"), Location.class, null); - EntityPose pose = EntityPose.valueOf(jsonElement.getAsJsonObject().get("pose").getAsString()); - ArmSwing swing = ArmSwing.valueOf(jsonElement.getAsJsonObject().get("swing").getAsString()); - ItemStack mainHand = Items.deserialize(jsonElement.getAsJsonObject().get("mainHand")); - ItemStack offHand = Items.deserialize(jsonElement.getAsJsonObject().get("offHand")); - ItemStack helmet = Items.deserialize(jsonElement.getAsJsonObject().get("helmet")); - ItemStack chestplate = Items.deserialize(jsonElement.getAsJsonObject().get("chestplate")); - ItemStack leggings = Items.deserialize(jsonElement.getAsJsonObject().get("leggings")); - ItemStack boots = Items.deserialize(jsonElement.getAsJsonObject().get("boots")); - return new EntityFrame( - location, pose, swing, mainHand, offHand, helmet, chestplate, leggings, boots); - } - - public @NotNull JsonElement serialize() { - String s = - """ - { - "location": %s, - "pose": %s, - "swing": %s, - "mainHand": %s, - "offHand": %s, - "helmet": %s, - "chestplate": %s, - "leggings": %s, - "boots": %s - } - """ - .formatted( - location.serialize(), - pose.name(), - swing.name(), - mainHand.serialize(), - offHand.serialize(), - helmet.serialize(), - chestplate.serialize(), - leggings.serialize(), - boots.serialize()); - return new JsonPrimitive(s); - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/Recordable.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/Recordable.java new file mode 100644 index 0000000..8f7252d --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/Recordable.java @@ -0,0 +1,16 @@ +package me.unurled.sacredrealms.sr.components.cutscene.recording; + +public abstract class Recordable { + private long tick; + + public abstract void replay(); + + public long tick() { + return tick; + } + + public Recordable setTick(long tick) { + this.tick = tick; + return this; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/Recording.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/Recording.java new file mode 100644 index 0000000..34f5dad --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/Recording.java @@ -0,0 +1,124 @@ +package me.unurled.sacredrealms.sr.components.cutscene.recording; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.UUID; +import java.util.concurrent.ConcurrentLinkedQueue; +import me.unurled.sacredrealms.sr.SR; +import me.unurled.sacredrealms.sr.components.cutscene.Cutscene; +import me.unurled.sacredrealms.sr.components.cutscene.tasks.ScanEntityTracker; +import me.unurled.sacredrealms.sr.components.cutscene.tasks.TickTracker; +import me.unurled.sacredrealms.sr.components.cutscene.tasks.TrackLocationTask; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; + +public class Recording { + // recordables + private final Map> recordables = new HashMap<>(); + private final Queue recordableEntities = new ConcurrentLinkedQueue<>(); + private final BukkitTask trackLocationTask; + private final BukkitTask scanEntitiesTask; + private Cutscene cutscene; + private Player recordingPlayer; + private long startTime; + private long endTime; + private long startTick; + private long endTick; + + public Recording(Cutscene cutscene, Player recordingPlayer) { + this.cutscene = cutscene; + this.recordingPlayer = recordingPlayer; + + this.startTime = System.currentTimeMillis(); + this.startTick = 1; // TODO: get tick + this.endTick = 1; // TODO: get tick + + this.scanEntitiesTask = + Bukkit.getScheduler().runTaskTimer(SR.getPlugin(), new ScanEntityTracker(this), 0L, 20L); + this.trackLocationTask = + Bukkit.getScheduler().runTaskTimer(SR.getPlugin(), new TrackLocationTask(this), 0L, 1L); + } + + public Map> recordables() { + return recordables; + } + + public Cutscene cutscene() { + return cutscene; + } + + public Queue recordableEntities() { + return recordableEntities; + } + + public Recording setCutscene(Cutscene cutscene) { + this.cutscene = cutscene; + return this; + } + + public Player recordingPlayer() { + return recordingPlayer; + } + + public Recording setRecordingPlayer(Player recordingPlayer) { + this.recordingPlayer = recordingPlayer; + return this; + } + + public long startTime() { + return startTime; + } + + public Recording setStartTime(long startTime) { + this.startTime = startTime; + return this; + } + + public long endTime() { + return endTime; + } + + public Recording setEndTime(long endTime) { + this.endTime = endTime; + return this; + } + + public long startTick() { + return startTick; + } + + public Recording setStartTick(long startTick) { + this.startTick = startTick; + return this; + } + + public void stopRecording() { + this.endTime = System.currentTimeMillis(); + this.endTick = TickTracker.currentTick(); + scanEntitiesTask.cancel(); + trackLocationTask.cancel(); + } + + public long tickDuration() { + return endTick - startTick; + } + + public boolean isEntityBeingTracked(UUID uuid) { + synchronized (recordableEntities) { + return recordableEntities.contains(uuid); + } + } + + public boolean addEntityIfNotBeingTracked(UUID uuid) { + synchronized (recordableEntities) { + if (recordableEntities.contains(uuid)) { + return false; + } + recordableEntities.add(uuid); + return true; + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/DespawnEntityRecordable.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/DespawnEntityRecordable.java new file mode 100644 index 0000000..8c6d608 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/DespawnEntityRecordable.java @@ -0,0 +1,29 @@ +package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables; + +import java.util.UUID; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable; + +public class DespawnEntityRecordable extends Recordable { + + private UUID entityId; + + public DespawnEntityRecordable() {} + + public DespawnEntityRecordable(UUID entityId) { + this.entityId = entityId; + } + + @Override + public void replay() { + // TODO: fake spawn entity + } + + public UUID entityId() { + return entityId; + } + + public DespawnEntityRecordable setEntityId(UUID entityId) { + this.entityId = entityId; + return this; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/LocationChangeRecordable.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/LocationChangeRecordable.java new file mode 100644 index 0000000..892eb56 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/LocationChangeRecordable.java @@ -0,0 +1,39 @@ +package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables; + +import java.util.UUID; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable; +import org.bukkit.Location; + +public class LocationChangeRecordable extends Recordable { + + private UUID entityId; + private Location location; + + public LocationChangeRecordable() {} + + public LocationChangeRecordable(UUID entityId, Location location) { + this.entityId = entityId; + this.location = location; + } + + @Override + public void replay() {} + + public UUID entityId() { + return entityId; + } + + public LocationChangeRecordable setEntityId(UUID entityId) { + this.entityId = entityId; + return this; + } + + public Location location() { + return location; + } + + public LocationChangeRecordable setLocation(Location location) { + this.location = location; + return this; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/SpawnEntityRecordable.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/SpawnEntityRecordable.java new file mode 100644 index 0000000..aaa21db --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/recording/recordables/SpawnEntityRecordable.java @@ -0,0 +1,75 @@ +package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables; + +import java.util.UUID; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable; +import net.kyori.adventure.text.Component; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.jetbrains.annotations.NotNull; + +public class SpawnEntityRecordable extends Recordable { + + private EntityType entityType; + private Location location; + private UUID entityId; + private Component name; + + public SpawnEntityRecordable() {} + + public SpawnEntityRecordable(@NotNull Entity e) { + this.entityType = e.getType(); + this.location = e.getLocation(); + this.entityId = e.getUniqueId(); + this.name = e.name(); + } + + public SpawnEntityRecordable( + EntityType entityType, Location location, UUID entityId, Component name) { + this.entityType = entityType; + this.location = location; + this.entityId = entityId; + this.name = name; + } + + @Override + public void replay() { + // TODO: fake spawn entity + } + + public EntityType entityType() { + return entityType; + } + + public SpawnEntityRecordable setEntityType(EntityType entityType) { + this.entityType = entityType; + return this; + } + + public Location location() { + return location; + } + + public SpawnEntityRecordable setLocation(Location location) { + this.location = location; + return this; + } + + public UUID entityId() { + return entityId; + } + + public SpawnEntityRecordable setEntityId(UUID entityId) { + this.entityId = entityId; + return this; + } + + public Component name() { + return name; + } + + public SpawnEntityRecordable setName(Component name) { + this.name = name; + return this; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/ReplayTask.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/ReplayTask.java new file mode 100644 index 0000000..d81a73d --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/ReplayTask.java @@ -0,0 +1,51 @@ +package me.unurled.sacredrealms.sr.components.cutscene.tasks; + +import static me.unurled.sacredrealms.sr.utils.Logger.error; +import static me.unurled.srcore.utils.Component.textComp; + +import me.unurled.sacredrealms.sr.components.cutscene.Replay; +import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable; +import me.unurled.srcore.api.Manager; + +public class ReplayTask implements Runnable { + + private final Replay replay; + private final ReplayManager rm; + private long currentTick = 0; + + public ReplayTask(Replay replay) { + this.replay = replay; + rm = Manager.getInstance(ReplayManager.class); + } + + @Override + public void run() { + + if (currentTick >= replay.recording().tickDuration()) { + replay.viewer().sendMessage(textComp("Replay has ended.")); + rm.stopReplay(replay); + return; + } + // get all recordables for current tick + var recordables = replay.recording().recordables().get(currentTick); + + try { + if (recordables == null) { + currentTick++; + return; + } + + for (Recordable r : recordables) { + // figure out how to replay a recordable + r.replay(); + } + } catch (Exception e) { + error("Tick: " + currentTick); + error(e.getMessage()); + + } finally { + currentTick++; + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/ScanEntityTracker.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/ScanEntityTracker.java new file mode 100644 index 0000000..0f69291 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/ScanEntityTracker.java @@ -0,0 +1,57 @@ +package me.unurled.sacredrealms.sr.components.cutscene.tasks; + +import java.util.ArrayList; +import java.util.List; +import me.unurled.sacredrealms.sr.components.cutscene.Cutscene; +import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording; +import me.unurled.sacredrealms.sr.components.cutscene.recording.recordables.SpawnEntityRecordable; +import me.unurled.srcore.api.Manager; +import org.bukkit.Chunk; +import org.bukkit.Location; + +public class ScanEntityTracker implements Runnable { + + private final Recording recording; + + public ScanEntityTracker(Recording recording) { + this.recording = recording; + } + + @Override + public void run() { + Cutscene cutscene = recording.cutscene(); + Location pos1 = cutscene.pos1(); + Location pos2 = cutscene.pos2(); + int chunkZ = pos1.getBlockZ() >> 4; + int chunkX = pos1.getBlockX() >> 4; + int chunkX2 = pos2.getBlockX() >> 4; + int chunkZ2 = pos2.getBlockZ() >> 4; + + var loadedChunks = pos1.getWorld().getLoadedChunks(); + List chunksInRegion = new ArrayList<>(); + for (Chunk chunk : loadedChunks) { + if (chunk.getX() >= chunkX + && chunk.getX() <= chunkX2 + && chunk.getZ() >= chunkZ + && chunk.getZ() <= chunkZ2) { + chunksInRegion.add(chunk); + } + } + + for (Chunk chunk : chunksInRegion) { + var entities = chunk.getEntities(); + for (var entity : entities) { + if (!cutscene.isInRegion(entity.getLocation())) { + continue; + } + + if (recording.addEntityIfNotBeingTracked(entity.getUniqueId())) { + // TODO: spawn entity + SpawnEntityRecordable recordable = new SpawnEntityRecordable(entity); + Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable); + } + } + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/TickTracker.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/TickTracker.java new file mode 100644 index 0000000..ef551e9 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/TickTracker.java @@ -0,0 +1,16 @@ +package me.unurled.sacredrealms.sr.components.cutscene.tasks; + +import me.unurled.sacredrealms.sr.SR; +import org.bukkit.Bukkit; + +public class TickTracker { + private static long currentTick = 0; + + public static void startTracking() { + Bukkit.getScheduler().scheduleSyncRepeatingTask(SR.getPlugin(), () -> currentTick++, 0L, 1L); + } + + public static long currentTick() { + return currentTick; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/TrackLocationTask.java b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/TrackLocationTask.java new file mode 100644 index 0000000..9fec3dd --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/components/cutscene/tasks/TrackLocationTask.java @@ -0,0 +1,47 @@ +package me.unurled.sacredrealms.sr.components.cutscene.tasks; + +import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager; +import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording; +import me.unurled.sacredrealms.sr.components.cutscene.recording.recordables.DespawnEntityRecordable; +import me.unurled.sacredrealms.sr.components.cutscene.recording.recordables.LocationChangeRecordable; +import me.unurled.srcore.api.Manager; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; + +public class TrackLocationTask implements Runnable { + + private final Recording recording; + + public TrackLocationTask(Recording recording) { + this.recording = recording; + } + + @Override + public void run() { + var recordebaleEntities = recording.recordableEntities(); + synchronized (recordebaleEntities) { + recordebaleEntities.forEach( + uuid -> { + Entity entity = Bukkit.getEntity(uuid); + if (entity == null) { + recording.recordableEntities().remove(uuid); + DespawnEntityRecordable recordable = new DespawnEntityRecordable(uuid); + Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable); + return; + } + + if (!recording.cutscene().isInRegion(entity.getLocation())) { + recording.recordableEntities().remove(uuid); + DespawnEntityRecordable recordable = new DespawnEntityRecordable(uuid); + Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable); + return; + } + + var recordable = + new LocationChangeRecordable(entity.getUniqueId(), entity.getLocation()); + + Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable); + }); + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/difficulty/Difficulty.java b/src/main/java/me/unurled/sacredrealms/sr/components/difficulty/Difficulty.java index 4258fd0..f2321be 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/difficulty/Difficulty.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/difficulty/Difficulty.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.components.difficulty; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/entity/SREntity.java b/src/main/java/me/unurled/sacredrealms/sr/components/entity/SREntity.java index 63ac464..d7dfe20 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/entity/SREntity.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/entity/SREntity.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.components.entity; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import java.util.UUID; import me.unurled.sacredrealms.sr.components.attributes.Attribute; diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java b/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java index c89732f..c2028e6 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.components.item; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import static me.unurled.sacredrealms.sr.utils.Items.lore; import static me.unurled.sacredrealms.sr.utils.Logger.error; diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/pack/ResourcePackManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/pack/ResourcePackManager.java index 801a26a..dbcf52e 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/pack/ResourcePackManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/pack/ResourcePackManager.java @@ -69,6 +69,9 @@ public class ResourcePackManager extends Manager { super.saveData(); DataManager dm = Manager.getInstance(DataManager.class); DataHandler dh = dm.getDataHandler(); + if (hostingProvider.getMinecraftPackURL() == null) { + return; + } dh.set("pack.url", hostingProvider.getMinecraftPackURL()); dh.set("pack.uuid", hostingProvider.getPackUUID().toString()); dh.set("pack.sha1", hostingProvider.getPackUUID().toString()); diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java index c1d3f26..9a9f7a9 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/player/PlayerManager.java @@ -1,9 +1,9 @@ package me.unurled.sacredrealms.sr.components.player; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; import static me.unurled.sacredrealms.sr.utils.Logger.error; import static me.unurled.sacredrealms.sr.utils.Logger.log; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.updateActionBar; +import static me.unurled.srcore.utils.Component.textComp; import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; import com.google.gson.Gson; @@ -167,7 +167,9 @@ public class PlayerManager extends Manager { } catch (Exception ex) { error("Failed to send resource pack to player. " + ex.getMessage()); log(rpm.getHostingProvider().getOriginalSHA1()); - log(rpm.getHostingProvider().getPackUUID().toString()); + if (rpm.getHostingProvider().getPackUUID() != null) { + log(rpm.getHostingProvider().getPackUUID().toString()); + } log(rpm.getHostingProvider().getMinecraftPackURL()); } } diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java index 9e17144..7c837fe 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.components.treasure; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java index 7da5ef9..ddab63a 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.components.treasure; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import static me.unurled.sacredrealms.sr.utils.Logger.error; import static me.unurled.sacredrealms.sr.utils.Logger.log; diff --git a/src/main/java/me/unurled/sacredrealms/sr/events/player/PlayerLevelUpEvent.java b/src/main/java/me/unurled/sacredrealms/sr/events/player/PlayerLevelUpEvent.java index 485b477..9234ba6 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/events/player/PlayerLevelUpEvent.java +++ b/src/main/java/me/unurled/sacredrealms/sr/events/player/PlayerLevelUpEvent.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.events.player; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import me.unurled.sacredrealms.sr.components.player.SRPlayer; import net.kyori.adventure.text.Component; diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributeItem.java b/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributeItem.java index 98d5c3b..87d40b4 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributeItem.java +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributeItem.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.gui.attributes; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer; import me.unurled.sacredrealms.sr.components.attributes.Attribute; diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributesGUI.java b/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributesGUI.java index a231e0a..781acc5 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributesGUI.java +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/attributes/AttributesGUI.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.gui.attributes; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import me.unurled.sacredrealms.sr.components.attributes.Attribute; import org.bukkit.Material; diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/entitytype/EntityTypeItem.java b/src/main/java/me/unurled/sacredrealms/sr/gui/entitytype/EntityTypeItem.java index 7f57fd4..8d2cb0c 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/gui/entitytype/EntityTypeItem.java +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/entitytype/EntityTypeItem.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.gui.entitytype; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import me.unurled.sacredrealms.sr.components.entity.SREntityType; import org.bukkit.Material; diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/recordings/CutsceneItem.java b/src/main/java/me/unurled/sacredrealms/sr/gui/recordings/CutsceneItem.java new file mode 100644 index 0000000..bfa7c6f --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/recordings/CutsceneItem.java @@ -0,0 +1,71 @@ +package me.unurled.sacredrealms.sr.gui.recordings; + +import static me.unurled.srcore.utils.Component.textComp; + +import java.util.UUID; +import me.unurled.sacredrealms.sr.SR; +import me.unurled.sacredrealms.sr.components.cutscene.Cutscene; +import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager; +import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager; +import me.unurled.srcore.api.Manager; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.AbstractItem; + +public class CutsceneItem extends AbstractItem { + + private static NamespacedKey ID = null; + private final String name; + private final UUID uuid; + + public CutsceneItem(String name, UUID uuid) { + this.name = name; + this.uuid = uuid; + ID = new NamespacedKey(SR.getPlugin(), "cutscene_id"); + } + + @Override + public ItemProvider getItemProvider() { + ItemStack itemStack = new ItemStack(Material.PAPER); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(textComp(name)); + itemMeta.getPersistentDataContainer().set(ID, PersistentDataType.STRING, uuid.toString()); + itemStack.setItemMeta(itemMeta); + + return new ItemBuilder(itemStack); + } + + @Override + public void handleClick( + @NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) { + // get uuid + if (event.getCurrentItem() != null) { + String uuid = + event + .getCurrentItem() + .getItemMeta() + .getPersistentDataContainer() + .get(ID, PersistentDataType.STRING); + + Cutscene cutscene = + Manager.getInstance(CutsceneManager.class).findByUUID(UUID.fromString(uuid)); + + if (cutscene == null) { + player.sendMessage(textComp("Unexpected error.")); + return; + } + if (clickType.isLeftClick()) { + Manager.getInstance(RecordingManager.class).startRecording(cutscene, player); + } + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/recordings/StartRecordingGui.java b/src/main/java/me/unurled/sacredrealms/sr/gui/recordings/StartRecordingGui.java new file mode 100644 index 0000000..9d1bc47 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/recordings/StartRecordingGui.java @@ -0,0 +1,45 @@ +package me.unurled.sacredrealms.sr.gui.recordings; + +import static me.unurled.sacredrealms.sr.utils.Items.glassPane; + +import java.util.ArrayList; +import java.util.List; +import me.unurled.sacredrealms.sr.components.cutscene.Cutscene; +import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager; +import me.unurled.sacredrealms.sr.gui.BackItem; +import me.unurled.sacredrealms.sr.gui.ForwardItem; +import me.unurled.srcore.api.Manager; +import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.gui.Gui; +import xyz.xenondevs.invui.gui.PagedGui; +import xyz.xenondevs.invui.gui.structure.Markers; +import xyz.xenondevs.invui.item.Item; +import xyz.xenondevs.invui.item.builder.ItemBuilder; + +public class StartRecordingGui { + private StartRecordingGui() {} + + public static @NotNull Gui listGui() { + CutsceneManager cm = Manager.getInstance(CutsceneManager.class); + + List items = new ArrayList<>(); + for (Cutscene cs : cm.cutscenes()) { + CutsceneItem item = new CutsceneItem(cs.name(), cs.id()); + items.add(item); + } + + return PagedGui.items() + .setStructure( + "# # # # # # # # #", + "# X X X X X X X #", + "# X X X X X X X #", + "# X X X X X X X #", + "# # # < # > # # #") + .addIngredient('#', new ItemBuilder(glassPane())) + .addIngredient('X', Markers.CONTENT_LIST_SLOT_HORIZONTAL) + .addIngredient('<', new BackItem()) + .addIngredient('>', new ForwardItem()) + .setContent(items) + .build(); + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/replay/ReplayGui.java b/src/main/java/me/unurled/sacredrealms/sr/gui/replay/ReplayGui.java new file mode 100644 index 0000000..1e52604 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/replay/ReplayGui.java @@ -0,0 +1,42 @@ +package me.unurled.sacredrealms.sr.gui.replay; + +import static me.unurled.sacredrealms.sr.utils.Items.glassPane; + +import java.util.ArrayList; +import java.util.List; +import me.unurled.sacredrealms.sr.components.cutscene.Replay; +import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager; +import me.unurled.sacredrealms.sr.gui.BackItem; +import me.unurled.sacredrealms.sr.gui.ForwardItem; +import me.unurled.srcore.api.Manager; +import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.gui.Gui; +import xyz.xenondevs.invui.gui.PagedGui; +import xyz.xenondevs.invui.gui.structure.Markers; +import xyz.xenondevs.invui.item.Item; +import xyz.xenondevs.invui.item.builder.ItemBuilder; + +public class ReplayGui { + private ReplayGui() {} + + public static @NotNull Gui listGui() { + ReplayManager rm = Manager.getInstance(ReplayManager.class); + + List items = new ArrayList<>(); + for (Replay r : rm.replays()) {} + + return PagedGui.items() + .setStructure( + "# # # # # # # # #", + "# X X X X X X X #", + "# X X X X X X X #", + "# X X X X X X X #", + "# # # < # > # # #") + .addIngredient('#', new ItemBuilder(glassPane())) + .addIngredient('X', Markers.CONTENT_LIST_SLOT_HORIZONTAL) + .addIngredient('<', new BackItem()) + .addIngredient('>', new ForwardItem()) + .setContent(items) + .build(); + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/replay/ReplayItem.java b/src/main/java/me/unurled/sacredrealms/sr/gui/replay/ReplayItem.java new file mode 100644 index 0000000..31a13ed --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/replay/ReplayItem.java @@ -0,0 +1,72 @@ +package me.unurled.sacredrealms.sr.gui.replay; + +import static me.unurled.srcore.utils.Component.textComp; + +import java.util.UUID; +import me.unurled.sacredrealms.sr.SR; +import me.unurled.sacredrealms.sr.components.cutscene.Cutscene; +import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager; +import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager; +import me.unurled.srcore.api.Manager; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.AbstractItem; + +public class ReplayItem extends AbstractItem { + private static NamespacedKey ID = null; + private final String name; + private final UUID uuid; + + public ReplayItem(String name, UUID uuid) { + ID = new NamespacedKey(SR.getPlugin(), "cutscene_id"); + this.name = name; + this.uuid = uuid; + } + + @Override + public ItemProvider getItemProvider() { + ItemStack itemStack = new ItemStack(Material.PAPER); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(textComp(name)); + itemMeta.getPersistentDataContainer().set(ID, PersistentDataType.STRING, uuid.toString()); + itemStack.setItemMeta(itemMeta); + return new ItemBuilder(itemStack); + } + + @Override + public void handleClick( + @NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) { + if (event.getCurrentItem() != null) { + String uuid = + event + .getCurrentItem() + .getItemMeta() + .getPersistentDataContainer() + .get(ID, PersistentDataType.STRING); + + if (uuid == null) { + return; + } + + Cutscene cutscene = + Manager.getInstance(CutsceneManager.class).findByUUID(UUID.fromString(uuid)); + + if (cutscene == null) { + player.sendMessage(textComp("Unexpected error.")); + return; + } + if (clickType.isLeftClick()) { + Manager.getInstance(RecordingManager.class).startRecording(cutscene, player); + } + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/ConfirmItem.java b/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/ConfirmItem.java index 7ff5ab4..12eaf59 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/ConfirmItem.java +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/ConfirmItem.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.gui.treasure; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import static me.unurled.sacredrealms.sr.utils.Logger.log; import java.util.HashMap; diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/DeleteItem.java b/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/DeleteItem.java index 2a97258..5a0fede 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/DeleteItem.java +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/DeleteItem.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.gui.treasure; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import me.unurled.sacredrealms.sr.components.treasure.Treasure; import me.unurled.sacredrealms.sr.components.treasure.TreasureManager; diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/Component.java b/src/main/java/me/unurled/sacredrealms/sr/utils/Component.java deleted file mode 100644 index a3c78d8..0000000 --- a/src/main/java/me/unurled/sacredrealms/sr/utils/Component.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.unurled.sacredrealms.sr.utils; - -import java.util.List; -import java.util.stream.Collectors; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.minimessage.MiniMessage; -import org.jetbrains.annotations.NotNull; - -public class Component { - - public static final String NOT_PLAYER = "You must be a player to use this command."; - public static final String NO_PERMISSION = "You do not have permission to use this command."; - public static final String ERROR = - "An error occurred while executing this command. Please" + " contact an admin."; - public static final String PLAYER_NOT_FOUND = "Player not found."; - - private static MiniMessage miniMessage; - - private Component() {} - - public static net.kyori.adventure.text.@NotNull Component comp(String msg) { - if (miniMessage == null) { - miniMessage = MiniMessage.miniMessage(); - } - return miniMessage.deserialize(msg); - } - - public static net.kyori.adventure.text.@NotNull TextComponent textComp(String msg) { - if (miniMessage == null) { - miniMessage = MiniMessage.miniMessage(); - } - return (TextComponent) miniMessage.deserialize(msg); - } - - public static List fromStringList( - @NotNull List list) { - return list.stream().map(Component::comp).collect(Collectors.toList()); - } -} diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/CutsceneUtil.java b/src/main/java/me/unurled/sacredrealms/sr/utils/CutsceneUtil.java index 019fc40..e8aadad 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/utils/CutsceneUtil.java +++ b/src/main/java/me/unurled/sacredrealms/sr/utils/CutsceneUtil.java @@ -1,12 +1,10 @@ package me.unurled.sacredrealms.sr.utils; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; +import static me.unurled.srcore.utils.Component.textComp; import java.time.Duration; import java.util.ArrayList; import java.util.List; -import me.unurled.sacredrealms.sr.components.cutscene.Frame; -import me.unurled.sacredrealms.sr.components.cutscene.Marker; import net.kyori.adventure.key.Key; import net.kyori.adventure.title.Title; import net.kyori.adventure.title.Title.Times; @@ -32,36 +30,4 @@ public class CutsceneUtil { Duration.ofSeconds(fadeOut))); p.showTitle(title); } - - public static @NotNull List interpolateFrames( - @NotNull Marker startMarker, @NotNull Marker endMarker, long stepMillis) { - long duration = startMarker.getOverAllTime(); - - int numFrames = (int) (duration / stepMillis); - - double xDiff = (endMarker.getStart().getX() - startMarker.getStart().getX()) / numFrames; - double yDiff = (endMarker.getStart().getY() - startMarker.getStart().getY()) / numFrames; - double zDiff = (endMarker.getStart().getZ() - startMarker.getStart().getZ()) / numFrames; - double yawDiff = (endMarker.getStart().getYaw() - startMarker.getStart().getYaw()) / numFrames; - double pitchDiff = - (endMarker.getStart().getPitch() - startMarker.getStart().getPitch()) / numFrames; - - ArrayList frames = new ArrayList<>(); - - for (int i = 0; i < numFrames; i++) { - - double x = startMarker.getStart().getX() + xDiff * i; - double y = startMarker.getStart().getY() + yDiff * i; - double z = startMarker.getStart().getZ() + zDiff * i; - double yaw = startMarker.getStart().getYaw() + yawDiff * i; - double pitch = startMarker.getStart().getPitch() + pitchDiff * i; - - Frame frame = - new Frame( - new Location(startMarker.getStart().getWorld(), x, y, z, (float) yaw, (float) pitch)); - - frames.add(frame); - } - return frames; - } } diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java b/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java index 1ebb3d3..1af206e 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java +++ b/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java @@ -1,8 +1,8 @@ package me.unurled.sacredrealms.sr.utils; -import static me.unurled.sacredrealms.sr.utils.Component.comp; -import static me.unurled.sacredrealms.sr.utils.Component.textComp; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer; +import static me.unurled.srcore.utils.Component.comp; +import static me.unurled.srcore.utils.Component.textComp; import com.google.gson.JsonElement; import java.util.ArrayList; diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/Region.java b/src/main/java/me/unurled/sacredrealms/sr/utils/Region.java new file mode 100644 index 0000000..84b790f --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/utils/Region.java @@ -0,0 +1,145 @@ +package me.unurled.sacredrealms.sr.utils; + +import java.util.ArrayList; +import java.util.List; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class Region { + private Location corner1; + private Location corner2; + + public Region() { + this.corner1 = null; + this.corner2 = null; + } + + public boolean isSet() { + return corner1 != null && corner2 != null; + } + + @Nullable + public World getWorld() { + if (corner1 == null) return null; + return corner1.getWorld(); + } + + public boolean isIn(final @NotNull Location loc) { + if (corner1 == null || corner2 == null) { + return false; + } + + double xMin = Math.min(corner1.getX(), corner2.getX()); + double xMax = Math.max(corner1.getX(), corner2.getX()); + double yMin = Math.min(corner1.getY(), corner2.getY()); + double yMax = Math.max(corner1.getY(), corner2.getY()); + double zMin = Math.min(corner1.getZ(), corner2.getZ()); + double zMax = Math.max(corner1.getZ(), corner2.getZ()); + + // if the location is within the region in the x, y, and z axis + return loc.getBlockX() >= xMin + && loc.getBlockX() <= xMax + && loc.getBlockY() >= yMin + && loc.getBlockY() <= yMax + && loc.getBlockZ() >= zMin + && loc.getBlockZ() <= zMax; + } + + public int getTotalBlockSize() { + return (int) (this.getHeight() * this.getXWidth() * this.getZWidth()); + } + + public double getHeight() { + if (corner1 == null || corner2 == null) { + return -1; + } + double yMin = Math.min(corner1.getY(), corner2.getY()); + double yMax = Math.max(corner1.getY(), corner2.getY()); + return yMax - yMin + 1; + } + + public double getXWidth() { + if (corner1 == null || corner2 == null) { + return -1; + } + double xMin = Math.min(corner1.getX(), corner2.getX()); + double xMax = Math.max(corner1.getX(), corner2.getX()); + return xMax - xMin + 1; + } + + public double getZWidth() { + if (corner1 == null || corner2 == null) { + return -1; + } + double zMin = Math.min(corner1.getZ(), corner2.getZ()); + double zMax = Math.max(corner1.getZ(), corner2.getZ()); + return zMax - zMin + 1; + } + + @NotNull + public List blockList(World world) { + if (corner1 == null || corner2 == null) { + return List.of(); + } + double xMin = Math.min(corner1.getX(), corner2.getX()); + double xMax = Math.max(corner1.getX(), corner2.getX()); + double yMin = Math.min(corner1.getY(), corner2.getY()); + double yMax = Math.max(corner1.getY(), corner2.getY()); + double zMin = Math.min(corner1.getZ(), corner2.getZ()); + double zMax = Math.max(corner1.getZ(), corner2.getZ()); + + final ArrayList bL = new ArrayList<>(this.getTotalBlockSize()); + for (double x = xMin; x <= xMax; ++x) { + for (double y = yMin; y <= yMax; ++y) { + for (double z = zMin; z <= zMax; ++z) { + final Block b = world.getBlockAt((int) x, (int) y, (int) z); + bL.add(b); + } + } + } + return bL; + } + + public boolean isPlayerIn(@NotNull Player player) { + return this.isIn(player.getLocation()); + } + + @NotNull + public List getEntities() { + List entities = new ArrayList<>(); + if (corner1 == null || corner1.getWorld() == null) { + return entities; + } + List blocks = blockList(corner1.getWorld()); + if (blocks == null) { + return entities; + } + for (Block block : blocks) { + entities.addAll(block.getWorld().getNearbyEntities(block.getLocation(), 1, 1, 1)); + } + return entities; + } + + public Location corner1() { + return corner1; + } + + public Location corner2() { + return corner2; + } + + public Region setCorner1(Location corner1) { + this.corner1 = corner1; + return this; + } + + public Region setCorner2(Location corner2) { + this.corner2 = corner2; + return this; + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/RegionUtil.java b/src/main/java/me/unurled/sacredrealms/sr/utils/RegionUtil.java new file mode 100644 index 0000000..f6003ce --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/utils/RegionUtil.java @@ -0,0 +1,139 @@ +package me.unurled.sacredrealms.sr.utils; + +import static me.unurled.sacredrealms.sr.utils.Logger.error; +import static me.unurled.sacredrealms.sr.utils.Logger.log; +import static org.bukkit.Bukkit.getServer; + +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Slime; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; +import org.jetbrains.annotations.NotNull; + +public class RegionUtil { + + private static final String REGIONSELECTOR = "srselector"; + + public static void killSelectorsWithTag(String inputTag) { + for (World world : getServer().getWorlds()) { + for (Entity entity : world.getEntities()) { + for (String tag : entity.getScoreboardTags()) { + if (tag.equals(REGIONSELECTOR + "-" + inputTag)) { + entity.remove(); + break; + } + } + } + } + } + + public static void killAllSelectors() { + for (World world : getServer().getWorlds()) { + for (Entity entity : world.getEntities()) { + for (String tag : entity.getScoreboardTags()) { + if (tag.startsWith(REGIONSELECTOR + "-")) { + entity.remove(); + break; + } + } + } + } + } + + public static void drawSelector( + @NotNull Region region, World world, String id, NamedTextColor glowColor) { + Location loc1 = region.corner1(); + Location loc2 = region.corner2(); + if (loc1.getWorld() == null || !loc1.getWorld().equals(loc2.getWorld())) { + return; + } + int minx = Math.min(loc1.getBlockX(), loc2.getBlockX()); + int miny = Math.min(loc1.getBlockY(), loc2.getBlockY()); + int minz = Math.min(loc1.getBlockZ(), loc2.getBlockZ()); + int maxx = Math.max(loc1.getBlockX(), loc2.getBlockX()); + int maxy = Math.max(loc1.getBlockY(), loc2.getBlockY()); + int maxz = Math.max(loc1.getBlockZ(), loc2.getBlockZ()); + + Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + + int highestNumber = 0; + + for (Team team : board.getTeams()) { + if (team.getName().startsWith(REGIONSELECTOR + "+")) { + String number = team.getName().substring(11); + try { + int tempNumber = Integer.parseInt(number); + if (tempNumber >= highestNumber) { + highestNumber = tempNumber; + } + } catch (NumberFormatException e) { + error(e.getMessage()); + } + } + } + + log(REGIONSELECTOR + "+" + (highestNumber + 1)); + + Team selectorTeam = board.registerNewTeam(REGIONSELECTOR + "+" + (highestNumber + 1)); + if (glowColor != null) { + selectorTeam.color(glowColor); + } + selectorTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER); + + for (double x = minx; x <= maxx; x++) { + makeSlime(id, world, selectorTeam, x, miny, minz); + makeSlime(id, world, selectorTeam, x, maxy, minz); + makeSlime(id, world, selectorTeam, x, miny, maxz); + makeSlime(id, world, selectorTeam, x, maxy, maxz); + } + + for (double y = miny; y <= maxy; y++) { + makeSlime(id, world, selectorTeam, minx, y, minz); + makeSlime(id, world, selectorTeam, maxx, y, minz); + makeSlime(id, world, selectorTeam, minx, y, maxz); + makeSlime(id, world, selectorTeam, maxx, y, maxz); + } + + for (double z = minz; z <= maxz; z++) { + makeSlime(id, world, selectorTeam, minx, miny, z); + makeSlime(id, world, selectorTeam, maxx, miny, z); + makeSlime(id, world, selectorTeam, minx, maxy, z); + makeSlime(id, world, selectorTeam, maxx, maxy, z); + } + } + + private static void makeSlime( + String id, @NotNull World world, @NotNull Team selectorTeam, double x, double y, double z) { + Slime slime = + (Slime) + world.spawnEntity( + new Location(world, x + 0.5, y, z + 0.5), EntityType.SLIME, SpawnReason.CUSTOM); + slime.setSize(2); + slime.setAI(false); + slime.setGravity(false); + slime.setCollidable(false); + slime.setSilent(true); + slime.setCanPickupItems(false); + slime.setGlowing(true); + slime.setInvulnerable(true); + slime.setInvisible(true); + slime.addScoreboardTag(REGIONSELECTOR + "-" + id); + slime.setPersistent(true); + selectorTeam.addEntry(String.valueOf(slime.getUniqueId())); + } + + public void removeTempTeams() { + Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + for (Team team : board.getTeams()) { + if (team.getName().startsWith(REGIONSELECTOR + "+")) { + team.unregister(); + } + } + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/SRPlayerUtils.java b/src/main/java/me/unurled/sacredrealms/sr/utils/SRPlayerUtils.java index c28975b..fd327d0 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/utils/SRPlayerUtils.java +++ b/src/main/java/me/unurled/sacredrealms/sr/utils/SRPlayerUtils.java @@ -1,6 +1,6 @@ package me.unurled.sacredrealms.sr.utils; -import static me.unurled.sacredrealms.sr.utils.Component.comp; +import static me.unurled.srcore.utils.Component.comp; import java.util.List; import java.util.Random;