From 3248ffe541e66411f95d2841c19c838b02ee48e7 Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 23 Apr 2024 22:54:49 -0700 Subject: [PATCH] Fixed /skills not working when a class has too many slots configured --- .../mmocore/api/player/PlayerData.java | 2 +- .../api/player/profess/PlayerClass.java | 35 ++++++++-------- .../api/quest/trigger/UnlockSlotTrigger.java | 2 +- .../rpg/admin/SlotCommandTreeNode.java | 4 -- .../net/Indyuce/mmocore/gui/SkillList.java | 4 +- .../mmocore/manager/ConfigManager.java | 3 +- .../net/Indyuce/mmocore/util/ConfigUtils.java | 42 +++++++++++++++++++ MMOCore-Dist/src/main/resources/config.yml | 3 -- 8 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/util/ConfigUtils.java diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index df37d21d..8fd652c4 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -1220,7 +1220,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD */ public void bindSkill(int slot, @NotNull ClassSkill skill) { Validate.notNull(skill, "Skill cannot be null"); - if (slot < 0) return; + if (slot <= 0) return; // Unbinds the previous skill (important for passive skills) unbindSkill(slot); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java index 03bc5861..bd874cbd 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java @@ -32,6 +32,7 @@ import net.Indyuce.mmocore.skill.RegisteredSkill; import net.Indyuce.mmocore.skill.binding.SkillSlot; import net.Indyuce.mmocore.skill.cast.ComboMap; import net.Indyuce.mmocore.skilltree.tree.SkillTree; +import net.Indyuce.mmocore.util.ConfigUtils; import net.md_5.bungee.api.ChatColor; import org.bukkit.Location; import org.bukkit.Material; @@ -66,7 +67,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject { @Nullable private final CastingParticle castParticle; - private final Map skillSlots = new HashMap<>(); + private final List skillSlots = new ArrayList<>(); private final List skillTrees = new ArrayList<>(); private final List classScripts = new LinkedList(); private final Map stats = new HashMap<>(); @@ -174,15 +175,13 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject { } // Skill slots - for (int i = 1; i < MMOCore.plugin.configManager.maxSkillSlots + 1; i++) - try { - if (config.contains("skill-slots." + i)) - skillSlots.put(i, new SkillSlot(config.getConfigurationSection("skill-slots." + i))); - else - skillSlots.put(i, new SkillSlot(i, 0, "true", "&eSkill Slot " + MMOCoreUtils.intToRoman(i), new ArrayList<>(), false, true, new ArrayList<>())); - } catch (RuntimeException exception) { - MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load skill slot '" + String.valueOf(i) + "' from class '" + getId() + "': " + exception.getMessage()); - } + if (config.isConfigurationSection("skill-slots")) + ConfigUtils.iterateConfigSectionList( + config.getConfigurationSection("skill-slots"), + skillSlots, + SkillSlot::new, + index -> new SkillSlot(index, 0, "true", "&eUnconfigured Skill Slot " + MMOCoreUtils.intToRoman(index), new ArrayList<>(), false, true, new ArrayList<>()), + (key, exception) -> MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load skill slot '" + key + "' from class '" + getId() + "': " + exception.getMessage())); // Class skills for (RegisteredSkill registered : MMOCore.plugin.skillManager.getAll()) { @@ -365,9 +364,9 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject { /** * @return A list of passive skills which correspond to class - * scripts wrapped in a format recognized by MythicLib. - * Class scripts are handled just like - * passive skills + * scripts wrapped in a format recognized by MythicLib. + * Class scripts are handled just like + * passive skills */ @NotNull public List getScripts() { @@ -426,19 +425,21 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject { } public boolean hasSlot(int slot) { - return skillSlots.containsKey(slot); + return 1 <= slot && slot <= skillSlots.size(); } public List getSkillTrees() { return skillTrees; } + @Nullable public SkillSlot getSkillSlot(int slot) { - return skillSlots.get(slot); + return hasSlot(slot) ? skillSlots.get(slot - 1) : null; } - public Collection getSlots() { - return skillSlots.values(); + @NotNull + public List getSlots() { + return skillSlots; } @NotNull diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java index 429b2d2e..7c96878d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java @@ -19,7 +19,7 @@ public class UnlockSlotTrigger extends Trigger implements Removable { }catch(NumberFormatException e){ throw new IllegalArgumentException("The slot should be a number"); } - Validate.isTrue(slot > 0 && slot <= MMOCore.plugin.configManager.maxSkillSlots, "The slot should be between 1 and " + MMOCore.plugin.configManager.maxSkillSlots); + Validate.isTrue(slot > 0, "Slot number must be positive"); } @Override diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java index d274b5ca..05e294bb 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java @@ -53,10 +53,6 @@ public class SlotCommandTreeNode extends CommandTreeNode { sender.sendMessage(ChatColor.RED + "The slot can't be negative."); return CommandResult.FAILURE; } - if (slot > MMOCore.plugin.configManager.maxSkillSlots) { - sender.sendMessage(ChatColor.RED + "The slot can't be higher than " + MMOCore.plugin.configManager.maxSkillSlots + "."); - return CommandResult.FAILURE; - } SkillSlot skillSlot = playerData.getProfess().getSkillSlot(slot); if(skillSlot.isUnlockedByDefault()){ sender.sendMessage(ChatColor.RED + "You can't lock a skill that is unlocked by default."); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java index b9cf4f28..1027c08e 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java @@ -213,8 +213,8 @@ public class SkillList extends EditableInventory { @Override public ItemStack display(SkillViewerInventory inv, int n) { - final @NotNull SkillSlot skillSlot = inv.getPlayerData().getProfess().getSkillSlot(n + 1); - if (!inv.getPlayerData().hasUnlocked(skillSlot)) + final @Nullable SkillSlot skillSlot = inv.getPlayerData().getProfess().getSkillSlot(n + 1); + if (skillSlot == null || !inv.getPlayerData().hasUnlocked(skillSlot)) return new ItemStack(Material.AIR); final @Nullable ClassSkill boundSkill = inv.getPlayerData().getBoundSkill(n + 1); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java index 27af2cd1..6ceceed6 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java @@ -34,7 +34,7 @@ public class ConfigManager { public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown; public double lootChestsChanceWeight, dropItemsChanceWeight, fishingDropsChanceWeight, partyMaxExpSplitRange, pvpModeToggleOnCooldown, pvpModeToggleOffCooldown, pvpModeCombatCooldown, pvpModeCombatTimeout, pvpModeInvulnerabilityTimeRegionChange, pvpModeInvulnerabilityTimeCommand, pvpModeRegionEnterCooldown, pvpModeRegionLeaveCooldown; - public int maxPartyLevelDifference, maxPartyPlayers, maxSkillSlots, minCombatLevel, maxCombatLevelDifference, skillTreeScrollStepX, skillTreeScrollStepY; + public int maxPartyLevelDifference, maxPartyPlayers, minCombatLevel, maxCombatLevelDifference, skillTreeScrollStepX, skillTreeScrollStepY; public final List combatLogDamageCauses = new ArrayList<>(); private final FileConfiguration messages; @@ -160,7 +160,6 @@ public class ConfigManager { canCreativeCast = MMOCore.plugin.getConfig().getBoolean("can-creative-cast"); cobbleGeneratorXP = MMOCore.plugin.getConfig().getBoolean("should-cobblestone-generators-give-exp"); saveDefaultClassInfo = MMOCore.plugin.getConfig().getBoolean("save-default-class-info"); - maxSkillSlots = MMOCore.plugin.getConfig().getInt("max-skill-slots"); overrideVanillaExp = MMOCore.plugin.getConfig().getBoolean("override-vanilla-exp"); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/ConfigUtils.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/ConfigUtils.java new file mode 100644 index 00000000..3581874a --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/ConfigUtils.java @@ -0,0 +1,42 @@ +package net.Indyuce.mmocore.util; + +import net.Indyuce.mmocore.MMOCore; +import org.apache.commons.lang.Validate; +import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.logging.Level; + +public class ConfigUtils { + + public static void iterateConfigSectionList(@NotNull ConfigurationSection config, + @NotNull List list, + @NotNull Function subconfigHandler, + @NotNull Function fill, + @NotNull BiConsumer errorHandler) { + int expectedOrdinal = 1; + + for (String key : config.getKeys(false)) + try { + final int index = Integer.parseInt(key); + final ConfigurationSection subconfig = config.getConfigurationSection(key); + Validate.notNull(subconfig, "Not a configuration section"); + MMOCore.plugin.getLogger().log(Level.INFO, "Received " + index); + + // Replace + if (index < expectedOrdinal) list.set(index, subconfigHandler.apply(subconfig)); + else { + while (expectedOrdinal < index) + list.add(fill.apply(expectedOrdinal++)); + list.add(subconfigHandler.apply(subconfig)); + expectedOrdinal++; + } + + } catch (RuntimeException exception) { + errorHandler.accept(key, exception); + } + } +} diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index 0dbd6c24..ed82747c 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -229,9 +229,6 @@ death-exp-loss: # Percentage of current EXP you lose when dying. percent: 30 -# Maximum number of skill slots. This means that you cannot unlock more than X skill slots. -max-skill-slots: 8 - # When set to true, passive skills must be bound in order to take effect. # When set to false, unlocked skills will take effect right away. # This is only the default behavior for skills but can be overridden by specifying true/false to