From fb84e2f96e0c2dfb37bdaf20c78a1f7774c3c669 Mon Sep 17 00:00:00 2001 From: Jules Date: Mon, 3 Jun 2024 22:48:11 -0700 Subject: [PATCH] Fixed NPE when clicking certain skill tree nodes --- .../mmocore/api/player/PlayerData.java | 45 ++++++++++--------- .../rpg/admin/AdminCommandTreeNode.java | 2 +- .../gui/skilltree/SkillTreeViewer.java | 14 +++--- .../mmocore/manager/ExperienceManager.java | 7 +++ 4 files changed, 40 insertions(+), 28 deletions(-) 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 2fa31512..f04b4f5e 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 @@ -2,8 +2,6 @@ package net.Indyuce.mmocore.api.player; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.player.MMOPlayerData; -import io.lumine.mythic.lib.api.stat.StatInstance; -import io.lumine.mythic.lib.api.stat.modifier.StatModifier; import io.lumine.mythic.lib.data.SynchronizedDataHolder; import io.lumine.mythic.lib.player.cooldown.CooldownMap; import io.lumine.mythic.lib.util.Closeable; @@ -22,7 +20,6 @@ import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; import net.Indyuce.mmocore.api.player.social.FriendRequest; import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.quest.PlayerQuests; -import net.Indyuce.mmocore.api.quest.trigger.StatTrigger; import net.Indyuce.mmocore.api.quest.trigger.Trigger; import net.Indyuce.mmocore.api.quest.trigger.api.Removable; import net.Indyuce.mmocore.api.util.MMOCoreUtils; @@ -90,7 +87,11 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD private final List friends = new ArrayList<>(); /** - * @deprecated Use {@link #hasUnlocked(Unlockable)} instead + * TODO Use {@link #hasUnlocked(Unlockable)} instead + *

+ * Merge waypoints with unlocked items, and create a method + * plugin-scope to check if some item is class-specific and + * should be reset when switching class */ @Deprecated private final Set waypoints = new HashSet<>(); @@ -281,11 +282,10 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD skillTreePoints.clear(); // Clear node claim count - final Iterator ite = tableItemClaims.keySet().iterator(); - while (ite.hasNext()) if (ite.next().startsWith(SkillTreeNode.KEY_PREFIX)) ite.remove(); + tableItemClaims.keySet().removeIf(s -> s.startsWith(SkillTreeNode.KEY_PREFIX)); } - public boolean canIncrementNodeLevel(SkillTreeNode node) { + public boolean canIncrementNodeLevel(@NotNull SkillTreeNode node) { SkillTreeStatus skillTreeStatus = nodeStates.get(node); //Check the State of the node if (skillTreeStatus != SkillTreeStatus.UNLOCKED && skillTreeStatus != SkillTreeStatus.UNLOCKABLE) return false; @@ -297,32 +297,37 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD * Consumes skill tree points from the tree first and then consumes the * global skill-tree points ('all') */ - public void incrementNodeLevel(SkillTreeNode node) { - setNodeLevel(node, getNodeLevel(node) + 1); + public void incrementNodeLevel(@NotNull SkillTreeNode node) { + nodeLevels.merge(node, 1, (level, ignored) -> level + 1); // Claims the nodes experience table. node.getExperienceTable().claim(this, getNodeLevel(node), node); if (nodeStates.get(node) == SkillTreeStatus.UNLOCKABLE) setNodeState(node, SkillTreeStatus.UNLOCKED); - int pointToWithdraw = node.getSkillTreePointsConsumed(); - if (skillTreePoints.get(node.getTree().getId()) > 0) { - int pointWithdrawn = Math.min(pointToWithdraw, skillTreePoints.get(node.getTree().getId())); + int cost = node.getSkillTreePointsConsumed(); + final int skillTreeSpecificPoints = skillTreePoints.getOrDefault(node.getTree().getId(), 0); + if (skillTreeSpecificPoints > 0) { + int pointWithdrawn = Math.min(cost, skillTreeSpecificPoints); withdrawSkillTreePoints(node.getTree().getId(), pointWithdrawn); - pointToWithdraw -= pointWithdrawn; + cost -= pointWithdrawn; } - if (pointToWithdraw > 0) withdrawSkillTreePoints("global", pointToWithdraw); - // We unload the nodeStates map (for the skill tree) and reload it completely - for (SkillTreeNode node1 : node.getTree().getNodes()) - nodeStates.remove(node1); + if (cost > 0) withdrawSkillTreePoints("global", cost); + // Unload the nodeStates map (for the skill tree) and reload it completely + for (SkillTreeNode node1 : node.getTree().getNodes()) nodeStates.remove(node1); node.getTree().setupNodeStates(this); } - + @Deprecated public int getSkillTreePoint(String treeId) { + return getSkillTreePoints(treeId); + } + + public int getSkillTreePoints(@NotNull String treeId) { return skillTreePoints.getOrDefault(treeId, 0); } - public void withdrawSkillTreePoints(String treeId, int withdraw) { - skillTreePoints.put(treeId, skillTreePoints.get(treeId) - withdraw); + public void withdrawSkillTreePoints(@NotNull String treeId, int withdrawn) { + final int cost = Math.max(0, withdrawn); + skillTreePoints.computeIfPresent(treeId, (ignored, points) -> cost >= points ? null : points - cost); } public void setNodeState(SkillTreeNode node, SkillTreeStatus skillTreeStatus) { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java index 18a444b3..a1148233 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java @@ -29,7 +29,7 @@ public class AdminCommandTreeNode extends CommandTreeNode { addChild(new PointsCommandTreeNode("attr-realloc", this, PlayerData::setAttributeReallocationPoints, PlayerData::giveAttributeReallocationPoints, PlayerData::getAttributeReallocationPoints)); addChild(new PointsCommandTreeNode("skill-realloc", this, PlayerData::setSkillReallocationPoints, PlayerData::giveSkillReallocationPoints, PlayerData::getSkillReallocationPoints)); addChild(new PointsCommandTreeNode("skill-tree-realloc", this, PlayerData::setSkillTreeReallocationPoints, PlayerData::giveSkillTreeReallocationPoints, PlayerData::getSkillTreeReallocationPoints)); - addChild(new SkillTreePointsCommandTreeNode(this, (playerData, integer, s) -> playerData.setSkillTreePoints(s, integer), (playerData, integer, s) -> playerData.giveSkillTreePoints(s, integer), ((playerData, s) -> playerData.getSkillTreePoint(s)))); + addChild(new SkillTreePointsCommandTreeNode(this, (playerData, integer, s) -> playerData.setSkillTreePoints(s, integer), (playerData, integer, s) -> playerData.giveSkillTreePoints(s, integer), PlayerData::getSkillTreePoints)); for (PlayerResource res : PlayerResource.values()) addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res)); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java index fd4c82dd..153584b3 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java @@ -103,8 +103,8 @@ public class SkillTreeViewer extends EditableInventory { @Override public Placeholders getPlaceholders(SkillTreeInventory inv, int n) { Placeholders holders = new Placeholders(); - holders.register("skill-tree-points", inv.getPlayerData().getSkillTreePoint(inv.getSkillTree().getId())); - holders.register("global-points", inv.getPlayerData().getSkillTreePoint("global")); + holders.register("skill-tree-points", inv.getPlayerData().getSkillTreePoints(inv.getSkillTree().getId())); + holders.register("global-points", inv.getPlayerData().getSkillTreePoints("global")); holders.register("realloc-points", inv.getPlayerData().getSkillTreeReallocationPoints()); int maxPointSpent = inv.getSkillTree().getMaxPointSpent(); holders.register("max-point-spent", maxPointSpent == Integer.MAX_VALUE ? "∞" : maxPointSpent); @@ -185,8 +185,8 @@ public class SkillTreeViewer extends EditableInventory { int maxPointSpent = inv.getSkillTree().getMaxPointSpent(); holders.register("max-point-spent", maxPointSpent == Integer.MAX_VALUE ? "∞" : maxPointSpent); holders.register("point-spent", inv.getPlayerData().getPointSpent(inv.getSkillTree())); - holders.register("skill-tree-points", inv.getPlayerData().getSkillTreePoint(inv.getSkillTree().getId())); - holders.register("global-points", inv.getPlayerData().getSkillTreePoint("global")); + holders.register("skill-tree-points", inv.getPlayerData().getSkillTreePoints(inv.getSkillTree().getId())); + holders.register("global-points", inv.getPlayerData().getSkillTreePoints("global")); return holders; } } @@ -316,8 +316,8 @@ public class SkillTreeViewer extends EditableInventory { int maxPointSpent = inv.getSkillTree().getMaxPointSpent(); holders.register("max-point-spent", maxPointSpent == Integer.MAX_VALUE ? "∞" : maxPointSpent); holders.register("point-spent", inv.getPlayerData().getPointSpent(inv.getSkillTree())); - holders.register("skill-tree-points", inv.getPlayerData().getSkillTreePoint(inv.getSkillTree().getId())); - holders.register("global-points", inv.getPlayerData().getSkillTreePoint("global")); + holders.register("skill-tree-points", inv.getPlayerData().getSkillTreePoints(inv.getSkillTree().getId())); + holders.register("global-points", inv.getPlayerData().getSkillTreePoints("global")); return holders; } @@ -484,7 +484,7 @@ public class SkillTreeViewer extends EditableInventory { playerData.giveSkillTreeReallocationPoints(-1); playerData.resetSkillTree(skillTree); skillTree.setupNodeStates(playerData); - ConfigMessage.fromKey("reallocated-points", "points", "" + playerData.getSkillTreePoint(skillTree.getId()), "skill-tree", skillTree.getName()).send(player); + ConfigMessage.fromKey("reallocated-points", "points", "" + playerData.getSkillTreePoints(skillTree.getId()), "skill-tree", skillTree.getName()).send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.RESET_SKILL_TREE).playTo(player); open(); return; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java index a1d70b4d..271a35b2 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java @@ -94,6 +94,13 @@ public class ExperienceManager implements MMOCoreManager { return expTables.values(); } + // TODO when required, define class-specific unlockable items. + // TODO - Skill, skill slots are class-specific + // TODO - Waypoints are not + public boolean isClassSpecific(@NotNull String namespacedKey) { + return true; + } + @Override public void initialize(boolean clearBefore) { if (clearBefore) {