package com.gmail.nossr50.datatypes.player; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.datatypes.MobHealthbarType; import com.gmail.nossr50.datatypes.experience.FormulaType; import com.gmail.nossr50.datatypes.skills.AbilityType; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.runnables.player.PlayerProfileSaveTask; import com.gmail.nossr50.skills.child.FamilyTree; import com.gmail.nossr50.util.player.UserManager; import com.google.common.collect.ImmutableMap; public class PlayerProfile { private final String playerName; private UUID uuid; private boolean loaded; private volatile boolean changed; /* HUDs */ private MobHealthbarType mobHealthbarType; /* Skill Data */ private final Map<SkillType, Integer> skills = new HashMap<SkillType, Integer>(); // Skill & Level private final Map<SkillType, Float> skillsXp = new HashMap<SkillType, Float>(); // Skill & XP private final Map<AbilityType, Integer> abilityDATS = new HashMap<AbilityType, Integer>(); // Ability & Cooldown @Deprecated public PlayerProfile(String playerName) { this(playerName, null); } public PlayerProfile(String playerName, UUID uuid) { this.uuid = uuid; this.playerName = playerName; mobHealthbarType = Config.getInstance().getMobHealthbarDefault(); for (AbilityType abilityType : AbilityType.values()) { abilityDATS.put(abilityType, 0); } for (SkillType skillType : SkillType.NON_CHILD_SKILLS) { skills.put(skillType, 0); skillsXp.put(skillType, 0F); } } @Deprecated public PlayerProfile(String playerName, boolean isLoaded) { this(playerName); this.loaded = isLoaded; } public PlayerProfile(String playerName, UUID uuid, boolean isLoaded) { this(playerName, uuid); this.loaded = isLoaded; } public PlayerProfile(String playerName, UUID uuid, Map<SkillType, Integer> levelData, Map<SkillType, Float> xpData, Map<AbilityType, Integer> cooldownData, MobHealthbarType mobHealthbarType) { this.playerName = playerName; this.uuid = uuid; this.mobHealthbarType = mobHealthbarType; skills.putAll(levelData); skillsXp.putAll(xpData); abilityDATS.putAll(cooldownData); loaded = true; } public void scheduleAsyncSave() { new PlayerProfileSaveTask(this).runTaskAsynchronously(mcMMO.p); } public void save() { if (!changed || !loaded) { return; } // TODO should this part be synchronized? PlayerProfile profileCopy = new PlayerProfile(playerName, uuid, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType); changed = !mcMMO.getDatabaseManager().saveUser(profileCopy); if (changed) { mcMMO.p.getLogger().warning("PlayerProfile saving failed for player: " + playerName + " " + uuid); } } public String getPlayerName() { return playerName; } public UUID getUniqueId() { return uuid; } public void setUniqueId(UUID uuid) { changed = true; this.uuid = uuid; } public boolean isLoaded() { return loaded; } /* * Mob Healthbars */ public MobHealthbarType getMobHealthbarType() { return mobHealthbarType; } public void setMobHealthbarType(MobHealthbarType mobHealthbarType) { this.mobHealthbarType = mobHealthbarType; } /* * Cooldowns */ /** * Get the current deactivation timestamp of an ability. * * @param ability The {@link AbilityType} to get the DATS for * @return the deactivation timestamp for the ability */ public long getAbilityDATS(AbilityType ability) { return abilityDATS.get(ability); } /** * Set the current deactivation timestamp of an ability. * * @param ability The {@link AbilityType} to set the DATS for * @param DATS the DATS of the ability */ protected void setAbilityDATS(AbilityType ability, long DATS) { changed = true; abilityDATS.put(ability, (int) (DATS * .001D)); } /** * Reset all ability cooldowns. */ protected void resetCooldowns() { changed = true; for (AbilityType ability : abilityDATS.keySet()) { abilityDATS.put(ability, 0); } } /* * Xp Functions */ public int getSkillLevel(SkillType skill) { return skill.isChildSkill() ? getChildSkillLevel(skill) : skills.get(skill); } public float getSkillXpLevelRaw(SkillType skill) { return skillsXp.get(skill); } public int getSkillXpLevel(SkillType skill) { return (int) Math.floor(getSkillXpLevelRaw(skill)); } public void setSkillXpLevel(SkillType skill, float xpLevel) { if (skill.isChildSkill()) { return; } changed = true; skillsXp.put(skill, xpLevel); } protected float levelUp(SkillType skill) { float xpRemoved = getXpToLevel(skill); changed = true; skills.put(skill, skills.get(skill) + 1); skillsXp.put(skill, skillsXp.get(skill) - xpRemoved); return xpRemoved; } /** * Remove Xp from a skill. * * @param skill Type of skill to modify * @param xp Amount of xp to remove */ public void removeXp(SkillType skill, int xp) { if (skill.isChildSkill()) { return; } changed = true; skillsXp.put(skill, skillsXp.get(skill) - xp); } public void removeXp(SkillType skill, float xp) { if (skill.isChildSkill()) { return; } changed = true; skillsXp.put(skill, skillsXp.get(skill) - xp); } /** * Modify a skill level. * * @param skill Type of skill to modify * @param level New level value for the skill */ public void modifySkill(SkillType skill, int level) { if (skill.isChildSkill()) { return; } changed = true; skills.put(skill, level); skillsXp.put(skill, 0F); } /** * Add levels to a skill. * * @param skill Type of skill to add levels to * @param levels Number of levels to add */ public void addLevels(SkillType skill, int levels) { modifySkill(skill, skills.get(skill) + levels); } /** * Add Experience to a skill. * * @param skill Type of skill to add experience to * @param xp Number of experience to add */ public void addXp(SkillType skill, float xp) { changed = true; if (skill.isChildSkill()) { Set<SkillType> parentSkills = FamilyTree.getParents(skill); float dividedXP = (xp / parentSkills.size()); for (SkillType parentSkill : parentSkills) { skillsXp.put(parentSkill, skillsXp.get(parentSkill) + dividedXP); } } else { skillsXp.put(skill, skillsXp.get(skill) + xp); } } /** * Get the total amount of Xp before the next level. * * @param skillType Type of skill to check * @return the total amount of Xp until next level */ public int getXpToLevel(SkillType skillType) { int level = (ExperienceConfig.getInstance().getCumulativeCurveEnabled()) ? UserManager.getPlayer(playerName).getPowerLevel() : skills.get(skillType); FormulaType formulaType = ExperienceConfig.getInstance().getFormulaType(); return mcMMO.getFormulaManager().getCachedXpToLevel(level, formulaType); } private int getChildSkillLevel(SkillType skillType) { Set<SkillType> parents = FamilyTree.getParents(skillType); int sum = 0; for (SkillType parent : parents) { sum += Math.min(getSkillLevel(parent), 1000); } return sum / parents.size(); } }