Skill Tree.

This commit is contained in:
Ka0rX 2022-08-18 14:27:22 +02:00
parent fbba7ff034
commit 467d9263c4
11 changed files with 156 additions and 190 deletions

View File

@ -211,19 +211,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
return nodeLevelsString.entrySet();
}
public void removeModifiersFrom(SkillTree skillTree) {
for (SkillTreeNode node : skillTree.getNodes()) {
for (int i = 0; i < node.getMaxLevel(); i++) {
List<PlayerModifier> modifiers = node.getModifiers(i);
if (modifiers != null) {
for (PlayerModifier modifier : modifiers) {
modifier.unregister(getMMOPlayerData());
}
}
}
}
}
public boolean canIncrementNodeLevel(SkillTreeNode node) {
NodeState nodeState = nodeStates.get(node);
//Check the State of the node
@ -238,21 +225,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
*/
public <T extends SkillTree> void incrementNodeLevel(SkillTreeNode node) {
setNodeLevel(node, getNodeLevel(node) + 1);
//Triggers the triggers of the node
List<Trigger> triggers = node.getTriggers(getNodeLevel(node));
if (triggers != null) {
for (Trigger trigger : triggers) {
trigger.apply(this);
}
}
//Applies player modifiers
List<PlayerModifier> modifiers = node.getModifiers(getNodeLevel(node));
if (modifiers != null)
for (PlayerModifier modifier : modifiers) {
modifier.register(getMMOPlayerData());
}
//Claims the nodes experience table.
node.getExperienceTable().claim(this,getNodeLevel(node),node);
if (nodeStates.get(node) == NodeState.UNLOCKABLE)
setNodeState(node, NodeState.UNLOCKED);

View File

@ -28,6 +28,7 @@ public class AdminCommandTreeNode extends CommandTreeNode {
addChild(new PointsCommandTreeNode("attr-realloc", this, PlayerData::setAttributeReallocationPoints, PlayerData::giveAttributeReallocationPoints, PlayerData::getAttributeReallocationPoints));
addChild(new PointsCommandTreeNode("skill-realloc", this, PlayerData::setSkillReallocationPoints, PlayerData::giveSkillReallocationPoints, PlayerData::getSkillReallocationPoints));
addChild(new PointsCommandTreeNode("skill-tree-realloc", this, PlayerData::setSkillTreeReallocationPoints, PlayerData::giveSkillTreeReallocationPoints, PlayerData::getSkillTreeReallocationPoints));
addChild(new SkillTreePointsCommandTreeNode(this,(playerData, integer, s) -> playerData.setSkillTreePoints(s,integer),(playerData, integer, s) -> playerData.giveSkillTreePoints(s,integer),((playerData, s) -> playerData.getSkillTreePoint(s))));
for (PlayerResource res : PlayerResource.values())
addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
}

View File

@ -10,6 +10,7 @@ import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot;
import net.Indyuce.mmocore.util.TriConsumer;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -88,10 +89,6 @@ public class ExperienceCommandTreeNode extends CommandTreeNode {
}
}
@FunctionalInterface
interface TriConsumer<A, B, C> {
void accept(A a, B b, C c);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {

View File

@ -8,6 +8,7 @@ import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.util.TriConsumer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@ -85,10 +86,6 @@ public class LevelCommandTreeNode extends CommandTreeNode {
}
}
@FunctionalInterface
interface TriConsumer<A, B, C> {
void accept(A a, B b, C c);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {

View File

@ -2,10 +2,10 @@ package net.Indyuce.mmocore.command.rpg.admin;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import io.lumine.mythic.utils.functions.TriConsumer;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.util.TriConsumer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;

View File

@ -15,6 +15,7 @@ import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
import net.Indyuce.mmocore.tree.IntegerCoordinates;
import net.Indyuce.mmocore.tree.SkillTreeNode;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
@ -26,6 +27,7 @@ import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class SkillTreeViewer extends EditableInventory {
@ -159,19 +161,25 @@ public class SkillTreeViewer extends EditableInventory {
*/
@Override
public ItemStack display(SkillTreeInventory inv, int n) {
int slot = getSlots().get(n);
int deltaX = (slot - inv.getMinSlot()) % 9;
int deltaY = (slot - inv.getMinSlot()) / 9;
IntegerCoordinates coordinates = new IntegerCoordinates(inv.getX() + deltaX, inv.getY() + deltaY);
IntegerCoordinates coordinates = inv.getCoordinates(n);
if (inv.getSkillTree().isNode(coordinates) || inv.getSkillTree().isPath(coordinates)) {
Icon icon = inv.getPlayerData().getIcon(inv.getSkillTree(), coordinates);
ItemStack item = super.display(inv, n, icon.getMaterial(), icon.getCustomModelData());
ItemMeta meta = item.getItemMeta();
if (inv.getSkillTree().isNode(coordinates)) {
SkillTreeNode node = inv.getSkillTree().getNode(coordinates);
List<String> lore = new ArrayList<>(node.getLore(inv.getPlayerData()));
lore.add("");
getLore().forEach(str -> lore.add(MythicLib.plugin.parseColors(getPlaceholders(inv, n).apply(inv.getPlayer(), str))));
List<String> lore = new ArrayList<>();
getLore().forEach(str -> {
if (str.contains("{node-lore}")) {
lore.addAll(node.getLore(inv.getPlayerData()));
} else if (str.contains("{strong-parents}")) {
lore.addAll(getParentsLore(inv, node, node.getStrongParents()));
} else if (str.contains("{soft-parents}")) {
lore.addAll(getParentsLore(inv, node, node.getSoftParents()));
} else
lore.add(getPlaceholders(inv, n).apply(inv.getPlayer(), str));
});
meta.setLore(lore);
meta.setDisplayName(node.getName());
}
@ -191,10 +199,32 @@ public class SkillTreeViewer extends EditableInventory {
}
/**
* Soft&Strong children lore for the node
*/
public List<String> getParentsLore(SkillTreeInventory inv, SkillTreeNode node, Collection<SkillTreeNode> parents) {
List<String> lore = new ArrayList<>();
for (SkillTreeNode parent : parents) {
int level = inv.getPlayerData().getNodeLevel(parent);
ChatColor color = level >= node.getParentNeededLevel(parent) ? ChatColor.GREEN : ChatColor.RED;
lore.add(ChatColor.GRAY + "" + parent.getName() + ": " + color + node.getParentNeededLevel(parent));
}
return lore;
}
@Override
public Placeholders getPlaceholders(SkillTreeInventory inv, int n) {
Placeholders holders = new Placeholders();
holders.register("skill-tree", inv.getSkillTree().getName());
if (inv.getSkillTree().isNode(inv.getCoordinates(n))) {
SkillTreeNode node = inv.getNode(n);
holders.register("current-level", inv.getPlayerData().getNodeLevel(node));
holders.register("current-state", inv.getPlayerData().getNodeState(node));
holders.register("max-level", node.getMaxLevel());
holders.register("max-children", node.getMaxChildren());
holders.register("size", node.getSize());
}
holders.register("skill-tree-points", inv.getPlayerData().getSkillTreePoint(inv.getSkillTree().getId()));
holders.register("global-points", inv.getPlayerData().getSkillTreePoint("global"));
return holders;
@ -210,6 +240,7 @@ public class SkillTreeViewer extends EditableInventory {
private int treeListPage;
private final int maxTreeListPage;
private final SkillTree skillTree;
private final List<Integer> slots;
public SkillTreeInventory(PlayerData playerData, EditableInventory editable) {
super(playerData, editable);
@ -217,7 +248,7 @@ public class SkillTreeViewer extends EditableInventory {
skillTree = playerData.getOpenedSkillTree();
maxTreeListPage = (MMOCore.plugin.skillTreeManager.getAll().size() - 1) / editable.getByFunction("skill-tree").getSlots().size();
//We get the width and height of the GUI(corresponding to the slots given)
List<Integer> slots = editable.getByFunction("skill-tree-node").getSlots();
slots = editable.getByFunction("skill-tree-node").getSlots();
minSlot = 64;
maxSlot = 0;
for (int slot : slots) {
@ -254,6 +285,19 @@ public class SkillTreeViewer extends EditableInventory {
return getEditable().getName().replace("{skill-tree-name}", skillTree.getName()).replace("{skill-tree-id}", skillTree.getId());
}
public IntegerCoordinates getCoordinates(int n) {
int slot = slots.get(n);
int deltaX = (slot - getMinSlot()) % 9;
int deltaY = (slot - getMinSlot()) / 9;
IntegerCoordinates coordinates = new IntegerCoordinates(getX() + deltaX, getY() + deltaY);
return coordinates;
}
public SkillTreeNode getNode(int n) {
return getSkillTree().getNode(getCoordinates(n));
}
public SkillTree getSkillTree() {
return skillTree;
}
@ -292,8 +336,6 @@ public class SkillTreeViewer extends EditableInventory {
//We remove all the nodeStates progress
playerData.giveSkillTreePoints(skillTree.getId(), reallocated);
playerData.giveSkillTreeReallocationPoints(-1);
//We unregister all the modifiers or the player
playerData.removeModifiersFrom(skillTree);
for (SkillTreeNode node : skillTree.getNodes()) {
playerData.setNodeLevel(node, 0);
playerData.setNodeState(node, NodeState.LOCKED);
@ -323,16 +365,14 @@ public class SkillTreeViewer extends EditableInventory {
if (event.getClickType() == ClickType.RIGHT) {
int offset = event.getSlot();
int xOffset=offset%9-middleSlot%9;
int yOffset=offset/9-middleSlot/9;
int xOffset = offset % 9 - middleSlot % 9;
int yOffset = offset / 9 - middleSlot / 9;
x += xOffset;
y += yOffset-1;
y += yOffset - 1;
open();
event.setCancelled(true);
return;
}
else if (event.getClickType() == ClickType.LEFT) {
} else if (event.getClickType() == ClickType.LEFT) {
PersistentDataContainer container = event.getItemStack().getItemMeta().getPersistentDataContainer();
int x = container.get(new NamespacedKey(MMOCore.plugin, "coordinates.x"), PersistentDataType.INTEGER);
int y = container.get(new NamespacedKey(MMOCore.plugin, "coordinates.y"), PersistentDataType.INTEGER);

View File

@ -1,26 +1,26 @@
package net.Indyuce.mmocore.tree;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.player.modifier.PlayerModifier;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.ExpCurve;
import net.Indyuce.mmocore.experience.ExperienceObject;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.player.Unlockable;
import net.Indyuce.mmocore.tree.skilltree.AutomaticSkillTree;
import net.Indyuce.mmocore.tree.skilltree.SkillTree;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.logging.Level;
//We must use generics to get the type of the corresponding tree
public class SkillTreeNode implements Unlockable {
public class SkillTreeNode implements Unlockable, ExperienceObject {
private final SkillTree tree;
private final String name, id;
private IntegerCoordinates coordinates;
@ -29,11 +29,9 @@ public class SkillTreeNode implements Unlockable {
/**
* The lore corresponding to each level
*/
private final HashMap<NodeContext, List<String>> lores = new HashMap<>();
private final List<String> lore = new ArrayList<>();
//TODO modifiers depending on level with drop tables
private final HashMap<Integer, List<PlayerModifier>> modifiers = new HashMap<>();
private final HashMap<Integer, List<Trigger>> triggers = new HashMap<>();
private final ExperienceTable experienceTable;
//The max level the skill tree node can have and the max amount of children it can have.
private final int maxLevel, maxChildren, size;
@ -55,56 +53,10 @@ public class SkillTreeNode implements Unlockable {
name = Objects.requireNonNull(config.getString("name"), "Could not find node name");
size = Objects.requireNonNull(config.getInt("size"));
isRoot = config.getBoolean("is-root", false);
//We initialize the value of the lore for each skill tree node.
for (String state : Objects.requireNonNull(config.getConfigurationSection("lores")).getKeys(false)) {
NodeState nodeState = NodeState.valueOf(UtilityMethods.enumName(state));
if (nodeState == NodeState.UNLOCKED) {
//TODO: Message could'nt load ... instead of exce/*99+*-*99**9+-ption
ConfigurationSection section = config.getConfigurationSection("lores." + state);
for (String level : section.getKeys(false))
lores.put(new NodeContext(nodeState, Integer.parseInt(level)), section.getStringList(level));
} else {
lores.put(new NodeContext(nodeState, 0), config.getStringList("lores." + state));
}
}
//We load the triggers
if (config.contains("triggers")) {
try {
ConfigurationSection section = config.getConfigurationSection("triggers");
for (String levelFormat : section.getKeys(false)) {
final int level = Integer.parseInt(levelFormat);
final List<Trigger> triggers = new ArrayList<>();
for (String str : section.getStringList(levelFormat))
triggers.add(MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(str)));
this.triggers.put(level, triggers);
}
} catch (NumberFormatException e) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Couldn't load triggers for skill node " + tree.getId() + "." + id + " : Problem with the Number Format.");
}
}
//We load the player Modifiers
if (config.contains("modifiers")) {
try {
ConfigurationSection section = config.getConfigurationSection("modifiers");
for (String level : section.getKeys(false)) {
int value = Integer.parseInt(level);
for (String str : section.getStringList(level)) {
PlayerModifier modifier = MythicLib.plugin.getModifiers().loadPlayerModifier(new MMOLineConfig(str));
if (!modifiers.containsKey(value)) {
modifiers.put(value, new ArrayList<>());
}
modifiers.get(value).add(modifier);
}
}
} catch (NumberFormatException e) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Couldn't load modifiers for the skill node " + tree.getId() + "." + id + " :Problem with the Number Format.");
}
}
lore.addAll(config.getStringList("lore"));
String expTableId = config.getString("experience-table");
Validate.notNull(expTableId, "You must specify an exp table for " + getFullId() + ".");
this.experienceTable = MMOCore.plugin.experience.getTableOrThrow(expTableId);
maxLevel = config.contains("max-level") ? config.getInt("max-level") : 1;
@ -116,15 +68,6 @@ public class SkillTreeNode implements Unlockable {
}
}
/*
if (config.contains("modifiers")) {
for (String key : config.getConfigurationSection("modifiers").getKeys(false)) {
PlayerModifier mod = MythicLib.plugin.getModifiers().loadPlayerModifier(new ConfigSectionObject(config.getConfigurationSection(key)));
modifiers.put(1, mod);
}
}
*/
public SkillTree getTree() {
return tree;
@ -205,12 +148,26 @@ public class SkillTreeNode implements Unlockable {
return coordinates;
}
public List<PlayerModifier> getModifiers(int level) {
return modifiers.get(level);
@Override
public String getKey() {
return "skill_tree_node:" + getFullId().replace("-", "_");
}
public List<Trigger> getTriggers(int level) {
return triggers.get(level);
@Nullable
@Override
public ExpCurve getExpCurve() {
throw new RuntimeException("Attributes don't have experience");
}
@Override
@NotNull
public ExperienceTable getExperienceTable() {
return Objects.requireNonNull(experienceTable);
}
@Override
public boolean hasExperienceTable() {
return experienceTable != null;
}
@Override
@ -239,60 +196,13 @@ public class SkillTreeNode implements Unlockable {
holders.register("level", playerData.getNodeLevel(this));
holders.register("max-level", getMaxLevel());
holders.register("max-children", getMaxChildren());
//List of all the children of the node
String str = "";
for (SkillTreeNode node : getChildren())
str += node.getName() + ",";
//We remove the last comma
if (str.length() != 0)
str = str.substring(0, str.length() - 1);
holders.register("children", str);
//list of parents with the level needed for each of them
str = "";
for (SkillTreeNode node : getSoftParents())
str += node.getName() + " " + MMOCoreUtils.toRomanNumerals(getParentNeededLevel(node)) + ",";
//We remove the last comma
if (str.length() != 0)
str = str.substring(0, str.length() - 1);
holders.register("soft-parents-level", str);
//list of parents
str = "";
for (SkillTreeNode node : getSoftParents())
str += node.getName() + ",";
//We remove the last comma
if (str.length() != 0)
str = str.substring(0, str.length() - 1);
holders.register("soft-parents", str);
//list of parents with the level needed for each of them
str = "";
for (SkillTreeNode node : getStrongParents())
str += node.getName() + " " + MMOCoreUtils.toRomanNumerals(getParentNeededLevel(node)) + ",";
//We remove the last comma
if (str.length() != 0)
str = str.substring(0, str.length() - 1);
holders.register("strong-parents-level", str);
//list of parents
str = "";
for (SkillTreeNode node : getStrongParents())
str += node.getName() + ",";
//We remove the last comma
if (str.length() != 0)
str = str.substring(0, str.length() - 1);
holders.register("strong-parents", str);
return holders;
}
public List<String> getLore(PlayerData playerData) {
Placeholders holders = getPlaceholders(playerData);
List<String> parsedLore = new ArrayList<>();
NodeContext context = new NodeContext(playerData.getNodeState(this), playerData.getNodeLevel(this));
lores.get(context).forEach(string -> parsedLore.add(
lore.forEach(string -> parsedLore.add(
MythicLib.plugin.parseColors(holders.apply(playerData.getPlayer(), string))));
return parsedLore;
@ -320,6 +230,16 @@ public class SkillTreeNode implements Unlockable {
return MMOCore.plugin.skillTreeManager.get(treeId).getNode(coords);
}
@Override
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, @NotNull EXPSource source) {
throw new RuntimeException("Attributes don't have experience");
}
@Override
public boolean shouldHandle(PlayerData playerData) {
throw new RuntimeException("Attributes don't have experience");
}
public class NodeContext {
private final NodeState nodeState;
private final int nodeLevel;

View File

@ -96,15 +96,15 @@ public class AutomaticSkillTree extends SkillTree {
SkillTreeNode child = node.getChildren().get(i);
if (childrenSize % 2 == 1 && i == 0) {
child.setCoordinates(new IntegerCoordinates(x, y - 2));
child.setCoordinates(new IntegerCoordinates(x, y - 1));
leftOffset += 2 + nodeBranches.get(child).getLeftBranches();
rightOffset += 2 + nodeBranches.get(child).getRightBranches();
} else if (i % 2 == 0) {
child.setCoordinates(new IntegerCoordinates(x - leftOffset - 2 - nodeBranches.get(child).getWidth(), y - 2));
child.setCoordinates(new IntegerCoordinates(x - leftOffset - 2 - nodeBranches.get(child).getWidth(), y - 1));
for (SkillTreeNode skillTree : nodeBranches.keySet())
leftOffset += 2 + nodeBranches.get(child).getWidth();
} else {
child.setCoordinates(new IntegerCoordinates(x + rightOffset + 2 + nodeBranches.get(child).getWidth(), y - 2));
child.setCoordinates(new IntegerCoordinates(x + rightOffset + 2 + nodeBranches.get(child).getWidth(), y - 1));
rightOffset += 2 + nodeBranches.get(child).getWidth();
}
@ -149,9 +149,9 @@ public class AutomaticSkillTree extends SkillTree {
leftBranches += nodeBranches.get(child).getLeftBranches();
rightBranches += nodeBranches.get(child).getRightBranches();
} else if (i % 2 == 0) {
leftBranches += nodeBranches.get(child).getWidth() + 2;
leftBranches += nodeBranches.get(child).getWidth();
} else {
rightBranches += nodeBranches.get(child).getWidth() + 2;
rightBranches += nodeBranches.get(child).getWidth();
}
}

View File

@ -4,12 +4,13 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.tree.ParentType;
import net.Indyuce.mmocore.tree.SkillTreeNode;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import java.util.logging.Level;
public class CustomSkillTree extends SkillTree{
public class CustomSkillTree extends SkillTree {
public CustomSkillTree(ConfigurationSection config) {
super(config);
@ -17,7 +18,6 @@ public class CustomSkillTree extends SkillTree{
super.coordinatesSetup();
}
@Override
@ -25,31 +25,33 @@ public class CustomSkillTree extends SkillTree{
//We setup the children and parents for each node.
for (SkillTreeNode node : nodes.values()) {
ConfigurationSection section = config.getConfigurationSection(node.getId() + ".children.soft");
if(section!=null) {
ConfigurationSection section = config.getConfigurationSection("nodes."+node.getId() + ".children.soft");
if (section != null) {
for (String child : section.getKeys(false)) {
node.addChild(getNode(child));
getNode(child).addParent(node, section.getInt(child), ParentType.SOFT);
}
}
section = config.getConfigurationSection(node.getId() + ".children.strong");
if(section!=null) {
section = config.getConfigurationSection("nodes."+node.getId() + ".children.strong");
if (section != null) {
for (String child : section.getKeys(false)) {
node.addChild(getNode(child));
getNode(child).addParent(node, section.getInt(child), ParentType.STRONG);
}
}
Bukkit.broadcastMessage(node.getSoftParents().size()+" strong: "+node.getStrongParents().size());
}
//We find the roots of the tree which don't have any parents
for (SkillTreeNode node : nodes.values()) {
if (node.getSoftParents().size() == 0 && node.getStrongParents().size() == 0) {
Validate.isTrue(roots.size() == 0, "You can't have 2 roots on one automatic skill tree. You have " + (roots.size() != 0 ? roots.get(0).getName() : "") + " and " + node.getName() + ".");
//We mark the node as a root also
roots.add(node);
node.setIsRoot();
}
}
MMOCore.plugin.getLogger().log(Level.SEVERE,roots.size()+" ROOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOoooT");
Bukkit.broadcastMessage("" + roots.size());
}

View File

@ -0,0 +1,5 @@
package net.Indyuce.mmocore.util;
@FunctionalInterface
public interface TriConsumer<A, B, C> {
void accept(A a, B b, C c);
}

View File

@ -1,3 +1,7 @@
# GUI display name
name: Your Character
# GUI display name
name: '&eCurrent Skill Tree: &6{skill-tree-name}'
@ -9,25 +13,51 @@ items:
skill-tree:
name: '{skill-tree-node}'
function: skill-tree
slots: [9,18,27,36]
slots: [9,18,27]
lore: 'Description: {skill-tree-description}'
next-tree-list-page:
function: 'next-tree-list-page'
item: ARROW
slots: [ 45 ]
slots: [ 36 ]
previous-tree-list-page:
function: 'previous-tree-list-page'
item: 'ARROW'
slots: [ 0 ]
reallocation:
function: reallocation
item: CAULDRON
slots: [45]
name: '&aReallocate Skill Tree Points'
lore:
- ''
- 'You have spent a total of &6{total}&7 skill tree points.'
- '&7Right click to reallocate them.'
- ''
- '&eCosts 1 attribute reallocation point.'
- '&e◆ Skill Tree Reallocation Points: &6{realloc-points}'
skill-tree-node:
function: 'skill-tree-node'
slots: [2,3,4,5,6,7,8,11,12,13,14,15,16,17,20,21,22,23,24,25,26,29,30,31,32,33,34,35,38,39,40,41,42,43,44]
#The lore that will be displayed after the lore of the node
lore:
- '&7Current State: &6{current-state}'
- '&7Current Level: &6{current-level}'
- '&7Max Level: &6{max-level}'
- '--------------------'
- '&7⧆ &6Requirements: '
- '&fStrong Parents: '
- '{strong-parents}'
- ''
- '&fSoft Parents: '
- '{soft-parents}'
- '--------------------'
- '{custom-lore}'
- '--------------------'
- '&eCurrent {skill-tree} &epoints: &6{skill-tree-points}'
- '&eCurrent global points: &6{global-points}'