diff --git a/MMOCore-API/MMOCore-API.iml b/MMOCore-API/MMOCore-API.iml
new file mode 100644
index 00000000..1b429aca
--- /dev/null
+++ b/MMOCore-API/MMOCore-API.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ SPIGOT
+ MCP
+ BUKKIT
+
+
+
+
+
+
+
+
\ No newline at end of file
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 97a7db7f..02d32258 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
@@ -4,6 +4,8 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.player.cooldown.CooldownMap;
import io.lumine.mythic.lib.player.skill.PassiveSkill;
+import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
+import net.Indyuce.mmocore.party.provided.Party;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.SoundEvent;
@@ -30,8 +32,6 @@ import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.guild.provided.Guild;
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
import net.Indyuce.mmocore.party.AbstractParty;
-import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
-import net.Indyuce.mmocore.party.provided.Party;
import net.Indyuce.mmocore.player.Unlockable;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
@@ -58,7 +58,6 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.logging.Level;
-import java.util.stream.Collectors;
public class PlayerData extends OfflinePlayerData implements Closable, ExperienceTableClaimer {
@@ -132,6 +131,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
this.mmoData = mmoData;
questData = new PlayerQuests(this);
playerStats = new PlayerStats(this);
+
+
}
/**
@@ -181,6 +182,14 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
return pointSpent.getOrDefault(skillTree, 0);
}
+ public HashMap getPointsSpent() {
+ return new HashMap<>(pointSpent);
+ }
+
+ public void clearPointsSpent() {
+ pointSpent.clear();
+
+ }
public void setSkillTreePoints(String treeId, int points) {
skillTreePoints.put(treeId, points);
@@ -194,10 +203,18 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
return nodeLevels.keySet().stream().filter(node -> node.getTree().equals(skillTree)).mapToInt(nodeLevels::get).sum();
}
+ /**
+ * We make a copy to assure that the object created is independent of the state of playerData.
+ */
public Map getSkillTreePoints() {
- return skillTreePoints;
+ return new HashMap(skillTreePoints);
}
+ public void clearSkillTreePoints() {
+ skillTreePoints.clear();
+ }
+
+
public boolean containsSkillPointTreeId(String treeId) {
return skillTreePoints.containsKey(treeId);
}
@@ -211,7 +228,11 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
}
public Map getNodeLevels() {
- return nodeLevels;
+ return new HashMap<>(nodeLevels);
+ }
+
+ public void clearNodeLevels() {
+ nodeLevels.clear();
}
public boolean canIncrementNodeLevel(SkillTreeNode node) {
@@ -219,7 +240,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
//Check the State of the node
if (nodeState != NodeState.UNLOCKED && nodeState != NodeState.UNLOCKABLE)
return false;
- return getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.get(node.getTree().getId()) > 0 || skillTreePoints.get("global") > 0);
+ return getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.getOrDefault(node.getTree().getId(), 0) > 0 || skillTreePoints.getOrDefault("global", 0) > 0);
}
/**
@@ -268,7 +289,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
}
public int getSkillTreePoint(String treeId) {
- return skillTreePoints.get(treeId);
+ return skillTreePoints.getOrDefault(treeId, 0);
}
public void withdrawSkillTreePoints(String treeId, int withdraw) {
@@ -301,12 +322,17 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
for (SkillTreeNode node : skillTree.getNodes()) {
node.getExperienceTable().reset(this, node);
setNodeLevel(node, 0);
+ nodeStates.remove(node);
}
skillTree.setupNodeState(this);
}
public Map getNodeStates() {
- return nodeStates;
+ return new HashMap<>(nodeStates);
+ }
+
+ public void clearNodeStates() {
+ nodeStates.clear();
}
public Map getNodeTimesClaimed() {
@@ -393,6 +419,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
return Math.max(1, level);
}
+
@Nullable
public AbstractParty getParty() {
return MMOCore.plugin.partyModule.getParty(this);
@@ -446,6 +473,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
public int getClaims(String key) {
return tableItemClaims.getOrDefault(key, 0);
+
}
@Override
@@ -455,8 +483,10 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
public void setClaims(String key, int times) {
tableItemClaims.put(key, times);
+
}
+
public Map getItemClaims() {
return tableItemClaims;
}
@@ -716,9 +746,9 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
final double r = Math.sin((double) t / warpTime * Math.PI);
for (double j = 0; j < Math.PI * 2; j += Math.PI / 4)
getPlayer().getLocation().getWorld().spawnParticle(Particle.REDSTONE, getPlayer().getLocation().add(
- Math.cos((double) 5 * t / warpTime + j) * r,
- (double) 2 * t / warpTime,
- Math.sin((double) 5 * t / warpTime + j) * r),
+ Math.cos((double) 5 * t / warpTime + j) * r,
+ (double) 2 * t / warpTime,
+ Math.sin((double) 5 * t / warpTime + j) * r),
1, new Particle.DustOptions(Color.PURPLE, 1.25f));
}
}.runTaskTimer(MMOCore.plugin, 0, 1);
@@ -751,27 +781,21 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
if (value <= 0)
return;
- // Splitting exp through party members
- AbstractParty party;
- if (splitExp && (party = getParty()) != null) {
- final List nearbyMembers = party.getOnlineMembers().stream()
- .filter(pd -> {
- if (equals(pd))
- return false;
- final double maxDis = MMOCore.plugin.configManager.partyMaxExpSplitRange;
- return maxDis <= 0 || pd.getPlayer().getLocation().distanceSquared(getPlayer().getLocation()) < maxDis * maxDis;
- }).collect(Collectors.toList());
- value /= (nearbyMembers.size() + 1);
- for (PlayerData member : nearbyMembers)
- member.giveExperience(value, source, null, false);
- }
-
- // Must be placed after exp spliting
if (hasReachedMaxLevel()) {
setExperience(0);
return;
}
+ // Splitting exp through party members
+ AbstractParty party;
+ if (splitExp && (party = getParty()) != null) {
+ List onlineMembers = party.getOnlineMembers();
+ value /= onlineMembers.size();
+ for (PlayerData member : onlineMembers)
+ if (!equals(member))
+ member.giveExperience(value, source, null, false);
+ }
+
// Apply buffs AFTER splitting exp
value *= (1 + getStats().getStat("ADDITIONAL_EXPERIENCE") / 100) * MMOCore.plugin.boosterManager.getMultiplier(null);
@@ -1131,7 +1155,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
* checks if they could potentially upgrade to one of these
*
* @return If the player can change its current class to
- * a subclass
+ * a subclass
*/
@Deprecated
public boolean canChooseSubclass() {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
index 197492aa..72c9eccf 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
@@ -9,6 +9,7 @@ import net.Indyuce.mmocore.manager.data.PlayerDataManager;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.tree.SkillTreeNode;
import net.Indyuce.mmocore.tree.skilltree.SkillTree;
+import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import java.util.HashMap;
@@ -26,7 +27,7 @@ public class SavedClassInformation {
/**
* Stores the tableItemsClaims values but only for skill tree node as it is class based.
*/
- private final Map nodeTimesClaimed;
+ private final Map nodeTimesClaimed;
public SavedClassInformation(ConfigurationSection config) {
level = config.getInt("level");
@@ -78,7 +79,7 @@ public class SavedClassInformation {
if (json.has("node-levels"))
for (Entry entry : json.getAsJsonObject("node-levels").entrySet())
nodeLevels.put(MMOCore.plugin.skillTreeManager.getNode(entry.getKey()), entry.getValue().getAsInt());
- nodeTimesClaimed=new HashMap<>();
+ nodeTimesClaimed = new HashMap<>();
if (json.has("node-times-claimed"))
for (Entry entry : json.getAsJsonObject("node-times-claimed").entrySet())
nodeTimesClaimed.put(entry.getKey(), entry.getValue().getAsInt());
@@ -89,7 +90,7 @@ public class SavedClassInformation {
public SavedClassInformation(PlayerData player) {
this(player.getLevel(), player.getExperience(), player.getSkillPoints(), player.getAttributePoints(), player.getAttributeReallocationPoints()
, player.getSkillTreeReallocationPoints(), player.getSkillReallocationPoints(),
- player.getAttributes().mapPoints(), player.mapSkillLevels(), player.getSkillTreePoints(), player.getNodeLevels(),player.getNodeTimesClaimed());
+ player.getAttributes().mapPoints(), player.mapSkillLevels(), player.getSkillTreePoints(), player.getNodeLevels(), player.getNodeTimesClaimed());
}
public SavedClassInformation(PlayerDataManager.DefaultPlayerData data) {
@@ -97,11 +98,12 @@ public class SavedClassInformation {
}
public SavedClassInformation(int level, double experience, int skillPoints, int attributePoints, int attributeReallocationPoints, int skillTreeReallocationPoints, int skillReallocationPoints) {
- this(level, experience, skillPoints, attributePoints, attributeReallocationPoints, skillTreeReallocationPoints, skillReallocationPoints, new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),new HashMap<>());
+ this(level, experience, skillPoints, attributePoints, attributeReallocationPoints, skillTreeReallocationPoints, skillReallocationPoints, new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());
}
public SavedClassInformation(int level, double experience, int skillPoints, int attributePoints, int attributeReallocationPoints, int skillTreeReallocationPoints, int skillReallocationPoints,
- Map attributes, Map skills, Map skillTreePoints, Map nodeLevels,Map nodeTimesClaimed) {
+ Map attributes, Map skills, Map skillTreePoints, Map nodeLevels, Map nodeTimesClaimed) {
+
this.level = level;
this.skillPoints = skillPoints;
this.attributePoints = attributePoints;
@@ -113,7 +115,7 @@ public class SavedClassInformation {
this.skills = skills;
this.skillTreePoints = skillTreePoints;
this.nodeLevels = nodeLevels;
- this.nodeTimesClaimed=nodeTimesClaimed;
+ this.nodeTimesClaimed = nodeTimesClaimed;
}
public int getLevel() {
@@ -173,6 +175,7 @@ public class SavedClassInformation {
return nodeLevels.get(node);
}
+
public Set getSkillTreePointsKeys() {
return skillTreePoints.keySet();
}
@@ -186,7 +189,7 @@ public class SavedClassInformation {
}
public int getAttributeLevel(String id) {
- return attributes.getOrDefault(id,0);
+ return attributes.getOrDefault(id, 0);
}
public void registerAttributeLevel(PlayerAttribute attribute, int level) {
@@ -212,13 +215,15 @@ public class SavedClassInformation {
player.mapSkillLevels().forEach((skill, level) -> player.resetSkillLevel(skill));
player.getAttributes().getInstances().forEach(ins -> ins.setBase(0));
-
+ player.clearSkillTreePoints();
+ player.clearNodeLevels();
+ player.clearNodeStates();
+ player.clearPointsSpent();
// We reset the experience table for each skill tree node to remove the perm stat.
- for (SkillTree skillTree : player.getProfess().getSkillTrees())
+ for (SkillTree skillTree : player.getProfess().getSkillTrees()) {
for (SkillTreeNode node : skillTree.getNodes())
node.getExperienceTable().reset(player, node);
- player.getNodeLevels().clear();
- player.getNodeStates().clear();
+ }
while (player.hasSkillBound(0))
player.unbindSkill(0);
@@ -238,18 +243,24 @@ public class SavedClassInformation {
(skills).forEach(player::setSkillLevel);
attributes.forEach((id, pts) -> player.getAttributes().setBaseAttribute(id, pts));
- skillTreePoints.forEach((skillTree, point) -> player.setSkillTreePoints(skillTree, point));
- //Setup node levels and node state.
- nodeLevels.forEach((node, level) -> player.setNodeLevel(node, level));
- for(SkillTree skillTree: profess.getSkillTrees())
+
+ //Careful, the global points must not be forgotten.
+ player.setSkillTreePoints("global", skillTreePoints.getOrDefault("global", 0));
+ for (SkillTree skillTree : profess.getSkillTrees()) {
+ player.setSkillTreePoints(skillTree.getId(), skillTreePoints.getOrDefault(skillTree.getId(), 0));
+ for (SkillTreeNode node : skillTree.getNodes()) {
+ player.setNodeLevel(node, nodeLevels.getOrDefault(node, 0));
+ }
+
skillTree.setupNodeState(player);
+ }
//Add the values to the times claimed table and claims the corresponding stat triggers.
- nodeTimesClaimed.forEach((str,val)->player.setClaims(str,val));
+ nodeTimesClaimed.forEach((str, val) -> player.setClaims(str, val));
//We claim back the stats triggers for all the skill tree nodes of the new class.
- for(SkillTree skillTree:profess.getSkillTrees())
- for(SkillTreeNode node:skillTree.getNodes())
- node.getExperienceTable().claimStatTriggers(player,node);
+ for (SkillTree skillTree : profess.getSkillTrees())
+ for (SkillTreeNode node : skillTree.getNodes())
+ node.getExperienceTable().claimStatTriggers(player, node);
/*
* unload current class information and set the new profess once
diff --git a/MMOCore-Dist/MMOCore-Dist.iml b/MMOCore-Dist/MMOCore-Dist.iml
new file mode 100644
index 00000000..d35a0362
--- /dev/null
+++ b/MMOCore-Dist/MMOCore-Dist.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ SPIGOT
+ MCP
+
+
+
+
+
+
+
+
\ No newline at end of file