(WIP) reworking level up commands to have multiple requirements

This commit is contained in:
nossr50 2024-02-18 15:45:51 -08:00
parent 0650731723
commit 9b5be855fd
11 changed files with 489 additions and 645 deletions

View File

@ -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<BiPredicate<PrimarySkillType, Integer>> conditions;
private final @Nullable Predicate<Integer> powerLevelCondition;
private final boolean logInfo;
private final @NotNull LinkedList<String> commands;
public LevelUpCommand(@Nullable List<BiPredicate<PrimarySkillType, Integer>> conditions,
@Nullable Predicate<Integer> powerLevelCondition,
@NotNull LinkedList<String> 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<Integer> levelsGained,
@NotNull Set<Integer> 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 +
'}';
}
}

View File

@ -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<String> commands = null;
private List<BiPredicate<PrimarySkillType, Integer>> conditions = null;
private Predicate<Integer> powerLevelCondition = null;
private boolean logInfo;
public LevelUpCommandBuilder() {
this.logInfo = false;
}
public LevelUpCommandBuilder withPredicate(BiPredicate<PrimarySkillType, Integer> condition) {
if (this.conditions == null) {
this.conditions = new LinkedList<>();
}
conditions.add(condition);
return this;
}
public LevelUpCommandBuilder withPowerLevelCondition(Predicate<Integer> powerLevelCondition) {
if (this.powerLevelCondition != null) {
throw new IllegalStateException("power level condition already set");
}
this.powerLevelCondition = powerLevelCondition;
return this;
}
public LevelUpCommandBuilder withConditions(
@NotNull Collection<BiPredicate<PrimarySkillType, Integer>> 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<String> 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);
}
}

View File

@ -16,26 +16,18 @@ import static java.util.Objects.requireNonNull;
* Manages commands to be executed on level up * Manages commands to be executed on level up
*/ */
public class LevelUpCommandManager { public class LevelUpCommandManager {
private final @NotNull Set<SkillLevelUpCommand> skillLevelCommands; private final @NotNull Set<LevelUpCommand> levelUpCommands;
private final @NotNull Set<PowerLevelUpCommand> powerLevelUpCommands;
private final @NotNull mcMMO plugin; private final @NotNull mcMMO plugin;
public LevelUpCommandManager(@NotNull mcMMO plugin) { public LevelUpCommandManager(@NotNull mcMMO plugin) {
this.plugin = requireNonNull(plugin, "plugin cannot be null"); this.plugin = requireNonNull(plugin, "plugin cannot be null");
this.skillLevelCommands = new HashSet<>(); this.levelUpCommands = new HashSet<>();
this.powerLevelUpCommands = new HashSet<>();
} }
public void registerCommand(@NotNull SkillLevelUpCommand skillLevelUpCommand) { public void registerCommand(@NotNull LevelUpCommand levelUpCommand) {
requireNonNull(skillLevelUpCommand, "skillLevelUpCommand cannot be null"); requireNonNull(levelUpCommand, "skillLevelUpCommand cannot be null");
skillLevelCommands.add(skillLevelUpCommand); levelUpCommands.add(levelUpCommand);
LogUtils.debug(mcMMO.p.getLogger(), "Registered level up command - SkillLevelUpCommand: " + skillLevelUpCommand); LogUtils.debug(mcMMO.p.getLogger(), "Registered level up command - SkillLevelUpCommand: " + levelUpCommand);
}
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);
} }
/** /**
@ -45,32 +37,19 @@ public class LevelUpCommandManager {
* @param primarySkillType the skill type * @param primarySkillType the skill type
* @param levelsGained the levels gained * @param levelsGained the levels gained
*/ */
public void applySkillLevelUp(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType, Set<Integer> levelsGained) { public void applySkillLevelUp(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType,
Set<Integer> levelsGained, Set<Integer> powerLevelsGained) {
if (!mmoPlayer.getPlayer().isOnline()) { if (!mmoPlayer.getPlayer().isOnline()) {
return; return;
} }
for (SkillLevelUpCommand command : skillLevelCommands) { for (LevelUpCommand command : levelUpCommands) {
command.process(mmoPlayer, primarySkillType, levelsGained); command.process(mmoPlayer, primarySkillType, levelsGained, powerLevelsGained);
} }
} }
public void applyPowerLevelUp(@NotNull McMMOPlayer mmoPlayer, Set<Integer> levelsGained) { public @NotNull Set<LevelUpCommand> getLevelUpCommands() {
if (!mmoPlayer.getPlayer().isOnline()) { return levelUpCommands;
return;
}
for (PowerLevelUpCommand command : powerLevelUpCommands) {
command.process(mmoPlayer, levelsGained);
}
}
public @NotNull Set<SkillLevelUpCommand> getSkillLevelCommands() {
return skillLevelCommands;
}
public @NotNull Set<PowerLevelUpCommand> getPowerLevelUpCommands() {
return powerLevelUpCommands;
} }
/** /**
@ -78,8 +57,7 @@ public class LevelUpCommandManager {
*/ */
public void clear() { public void clear() {
mcMMO.p.getLogger().info("Clearing registered commands on level up"); mcMMO.p.getLogger().info("Clearing registered commands on level up");
skillLevelCommands.clear(); levelUpCommands.clear();
powerLevelUpCommands.clear();
} }
@Override @Override
@ -87,19 +65,18 @@ public class LevelUpCommandManager {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
LevelUpCommandManager that = (LevelUpCommandManager) o; 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 @Override
public int hashCode() { public int hashCode() {
return Objects.hash(skillLevelCommands, powerLevelUpCommands, plugin); return Objects.hash(levelUpCommands, plugin);
} }
@Override @Override
public String toString() { public String toString() {
return "LevelUpCommandManager{" + return "LevelUpCommandManager{" +
"skillLevelCommands=" + skillLevelCommands + "levelUpCommands=" + levelUpCommands +
", powerLevelUpCommands=" + powerLevelUpCommands +
", plugin=" + plugin + ", plugin=" + plugin +
'}'; '}';
} }

View File

@ -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<Integer> predicate;
private final boolean logInfo;
private final @NotNull LinkedList<String> commands;
public PowerLevelUpCommand(@NotNull Predicate<Integer> predicate, @NotNull String command, boolean logInfo) {
this.predicate = predicate;
this.commands = new LinkedList<>();
this.commands.add(command);
this.logInfo = logInfo;
}
public PowerLevelUpCommand(@NotNull Predicate<Integer> predicate, @NotNull LinkedList<String> commands, boolean logInfo) {
this.predicate = predicate;
this.commands = commands;
this.logInfo = logInfo;
}
public void process(McMMOPlayer player, Set<Integer> 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 +
'}';
}
}

View File

@ -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<Integer> levels = null;
private LinkedList<String> commands = null;
private Predicate<Integer> predicate = null;
private boolean logInfo;
public PowerLevelUpCommandBuilder() {
this.logInfo = false;
}
public PowerLevelUpCommandBuilder withPredicate(Predicate<Integer> 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<String> command) {
this.commands = new LinkedList<>(command);
return this;
}
public PowerLevelUpCommandBuilder withLevels(@NotNull Collection<Integer> 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);
}
}

View File

@ -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<PrimarySkillType, Integer> predicate;
private final boolean logInfo;
private final @NotNull LinkedList<String> commands;
public SkillLevelUpCommand(@NotNull BiPredicate<PrimarySkillType, Integer> predicate, @NotNull String command, boolean logInfo) {
this.predicate = predicate;
this.commands = new LinkedList<>();
this.commands.add(command);
this.logInfo = logInfo;
}
public SkillLevelUpCommand(@NotNull BiPredicate<PrimarySkillType, Integer> predicate, @NotNull LinkedList<String> commands, boolean logInfo) {
this.predicate = predicate;
this.commands = commands;
this.logInfo = logInfo;
}
public void process(McMMOPlayer player, PrimarySkillType primarySkillType, Set<Integer> 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 + '\'' +
'}';
}
}

View File

@ -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<PrimarySkillType> skillFilter = null;
private Set<Integer> levels = null;
private LinkedList<String> commands = null;
private BiPredicate<PrimarySkillType, Integer> predicate = null;
private boolean logInfo;
public SkillLevelUpCommandBuilder() {
this.logInfo = false;
}
public SkillLevelUpCommandBuilder withPredicate(BiPredicate<PrimarySkillType, Integer> 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<String> command) {
this.commands = new LinkedList<>(command);
return this;
}
public SkillLevelUpCommandBuilder withLevels(@NotNull Collection<Integer> levels) {
requireNonNull(levels, "levels is null!");
this.levels = Set.copyOf(levels);
return this;
}
public SkillLevelUpCommandBuilder withSkillFilter(@NotNull Set<PrimarySkillType> 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);
}
}

View File

@ -1,9 +1,7 @@
package com.gmail.nossr50.config; package com.gmail.nossr50.config;
import com.gmail.nossr50.commands.levelup.PowerLevelUpCommand; import com.gmail.nossr50.commands.levelup.LevelUpCommand;
import com.gmail.nossr50.commands.levelup.PowerLevelUpCommandBuilder; import com.gmail.nossr50.commands.levelup.LevelUpCommandBuilder;
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.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.LogUtils; import com.gmail.nossr50.util.LogUtils;
@ -48,153 +46,89 @@ public class CommandOnLevelUpConfig extends BukkitConfig {
continue; continue;
} }
SkillLevelUpCommand skillLevelUpCommand = buildSkillLevelUpCommand(commandSection); LevelUpCommand levelUpCommand = buildSkillLevelUpCommand(commandSection);
PowerLevelUpCommand powerLevelUpCommand = buildPowerLevelUpCommand(commandSection);
if (skillLevelUpCommand == null && powerLevelUpCommand == null) { if (levelUpCommand == null) {
mcMMO.p.getLogger().severe("Invalid command format for key: " + key); mcMMO.p.getLogger().severe("Invalid command format for key: " + key);
} else { } else {
if(skillLevelUpCommand != null) { mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
mcMMO.p.getLevelUpCommandManager().registerCommand(skillLevelUpCommand); mcMMO.p.getLogger().info("Level up command successfully loaded from config for key: " + key);
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);
}
} }
} }
} }
private @Nullable SkillLevelUpCommand buildSkillLevelUpCommand(final ConfigurationSection commandSection) { private @Nullable LevelUpCommand buildSkillLevelUpCommand(final ConfigurationSection commandSection) {
SkillLevelUpCommandBuilder builder = new SkillLevelUpCommandBuilder(); // TODO: Rework
// check if command is enabled
if (!commandSection.getBoolean(ENABLED, true)) {
return null; return null;
} // LevelUpCommandBuilder builder = new LevelUpCommandBuilder();
/* Condition Section */ // // check if command is enabled
ConfigurationSection condition = commandSection.getConfigurationSection(CONDITION_SECTION); // if (!commandSection.getBoolean(ENABLED, true)) {
if (condition == null) { // return null;
mcMMO.p.getLogger().severe("No condition section found for command named " + commandSection.getName()); // }
return null; // /* Condition Section */
} // ConfigurationSection condition = commandSection.getConfigurationSection(CONDITION_SECTION);
// if (condition == null) {
// Skill Filter // mcMMO.p.getLogger().severe("No condition section found for command named " + commandSection.getName());
// check if skills is string or configuration section // return null;
if (condition.contains(SKILLS_SECTION)) { // }
if (condition.isString(SKILLS_SECTION)) { //
String skillName = condition.getString(SKILLS_SECTION); // // Skill Filter
if (skillName != null) { // // check if skills is string or configuration section
PrimarySkillType primarySkillType = mcMMO.p.getSkillTools().matchSkill(skillName); // if (condition.contains(SKILLS_SECTION)) {
if (primarySkillType != null) { // if (condition.isString(SKILLS_SECTION)) {
builder.withSkillFilter(getSkillsFromFilter(new HashSet<>(Set.of(skillName)))); // String skillName = condition.getString(SKILLS_SECTION);
} // if (skillName != null) {
} // PrimarySkillType primarySkillType = mcMMO.p.getSkillTools().matchSkill(skillName);
} else { // if (primarySkillType != null) {
ConfigurationSection skillsSection = condition.getConfigurationSection(SKILLS_SECTION); // builder.withSkillFilter(getSkillsFromFilter(new HashSet<>(Set.of(skillName))));
if (skillsSection != null) { // }
Set<String> skillNames = skillsSection.getKeys(false); // }
Set<PrimarySkillType> skillsFromFilter = getSkillsFromFilter(skillNames); // } else {
if (skillsFromFilter.isEmpty()) { // ConfigurationSection skillsSection = condition.getConfigurationSection(SKILLS_SECTION);
LogUtils.debug(mcMMO.p.getLogger(), "No valid skills found for command named " // if (skillsSection != null) {
+ commandSection.getName() + "for condition section named " + skillsSection.getName()); // Set<String> skillNames = skillsSection.getKeys(false);
} else { // Set<PrimarySkillType> skillsFromFilter = getSkillsFromFilter(skillNames);
builder.withSkillFilter(skillsFromFilter); // 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; //
} // // for now only simple condition is supported
// if (!condition.contains(LEVELS_SECTION)) {
Collection<Integer> levels = condition.getIntegerList(LEVELS_SECTION); // mcMMO.p.getLogger().severe("No condition.levels section found for command named " + commandSection.getName());
if (levels.isEmpty()) { // return null;
mcMMO.p.getLogger().severe("No valid levels found in condition.levels for command named " // }
+ commandSection.getName()); //
return null; // Collection<Integer> levels = condition.getIntegerList(LEVELS_SECTION);
} // if (levels.isEmpty()) {
builder.withLevels(levels); // mcMMO.p.getLogger().severe("No valid levels found in condition.levels for command named "
// + commandSection.getName());
// commands // return null;
if (commandSection.isString(COMMANDS)) { // }
String command = commandSection.getString(COMMANDS); // builder.withLevels(levels);
if (command != null) { //
builder.command(command); // // commands
} // if (commandSection.isString(COMMANDS)) {
} else { // String command = commandSection.getString(COMMANDS);
List<String> commands = commandSection.getStringList(COMMANDS); // if (command != null) {
if (commands.isEmpty()) { // builder.command(command);
mcMMO.p.getLogger().severe("No commands defined for command named " // }
+ commandSection.getName()); // } else {
return null; // List<String> commands = commandSection.getStringList(COMMANDS);
} else { // if (commands.isEmpty()) {
builder.commands(commands); // mcMMO.p.getLogger().severe("No commands defined for command named "
} // + commandSection.getName());
} // return null;
// } else {
return builder.build(); // builder.commands(commands);
} // }
// }
private @Nullable PowerLevelUpCommand buildPowerLevelUpCommand(final ConfigurationSection commandSection) { //
PowerLevelUpCommandBuilder builder = new PowerLevelUpCommandBuilder(); // return builder.build();
// 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<Integer> 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<String> 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<PrimarySkillType> getSkillsFromFilter(Set<String> skillFilter) {
return mcMMO.p.getSkillTools().matchSkills(skillFilter);
} }
} }

View File

@ -70,8 +70,7 @@ public class SelfListener implements Listener {
powerLevelsAchieved.add(startingPowerLevel + (i + 1)); powerLevelsAchieved.add(startingPowerLevel + (i + 1));
} }
plugin.getLevelUpCommandManager().applySkillLevelUp(mcMMOPlayer, skill, levelsAchieved); plugin.getLevelUpCommandManager().applySkillLevelUp(mcMMOPlayer, skill, levelsAchieved, powerLevelsAchieved);
plugin.getLevelUpCommandManager().applyPowerLevelUp(mcMMOPlayer, powerLevelsAchieved);
} }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

View File

@ -1,32 +1,23 @@
level_up_commands: level_up_commands:
unique_id_here: woodcutting_and_swords_command:
enabled: true enabled: true
condition: condition:
skills: swords:
- 'Swords' levels: [10, 100]
- 'Axes' woodcutting:
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] levels: [10, 100]
commands: commands:
- "say %player% reached level %level%!" - "say {@player} reached level {@swords_level} in swords, and {@woodcutting_level} in woodcutting!"
- "say Isn't that nice?" - "say Isn't that nice?"
run_command_as: 'CONSOLE' run_command_as: 'CONSOLE'
log_level: 'INFO' 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: power_level_milestones:
enabled: true enabled: true
condition: condition:
power_level: true power_level:
levels: [ 10, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 10000, 20000 ] levels: [ 1000, 2000, 3000, 4000, 5000 ]
commands: commands:
- "say %player% has reached a power level milestone!" - "say {@player} has reached a power level milestone!"
- "say %player% is now at power level %level%!" - "say {@player} is now at power level {@power_level}!"
run_command_as: 'CONSOLE' run_command_as: 'CONSOLE'
log_level: 'DEBUG' log_level: 'DEBUG'

View File

@ -9,28 +9,32 @@ import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.EventUtils; import com.gmail.nossr50.util.EventUtils;
import org.bukkit.Bukkit; 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.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Predicate; 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.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
class LevelUpCommandTest extends MMOTestEnvironmentBasic { class LevelUpCommandTest extends MMOTestEnvironmentBasic {
private final PrimarySkillType mining = PrimarySkillType.MINING; private static final BiPredicate<PrimarySkillType, Integer> ALWAYS_TRUE = (skill, level) -> true;
private final PrimarySkillType woodcutting = PrimarySkillType.WOODCUTTING;
private McMMOPlayer mmoPlayer; private McMMOPlayer mmoPlayer;
private final String playerName = "Momshroom"; private final String playerName = "Momshroom";
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
mcMMO.p.getLevelUpCommandManager().getSkillLevelCommands().clear(); mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().clear();
mcMMO.p.getLevelUpCommandManager().getPowerLevelUpCommands().clear();
this.mmoPlayer = getMMOPlayer(UUID.randomUUID(), playerName, 0); this.mmoPlayer = getMMOPlayer(UUID.randomUUID(), playerName, 0);
} }
@ -38,73 +42,96 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
@Test @Test
void skillLevelUpShouldRunFiveTimes() { void skillLevelUpShouldRunFiveTimes() {
// GIVEN level up command for Mining should always execute for Mining level up // 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 String commandStr = "say hello";
final SkillLevelUpCommand levelUpCommand final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
= buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5);
mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
// WHEN player gains 5 levels in mining via command // 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 // THEN the command should be checked for execution
verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any()); verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any(), any());
verify(levelUpCommand, atLeastOnce()).process(any(), any(), any()); verify(levelUpCommand, atLeastOnce()).process(any(), any(), any(), any());
// THEN the command should have executed // 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)); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5));
} }
@Test
void dualRequirementsShouldRunOnce() {
// GIVEN
assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
final String commandStr = "say hello";
BiPredicate<PrimarySkillType, Integer> predicate = (skill, skillLevel) -> skill == MINING && skillLevel == 3;
BiPredicate<PrimarySkillType, Integer> 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 @Test
void skillLevelUpViaXPGainShouldRunFiveTimes() { void skillLevelUpViaXPGainShouldRunFiveTimes() {
// GIVEN level up command for Mining should always execute for Mining level up // 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 String commandStr = "say hello";
final SkillLevelUpCommand levelUpCommand final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
= buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5);
mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
// WHEN player gains 5 levels in mining via command // 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 // THEN the command should be checked for execution
verify(levelUpCommandManager, times(5)).applySkillLevelUp(any(), any(), any()); verify(levelUpCommandManager, times(5)).applySkillLevelUp(any(), any(), any(), any());
verify(levelUpCommand, times(5)).process(any(), any(), any()); verify(levelUpCommand, times(5)).process(any(), any(), any(), any());
// THEN the command should have executed // 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)); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5));
} }
@Test @Test
void skillLevelUpViaXPGainShouldRunCommandFiveTimesWithPlaceholders() { void skillLevelUpViaXPGainShouldRunCommandFiveTimesWithPlaceholders() {
// GIVEN level up command for Mining should always execute for Mining level up // 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); 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 expectedStr1 = "say hello " + playerName + ", you have reached level 1";
final String expectedStr2 = "say hello " + playerName + ", you have reached level 2"; final String expectedStr2 = "say hello " + playerName + ", you have reached level 2";
final String expectedStr3 = "say hello " + playerName + ", you have reached level 3"; final String expectedStr3 = "say hello " + playerName + ", you have reached level 3";
final String expectedStr4 = "say hello " + playerName + ", you have reached level 4"; final String expectedStr4 = "say hello " + playerName + ", you have reached level 4";
final String expectedStr5 = "say hello " + playerName + ", you have reached level 5"; final String expectedStr5 = "say hello " + playerName + ", you have reached level 5";
final SkillLevelUpCommand levelUpCommand final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
= buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5);
mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
// WHEN player gains 5 levels in mining via command // WHEN player gains 5 levels in mining via command
assertEquals(0, mmoPlayer.getSkillLevel(mining)); assertEquals(0, mmoPlayer.getSkillLevel(MINING));
int levelsGained = 5; int levelsGained = 5;
for (int i = 0; i < 5; i++) { levelPlayerViaXP(mmoPlayer, MINING, levelsGained);
mmoPlayer.applyXpGain(mining, mmoPlayer.getProfile().getXpToLevel(mining), XPGainReason.COMMAND, XPGainSource.COMMAND);
}
// THEN the command should be checked for execution // THEN the command should be checked for execution
verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any()); verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any(), any());
verify(levelUpCommand, times(levelsGained)).process(any(), any(), any()); verify(levelUpCommand, times(levelsGained)).process(any(), any(), any(), any());
// THEN the command should have executed // 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)); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5));
// AND THEN the message for each level up should have happened at least once // 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 // verify that Bukkit.dispatchCommand got executed at least 5 times with the correct injectedCommand
@ -116,64 +143,110 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
} }
@Test @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 // 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); assertEquals(mmoPlayer.getPlayer().getName(), playerName);
final String commandStr = "say hello %player%"; final String commandStr = "say hello {@player}";
final String expectedStr = "say hello " + playerName; final String expectedStr = "say hello " + playerName;
final SkillLevelUpCommand levelUpCommand final LevelUpCommand levelUpCommandOne = buildLevelUpCommand(commandStr, (skill, level) -> skill == MINING && level == 1);
= buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandOne);
mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); 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; int levelsGained = 5;
// WHEN player gains 5 levels in mining // WHEN player gains 5 levels in mining
McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), mining, levelsGained, XPGainReason.PVE); levelPlayerViaXP(mmoPlayer, MINING, levelsGained);
selfListener.onPlayerLevelUp(event);
// THEN the command should be checked for execution // THEN the command should be checked for execution
verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommandManager, times(levelsGained)).applySkillLevelUp(any(), any(), any(), any());
verify(levelUpCommand).process(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 // THEN the command should have executed
verify(levelUpCommand, times(levelsGained)).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); verify(levelUpCommandOne, times(1)).executeCommand(any(McMMOPlayer.class));
// verify that Bukkit.dispatchCommand got executed at least 5 times with the correct injectedCommand verify(levelUpCommandTwo, times(1)).executeCommand(any(McMMOPlayer.class));
mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr)), atLeast(5)); 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 @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 // 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); 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 expectedStr1 = "say hello " + playerName + ", you have reached level 1";
final String expectedStr2 = "say hello " + playerName + ", you have reached level 2"; final String expectedStr2 = "say hello " + playerName + ", you have reached level 2";
final String expectedStr3 = "say hello " + playerName + ", you have reached level 3"; final String expectedStr3 = "say hello " + playerName + ", you have reached level 3";
final String expectedStr4 = "say hello " + playerName + ", you have reached level 4"; final String expectedStr4 = "say hello " + playerName + ", you have reached level 4";
final String expectedStr5 = "say hello " + playerName + ", you have reached level 5"; final String expectedStr5 = "say hello " + playerName + ", you have reached level 5";
final SkillLevelUpCommand levelUpCommand final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, (skill, ignored) -> skill == MINING); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
= buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining);
mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
// WHEN player gains 5 levels in mining // WHEN player gains 5 levels in mining
int levelsGained = 5; int levelsGained = 5;
mmoPlayer.getProfile().addLevels(mining, levelsGained); mmoPlayer.getProfile().addLevels(MINING, levelsGained);
EventUtils.tryLevelChangeEvent( EventUtils.tryLevelChangeEvent(
mmoPlayer.getPlayer(), mmoPlayer.getPlayer(),
mining, MINING,
levelsGained, levelsGained,
mmoPlayer.getProfile().getSkillXpLevelRaw(mining), mmoPlayer.getProfile().getSkillXpLevelRaw(MINING),
true, true,
XPGainReason.COMMAND); XPGainReason.COMMAND);
// THEN the command should be checked for execution // THEN the command should be checked for execution
verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any(), any());
verify(levelUpCommand).process(any(), any(), any()); verify(levelUpCommand).process(any(), any(), any(), any());
// THEN the command should have executed // 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 // 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(expectedStr1)));
mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr2))); mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr2)));
@ -185,118 +258,128 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
@Test @Test
void skillLevelUpShouldRunCommandAtLeastOnce() { void skillLevelUpShouldRunCommandAtLeastOnce() {
// GIVEN level up command for Mining should always execute for Mining level up // 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 String commandStr = "say hello";
final SkillLevelUpCommand levelUpCommand final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, (skill, ignored) -> skill == MINING);
= buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == mining);
mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
int levelsGained = 1; int levelsGained = 1;
// WHEN player gains 5 levels in mining // 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); selfListener.onPlayerLevelUp(event);
// THEN the command should be checked for execution // THEN the command should be checked for execution
verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any(), any());
verify(levelUpCommand).process(any(), any(), any()); verify(levelUpCommand).process(any(), any(), any(), any());
// THEN the command should have executed // THEN the command should have executed
verify(levelUpCommand).executeCommand(any(McMMOPlayer.class), any(PrimarySkillType.class), anyInt()); verify(levelUpCommand).executeCommand(any(McMMOPlayer.class));
} }
@Test @Test
void skillLevelUpShouldNotRunCommand() { void skillLevelUpShouldNotRunCommand() {
// GIVEN level up command for Woodcutting should not execute for Mining level up // 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 String commandStr = "say hello";
final SkillLevelUpCommand levelUpCommand final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, (skill, ignored) -> skill == WOODCUTTING);
= buildSkillLevelUpCommand(commandStr, (s, ignored) -> s == woodcutting);
mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
int levelsGained = 5; int levelsGained = 5;
// WHEN player gains 5 levels in mining // 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); selfListener.onPlayerLevelUp(event);
// THEN the command should be checked for execution // THEN the command should be checked for execution
verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any()); verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any(), any());
verify(levelUpCommand).process(any(), any(), any()); verify(levelUpCommand).process(any(), any(), any(), any());
// THEN the command should not be run // 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 @Test
public void skillLevelUpShouldAlwaysRunPowerlevelCommand() { public void levelUpShouldAlwaysRunCommand() {
// GIVEN level up command for power level should always execute for any level up // GIVEN level up command 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 String commandStr = "say hello";
final PowerLevelUpCommand powerLevelUpCommand final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, ALWAYS_TRUE);
= buildPowerLevelUpCommand(commandStr, (i) -> true); mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand);
// WHEN player gains 10 levels // WHEN player gains 10 levels
levelPlayerViaXP(mmoPlayer, mining, 10); levelPlayerViaXP(mmoPlayer, MINING, 10);
// THEN the command should be checked for execution // THEN the command should be checked for execution
verify(levelUpCommandManager, atLeastOnce()).applyPowerLevelUp(any(), any()); verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), eq(MINING), any(), any());
verify(powerLevelUpCommand, atLeastOnce()).process(any(), any()); verify(levelUpCommand, atLeastOnce()).process(any(), any(), any(), any());
// THEN the command should have executed // THEN the command should have executed
verify(powerLevelUpCommand, times(10)).executeCommand(any(McMMOPlayer.class), anyInt()); verify(levelUpCommand, times(10)).executeCommand(any(McMMOPlayer.class));
} }
@Test @Test
public void skillLevelUpShouldRunPowerlevelCommandOnce() { public void skillLevelUpShouldRunPowerlevelCommandOnce() {
// GIVEN level up command for power level should always execute for any level up // 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 String commandStr = "say hello";
final PowerLevelUpCommand powerLevelUpCommand final LevelUpCommand powerLevelUpCommand = buildLevelUpCommand(commandStr,
= buildPowerLevelUpCommand(commandStr, (i) -> i == 5); (ignoredA, ignoredB) -> true, (powerlevel) -> powerlevel == 3);
mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand); mcMMO.p.getLevelUpCommandManager().registerCommand(powerLevelUpCommand);
// WHEN player gains 5 levels // WHEN player gains 5 levels
levelPlayerViaXP(mmoPlayer, mining, 5); levelPlayerViaXP(mmoPlayer, MINING, 5);
// THEN the command should be checked for execution // THEN the command should be checked for execution
verify(levelUpCommandManager, atLeastOnce()).applyPowerLevelUp(any(), any()); verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any(), any());
verify(powerLevelUpCommand, atLeastOnce()).process(any(), any()); verify(powerLevelUpCommand, atLeastOnce()).process(any(), any(), any(), any());
// THEN the command should have executed // 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<PrimarySkillType, Integer> predicate) { private LevelUpCommand buildLevelUpCommand(@NotNull String commandStr,
final SkillLevelUpCommandBuilder builder = new SkillLevelUpCommandBuilder(); @NotNull List<BiPredicate<PrimarySkillType, Integer>> conditions,
@Nullable Predicate<Integer> 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<BiPredicate<PrimarySkillType, Integer>> conditions) {
return buildLevelUpCommand(commandStr, conditions, null);
}
private LevelUpCommand buildLevelUpCommand(@NotNull String commandStr,
@NotNull BiPredicate<PrimarySkillType, Integer> predicate,
@Nullable Predicate<Integer> 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) builder.command(commandStr)
.withPredicate(predicate) .withPredicate(predicate)
.withLogInfo(true); .withLogInfo(true);
return Mockito.spy(builder.build()); return Mockito.spy(builder.build());
} }
private PowerLevelUpCommand buildPowerLevelUpCommand(String commandStr, Predicate<Integer> predicate) { private LevelUpCommand buildLevelUpCommand(@NotNull String commandStr,
final PowerLevelUpCommandBuilder builder = new PowerLevelUpCommandBuilder(); @NotNull BiPredicate<PrimarySkillType, Integer> predicate) {
builder.command(commandStr) return buildLevelUpCommand(commandStr, predicate, null);
.withPredicate(predicate)
.withLogInfo(true);
return Mockito.spy(builder.build());
} }
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)); assertEquals(0, mmoPlayer.getSkillLevel(skill));
for (int i = 0; i < levelsGained; i++) { 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)); 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));
}
} }