Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commands on level up #4916

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/com/gmail/nossr50/api/ExperienceAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ public static void removeXPOffline(UUID uuid, String skillType, int xp) {
* @throws InvalidFormulaTypeException if the given formulaType is not valid
*/
public static int getXpNeededToLevel(int level) {
return mcMMO.getFormulaManager().getXPtoNextLevel(level, ExperienceConfig.getInstance().getFormulaType());
return mcMMO.p.getFormulaManager().getXPtoNextLevel(level, ExperienceConfig.getInstance().getFormulaType());
}

/**
Expand All @@ -1137,7 +1137,7 @@ public static int getXpNeededToLevel(int level) {
* @throws InvalidFormulaTypeException if the given formulaType is not valid
*/
public static int getXpNeededToLevel(int level, String formulaType) {
return mcMMO.getFormulaManager().getXPtoNextLevel(level, getFormulaType(formulaType));
return mcMMO.p.getFormulaManager().getXPtoNextLevel(level, getFormulaType(formulaType));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class ConvertExperienceCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (args.length == 2) {
FormulaType previousType = mcMMO.getFormulaManager().getPreviousFormulaType();
FormulaType previousType = mcMMO.p.getFormulaManager().getPreviousFormulaType();
FormulaType newType = FormulaType.getFormulaType(args[1].toUpperCase(Locale.ENGLISH));

if (newType == FormulaType.UNKNOWN) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.gmail.nossr50.commands.levelup;

public interface CommandsOnLevel {
}
114 changes: 114 additions & 0 deletions src/main/java/com/gmail/nossr50/commands/levelup/LevelUpCommand.java
Original file line number Diff line number Diff line change
@@ -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 +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
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.jetbrains.annotations.NotNull;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import static java.util.Objects.requireNonNull;

/**
* Manages commands to be executed on level up
*/
public class LevelUpCommandManager {
private final @NotNull Set<LevelUpCommand> levelUpCommands;
private final @NotNull mcMMO plugin;

public LevelUpCommandManager(@NotNull mcMMO plugin) {
this.plugin = requireNonNull(plugin, "plugin cannot be null");
this.levelUpCommands = new HashSet<>();
}

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);
}

/**
* Apply the level up commands to the player
*
* @param mmoPlayer the player
* @param primarySkillType the skill type
* @param levelsGained the levels gained
*/
public void applySkillLevelUp(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType,
Set<Integer> levelsGained, Set<Integer> powerLevelsGained) {
if (!mmoPlayer.getPlayer().isOnline()) {
return;
}

for (LevelUpCommand command : levelUpCommands) {
command.process(mmoPlayer, primarySkillType, levelsGained, powerLevelsGained);
}
}

public @NotNull Set<LevelUpCommand> getLevelUpCommands() {
return levelUpCommands;
}

/**
* Clear all registered commands
*/
public void clear() {
mcMMO.p.getLogger().info("Clearing registered commands on level up");
levelUpCommands.clear();
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LevelUpCommandManager that = (LevelUpCommandManager) o;
return Objects.equals(levelUpCommands, that.levelUpCommands) && Objects.equals(plugin, that.plugin);
}

@Override
public int hashCode() {
return Objects.hash(levelUpCommands, plugin);
}

@Override
public String toString() {
return "LevelUpCommandManager{" +
"levelUpCommands=" + levelUpCommands +
", plugin=" + plugin +
'}';
}
}
Loading
Loading