Merge remote-tracking branch 'origin/master'

# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
#	README.md
This commit is contained in:
Jules 2023-04-08 14:28:40 +02:00
commit c8932e3a5d
39 changed files with 480 additions and 301 deletions

19
LICENSE
View File

@ -1,3 +1,18 @@
This project is owned and maintained by PhoenixDvpt and is distributed with "All Right's Reserved". This project is owned and maintained by "Phoenix Development" and is distributed with "All Rights Reserved".
PhoenixDevt reserves the right to change these terms at any time, you have to comply with the most recent version.
We do NOT provide support to servers involved with piracy in any form, or owners who have downloaded ANY of our plugins from an unofficial/illegal source.
You can fork and modify the source code of this project as you wish to meet your server's needs, and merge requests are accepted under the terms that you grant full rights to us using any pushed code. However, you may not distribute the plugin for any purpose other than providing cross-compatibility with other Minecraft plugins, and may not bypass any anti-piracy protection. Things can you CANNOT do:
- Issue a refund on PayPal without our explicit permission, as this is a digital good.
- Redistribute, sell or give an official/modified version of the plugin (with or without any type of counterpart) to anyone else.
- Modify and compile the project source code to bypass an anti-piracy protection.
- Download, compile, decompile or use the plugin on a production server without purchasing a license.
Things can you CAN do when purchasing the plugin:
- Download and decompile the plugin file.
- Fork and modify the project source code to meet your production server's needs.
- Use it on ONE production server or network (= proxy-connected servers) at a time.
You may propose a merge request, under the terms that you grant full rights to us using any pushed code.
If you are a developer and have not purchased a license, you have the permission to download, fork, edit and compile the project source code, and sell code modifications to your client ONLY IF they have already purchased a license. This only applies to one-time comission works and does NOT apply to public sales.

View File

@ -343,7 +343,6 @@ public class MMOCore extends JavaPlugin {
statManager.initialize(clearBefore); statManager.initialize(clearBefore);
professionManager.initialize(clearBefore); professionManager.initialize(clearBefore);
InventoryManager.load();
skillTreeManager.initialize(clearBefore); skillTreeManager.initialize(clearBefore);
classManager.initialize(clearBefore); classManager.initialize(clearBefore);
questManager.initialize(clearBefore); questManager.initialize(clearBefore);
@ -353,6 +352,8 @@ public class MMOCore extends JavaPlugin {
requestManager.initialize(clearBefore); requestManager.initialize(clearBefore);
soundManager.initialize(clearBefore); soundManager.initialize(clearBefore);
configItems.initialize(clearBefore); configItems.initialize(clearBefore);
//Needs to be loaded after the class manager.
InventoryManager.load();
if (getConfig().isConfigurationSection("action-bar")) if (getConfig().isConfigurationSection("action-bar"))
actionBarManager.reload(getConfig().getConfigurationSection("action-bar")); actionBarManager.reload(getConfig().getConfigurationSection("action-bar"));

View File

@ -12,15 +12,12 @@ import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent; import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent;
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent; import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent; import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.event.unlocking.ItemLockedEvent;
import net.Indyuce.mmocore.api.event.unlocking.ItemUnlockedEvent;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes; import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
import net.Indyuce.mmocore.api.player.profess.Subclass; import net.Indyuce.mmocore.api.player.profess.Subclass;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.api.player.profess.skillbinding.BoundSkillInfo;
import net.Indyuce.mmocore.api.player.social.FriendRequest; import net.Indyuce.mmocore.api.player.social.FriendRequest;
import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.player.stats.PlayerStats;
import net.Indyuce.mmocore.api.quest.PlayerQuests; import net.Indyuce.mmocore.api.quest.PlayerQuests;
@ -31,12 +28,14 @@ import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.ExperienceObject; import net.Indyuce.mmocore.experience.ExperienceObject;
import net.Indyuce.mmocore.experience.ExperienceTableClaimer; import net.Indyuce.mmocore.experience.ExperienceTableClaimer;
import net.Indyuce.mmocore.experience.PlayerProfessions; import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.experience.droptable.ExperienceItem;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.guild.provided.Guild; import net.Indyuce.mmocore.guild.provided.Guild;
import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect; import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
import net.Indyuce.mmocore.party.AbstractParty; import net.Indyuce.mmocore.party.AbstractParty;
import net.Indyuce.mmocore.party.provided.MMOCorePartyModule; import net.Indyuce.mmocore.player.ClassDataContainer;
import net.Indyuce.mmocore.party.provided.Party;
import net.Indyuce.mmocore.player.CombatHandler; import net.Indyuce.mmocore.player.CombatHandler;
import net.Indyuce.mmocore.player.Unlockable;
import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill; import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
@ -46,6 +45,7 @@ import net.Indyuce.mmocore.skilltree.SkillTreeNode;
import net.Indyuce.mmocore.skilltree.tree.SkillTree; import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import net.Indyuce.mmocore.skilltree.tree.display.DisplayInfo; import net.Indyuce.mmocore.skilltree.tree.display.DisplayInfo;
import net.Indyuce.mmocore.skilltree.tree.display.Icon; import net.Indyuce.mmocore.skilltree.tree.display.Icon;
import net.Indyuce.mmocore.waypoint.Waypoint;
import net.Indyuce.mmocore.waypoint.WaypointOption; import net.Indyuce.mmocore.waypoint.WaypointOption;
import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
@ -79,10 +79,13 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
*/ */
@Nullable @Nullable
private PlayerClass profess; private PlayerClass profess;
private int level, classPoints, skillPoints, attributePoints, attributeReallocationPoints; private int level, classPoints, skillPoints, attributePoints, attributeReallocationPoints, skillTreeReallocationPoints, skillReallocationPoints;
private int skillTreeReallocationPoints, skillReallocationPoints;
private double experience; private double experience;
private double mana, stamina, stellium; private double mana, stamina, stellium;
/**
* Health is stored in playerData because when saving the playerData we can't access the player health anymore as the payer is Offline.
*/
private double health;
private Guild guild; private Guild guild;
private SkillCastingHandler skillCasting; private SkillCastingHandler skillCasting;
private final PlayerQuests questData; private final PlayerQuests questData;
@ -263,7 +266,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
//Check the State of the node //Check the State of the node
if (nodeStatus != NodeStatus.UNLOCKED && nodeStatus != NodeStatus.UNLOCKABLE) if (nodeStatus != NodeStatus.UNLOCKED && nodeStatus != NodeStatus.UNLOCKABLE)
return false; return false;
return getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.getOrDefault(node.getTree().getId(), 0) > 0 || skillTreePoints.getOrDefault("global", 0) > 0); return getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.getOrDefault(node.getTree().getId(), 0) + skillTreePoints.getOrDefault("global", 0) >= node.getSkillTreePointsConsumed());
} }
/** /**
@ -278,10 +281,14 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
if (nodeStates.get(node) == NodeStatus.UNLOCKABLE) if (nodeStates.get(node) == NodeStatus.UNLOCKABLE)
setNodeState(node, NodeStatus.UNLOCKED); setNodeState(node, NodeStatus.UNLOCKED);
if (skillTreePoints.get(node.getTree().getId()) > 0) int pointToWithdraw = node.getSkillTreePointsConsumed();
withdrawSkillTreePoints(node.getTree().getId(), 1); if (skillTreePoints.get(node.getTree().getId()) > 0) {
else int pointWithdrawn = Math.min(pointToWithdraw, skillTreePoints.get(node.getTree().getId()));
withdrawSkillTreePoints("global", 1); withdrawSkillTreePoints(node.getTree().getId(), pointWithdrawn);
pointToWithdraw -= pointWithdrawn;
}
if (pointToWithdraw > 0)
withdrawSkillTreePoints("global", pointToWithdraw);
//We unload the nodeStates map (for the skill tree) and reload it completely //We unload the nodeStates map (for the skill tree) and reload it completely
for (SkillTreeNode node1 : node.getTree().getNodes()) for (SkillTreeNode node1 : node.getTree().getNodes())
nodeStates.remove(node1); nodeStates.remove(node1);
@ -336,7 +343,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
} }
public void setNodeLevel(SkillTreeNode node, int nodeLevel) { public void setNodeLevel(SkillTreeNode node, int nodeLevel) {
int delta = nodeLevel - nodeLevels.getOrDefault(node, 0); int delta = (nodeLevel - nodeLevels.getOrDefault(node, 0))*node.getSkillTreePointsConsumed();
pointSpent.put(node.getTree(), pointSpent.getOrDefault(node.getTree(), 0) + delta); pointSpent.put(node.getTree(), pointSpent.getOrDefault(node.getTree(), 0) + delta);
nodeLevels.put(node, nodeLevel); nodeLevels.put(node, nodeLevel);
} }
@ -431,6 +438,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
@Override @Override
public void close() { public void close() {
health = getPlayer().getHealth();
// Remove from party if it is MMO Party Module // Remove from party if it is MMO Party Module
if (MMOCore.plugin.partyModule instanceof MMOCorePartyModule) { if (MMOCore.plugin.partyModule instanceof MMOCorePartyModule) {
AbstractParty party = getParty(); AbstractParty party = getParty();
@ -989,7 +998,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
@Override @Override
public double getHealth() { public double getHealth() {
return getPlayer().getHealth(); return isOnline() ? getPlayer().getHealth() : health;
} }
@Override @Override

View File

@ -316,7 +316,9 @@ public class SavedClassInformation {
player.setMana(mana); player.setMana(mana);
player.setStellium(stellium); player.setStellium(stellium);
player.setStamina(stamina); player.setStamina(stamina);
double health=this.health;
health = health == 0 ? 20 : health;
player.getPlayer().setHealth(Math.min(health,player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()));
// Updates level on exp bar // Updates level on exp bar
player.refreshVanillaExp(); player.refreshVanillaExp();
} }

View File

@ -47,8 +47,6 @@ public class QuestProgress {
objective++; objective++;
objectiveProgress.close(); objectiveProgress.close();
// apply triggers
objectiveProgress.getObjective().getTriggers().forEach(trigger -> trigger.schedule(getPlayer()));
// end quest // end quest
if (objective >= quest.getObjectives().size()) if (objective >= quest.getObjectives().size())
@ -57,6 +55,10 @@ public class QuestProgress {
objectiveProgress = nextObjective().newProgress(this); objectiveProgress = nextObjective().newProgress(this);
player.getQuestData().updateBossBar(); player.getQuestData().updateBossBar();
// apply triggers at the end so the quest is ended when a trigger quest start is launched.
objectiveProgress.getObjective().getTriggers().forEach(trigger -> trigger.schedule(getPlayer()));
} }
public String getFormattedLore() { public String getFormattedLore() {

View File

@ -18,6 +18,9 @@ public class AttributesCommand extends RegisteredCommand {
@Override @Override
public boolean execute(CommandSender sender, String label, String[] args) { public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.attributes"))
return false;
if (!(sender instanceof Player)) { if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only."); sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true; return true;

View File

@ -25,6 +25,8 @@ public class FriendsCommand extends RegisteredCommand {
@Override @Override
public boolean execute(CommandSender sender, String label, String[] args) { public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.friends"))
return false;
if (!(sender instanceof Player)) { if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only."); sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true; return true;

View File

@ -26,6 +26,8 @@ public class GuildCommand extends RegisteredCommand {
@Override @Override
public boolean execute(CommandSender sender, String label, String[] args) { public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.guild"))
return false;
if (!(sender instanceof Player)) { if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only."); sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true; return true;

View File

@ -27,6 +27,8 @@ public class PartyCommand extends RegisteredCommand {
@Override @Override
public boolean execute(CommandSender sender, String label, String[] args) { public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.party"))
return false;
if (!(sender instanceof Player)) { if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only."); sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true; return true;

View File

@ -18,6 +18,8 @@ public class PlayerStatsCommand extends RegisteredCommand {
@Override @Override
public boolean execute(CommandSender sender, String label, String[] args) { public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.profile"))
return false;
if (!(sender instanceof Player)) { if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only."); sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true; return true;

View File

@ -17,6 +17,8 @@ public class QuestsCommand extends RegisteredCommand {
@Override @Override
public boolean execute(CommandSender sender, String label, String[] args) { public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.quests"))
return false;
if (sender instanceof Player) { if (sender instanceof Player) {
PlayerData data = PlayerData.get((Player) sender); PlayerData data = PlayerData.get((Player) sender);
MMOCommandEvent event = new MMOCommandEvent(data, "quests"); MMOCommandEvent event = new MMOCommandEvent(data, "quests");

View File

@ -19,6 +19,8 @@ public class SkillTreesCommand extends RegisteredCommand {
@Override @Override
public boolean execute(@NotNull CommandSender sender, String s, String[] args) { public boolean execute(@NotNull CommandSender sender, String s, String[] args) {
if (!sender.hasPermission("mmocore.skilltrees"))
return false;
if (!(sender instanceof Player player)) if (!(sender instanceof Player player))
return false; return false;
PlayerData data = PlayerData.get(player); PlayerData data = PlayerData.get(player);

View File

@ -18,6 +18,8 @@ public class SkillsCommand extends RegisteredCommand {
@Override @Override
public boolean execute(CommandSender sender, String label, String[] args) { public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.skills"))
return false;
if (sender instanceof Player) { if (sender instanceof Player) {
PlayerData data = PlayerData.get((Player) sender); PlayerData data = PlayerData.get((Player) sender);
MMOCommandEvent event = new MMOCommandEvent(data, "skills"); MMOCommandEvent event = new MMOCommandEvent(data, "skills");

View File

@ -32,7 +32,7 @@ public enum ToggleableCommand {
PARTY("party", "Invite players in a party to split exp", config -> new PartyCommand(config)), PARTY("party", "Invite players in a party to split exp", config -> new PartyCommand(config)),
GUILD("guild", "Show players in current guild", config -> new GuildCommand(config)), GUILD("guild", "Show players in current guild", config -> new GuildCommand(config)),
WITHDRAW("withdraw", "Withdraw money into coins and notes", config -> new WithdrawCommand(config), v -> MMOCore.plugin.hasEconomy() && MMOCore.plugin.economy.isValid(), "w"), WITHDRAW("withdraw", "Withdraw money into coins and notes", config -> new WithdrawCommand(config), v -> MMOCore.plugin.hasEconomy() && MMOCore.plugin.economy.isValid(), "w"),
SKILL_TREES("skiltrees", "Open up the skill tree menu", config -> new SkillTreesCommand(config), "st", "trees", "tree"), SKILL_TREES("skilltrees", "Open up the skill tree menu", config -> new SkillTreesCommand(config), "st", "trees", "tree"),
DEPOSIT("deposit", "Open the currency deposit menu", config -> new DepositCommand(config), "d"), DEPOSIT("deposit", "Open the currency deposit menu", config -> new DepositCommand(config), "d"),
PVP_MODE("pvpmode", "Toggle on/off PVP mode.", config -> new PvpModeCommand(config), "pvp"); PVP_MODE("pvpmode", "Toggle on/off PVP mode.", config -> new PvpModeCommand(config), "pvp");

View File

@ -1,12 +1,12 @@
package net.Indyuce.mmocore.gui; package net.Indyuce.mmocore.gui;
import io.lumine.mythic.lib.UtilityMethods;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent; import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext; import net.Indyuce.mmocore.gui.api.InventoryClickContext;
@ -21,21 +21,14 @@ import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class ClassConfirmation extends EditableInventory { public class ClassConfirmation extends EditableInventory {
/** private final PlayerClass playerClass;
* This enables to configure the name of the
* class confirmation GUI (for custom GUI textures).
*/
private final Map<String, String> specificNames = new HashMap<>();
public ClassConfirmation() { public ClassConfirmation(PlayerClass playerClass, boolean isDefault) {
super("class-confirm"); super("class-confirm-" + (isDefault ? "default" : UtilityMethods.ymlName(playerClass.getId())));
this.playerClass = playerClass;
} }
@Override @Override
@ -43,21 +36,13 @@ public class ClassConfirmation extends EditableInventory {
return function.equalsIgnoreCase("yes") ? new YesItem(config) : new SimplePlaceholderItem(config); return function.equalsIgnoreCase("yes") ? new YesItem(config) : new SimplePlaceholderItem(config);
} }
public GeneratedInventory newInventory(PlayerData data, PlayerClass profess, PluginInventory last) { public GeneratedInventory newInventory(PlayerData data, PluginInventory last) {
return new ClassConfirmationInventory(data, this, profess, last); return new ClassConfirmationInventory(data, this, playerClass, last);
} }
@Override @Override
public void reload(FileConfiguration config) { public void reload(FileConfiguration config) {
super.reload(config); super.reload(config);
specificNames.clear();
if (config.contains("class-specific-name")) {
final ConfigurationSection section = config.getConfigurationSection("class-specific-name");
for (String key : section.getKeys(false))
specificNames.put(key, section.getString(key));
}
} }
public class UnlockedItem extends InventoryItem<ClassConfirmationInventory> { public class UnlockedItem extends InventoryItem<ClassConfirmationInventory> {
@ -154,9 +139,7 @@ public class ClassConfirmation extends EditableInventory {
@Override @Override
public String calculateName() { public String calculateName() {
final String professKey = MMOCoreUtils.ymlName(profess.getId()); return getName().replace("{class}", profess.getName());
final @Nullable String found = specificNames.get(professKey);
return found == null ? getName().replace("{class}", profess.getName()) : found;
} }
} }
} }

View File

@ -1,18 +1,21 @@
package net.Indyuce.mmocore.gui; package net.Indyuce.mmocore.gui;
import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.ClassOption; import net.Indyuce.mmocore.api.player.profess.ClassOption;
import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext; import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.manager.InventoryManager; import net.Indyuce.mmocore.manager.InventoryManager;
import org.apache.commons.lang.Validate;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
@ -24,6 +27,7 @@ import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ClassSelect extends EditableInventory { public class ClassSelect extends EditableInventory {
@ -33,7 +37,7 @@ public class ClassSelect extends EditableInventory {
@Override @Override
public InventoryItem load(String function, ConfigurationSection config) { public InventoryItem load(String function, ConfigurationSection config) {
return function.equals("class") ? new ClassItem(config) : new SimplePlaceholderItem(config); return function.startsWith("class") ? new ClassItem(config) : new SimplePlaceholderItem(config);
} }
public GeneratedInventory newInventory(PlayerData data) { public GeneratedInventory newInventory(PlayerData data) {
@ -43,10 +47,13 @@ public class ClassSelect extends EditableInventory {
public class ClassItem extends SimplePlaceholderItem<ProfessSelectionInventory> { public class ClassItem extends SimplePlaceholderItem<ProfessSelectionInventory> {
private final String name; private final String name;
private final List<String> lore; private final List<String> lore;
private final PlayerClass playerClass;
public ClassItem(ConfigurationSection config) { public ClassItem(ConfigurationSection config) {
super(Material.BARRIER, config); super(Material.BARRIER, config);
Validate.isTrue(config.getString("function").length()>6,"Couldn't find the class associated to: "+config.getString("function"));
String classId = UtilityMethods.enumName(config.getString("function").substring(6));
this.playerClass = Objects.requireNonNull(MMOCore.plugin.classManager.get(classId),classId+" does not correspond to any classId.");
this.name = config.getString("name"); this.name = config.getString("name");
this.lore = config.getStringList("lore"); this.lore = config.getStringList("lore");
} }
@ -57,36 +64,34 @@ public class ClassSelect extends EditableInventory {
@Override @Override
public ItemStack display(ProfessSelectionInventory inv, int n) { public ItemStack display(ProfessSelectionInventory inv, int n) {
if (n >= inv.classes.size()) ItemStack item = playerClass.getIcon();
return null;
PlayerClass profess = inv.classes.get(n);
ItemStack item = profess.getIcon();
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
if (hideFlags()) if (hideFlags())
meta.addItemFlags(ItemFlag.values()); meta.addItemFlags(ItemFlag.values());
meta.setDisplayName(MythicLib.plugin.parseColors(name).replace("{name}", profess.getName())); meta.setDisplayName(MythicLib.plugin.parseColors(name).replace("{name}", playerClass.getName()));
List<String> lore = new ArrayList<>(this.lore); List<String> lore = new ArrayList<>(this.lore);
int index = lore.indexOf("{lore}"); int index = lore.indexOf("{lore}");
if (index >= 0) { if (index >= 0) {
lore.remove(index); lore.remove(index);
for (int j = 0; j < profess.getDescription().size(); j++) for (int j = 0; j < playerClass.getDescription().size(); j++)
lore.add(index + j, profess.getDescription().get(j)); lore.add(index + j, playerClass.getDescription().get(j));
} }
index = lore.indexOf("{attribute-lore}"); index = lore.indexOf("{attribute-lore}");
if (index >= 0) { if (index >= 0) {
lore.remove(index); lore.remove(index);
for (int j = 0; j < profess.getAttributeDescription().size(); j++) for (int j = 0; j < playerClass.getAttributeDescription().size(); j++)
lore.add(index + j, profess.getAttributeDescription().get(j)); lore.add(index + j, playerClass.getAttributeDescription().get(j));
} }
meta.getPersistentDataContainer().set(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING, profess.getId()); meta.getPersistentDataContainer().set(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING, playerClass.getId());
meta.setLore(lore); meta.setLore(lore);
item.setItemMeta(meta); item.setItemMeta(meta);
return item; return item;
} }
} }
public class ProfessSelectionInventory extends GeneratedInventory { public class ProfessSelectionInventory extends GeneratedInventory {
@ -104,10 +109,8 @@ public class ClassSelect extends EditableInventory {
@Override @Override
public void whenClicked(InventoryClickContext context, InventoryItem item) { public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("class")) { if (item instanceof ClassItem) {
String classId = context.getClickedItem().getItemMeta().getPersistentDataContainer().get(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING); PlayerClass profess = ((ClassItem) item).playerClass;
if (classId.equals(""))
return;
if (playerData.getClassPoints() < 1) { if (playerData.getClassPoints() < 1) {
MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player); MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player);
@ -115,7 +118,6 @@ public class ClassSelect extends EditableInventory {
return; return;
} }
final PlayerClass profess = MMOCore.plugin.classManager.get(classId);
if (profess.hasOption(ClassOption.NEEDS_PERMISSION) && !player.hasPermission("mmocore.class." + profess.getId().toLowerCase())) { if (profess.hasOption(ClassOption.NEEDS_PERMISSION) && !player.hasPermission("mmocore.class." + profess.getId().toLowerCase())) {
MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player); MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(player);
new ConfigMessage("no-permission-for-class").send(player); new ConfigMessage("no-permission-for-class").send(player);
@ -129,7 +131,7 @@ public class ClassSelect extends EditableInventory {
} }
final PlayerClass playerClass = findDeepestSubclass(playerData, profess); final PlayerClass playerClass = findDeepestSubclass(playerData, profess);
InventoryManager.CLASS_CONFIRM.newInventory(playerData, playerClass, this).open(); InventoryManager.CLASS_CONFIRM.get(MMOCoreUtils.ymlName(playerClass.getId())).newInventory(playerData, this).open();
} }
} }
} }

View File

@ -248,6 +248,7 @@ public class SkillTreeViewer extends EditableInventory {
holders.register("max-level", node.getMaxLevel()); holders.register("max-level", node.getMaxLevel());
holders.register("max-children", node.getMaxChildren()); holders.register("max-children", node.getMaxChildren());
holders.register("size", node.getSize()); holders.register("size", node.getSize());
holders.register("point-consumed", node.getSkillTreePointsConsumed());
} }
int maxPointSpent = inv.getSkillTree().getMaxPointSpent(); int maxPointSpent = inv.getSkillTree().getMaxPointSpent();
holders.register("max-point-spent", maxPointSpent == Integer.MAX_VALUE ? "" : maxPointSpent); holders.register("max-point-spent", maxPointSpent == Integer.MAX_VALUE ? "" : maxPointSpent);
@ -367,7 +368,7 @@ public class SkillTreeViewer extends EditableInventory {
open(); open();
} }
if (item.getFunction().equals("reallocation")) { if (item.getFunction().equals("reallocation")) {
int spent = playerData.countSkillTreePoints(skillTree); int spent = playerData.getPointSpent(skillTree);
if (spent < 1) { if (spent < 1) {
MMOCore.plugin.configManager.getSimpleMessage("no-skill-tree-points-spent").send(player); MMOCore.plugin.configManager.getSimpleMessage("no-skill-tree-points-spent").send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
@ -381,7 +382,7 @@ public class SkillTreeViewer extends EditableInventory {
event.setCancelled(true); event.setCancelled(true);
return; return;
} else { } else {
int reallocated = playerData.countSkillTreePoints(skillTree); int reallocated = playerData.getPointSpent(skillTree);
//We remove all the nodeStates progress //We remove all the nodeStates progress
playerData.giveSkillTreePoints(skillTree.getId(), reallocated); playerData.giveSkillTreePoints(skillTree.getId(), reallocated);
playerData.giveSkillTreeReallocationPoints(-1); playerData.giveSkillTreeReallocationPoints(-1);
@ -446,7 +447,7 @@ public class SkillTreeViewer extends EditableInventory {
//Else the player doesn't doesn't have the skill tree points //Else the player doesn't doesn't have the skill tree points
else { else {
MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-tree-points").send(player); MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-tree-points", "point", "" + node.getSkillTreePointsConsumed()).send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
event.setCancelled(true); event.setCancelled(true);
return; return;

View File

@ -1,77 +0,0 @@
package net.Indyuce.mmocore.gui;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.SoundEvent;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
public class SubclassConfirmation extends EditableInventory {
public SubclassConfirmation() {
super("subclass-confirm");
}
@Override
public InventoryItem load(String function, ConfigurationSection config) {
return function.equalsIgnoreCase("yes") ? new InventoryItem<SubclassConfirmationInventory>(config) {
@Override
public Placeholders getPlaceholders(SubclassConfirmationInventory inv, int n) {
Placeholders holders = new Placeholders();
holders.register("class", inv.profess.getName());
return holders;
}
} : new SimplePlaceholderItem(config);
}
public GeneratedInventory newInventory(PlayerData data, PlayerClass profess, PluginInventory last) {
return new SubclassConfirmationInventory(data, this, profess, last);
}
public class SubclassConfirmationInventory extends GeneratedInventory {
private final PlayerClass profess;
private final PluginInventory last;
public SubclassConfirmationInventory(PlayerData playerData, EditableInventory editable, PlayerClass profess, PluginInventory last) {
super(playerData, editable);
this.profess = profess;
this.last = last;
}
@Override
public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("back"))
last.open();
else if (item.getFunction().equals("yes")) {
PlayerChangeClassEvent called = new PlayerChangeClassEvent(playerData, profess);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return;
playerData.setClass(profess);
MMOCore.plugin.configManager.getSimpleMessage("class-select", "class", profess.getName()).send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.SELECT_CLASS).playTo(player);
player.closeInventory();
}
}
@Override
public String calculateName() {
return getName();
}
}
}

View File

@ -1,8 +1,7 @@
package net.Indyuce.mmocore.gui; package net.Indyuce.mmocore.gui;
import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag; import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.EditableInventory;
@ -15,116 +14,118 @@ import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.player.profess.Subclass; import net.Indyuce.mmocore.api.player.profess.Subclass;
import org.apache.commons.lang.Validate;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SubclassSelect extends EditableInventory { public class SubclassSelect extends EditableInventory {
public SubclassSelect() { public SubclassSelect() {
super("subclass-select"); super("subclass-select");
} }
@Override @Override
public InventoryItem load(String function, ConfigurationSection config) { public InventoryItem load(String function, ConfigurationSection config) {
return function.equals("class") ? new ClassItem(config) : new SimplePlaceholderItem(config); return function.startsWith("sub-class") ? new ClassItem(config) : new SimplePlaceholderItem(config);
} }
public GeneratedInventory newInventory(PlayerData data) { public GeneratedInventory newInventory(PlayerData data) {
return new SubclassSelectionInventory(data, this); return new SubclassSelectionInventory(data, this);
} }
public class ClassItem extends SimplePlaceholderItem<SubclassSelectionInventory> { public class ClassItem extends SimplePlaceholderItem<SubclassSelectionInventory> {
private final String name; private final String name;
private final List<String> lore; private final List<String> lore;
private final PlayerClass playerClass;
public ClassItem(ConfigurationSection config) { public ClassItem(ConfigurationSection config) {
super(Material.BARRIER, config); super(Material.BARRIER, config);
Validate.isTrue(config.getString("function").length() > 10, "Couldn't find the class associated to: " + config.getString("function"));
String classId = UtilityMethods.enumName(config.getString("function").substring(10));
this.playerClass = Objects.requireNonNull(MMOCore.plugin.classManager.get(classId), classId + " does not correspond to any classId.");
this.name = config.getString("name");
this.lore = config.getStringList("lore");
}
this.name = config.getString("name"); public boolean hasDifferentDisplay() {
this.lore = config.getStringList("lore"); return true;
} }
@Override @Override
public boolean hasDifferentDisplay() { public ItemStack display(SubclassSelectionInventory inv, int n) {
return true; ItemStack item = playerClass.getIcon();
} ItemMeta meta = item.getItemMeta();
if (hideFlags())
meta.addItemFlags(ItemFlag.values());
meta.setDisplayName(MythicLib.plugin.parseColors(name).replace("{name}", playerClass.getName()));
List<String> lore = new ArrayList<>(this.lore);
@Override int index = lore.indexOf("{lore}");
public ItemStack display(SubclassSelectionInventory inv, int n) { if (index >= 0) {
if (n >= inv.subclasses.size()) lore.remove(index);
return null; for (int j = 0; j < playerClass.getDescription().size(); j++)
lore.add(index + j, playerClass.getDescription().get(j));
}
PlayerClass profess = inv.subclasses.get(n).getProfess(); index = lore.indexOf("{attribute-lore}");
if (index >= 0) {
lore.remove(index);
for (int j = 0; j < playerClass.getAttributeDescription().size(); j++)
lore.add(index + j, playerClass.getAttributeDescription().get(j));
}
ItemStack item = profess.getIcon(); meta.getPersistentDataContainer().set(new NamespacedKey(MMOCore.plugin, "class_id"), PersistentDataType.STRING, playerClass.getId());
ItemMeta meta = item.getItemMeta(); meta.setLore(lore);
meta.setDisplayName(MythicLib.plugin.parseColors(name).replace("{name}", profess.getName())); item.setItemMeta(meta);
List<String> lore = new ArrayList<>(this.lore); return item;
}
int index = lore.indexOf("{lore}"); @Override
if (index >= 0) { public boolean canDisplay(SubclassSelectionInventory inv) {
lore.remove(index); return inv.getPlayerData().getProfess().hasSubclass(playerClass);
for (int j = 0; j < profess.getDescription().size(); j++) }
lore.add(index + j, profess.getDescription().get(j)); }
}
index = lore.indexOf("{attribute-lore}"); public class SubclassSelectionInventory extends GeneratedInventory {
if (index >= 0) { private final List<Subclass> subclasses;
lore.remove(index);
for (int j = 0; j < profess.getAttributeDescription().size(); j++)
lore.add(index + j, profess.getAttributeDescription().get(j));
}
meta.setLore(lore); public SubclassSelectionInventory(PlayerData playerData, EditableInventory editable) {
item.setItemMeta(meta); super(playerData, editable);
return NBTItem.get(item).addTag(new ItemTag("classId", profess.getId())).toItem();
}
@Override subclasses = playerData.getProfess().getSubclasses().stream().filter(sub -> playerData.getLevel() >= sub.getLevel())
public boolean canDisplay(SubclassSelectionInventory inv) { .collect(Collectors.toList());
return true; }
}
}
public class SubclassSelectionInventory extends GeneratedInventory { @Override
private final List<Subclass> subclasses; public String calculateName() {
return getName();
}
public SubclassSelectionInventory(PlayerData playerData, EditableInventory editable) { @Override
super(playerData, editable); public void whenClicked(InventoryClickContext context, InventoryItem item) {
if (item.getFunction().equals("back"))
InventoryManager.CLASS_SELECT.newInventory(playerData).open();
subclasses = playerData.getProfess().getSubclasses().stream().filter(sub -> playerData.getLevel() >= sub.getLevel()) if (item.getFunction().startsWith("sub-class")) {
.collect(Collectors.toList()); String classId= item.getFunction().substring(10);
}
@Override if (playerData.getClassPoints() < 1) {
public String calculateName() { player.closeInventory();
return getName(); MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(getPlayer());
} new ConfigMessage("cant-choose-new-class").send(player);
return;
@Override }
public void whenClicked(InventoryClickContext context, InventoryItem item) { InventoryManager.CLASS_CONFIRM.get(classId).newInventory(playerData, this).open();
if (item.getFunction().equals("back")) }
InventoryManager.CLASS_SELECT.newInventory(playerData).open(); }
}
if (item.getFunction().equals("class")) {
String tag = NBTItem.get(context.getClickedItem()).getString("classId");
if (tag.equals(""))
return;
if (playerData.getClassPoints() < 1) {
player.closeInventory();
MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(getPlayer());
new ConfigMessage("cant-choose-new-class").send(player);
return;
}
InventoryManager.SUBCLASS_CONFIRM.newInventory(playerData, MMOCore.plugin.classManager.get(tag), this).open();
}
}
}
} }

View File

@ -182,12 +182,19 @@ public class ConfigManager {
} }
public void loadDefaultFile(String path, String name) { public void loadDefaultFile(String path, String name) {
String newPath = path.isEmpty() ? "" : "/" + path; String newPath ="";
File folder = new File(MMOCore.plugin.getDataFolder() + (newPath)); if(!path.isEmpty()){
if (!folder.exists()) folder.mkdir(); String[] subpaths = path.split("/");
for (String subpath : subpaths) {
newPath+="/"+subpath;
File folder = new File(MMOCore.plugin.getDataFolder() + (newPath));
if (!folder.exists()) folder.mkdir();
}
}
File file = new File(MMOCore.plugin.getDataFolder() + (newPath), name); File file = new File(MMOCore.plugin.getDataFolder() + (newPath), name);
if (!file.exists()) try { if (!file.exists()) try {
MMOCore.log("default/" + (path.isEmpty() ? "" : path + "/") + name);
Files.copy(MMOCore.plugin.getResource("default/" + (path.isEmpty() ? "" : path + "/") + name), file.getAbsoluteFile().toPath()); Files.copy(MMOCore.plugin.getResource("default/" + (path.isEmpty() ? "" : path + "/") + name), file.getAbsoluteFile().toPath());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -1,10 +1,11 @@
package net.Indyuce.mmocore.manager; package net.Indyuce.mmocore.manager;
import java.util.Arrays; import java.util.*;
import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.social.friend.EditableFriendList; import net.Indyuce.mmocore.gui.social.friend.EditableFriendList;
import net.Indyuce.mmocore.gui.*; import net.Indyuce.mmocore.gui.*;
import net.Indyuce.mmocore.gui.social.friend.EditableFriendRemoval; import net.Indyuce.mmocore.gui.social.friend.EditableFriendRemoval;
@ -20,8 +21,7 @@ public class InventoryManager {
public static final SkillList SKILL_LIST = new SkillList(); public static final SkillList SKILL_LIST = new SkillList();
public static final ClassSelect CLASS_SELECT = new ClassSelect(); public static final ClassSelect CLASS_SELECT = new ClassSelect();
public static final SubclassSelect SUBCLASS_SELECT = new SubclassSelect(); public static final SubclassSelect SUBCLASS_SELECT = new SubclassSelect();
public static final ClassConfirmation CLASS_CONFIRM = new ClassConfirmation(); public static final Map<String, ClassConfirmation> CLASS_CONFIRM = new HashMap<>();
public static final SubclassConfirmation SUBCLASS_CONFIRM = new SubclassConfirmation();
public static final WaypointViewer WAYPOINTS = new WaypointViewer(); public static final WaypointViewer WAYPOINTS = new WaypointViewer();
public static final EditableFriendList FRIEND_LIST = new EditableFriendList(); public static final EditableFriendList FRIEND_LIST = new EditableFriendList();
public static final EditableFriendRemoval FRIEND_REMOVAL = new EditableFriendRemoval(); public static final EditableFriendRemoval FRIEND_REMOVAL = new EditableFriendRemoval();
@ -32,15 +32,39 @@ public class InventoryManager {
public static final QuestViewer QUEST_LIST = new QuestViewer(); public static final QuestViewer QUEST_LIST = new QuestViewer();
public static final AttributeView ATTRIBUTE_VIEW = new AttributeView(); public static final AttributeView ATTRIBUTE_VIEW = new AttributeView();
public static final SkillTreeViewer TREE_VIEW = new SkillTreeViewer(); public static final SkillTreeViewer TREE_VIEW = new SkillTreeViewer();
public static final List<EditableInventory> list = Arrays.asList(PLAYER_STATS, ATTRIBUTE_VIEW, TREE_VIEW,SKILL_LIST, CLASS_SELECT, SUBCLASS_SELECT, SUBCLASS_CONFIRM, QUEST_LIST, WAYPOINTS, CLASS_CONFIRM, FRIEND_LIST, FRIEND_REMOVAL, PARTY_VIEW, PARTY_CREATION, GUILD_VIEW, GUILD_CREATION);
public static final List<EditableInventory> list = new ArrayList(Arrays.asList(PLAYER_STATS, ATTRIBUTE_VIEW, TREE_VIEW, SKILL_LIST, CLASS_SELECT, SUBCLASS_SELECT, QUEST_LIST, WAYPOINTS, FRIEND_LIST, FRIEND_REMOVAL, PARTY_VIEW, PARTY_CREATION, GUILD_VIEW, GUILD_CREATION));
private static List<String> defaultClass = Arrays.asList(new String[]{"human", "mage", "paladin", "warrior", "rogue", "arcane-mage"});
public static void load() { public static void load() {
list.forEach(inv -> { String classConfirmFolder = "gui/class-confirm";
MMOCore.plugin.configManager.loadDefaultFile("gui", inv.getId() + ".yml"); try {
MMOCore.plugin.configManager.loadDefaultFile(classConfirmFolder, "class-confirm-default.yml");
} catch (Exception exception) {
MMOCore.log(Level.WARNING, "Could not load inventory 'class-confirm/class-confirm-default" + "': " + exception.getMessage());
}
for (PlayerClass playerClass : MMOCore.plugin.classManager.getAll()) {
String classId = MMOCoreUtils.ymlName(playerClass.getId());
ConfigFile configFile = new ConfigFile(classConfirmFolder, "class-confirm-" + classId);
ClassConfirmation GUI;
if (configFile.exists())
GUI = new ClassConfirmation(playerClass, false);
else {
GUI = new ClassConfirmation(playerClass, true);
}
CLASS_CONFIRM.put(MMOCoreUtils.ymlName(playerClass.getId()), GUI);
GUI.reload(new ConfigFile("/" +classConfirmFolder, GUI.getId()).getConfig());
}
list.forEach(inv ->
{
String folder = "gui" + (inv instanceof ClassConfirmation ? "/class-confirm" : "");
try { try {
inv.reload(new ConfigFile("/gui", inv.getId()).getConfig()); MMOCore.plugin.configManager.loadDefaultFile(folder, inv.getId() + ".yml");
} catch (IllegalArgumentException exception) { inv.reload(new ConfigFile("/" + folder, inv.getId()).getConfig());
MMOCore.log(Level.WARNING, "Could not load inventory '" + inv.getId() + "': " + exception.getMessage()); } catch (Exception exception) {
MMOCore.log(Level.WARNING, "Could not load inventory '" + (inv instanceof ClassConfirmation ? "class-confirm/" : "") + inv.getId() + "': " + exception.getMessage());
} }
}); });
} }

View File

@ -45,13 +45,13 @@ public abstract class PlayerDataManager {
*/ */
public void unregisterSafe(PlayerData playerData) { public void unregisterSafe(PlayerData playerData) {
// Save data async if required
if (playerData.isFullyLoaded())
Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> saveData(playerData, true));
// Close and unregister data instantly if no error occured // Close and unregister data instantly if no error occured
playerData.close(); playerData.close();
data.remove(playerData.getUniqueId()); data.remove(playerData.getUniqueId());
// Save data async if required
if (playerData.isFullyLoaded())
Bukkit.getScheduler().runTaskAsynchronously(MMOCore.plugin, () -> saveData(playerData, true));
} }
/** /**

View File

@ -113,15 +113,21 @@ public class MMOCoreDataSynchronizer extends DataSynchronizer {
} }
} }
//These should be loaded after to make sure that the MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded. /*
* These should be loaded after to make sure that the
* MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded.
*/
data.setHealth(result.getDouble("health"));
data.setMana(result.getDouble("mana")); data.setMana(result.getDouble("mana"));
data.setStamina(result.getDouble("stamina")); data.setStamina(result.getDouble("stamina"));
data.setStellium(result.getDouble("stellium")); data.setStellium(result.getDouble("stellium"));
double health = result.getDouble("health");
health = health == 0 ? 20 : health;
health = Math.min(health, data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
data.getPlayer().setHealth(health);
if (data.isOnline()) {
double health = data.getHealth();
health = health == 0 ? data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue() : health;
health = Math.max(Math.min(health, data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()), 0);
data.getPlayer().setHealth(health);
}
UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel())); UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel()));
data.setFullyLoaded(); data.setFullyLoaded();

View File

@ -118,14 +118,22 @@ public class YAMLPlayerDataManager extends PlayerDataManager {
MMOCore.log(Level.WARNING, "Could not load class info '" + key + "': " + exception.getMessage()); MMOCore.log(Level.WARNING, "Could not load class info '" + key + "': " + exception.getMessage());
} }
/*
//These should be loaded after to make sure that the MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded. * These should be loaded after to make sure that the
* MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded.
*/
data.setHealth(config.getDouble("health"));
data.setMana(config.contains("mana") ? config.getDouble("mana") : data.getStats().getStat("MAX_MANA")); data.setMana(config.contains("mana") ? config.getDouble("mana") : data.getStats().getStat("MAX_MANA"));
data.setStamina(config.contains("stamina") ? config.getDouble("stamina") : data.getStats().getStat("MAX_STAMINA")); data.setStamina(config.contains("stamina") ? config.getDouble("stamina") : data.getStats().getStat("MAX_STAMINA"));
data.setStellium(config.contains("stellium") ? config.getDouble("stellium") : data.getStats().getStat("MAX_STELLIUM")); data.setStellium(config.contains("stellium") ? config.getDouble("stellium") : data.getStats().getStat("MAX_STELLIUM"));
double health=config.contains("health") ? config.getDouble("health") : data.getStats().getStat("MAX_HEALTH");
health=Math.min(health,data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()); if (data.isOnline()) {
data.getPlayer().setHealth(health); double health = config.contains("health") ? config.getDouble("health") : data.getStats().getStat("MAX_HEALTH");
health = health == 0 ? 20 : health;
health = Math.min(health, data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
data.getPlayer().setHealth(health);
}
data.setFullyLoaded(); data.setFullyLoaded();
} }

View File

@ -22,6 +22,10 @@ public class SkillTreeNode implements ExperienceObject {
private final SkillTree tree; private final SkillTree tree;
private final String name, id; private final String name, id;
private IntegerCoordinates coordinates; private IntegerCoordinates coordinates;
/**
* The number of skill tree points this node requires.
*/
private final int skillTreePointsConsumed;
private boolean isRoot; private boolean isRoot;
/** /**
@ -56,7 +60,8 @@ public class SkillTreeNode implements ExperienceObject {
name = Objects.requireNonNull(config.getString("name"), "Could not find node name"); name = Objects.requireNonNull(config.getString("name"), "Could not find node name");
size = Objects.requireNonNull(config.getInt("size")); size = Objects.requireNonNull(config.getInt("size"));
isRoot = config.getBoolean("is-root", false); isRoot = config.getBoolean("is-root", false);
skillTreePointsConsumed=config.getInt("point-consumed",1);
Validate.isTrue(skillTreePointsConsumed>0,"The skill tree points consumed by a node must be greater than 0.");
if (config.contains("lores")) if (config.contains("lores"))
for (String key : config.getConfigurationSection("lores").getKeys(false)) for (String key : config.getConfigurationSection("lores").getKeys(false))
try { try {
@ -100,6 +105,10 @@ public class SkillTreeNode implements ExperienceObject {
children.add(child); children.add(child);
} }
public int getSkillTreePointsConsumed() {
return skillTreePointsConsumed;
}
public void setCoordinates(IntegerCoordinates coordinates) { public void setCoordinates(IntegerCoordinates coordinates) {
this.coordinates = coordinates; this.coordinates = coordinates;
} }
@ -112,6 +121,7 @@ public class SkillTreeNode implements ExperienceObject {
return softParents.containsKey(parent) || strongParents.containsKey(parent); return softParents.containsKey(parent) || strongParents.containsKey(parent);
} }
public int getMaxLevel() { public int getMaxLevel() {
return maxLevel; return maxLevel;
} }

View File

@ -1,16 +1,6 @@
# GUI display name, used by default # GUI display name, used by default
name: 'Confirmation: {class}' name: 'Confirmation: {class}'
# GUI display name which overrides the default one.
# This can be used to apply custom textures to the GUI
class-specific-name:
mage: "Select Mage"
rogue: "Select Rogue"
marksman: "Select Marksman"
warrior: "Select Warrior"
paladin: "Select Paladin"
# Number of slots in your inventory. Must be # Number of slots in your inventory. Must be
# between 9 and 54 and must be a multiple of 9. # between 9 and 54 and must be a multiple of 9.
slots: 27 slots: 27

View File

@ -7,10 +7,51 @@ name: Class Selection
slots: 27 slots: 27
items: items:
class:
slots: [13,12,14,11,15,10,16] class-rogue:
function: class slots: [11]
name: '&a&lThe {name}' function: class-rogue
name: '&a&lThe Rogue'
hide-flags: true
lore:
- '{lore}'
- ''
- '{attribute-lore}'
class-mage:
slots: [12]
function: class-mage
name: '&a&lThe Mage'
hide-flags: true
lore:
- '{lore}'
- ''
- '{attribute-lore}'
class-marksman:
slots: [13]
function: class-marksman
name: '&a&lThe Marksman'
hide-flags: true
lore:
- '{lore}'
- ''
- '{attribute-lore}'
class-warrior:
slots: [14]
function: class-warrior
name: '&a&lThe Warrior'
hide-flags: true
lore:
- '{lore}'
- ''
- '{attribute-lore}'
class-paladin:
slots: [15]
function: class-paladin
name: '&a&lThe Paladin'
hide-flags: true hide-flags: true
lore: lore:
- '{lore}' - '{lore}'

View File

@ -83,6 +83,7 @@ items:
- '&7Current Level: &6{current-level}' - '&7Current Level: &6{current-level}'
- '&7Max Level: &6{max-level}' - '&7Max Level: &6{max-level}'
- '&7Max Children: &6{max-children}' - '&7Max Children: &6{max-children}'
- '&7Points required: &6{point-consumed}'
- '&7Size: &6{size}' - '&7Size: &6{size}'
- '--------------------' - '--------------------'
- '&7⧆ &6Requirements: ' - '&7⧆ &6Requirements: '

View File

@ -1,21 +0,0 @@
# GUI display name
name: Subclass Confirmation
# Number of slots in your inventory. Must be
# between 9 and 54 and must be a multiple of 9.
slots: 27
items:
yes:
slots: [12]
item: GREEN_TERRACOTTA
function: 'yes'
name: '&aSelect {class}'
lore: {}
back:
slots: [14]
item: RED_TERRACOTTA
function: back
name: '&aBack'
lore: {}

View File

@ -13,10 +13,10 @@ items:
item: RED_STAINED_GLASS_PANE item: RED_STAINED_GLASS_PANE
name: '&aBack to Class Selection' name: '&aBack to Class Selection'
lore: [] lore: []
class: arcane-mage:
slots: [13,12,14,11,15,10,16] slots: [13]
function: class function: sub-class-arcane-mage
name: '&a&lThe {name}' name: '&a&lThe Arcane Mage'
lore: lore:
- '{lore}' - '{lore}'
- '' - ''

View File

@ -215,7 +215,7 @@ no-skill-tree-points-spent: '&cYou have not spent any skill tree points.'
locked-node: '&cThis skill is locked!' locked-node: '&cThis skill is locked!'
upgrade-skill-node: '&eYour skill node &6{skill-node} &eis now Level &6{level}&e!' upgrade-skill-node: '&eYour skill node &6{skill-node} &eis now Level &6{level}&e!'
skill-node-max-level-hit: '&cYou already hit the max level for that skill node.' skill-node-max-level-hit: '&cYou already hit the max level for that skill node.'
not-enough-skill-tree-points: '&cYou need one skill tree point.' not-enough-skill-tree-points: '&cYou need {point} skill tree point.'
reallocated-points: '&eYou successfully reset the skill tree {skill-tree}. &eYou now have &6{points} &eskill tree points.' reallocated-points: '&eYou successfully reset the skill tree {skill-tree}. &eYou now have &6{points} &eskill tree points.'
not-skill-tree-reallocation-point: '&cYou do not have 1 skill tree reallocation point.' not-skill-tree-reallocation-point: '&cYou do not have 1 skill tree reallocation point.'
no-skill-tree: '&cYour class doesn''t have any skill tree.' no-skill-tree: '&cYour class doesn''t have any skill tree.'

View File

@ -15,6 +15,7 @@ nodes:
max-level: 1 max-level: 1
is-root: true is-root: true
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_cooldown_reduction5 experience-table: skilltree_cooldown_reduction5
lores: lores:
0: 0:
@ -27,6 +28,7 @@ nodes:
a2: a2:
name: 'Cooldown Reduction' name: 'Cooldown Reduction'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_cooldown_reduction10 experience-table: skilltree_cooldown_reduction10
coordinates: coordinates:
@ -41,6 +43,7 @@ nodes:
a3: a3:
name: 'Cooldown Reduction' name: 'Cooldown Reduction'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_cooldown_reduction15 experience-table: skilltree_cooldown_reduction15
coordinates: coordinates:
@ -57,6 +60,7 @@ nodes:
b1: b1:
name: 'Critical Strike Chance' name: 'Critical Strike Chance'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_critical_strike_chance1 experience-table: skilltree_critical_strike_chance1
coordinates: coordinates:
@ -71,6 +75,7 @@ nodes:
b2: b2:
name: 'Critical Strike Chance' name: 'Critical Strike Chance'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_critical_strike_chance2 experience-table: skilltree_critical_strike_chance2
coordinates: coordinates:
@ -85,6 +90,7 @@ nodes:
b3: b3:
name: 'Critical Strike Chance' name: 'Critical Strike Chance'
size: 1 size: 1
point-consumed: 1
max-children: 2 max-children: 2
experience-table: skilltree_critical_strike_chance3 experience-table: skilltree_critical_strike_chance3
coordinates: coordinates:
@ -101,6 +107,7 @@ nodes:
c1: c1:
name: 'Life Steal' name: 'Life Steal'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_lifesteal1 experience-table: skilltree_lifesteal1
coordinates: coordinates:
@ -115,6 +122,7 @@ nodes:
c2: c2:
name: 'Life Steal' name: 'Life Steal'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_lifesteal2 experience-table: skilltree_lifesteal2
coordinates: coordinates:
@ -129,6 +137,7 @@ nodes:
c3: c3:
name: 'Life Steal' name: 'Life Steal'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_lifesteal2 experience-table: skilltree_lifesteal2
coordinates: coordinates:
@ -145,6 +154,7 @@ nodes:
d1: d1:
name: 'Damage Reduction' name: 'Damage Reduction'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_damage_reduction1 experience-table: skilltree_damage_reduction1
coordinates: coordinates:
@ -159,6 +169,7 @@ nodes:
d2: d2:
name: 'Damage Reduction' name: 'Damage Reduction'
size: 1 size: 1
point-consumed: 1
max-children: 2 max-children: 2
experience-table: skilltree_damage_reduction2 experience-table: skilltree_damage_reduction2
coordinates: coordinates:
@ -173,6 +184,7 @@ nodes:
d3: d3:
name: 'Damage Reduction' name: 'Damage Reduction'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_damage_reduction2 experience-table: skilltree_damage_reduction2
coordinates: coordinates:
@ -189,6 +201,7 @@ nodes:
e1: e1:
name: 'Health Regeneration' name: 'Health Regeneration'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_health_regeneration1 experience-table: skilltree_health_regeneration1
coordinates: coordinates:
@ -203,6 +216,7 @@ nodes:
e2: e2:
name: 'Health Regeneration' name: 'Health Regeneration'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_health_regeneration2 experience-table: skilltree_health_regeneration2
coordinates: coordinates:
@ -217,6 +231,7 @@ nodes:
e3: e3:
name: 'Health Regeneration' name: 'Health Regeneration'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_health_regeneration2 experience-table: skilltree_health_regeneration2
coordinates: coordinates:
@ -233,6 +248,7 @@ nodes:
f1: f1:
name: 'Mana Regeneration' name: 'Mana Regeneration'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_mana_regeneration1 experience-table: skilltree_mana_regeneration1
coordinates: coordinates:
@ -247,6 +263,7 @@ nodes:
f2: f2:
name: 'Mana Regeneration' name: 'Mana Regeneration'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_mana_regeneration2 experience-table: skilltree_mana_regeneration2
coordinates: coordinates:
@ -261,6 +278,7 @@ nodes:
f3: f3:
name: 'Mana Regeneration' name: 'Mana Regeneration'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_mana_regeneration2 experience-table: skilltree_mana_regeneration2
coordinates: coordinates:
@ -277,6 +295,7 @@ nodes:
g1: g1:
name: 'Magic Damage' name: 'Magic Damage'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_magic_damage1 experience-table: skilltree_magic_damage1
coordinates: coordinates:
@ -291,6 +310,7 @@ nodes:
g2: g2:
name: 'Magic Damage' name: 'Magic Damage'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_magic_damage2 experience-table: skilltree_magic_damage2
coordinates: coordinates:
@ -305,6 +325,7 @@ nodes:
g3: g3:
name: 'Magic Damage' name: 'Magic Damage'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_magic_damage2 experience-table: skilltree_magic_damage2
coordinates: coordinates:
@ -321,6 +342,7 @@ nodes:
h1: h1:
name: 'Max Health' name: 'Max Health'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_max_health2 experience-table: skilltree_max_health2
coordinates: coordinates:
@ -335,6 +357,7 @@ nodes:
h2: h2:
name: 'Max Health' name: 'Max Health'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_max_health4 experience-table: skilltree_max_health4
coordinates: coordinates:
@ -349,6 +372,7 @@ nodes:
h3: h3:
name: 'Max Health' name: 'Max Health'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_max_health4 experience-table: skilltree_max_health4
coordinates: coordinates:
@ -365,6 +389,7 @@ nodes:
j1: j1:
name: 'Weapon Damage' name: 'Weapon Damage'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_weapon_damage2 experience-table: skilltree_weapon_damage2
coordinates: coordinates:
@ -379,6 +404,7 @@ nodes:
j2: j2:
name: 'Weapon Damage' name: 'Weapon Damage'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_weapon_damage4 experience-table: skilltree_weapon_damage4
coordinates: coordinates:
@ -393,6 +419,7 @@ nodes:
j3: j3:
name: 'Weapon Damage' name: 'Weapon Damage'
size: 1 size: 1
point-consumed: 1
max-children: 1 max-children: 1
experience-table: skilltree_weapon_damage4 experience-table: skilltree_weapon_damage4
coordinates: coordinates:

View File

@ -18,6 +18,7 @@ nodes:
max-level: 1 max-level: 1
is-root: true is-root: true
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_mana_regeneration1 experience-table: skilltree_mana_regeneration1
lores: lores:
0: 0:
@ -36,6 +37,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_mana_regeneration2 experience-table: skilltree_mana_regeneration2
lores: lores:
0: 0:
@ -54,6 +57,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_mana_regeneration2 experience-table: skilltree_mana_regeneration2
lores: lores:
0: 0:
@ -71,6 +76,8 @@ nodes:
max-level: 1 max-level: 1
is-root: true is-root: true
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_health_regeneration1 experience-table: skilltree_health_regeneration1
lores: lores:
0: 0:
@ -90,6 +97,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_health_regeneration2 experience-table: skilltree_health_regeneration2
lores: lores:
0: 0:
@ -109,6 +118,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_health_regeneration2 experience-table: skilltree_health_regeneration2
lores: lores:
0: 0:
@ -126,6 +137,8 @@ nodes:
max-level: 1 max-level: 1
is-root: true is-root: true
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_cooldown_reduction5 experience-table: skilltree_cooldown_reduction5
lores: lores:
0: 0:
@ -145,6 +158,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_cooldown_reduction10 experience-table: skilltree_cooldown_reduction10
lores: lores:
0: 0:
@ -164,6 +179,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_cooldown_reduction15 experience-table: skilltree_cooldown_reduction15
lores: lores:
0: 0:
@ -186,6 +203,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_critical_strike_chance1 experience-table: skilltree_critical_strike_chance1
lores: lores:
0: 0:
@ -205,6 +224,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_critical_strike_chance2 experience-table: skilltree_critical_strike_chance2
lores: lores:
0: 0:
@ -224,6 +245,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_critical_strike_chance5 experience-table: skilltree_critical_strike_chance5
lores: lores:
0: 0:
@ -245,6 +268,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_damage_reduction1 experience-table: skilltree_damage_reduction1
lores: lores:
0: 0:
@ -264,6 +289,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_damage_reduction2 experience-table: skilltree_damage_reduction2
lores: lores:
0: 0:
@ -283,6 +310,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_damage_reduction2 experience-table: skilltree_damage_reduction2
lores: lores:
0: 0:
@ -303,6 +332,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_weapon_damage1 experience-table: skilltree_weapon_damage1
lores: lores:
0: 0:
@ -322,6 +353,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_weapon_damage2 experience-table: skilltree_weapon_damage2
lores: lores:
0: 0:
@ -341,6 +374,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_weapon_damage2 experience-table: skilltree_weapon_damage2
lores: lores:
0: 0:
@ -362,6 +397,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_lifesteal3 experience-table: skilltree_lifesteal3
lores: lores:
0: 0:
@ -382,6 +419,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_max_health5 experience-table: skilltree_max_health5
lores: lores:
0: 0:
@ -401,6 +440,8 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
point-consumed: 1
experience-table: skilltree_magic_damage3 experience-table: skilltree_magic_damage3
lores: lores:
0: 0:

View File

@ -18,6 +18,7 @@ nodes:
max-level: 1 max-level: 1
is-root: true is-root: true
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_mana_regeneration1 experience-table: skilltree_mana_regeneration1
lores: lores:
0: 0:
@ -36,6 +37,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_mana_regeneration2 experience-table: skilltree_mana_regeneration2
lores: lores:
0: 0:
@ -54,6 +56,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_mana_regeneration2 experience-table: skilltree_mana_regeneration2
lores: lores:
0: 0:
@ -75,6 +78,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_skill_damage5 experience-table: skilltree_skill_damage5
lores: lores:
0: 0:
@ -93,6 +97,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_skill_damage5 experience-table: skilltree_skill_damage5
lores: lores:
0: 0:
@ -111,6 +116,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_skill_damage10 experience-table: skilltree_skill_damage10
lores: lores:
0: 0:
@ -132,6 +138,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_spell_vampirism2 experience-table: skilltree_spell_vampirism2
lores: lores:
0: 0:
@ -150,6 +157,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_spell_vampirism2 experience-table: skilltree_spell_vampirism2
lores: lores:
0: 0:
@ -168,6 +176,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_spell_vampirism6 experience-table: skilltree_spell_vampirism6
lores: lores:
0: 0:
@ -189,6 +198,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_additional_experience2 experience-table: skilltree_additional_experience2
lores: lores:
0: 0:
@ -207,6 +217,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_additional_experience3 experience-table: skilltree_additional_experience3
lores: lores:
0: 0:
@ -225,6 +236,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_additional_experience5 experience-table: skilltree_additional_experience5
lores: lores:
0: 0:
@ -246,6 +258,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_magic_damage_reduction5 experience-table: skilltree_magic_damage_reduction5
lores: lores:
0: 0:
@ -264,6 +277,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_magic_damage_reduction5 experience-table: skilltree_magic_damage_reduction5
lores: lores:
0: 0:
@ -282,6 +296,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_magic_damage_reduction10 experience-table: skilltree_magic_damage_reduction10
lores: lores:
0: 0:
@ -303,6 +318,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_skill_critical_strike_chance5 experience-table: skilltree_skill_critical_strike_chance5
lores: lores:
0: 0:
@ -321,6 +337,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_skill_critical_strike_chance10 experience-table: skilltree_skill_critical_strike_chance10
lores: lores:
0: 0:
@ -339,6 +356,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_skill_critical_strike_chance15 experience-table: skilltree_skill_critical_strike_chance15
lores: lores:
0: 0:
@ -360,6 +378,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_magic_damage1 experience-table: skilltree_magic_damage1
lores: lores:
0: 0:
@ -378,6 +397,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_magic_damage2 experience-table: skilltree_magic_damage2
lores: lores:
0: 0:
@ -396,6 +416,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_magic_damage2 experience-table: skilltree_magic_damage2
lores: lores:
0: 0:

View File

@ -18,6 +18,7 @@ nodes:
max-level: 1 max-level: 1
is-root: true is-root: true
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_additional_experience2 experience-table: skilltree_additional_experience2
lores: lores:
0: 0:
@ -36,6 +37,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_additional_experience3 experience-table: skilltree_additional_experience3
lores: lores:
0: 0:
@ -54,6 +56,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_additional_experience5 experience-table: skilltree_additional_experience5
lores: lores:
0: 0:
@ -75,6 +78,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_arrow_velocity10 experience-table: skilltree_arrow_velocity10
lores: lores:
0: 0:
@ -93,6 +97,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_arrow_velocity15 experience-table: skilltree_arrow_velocity15
lores: lores:
0: 0:
@ -111,6 +116,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_arrow_velocity25 experience-table: skilltree_arrow_velocity25
lores: lores:
0: 0:
@ -132,6 +138,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_lifesteal1 experience-table: skilltree_lifesteal1
lores: lores:
0: 0:
@ -150,6 +157,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_lifesteal2 experience-table: skilltree_lifesteal2
lores: lores:
0: 0:
@ -168,6 +176,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_lifesteal2 experience-table: skilltree_lifesteal2
lores: lores:
0: 0:
@ -189,6 +198,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_knockback_resistance5 experience-table: skilltree_knockback_resistance5
lores: lores:
0: 0:
@ -207,6 +217,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_knockback_resistance5 experience-table: skilltree_knockback_resistance5
lores: lores:
0: 0:
@ -225,6 +236,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_knockback_resistance10 experience-table: skilltree_knockback_resistance10
lores: lores:
0: 0:
@ -246,6 +258,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_critical_strike_chance2 experience-table: skilltree_critical_strike_chance2
lores: lores:
0: 0:
@ -264,6 +277,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_critical_strike_chance3 experience-table: skilltree_critical_strike_chance3
lores: lores:
0: 0:
@ -282,6 +296,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_critical_strike_chance5 experience-table: skilltree_critical_strike_chance5
lores: lores:
0: 0:
@ -303,6 +318,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_movement_speed2 experience-table: skilltree_movement_speed2
lores: lores:
0: 0:
@ -321,6 +337,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_movement_speed2 experience-table: skilltree_movement_speed2
lores: lores:
0: 0:
@ -339,6 +356,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_movement_speed6 experience-table: skilltree_movement_speed6
lores: lores:
0: 0:
@ -360,6 +378,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_projectile_damage2 experience-table: skilltree_projectile_damage2
lores: lores:
0: 0:
@ -378,6 +397,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_projectile_damage2 experience-table: skilltree_projectile_damage2
lores: lores:
0: 0:
@ -396,6 +416,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_projectile_damage6 experience-table: skilltree_projectile_damage6
lores: lores:
0: 0:

View File

@ -18,6 +18,7 @@ nodes:
max-level: 1 max-level: 1
is-root: true is-root: true
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_attack_speed5 experience-table: skilltree_attack_speed5
lores: lores:
0: 0:
@ -36,6 +37,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_attack_speed10 experience-table: skilltree_attack_speed10
lores: lores:
0: 0:
@ -54,6 +56,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_attack_speed15 experience-table: skilltree_attack_speed15
lores: lores:
0: 0:
@ -75,6 +78,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_health_regeneration1 experience-table: skilltree_health_regeneration1
lores: lores:
0: 0:
@ -93,6 +97,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_health_regeneration2 experience-table: skilltree_health_regeneration2
lores: lores:
0: 0:
@ -111,6 +116,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_health_regeneration2 experience-table: skilltree_health_regeneration2
lores: lores:
0: 0:
@ -132,6 +138,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_physical_damage_reduction5 experience-table: skilltree_physical_damage_reduction5
lores: lores:
0: 0:
@ -150,6 +157,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_physical_damage_reduction10 experience-table: skilltree_physical_damage_reduction10
lores: lores:
0: 0:
@ -168,6 +176,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_physical_damage_reduction15 experience-table: skilltree_physical_damage_reduction15
lores: lores:
0: 0:
@ -189,6 +198,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_parry_rating5 experience-table: skilltree_parry_rating5
lores: lores:
0: 0:
@ -207,6 +217,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_parry_rating5 experience-table: skilltree_parry_rating5
lores: lores:
0: 0:
@ -225,6 +236,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_parry_rating10 experience-table: skilltree_parry_rating10
lores: lores:
0: 0:
@ -246,6 +258,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_knockback_resistance5 experience-table: skilltree_knockback_resistance5
lores: lores:
0: 0:
@ -264,6 +277,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_knockback_resistance5 experience-table: skilltree_knockback_resistance5
lores: lores:
0: 0:
@ -282,6 +296,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_knockback_resistance10 experience-table: skilltree_knockback_resistance10
lores: lores:
0: 0:
@ -303,6 +318,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_dodge_rating2 experience-table: skilltree_dodge_rating2
lores: lores:
0: 0:
@ -321,6 +337,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_dodge_rating3 experience-table: skilltree_dodge_rating3
lores: lores:
0: 0:
@ -339,6 +356,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_dodge_rating5 experience-table: skilltree_dodge_rating5
lores: lores:
0: 0:
@ -360,6 +378,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_weapon_damage1 experience-table: skilltree_weapon_damage1
lores: lores:
0: 0:
@ -378,6 +397,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_weapon_damage2 experience-table: skilltree_weapon_damage2
lores: lores:
0: 0:
@ -396,6 +416,7 @@ nodes:
max-level: 1 max-level: 1
size: 1 size: 1
point-consumed: 1
experience-table: skilltree_weapon_damage2 experience-table: skilltree_weapon_damage2
lores: lores:
0: 0:

View File

@ -27,3 +27,27 @@ permissions:
mmocore.class-select: mmocore.class-select:
description: Access to /class description: Access to /class
default: op default: op
mmocore.attributes:
description: Access to /attributes
default: true
mmocore.skills:
description: Access to /skills
default: true
mmocore.profile:
description: Access to /profile
default: true
mmocore.friends:
description: Access to /friends
default: true
mmocore.guild:
description: Access to /guild
default: true
mmocore.party:
description: Access to /party
default: true
mmocore.skilltrees:
description: Access to /skilltrees
default: true
mmocore.quests:
description: Access to /quests
default: true

View File

@ -13,7 +13,7 @@ And then add MMOCore-API as dependency
<dependency> <dependency>
<groupId>net.Indyuce</groupId> <groupId>net.Indyuce</groupId>
<artifactId>MMOCore-API</artifactId> <artifactId>MMOCore-API</artifactId>
<version>1.12.0-SNAPSHOT</version> <version>1.12-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
``` ```

View File

@ -3,3 +3,5 @@ files:
translation: /**/MMOCore-Dist/src/main/resources/default/translation/%language%/gui/%file_name%.%file_extension% translation: /**/MMOCore-Dist/src/main/resources/default/translation/%language%/gui/%file_name%.%file_extension%
- source: MMOCore-Dist/src/main/resources/default/messages.yml - source: MMOCore-Dist/src/main/resources/default/messages.yml
translation: /**/MMOCore-Dist/src/main/resources/default/translation/%language%/%file_name%.%file_extension% translation: /**/MMOCore-Dist/src/main/resources/default/translation/%language%/%file_name%.%file_extension%
- source: MMOCore-Dist/src/main/resources/default/gui/class-confirm/*.yml
translation: /**/MMOCore-Dist/src/main/resources/default/translation/%language%/gui/class-confirm/%file_name%.%file_extension%