forked from Upstream/mmocore
Big modification for the skilltree GUI. Make sure to reload gui/skilltree.yml and look at the wiki.
This commit is contained in:
parent
77f543f347
commit
8b3d553183
@ -49,8 +49,8 @@ import net.Indyuce.mmocore.skilltree.IntegerCoordinates;
|
|||||||
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
||||||
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
|
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.gui.skilltree.display.DisplayInfo;
|
||||||
import net.Indyuce.mmocore.skilltree.tree.display.Icon;
|
import net.Indyuce.mmocore.gui.skilltree.display.Icon;
|
||||||
import net.Indyuce.mmocore.waypoint.Waypoint;
|
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;
|
||||||
@ -308,27 +308,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
|||||||
node.getTree().setupNodeStates(this);
|
node.getTree().setupNodeStates(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the icon the node should have.
|
|
||||||
*/
|
|
||||||
public Icon getIcon(SkillTreeNode node) {
|
|
||||||
SkillTree skillTree = node.getTree();
|
|
||||||
|
|
||||||
DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize());
|
|
||||||
|
|
||||||
return skillTree.getIcon(displayInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Icon getIcon(SkillTree skillTree, IntegerCoordinates coordinates) {
|
|
||||||
|
|
||||||
if (skillTree.isNode(coordinates)) {
|
|
||||||
SkillTreeNode node = skillTree.getNode(coordinates);
|
|
||||||
DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize());
|
|
||||||
return skillTree.getIcon(displayInfo);
|
|
||||||
}
|
|
||||||
if (skillTree.isPath(coordinates)) return skillTree.getIcon(DisplayInfo.pathInfo);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSkillTreePoint(String treeId) {
|
public int getSkillTreePoint(String treeId) {
|
||||||
return skillTreePoints.getOrDefault(treeId, 0);
|
return skillTreePoints.getOrDefault(treeId, 0);
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
package net.Indyuce.mmocore.gui;
|
package net.Indyuce.mmocore.gui.skilltree;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.MythicLib;
|
import io.lumine.mythic.lib.MythicLib;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
|
||||||
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
|
||||||
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
|
|
||||||
import net.Indyuce.mmocore.skilltree.tree.display.Icon;
|
|
||||||
import net.Indyuce.mmocore.api.SoundEvent;
|
import net.Indyuce.mmocore.api.SoundEvent;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
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.Placeholders;
|
import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||||
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
||||||
|
import net.Indyuce.mmocore.gui.skilltree.display.*;
|
||||||
import net.Indyuce.mmocore.skilltree.IntegerCoordinates;
|
import net.Indyuce.mmocore.skilltree.IntegerCoordinates;
|
||||||
|
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
||||||
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
|
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
|
||||||
|
import net.Indyuce.mmocore.skilltree.SkillTreePath;
|
||||||
|
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
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;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.event.inventory.ClickType;
|
import org.bukkit.event.inventory.ClickType;
|
||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@ -26,17 +29,39 @@ import org.bukkit.inventory.meta.ItemMeta;
|
|||||||
import org.bukkit.persistence.PersistentDataContainer;
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class SkillTreeViewer extends EditableInventory {
|
public class SkillTreeViewer extends EditableInventory {
|
||||||
|
protected final Map<DisplayInfo, Icon> icons = new HashMap<>();
|
||||||
|
|
||||||
public SkillTreeViewer() {
|
public SkillTreeViewer() {
|
||||||
super("skill-tree");
|
super("skill-tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload(FileConfiguration config) {
|
||||||
|
super.reload(config);
|
||||||
|
//Loads all the pathDisplayInfo
|
||||||
|
for (PathStatus status : PathStatus.values())
|
||||||
|
for (PathType pathType :PathType.values()){
|
||||||
|
if(!config.contains("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))){
|
||||||
|
MMOCore.log("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()));
|
||||||
|
MMOCore.log("Missing path type: " + MMOCoreUtils.ymlName(pathType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
icons.put(new PathDisplayInfo(pathType, status), new Icon(config.getConfigurationSection("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))));
|
||||||
|
}
|
||||||
|
//Loads all the nodeDisplayInfo
|
||||||
|
for (NodeStatus status : NodeStatus.values())
|
||||||
|
for (NodeType nodeType :NodeType.values()){
|
||||||
|
if(!config.contains("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))){
|
||||||
|
MMOCore.log("Missing node type: " + MMOCoreUtils.ymlName(nodeType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
icons.put(new NodeDisplayInfo(nodeType, status), new Icon(config.getConfigurationSection("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InventoryItem load(String function, ConfigurationSection config) {
|
public InventoryItem load(String function, ConfigurationSection config) {
|
||||||
if (function.equals("skill-tree")) {
|
if (function.equals("skill-tree")) {
|
||||||
@ -190,7 +215,7 @@ public class SkillTreeViewer extends EditableInventory {
|
|||||||
public ItemStack display(SkillTreeInventory inv, int n) {
|
public ItemStack display(SkillTreeInventory inv, int n) {
|
||||||
IntegerCoordinates coordinates = inv.getCoordinates(n);
|
IntegerCoordinates coordinates = inv.getCoordinates(n);
|
||||||
if (inv.getSkillTree().isNode(coordinates) || inv.getSkillTree().isPath(coordinates)) {
|
if (inv.getSkillTree().isNode(coordinates) || inv.getSkillTree().isPath(coordinates)) {
|
||||||
Icon icon = inv.getPlayerData().getIcon(inv.getSkillTree(), coordinates);
|
Icon icon = inv.getIcon(coordinates);
|
||||||
ItemStack item = super.display(inv, n, icon.getMaterial(), icon.getCustomModelData());
|
ItemStack item = super.display(inv, n, icon.getMaterial(), icon.getCustomModelData());
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
if (inv.getSkillTree().isNode(coordinates)) {
|
if (inv.getSkillTree().isNode(coordinates)) {
|
||||||
@ -313,6 +338,23 @@ public class SkillTreeViewer extends EditableInventory {
|
|||||||
return maxTreeListPage;
|
return maxTreeListPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Icon getIcon(IntegerCoordinates coordinates) {
|
||||||
|
boolean hasNorthPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1));
|
||||||
|
boolean hasSouthPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1));
|
||||||
|
boolean hasEastPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY()));
|
||||||
|
boolean hasWestPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() - 1, coordinates.getY()));
|
||||||
|
|
||||||
|
if (skillTree.isNode(coordinates)) {
|
||||||
|
SkillTreeNode node = skillTree.getNode(coordinates);
|
||||||
|
NodeType nodeType = NodeType.getNodeType(hasNorthPath, hasEastPath, hasSouthPath, hasWestPath);
|
||||||
|
return icons.get(new NodeDisplayInfo(nodeType, playerData.getNodeState(node)));
|
||||||
|
} else {
|
||||||
|
PathType pathType = PathType.getPathType(hasNorthPath, hasEastPath, hasSouthPath, hasWestPath);
|
||||||
|
SkillTreePath path = skillTree.getPath(coordinates);
|
||||||
|
return icons.get(new PathDisplayInfo(pathType, path.getStatus(playerData)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String calculateName() {
|
public String calculateName() {
|
||||||
return getEditable().getName().replace("{skill-tree-name}", skillTree.getName()).replace("{skill-tree-id}", skillTree.getId());
|
return getEditable().getName().replace("{skill-tree-name}", skillTree.getName()).replace("{skill-tree-id}", skillTree.getId());
|
||||||
@ -434,18 +476,15 @@ public class SkillTreeViewer extends EditableInventory {
|
|||||||
MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer());
|
MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer());
|
||||||
open();
|
open();
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
|
||||||
} else if (playerData.getNodeState(node) == NodeStatus.LOCKED || playerData.getNodeState(node) == NodeStatus.FULLY_LOCKED) {
|
} else if (playerData.getNodeState(node) == NodeStatus.LOCKED || playerData.getNodeState(node) == NodeStatus.FULLY_LOCKED) {
|
||||||
MMOCore.plugin.configManager.getSimpleMessage("locked-node").send(player);
|
MMOCore.plugin.configManager.getSimpleMessage("locked-node").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;
|
|
||||||
|
|
||||||
} else if (playerData.getNodeLevel(node) >= node.getMaxLevel()) {
|
} else if (playerData.getNodeLevel(node) >= node.getMaxLevel()) {
|
||||||
MMOCore.plugin.configManager.getSimpleMessage("skill-node-max-level-hit").send(player);
|
MMOCore.plugin.configManager.getSimpleMessage("skill-node-max-level-hit").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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Else the player doesn't doesn't have the skill tree points
|
//Else the player doesn't doesn't have the skill tree points
|
||||||
@ -453,7 +492,6 @@ public class SkillTreeViewer extends EditableInventory {
|
|||||||
MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-tree-points", "point", "" + node.getSkillTreePointsConsumed()).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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package net.Indyuce.mmocore.gui.skilltree.display;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The information needed to determine the display of a node/path depending on its context.
|
||||||
|
*/
|
||||||
|
public interface DisplayInfo {
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.Indyuce.mmocore.skilltree.tree.display;
|
package net.Indyuce.mmocore.gui.skilltree.display;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.UtilityMethods;
|
import io.lumine.mythic.lib.UtilityMethods;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -23,7 +23,7 @@ public class Icon {
|
|||||||
|
|
||||||
public Icon(ConfigurationSection config) {
|
public Icon(ConfigurationSection config) {
|
||||||
this(Material.valueOf(Objects.requireNonNull(UtilityMethods.enumName(
|
this(Material.valueOf(Objects.requireNonNull(UtilityMethods.enumName(
|
||||||
config.getString("item")))), config.contains("model-data") ? config.getInt("model-data") : 0);
|
config.getString("item")))), config.contains("custom-model-data") ? config.getInt("custom-model-data") : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Icon(Material material, int customModelData) {
|
public Icon(Material material, int customModelData) {
|
@ -0,0 +1,49 @@
|
|||||||
|
package net.Indyuce.mmocore.gui.skilltree.display;
|
||||||
|
|
||||||
|
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class NodeDisplayInfo implements DisplayInfo{
|
||||||
|
|
||||||
|
private NodeStatus nodeStatus;
|
||||||
|
private NodeType nodeType;
|
||||||
|
|
||||||
|
public NodeDisplayInfo(NodeType nodeType,NodeStatus nodeStatus) {
|
||||||
|
this.nodeStatus = nodeStatus;
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeStatus getNodeState() {
|
||||||
|
return nodeStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeStatus getNodeStatus() {
|
||||||
|
return nodeStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeType getNodeType() {
|
||||||
|
return nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
NodeDisplayInfo that = (NodeDisplayInfo) o;
|
||||||
|
return nodeStatus == that.nodeStatus && nodeType == that.nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(nodeStatus, nodeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "NodeDisplayInfo{" +
|
||||||
|
"nodeStatus=" + nodeStatus +
|
||||||
|
", nodeType=" + nodeType +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package net.Indyuce.mmocore.gui.skilltree.display;
|
||||||
|
|
||||||
|
public enum NodeType {
|
||||||
|
NORTH_EAST_SOUTH_WEST,
|
||||||
|
NORTH_EAST_SOUTH,
|
||||||
|
NORTH_EAST_WEST,
|
||||||
|
NORTH_SOUTH_WEST,
|
||||||
|
SOUTH_EAST_WEST,
|
||||||
|
NORTH_EAST,
|
||||||
|
NORTH_SOUTH,
|
||||||
|
NORTH_WEST,
|
||||||
|
SOUTH_EAST,
|
||||||
|
SOUTH_WEST,
|
||||||
|
EAST_WEST,
|
||||||
|
NO_PATH;
|
||||||
|
|
||||||
|
public static NodeType getNodeType(boolean hasNorthPath, boolean hasEastPath, boolean hasSouthPath, boolean hasWestPath) {
|
||||||
|
if (hasNorthPath && hasEastPath && hasSouthPath && hasWestPath) {
|
||||||
|
return NORTH_EAST_SOUTH_WEST;
|
||||||
|
} else if (hasNorthPath && hasEastPath && hasSouthPath) {
|
||||||
|
return NORTH_EAST_SOUTH;
|
||||||
|
} else if (hasNorthPath && hasEastPath && hasWestPath) {
|
||||||
|
return NORTH_EAST_WEST;
|
||||||
|
} else if (hasNorthPath && hasSouthPath && hasWestPath) {
|
||||||
|
return NORTH_SOUTH_WEST;
|
||||||
|
} else if (hasSouthPath && hasEastPath && hasWestPath) {
|
||||||
|
return SOUTH_EAST_WEST;
|
||||||
|
} else if (hasNorthPath && hasEastPath) {
|
||||||
|
return NORTH_EAST;
|
||||||
|
} else if (hasNorthPath && hasSouthPath) {
|
||||||
|
return NORTH_SOUTH;
|
||||||
|
} else if (hasNorthPath && hasWestPath) {
|
||||||
|
return NORTH_WEST;
|
||||||
|
} else if (hasSouthPath && hasEastPath) {
|
||||||
|
return SOUTH_EAST;
|
||||||
|
} else if (hasSouthPath && hasWestPath) {
|
||||||
|
return SOUTH_WEST;
|
||||||
|
} else if (hasEastPath && hasWestPath) {
|
||||||
|
return EAST_WEST;
|
||||||
|
}
|
||||||
|
return NO_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
package net.Indyuce.mmocore.gui.skilltree.display;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class PathDisplayInfo implements DisplayInfo{
|
||||||
|
|
||||||
|
private PathType pathType;
|
||||||
|
private PathStatus pathStatus;
|
||||||
|
|
||||||
|
public PathDisplayInfo(PathType pathType, PathStatus pathStatus) {
|
||||||
|
this.pathType = pathType;
|
||||||
|
this.pathStatus = pathStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathType getPathType() {
|
||||||
|
return pathType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathStatus getPathStatus() {
|
||||||
|
return pathStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(pathType, pathStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
PathDisplayInfo that = (PathDisplayInfo) o;
|
||||||
|
return pathType == that.pathType && pathStatus == that.pathStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PathDisplayInfo{" +
|
||||||
|
"pathType=" + pathType +
|
||||||
|
", pathStatus=" + pathStatus +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package net.Indyuce.mmocore.gui.skilltree.display;
|
||||||
|
|
||||||
|
public enum PathStatus {
|
||||||
|
LOCKED,
|
||||||
|
FULLY_LOCKED,
|
||||||
|
UNLOCKED;
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package net.Indyuce.mmocore.gui.skilltree.display;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The direction of the path.
|
||||||
|
*/
|
||||||
|
public enum PathType {
|
||||||
|
|
||||||
|
NORTH,
|
||||||
|
/**
|
||||||
|
* Goes to north then east/ goes to west then south.
|
||||||
|
*/
|
||||||
|
NORTH_EAST,
|
||||||
|
NORTH_WEST,
|
||||||
|
SOUTH_EAST,
|
||||||
|
SOUTH_WEST,
|
||||||
|
EAST,
|
||||||
|
|
||||||
|
DEFAULT;
|
||||||
|
|
||||||
|
public static PathType getPathType(boolean hasNorth,boolean hasEast,boolean hasSouth,boolean hasWest) {
|
||||||
|
if ((hasNorth || hasSouth) && !hasWest && hasEast) {
|
||||||
|
return NORTH;
|
||||||
|
} else if ((hasEast || hasWest)&& !hasNorth && !hasSouth) {
|
||||||
|
return EAST;
|
||||||
|
} else if (hasNorth && hasEast) {
|
||||||
|
return NORTH_EAST;
|
||||||
|
}
|
||||||
|
else if (hasNorth && hasWest) {
|
||||||
|
return NORTH_WEST;
|
||||||
|
}
|
||||||
|
else if (hasSouth && hasEast) {
|
||||||
|
return SOUTH_EAST;
|
||||||
|
}
|
||||||
|
else if (hasSouth && hasWest) {
|
||||||
|
return SOUTH_WEST;
|
||||||
|
}
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,6 +6,7 @@ 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.player.profess.PlayerClass;
|
||||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||||
|
import net.Indyuce.mmocore.gui.skilltree.SkillTreeViewer;
|
||||||
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;
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package net.Indyuce.mmocore.skilltree;
|
||||||
|
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.gui.skilltree.display.PathStatus;
|
||||||
|
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
|
||||||
|
|
||||||
|
public record SkillTreePath(SkillTree tree, IntegerCoordinates coordinates, SkillTreeNode from, SkillTreeNode to) {
|
||||||
|
|
||||||
|
public PathStatus getStatus(PlayerData playerData) {
|
||||||
|
if (playerData.getNodeState(from) == NodeStatus.UNLOCKED && playerData.getNodeState(to) == NodeStatus.UNLOCKED) {
|
||||||
|
return PathStatus.UNLOCKED;
|
||||||
|
}
|
||||||
|
return PathStatus.LOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -5,12 +5,15 @@ import io.lumine.mythic.lib.UtilityMethods;
|
|||||||
import io.lumine.mythic.lib.api.util.PostLoadObject;
|
import io.lumine.mythic.lib.api.util.PostLoadObject;
|
||||||
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.skilltree.display.DisplayInfo;
|
||||||
|
import net.Indyuce.mmocore.gui.skilltree.display.Icon;
|
||||||
|
import net.Indyuce.mmocore.gui.skilltree.display.NodeDisplayInfo;
|
||||||
|
import net.Indyuce.mmocore.gui.skilltree.display.NodeType;
|
||||||
import net.Indyuce.mmocore.manager.registry.RegisteredObject;
|
import net.Indyuce.mmocore.manager.registry.RegisteredObject;
|
||||||
import net.Indyuce.mmocore.skilltree.tree.display.DisplayInfo;
|
|
||||||
import net.Indyuce.mmocore.skilltree.tree.display.Icon;
|
|
||||||
import net.Indyuce.mmocore.skilltree.IntegerCoordinates;
|
import net.Indyuce.mmocore.skilltree.IntegerCoordinates;
|
||||||
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
||||||
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
|
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
|
||||||
|
import net.Indyuce.mmocore.skilltree.SkillTreePath;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
@ -42,16 +45,21 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
|
|||||||
private final int customModelData;
|
private final int customModelData;
|
||||||
|
|
||||||
//2 different maps to get the nodes
|
//2 different maps to get the nodes
|
||||||
|
/**
|
||||||
//Represents all the coordinates that will be displayed as a path (between 2 nodes of the tree)
|
* Represents all the nodes
|
||||||
protected final ArrayList<IntegerCoordinates> paths = new ArrayList<>();
|
* Key: the coordinates of the node
|
||||||
//Represents all the nodes
|
* Value: the node
|
||||||
|
*/
|
||||||
protected final Map<IntegerCoordinates, SkillTreeNode> coordinatesNodes = new HashMap<>();
|
protected final Map<IntegerCoordinates, SkillTreeNode> coordinatesNodes = new HashMap<>();
|
||||||
|
/**
|
||||||
|
* Represents all the paths between nodes.
|
||||||
|
*/
|
||||||
|
protected final Map<IntegerCoordinates, SkillTreePath> coordinatesPaths = new HashMap<>();
|
||||||
|
|
||||||
protected final Map<String, SkillTreeNode> nodes = new HashMap<>();
|
protected final Map<String, SkillTreeNode> nodes = new HashMap<>();
|
||||||
protected final int maxPointSpent;
|
protected final int maxPointSpent;
|
||||||
//Caches the height of the skill tree
|
//Caches the height of the skill tree
|
||||||
protected int minX, minY, maxX, maxY;
|
protected int minX, minY, maxX, maxY;
|
||||||
protected final HashMap<DisplayInfo, Icon> icons = new HashMap<>();
|
|
||||||
protected final List<SkillTreeNode> roots = new ArrayList<>();
|
protected final List<SkillTreeNode> roots = new ArrayList<>();
|
||||||
|
|
||||||
public SkillTree(ConfigurationSection config) {
|
public SkillTree(ConfigurationSection config) {
|
||||||
@ -66,47 +74,32 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
|
|||||||
this.maxPointSpent = config.getInt("max-point-spent", Integer.MAX_VALUE);
|
this.maxPointSpent = config.getInt("max-point-spent", Integer.MAX_VALUE);
|
||||||
for (String key : config.getConfigurationSection("nodes").getKeys(false)) {
|
for (String key : config.getConfigurationSection("nodes").getKeys(false)) {
|
||||||
try {
|
try {
|
||||||
|
ConfigurationSection section = config.getConfigurationSection("nodes." + key);
|
||||||
SkillTreeNode node = new SkillTreeNode(this, config.getConfigurationSection("nodes." + key));
|
SkillTreeNode node = new SkillTreeNode(this, section);
|
||||||
nodes.put(node.getId(), node);
|
nodes.put(node.getId(), node);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
MMOCore.log("Couldn't load skill tree node " + id + "." + key + ": " + e.getMessage());
|
MMOCore.log("Couldn't load skill tree node " + id + "." + key + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
for (String from : config.getConfigurationSection("nodes").getKeys(false)) {
|
||||||
if (config.contains("paths")) {
|
ConfigurationSection section = config.getConfigurationSection("nodes." + from);
|
||||||
ConfigurationSection section = config.getConfigurationSection("paths");
|
MMOCore.log("skilltree:" + id + " " + (section.contains("paths")));
|
||||||
for (String key : section.getKeys(false)) {
|
if (section.contains("paths")) {
|
||||||
if (section.contains(key + ".x") && section.contains(key + ".y")) {
|
for (String to : section.getConfigurationSection("paths").getKeys(false)) {
|
||||||
paths.add(new IntegerCoordinates(section.getInt(key + ".x"), section.getInt(key + ".y")));
|
SkillTreeNode node1 = nodes.get(to);
|
||||||
}
|
if (node1 == null) {
|
||||||
|
MMOCore.log("Couldn't find node " + to + " for path in node " + from + ".");
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
MMOCore.log(Level.WARNING, "Couldn't load paths for skill tree: " + id);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
//Load the icons of the skill tree.
|
|
||||||
for (String key : config.getConfigurationSection("icons").getKeys(false)) {
|
|
||||||
if (key.equalsIgnoreCase("path")) {
|
|
||||||
icons.put(DisplayInfo.pathInfo, new Icon(config.getConfigurationSection("icons." + key)));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (String size : config.getConfigurationSection("icons." + key).getKeys(false)) {
|
for (String pathKey : section.getConfigurationSection("paths." + to).getKeys(false)) {
|
||||||
DisplayInfo displayInfo = new DisplayInfo(NodeStatus.valueOf(UtilityMethods.enumName(key)), Integer.parseInt(size));
|
IntegerCoordinates coordinates = new IntegerCoordinates(section.getInt("paths." + to + "." + pathKey + ".x"), section.getInt("paths." + to + "." + pathKey + ".y"));
|
||||||
Icon icon = new Icon(config.getConfigurationSection("icons." + key + "." + size));
|
coordinatesPaths.put(coordinates, new SkillTreePath(this, coordinates, nodes.get(from), node1));
|
||||||
icons.put(displayInfo, icon);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
MMOCore.log("Couldn't load icons for the skill tree " + id);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to setup everything related to coordinates when each node has its coordinates loaded.
|
* Used to setup everything related to coordinates when each node has its coordinates loaded.
|
||||||
@ -121,12 +114,28 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected abstract void whenPostLoaded(@NotNull ConfigurationSection configurationSection);
|
protected abstract void whenPostLoaded(@NotNull ConfigurationSection configurationSection);
|
||||||
|
/*
|
||||||
|
|
||||||
public Icon getIcon(DisplayInfo info) {
|
public Icon getIcon(SkillTreeNode node) {
|
||||||
Validate.isTrue(icons.containsKey(info), "The icon corresponding to " + info + " doesn't exist for the skill tree " + id + ".");
|
SkillTree skillTree = node.getTree();
|
||||||
return icons.get(info);
|
|
||||||
|
DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize());
|
||||||
|
|
||||||
|
return skillTree.getIcon(displayInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Icon getIcon(SkillTree skillTree, IntegerCoordinates coordinates) {
|
||||||
|
|
||||||
|
if (skillTree.isNode(coordinates)) {
|
||||||
|
SkillTreeNode node = skillTree.getNode(coordinates);
|
||||||
|
DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize());
|
||||||
|
return skillTree.getIcon(displayInfo);
|
||||||
|
}
|
||||||
|
if (skillTree.isPath(coordinates)) return skillTree.getIcon(DisplayInfo.pathInfo);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public int getMaxX() {
|
public int getMaxX() {
|
||||||
return maxX;
|
return maxX;
|
||||||
}
|
}
|
||||||
@ -266,7 +275,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPath(IntegerCoordinates coordinates) {
|
public boolean isPath(IntegerCoordinates coordinates) {
|
||||||
return paths.contains(coordinates);
|
return coordinatesPaths.keySet().contains(coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Material getItem() {
|
public Material getItem() {
|
||||||
@ -291,11 +300,17 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
|
|||||||
return Objects.requireNonNull(coordinatesNodes.get(coords), "Could not find node in tree '" + id + "' with coordinates '" + coords.toString() + "'");
|
return Objects.requireNonNull(coordinatesNodes.get(coords), "Could not find node in tree '" + id + "' with coordinates '" + coords.toString() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public SkillTreePath getPath(IntegerCoordinates coords) {
|
||||||
|
return Objects.requireNonNull(coordinatesPaths.get(coords), "Could not find path in tree '" + id + "' with coordinates '" + coords.toString() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public SkillTreeNode getNode(String name) {
|
public SkillTreeNode getNode(String name) {
|
||||||
return Objects.requireNonNull(nodes.get(name), "Could not find node in tree '" + id + "' with name '" + name + "'");
|
return Objects.requireNonNull(nodes.get(name), "Could not find node in tree '" + id + "' with name '" + name + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isNode(String name) {
|
public boolean isNode(String name) {
|
||||||
return nodes.containsKey(name);
|
return nodes.containsKey(name);
|
||||||
}
|
}
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
package net.Indyuce.mmocore.skilltree.tree.display;
|
|
||||||
|
|
||||||
import net.Indyuce.mmocore.skilltree.NodeStatus;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The information needed to determine the display type of a node
|
|
||||||
*/
|
|
||||||
public class DisplayInfo {
|
|
||||||
private NodeStatus nodeStatus;
|
|
||||||
private int size;
|
|
||||||
|
|
||||||
//this NodeDisplayInfo represent a path
|
|
||||||
public static DisplayInfo pathInfo= new DisplayInfo();
|
|
||||||
|
|
||||||
|
|
||||||
public DisplayInfo() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public DisplayInfo(NodeStatus nodeStatus, int size) {
|
|
||||||
this.nodeStatus = nodeStatus;
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeStatus getNodeState() {
|
|
||||||
return nodeStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(nodeStatus, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if(!(obj instanceof DisplayInfo))
|
|
||||||
return false;
|
|
||||||
DisplayInfo displayInfo= (DisplayInfo) obj;
|
|
||||||
if(nodeStatus ==null)
|
|
||||||
return displayInfo.getNodeState()==null;
|
|
||||||
return nodeStatus ==displayInfo.getNodeState()&&size==displayInfo.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "DisplayInfo{" +
|
|
||||||
"nodeState=" + nodeStatus +
|
|
||||||
", size=" + size +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -99,4 +99,221 @@ items:
|
|||||||
- '&e◆Points spent for {skill-tree}&e:&6 {point-spent}'
|
- '&e◆Points spent for {skill-tree}&e:&6 {point-spent}'
|
||||||
- '&e◆Current {skill-tree} &epoints: &6{skill-tree-points}'
|
- '&e◆Current {skill-tree} &epoints: &6{skill-tree-points}'
|
||||||
- '&e◆Current &6global&e points: &6{global-points}'
|
- '&e◆Current &6global&e points: &6{global-points}'
|
||||||
|
display:
|
||||||
|
paths:
|
||||||
|
unlocked:
|
||||||
|
north:
|
||||||
|
item: "WHITE_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east:
|
||||||
|
item: "WHITE_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-west:
|
||||||
|
item: "WHITE_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east:
|
||||||
|
item: "WHITE_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-west:
|
||||||
|
item: "WHITE_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
east:
|
||||||
|
item: "WHITE_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
default:
|
||||||
|
item: "WHITE_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
locked:
|
||||||
|
north:
|
||||||
|
item: "GRAY_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east:
|
||||||
|
item: "GRAY_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-west:
|
||||||
|
item: "GRAY_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east:
|
||||||
|
item: "GRAY_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-west:
|
||||||
|
item: "GRAY_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
east:
|
||||||
|
item: "GRAY_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
default:
|
||||||
|
item: "GRAY_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
fully-locked:
|
||||||
|
north:
|
||||||
|
item: "BLACK_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east:
|
||||||
|
item: "BLACK_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-west:
|
||||||
|
item: "BLACK_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east:
|
||||||
|
item: "BLACK_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-west:
|
||||||
|
item: "BLACK_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
east:
|
||||||
|
item: "BLACK_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
default:
|
||||||
|
item: "BLACK_DYE"
|
||||||
|
custom-model-data: 0
|
||||||
|
nodes:
|
||||||
|
unlocked:
|
||||||
|
north-east-south-west:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-south:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-west:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south-west:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east-west:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-west:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-west:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
east-west:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
no-path:
|
||||||
|
item: "WHITE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
locked:
|
||||||
|
north-east-south-west:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-south:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-west:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south-west:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east-west:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-west:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-west:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
east-west:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
no-path:
|
||||||
|
item: "GRAY_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
unlockable:
|
||||||
|
north-east-south-west:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-south:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-west:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south-west:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east-west:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-west:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-west:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
east-west:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
no-path:
|
||||||
|
item: "BLUE_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
fully-locked:
|
||||||
|
north-east-south-west:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-south:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east-west:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south-west:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east-west:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-east:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-south:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
north-west:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-east:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
south-west:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
east-west:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
no-path:
|
||||||
|
item: "BLACK_CONCRETE"
|
||||||
|
custom-model-data: 0
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user