From 0965e621a959e99e12e5a00355d873b458e82d47 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 30 Jun 2024 22:32:15 -0500 Subject: [PATCH] More options and bug fixes --- .../org/battleplugins/arena/BattleArena.java | 11 ++++---- .../arena/command/ArenaCommandExecutor.java | 10 +++++++ .../arena/command/BaseCommandExecutor.java | 28 +++++++++++-------- .../arena/competition/OptionsListener.java | 12 ++++++++ .../phase/phases/VictoryPhase.java | 5 ++-- .../arena/config/ArenaConfigParser.java | 11 +++++++- .../arena/editor/ArenaEditorWizards.java | 2 ++ .../arena/event/ArenaEventManager.java | 1 + .../arena/options/ArenaOptionType.java | 2 ++ 9 files changed, 62 insertions(+), 20 deletions(-) diff --git a/plugin/src/main/java/org/battleplugins/arena/BattleArena.java b/plugin/src/main/java/org/battleplugins/arena/BattleArena.java index c4b0246b..fbaad434 100644 --- a/plugin/src/main/java/org/battleplugins/arena/BattleArena.java +++ b/plugin/src/main/java/org/battleplugins/arena/BattleArena.java @@ -326,12 +326,6 @@ public void registerArena(Plugin plugin, String name, Class throw new RuntimeException("Failed to instantiate arena " + arenaClass.getName(), e); } }); - - if (plugin != this) { - this.info("Registered arena {} from plugin {}.", name, plugin.getName()); - - this.loadArenaLoaders(plugin.getDataFolder().toPath().resolve("arenas")); - } } /** @@ -346,6 +340,11 @@ public void registerArena(Plugin plugin, String name, Class ArenaConfigParser.registerFactory(arenaClass, arenaFactory); this.arenaTypes.put(name, new ArenaType(plugin, arenaClass)); + if (plugin != this) { + this.info("Registered arena {} from plugin {}.", name, plugin.getName()); + + this.loadArenaLoaders(plugin.getDataFolder().toPath().resolve("arenas")); + } } /** diff --git a/plugin/src/main/java/org/battleplugins/arena/command/ArenaCommandExecutor.java b/plugin/src/main/java/org/battleplugins/arena/command/ArenaCommandExecutor.java index 6350434c..727694e2 100644 --- a/plugin/src/main/java/org/battleplugins/arena/command/ArenaCommandExecutor.java +++ b/plugin/src/main/java/org/battleplugins/arena/command/ArenaCommandExecutor.java @@ -288,6 +288,16 @@ protected List onVerifyTabComplete(String arg, Class parameter) { return super.onVerifyTabComplete(arg, parameter); } + @Override + protected String onGetUsageString(Class parameter) { + return switch (parameter.getSimpleName().toLowerCase()) { + case "arena" -> " "; + case "competition" -> " "; // Best name for player-facing values + case "competitionmap" -> " "; + default -> super.onGetUsageString(parameter); + }; + } + @Override public final void sendHeader(CommandSender sender) { Messages.HEADER.sendCentered(sender, this.arena.getName()); diff --git a/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java b/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java index 97240503..077ca2ac 100644 --- a/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java +++ b/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java @@ -7,6 +7,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.MethodUtils; import org.battleplugins.arena.BattleArena; import org.battleplugins.arena.config.ItemStackParser; import org.battleplugins.arena.config.ParseException; @@ -128,17 +129,15 @@ public final boolean onCommand(CommandSender sender, Command command, String lab } private void registerCommands() { - for (Method method : this.getClass().getDeclaredMethods()) { - if (method.isAnnotationPresent(ArenaCommand.class)) { - ArenaCommand arenaCommand = method.getAnnotation(ArenaCommand.class); + for (Method method : MethodUtils.getMethodsWithAnnotation(this.getClass(), ArenaCommand.class, true, true)) { + ArenaCommand arenaCommand = method.getAnnotation(ArenaCommand.class); - CommandWrapper wrapper = new CommandWrapper(this, method, this.getUsage(method)); - for (String cmd : arenaCommand.commands()) { - Set wrappers = this.commandMethods.getOrDefault(cmd, new HashSet<>()); - wrappers.add(wrapper); + CommandWrapper wrapper = new CommandWrapper(this, method, this.getUsage(method)); + for (String cmd : arenaCommand.commands()) { + Set wrappers = this.commandMethods.getOrDefault(cmd, new HashSet<>()); + wrappers.add(wrapper); - this.commandMethods.put(cmd, wrappers); - } + this.commandMethods.put(cmd, wrappers); } } } @@ -587,6 +586,11 @@ private String getUsageString(Class parameter, @Nullable Argument argument) { return "<" + argument.name() + "> "; } + String usageString = this.onGetUsageString(parameter); + if (usageString != null) { + return usageString; + } + return switch (parameter.getSimpleName().toLowerCase()) { case "string[]" -> "[string...] "; case "int", "double", "float" -> " "; @@ -594,8 +598,6 @@ private String getUsageString(Class parameter, @Nullable Argument argument) { case "material" -> " "; case "player", "offlineplayer" -> " "; case "world" -> " "; - case "arena" -> " "; - case "competition" -> " "; // Best name for player-facing values default -> { for (SubCommandExecutor subCommandExecutor : this.subCommandExecutors) { String usage = subCommandExecutor.getUsageString(parameter); @@ -619,6 +621,10 @@ private String getUsageString(Class parameter, @Nullable Argument argument) { }; } + protected String onGetUsageString(Class parameter) { + return null; + } + @NotNull @Override public final List onTabComplete(CommandSender sender, Command command, String label, String[] args) { diff --git a/plugin/src/main/java/org/battleplugins/arena/competition/OptionsListener.java b/plugin/src/main/java/org/battleplugins/arena/competition/OptionsListener.java index afe1c122..e16d1e45 100644 --- a/plugin/src/main/java/org/battleplugins/arena/competition/OptionsListener.java +++ b/plugin/src/main/java/org/battleplugins/arena/competition/OptionsListener.java @@ -14,6 +14,7 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; class OptionsListener> implements ArenaListener, CompetitionLike { @@ -28,6 +29,10 @@ public void onBlockBreak(BlockBreakEvent event) { if (!this.competition.option(ArenaOptionType.BLOCK_BREAK).map(BooleanArenaOption::isEnabled).orElse(true)) { event.setCancelled(true); } + + if (!this.competition.option(ArenaOptionType.BLOCK_DROPS).map(BooleanArenaOption::isEnabled).orElse(true)) { + event.setDropItems(false); + } } @ArenaEventHandler(priority = EventPriority.LOWEST) @@ -37,6 +42,13 @@ public void onBlockPlace(BlockPlaceEvent event) { } } + @ArenaEventHandler(priority = EventPriority.LOWEST) + public void onDropItem(PlayerDropItemEvent event) { + if (!this.competition.option(ArenaOptionType.ITEM_DROPS).map(BooleanArenaOption::isEnabled).orElse(true)) { + event.setCancelled(true); + } + } + @ArenaEventHandler(priority = EventPriority.LOWEST) public void onPlayerInteract(PlayerInteractEvent event) { if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_BLOCK) { diff --git a/plugin/src/main/java/org/battleplugins/arena/competition/phase/phases/VictoryPhase.java b/plugin/src/main/java/org/battleplugins/arena/competition/phase/phases/VictoryPhase.java index 5369d4b0..e699bb18 100644 --- a/plugin/src/main/java/org/battleplugins/arena/competition/phase/phases/VictoryPhase.java +++ b/plugin/src/main/java/org/battleplugins/arena/competition/phase/phases/VictoryPhase.java @@ -10,12 +10,13 @@ import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitTask; +import java.time.Duration; import java.util.HashSet; import java.util.Set; public class VictoryPhase> extends LiveCompetitionPhase { @ArenaOption(name = "duration", description = "The number of seconds to remain in the victory condition.", required = true) - private int duration; + private Duration duration; private BukkitTask durationTask; @@ -31,7 +32,7 @@ public void onStart() { this.durationTask = Bukkit.getScheduler().runTaskLater( this.competition.getArena().getPlugin(), this::advanceToNextPhase, - this.duration * 20L + this.duration.toMillis() / 50 ); } diff --git a/plugin/src/main/java/org/battleplugins/arena/config/ArenaConfigParser.java b/plugin/src/main/java/org/battleplugins/arena/config/ArenaConfigParser.java index 03801fe4..21891ce2 100644 --- a/plugin/src/main/java/org/battleplugins/arena/config/ArenaConfigParser.java +++ b/plugin/src/main/java/org/battleplugins/arena/config/ArenaConfigParser.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -233,7 +234,9 @@ private static void populateType(@Nullable Path sourceFile, Field field, ArenaOp // Unknown object! Let's try to parse it ConfigurationSection configurationSection = configuration.getConfigurationSection(name); if (configurationSection == null) { - if (configuration.contains(name)) { + if (configuration.get(name) instanceof Map map) { + configurationSection = toMemorySection((Map) map); + } else if (configuration.contains(name)) { throw new ParseException("Invalid object " + name + " in configuration section " + configuration.getName()) .cause(ParseException.Cause.INVALID_TYPE) .context("Option name", arenaOption.name()) @@ -514,6 +517,12 @@ private static List toMemorySections(List list) { return sections; } + private static ConfigurationSection toMemorySection(Map map) { + MemoryConfiguration memoryConfig = new MemoryConfiguration(); + memoryConfig.addDefaults(map); + return memoryConfig; + } + public interface Parser { T parse(Object object) throws ParseException; } diff --git a/plugin/src/main/java/org/battleplugins/arena/editor/ArenaEditorWizards.java b/plugin/src/main/java/org/battleplugins/arena/editor/ArenaEditorWizards.java index 0c99336b..7c7ba043 100644 --- a/plugin/src/main/java/org/battleplugins/arena/editor/ArenaEditorWizards.java +++ b/plugin/src/main/java/org/battleplugins/arena/editor/ArenaEditorWizards.java @@ -102,6 +102,8 @@ public final class ArenaEditorWizards { Spawns spawns = new Spawns(ctx.getWaitroomSpawn(), ctx.getSpectatorSpawn(), teamSpawns); LiveCompetitionMap map = ctx.getArena().getMapFactory().create(ctx.getMapName(), ctx.getArena(), ctx.getMapType(), ctx.getPlayer().getWorld().getName(), bounds, spawns); + map.postProcess(); // Call post process to ensure all data is loaded + BattleArena.getInstance().addArenaMap(ctx.getArena(), map); // If our competition is a match, create it diff --git a/plugin/src/main/java/org/battleplugins/arena/event/ArenaEventManager.java b/plugin/src/main/java/org/battleplugins/arena/event/ArenaEventManager.java index feaa3a7c..2c483d86 100644 --- a/plugin/src/main/java/org/battleplugins/arena/event/ArenaEventManager.java +++ b/plugin/src/main/java/org/battleplugins/arena/event/ArenaEventManager.java @@ -258,6 +258,7 @@ public void registerEvents(ArenaListener listener) { if (ArenaPlayerEvent.class.isAssignableFrom(eventClass)) { try { method.invoke(eventListener, event, ((ArenaPlayerEvent) event).getArenaPlayer()); + return; } catch (Exception e) { throw new EventException(e, "Error executing ArenaPlayerEvent: " + eventClass); } diff --git a/plugin/src/main/java/org/battleplugins/arena/options/ArenaOptionType.java b/plugin/src/main/java/org/battleplugins/arena/options/ArenaOptionType.java index 92ea7769..aa2ac374 100644 --- a/plugin/src/main/java/org/battleplugins/arena/options/ArenaOptionType.java +++ b/plugin/src/main/java/org/battleplugins/arena/options/ArenaOptionType.java @@ -21,7 +21,9 @@ public final class ArenaOptionType { public static final ArenaOptionType BLOCK_BREAK = new ArenaOptionType<>("block-break", BooleanArenaOption::new); public static final ArenaOptionType BLOCK_PLACE = new ArenaOptionType<>("block-place", BooleanArenaOption::new); + public static final ArenaOptionType BLOCK_DROPS = new ArenaOptionType<>("block-drops", BooleanArenaOption::new); public static final ArenaOptionType BLOCK_INTERACT = new ArenaOptionType<>("block-interact", BooleanArenaOption::new); + public static final ArenaOptionType ITEM_DROPS = new ArenaOptionType<>("item-drops", BooleanArenaOption::new); public static final ArenaOptionType KEEP_INVENTORY = new ArenaOptionType<>("keep-inventory", BooleanArenaOption::new); public static final ArenaOptionType KEEP_EXPERIENCE = new ArenaOptionType<>("keep-experience", BooleanArenaOption::new);