forked from Upstream/mmocore
Merge remote-tracking branch 'origin/master'
# Conflicts: # MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java
This commit is contained in:
commit
792ca9af39
@ -5,6 +5,7 @@ import io.lumine.mythic.lib.manager.StatManager;
|
|||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerActivity;
|
import net.Indyuce.mmocore.api.player.PlayerActivity;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||||
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;
|
||||||
import org.bukkit.attribute.Attribute;
|
import org.bukkit.attribute.Attribute;
|
||||||
@ -37,25 +38,33 @@ public class PlayerActionBar extends BukkitRunnable {
|
|||||||
public void run() {
|
public void run() {
|
||||||
for (PlayerData data : PlayerData.getAll())
|
for (PlayerData data : PlayerData.getAll())
|
||||||
if (data.isOnline() && !data.getPlayer().isDead() && !data.isCasting() && data.getActivityTimeOut(PlayerActivity.ACTION_BAR_MESSAGE) == 0) {
|
if (data.isOnline() && !data.getPlayer().isDead() && !data.isCasting() && data.getActivityTimeOut(PlayerActivity.ACTION_BAR_MESSAGE) == 0) {
|
||||||
data.getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(MMOCore.plugin.placeholderParser.parse(data.getPlayer(),
|
Placeholders holders=getActionBarPlaceholder(data);
|
||||||
MythicLib.plugin.parseColors((data.getProfess().hasActionBar() ? data.getProfess().getActionBar() : config.format)
|
data.getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(
|
||||||
.replace("{health}", digit.format(data.getPlayer().getHealth()))
|
holders.apply(data.getPlayer(), data.getProfess().hasActionBar() ? data.getProfess().getActionBar() : config.format)));
|
||||||
.replace("{max_health}", StatManager.format("MAX_HEALTH", data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()))
|
|
||||||
.replace("{mana_icon}", data.getProfess().getManaDisplay().getIcon())
|
|
||||||
.replace("{mana}", digit.format(data.getMana()))
|
|
||||||
.replace("{max_mana}", StatManager.format("MAX_MANA", data.getStats().getStat("MAX_MANA")))
|
|
||||||
.replace("{stamina}", digit.format(data.getStamina()))
|
|
||||||
.replace("{max_stamina}", StatManager.format("MAX_STAMINA", data.getStats().getStat("MAX_STAMINA")))
|
|
||||||
.replace("{stellium}", digit.format(data.getStellium()))
|
|
||||||
.replace("{max_stellium}", StatManager.format("MAX_STELLIUM", data.getStats().getStat("MAX_STELLIUM")))
|
|
||||||
.replace("{class}", data.getProfess().getName())
|
|
||||||
.replace("{xp}", MythicLib.plugin.getMMOConfig().decimal.format(data.getExperience()))
|
|
||||||
.replace("{armor}", StatManager.format("ARMOR", data.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).getValue()))
|
|
||||||
.replace("{level}", "" + data.getLevel())
|
|
||||||
.replace("{name}", data.getPlayer().getDisplayName())))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Placeholders getActionBarPlaceholder(PlayerData data) {
|
||||||
|
Placeholders holders= new Placeholders();
|
||||||
|
holders.register("health", digit.format(data.getPlayer().getHealth()));
|
||||||
|
holders.register("max_health", StatManager.format("MAX_HEALTH", data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()));
|
||||||
|
holders.register("mana_icon", data.getProfess().getManaDisplay().getIcon());
|
||||||
|
holders.register("mana", digit.format(data.getMana()));
|
||||||
|
holders.register("max_mana", StatManager.format("MAX_MANA", data.getStats().getStat("MAX_MANA")));
|
||||||
|
holders.register("stamina", digit.format(data.getStamina()));
|
||||||
|
holders.register("max_stamina", StatManager.format("MAX_STAMINA", data.getStats().getStat("MAX_STAMINA")));
|
||||||
|
holders.register("stellium", digit.format(data.getStellium()));
|
||||||
|
holders.register("max_stellium", StatManager.format("MAX_STELLIUM", data.getStats().getStat("MAX_STELLIUM")));
|
||||||
|
holders.register("class", data.getProfess().getName());
|
||||||
|
holders.register("xp", MythicLib.plugin.getMMOConfig().decimal.format(data.getExperience()));
|
||||||
|
holders.register("armor", StatManager.format("ARMOR", data.getPlayer().getAttribute(Attribute.GENERIC_ARMOR).getValue()));
|
||||||
|
holders.register("level", "" + data.getLevel());
|
||||||
|
holders.register("name", data.getPlayer().getDisplayName());
|
||||||
|
return holders;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class ActionBarConfig {
|
private static class ActionBarConfig {
|
||||||
private final boolean enabled;
|
private final boolean enabled;
|
||||||
private final int ticks, timeout;
|
private final int ticks, timeout;
|
||||||
|
@ -598,6 +598,11 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
|||||||
waypoints.add(waypoint.getId());
|
waypoints.add(waypoint.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void lockWaypoint(Waypoint waypoint) {
|
||||||
|
waypoints.remove(waypoint.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Provide a heal reason with {@link #heal(double, PlayerResourceUpdateEvent.UpdateReason)}
|
* @deprecated Provide a heal reason with {@link #heal(double, PlayerResourceUpdateEvent.UpdateReason)}
|
||||||
*/
|
*/
|
||||||
@ -692,8 +697,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MMOCore.plugin.configManager.getSimpleMessage("warping-comencing", "left", "" + ((120 - t) / 20)).send(getPlayer());
|
MMOCore.plugin.configManager.getSimpleMessage("warping-comencing", "left", "" + ((MMOCore.plugin.configManager.waypointWarpTime+20 - t) / 20)).send(getPlayer());
|
||||||
if (t++ >= 100) {
|
if (t++ >= MMOCore.plugin.configManager.waypointWarpTime) {
|
||||||
getPlayer().teleport(target.getLocation());
|
getPlayer().teleport(target.getLocation());
|
||||||
getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 20, 1, false, false));
|
getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 20, 1, false, false));
|
||||||
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_TELEPORT).playTo(getPlayer());
|
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_TELEPORT).playTo(getPlayer());
|
||||||
@ -701,11 +706,11 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_CHARGE).playTo(getPlayer(), 1, (float) (t / Math.PI * .015 + .5));
|
MMOCore.plugin.soundManager.getSound(SoundEvent.WARP_CHARGE).playTo(getPlayer(), 1, (float) (t / Math.PI * 1.5/MMOCore.plugin.configManager.waypointWarpTime + .5));
|
||||||
double r = Math.sin((double) t / 100 * Math.PI);
|
double r = Math.sin((double) t / MMOCore.plugin.configManager.waypointWarpTime * Math.PI);
|
||||||
for (double j = 0; j < Math.PI * 2; j += Math.PI / 4)
|
for (double j = 0; j < Math.PI * 2; j += Math.PI / 4)
|
||||||
getPlayer().getLocation().getWorld().spawnParticle(Particle.REDSTONE,
|
getPlayer().getLocation().getWorld().spawnParticle(Particle.REDSTONE,
|
||||||
getPlayer().getLocation().add(Math.cos((double) t / 20 + j) * r, (double) t / 50, Math.sin((double) t / 20 + j) * r), 1,
|
getPlayer().getLocation().add(Math.cos((double) 5*t /MMOCore.plugin.configManager.waypointWarpTime + j) * r, (double) 2*t / MMOCore.plugin.configManager.waypointWarpTime, Math.sin((double) 5*t / MMOCore.plugin.configManager.waypointWarpTime + j) * r), 1,
|
||||||
new Particle.DustOptions(Color.PURPLE, 1.25f));
|
new Particle.DustOptions(Color.PURPLE, 1.25f));
|
||||||
}
|
}
|
||||||
}.runTaskTimer(MMOCore.plugin, 0, 1);
|
}.runTaskTimer(MMOCore.plugin, 0, 1);
|
||||||
@ -952,6 +957,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
|
|||||||
getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
|
getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setAttribute(PlayerAttribute attribute, int value) {
|
public void setAttribute(PlayerAttribute attribute, int value) {
|
||||||
setAttribute(attribute.getId(), value);
|
setAttribute(attribute.getId(), value);
|
||||||
|
@ -34,12 +34,12 @@ import net.Indyuce.mmocore.skill.cast.KeyCombo;
|
|||||||
import net.Indyuce.mmocore.skill.cast.PlayerKey;
|
import net.Indyuce.mmocore.skill.cast.PlayerKey;
|
||||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
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.craftbukkit.libs.org.apache.commons.lang3.Validate;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -76,6 +76,10 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
|||||||
|
|
||||||
// If the class redefines its own key combos.
|
// If the class redefines its own key combos.
|
||||||
private final Map<KeyCombo, Integer> combos = new HashMap<>();
|
private final Map<KeyCombo, Integer> combos = new HashMap<>();
|
||||||
|
|
||||||
|
private final Set<PlayerKey> firstComboKeys= new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
private int longestCombo;
|
private int longestCombo;
|
||||||
|
|
||||||
private final Map<PlayerResource, ResourceRegeneration> resourceHandlers = new HashMap<>();
|
private final Map<PlayerResource, ResourceRegeneration> resourceHandlers = new HashMap<>();
|
||||||
@ -153,6 +157,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
|||||||
combo.registerKey(PlayerKey.valueOf(UtilityMethods.enumName(str)));
|
combo.registerKey(PlayerKey.valueOf(UtilityMethods.enumName(str)));
|
||||||
|
|
||||||
combos.put(combo, spellSlot);
|
combos.put(combo, spellSlot);
|
||||||
|
firstComboKeys.add(combo.getAt(0));
|
||||||
longestCombo = Math.max(longestCombo, combo.countKeys());
|
longestCombo = Math.max(longestCombo, combo.countKeys());
|
||||||
} catch (RuntimeException exception) {
|
} catch (RuntimeException exception) {
|
||||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load key combo '" + key + "': " + exception.getMessage());
|
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load key combo '" + key + "': " + exception.getMessage());
|
||||||
@ -441,6 +446,10 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
|
|||||||
return combos;
|
return combos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<PlayerKey> getFirstComboKeys() {
|
||||||
|
return firstComboKeys;
|
||||||
|
}
|
||||||
|
|
||||||
public int getLongestCombo() {
|
public int getLongestCombo() {
|
||||||
return longestCombo;
|
return longestCombo;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,8 @@ public class CommandVerbose {
|
|||||||
POINTS,
|
POINTS,
|
||||||
SKILL_TREE_POINTS,
|
SKILL_TREE_POINTS,
|
||||||
RESET,
|
RESET,
|
||||||
RESOURCE
|
RESOURCE,
|
||||||
|
WAYPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum VerboseValue {
|
private enum VerboseValue {
|
||||||
|
@ -28,7 +28,6 @@ public class AdminCommandTreeNode extends CommandTreeNode {
|
|||||||
addChild(new PointsCommandTreeNode("attr-realloc", this, PlayerData::setAttributeReallocationPoints, PlayerData::giveAttributeReallocationPoints, PlayerData::getAttributeReallocationPoints));
|
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-realloc", this, PlayerData::setSkillReallocationPoints, PlayerData::giveSkillReallocationPoints, PlayerData::getSkillReallocationPoints));
|
||||||
addChild(new PointsCommandTreeNode("skill-tree-realloc", this, PlayerData::setSkillTreeReallocationPoints, PlayerData::giveSkillTreeReallocationPoints, PlayerData::getSkillTreeReallocationPoints));
|
addChild(new PointsCommandTreeNode("skill-tree-realloc", this, PlayerData::setSkillTreeReallocationPoints, PlayerData::giveSkillTreeReallocationPoints, PlayerData::getSkillTreeReallocationPoints));
|
||||||
|
|
||||||
for (PlayerResource res : PlayerResource.values())
|
for (PlayerResource res : PlayerResource.values())
|
||||||
addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
|
addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package net.Indyuce.mmocore.command.rpg.waypoint;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.command.api.CommandTreeNode;
|
||||||
|
import io.lumine.mythic.lib.command.api.Parameter;
|
||||||
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.command.CommandVerbose;
|
||||||
|
import net.Indyuce.mmocore.waypoint.Waypoint;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class LockCommandTreeNode extends CommandTreeNode {
|
||||||
|
|
||||||
|
public LockCommandTreeNode(CommandTreeNode parent) {
|
||||||
|
super(parent, "lock");
|
||||||
|
|
||||||
|
addParameter(new Parameter("<waypoint>", (explorer, list) -> MMOCore.plugin.waypointManager.getAll().forEach(way -> list.add(way.getId()))));
|
||||||
|
addParameter(Parameter.PLAYER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(CommandSender sender, String[] args) {
|
||||||
|
if (args.length < 4)
|
||||||
|
return CommandResult.THROW_USAGE;
|
||||||
|
|
||||||
|
if (!MMOCore.plugin.waypointManager.has(args[2])) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Could not find waypoint " + args[2]);
|
||||||
|
return CommandResult.FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = Bukkit.getPlayer(args[3]);
|
||||||
|
if (player == null) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Could not find player " + args[3]);
|
||||||
|
return CommandResult.FAILURE;
|
||||||
|
}
|
||||||
|
PlayerData playerData = PlayerData.get(player);
|
||||||
|
Waypoint waypoint = MMOCore.plugin.waypointManager.get(args[2]);
|
||||||
|
|
||||||
|
if (!playerData.hasWaypoint(waypoint)) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "The waypoint " + args[2] + " is already locked.");
|
||||||
|
return CommandResult.FAILURE;
|
||||||
|
}
|
||||||
|
PlayerData.get(player).lockWaypoint(waypoint);
|
||||||
|
CommandVerbose.verbose(sender,CommandVerbose.CommandType.WAYPOINT,ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " successfully locked " + ChatColor.GOLD + waypoint.getId()
|
||||||
|
+ ChatColor.YELLOW + ".");
|
||||||
|
return CommandResult.SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@ public class WaypointsCommandTreeNode extends CommandTreeNode {
|
|||||||
addChild(new OpenCommandTreeNode(this));
|
addChild(new OpenCommandTreeNode(this));
|
||||||
addChild(new TeleportCommandTreeNode(this));
|
addChild(new TeleportCommandTreeNode(this));
|
||||||
addChild(new ItemCommandTreeNode(this));
|
addChild(new ItemCommandTreeNode(this));
|
||||||
|
addChild(new LockCommandTreeNode(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,6 +25,9 @@ public class Placeholders {
|
|||||||
@Nullable String found = placeholders.get(holder);
|
@Nullable String found = placeholders.get(holder);
|
||||||
if (found != null)
|
if (found != null)
|
||||||
str = str.replace("{" + holder + "}", found);
|
str = str.replace("{" + holder + "}", found);
|
||||||
|
else
|
||||||
|
str = str.replace("{" + holder + "}", "PHE");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// External placeholders
|
// External placeholders
|
||||||
|
@ -2,8 +2,8 @@ package net.Indyuce.mmocore.manager;
|
|||||||
|
|
||||||
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.ConfigFile;
|
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.api.ConfigFile;
|
||||||
import net.Indyuce.mmocore.api.util.input.ChatInput;
|
import net.Indyuce.mmocore.api.util.input.ChatInput;
|
||||||
import net.Indyuce.mmocore.api.util.input.PlayerInput;
|
import net.Indyuce.mmocore.api.util.input.PlayerInput;
|
||||||
import net.Indyuce.mmocore.api.util.input.PlayerInput.InputType;
|
import net.Indyuce.mmocore.api.util.input.PlayerInput.InputType;
|
||||||
@ -27,6 +27,7 @@ public class ConfigManager {
|
|||||||
public final long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown;
|
public final long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown;
|
||||||
public final double lootChestsChanceWeight, fishingDropsChanceWeight;
|
public final double lootChestsChanceWeight, fishingDropsChanceWeight;
|
||||||
public final int maxPartyLevelDifference, maxBoundSkills;
|
public final int maxPartyLevelDifference, maxBoundSkills;
|
||||||
|
|
||||||
private final FileConfiguration messages;
|
private final FileConfiguration messages;
|
||||||
|
|
||||||
public ConfigManager() {
|
public ConfigManager() {
|
||||||
@ -67,7 +68,6 @@ public class ConfigManager {
|
|||||||
loadDefaultFile("expcurves", "levels.txt");
|
loadDefaultFile("expcurves", "levels.txt");
|
||||||
loadDefaultFile("expcurves", "mining.txt");
|
loadDefaultFile("expcurves", "mining.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!new File(MMOCore.plugin.getDataFolder()+"/skilltree").exists()) {
|
if(!new File(MMOCore.plugin.getDataFolder()+"/skilltree").exists()) {
|
||||||
loadDefaultFile("skilltree","combat.yml");
|
loadDefaultFile("skilltree","combat.yml");
|
||||||
}
|
}
|
||||||
@ -109,8 +109,7 @@ public class ConfigManager {
|
|||||||
canCreativeCast = MMOCore.plugin.getConfig().getBoolean("can-creative-cast");
|
canCreativeCast = MMOCore.plugin.getConfig().getBoolean("can-creative-cast");
|
||||||
cobbleGeneratorXP = MMOCore.plugin.getConfig().getBoolean("should-cobblestone-generators-give-exp");
|
cobbleGeneratorXP = MMOCore.plugin.getConfig().getBoolean("should-cobblestone-generators-give-exp");
|
||||||
saveDefaultClassInfo = MMOCore.plugin.getConfig().getBoolean("save-default-class-info");
|
saveDefaultClassInfo = MMOCore.plugin.getConfig().getBoolean("save-default-class-info");
|
||||||
maxBoundSkills = MMOCore.plugin.getConfig().getInt("max-bound-skills",6);
|
maxBoundSkills= MMOCore.plugin.getConfig().getInt("max-bound-skills",6);
|
||||||
overrideVanillaExp = MMOCore.plugin.getConfig().getBoolean("override-vanilla-exp");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChatColor getColorOrDefault(String key, ChatColor defaultColor) {
|
private ChatColor getColorOrDefault(String key, ChatColor defaultColor) {
|
||||||
|
@ -10,11 +10,13 @@ import io.lumine.mythic.lib.skill.trigger.TriggerType;
|
|||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
|
import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||||
import net.Indyuce.mmocore.skill.cast.PlayerKey;
|
import net.Indyuce.mmocore.skill.cast.PlayerKey;
|
||||||
import net.Indyuce.mmocore.api.SoundObject;
|
import net.Indyuce.mmocore.api.SoundObject;
|
||||||
import net.Indyuce.mmocore.skill.cast.KeyCombo;
|
import net.Indyuce.mmocore.skill.cast.KeyCombo;
|
||||||
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
|
import net.Indyuce.mmocore.skill.cast.SkillCastingHandler;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -32,10 +34,15 @@ public class KeyCombos implements Listener {
|
|||||||
* hash code method
|
* hash code method
|
||||||
*/
|
*/
|
||||||
private final Map<KeyCombo, Integer> combos = new HashMap<>();
|
private final Map<KeyCombo, Integer> combos = new HashMap<>();
|
||||||
|
/**
|
||||||
|
* All the keys that are at the start of a combo.
|
||||||
|
*/
|
||||||
|
private final Set<PlayerKey> firstComboKeys = new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key players need to press to start a combo
|
* Key players need to press to start a combo
|
||||||
*/
|
*/
|
||||||
|
private final boolean needsInitializerKey;
|
||||||
private final PlayerKey initializerKey;
|
private final PlayerKey initializerKey;
|
||||||
private final int longestCombo;
|
private final int longestCombo;
|
||||||
|
|
||||||
@ -64,6 +71,7 @@ public class KeyCombos implements Listener {
|
|||||||
combo.registerKey(PlayerKey.valueOf(UtilityMethods.enumName(str)));
|
combo.registerKey(PlayerKey.valueOf(UtilityMethods.enumName(str)));
|
||||||
|
|
||||||
combos.put(combo, spellSlot);
|
combos.put(combo, spellSlot);
|
||||||
|
firstComboKeys.add(combo.getAt(0));
|
||||||
longestCombo = Math.max(longestCombo, combo.countKeys());
|
longestCombo = Math.max(longestCombo, combo.countKeys());
|
||||||
} catch (RuntimeException exception) {
|
} catch (RuntimeException exception) {
|
||||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load key combo '" + key + "': " + exception.getMessage());
|
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load key combo '" + key + "': " + exception.getMessage());
|
||||||
@ -79,8 +87,13 @@ public class KeyCombos implements Listener {
|
|||||||
comboClickSound = config.contains("sound.combo-key") ? new SoundObject(config.getConfigurationSection("sound.combo-key")) : null;
|
comboClickSound = config.contains("sound.combo-key") ? new SoundObject(config.getConfigurationSection("sound.combo-key")) : null;
|
||||||
failComboSound = config.contains("sound.fail-combo") ? new SoundObject(config.getConfigurationSection("sound.fail-combo")) : null;
|
failComboSound = config.contains("sound.fail-combo") ? new SoundObject(config.getConfigurationSection("sound.fail-combo")) : null;
|
||||||
|
|
||||||
|
needsInitializerKey = config.getBoolean("needs-initializer-key", true);
|
||||||
|
|
||||||
|
|
||||||
// Find initializer key
|
// Find initializer key
|
||||||
initializerKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("initializer-key"), "Could not find initializer key")));
|
initializerKey = needsInitializerKey ? PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(
|
||||||
|
config.getString("initializer-key"), "Could not find initializer key"))) : null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
@ -89,21 +102,37 @@ public class KeyCombos implements Listener {
|
|||||||
Player player = playerData.getPlayer();
|
Player player = playerData.getPlayer();
|
||||||
|
|
||||||
if (!event.getData().isCasting()) {
|
if (!event.getData().isCasting()) {
|
||||||
if (event.getPressed() == initializerKey) {
|
if (needsInitializerKey) {
|
||||||
|
if (event.getPressed() == initializerKey) {
|
||||||
|
|
||||||
// Always cancel event
|
// Always cancel event
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
||||||
// Start combo
|
// Start combo
|
||||||
playerData.setSkillCasting(new CustomSkillCastingHandler(playerData));
|
playerData.setSkillCasting(new CustomSkillCastingHandler(playerData));
|
||||||
if (beginComboSound != null)
|
if (beginComboSound != null)
|
||||||
beginComboSound.playTo(player);
|
beginComboSound.playTo(player);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Set<PlayerKey> firstKeys = playerData.getProfess().getFirstComboKeys().isEmpty() ? firstComboKeys : playerData.getProfess().getFirstComboKeys();
|
||||||
|
if (firstKeys.contains(event.getPressed())) {
|
||||||
|
|
||||||
|
// Always cancel event
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
// Start combo
|
||||||
|
CustomSkillCastingHandler casting =new CustomSkillCastingHandler(playerData);
|
||||||
|
playerData.setSkillCasting(casting);
|
||||||
|
casting.current.registerKey(event.getPressed());
|
||||||
|
if (beginComboSound != null)
|
||||||
|
beginComboSound.playTo(player);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Adding pressed key
|
// Adding pressed key
|
||||||
CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting();
|
CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting();
|
||||||
casting.current.registerKey(event.getPressed());
|
casting.current.registerKey(event.getPressed());
|
||||||
@ -172,54 +201,63 @@ public class KeyCombos implements Listener {
|
|||||||
CustomSkillCastingHandler(PlayerData caster) {
|
CustomSkillCastingHandler(PlayerData caster) {
|
||||||
super(caster, 10);
|
super(caster, 10);
|
||||||
if (!caster.getProfess().getKeyCombos().isEmpty()) {
|
if (!caster.getProfess().getKeyCombos().isEmpty()) {
|
||||||
classCombos=caster.getProfess().getKeyCombos();
|
classCombos = caster.getProfess().getKeyCombos();
|
||||||
classLongestCombo=caster.getProfess().getLongestCombo();
|
classLongestCombo = caster.getProfess().getLongestCombo();
|
||||||
} else {
|
} else {
|
||||||
classCombos = combos;
|
classCombos = combos;
|
||||||
classLongestCombo=longestCombo;
|
classLongestCombo = longestCombo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTick() {
|
public void onTick() {
|
||||||
if (actionBarOptions != null)
|
if (actionBarOptions != null)
|
||||||
getCaster().displayActionBar(actionBarOptions.format(this));
|
if (actionBarOptions.isSubtitle)
|
||||||
|
getCaster().getPlayer().sendTitle(" ", actionBarOptions.format(this), 0, 20, 0);
|
||||||
|
else
|
||||||
|
getCaster().displayActionBar(actionBarOptions.format(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class ActionBarOptions {
|
private class ActionBarOptions {
|
||||||
private final String separator, noKey;
|
private final String separator, noKey, prefix, suffix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the names for all the players keys. Used when displaying
|
* Saves the names for all the players keys. Used when displaying
|
||||||
* the current player's key combo on the action bar
|
* the current player's key combo on the action bar
|
||||||
*/
|
*/
|
||||||
private final Map<PlayerKey, String> keyNames = new HashMap<>();
|
private final Map<PlayerKey, String> keyNames = new HashMap<>();
|
||||||
|
private final boolean isSubtitle;
|
||||||
|
|
||||||
ActionBarOptions(ConfigurationSection config) {
|
ActionBarOptions(ConfigurationSection config) {
|
||||||
|
this.prefix = config.contains("prefix") ? config.getString("prefix") : "";
|
||||||
|
this.suffix = config.contains("suffix") ? config.getString("suffix") : "";
|
||||||
this.separator = Objects.requireNonNull(config.getString("separator"), "Could not find action bar option 'separator'");
|
this.separator = Objects.requireNonNull(config.getString("separator"), "Could not find action bar option 'separator'");
|
||||||
this.noKey = Objects.requireNonNull(config.getString("no-key"), "Could not find action bar option 'no-key'");
|
this.noKey = Objects.requireNonNull(config.getString("no-key"), "Could not find action bar option 'no-key'");
|
||||||
|
this.isSubtitle = config.getBoolean("" + "", false);
|
||||||
for (PlayerKey key : PlayerKey.values())
|
for (PlayerKey key : PlayerKey.values())
|
||||||
keyNames.put(key, Objects.requireNonNull(config.getString("key-name." + key.name()), "Could not find translation for key " + key.name()));
|
keyNames.put(key, Objects.requireNonNull(config.getString("key-name." + key.name()), "Could not find translation for key " + key.name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String format(CustomSkillCastingHandler casting) {
|
public String format(CustomSkillCastingHandler casting) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
Placeholders holders = MMOCore.plugin.actionBarManager.getActionBarPlaceholder(casting.getCaster());
|
||||||
|
|
||||||
|
builder.append(prefix);
|
||||||
// Join all keys with separator
|
// Join all keys with separator
|
||||||
String builder = casting.current.countKeys() == 0 ? noKey : keyNames.get(casting.current.getAt(0));
|
builder.append(casting.current.countKeys() == 0 ? noKey : keyNames.get(casting.current.getAt(0)));
|
||||||
int j = 1;
|
int j = 1;
|
||||||
for (; j < casting.current.countKeys(); j++)
|
for (; j < casting.current.countKeys(); j++)
|
||||||
builder += separator + keyNames.get(casting.current.getAt(j));
|
builder.append(separator + keyNames.get(casting.current.getAt(j)));
|
||||||
|
|
||||||
// All remaining
|
// All remaining
|
||||||
for (; j < casting.classLongestCombo; j++)
|
for (; j < casting.classLongestCombo; j++)
|
||||||
builder += separator + noKey;
|
builder.append(separator + noKey);
|
||||||
|
|
||||||
|
builder.append(suffix);
|
||||||
return MythicLib.plugin.parseColors(builder);
|
return holders.apply(casting.getCaster().getPlayer(), builder.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,6 +227,9 @@ combat-log:
|
|||||||
# skills, etc.) when selecting a new class
|
# skills, etc.) when selecting a new class
|
||||||
save-default-class-info: false
|
save-default-class-info: false
|
||||||
|
|
||||||
|
#Time taken in ticks to teleport using waypoints.
|
||||||
|
waypoint-warp-time: 100
|
||||||
|
|
||||||
# Change this to the name of the color you want for
|
# Change this to the name of the color you want for
|
||||||
# the different resource bar placeholders
|
# the different resource bar placeholders
|
||||||
resource-bar-colors:
|
resource-bar-colors:
|
||||||
@ -252,4 +255,5 @@ command-verbose:
|
|||||||
skill-tree-points: true
|
skill-tree-points: true
|
||||||
points: true
|
points: true
|
||||||
reset: true
|
reset: true
|
||||||
resource: true
|
resource: true
|
||||||
|
waypoint: true
|
@ -0,0 +1,9 @@
|
|||||||
|
#Example
|
||||||
|
test-condition:
|
||||||
|
- 'level{amount=10}'
|
||||||
|
#Will load the 2 conditions from test-condition-2.
|
||||||
|
- 'from{source=test-condition-2}'
|
||||||
|
|
||||||
|
test-condition-2:
|
||||||
|
- 'world{name=world}'
|
||||||
|
- 'level{profession=MINING;amount=3}'
|
@ -1,143 +0,0 @@
|
|||||||
id: autocombat
|
|
||||||
name: AutoCombat
|
|
||||||
type: automatic
|
|
||||||
item: GOLDEN_AXE
|
|
||||||
lore:
|
|
||||||
- '&6This autoskill tree is used for combat abilities!'
|
|
||||||
|
|
||||||
nodes:
|
|
||||||
strength:
|
|
||||||
name: 'Combat strength'
|
|
||||||
children:
|
|
||||||
strong:
|
|
||||||
force: 2
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
#modifers
|
|
||||||
|
|
||||||
force:
|
|
||||||
name: 'Force'
|
|
||||||
size: 1
|
|
||||||
max-children: 1
|
|
||||||
children:
|
|
||||||
strong:
|
|
||||||
weaponry: 1
|
|
||||||
archery: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
|
|
||||||
weaponry:
|
|
||||||
name: 'Weaponry'
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
|
|
||||||
archery:
|
|
||||||
name: 'Archery'
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
children:
|
|
||||||
strong:
|
|
||||||
archery2: 2
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
archery2:
|
|
||||||
name: 'Archery2'
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
children:
|
|
||||||
strong:
|
|
||||||
archery3: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
archery3:
|
|
||||||
name: 'Archery3'
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
icons:
|
|
||||||
unlocked:
|
|
||||||
1:
|
|
||||||
item: 'GREEN_DYE'
|
|
||||||
locked:
|
|
||||||
1:
|
|
||||||
item: "BROWN_DYE"
|
|
||||||
unlockable:
|
|
||||||
1:
|
|
||||||
item: "BLUE_DYE"
|
|
||||||
fully-locked:
|
|
||||||
1:
|
|
||||||
item: "BLACK_DYE"
|
|
||||||
path:
|
|
||||||
item: "WHITE_DYE"
|
|
@ -1,152 +0,0 @@
|
|||||||
id: 'combat'
|
|
||||||
name: '&4Combat'
|
|
||||||
lore:
|
|
||||||
- '&6This skill tree is used for combat abilities!'
|
|
||||||
type: 'linked'
|
|
||||||
item: 'DIAMOND_AXE'
|
|
||||||
nodes:
|
|
||||||
strength:
|
|
||||||
name: 'Combat strength'
|
|
||||||
coordinates:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
is-root: true
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
#modifers
|
|
||||||
|
|
||||||
force:
|
|
||||||
name: 'Force'
|
|
||||||
size: 1
|
|
||||||
max-children: 1
|
|
||||||
coordinates:
|
|
||||||
x: 1
|
|
||||||
y: 0
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
|
|
||||||
weaponry:
|
|
||||||
name: 'Weaponry'
|
|
||||||
coordinates:
|
|
||||||
x: 2
|
|
||||||
y: 0
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
|
|
||||||
archery:
|
|
||||||
name: 'Archery'
|
|
||||||
coordinates:
|
|
||||||
x: 1
|
|
||||||
y: 1
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
archery2:
|
|
||||||
name: 'Archery2'
|
|
||||||
coordinates:
|
|
||||||
x: 1
|
|
||||||
y: 2
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
archery3:
|
|
||||||
name: 'Archery3'
|
|
||||||
coordinates:
|
|
||||||
x: 1
|
|
||||||
y: 3
|
|
||||||
|
|
||||||
max-level: 2
|
|
||||||
size: 1
|
|
||||||
lores:
|
|
||||||
unlocked:
|
|
||||||
1 :
|
|
||||||
- "&eYou are level 1"
|
|
||||||
2:
|
|
||||||
- "&eYou are level 2"
|
|
||||||
locked:
|
|
||||||
- "&4This skill is locked"
|
|
||||||
unlockable:
|
|
||||||
- "&aThis skill is unlockable"
|
|
||||||
fully-locked:
|
|
||||||
- '&aThis is skill is fully locked'
|
|
||||||
|
|
||||||
paths:
|
|
||||||
coordinates:
|
|
||||||
x: 2
|
|
||||||
y: 2
|
|
||||||
|
|
||||||
icons:
|
|
||||||
unlocked:
|
|
||||||
1:
|
|
||||||
item: 'GREEN_DYE'
|
|
||||||
locked:
|
|
||||||
1:
|
|
||||||
item: "BROWN_DYE"
|
|
||||||
unlockable:
|
|
||||||
1:
|
|
||||||
item: "BLUE_DYE"
|
|
||||||
fully-locked:
|
|
||||||
1:
|
|
||||||
item: "BLACK_DYE"
|
|
||||||
path:
|
|
||||||
item: "WHITE_DYE"
|
|
Loading…
Reference in New Issue
Block a user