diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommand.java b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommand.java new file mode 100644 index 000000000..1e88f8158 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommand.java @@ -0,0 +1,114 @@ +package com.gmail.nossr50.commands.levelup; + +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.util.LogUtils; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; + +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +public class LevelUpCommand implements CommandsOnLevel { + private final @Nullable List> conditions; + private final @Nullable Predicate powerLevelCondition; + private final boolean logInfo; + private final @NotNull LinkedList commands; + + public LevelUpCommand(@Nullable List> conditions, + @Nullable Predicate powerLevelCondition, + @NotNull LinkedList commands, boolean logInfo) { + this.conditions = conditions; + this.powerLevelCondition = powerLevelCondition; + if (conditions == null && powerLevelCondition == null) + throw new IllegalArgumentException("At least one condition must be set"); + this.commands = commands; + this.logInfo = logInfo; + } + + public void process(@NotNull McMMOPlayer player, @NotNull PrimarySkillType primarySkillType, @NotNull Set levelsGained, + @NotNull Set powerLevelsGained) { + // each predicate has to pass at least once + // we check the predicates against all levels gained to see if they pass at least once + // if all predicates pass at least once, we execute the command + boolean allConditionsPass = (conditions == null) || conditions.stream().allMatch(predicate -> levelsGained.stream().anyMatch(level -> predicate.test(primarySkillType, level))); + // we also check the power level predicate to see if it passes at least once, if this predicate is null, we mark it as passed + boolean powerLevelConditionPass = (powerLevelCondition == null) || powerLevelsGained.stream().anyMatch(powerLevelCondition); + if (allConditionsPass && powerLevelConditionPass) { + executeCommand(player); + } + } + + @VisibleForTesting + void executeCommand(@NotNull McMMOPlayer player) { + LogUtils.debug(mcMMO.p.getLogger(), "Executing level up commands: " + commands); + for (String command : commands) { + LogUtils.debug(mcMMO.p.getLogger(), "Executing command: " + command); + String injectedCommand = injectedCommand(command, player); + if (!injectedCommand.equalsIgnoreCase(command)) { + LogUtils.debug(mcMMO.p.getLogger(), ("Command has been injected with new values: " + injectedCommand)); + } + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), injectedCommand); + } + } + + @VisibleForTesting + String injectedCommand(String command, McMMOPlayer player) { + // TODO: unit tests + StringBuilder commandBuilder = new StringBuilder(command); + + // Replace %player% with player name + replaceAll(commandBuilder, "{@player}", player.getPlayer().getName()); + + // Replace each skill level + for (PrimarySkillType primarySkillType : PrimarySkillType.values()) { + if (primarySkillType == PrimarySkillType.SMELTING || primarySkillType == PrimarySkillType.SALVAGE) { + continue; + } + replaceAll(commandBuilder, "{@" + primarySkillType.name().toLowerCase() + "_level}", + String.valueOf(player.getSkillLevel(primarySkillType))); + } + + // Replace power level + replaceAll(commandBuilder, "{@power_level}", String.valueOf(player.getPowerLevel())); + + return commandBuilder.toString(); + } + + private void replaceAll(StringBuilder builder, String from, String to) { + int index = builder.indexOf(from); + while (index != -1) { + builder.replace(index, index + from.length(), to); + index = builder.indexOf(from, index + to.length()); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LevelUpCommand that = (LevelUpCommand) o; + return logInfo == that.logInfo && Objects.equals(conditions, that.conditions) && Objects.equals(commands, that.commands); + } + + @Override + public int hashCode() { + return Objects.hash(conditions, logInfo, commands); + } + + @Override + public String toString() { + return "SkillLevelUpCommand{" + + "conditions=" + conditions + + ", logInfo=" + logInfo + + ", commands=" + commands + + '}'; + } +} diff --git a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandBuilder.java b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandBuilder.java new file mode 100644 index 000000000..d3366e2a8 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandBuilder.java @@ -0,0 +1,79 @@ +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.List; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import static java.util.Objects.requireNonNull; + +public class LevelUpCommandBuilder { + private LinkedList commands = null; + private List> conditions = null; + private Predicate powerLevelCondition = null; + private boolean logInfo; + + public LevelUpCommandBuilder() { + this.logInfo = false; + } + + public LevelUpCommandBuilder withPredicate(BiPredicate condition) { + if (this.conditions == null) { + this.conditions = new LinkedList<>(); + } + + conditions.add(condition); + return this; + } + + public LevelUpCommandBuilder withPowerLevelCondition(Predicate powerLevelCondition) { + if (this.powerLevelCondition != null) { + throw new IllegalStateException("power level condition already set"); + } + + this.powerLevelCondition = powerLevelCondition; + return this; + } + + public LevelUpCommandBuilder withConditions( + @NotNull Collection> conditions) { + if (this.conditions == null) { + this.conditions = new LinkedList<>(); + } else { + throw new IllegalStateException("conditions already set"); + } + + this.conditions.addAll(conditions); + 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 LevelUpCommand build() { + if (conditions == null && powerLevelCondition == null) { + throw new IllegalStateException("no conditions found for level up command"); + } + requireNonNull(commands, "no commands found for level up command"); + + return new LevelUpCommand(conditions, powerLevelCondition, 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 d5b714abb..056ec6771 100644 --- a/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandManager.java +++ b/src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommandManager.java @@ -16,26 +16,18 @@ import static java.util.Objects.requireNonNull; * Manages commands to be executed on level up */ public class LevelUpCommandManager { - private final @NotNull Set skillLevelCommands; - private final @NotNull Set powerLevelUpCommands; + private final @NotNull Set levelUpCommands; private final @NotNull mcMMO plugin; public LevelUpCommandManager(@NotNull mcMMO plugin) { this.plugin = requireNonNull(plugin, "plugin cannot be null"); - this.skillLevelCommands = new HashSet<>(); - this.powerLevelUpCommands = new HashSet<>(); + this.levelUpCommands = new HashSet<>(); } - public void registerCommand(@NotNull SkillLevelUpCommand skillLevelUpCommand) { - requireNonNull(skillLevelUpCommand, "skillLevelUpCommand cannot be null"); - skillLevelCommands.add(skillLevelUpCommand); - LogUtils.debug(mcMMO.p.getLogger(), "Registered level up command - SkillLevelUpCommand: " + skillLevelUpCommand); - } - - public void registerCommand(@NotNull PowerLevelUpCommand powerLevelUpCommand) { - requireNonNull(powerLevelUpCommand, "powerLevelUpCommand cannot be null"); - powerLevelUpCommands.add(powerLevelUpCommand); - LogUtils.debug(mcMMO.p.getLogger(), "Registered level up command - PowerLevelUpCommand: " + powerLevelUpCommand); + public void registerCommand(@NotNull LevelUpCommand levelUpCommand) { + requireNonNull(levelUpCommand, "skillLevelUpCommand cannot be null"); + levelUpCommands.add(levelUpCommand); + LogUtils.debug(mcMMO.p.getLogger(), "Registered level up command - SkillLevelUpCommand: " + levelUpCommand); } /** @@ -45,32 +37,19 @@ public class LevelUpCommandManager { * @param primarySkillType the skill type * @param levelsGained the levels gained */ - public void applySkillLevelUp(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType, Set levelsGained) { + public void applySkillLevelUp(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType, + Set levelsGained, Set powerLevelsGained) { if (!mmoPlayer.getPlayer().isOnline()) { return; } - for (SkillLevelUpCommand command : skillLevelCommands) { - command.process(mmoPlayer, primarySkillType, levelsGained); + for (LevelUpCommand command : levelUpCommands) { + command.process(mmoPlayer, primarySkillType, levelsGained, powerLevelsGained); } } - 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; + public @NotNull Set getLevelUpCommands() { + return levelUpCommands; } /** @@ -78,8 +57,7 @@ public class LevelUpCommandManager { */ public void clear() { mcMMO.p.getLogger().info("Clearing registered commands on level up"); - skillLevelCommands.clear(); - powerLevelUpCommands.clear(); + levelUpCommands.clear(); } @Override @@ -87,19 +65,18 @@ public class LevelUpCommandManager { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LevelUpCommandManager that = (LevelUpCommandManager) o; - return Objects.equals(skillLevelCommands, that.skillLevelCommands) && Objects.equals(powerLevelUpCommands, that.powerLevelUpCommands) && Objects.equals(plugin, that.plugin); + return Objects.equals(levelUpCommands, that.levelUpCommands) && Objects.equals(plugin, that.plugin); } @Override public int hashCode() { - return Objects.hash(skillLevelCommands, powerLevelUpCommands, plugin); + return Objects.hash(levelUpCommands, plugin); } @Override public String toString() { return "LevelUpCommandManager{" + - "skillLevelCommands=" + skillLevelCommands + - ", powerLevelUpCommands=" + powerLevelUpCommands + + "levelUpCommands=" + levelUpCommands + ", 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 deleted file mode 100644 index 5d97a5d3c..000000000 --- a/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommand.java +++ /dev/null @@ -1,96 +0,0 @@ -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) { - LogUtils.debug(mcMMO.p.getLogger(), "Executing commands for level up: " + commands); - for (String command : commands) { - LogUtils.debug(mcMMO.p.getLogger(), "Executing command: " + command); - String injectedCommand = injectedCommand(command, player, level); - if (!injectedCommand.equalsIgnoreCase(command)) { - LogUtils.debug(mcMMO.p.getLogger(), ("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, "%power_level%", "power level"); - 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 deleted file mode 100644 index a80c0251e..000000000 --- a/src/main/java/com/gmail/nossr50/commands/levelup/PowerLevelUpCommandBuilder.java +++ /dev/null @@ -1,59 +0,0 @@ -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/SkillLevelUpCommand.java b/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommand.java deleted file mode 100644 index 246bb0d21..000000000 --- a/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommand.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.gmail.nossr50.commands.levelup; - -import com.gmail.nossr50.datatypes.player.McMMOPlayer; -import com.gmail.nossr50.datatypes.skills.PrimarySkillType; -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.BiPredicate; - -public class SkillLevelUpCommand implements CommandsOnLevel { - private final BiPredicate predicate; - private final boolean logInfo; - private final @NotNull LinkedList commands; - - 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 SkillLevelUpCommand(@NotNull BiPredicate predicate, @NotNull LinkedList commands, boolean logInfo) { - this.predicate = predicate; - this.commands = commands; - this.logInfo = logInfo; - } - - public void process(McMMOPlayer player, PrimarySkillType primarySkillType, Set levelsGained) { - for (int i : levelsGained) { - if (predicate.test(primarySkillType, 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, primarySkillType, i); - } - } - } - - public void executeCommand(McMMOPlayer player, PrimarySkillType primarySkillType, int level) { - LogUtils.debug(mcMMO.p.getLogger(), "Executing commands for level up: " + commands); - for (String command : commands) { - LogUtils.debug(mcMMO.p.getLogger(), "Executing command: " + command); - String injectedCommand = injectedCommand(command, player, primarySkillType, level); - if (!injectedCommand.equalsIgnoreCase(command)) { - LogUtils.debug(mcMMO.p.getLogger(), ("Command has been injected with new values: " + injectedCommand)); - } - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), injectedCommand); - } - } - - private String injectedCommand(String command, McMMOPlayer player, PrimarySkillType primarySkillType, 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%", primarySkillType.getName()); - 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; - SkillLevelUpCommand that = (SkillLevelUpCommand) 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 "LevelUpCommandImpl{" + - "predicate=" + predicate + - ", logInfo=" + logInfo + - ", commandStr='" + 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 deleted file mode 100644 index 98b731d96..000000000 --- a/src/main/java/com/gmail/nossr50/commands/levelup/SkillLevelUpCommandBuilder.java +++ /dev/null @@ -1,82 +0,0 @@ -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 8ace6035e..4fbc3a8b9 100644 --- a/src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java +++ b/src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java @@ -1,9 +1,7 @@ package com.gmail.nossr50.config; -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.commands.levelup.LevelUpCommand; +import com.gmail.nossr50.commands.levelup.LevelUpCommandBuilder; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.LogUtils; @@ -48,153 +46,89 @@ public class CommandOnLevelUpConfig extends BukkitConfig { continue; } - SkillLevelUpCommand skillLevelUpCommand = buildSkillLevelUpCommand(commandSection); - PowerLevelUpCommand powerLevelUpCommand = buildPowerLevelUpCommand(commandSection); + LevelUpCommand levelUpCommand = buildSkillLevelUpCommand(commandSection); - if (skillLevelUpCommand == null && powerLevelUpCommand == null) { + if (levelUpCommand == null) { mcMMO.p.getLogger().severe("Invalid command format for key: " + key); } else { - 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); - } + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); + mcMMO.p.getLogger().info("Level up command successfully loaded from config for key: " + key); } } } - private @Nullable SkillLevelUpCommand buildSkillLevelUpCommand(final ConfigurationSection commandSection) { - SkillLevelUpCommandBuilder builder = new SkillLevelUpCommandBuilder(); - // 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; - } - - // Skill Filter - // check if skills is string or configuration section - if (condition.contains(SKILLS_SECTION)) { - if (condition.isString(SKILLS_SECTION)) { - String skillName = condition.getString(SKILLS_SECTION); - if (skillName != null) { - PrimarySkillType primarySkillType = mcMMO.p.getSkillTools().matchSkill(skillName); - if (primarySkillType != null) { - builder.withSkillFilter(getSkillsFromFilter(new HashSet<>(Set.of(skillName)))); - } - } - } else { - ConfigurationSection skillsSection = condition.getConfigurationSection(SKILLS_SECTION); - if (skillsSection != null) { - Set skillNames = skillsSection.getKeys(false); - Set skillsFromFilter = getSkillsFromFilter(skillNames); - if (skillsFromFilter.isEmpty()) { - LogUtils.debug(mcMMO.p.getLogger(), "No valid skills found for command named " - + commandSection.getName() + "for condition section named " + skillsSection.getName()); - } else { - builder.withSkillFilter(skillsFromFilter); - } - } - } - } - - // for now only simple condition is supported - if (!condition.contains(LEVELS_SECTION)) { - mcMMO.p.getLogger().severe("No condition.levels section found for 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 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 command named " - + commandSection.getName()); - return null; - } else { - builder.commands(commands); - } - } - - 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); + private @Nullable LevelUpCommand buildSkillLevelUpCommand(final ConfigurationSection commandSection) { + // TODO: Rework + return null; +// LevelUpCommandBuilder builder = new LevelUpCommandBuilder(); +// // 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; +// } +// +// // Skill Filter +// // check if skills is string or configuration section +// if (condition.contains(SKILLS_SECTION)) { +// if (condition.isString(SKILLS_SECTION)) { +// String skillName = condition.getString(SKILLS_SECTION); +// if (skillName != null) { +// PrimarySkillType primarySkillType = mcMMO.p.getSkillTools().matchSkill(skillName); +// if (primarySkillType != null) { +// builder.withSkillFilter(getSkillsFromFilter(new HashSet<>(Set.of(skillName)))); +// } +// } +// } else { +// ConfigurationSection skillsSection = condition.getConfigurationSection(SKILLS_SECTION); +// if (skillsSection != null) { +// Set skillNames = skillsSection.getKeys(false); +// Set skillsFromFilter = getSkillsFromFilter(skillNames); +// if (skillsFromFilter.isEmpty()) { +// LogUtils.debug(mcMMO.p.getLogger(), "No valid skills found for command named " +// + commandSection.getName() + "for condition section named " + skillsSection.getName()); +// } else { +// builder.withSkillFilter(skillsFromFilter); +// } +// } +// } +// } +// +// // for now only simple condition is supported +// if (!condition.contains(LEVELS_SECTION)) { +// mcMMO.p.getLogger().severe("No condition.levels section found for 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 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 command named " +// + commandSection.getName()); +// return null; +// } else { +// builder.commands(commands); +// } +// } +// +// return builder.build(); } } diff --git a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java index dce1bc44b..7c7f98de3 100644 --- a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java @@ -70,8 +70,7 @@ public class SelfListener implements Listener { powerLevelsAchieved.add(startingPowerLevel + (i + 1)); } - plugin.getLevelUpCommandManager().applySkillLevelUp(mcMMOPlayer, skill, levelsAchieved); - plugin.getLevelUpCommandManager().applyPowerLevelUp(mcMMOPlayer, powerLevelsAchieved); + plugin.getLevelUpCommandManager().applySkillLevelUp(mcMMOPlayer, skill, levelsAchieved, powerLevelsAchieved); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) diff --git a/src/main/resources/levelupcommands.yml b/src/main/resources/levelupcommands.yml index eeb390013..3f8481258 100644 --- a/src/main/resources/levelupcommands.yml +++ b/src/main/resources/levelupcommands.yml @@ -1,32 +1,23 @@ level_up_commands: - unique_id_here: + woodcutting_and_swords_command: enabled: true condition: - skills: - - 'Swords' - - 'Axes' - levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + swords: + levels: [10, 100] + woodcutting: + levels: [10, 100] commands: - - "say %player% reached level %level%!" + - "say {@player} reached level {@swords_level} in swords, and {@woodcutting_level} in woodcutting!" - "say Isn't that nice?" run_command_as: 'CONSOLE' log_level: 'INFO' - other_unique_id_here: - enabled: true - condition: - levels: [1, 2, 3, 4, 5] - commands: - - "say this command should execute for all skills, %player%!" - - "say Isn't that fun?" - run_command_as: 'CONSOLE' - log_level: 'DEBUG' power_level_milestones: enabled: true condition: - power_level: true - levels: [ 10, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 10000, 20000 ] + power_level: + levels: [ 1000, 2000, 3000, 4000, 5000 ] commands: - - "say %player% has reached a power level milestone!" - - "say %player% is now at power level %level%!" + - "say {@player} has reached a power level milestone!" + - "say {@player} is now at power level {@power_level}!" run_command_as: 'CONSOLE' log_level: 'DEBUG' 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 59cd22a6e..6499a80ca 100644 --- a/src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java +++ b/src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java @@ -9,28 +9,32 @@ import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.EventUtils; import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.util.List; import java.util.UUID; import java.util.function.BiPredicate; import java.util.function.Predicate; +import static com.gmail.nossr50.datatypes.skills.PrimarySkillType.MINING; +import static com.gmail.nossr50.datatypes.skills.PrimarySkillType.WOODCUTTING; +import static java.util.Objects.requireNonNull; 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 mining = PrimarySkillType.MINING; - private final PrimarySkillType woodcutting = PrimarySkillType.WOODCUTTING; + private static final BiPredicate ALWAYS_TRUE = (skill, level) -> true; private McMMOPlayer mmoPlayer; private final String playerName = "Momshroom"; @BeforeEach void beforeEach() { - mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().clear(); - mcMMO.p.getLevelUpCommandManager().getPowerLevelUpCommands().clear(); + mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().clear(); this.mmoPlayer = getMMOPlayer(UUID.randomUUID(), playerName, 0); } @@ -38,73 +42,96 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic { @Test void skillLevelUpShouldRunFiveTimes() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); final String commandStr = "say hello"; - final SkillLevelUpCommand levelUpCommand - = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, + (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining via command - levelPlayerViaXP(mmoPlayer, mining, 5); + levelPlayerViaXP(mmoPlayer, MINING, 5); // THEN the command should be checked for execution - verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any()); - verify(levelUpCommand, atLeastOnce()).process(any(), any(), any()); + verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommand, atLeastOnce()).process(any(), any(), any(), any()); // THEN the command should have executed - verify(levelUpCommand, times(5)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand, times(5)).executeCommand(any(McMMOPlayer.class)); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5)); } + @Test + void dualRequirementsShouldRunOnce() { + // GIVEN + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); + final String commandStr = "say hello"; + BiPredicate predicate = (skill, skillLevel) -> skill == MINING && skillLevel == 3; + BiPredicate predicate2 = (skill, skillLevel) -> skill == WOODCUTTING && skillLevel == 3; + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, List.of(predicate, predicate2)); + + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); + + // WHEN player gains 5 levels in mining and woodcutting via command + levelPlayerViaXP(mmoPlayer, MINING, 5); + levelPlayerViaXP(mmoPlayer, WOODCUTTING, 5); + + // THEN the command should be checked for execution + verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommand, times(10)).process(any(), any(), any(), any()); + + // THEN the command should have executed + verify(levelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class)); + mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(1)); + } + @Test void skillLevelUpViaXPGainShouldRunFiveTimes() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); final String commandStr = "say hello"; - final SkillLevelUpCommand levelUpCommand - = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, + (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining via command - levelPlayerViaXP(mmoPlayer, mining, 5); + levelPlayerViaXP(mmoPlayer, MINING, 5); // THEN the command should be checked for execution - verify(levelUpCommandManager, times(5)).applySkillLevelUp(any(), any(), any()); - verify(levelUpCommand, times(5)).process(any(), any(), any()); + verify(levelUpCommandManager, times(5)).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommand, times(5)).process(any(), any(), any(), any()); // THEN the command should have executed - verify(levelUpCommand, times(5)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand, times(5)).executeCommand(any(McMMOPlayer.class)); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5)); } @Test void skillLevelUpViaXPGainShouldRunCommandFiveTimesWithPlaceholders() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); assertEquals(mmoPlayer.getPlayer().getName(), playerName); - final String commandStr = "say hello %player%, you have reached level %level%"; + final String commandStr = "say hello {@player}, you have reached level {@mining_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 SkillLevelUpCommand levelUpCommand - = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, + (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining via command - assertEquals(0, mmoPlayer.getSkillLevel(mining)); + assertEquals(0, mmoPlayer.getSkillLevel(MINING)); int levelsGained = 5; - for (int i = 0; i < 5; i++) { - mmoPlayer.applyXpGain(mining, mmoPlayer.getProfile().getXpToLevel(mining), XPGainReason.COMMAND, XPGainSource.COMMAND); - } + levelPlayerViaXP(mmoPlayer, MINING, levelsGained); // THEN the command should be checked for execution - verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any()); - verify(levelUpCommand, times(levelsGained)).process(any(), any(), any()); + verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommand, times(levelsGained)).process(any(), any(), any(), any()); // THEN the command should have executed - verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class)); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5)); // AND THEN the message for each level up should have happened at least once // verify that Bukkit.dispatchCommand got executed at least 5 times with the correct injectedCommand @@ -116,64 +143,110 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic { } @Test - void skillLevelUpShouldRunCommandFiveTimesWithPlaceholders() { + void skillLevelUpShouldRunCommandThreeTimesWithPlaceholders() { + /* + This test executes a player leveling up 5 times. + With level 3 separate registered level up commands. + Each registered command runs only once. + */ // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); assertEquals(mmoPlayer.getPlayer().getName(), playerName); - final String commandStr = "say hello %player%"; + final String commandStr = "say hello {@player}"; final String expectedStr = "say hello " + playerName; - final SkillLevelUpCommand levelUpCommand - = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); - mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); + final LevelUpCommand levelUpCommandOne = buildLevelUpCommand(commandStr, (skill, level) -> skill == MINING && level == 1); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandOne); + final LevelUpCommand levelUpCommandTwo = buildLevelUpCommand(commandStr, (skill, level) -> skill == MINING && level == 2); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandTwo); + final LevelUpCommand levelUpCommandThree = buildLevelUpCommand(commandStr, (skill, level) -> skill == MINING && level == 3); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandThree); int levelsGained = 5; // WHEN player gains 5 levels in mining - McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), mining, levelsGained, XPGainReason.PVE); - selfListener.onPlayerLevelUp(event); + levelPlayerViaXP(mmoPlayer, MINING, levelsGained); // THEN the command should be checked for execution - verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); - verify(levelUpCommand).process(any(), any(), any()); + verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommandOne, times(levelsGained)).process(any(), any(), any(), any()); + verify(levelUpCommandTwo, times(levelsGained)).process(any(), any(), any(), any()); + verify(levelUpCommandThree, times(levelsGained)).process(any(), any(), any(), any()); // THEN the command should have executed - verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); - // verify that Bukkit.dispatchCommand got executed at least 5 times with the correct injectedCommand - mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr)), atLeast(5)); + verify(levelUpCommandOne, times(1)).executeCommand(any(McMMOPlayer.class)); + verify(levelUpCommandTwo, times(1)).executeCommand(any(McMMOPlayer.class)); + verify(levelUpCommandThree, times(1)).executeCommand(any(McMMOPlayer.class)); + // verify that Bukkit.dispatchCommand got executed at least 20 times with the correct injectedCommand + mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr)), atLeast(3)); } @Test - void skillLevelUpViaAddLevelsShouldRunCommandFiveTimesWithPlaceholdersForLevel() { + void skillLevelUpShouldRunCommandFourTimesWithPlaceholders() { + /* + This test executes a player leveling up 5 times. + With level 3 separate registered level up commands. + One command runs twice, the others run once. + */ // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); assertEquals(mmoPlayer.getPlayer().getName(), playerName); - final String commandStr = "say hello %player%, you have reached level %level%"; + final String commandStr = "say hello {@player}"; + final String expectedStr = "say hello " + playerName; + final LevelUpCommand levelUpCommandOne = buildLevelUpCommand(commandStr, (skill, level) -> skill == MINING && (level == 1 || level == 4)); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandOne); + final LevelUpCommand levelUpCommandTwo = buildLevelUpCommand(commandStr, (skill, level) -> skill == MINING && level == 2); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandTwo); + final LevelUpCommand levelUpCommandThree = buildLevelUpCommand(commandStr, (skill, level) -> skill == MINING && level == 3); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandThree); + int levelsGained = 5; + + // WHEN player gains 5 levels in mining + levelPlayerViaXP(mmoPlayer, MINING, levelsGained); + + // THEN the command should be checked for execution + verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommandOne, times(levelsGained)).process(any(), any(), any(), any()); + verify(levelUpCommandTwo, times(levelsGained)).process(any(), any(), any(), any()); + verify(levelUpCommandThree, times(levelsGained)).process(any(), any(), any(), any()); + // THEN the command should have executed + verify(levelUpCommandOne, times(2)).executeCommand(any(McMMOPlayer.class)); + verify(levelUpCommandTwo, times(1)).executeCommand(any(McMMOPlayer.class)); + verify(levelUpCommandThree, times(1)).executeCommand(any(McMMOPlayer.class)); + // verify that Bukkit.dispatchCommand got executed at least 20 times with the correct injectedCommand + mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr)), atLeast(3)); + } + + @Test + void addLevelsShouldRunCommandFiveTimesWithPlaceholdersForLevel() { + // GIVEN level up command for Mining should always execute for Mining level up + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); + assertEquals(mmoPlayer.getPlayer().getName(), playerName); + + final String commandStr = "say hello {@player}, you have reached level {@mining_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 SkillLevelUpCommand levelUpCommand - = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); - mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, (skill, ignored) -> skill == MINING); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 5 levels in mining int levelsGained = 5; - mmoPlayer.getProfile().addLevels(mining, levelsGained); + mmoPlayer.getProfile().addLevels(MINING, levelsGained); EventUtils.tryLevelChangeEvent( mmoPlayer.getPlayer(), - mining, + MINING, levelsGained, - mmoPlayer.getProfile().getSkillXpLevelRaw(mining), + mmoPlayer.getProfile().getSkillXpLevelRaw(MINING), true, XPGainReason.COMMAND); // THEN the command should be checked for execution - verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); - verify(levelUpCommand).process(any(), any(), any()); + verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommand).process(any(), any(), any(), any()); // THEN the command should have executed - verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class)); // verify that Bukkit.dispatchCommand got executed at least 5 times with the correct injectedCommand mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr1))); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr2))); @@ -185,118 +258,128 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic { @Test void skillLevelUpShouldRunCommandAtLeastOnce() { // GIVEN level up command for Mining should always execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); final String commandStr = "say hello"; - final SkillLevelUpCommand levelUpCommand - = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, (skill, ignored) -> skill == MINING); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); int levelsGained = 1; // WHEN player gains 5 levels in mining - McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), mining, 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).applySkillLevelUp(any(), any(), any()); - verify(levelUpCommand).process(any(), any(), any()); + verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommand).process(any(), any(), any(), any()); // THEN the command should have executed - verify(levelUpCommand).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand).executeCommand(any(McMMOPlayer.class)); } @Test void skillLevelUpShouldNotRunCommand() { // GIVEN level up command for Woodcutting should not execute for Mining level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); final String commandStr = "say hello"; - final SkillLevelUpCommand levelUpCommand - = buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == woodcutting); + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, (skill, ignored) -> skill == WOODCUTTING); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); int levelsGained = 5; // WHEN player gains 5 levels in mining - McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), mining, 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).applySkillLevelUp(any(), any(), any()); - verify(levelUpCommand).process(any(), any(), any()); + verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any(), any()); + verify(levelUpCommand).process(any(), any(), any(), any()); // THEN the command should not be run - verify(levelUpCommand, never()).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); + verify(levelUpCommand, never()).executeCommand(any(McMMOPlayer.class)); } @Test - public void skillLevelUpShouldAlwaysRunPowerlevelCommand() { - // GIVEN level up command for power level should always execute for any level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + public void levelUpShouldAlwaysRunCommand() { + // GIVEN level up command should always execute for any level up + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); final String commandStr = "say hello"; - final PowerLevelUpCommand powerLevelUpCommand - = buildPowerLevelUpCommand(commandStr, (i) -> true); - mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand); + final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, ALWAYS_TRUE); + mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); // WHEN player gains 10 levels - levelPlayerViaXP(mmoPlayer, mining, 10); + levelPlayerViaXP(mmoPlayer, MINING, 10); // THEN the command should be checked for execution - verify(levelUpCommandManager, atLeastOnce()).applyPowerLevelUp(any(), any()); - verify(powerLevelUpCommand, atLeastOnce()).process(any(), any()); + verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), eq(MINING), any(), any()); + verify(levelUpCommand, atLeastOnce()).process(any(), any(), any(), any()); // THEN the command should have executed - verify(powerLevelUpCommand, times(10)).executeCommand(any(McMMOPlayer.class), anyInt()); + verify(levelUpCommand, times(10)).executeCommand(any(McMMOPlayer.class)); } @Test public void skillLevelUpShouldRunPowerlevelCommandOnce() { // GIVEN level up command for power level should always execute for any level up - assert mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().isEmpty(); + assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty(); final String commandStr = "say hello"; - final PowerLevelUpCommand powerLevelUpCommand - = buildPowerLevelUpCommand(commandStr, (i) -> i == 5); + final LevelUpCommand powerLevelUpCommand = buildLevelUpCommand(commandStr, + (ignoredA, ignoredB) -> true, (powerlevel) -> powerlevel == 3); mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand); // WHEN player gains 5 levels - levelPlayerViaXP(mmoPlayer, mining, 5); + levelPlayerViaXP(mmoPlayer, MINING, 5); // THEN the command should be checked for execution - verify(levelUpCommandManager, atLeastOnce()).applyPowerLevelUp(any(), any()); - verify(powerLevelUpCommand, atLeastOnce()).process(any(), any()); + verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any(), any()); + verify(powerLevelUpCommand, atLeastOnce()).process(any(), any(), any(), any()); // THEN the command should have executed - verify(powerLevelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class), anyInt()); + verify(powerLevelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class)); } - private SkillLevelUpCommand buildSkillLevelUpCommand(String commandStr, BiPredicate predicate) { - final SkillLevelUpCommandBuilder builder = new SkillLevelUpCommandBuilder(); + private LevelUpCommand buildLevelUpCommand(@NotNull String commandStr, + @NotNull List> conditions, + @Nullable Predicate powerLevelCondition) { + requireNonNull(commandStr, "commandStr cannot be null"); + requireNonNull(conditions, "conditions cannot be null"); + final var builder = new LevelUpCommandBuilder(); + if (powerLevelCondition != null) { + builder.withPowerLevelCondition(powerLevelCondition); + } + builder.command(commandStr) + .withConditions(conditions) + .withLogInfo(true); + return Mockito.spy(builder.build()); + } + + private LevelUpCommand buildLevelUpCommand(@NotNull String commandStr, + @NotNull List> conditions) { + return buildLevelUpCommand(commandStr, conditions, null); + } + + private LevelUpCommand buildLevelUpCommand(@NotNull String commandStr, + @NotNull BiPredicate predicate, + @Nullable Predicate powerLevelCondition) { + requireNonNull(commandStr, "commandStr cannot be null"); + requireNonNull(predicate, "predicate cannot be null"); + final var builder = new LevelUpCommandBuilder(); + if (powerLevelCondition != null) { + builder.withPowerLevelCondition(powerLevelCondition); + } 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 LevelUpCommand buildLevelUpCommand(@NotNull String commandStr, + @NotNull BiPredicate predicate) { + return buildLevelUpCommand(commandStr, predicate, null); } - private void levelPlayerViaXP(McMMOPlayer mmoPlayer, PrimarySkillType skill, int levelsGained) { + private void levelPlayerViaXP(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType skill, int levelsGained) { + System.out.println("Leveling " + mmoPlayer.getPlayer().getName() + " up " + levelsGained + " levels in " + skill.getName()); assertEquals(0, mmoPlayer.getSkillLevel(skill)); for (int i = 0; i < levelsGained; i++) { - mmoPlayer.applyXpGain(mining, mmoPlayer.getProfile().getXpToLevel(skill), XPGainReason.COMMAND, XPGainSource.COMMAND); + mmoPlayer.applyXpGain(skill, 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