diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/CommandsOnLevel.java b/src/main/java/com/gmail/nossr50/commands/levelup/CommandsOnLevel.java new file mode 100644 index 000000000..eed723aa2 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/levelup/CommandsOnLevel.java @@ -0,0 +1,4 @@ +package com.gmail.nossr50.commands.levelup; + +public interface CommandsOnLevel { +} diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommand.java b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommand.java deleted file mode 100644 index 02876bfa1..000000000 --- a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommand.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.gmail.nossr50.commands.levelup; - -import com.gmail.nossr50.datatypes.player.McMMOPlayer; -import com.gmail.nossr50.datatypes.skills.PrimarySkillType; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.Set; -import java.util.function.BiPredicate; - -import static java.util.Objects.requireNonNull; - -/** - * Represents a command to be executed on a level up - */ -public interface LevelUpCommand { - /** - * Process the command - * - * @param player the player - * @param primarySkillType the skill type - * @param levelsGained the levels gained - */ - void process(McMMOPlayer player, PrimarySkillType primarySkillType, Set levelsGained); - - /** - * Execute the command - * @param player the player - * @param primarySkillType the skill - * @param level the level of the skill - */ - void executeCommand(McMMOPlayer player, PrimarySkillType primarySkillType, int level); - - class LevelUpCommandBuilder { - private Set skillFilter = null; - private Set levels = null; - private LinkedList commands = null; - private BiPredicate predicate = null; - private boolean logInfo; - - public LevelUpCommandBuilder() { - this.logInfo = false; - } - - public LevelUpCommandBuilder withPredicate(BiPredicate predicate) { - this.predicate = predicate; - return this; - } - - public LevelUpCommandBuilder withLogInfo(boolean logInfo) { - this.logInfo = logInfo; - return this; - } - - public LevelUpCommandBuilder command(@NotNull String command) { - this.commands = new LinkedList<>(); - this.commands.add(command); - return this; - } - - public LevelUpCommandBuilder commands(@NotNull Collection command) { - this.commands = new LinkedList<>(command); - return this; - } - - public LevelUpCommandBuilder withLevels(@NotNull Collection levels) { - requireNonNull(levels, "levels is null!"); - this.levels = Set.copyOf(levels); - return this; - } - - public LevelUpCommandBuilder withSkillFilter(@NotNull Set skillFilter) { - requireNonNull(skillFilter, "skillFilter is null!"); - if (skillFilter.isEmpty()) { - throw new IllegalArgumentException("skillFilter is empty"); - } - this.skillFilter = skillFilter; - return this; - } - - public LevelUpCommandBuilder withSkillFilter(@NotNull PrimarySkillType skill) { - requireNonNull(skill, "skill is null!"); - this.skillFilter = Set.of(skill); - return this; - } - - public LevelUpCommand build() { - requireNonNull(commands, "commandStr is null"); - if (predicate == null) { - requireNonNull(levels, "levels is null"); - - return new LevelUpCommandImpl((skill, level) -> { - if (skillFilter == null) { - return levels.contains(level); - } else { - return skillFilter.contains(skill) && levels.contains(level); - } - }, commands, logInfo); - } - - return new LevelUpCommandImpl(predicate, commands, logInfo); - } - } -} diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandManager.java b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandManager.java index 72a6e9633..c1ae12a90 100644 --- a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandManager.java +++ b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandManager.java @@ -9,26 +9,32 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; +import static java.util.Objects.requireNonNull; + /** * Manages commands to be executed on level up */ public class LevelUpCommandManager { - private final @NotNull Set commands; + private final @NotNull Set skillLevelCommands; + private final @NotNull Set powerLevelUpCommands; private final @NotNull mcMMO plugin; public LevelUpCommandManager(@NotNull mcMMO plugin) { - this.plugin = plugin; - this.commands = new HashSet<>(); + this.plugin = requireNonNull(plugin, "plugin cannot be null"); + this.skillLevelCommands = new HashSet<>(); + this.powerLevelUpCommands = new HashSet<>(); } - /** - * Register a level up command to be executed on level up - * - * @param levelUpCommand the levelUpCommand - */ - public void registerCommand(@NotNull LevelUpCommand levelUpCommand) { - commands.add(levelUpCommand); - mcMMO.p.getLogger().info("Registered levelUpCommand on level up: " + levelUpCommand); + public void registerCommand(@NotNull SkillLevelUpCommand skillLevelUpCommand) { + requireNonNull(skillLevelUpCommand, "skillLevelUpCommand cannot be null"); + skillLevelCommands.add(skillLevelUpCommand); + mcMMO.p.getLogger().info("Registered level up command - SkillLevelUpCommand: " + skillLevelUpCommand); + } + + public void registerCommand(@NotNull PowerLevelUpCommand powerLevelUpCommand) { + requireNonNull(powerLevelUpCommand, "powerLevelUpCommand cannot be null"); + powerLevelUpCommands.add(powerLevelUpCommand); + mcMMO.p.getLogger().info("Registered level up command - PowerLevelUpCommand: " + powerLevelUpCommand); } /** @@ -38,29 +44,41 @@ public class LevelUpCommandManager { * @param primarySkillType the skill type * @param levelsGained the levels gained */ - public void apply(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType, Set levelsGained) { + public void applySkillLevelUp(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType, Set levelsGained) { if (!mmoPlayer.getPlayer().isOnline()) { return; } - for (LevelUpCommand command : commands) { + for (SkillLevelUpCommand command : skillLevelCommands) { command.process(mmoPlayer, primarySkillType, levelsGained); } } + public void applyPowerLevelUp(@NotNull McMMOPlayer mmoPlayer, Set levelsGained) { + if (!mmoPlayer.getPlayer().isOnline()) { + return; + } + + for (PowerLevelUpCommand command : powerLevelUpCommands) { + command.process(mmoPlayer, levelsGained); + } + } + + public @NotNull Set getSkillLevelCommands() { + return skillLevelCommands; + } + + public @NotNull Set getPowerLevelUpCommands() { + return powerLevelUpCommands; + } + /** * Clear all registered commands */ public void clear() { mcMMO.p.getLogger().info("Clearing registered commands on level up"); - commands.clear(); - } - - /** - * @return true if there are no registered commands - */ - public boolean isEmpty() { - return commands.isEmpty(); + skillLevelCommands.clear(); + powerLevelUpCommands.clear(); } @Override @@ -68,18 +86,19 @@ public class LevelUpCommandManager { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LevelUpCommandManager that = (LevelUpCommandManager) o; - return Objects.equals(commands, that.commands) && Objects.equals(plugin, that.plugin); + return Objects.equals(skillLevelCommands, that.skillLevelCommands) && Objects.equals(powerLevelUpCommands, that.powerLevelUpCommands) && Objects.equals(plugin, that.plugin); } @Override public int hashCode() { - return Objects.hash(commands, plugin); + return Objects.hash(skillLevelCommands, powerLevelUpCommands, plugin); } @Override public String toString() { return "LevelUpCommandManager{" + - "commands=" + commands + + "skillLevelCommands=" + skillLevelCommands + + ", powerLevelUpCommands=" + powerLevelUpCommands + ", plugin=" + plugin + '}'; } diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommand.java b/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommand.java new file mode 100644 index 000000000..754eff0f2 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommand.java @@ -0,0 +1,98 @@ +package com.gmail.nossr50.commands.levelup; + +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.util.LogUtils; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedList; +import java.util.Objects; +import java.util.Set; +import java.util.function.Predicate; + +public class PowerLevelUpCommand implements CommandsOnLevel { + private final Predicate predicate; + private final boolean logInfo; + private final @NotNull LinkedList commands; + + public PowerLevelUpCommand(@NotNull Predicate predicate, @NotNull String command, boolean logInfo) { + this.predicate = predicate; + this.commands = new LinkedList<>(); + this.commands.add(command); + this.logInfo = logInfo; + } + + public PowerLevelUpCommand(@NotNull Predicate predicate, @NotNull LinkedList commands, boolean logInfo) { + this.predicate = predicate; + this.commands = commands; + this.logInfo = logInfo; + } + + public void process(McMMOPlayer player, Set levelsGained) { + for (int i : levelsGained) { + if (predicate.test(i)) { + // execute command via server console in Bukkit + if(logInfo) { + mcMMO.p.getLogger().info("Executing command: " + commands); + } else { + LogUtils.debug(mcMMO.p.getLogger(), "Executing command: " + commands); + } + executeCommand(player, i); + } + } + } + + public void executeCommand(McMMOPlayer player, int level) { + // TODO: Change this to debug later + mcMMO.p.getLogger().info("Executing commands for level up: " + commands); + for (String command : commands) { + // TODO: Change this to debug later + mcMMO.p.getLogger().info("Executing command: " + command); + String injectedCommand = injectedCommand(command, player, level); + // TODO: Remove verbose logging later + if (!injectedCommand.equalsIgnoreCase(command)) { + mcMMO.p.getLogger().info(("Command has been injected with new values: " + injectedCommand)); + } + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), injectedCommand); + } + } + + private String injectedCommand(String command, McMMOPlayer player, int level) { + // replace %player% with player name, %skill% with skill name, and %level% with level + command = safeReplace(command, "%player%", player.getPlayer().getName()); + command = safeReplace(command, "%skill%", "power level"); + command = safeReplace(command, "%level%", String.valueOf(level)); + return command; + } + + private String safeReplace(String targetStr, String toReplace, String replacement) { + if (replacement == null) { + return targetStr; + } + + return targetStr.replace(toReplace, replacement); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PowerLevelUpCommand that = (PowerLevelUpCommand) o; + return logInfo == that.logInfo && Objects.equals(predicate, that.predicate) && Objects.equals(commands, that.commands); + } + + @Override + public int hashCode() { + return Objects.hash(predicate, logInfo, commands); + } + + @Override + public String toString() { + return "PowerLevelUpCommand{" + + "predicate=" + predicate + + ", logInfo=" + logInfo + + ", commands=" + commands + + '}'; + } +} diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommandBuilder.java b/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommandBuilder.java new file mode 100644 index 000000000..a80c0251e --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommandBuilder.java @@ -0,0 +1,59 @@ +package com.gmail.nossr50.commands.levelup; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.Set; +import java.util.function.Predicate; + +import static java.util.Objects.requireNonNull; + +public class PowerLevelUpCommandBuilder { + private Set levels = null; + private LinkedList commands = null; + private Predicate predicate = null; + private boolean logInfo; + + public PowerLevelUpCommandBuilder() { + this.logInfo = false; + } + + public PowerLevelUpCommandBuilder withPredicate(Predicate predicate) { + this.predicate = predicate; + return this; + } + + public PowerLevelUpCommandBuilder withLogInfo(boolean logInfo) { + this.logInfo = logInfo; + return this; + } + + public PowerLevelUpCommandBuilder command(@NotNull String command) { + this.commands = new LinkedList<>(); + this.commands.add(command); + return this; + } + + public PowerLevelUpCommandBuilder commands(@NotNull Collection command) { + this.commands = new LinkedList<>(command); + return this; + } + + public PowerLevelUpCommandBuilder withLevels(@NotNull Collection levels) { + requireNonNull(levels, "levels is null!"); + this.levels = Set.copyOf(levels); + return this; + } + + public PowerLevelUpCommand build() { + requireNonNull(commands, "commandStr is null"); + if (predicate == null) { + requireNonNull(levels, "levels is null"); + + return new PowerLevelUpCommand((level) -> levels.contains(level), commands, logInfo); + } + + return new PowerLevelUpCommand(predicate, commands, logInfo); + } +} diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandImpl.java b/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommand.java similarity index 89% rename from src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandImpl.java rename to src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommand.java index 935abed0a..798abbe67 100644 --- a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandImpl.java +++ b/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommand.java @@ -12,25 +12,24 @@ import java.util.Objects; import java.util.Set; import java.util.function.BiPredicate; -public class LevelUpCommandImpl implements LevelUpCommand { +public class SkillLevelUpCommand implements CommandsOnLevel { private final BiPredicate predicate; private final boolean logInfo; private final @NotNull LinkedList commands; - public LevelUpCommandImpl(@NotNull BiPredicate predicate, @NotNull String command, boolean logInfo) { + public SkillLevelUpCommand(@NotNull BiPredicate predicate, @NotNull String command, boolean logInfo) { this.predicate = predicate; this.commands = new LinkedList<>(); this.commands.add(command); this.logInfo = logInfo; } - public LevelUpCommandImpl(@NotNull BiPredicate predicate, @NotNull LinkedList commands, boolean logInfo) { + public SkillLevelUpCommand(@NotNull BiPredicate predicate, @NotNull LinkedList commands, boolean logInfo) { this.predicate = predicate; this.commands = commands; this.logInfo = logInfo; } - @Override public void process(McMMOPlayer player, PrimarySkillType primarySkillType, Set levelsGained) { for (int i : levelsGained) { if (predicate.test(primarySkillType, i)) { @@ -80,7 +79,7 @@ public class LevelUpCommandImpl implements LevelUpCommand { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - LevelUpCommandImpl that = (LevelUpCommandImpl) o; + SkillLevelUpCommand that = (SkillLevelUpCommand) o; return logInfo == that.logInfo && Objects.equals(predicate, that.predicate) && Objects.equals(commands, that.commands); } diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommandBuilder.java b/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommandBuilder.java new file mode 100644 index 000000000..98b731d96 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommandBuilder.java @@ -0,0 +1,82 @@ +package com.gmail.nossr50.commands.levelup; + +import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.Set; +import java.util.function.BiPredicate; + +import static java.util.Objects.requireNonNull; + +public class SkillLevelUpCommandBuilder { + private Set skillFilter = null; + private Set levels = null; + private LinkedList commands = null; + private BiPredicate predicate = null; + private boolean logInfo; + + public SkillLevelUpCommandBuilder() { + this.logInfo = false; + } + + public SkillLevelUpCommandBuilder withPredicate(BiPredicate predicate) { + this.predicate = predicate; + return this; + } + + public SkillLevelUpCommandBuilder withLogInfo(boolean logInfo) { + this.logInfo = logInfo; + return this; + } + + public SkillLevelUpCommandBuilder command(@NotNull String command) { + this.commands = new LinkedList<>(); + this.commands.add(command); + return this; + } + + public SkillLevelUpCommandBuilder commands(@NotNull Collection command) { + this.commands = new LinkedList<>(command); + return this; + } + + public SkillLevelUpCommandBuilder withLevels(@NotNull Collection levels) { + requireNonNull(levels, "levels is null!"); + this.levels = Set.copyOf(levels); + return this; + } + + public SkillLevelUpCommandBuilder withSkillFilter(@NotNull Set skillFilter) { + requireNonNull(skillFilter, "skillFilter is null!"); + if (skillFilter.isEmpty()) { + throw new IllegalArgumentException("skillFilter is empty"); + } + this.skillFilter = skillFilter; + return this; + } + + public SkillLevelUpCommandBuilder withSkillFilter(@NotNull PrimarySkillType skill) { + requireNonNull(skill, "skill is null!"); + this.skillFilter = Set.of(skill); + return this; + } + + public SkillLevelUpCommand build() { + requireNonNull(commands, "commandStr is null"); + if (predicate == null) { + requireNonNull(levels, "levels is null"); + + return new SkillLevelUpCommand((skill, level) -> { + if (skillFilter == null) { + return levels.contains(level); + } else { + return skillFilter.contains(skill) && levels.contains(level); + } + }, commands, logInfo); + } + + return new SkillLevelUpCommand(predicate, commands, logInfo); + } +} diff --git a/src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java b/src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java index 7d4a7e388..dcac847bc 100644 --- a/src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java +++ b/src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java @@ -1,6 +1,9 @@ package com.gmail.nossr50.config; -import com.gmail.nossr50.commands.levelup.LevelUpCommand; +import com.gmail.nossr50.commands.levelup.PowerLevelUpCommand; +import com.gmail.nossr50.commands.levelup.PowerLevelUpCommandBuilder; +import com.gmail.nossr50.commands.levelup.SkillLevelUpCommand; +import com.gmail.nossr50.commands.levelup.SkillLevelUpCommandBuilder; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.LogUtils; @@ -22,6 +25,7 @@ public class CommandOnLevelUpConfig extends BukkitConfig { public static final String CONDITION_SECTION = "condition"; public static final String ENABLED = "enabled"; public static final String COMMANDS = "commands"; + public static final String POWER_LEVEL_SECTION = "power_level"; public CommandOnLevelUpConfig(@NotNull File dataFolder) { super("levelupcommands.yml", dataFolder); @@ -44,20 +48,26 @@ public class CommandOnLevelUpConfig extends BukkitConfig { continue; } - LevelUpCommand levelUpCommand = buildCommand(commandSection); - if (levelUpCommand == null) { + SkillLevelUpCommand skillLevelUpCommand = buildSkillLevelUpCommand(commandSection); + PowerLevelUpCommand powerLevelUpCommand = buildPowerLevelUpCommand(commandSection); + + if (skillLevelUpCommand == null && powerLevelUpCommand == null) { mcMMO.p.getLogger().severe("Invalid command format for key: " + key); - continue; } else { - mcMMO.p.getLogger().info("Command successfully loaded from config for key: " + key); - mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); + if(skillLevelUpCommand != null) { + mcMMO.p.getLevelUpCommandManager().registerCommand(skillLevelUpCommand); + mcMMO.p.getLogger().info("Skill Level up command successfully loaded from config for key: " + key); + } + if(powerLevelUpCommand != null) { + mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand); + mcMMO.p.getLogger().info("Power Level up command successfully loaded from config for key: " + key); + } } } } - @Nullable - private LevelUpCommand buildCommand(final ConfigurationSection commandSection) { - LevelUpCommand.LevelUpCommandBuilder builder = new LevelUpCommand.LevelUpCommandBuilder(); + private @NotNull SkillLevelUpCommand buildSkillLevelUpCommand(final ConfigurationSection commandSection) { + SkillLevelUpCommandBuilder builder = new SkillLevelUpCommandBuilder(); // check if command is enabled if (!commandSection.getBoolean(ENABLED, true)) { return null; @@ -129,6 +139,60 @@ public class CommandOnLevelUpConfig extends BukkitConfig { return builder.build(); } + private @Nullable PowerLevelUpCommand buildPowerLevelUpCommand(final ConfigurationSection commandSection) { + PowerLevelUpCommandBuilder builder = new PowerLevelUpCommandBuilder(); + // check if command is enabled + if (!commandSection.getBoolean(ENABLED, true)) { + return null; + } + + /* Condition Section */ + ConfigurationSection condition = commandSection.getConfigurationSection(CONDITION_SECTION); + if (condition == null) { + mcMMO.p.getLogger().severe("No condition section found for command named " + commandSection.getName()); + return null; + } + + // No power level condition + if (!condition.contains(POWER_LEVEL_SECTION)) { + return null; + } + + // for now only simple condition is supported + if (!condition.contains(LEVELS_SECTION)) { + mcMMO.p.getLogger().severe("No condition.levels section found for power level command named " + + commandSection.getName()); + return null; + } + + Collection levels = condition.getIntegerList(LEVELS_SECTION); + if (levels.isEmpty()) { + mcMMO.p.getLogger().severe("No valid levels found in condition.levels for power level command named " + + commandSection.getName()); + return null; + } + builder.withLevels(levels); + + // commands + if (commandSection.isString(COMMANDS)) { + String command = commandSection.getString(COMMANDS); + if (command != null) { + builder.command(command); + } + } else { + List commands = commandSection.getStringList(COMMANDS); + if (commands.isEmpty()) { + mcMMO.p.getLogger().severe("No commands defined for power level command named " + + commandSection.getName()); + return null; + } else { + builder.commands(commands); + } + } + + return builder.build(); + } + private Set getSkillsFromFilter(Set skillFilter) { return mcMMO.p.getSkillTools().matchSkills(skillFilter); } diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index e96cd5668..91dfe17e5 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -54,7 +54,6 @@ import com.gmail.nossr50.util.sounds.SoundManager; import com.gmail.nossr50.util.sounds.SoundType; import net.kyori.adventure.identity.Identified; import net.kyori.adventure.identity.Identity; -import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.block.Block; diff --git a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java index e72c82194..dce1bc44b 100644 --- a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java @@ -60,11 +60,18 @@ public class SelfListener implements Listener { } final Set levelsAchieved = new LinkedHashSet<>(); + final Set powerLevelsAchieved = new LinkedHashSet<>(); int startingLevel = event.getSkillLevel() - event.getLevelsGained(); + int startingPowerLevel = mcMMOPlayer.getPowerLevel() - event.getLevelsGained(); for (int i = 0; i < event.getLevelsGained(); i++) { levelsAchieved.add(startingLevel + (i + 1)); } - plugin.getLevelUpCommandManager().apply(mcMMOPlayer, skill, levelsAchieved); + for (int i = 0; i < event.getLevelsGained(); i++) { + powerLevelsAchieved.add(startingPowerLevel + (i + 1)); + } + + plugin.getLevelUpCommandManager().applySkillLevelUp(mcMMOPlayer, skill, levelsAchieved); + plugin.getLevelUpCommandManager().applyPowerLevelUp(mcMMOPlayer, powerLevelsAchieved); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) diff --git a/src/test/java/com/gmail/nossr50/MMOTestEnvironmentBasic.java b/src/test/java/com/gmail/nossr50/MMOTestEnvironmentBasic.java index a260b7ad4..106648c97 100644 --- a/src/test/java/com/gmail/nossr50/MMOTestEnvironmentBasic.java +++ b/src/test/java/com/gmail/nossr50/MMOTestEnvironmentBasic.java @@ -24,17 +24,14 @@ import org.bukkit.World; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.plugin.PluginManager; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.mockito.MockedStatic; import org.mockito.Mockito; -import org.mockito.internal.matchers.Not; import java.util.UUID; -import java.util.function.Function; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -67,15 +64,7 @@ public abstract class MMOTestEnvironmentBasic { private FormulaManager formulaManager; /* Mocks */ - protected Player player; - - protected UUID playerUUID = UUID.randomUUID(); - protected ItemStack itemInMainHand; - protected PlayerInventory playerInventory; - protected PlayerProfile playerProfile; - protected McMMOPlayer mmoPlayer; - protected String playerName = "testPlayer"; protected ChunkManager chunkManager; @@ -163,29 +152,12 @@ public abstract class MMOTestEnvironmentBasic { this.mockedMisc = Mockito.mockStatic(Misc.class); // Mockito.when(Misc.getBlockCenter(any())).thenReturn(new Location(world, 0, 0, 0)); - // setup player and player related mocks after everything else - this.player = mock(Player.class); - when(player.getUniqueId()).thenReturn(playerUUID); - - // wire inventory - this.playerInventory = mock(PlayerInventory.class); - when(player.getInventory()).thenReturn(playerInventory); - - // PlayerProfile and McMMOPlayer are partially mocked - playerProfile = Mockito.spy(new PlayerProfile("testPlayer", player.getUniqueId(), 0)); - when(playerProfile.isLoaded()).thenReturn(true); - mmoPlayer = Mockito.spy(new McMMOPlayer(player, playerProfile)); - // wire user manager this.mockedUserManager = Mockito.mockStatic(UserManager.class); - when(UserManager.getPlayer(player)).thenReturn(mmoPlayer); // Self listener selfListener = Mockito.spy(new SelfListener(mcMMO.p)); - // Player online status - when(player.isOnline()).thenReturn(true); - // Console command sender consoleCommandSender = mock(ConsoleCommandSender.class); when(consoleCommandSender.getName()).thenReturn("CONSOLE"); @@ -279,4 +251,32 @@ public abstract class MMOTestEnvironmentBasic { mockedNotificationManager.close(); } } + + protected McMMOPlayer getMMOPlayer(UUID playerUUID, String playerName, int startingLevel) { + Player player = mock(Player.class); + // Player UUID + when(player.getUniqueId()).thenReturn(playerUUID); + // Player name + when(player.getName()).thenReturn(playerName); + + // Player Inventory + this.playerInventory = mock(PlayerInventory.class); + when(player.getInventory()).thenReturn(playerInventory); + + // Player Profile + PlayerProfile playerProfile = Mockito.spy(new PlayerProfile(playerName, player.getUniqueId(), startingLevel)); + when(playerProfile.isLoaded()).thenReturn(true); + // McMMOPlayer + McMMOPlayer mmoPlayer = Mockito.spy(new McMMOPlayer(player, playerProfile)); + // Wire UserManager + when(UserManager.getPlayer(player)).thenReturn(mmoPlayer); + // Player is online + when(player.isOnline()).thenReturn(true); + + return mmoPlayer; + } + + protected McMMOPlayer getMMOPlayer(UUID playerUUID, String playerName) { + return getMMOPlayer(playerUUID, playerName, 0); + } } diff --git a/src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java b/src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java index 7c47d01e7..59cd22a6e 100644 --- a/src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java +++ b/src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java @@ -9,98 +9,98 @@ import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.EventUtils; import org.bukkit.Bukkit; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.util.UUID; import java.util.function.BiPredicate; +import java.util.function.Predicate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; class LevelUpCommandTest extends MMOTestEnvironmentBasic { - private final PrimarySkillType skill = PrimarySkillType.MINING; - private final PrimarySkillType otherSkill = PrimarySkillType.WOODCUTTING; + private final PrimarySkillType mining = PrimarySkillType.MINING; + private final PrimarySkillType woodcutting = PrimarySkillType.WOODCUTTING; + private McMMOPlayer mmoPlayer; + private final String playerName = "Momshroom"; + + @BeforeEach + void beforeEach() { + mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().clear(); + mcMMO.p.getLevelUpCommandManager().getPowerLevelUpCommands().clear(); + + this.mmoPlayer = getMMOPlayer(UUID.randomUUID(), playerName, 0); + } @Test - void levelUpShouldRunCommandFiveTimes() { + void skillLevelUpShouldRunFiveTimes() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); final String commandStr = "say hello"; - final LevelUpCommand levelUpCommand - = buildLevelUpCommand(commandStr, (s, ignored) -> s == skill); + final SkillLevelUpCommand levelUpCommand + = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining via command - assertEquals(0, mmoPlayer.getSkillLevel(skill)); - int levelsGained = 5; - EventUtils.tryLevelChangeEvent( - player, - skill, - levelsGained, - mmoPlayer.getProfile().getSkillXpLevelRaw(skill), - true, - XPGainReason.COMMAND); + levelPlayerViaXP(mmoPlayer, mining, 5); // THEN the command should be checked for execution - verify(levelUpCommandManager).apply(any(), any(), any()); - verify(levelUpCommand).process(any(), any(), any()); + verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any()); + verify(levelUpCommand, atLeastOnce()).process(any(), any(), any()); + // THEN the command should have executed - verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand, times(5)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5)); } @Test - void levelUpViaXPGainShouldRunCommandFiveTimes() { + void skillLevelUpViaXPGainShouldRunFiveTimes() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); final String commandStr = "say hello"; - final LevelUpCommand levelUpCommand - = buildLevelUpCommand(commandStr, (s, ignored) -> s == skill); + final SkillLevelUpCommand levelUpCommand + = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining via command - assertEquals(0, mmoPlayer.getSkillLevel(skill)); - int levelsGained = 5; - for (int i = 0; i < 5; i++) { - mmoPlayer.applyXpGain(skill, mmoPlayer.getProfile().getXpToLevel(skill), XPGainReason.COMMAND, XPGainSource.COMMAND); - } + levelPlayerViaXP(mmoPlayer, mining, 5); // THEN the command should be checked for execution - verify(levelUpCommandManager, times(levelsGained)).apply(any(), any(), any()); - verify(levelUpCommand, times(levelsGained)).process(any(), any(), any()); + verify(levelUpCommandManager, times(5)).applySkillLevelUp(any(), any(), any()); + verify(levelUpCommand, times(5)).process(any(), any(), any()); // THEN the command should have executed - verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand, times(5)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5)); } @Test - void levelUpViaXPGainShouldRunCommandFiveTimesWithPlaceholders() { + void skillLevelUpViaXPGainShouldRunCommandFiveTimesWithPlaceholders() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().isEmpty(); - String playerName = "Momshroom"; - when (player.getName()).thenReturn(playerName); - assertEquals(player.getName(), playerName); + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assertEquals(mmoPlayer.getPlayer().getName(), playerName); final String commandStr = "say hello %player%, you have reached level %level%"; final String expectedStr1 = "say hello " + playerName + ", you have reached level 1"; final String expectedStr2 = "say hello " + playerName + ", you have reached level 2"; final String expectedStr3 = "say hello " + playerName + ", you have reached level 3"; final String expectedStr4 = "say hello " + playerName + ", you have reached level 4"; final String expectedStr5 = "say hello " + playerName + ", you have reached level 5"; - final LevelUpCommand levelUpCommand - = buildLevelUpCommand(commandStr, (s, ignored) -> s == skill); + final SkillLevelUpCommand levelUpCommand + = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining via command - assertEquals(0, mmoPlayer.getSkillLevel(skill)); + assertEquals(0, mmoPlayer.getSkillLevel(mining)); int levelsGained = 5; for (int i = 0; i < 5; i++) { - mmoPlayer.applyXpGain(skill, mmoPlayer.getProfile().getXpToLevel(skill), XPGainReason.COMMAND, XPGainSource.COMMAND); + mmoPlayer.applyXpGain(mining, mmoPlayer.getProfile().getXpToLevel(mining), XPGainReason.COMMAND, XPGainSource.COMMAND); } // THEN the command should be checked for execution - verify(levelUpCommandManager, times(levelsGained)).apply(any(), any(), any()); + verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any()); verify(levelUpCommand, times(levelsGained)).process(any(), any(), any()); // THEN the command should have executed @@ -116,26 +116,24 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic { } @Test - void levelUpShouldRunCommandFiveTimesWithPlaceholders() { + void skillLevelUpShouldRunCommandFiveTimesWithPlaceholders() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().isEmpty(); - String playerName = "Momshroom"; - when (player.getName()).thenReturn(playerName); - assertEquals(player.getName(), playerName); + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assertEquals(mmoPlayer.getPlayer().getName(), playerName); final String commandStr = "say hello %player%"; final String expectedStr = "say hello " + playerName; - final LevelUpCommand levelUpCommand - = buildLevelUpCommand(commandStr, (s, ignored) -> s == skill); + final SkillLevelUpCommand levelUpCommand + = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); int levelsGained = 5; // WHEN player gains 5 levels in mining - McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(player, skill, levelsGained, XPGainReason.PVE); + McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), mining, levelsGained, XPGainReason.PVE); selfListener.onPlayerLevelUp(event); // THEN the command should be checked for execution - verify(levelUpCommandManager).apply(any(), any(), any()); + verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommand).process(any(), any(), any()); // THEN the command should have executed verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); @@ -144,12 +142,10 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic { } @Test - void levelUpViaAddLevelsShouldRunCommandFiveTimesWithPlaceholdersForLevel() { + void skillLevelUpViaAddLevelsShouldRunCommandFiveTimesWithPlaceholdersForLevel() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().isEmpty(); - String playerName = "Momshroom"; - when (player.getName()).thenReturn(playerName); - assertEquals(player.getName(), playerName); + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assertEquals(mmoPlayer.getPlayer().getName(), playerName); final String commandStr = "say hello %player%, you have reached level %level%"; final String expectedStr1 = "say hello " + playerName + ", you have reached level 1"; @@ -158,23 +154,23 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic { final String expectedStr4 = "say hello " + playerName + ", you have reached level 4"; final String expectedStr5 = "say hello " + playerName + ", you have reached level 5"; - final LevelUpCommand levelUpCommand - = buildLevelUpCommand(commandStr, (s, ignored) -> s == skill); + final SkillLevelUpCommand levelUpCommand + = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining int levelsGained = 5; - mmoPlayer.getProfile().addLevels(skill, levelsGained); + mmoPlayer.getProfile().addLevels(mining, levelsGained); EventUtils.tryLevelChangeEvent( - player, - skill, + mmoPlayer.getPlayer(), + mining, levelsGained, - mmoPlayer.getProfile().getSkillXpLevelRaw(skill), + mmoPlayer.getProfile().getSkillXpLevelRaw(mining), true, XPGainReason.COMMAND); // THEN the command should be checked for execution - verify(levelUpCommandManager).apply(any(), any(), any()); + verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommand).process(any(), any(), any()); // THEN the command should have executed verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); @@ -187,53 +183,120 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic { } @Test - void levelUpShouldRunCommandAtLeastOnce() { + void skillLevelUpShouldRunCommandAtLeastOnce() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); final String commandStr = "say hello"; - final LevelUpCommand levelUpCommand - = buildLevelUpCommand(commandStr, (s, ignored) -> s == skill); + final SkillLevelUpCommand levelUpCommand + = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); int levelsGained = 1; // WHEN player gains 5 levels in mining - McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(player, skill, levelsGained, XPGainReason.PVE); + McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), mining, levelsGained, XPGainReason.PVE); selfListener.onPlayerLevelUp(event); // THEN the command should be checked for execution - verify(levelUpCommandManager).apply(any(), any(), any()); + verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommand).process(any(), any(), any()); // THEN the command should have executed verify(levelUpCommand).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); } @Test - void levelUpShouldNotRunCommand() { + void skillLevelUpShouldNotRunCommand() { // GIVEN level up command for Woodcutting should not execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); final String commandStr = "say hello"; - final LevelUpCommand levelUpCommand - = buildLevelUpCommand(commandStr, (s, ignored) -> s == otherSkill); + final SkillLevelUpCommand levelUpCommand + = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == woodcutting); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); int levelsGained = 5; // WHEN player gains 5 levels in mining - McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(player, skill, levelsGained, XPGainReason.PVE); + McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), mining, levelsGained, XPGainReason.PVE); selfListener.onPlayerLevelUp(event); // THEN the command should be checked for execution - verify(levelUpCommandManager).apply(any(), any(), any()); + verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommand).process(any(), any(), any()); // THEN the command should not be run verify(levelUpCommand, never()).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); } - private LevelUpCommand buildLevelUpCommand(String commandStr, BiPredicate predicate) { - LevelUpCommand.LevelUpCommandBuilder builder = new LevelUpCommand.LevelUpCommandBuilder(); + @Test + public void skillLevelUpShouldAlwaysRunPowerlevelCommand() { + // GIVEN level up command for power level should always execute for any level up + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + final String commandStr = "say hello"; + final PowerLevelUpCommand powerLevelUpCommand + = buildPowerLevelUpCommand(commandStr, (i) -> true); + mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand); + + // WHEN player gains 10 levels + levelPlayerViaXP(mmoPlayer, mining, 10); + + // THEN the command should be checked for execution + verify(levelUpCommandManager, atLeastOnce()).applyPowerLevelUp(any(), any()); + verify(powerLevelUpCommand, atLeastOnce()).process(any(), any()); + // THEN the command should have executed + verify(powerLevelUpCommand, times(10)).executeCommand(any(McMMOPlayer.class), anyInt()); + } + + @Test + public void skillLevelUpShouldRunPowerlevelCommandOnce() { + // GIVEN level up command for power level should always execute for any level up + assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + final String commandStr = "say hello"; + final PowerLevelUpCommand powerLevelUpCommand + = buildPowerLevelUpCommand(commandStr, (i) -> i == 5); + mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand); + + // WHEN player gains 5 levels + levelPlayerViaXP(mmoPlayer, mining, 5); + + // THEN the command should be checked for execution + verify(levelUpCommandManager, atLeastOnce()).applyPowerLevelUp(any(), any()); + verify(powerLevelUpCommand, atLeastOnce()).process(any(), any()); + + // THEN the command should have executed + verify(powerLevelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class), anyInt()); + } + + private SkillLevelUpCommand buildSkillLevelUpCommand(String commandStr, BiPredicate predicate) { + final SkillLevelUpCommandBuilder builder = new SkillLevelUpCommandBuilder(); builder.command(commandStr) .withPredicate(predicate) .withLogInfo(true); return Mockito.spy(builder.build()); } + + private PowerLevelUpCommand buildPowerLevelUpCommand(String commandStr, Predicate predicate) { + final PowerLevelUpCommandBuilder builder = new PowerLevelUpCommandBuilder(); + builder.command(commandStr) + .withPredicate(predicate) + .withLogInfo(true); + return Mockito.spy(builder.build()); + } + + private void levelPlayerViaXP(McMMOPlayer mmoPlayer, PrimarySkillType skill, int levelsGained) { + assertEquals(0, mmoPlayer.getSkillLevel(skill)); + for (int i = 0; i < levelsGained; i++) { + mmoPlayer.applyXpGain(mining, mmoPlayer.getProfile().getXpToLevel(skill), XPGainReason.COMMAND, XPGainSource.COMMAND); + } + assertEquals(levelsGained, mmoPlayer.getSkillLevel(skill)); + } + + private void levelPlayerViaLevelChangeEvent(McMMOPlayer mmoPlayer, PrimarySkillType skill, int levelsGained) { + assertEquals(0, mmoPlayer.getSkillLevel(skill)); + EventUtils.tryLevelChangeEvent( + mmoPlayer.getPlayer(), + skill, + levelsGained, + mmoPlayer.getProfile().getSkillXpLevelRaw(skill), + true, + XPGainReason.COMMAND); + assertEquals(levelsGained, mmoPlayer.getSkillLevel(skill)); + } } \ No newline at end of file