getFaces() {
+ return faces;
+ }
+
+ @Override
+ public boolean breakRestrictions(@NotNull Block block) {
+ return true;
+ }
+
+ @Override
+ public void place(RegeneratingBlock block) {
+ Location loc = block.getLocation();
+ block.getLocation().getBlock().setType(type);
+
+ var state = (MultipleFacing) loc.getBlock().getBlockData();
+ for (var face : faces) state.setFace(face, true);
+ loc.getBlock().setBlockData(state);
+ }
+
+ @Override
+ public void regenerate(RegeneratingBlock block) {
+ Location loc = block.getLocation();
+ loc.getBlock().setType(type);
+ // Sets the original blocks old data (only when regenerating)
+ loc.getBlock().setBlockData(block.getBlockData());
+ }
+
+ @Override
+ public @NotNull String display() {
+ return "Mushroom{type=" + type.name() + ", faces=[" + this.faces.stream().map(BlockFace::name).reduce((a, b) -> a + ", " + b).orElse("") + "]}";
+ }
+
+ @Override
+ public String toString() {
+ return display();
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) return true;
+ if (object == null || getClass() != object.getClass()) return false;
+ MushroomBlockType that = (MushroomBlockType) object;
+ return Objects.equals(faces, that.faces) && type == that.type;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(faces, type);
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/NoteBlockType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/NoteBlockType.java
new file mode 100644
index 00000000..45a7f13b
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/NoteBlockType.java
@@ -0,0 +1,84 @@
+package net.Indyuce.mmocore.api.block;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.api.MMOLineConfig;
+import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
+import org.bukkit.Instrument;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Note;
+import org.bukkit.block.Block;
+import org.bukkit.block.data.type.NoteBlock;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+public class NoteBlockType implements BlockType {
+ private final Instrument instrument;
+ private final Note note;
+
+ public NoteBlockType(MMOLineConfig config) {
+ config.validateKeys("note");
+
+ instrument = config.contains("instrument")
+ ? UtilityMethods.prettyValueOf(Instrument::valueOf, config.getString("instrument"), "No instrument with ID '%s'")
+ : Instrument.PIANO;
+ note = new Note(config.getInt("note"));
+ }
+
+ public NoteBlockType(@NotNull Block block) {
+ final var state = (NoteBlock) block.getBlockData();
+ this.instrument = state.getInstrument();
+ this.note = state.getNote();
+ }
+
+ public Instrument getInstrument() {
+ return instrument;
+ }
+
+ public Note getNote() {
+ return note;
+ }
+
+ @Override
+ public boolean breakRestrictions(@NotNull Block block) {
+ return true;
+ }
+
+ @Override
+ public void place(RegeneratingBlock block) {
+ Location loc = block.getLocation();
+ block.getLocation().getBlock().setType(Material.NOTE_BLOCK);
+
+ NoteBlock state = (NoteBlock) loc.getBlock().getBlockData();
+ state.setInstrument(instrument);
+ state.setNote(note);
+ loc.getBlock().setBlockData(state);
+ }
+
+ @Override
+ public void regenerate(RegeneratingBlock block) {
+ Location loc = block.getLocation();
+ loc.getBlock().setType(Material.NOTE_BLOCK);
+ // Sets the original blocks old data (only when regenerating)
+ loc.getBlock().setBlockData(block.getBlockData());
+ }
+
+ @Override
+ public @NotNull String display() {
+ return "NoteBlock{instrument=" + instrument.name() + ", note=" + note.getId() + "}";
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) return true;
+ if (object == null || getClass() != object.getClass()) return false;
+ NoteBlockType that = (NoteBlockType) object;
+ return instrument == that.instrument && Objects.equals(note, that.note);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(instrument, note);
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/RegenInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/RegenInfo.java
index fa44e8d8..4de88248 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/RegenInfo.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/RegenInfo.java
@@ -1,8 +1,8 @@
package net.Indyuce.mmocore.api.block;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
public class RegenInfo {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/SkullBlockType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/SkullBlockType.java
index 61d2cac5..525f2148 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/SkullBlockType.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/SkullBlockType.java
@@ -7,6 +7,7 @@ import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
+import org.jetbrains.annotations.NotNull;
import java.util.Objects;
@@ -49,7 +50,7 @@ public class SkullBlockType implements BlockType {
}
@Override
- public String display() {
+ public @NotNull String display() {
return "Skull{" + value + "}";
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/VanillaBlockType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/VanillaBlockType.java
index 84dafe93..7a4fcea3 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/VanillaBlockType.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/VanillaBlockType.java
@@ -1,13 +1,15 @@
package net.Indyuce.mmocore.api.block;
+import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
-import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.Ageable;
import org.bukkit.block.data.BlockData;
+import org.jetbrains.annotations.NotNull;
import java.util.Objects;
@@ -23,7 +25,7 @@ public class VanillaBlockType implements BlockType {
public VanillaBlockType(MMOLineConfig config) {
config.validate("type");
- type = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
+ type = UtilityMethods.prettyValueOf(Material::valueOf, config.getString("type"), "No material with ID %s");
age = config.getInt("age", 0);
Validate.isTrue(age >= 0 && age < 8, "Age must be between 0 and 7");
@@ -43,8 +45,8 @@ public class VanillaBlockType implements BlockType {
Location loc = block.getLocation();
block.getLocation().getBlock().setType(type);
- BlockData state = block.getLocation().getBlock().getBlockData();
- if (age > 0 && state instanceof Ageable) {
+ BlockData state;
+ if (age > 0 && (state = block.getLocation().getBlock().getBlockData()) instanceof Ageable) {
((Ageable) state).setAge(age);
loc.getBlock().setBlockData(state);
}
@@ -59,7 +61,7 @@ public class VanillaBlockType implements BlockType {
}
@Override
- public String display() {
+ public @NotNull String display() {
return "Vanilla{" + type.name() + "}";
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/MMOCommandEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/MMOCommandEvent.java
index f723c663..6f8437ec 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/MMOCommandEvent.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/MMOCommandEvent.java
@@ -1,45 +1,50 @@
package net.Indyuce.mmocore.api.event;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
-/**
- * @deprecated Use Bukkit event instead
- */
-@Deprecated
+// TODO move to MythicLib
public class MMOCommandEvent extends PlayerDataEvent implements Cancellable {
- private static final HandlerList handlers = new HandlerList();
+ private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
- private final String command;
+ private final String command;
- public MMOCommandEvent(PlayerData player, String command) {
- super(player);
+ @Deprecated
+ public MMOCommandEvent(PlayerData player, String command) {
+ super(player);
- this.command = command;
- }
+ this.command = command;
+ }
- public String getCommand() {
- return command;
- }
+ public MMOCommandEvent(PlayerData player, CommandTreeRoot command) {
+ super(player);
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
+ this.command = command.getId();
+ }
- public static HandlerList getHandlerList() {
- return handlers;
- }
+ public String getCommand() {
+ return command;
+ }
- @Override
- public boolean isCancelled() {
- return cancelled;
- }
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
- @Override
- public void setCancelled(boolean b) {
- cancelled = b;
- }
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ cancelled = b;
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerChangeClassEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerChangeClassEvent.java
index 2402a209..eddb1347 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerChangeClassEvent.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerChangeClassEvent.java
@@ -4,44 +4,81 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
public class PlayerChangeClassEvent extends PlayerDataEvent implements Cancellable {
- private static final HandlerList handlers = new HandlerList();
+ private static final HandlerList HANDLERS = new HandlerList();
- private final PlayerClass newClass;
+ private final PlayerClass newClass;
+ private final Reason reason;
- private boolean cancelled = false;
+ private boolean cancelled = false;
- public PlayerChangeClassEvent(PlayerData player, PlayerClass newClass) {
- super(player);
+ @Deprecated
+ public PlayerChangeClassEvent(PlayerData player, PlayerClass newClass) {
+ this(player, newClass, Reason.UNKNOWN);
+ }
- this.newClass = newClass;
- }
+ public PlayerChangeClassEvent(PlayerData player, PlayerClass newClass, Reason reason) {
+ super(player);
- public PlayerClass getNewClass() {
- return newClass;
- }
+ this.reason = reason;
+ this.newClass = newClass;
+ }
- public boolean isSubclass() {
- return getData().getProfess().getSubclasses().stream().anyMatch(sub -> sub.getProfess().equals(newClass));
- }
+ @NotNull
+ public Reason getReason() {
+ return reason;
+ }
- @Override
- public boolean isCancelled() {
- return cancelled;
- }
+ @NotNull
+ public PlayerClass getNewClass() {
+ return newClass;
+ }
- @Override
- public void setCancelled(boolean value) {
- cancelled = value;
- }
+ public boolean isSubclass() {
+ return getData().getProfess().getSubclasses().stream().anyMatch(sub -> sub.getProfess().equals(newClass));
+ }
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
- public static HandlerList getHandlerList() {
- return handlers;
- }
+ @Override
+ public void setCancelled(boolean value) {
+ cancelled = value;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+
+ public static enum Reason {
+
+ /**
+ * Class is selected (class switch) by an admin command.
+ */
+ COMMAND_SELECT,
+
+ /**
+ * Class is forcefully changed by an admin command.
+ */
+ COMMAND_FORCE,
+
+ /**
+ * When the player changes class using the class change GUI
+ */
+ GUI,
+
+ /**
+ * Not specified by user
+ */
+ UNKNOWN
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerExperienceGainEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerExperienceGainEvent.java
index cb81d342..337282a3 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerExperienceGainEvent.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerExperienceGainEvent.java
@@ -5,6 +5,7 @@ import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.Profession;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PlayerExperienceGainEvent extends PlayerDataEvent implements Cancellable {
@@ -17,11 +18,11 @@ public class PlayerExperienceGainEvent extends PlayerDataEvent implements Cancel
private double experience;
private boolean cancelled;
- public PlayerExperienceGainEvent(PlayerData player, double experience, EXPSource source) {
+ public PlayerExperienceGainEvent(@NotNull PlayerData player, double experience, @NotNull EXPSource source) {
this(player, null, experience, source);
}
- public PlayerExperienceGainEvent(PlayerData player, @Nullable Profession profession, double experience, EXPSource source) {
+ public PlayerExperienceGainEvent(@NotNull PlayerData player, @Nullable Profession profession, double experience, @NotNull EXPSource source) {
super(player);
this.profession = profession;
@@ -56,16 +57,18 @@ public class PlayerExperienceGainEvent extends PlayerDataEvent implements Cancel
return profession != null;
}
+ @Nullable
public Profession getProfession() {
return profession;
}
+ @NotNull
public EXPSource getSource() {
return source;
}
@Override
- public HandlerList getHandlers() {
+ public @NotNull HandlerList getHandlers() {
return handlers;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerLevelChangeEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerLevelChangeEvent.java
new file mode 100644
index 00000000..e19abb97
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerLevelChangeEvent.java
@@ -0,0 +1,104 @@
+package net.Indyuce.mmocore.api.event;
+
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.experience.Profession;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PlayerLevelChangeEvent extends PlayerDataEvent {
+ private final int oldLevel, newLevel;
+ @Nullable(value = "null if class levels")
+ private final Profession profession;
+ private final Reason reason;
+
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ @Deprecated
+ public PlayerLevelChangeEvent(PlayerData player, int oldLevel, int newLevel) {
+ this(player, null, oldLevel, newLevel, Reason.UNKNOWN);
+ }
+
+ @Deprecated
+ public PlayerLevelChangeEvent(PlayerData player, Profession profession, int oldLevel, int newLevel) {
+ this(player, profession, oldLevel, newLevel, Reason.UNKNOWN);
+ }
+
+ public PlayerLevelChangeEvent(PlayerData player, @Nullable Profession profession, int oldLevel, int newLevel, Reason reason) {
+ super(player);
+
+ this.profession = profession;
+ this.oldLevel = oldLevel;
+ this.newLevel = newLevel;
+ this.reason = reason;
+ }
+
+ @NotNull
+ public Reason getReason() {
+ return reason;
+ }
+
+ public int getNewLevel() {
+ return newLevel;
+ }
+
+ public int getOldLevel() {
+ return oldLevel;
+ }
+
+ public boolean hasProfession() {
+ return profession != null;
+ }
+
+ @Nullable
+ public Profession getProfession() {
+ return profession;
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+
+ public static enum Reason {
+
+ /**
+ * Players level up one of their profession or main class
+ */
+ LEVEL_UP,
+
+ /**
+ * Command to change the player's level
+ */
+ COMMAND,
+
+ /**
+ * Their level is reset using the player data reset command
+ */
+ RESET,
+
+ /**
+ * When a player changes their current class
+ */
+ CHOOSE_CLASS,
+
+ /**
+ * When a player logs in or chooses their profile
+ */
+ CHOOSE_PROFILE,
+
+ /**
+ * Not provided by the user
+ */
+ UNKNOWN,
+
+ /**
+ * Not used internally
+ */
+ OTHER,
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerLevelUpEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerLevelUpEvent.java
index 19e984b5..91f1f754 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerLevelUpEvent.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerLevelUpEvent.java
@@ -5,48 +5,64 @@ import net.Indyuce.mmocore.experience.Profession;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.Nullable;
+/**
+ * @see PlayerLevelChangeEvent
+ * @see net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent.Reason#LEVEL_UP
+ * @deprecated Level up can now be detected through PlayerLevelChangeEvent with a reason of LEVEL_UP.
+ */
+@Deprecated
public class PlayerLevelUpEvent extends PlayerDataEvent {
- private static final HandlerList handlers = new HandlerList();
+ private static final HandlerList handlers = new HandlerList();
- // If null, this is main level
- private final Profession profession;
- private final int oldLevel, newLevel;
+ // If null, this is main level
+ private final Profession profession;
+ private final int oldLevel, newLevel;
- public PlayerLevelUpEvent(PlayerData player, int oldLevel, int newLevel) {
- this(player, null, oldLevel, newLevel);
- }
+ /**
+ * @see PlayerLevelChangeEvent
+ * @deprecated
+ */
+ @Deprecated
+ public PlayerLevelUpEvent(PlayerData player, int oldLevel, int newLevel) {
+ this(player, null, oldLevel, newLevel);
+ }
- public PlayerLevelUpEvent(PlayerData player, Profession profession, int oldLevel, int newLevel) {
- super(player);
+ /**
+ * @see PlayerLevelChangeEvent
+ * @deprecated
+ */
+ @Deprecated
+ public PlayerLevelUpEvent(PlayerData player, Profession profession, int oldLevel, int newLevel) {
+ super(player);
- this.profession = profession;
- this.oldLevel = oldLevel;
- this.newLevel = newLevel;
- }
+ this.profession = profession;
+ this.oldLevel = oldLevel;
+ this.newLevel = newLevel;
+ }
- public int getNewLevel() {
- return newLevel;
- }
+ public int getNewLevel() {
+ return newLevel;
+ }
- public int getOldLevel() {
- return oldLevel;
- }
+ public int getOldLevel() {
+ return oldLevel;
+ }
- public boolean hasProfession() {
- return profession != null;
- }
+ public boolean hasProfession() {
+ return profession != null;
+ }
- @Nullable
- public Profession getProfession() {
- return profession;
- }
+ @Nullable
+ public Profession getProfession() {
+ return profession;
+ }
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
- public static HandlerList getHandlerList() {
- return handlers;
- }
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerResourceUpdateEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerResourceUpdateEvent.java
index f0768dfa..0e8146a4 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerResourceUpdateEvent.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerResourceUpdateEvent.java
@@ -5,131 +5,180 @@ import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.api.quest.trigger.ManaTrigger;
import net.Indyuce.mmocore.api.quest.trigger.StaminaTrigger;
import net.Indyuce.mmocore.api.quest.trigger.StelliumTrigger;
-import net.Indyuce.mmocore.command.rpg.admin.ResourceCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.admin.ResourceCommandTreeNode;
import net.Indyuce.mmocore.skill.list.Neptune_Gift;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
public class PlayerResourceUpdateEvent extends PlayerDataEvent implements Cancellable {
- private static final HandlerList handlers = new HandlerList();
+ private static final HandlerList HANDLERS = new HandlerList();
- /**
- * Type of resource being regenerated, this way
- * this event handles all four resources.
- */
- private final PlayerResource resource;
- private final UpdateReason reason;
+ /**
+ * Type of resource being regenerated, this way
+ * this event handles all four resources.
+ */
+ private final PlayerResource resource;
+ private final UpdateReason reason;
+ private final double oldAmount, originalNewAmount;
- /**
- * Amount of resource regenerated. The whole point of the event is
- * being able to modify it, for instance to apply the mana regeneration stat.
- */
- private double amount;
+ /**
+ * New amount. To obtain the amount of resource regenerated, if REASON
+ * is REGENERATION, you must subtract oldAmount from newAmount.
+ */
+ private double newAmount;
- private boolean cancelled = false;
+ private boolean cancelled = false;
- /**
- * Called when a player gains some resource back. This can
- * be used to handle stats like health or mana regeneration.
- *
- * Example use: {@link Neptune_Gift} which is a skill
- * that temporarily increases resource regeneration for a short amount of time.
- *
- * @param playerData Player regenerating
- * @param resource Resource being increased
- * @param amount Amount being taken away/regenerated
- * @param reason The reason why this event was called
- */
- public PlayerResourceUpdateEvent(PlayerData playerData, PlayerResource resource, double amount, UpdateReason reason) {
- super(playerData);
+ /**
+ * Called when a player gains some resource back. This can
+ * be used to handle stats like health or mana regeneration.
+ *
+ * Example use: {@link Neptune_Gift} which is a skill
+ * that temporarily increases resource regeneration for a short amount of time.
+ *
+ * @param playerData Player regenerating
+ * @param resource Resource being increased
+ * @param oldAmount The old amount of resource before this event was called. Not modifiable.
+ * @param newAmount The new amount of resource after this event was called. Modifiable.
+ * @param reason The reason why this event was called
+ */
+ public PlayerResourceUpdateEvent(@NotNull PlayerData playerData, @NotNull PlayerResource resource, double oldAmount, double newAmount, @NotNull UpdateReason reason) {
+ super(playerData);
- this.resource = resource;
- this.amount = amount;
- this.reason = reason;
- }
+ this.resource = resource;
+ this.oldAmount = oldAmount;
+ this.originalNewAmount = newAmount;
+ this.newAmount = newAmount;
+ this.reason = reason;
+ }
- public PlayerResource getResource() {
- return resource;
- }
+ @NotNull
+ public PlayerResource getResource() {
+ return resource;
+ }
- public double getAmount() {
- return amount;
- }
+ @Deprecated
+ public double getAmount() {
+ return getDifference();
+ }
- public UpdateReason getReason() {
- return reason;
- }
+ public double getDifference() {
+ return newAmount - oldAmount;
+ }
- /**
- * Changes the amount of resource given/taken away
- *
- * @param amount New amount
- */
- public void setAmount(double amount) {
- this.amount = amount;
- }
+ public double getNewAmount() {
+ return newAmount;
+ }
- @Override
- public boolean isCancelled() {
- return cancelled;
- }
+ public double getOriginalNewAmount() {
+ return originalNewAmount;
+ }
- @Override
- public void setCancelled(boolean cancelled) {
- this.cancelled = cancelled;
- }
+ public double getOldAmount() {
+ return oldAmount;
+ }
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
+ @NotNull
+ public UpdateReason getReason() {
+ return reason;
+ }
- public static HandlerList getHandlerList() {
- return handlers;
- }
+ /**
+ * @see #setNewAmount(double)
+ * @deprecated
+ */
+ @Deprecated
+ public void setAmount(double amount) {
+ this.setNewAmount(amount + oldAmount);
+ }
- public enum UpdateReason {
+ /**
+ * Sets the new amount of resource after the update.
+ * Will not be applied if the event is cancelled.
+ *
+ * @param newAmount New amount of resource
+ */
+ public void setNewAmount(double newAmount) {
+ this.newAmount = newAmount;
+ }
- /**
- * When resource is being regenerated
- */
- REGENERATION,
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
- /**
- * When some resource is gained, or consumed by some skills
- */
- SKILL_REGENERATION,
+ @Override
+ public void setCancelled(boolean cancelled) {
+ this.cancelled = cancelled;
+ }
- /**
- * When some resource is gained, or consumed by some skills
- */
- SKILL_COST,
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return HANDLERS;
+ }
- /**
- * When consuming stellium to use a waypoint
- */
- USE_WAYPOINT,
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
- /**
- * Used by quests triggers
- * - {@link ManaTrigger}
- * - {@link StaminaTrigger}
- * - {@link StelliumTrigger}
- */
- TRIGGER,
+ public enum UpdateReason {
- /**
- * When using the resource command {@link ResourceCommandTreeNode}
- */
- COMMAND,
+ /**
+ * When resource is being regenerated
+ */
+ REGENERATION,
- /**
- * Anything else
- */
- OTHER;
+ /**
+ * When some resource is gained, or consumed by some skills
+ */
+ SKILL_REGENERATION,
- public boolean isSkill() {
- return this == SKILL_COST || this == SKILL_REGENERATION;
- }
- }
+ /**
+ * When some resource is gained, or consumed by some skills
+ */
+ SKILL_COST,
+
+ /**
+ * When consuming stellium to use a waypoint
+ */
+ USE_WAYPOINT,
+
+ /**
+ * When the player chooses a class and mana from their previous
+ * game session is restored
+ */
+ CHOOSE_CLASS,
+
+ /**
+ * Used by quests triggers
+ * - {@link ManaTrigger}
+ * - {@link StaminaTrigger}
+ * - {@link StelliumTrigger}
+ */
+ TRIGGER,
+
+ /**
+ * When using the resource command {@link ResourceCommandTreeNode}
+ */
+ COMMAND,
+
+ /**
+ * Reason not provided by user
+ */
+ UNKNOWN,
+
+ /**
+ * Anything else
+ */
+ OTHER;
+
+ public boolean isRegeneration() {
+ return this == REGENERATION || this == SKILL_REGENERATION;
+ }
+
+ public boolean isSkill() {
+ return this == SKILL_COST || this == SKILL_REGENERATION;
+ }
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java
index f9350725..71d5692e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/GuildChatEvent.java
@@ -5,32 +5,36 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.guild.provided.Guild;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Objects;
public class GuildChatEvent extends PlayerDataEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Guild guild;
- private boolean cancelled;
-
- @Deprecated
private String message;
+ private boolean cancelled;
public GuildChatEvent(PlayerData playerData, String message) {
super(playerData);
+
this.guild = playerData.getGuild();
this.message = message;
}
- public void setMessage(String message) {
+ public void setMessage(@Nullable String message) {
this.message = message;
}
- @Deprecated
+ @Nullable
public String getMessage() {
return message;
}
+ @NotNull
public Guild getGuild() {
return guild;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/PartyChatEvent.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/PartyChatEvent.java
index 29802662..49dbbaef 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/PartyChatEvent.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/social/PartyChatEvent.java
@@ -5,6 +5,10 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.party.provided.Party;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Objects;
public class PartyChatEvent extends PlayerDataEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@@ -12,23 +16,25 @@ public class PartyChatEvent extends PlayerDataEvent implements Cancellable {
private final Party party;
private boolean cancelled;
- private String message;
+ private String rawMessage;
- public PartyChatEvent(Party party, PlayerData playerData, String message) {
+ public PartyChatEvent(Party party, PlayerData playerData, String rawMessage) {
super(playerData);
this.party = party;
- this.message = message;
+ this.rawMessage = rawMessage;
}
- public void setMessage(String message) {
- this.message = message;
+ public void setMessage(@Nullable String rawMessage) {
+ this.rawMessage = Objects.requireNonNull(rawMessage, "Message cannot be null");
}
+ @Nullable
public String getMessage() {
- return message;
+ return rawMessage;
}
+ @NotNull
public Party getParty() {
return party;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java
index 74d3a2ad..6a969a21 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/load/DefaultMMOLoader.java
@@ -1,9 +1,7 @@
package net.Indyuce.mmocore.api.load;
import io.lumine.mythic.lib.api.MMOLineConfig;
-import net.Indyuce.mmocore.api.block.BlockType;
-import net.Indyuce.mmocore.api.block.SkullBlockType;
-import net.Indyuce.mmocore.api.block.VanillaBlockType;
+import net.Indyuce.mmocore.api.block.*;
import net.Indyuce.mmocore.api.quest.objective.*;
import net.Indyuce.mmocore.api.quest.trigger.*;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
@@ -196,8 +194,11 @@ public class DefaultMMOLoader extends MMOLoader {
@Override
public BlockType loadBlockType(MMOLineConfig config) {
- if (config.getKey().equalsIgnoreCase("vanilla"))
- return new VanillaBlockType(config);
+ if (config.getKey().equalsIgnoreCase("vanilla")) return new VanillaBlockType(config);
+
+ if (config.getKey().equalsIgnoreCase("note")) return new NoteBlockType(config);
+
+ if (config.getKey().equalsIgnoreCase("mushroom")) return new MushroomBlockType(config);
if (config.getKey().equalsIgnoreCase("skull") || config.getKey().equals("head") || config.getKey().equals("playerhead"))
return new SkullBlockType(config);
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
index f1ba1bff..42db7f35 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
@@ -1,11 +1,14 @@
package net.Indyuce.mmocore.api.player;
import io.lumine.mythic.lib.MythicLib;
+import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
+import io.lumine.mythic.lib.data.SaveReason;
import io.lumine.mythic.lib.data.SynchronizedDataHolder;
import io.lumine.mythic.lib.message.actionbar.ActionBarPriority;
import io.lumine.mythic.lib.player.cooldown.CooldownMap;
-import io.lumine.mythic.lib.util.Closeable;
+import io.lumine.mythic.lib.skill.trigger.TriggerType;
+import io.lumine.mythic.lib.util.lang3.Validate;
import io.lumine.mythic.lib.version.Attributes;
import io.lumine.mythic.lib.version.VParticle;
import net.Indyuce.mmocore.MMOCore;
@@ -24,6 +27,7 @@ import net.Indyuce.mmocore.api.quest.PlayerQuests;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.ExperienceObject;
import net.Indyuce.mmocore.experience.PlayerProfessions;
@@ -32,7 +36,6 @@ import net.Indyuce.mmocore.experience.droptable.ExperienceItem;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.gui.skilltree.NodeIncrementResult;
import net.Indyuce.mmocore.guild.provided.Guild;
-import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
import net.Indyuce.mmocore.manager.data.OfflinePlayerData;
import net.Indyuce.mmocore.party.AbstractParty;
import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
@@ -48,12 +51,13 @@ import net.Indyuce.mmocore.skill.binding.SkillSlot;
import net.Indyuce.mmocore.skill.cast.SkillCastingInstance;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import net.Indyuce.mmocore.skilltree.NodeState;
+import net.Indyuce.mmocore.skilltree.ParentInformation;
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
+import net.Indyuce.mmocore.skilltree.display.PathState;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import net.Indyuce.mmocore.util.Language;
import net.Indyuce.mmocore.waypoint.Waypoint;
import net.Indyuce.mmocore.waypoint.WaypointOption;
-import org.apache.commons.lang.Validate;
import org.bukkit.*;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
@@ -67,7 +71,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.stream.Collectors;
-public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerData, Closeable, ClassDataContainer {
+public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerData, ClassDataContainer {
/**
* Can be null, the {@link #getProfess()} method will return the
@@ -85,7 +89,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
/**
* Saving resources (especially health) right in player data fixes TONS of issues.
*/
- private double health, mana, stamina, stellium;
+ private double lastHealth, lastMana, lastStamina, lastStellium;
+ private double mana, stamina, stellium;
private Guild guild;
private SkillCastingInstance skillCasting;
private final PlayerQuests questData;
@@ -99,7 +104,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
* plugin-scope to check if some item is class-specific and
* should be reset when switching class
*/
- @Deprecated
private final Set waypoints = new HashSet<>();
private final Map skills = new HashMap<>();
private final Map boundSkills = new HashMap<>();
@@ -109,25 +113,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
private final Map lastActivity = new HashMap<>();
private final CombatHandler combat = new CombatHandler(this);
- /**
- * Cached data
- *
- * Current state of each node. This does not get saved in the player database
- * as it can be inferred from the skill tree node levels map.
- */
- private final Map nodeStates = new HashMap<>();
-
- private final Map nodeLevels = new HashMap<>();
- private final Map skillTreePoints = new HashMap<>();
-
- /**
- * Cached data
- *
- * Amount of points spent in each tree. This does not get saved in the
- * player database as it can be inferred from the skill tree node levels map.
- */
- private final Map skillTreePointsSpent = new HashMap<>();
-
/**
* Saves the NSK's of the items that have been unlocked in the format "namespace:key".
* This is used for:
@@ -196,11 +181,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
attributes.reload();
}
- @Deprecated
- public void setupRemovableTrigger() {
- applyTemporaryTriggers();
- }
-
/**
* Some triggers are marked with the {@link Removable} interface as
* they are non-permanent triggers, and they need to be re-applied
@@ -230,35 +210,117 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
node.getExperienceTable().applyTemporaryTriggers(this, node);
}
- public void setupSkillTrees() {
+ @Override
+ protected void onSessionReady() {
+
+ // Update class stats and all
+ this.setupSkillTrees();
+ this.applyTemporaryTriggers();
+ this.getStats().updateStats();
+
+ getMMOPlayerData().getProfileSession().addOpenCallback(session -> this.onProfileSessionReady());
+ }
+
+ private void castOnLoginScripts() {
+
+ // Class Skills
+ for (ClassSkill skill : getProfess().getSkills())
+ if (skill.getSkill().getTrigger() == TriggerType.LOGIN)
+ skill.toCastable(this).cast(getMMOPlayerData());
+
+ // Call Scripts
+ for (var script : getProfess().getScripts())
+ if (script.getTrigger() == TriggerType.LOGIN) script.getTriggeredSkill().cast(getMMOPlayerData());
+ }
+
+ private void onProfileSessionReady() {
+ this.castOnLoginScripts();
+
+ // Set health again
+ UtilityMethods.setHealth(getPlayer(), lastHealth);
+ setMana(lastMana, PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS);
+ setStamina(lastStamina, PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS);
+ setStellium(lastStellium, PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS);
+ }
+
+ @Override
+ public Map mapBoundSkills() {
+ Map result = new HashMap<>();
+ for (int slot : boundSkills.keySet())
+ result.put(slot, boundSkills.get(slot).getClassSkill().getSkill().getHandler().getId());
+ return result;
+ }
+
+ public void resetTriggerStats() {
+ getMMOPlayerData().getStatMap().getInstances().forEach(statInstance -> statInstance.removeIf(Trigger.STAT_MODIFIER_KEY::equals));
+ getMMOPlayerData().getSkillModifierMap().removeModifiers(Trigger.STAT_MODIFIER_KEY);
+ }
+
+ //region Skill trees
+
+ /**
+ * Current state of each node. This does not get saved in the player database
+ * as it can be inferred from the skill tree node levels map. This is used
+ * mainly for displaying the skill tree in the GUI.
+ */
+ private final Map nodeStates = new HashMap<>();
+
+ /**
+ * Current state of each path. This does not get saved in the player database
+ * as it can be inferred from the skill tree node levels map. This is used
+ * mainly for displaying the skill tree in the GUI.
+ */
+ private final Map edgeStates = new HashMap<>();
+
+ private final Map nodeLevels = new HashMap<>();
+ private final Map skillTreePoints = new HashMap<>();
+
+ /**
+ * Cached data
+ *
+ * Amount of points spent in each tree. This does not get saved in the
+ * player database as it can be inferred from the skill tree node levels map.
+ */
+ private final Map skillTreePointsSpent = new HashMap<>();
+
+ @Override
+ public int getSkillTreeReallocationPoints() {
+ return skillTreeReallocationPoints;
+ }
+
+ private void setupSkillTrees() {
// Node states setup
for (SkillTree skillTree : getProfess().getSkillTrees())
- skillTree.setupNodeStates(this);
+ skillTree.resolveStates(this);
}
public int getPointsSpent(@NotNull SkillTree skillTree) {
return skillTreePointsSpent.getOrDefault(skillTree, 0);
}
- @Deprecated
- public int getPointSpent(SkillTree skillTree) {
- return getPointsSpent(skillTree);
+ @NotNull
+ private static String asKey(@Nullable SkillTree skillTree) {
+ return skillTree == null ? Arguments.SKILL_TREE_GLOBAL_KEY : skillTree.getId();
}
- public void setSkillTreePoints(@NotNull String treeId, int points) {
- if (points <= 0) skillTreePoints.remove(treeId);
- else skillTreePoints.put(treeId, points);
+ public void setSkillTreePoints(@NotNull SkillTree skillTree, int points) {
+ setSkillTreePoints(asKey(skillTree), points);
+ }
+
+ public void setSkillTreePoints(@NotNull String skillTreeId, int points) {
+ if (points <= 0) skillTreePoints.remove(skillTreeId);
+ else skillTreePoints.put(skillTreeId, points);
+ }
+
+ public void giveSkillTreePoints(@Nullable SkillTree skillTree, int val) {
+ giveSkillTreePoints(asKey(skillTree), val);
}
public void giveSkillTreePoints(@NotNull String id, int val) {
skillTreePoints.merge(id, Math.max(0, val), (points, ignored) -> Math.max(0, points + val));
}
- public int countSkillTreePoints(@NotNull SkillTree skillTree) {
- return nodeLevels.keySet().stream().filter(node -> node.getTree().equals(skillTree)).mapToInt(node -> nodeLevels.get(node) * node.getPointConsumption()).sum();
- }
-
/**
* Make a copy to make sure that the object
* created is independent of the state of playerData.
@@ -268,14 +330,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return new HashMap<>(skillTreePoints);
}
- @Override
- public Map mapBoundSkills() {
- Map result = new HashMap<>();
- for (int slot : boundSkills.keySet())
- result.put(slot, boundSkills.get(slot).getClassSkill().getSkill().getHandler().getId());
- return result;
- }
-
public Set> getNodeLevelsEntrySet() {
HashMap nodeLevelsString = new HashMap<>();
for (SkillTreeNode node : nodeLevels.keySet())
@@ -283,11 +337,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return nodeLevelsString.entrySet();
}
- public void resetTriggerStats() {
- getMMOPlayerData().getStatMap().getInstances().forEach(statInstance -> statInstance.removeIf(Trigger.STAT_MODIFIER_KEY::equals));
- getMMOPlayerData().getSkillModifierMap().removeModifiers(Trigger.STAT_MODIFIER_KEY);
- }
-
@Override
public Map getNodeLevels() {
final Map mapped = new HashMap<>();
@@ -295,11 +344,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return mapped;
}
- @Deprecated
- public void clearSkillTrees() {
- resetSkillTrees();
- }
-
public void resetSkillTrees() {
// Un-apply triggers
@@ -310,6 +354,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
// Skill trees progress
nodeLevels.clear();
nodeStates.clear(); // Cache data
+ edgeStates.clear();
skillTreePointsSpent.clear();
tableItemClaims.keySet().removeIf(s -> s.startsWith(SkillTreeNode.KEY_PREFIX)); // Clear node claim count
@@ -321,13 +366,14 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
setupSkillTrees();
}
- public void clearNodeStates(@NotNull SkillTree skillTree) {
- for (SkillTreeNode node : skillTree.getNodes()) nodeStates.remove(node);
+ public void clearStates(@NotNull SkillTree skillTree) {
+ for (var node : skillTree.getNodes()) nodeStates.remove(node);
+ // TODO clear path states.
}
- // TODO move to UI...?
@NotNull
public NodeIncrementResult canIncrementNodeLevel(@NotNull SkillTreeNode node) {
+ // TODO move to UI...?
final var nodeState = nodeStates.get(node);
// Node is maxed out
@@ -356,10 +402,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
final int newLevel = addNodeLevels(node, 1);
node.updateAdvancement(this, newLevel); // Claim the node exp table
- // Update node state
- // TODO check/remove: USELESS LINE? since node states are updated afterwards
- // nodeStates.compute(node, (key, status) -> status == NodeState.UNLOCKABLE ? NodeState.UNLOCKED : status);
-
// Consume skill tree points
final AtomicInteger cost = new AtomicInteger(node.getPointConsumption());
skillTreePoints.computeIfPresent(node.getTree().getId(), (key, points) -> {
@@ -369,14 +411,12 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
});
if (cost.get() > 0) withdrawSkillTreePoints("global", cost.get());
- // Reload node states from full skill tree
- clearNodeStates(node.getTree());
- node.getTree().setupNodeStates(this);
+ // Reload node/path states from full skill tree
+ node.getTree().resolveStates(this);
}
- @Deprecated
- public int getSkillTreePoint(String treeId) {
- return getSkillTreePoints(treeId);
+ public int getSkillTreePoints(@Nullable SkillTree skillTree) {
+ return getSkillTreePoints(asKey(skillTree));
}
public int getSkillTreePoints(@NotNull String treeId) {
@@ -388,17 +428,20 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
skillTreePoints.computeIfPresent(treeId, (ignored, points) -> cost >= points ? null : points - cost);
}
- public void setNodeState(SkillTreeNode node, NodeState nodeState) {
+ public void setNodeState(@NotNull SkillTreeNode node, @NotNull NodeState nodeState) {
nodeStates.put(node, nodeState);
}
- public NodeState getNodeState(SkillTreeNode node) {
+ public void setPathState(@NotNull ParentInformation edge, @NotNull PathState pathState) {
+ edgeStates.put(edge, pathState);
+ }
+
+ public NodeState getNodeState(@NotNull SkillTreeNode node) {
return nodeStates.get(node);
}
- @Deprecated
- public NodeState getNodeStatus(SkillTreeNode node) {
- return getNodeState(node);
+ public PathState getPathState(@NotNull ParentInformation path) {
+ return edgeStates.get(path);
}
public boolean hasNodeState(@NotNull SkillTreeNode node) {
@@ -428,9 +471,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
for (SkillTreeNode node : skillTree.getNodes()) {
node.resetAdvancement(this, true);
setNodeLevel(node, 0);
- nodeStates.remove(node);
}
- skillTree.setupNodeStates(this);
+ skillTree.resolveStates(this);
}
@NotNull
@@ -442,6 +484,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return !nodeStates.isEmpty();
}
+ //endregion Skill trees
+
@Override
public Map getNodeTimesClaimed() {
Map result = new HashMap<>();
@@ -499,16 +543,14 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
this.unlockedItems.addAll(unlockedItems);
}
- @Deprecated
- public void resetTimesClaimed() {
- tableItemClaims.clear();
- }
-
@Override
- public void close() {
+ public void onSaved(@NotNull SaveReason reason) {
+ super.onSaved(reason);
// Saves player health before saveData as the player will be considered offline into it if it is async
- health = getPlayer().getHealth();
+ lastHealth = getPlayer().getHealth();
+
+ if (reason == SaveReason.AUTOSAVE) return;
// Remove from party if it is MMO Party Module
if (MMOCore.plugin.partyModule instanceof MMOCorePartyModule) {
@@ -619,11 +661,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return attributeReallocationPoints;
}
- @Override
- public int getSkillTreeReallocationPoints() {
- return skillTreeReallocationPoints;
- }
-
public int getClaims(@NotNull ExperienceObject object, @NotNull ExperienceItem item) {
final ExperienceTable table = object.getExperienceTable();
return getClaims(object.getKey() + "." + table.getId() + "." + item.getId());
@@ -648,16 +685,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
else tableItemClaims.put(itemKey, times);
}
- @Deprecated
- public void setClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item, int times) {
- setClaims(object.getKey() + "." + table.getId() + "." + item.getId(), times);
- }
-
- @Deprecated
- public int getClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item) {
- return getClaims(object.getKey() + "." + table.getId() + "." + item.getId());
- }
-
public Map getItemClaims() {
return tableItemClaims;
}
@@ -677,19 +704,22 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return guild != null;
}
- public void setLevel(int level) {
- this.level = Math.max(1, level);
- if (isOnline()) {
- if (isSynchronized()) getStats().updateStats();
+ public void setLevel(int level, @NotNull PlayerLevelChangeEvent.Reason reason) {
+
+ final var oldLevel = this.level;
+ final var newLevel = Math.max(1, level);
+ this.level = newLevel;
+
+ if (reason != PlayerLevelChangeEvent.Reason.CHOOSE_PROFILE) // No event, data is loaded async
+ Bukkit.getPluginManager().callEvent(new PlayerLevelChangeEvent(this, null, oldLevel, newLevel, reason));
+
+ if (getMMOPlayerData().isPlaying()) {
+ getStats().updateStats();
refreshVanillaExp();
}
}
- public void takeLevels(int value) {
- setLevel(level - value);
- }
-
- public void giveLevels(int value, EXPSource source) {
+ public void giveLevels(int value, @NotNull EXPSource source) {
long equivalentExp = 0;
while (value-- > 0) equivalentExp += getProfess().getExpCurve().getExperience(getLevel() + value + 1);
giveExperience(equivalentExp, source);
@@ -779,7 +809,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return waypoint.hasOption(WaypointOption.DEFAULT) || waypoints.contains(waypoint.getId());
}
- public void unlockWaypoint(Waypoint waypoint) {
+ public void unlockWaypoint(@NotNull Waypoint waypoint) {
+ Message.WAYPOINT_UNLOCK.send(this, "waypoint", waypoint.getName());
waypoints.add(waypoint.getId());
}
@@ -787,30 +818,88 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
waypoints.remove(waypoint.getId());
}
- /**
- * @deprecated Provide a heal reason with {@link #heal(double, PlayerResourceUpdateEvent.UpdateReason)}
- */
- @Deprecated
- public void heal(double heal) {
- this.heal(heal, PlayerResourceUpdateEvent.UpdateReason.OTHER);
- }
+ //region Resources
- public void heal(double heal, PlayerResourceUpdateEvent.UpdateReason reason) {
+ public void heal(double amount, @NotNull PlayerResourceUpdateEvent.UpdateReason reason) {
if (!isOnline()) return;
- // Avoid calling an useless event
- double max = getPlayer().getAttribute(Attributes.MAX_HEALTH).getValue();
- double newest = Math.max(0, Math.min(getPlayer().getHealth() + heal, max));
- if (getPlayer().getHealth() == newest) return;
+ final var maxValue = getPlayer().getAttribute(Attributes.MAX_HEALTH).getValue();
+ var newValue = Math.max(0, Math.min(getPlayer().getHealth() + amount, maxValue));
+ if (getPlayer().getHealth() == newValue) return;
- PlayerResourceUpdateEvent event = new PlayerResourceUpdateEvent(this, PlayerResource.HEALTH, heal, reason);
- Bukkit.getPluginManager().callEvent(event);
- if (event.isCancelled()) return;
+ if (reason != PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS) {
+ final var event = new PlayerResourceUpdateEvent(this, PlayerResource.HEALTH, getPlayer().getHealth(), newValue, reason);
+ Bukkit.getPluginManager().callEvent(event);
+ if (event.isCancelled()) return;
+ newValue = event.getNewAmount();
+ }
// Use updated amount from event
- getPlayer().setHealth(Math.max(0, Math.min(getPlayer().getHealth() + event.getAmount(), max)));
+ getPlayer().setHealth(Math.max(0, Math.min(newValue, maxValue)));
}
+ public void setMana(double amount, @NotNull PlayerResourceUpdateEvent.UpdateReason reason) {
+
+ final var maxValue = getStats().getStat("MAX_MANA");
+ var newValue = Math.max(0, Math.min(amount, maxValue));
+ if (mana == newValue) return;
+
+ if (reason != PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS) {
+ final var called = new PlayerResourceUpdateEvent(this, PlayerResource.MANA, this.mana, newValue, reason);
+ Bukkit.getPluginManager().callEvent(called);
+ if (called.isCancelled()) return;
+ newValue = called.getNewAmount();
+ }
+
+ mana = Math.max(0, Math.min(newValue, maxValue));
+ }
+
+ public void setStamina(double amount, @NotNull PlayerResourceUpdateEvent.UpdateReason reason) {
+
+ final var maxValue = getStats().getStat("MAX_STAMINA");
+ var newValue = Math.max(0, Math.min(amount, maxValue));
+ if (stamina == newValue) return;
+
+ if (reason != PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS) {
+ final var called = new PlayerResourceUpdateEvent(this, PlayerResource.STAMINA, this.stamina, newValue, reason);
+ Bukkit.getPluginManager().callEvent(called);
+ if (called.isCancelled()) return;
+ newValue = called.getNewAmount();
+ }
+
+ stamina = Math.max(0, Math.min(newValue, maxValue));
+ }
+
+ public void setStellium(double amount, @NotNull PlayerResourceUpdateEvent.UpdateReason reason) {
+
+ final var maxValue = getStats().getStat("MAX_STELLIUM");
+ var newValue = Math.max(0, Math.min(amount, maxValue));
+ if (stellium == newValue) return;
+
+ if (reason != PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS) {
+ final var called = new PlayerResourceUpdateEvent(this, PlayerResource.STELLIUM, this.stellium, newValue, reason);
+ Bukkit.getPluginManager().callEvent(called);
+ if (called.isCancelled()) return;
+ newValue = called.getNewAmount();
+ }
+
+ stellium = Math.max(0, Math.min(newValue, maxValue));
+ }
+
+ public void giveMana(double amount, @NotNull PlayerResourceUpdateEvent.UpdateReason reason) {
+ setMana(mana + amount, reason);
+ }
+
+ public void giveStamina(double amount, @NotNull PlayerResourceUpdateEvent.UpdateReason reason) {
+ setStamina(stamina + amount, reason);
+ }
+
+ public void giveStellium(double amount, @NotNull PlayerResourceUpdateEvent.UpdateReason reason) {
+ setStellium(stellium + amount, reason);
+ }
+
+ //endregion
+
public void addFriend(UUID uuid) {
friends.add(uuid);
}
@@ -903,7 +992,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
* @param value Experience to give the player
* @param source How the player earned experience
*/
- public void giveExperience(double value, EXPSource source) {
+ public void giveExperience(double value, @NotNull EXPSource source) {
giveExperience(value, source, null, true);
}
@@ -916,8 +1005,9 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
* If it's null, no hologram will be displayed
* @param splitExp Should the exp be split among party members
*/
- public void giveExperience(double value, @NotNull EXPSource source, @Nullable Location hologramLocation,
- boolean splitExp) {
+ public void giveExperience(double value, @NotNull EXPSource source, @Nullable Location hologramLocation, boolean splitExp) {
+
+ // Take exp on negative amounts
if (value <= 0) {
experience = Math.max(0, experience + value);
return;
@@ -941,40 +1031,42 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
// Apply buffs AFTER splitting exp
value *= (1 + getStats().getStat("ADDITIONAL_EXPERIENCE") / 100) * MMOCore.plugin.boosterManager.getMultiplier(null);
- PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, value, source);
+ final var event = new PlayerExperienceGainEvent(this, value, source);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) return;
// Experience hologram
if (hologramLocation != null)
- MMOCoreUtils.displayIndicator(hologramLocation, Language.EXP_HOLOGRAM.getFormat().replace("exp", MythicLib.plugin.getMMOConfig().decimal.format(event.getExperience())));
+ MMOCoreUtils.displayIndicator(hologramLocation, Language.EXP_HOLOGRAM.getFormat().replace("{exp}", MythicLib.plugin.getMMOConfig().decimal.format(event.getExperience())));
experience = Math.max(0, experience + event.getExperience());
// Calculate the player's next level
- int oldLevel = level;
- long needed;
- while (experience >= (needed = getLevelUpExperience())) {
+ final var oldLevel = level;
+ var newLevel = level;
+ long experienceNeeded;
+
+ /*
+ * Loop for exp overload when leveling up, will continue
+ * looping until exp is 0 or max currentLevel has been reached
+ */
+ while (experience >= (experienceNeeded = getProfess().getExpCurve().getExperience(newLevel + 1))) {
if (hasReachedMaxLevel()) {
experience = 0;
break;
}
- experience -= needed;
- level = getLevel() + 1;
+ experience -= experienceNeeded;
+ newLevel++;
// Apply class experience table
- getProfess().updateAdvancement(this, level);
+ getProfess().updateAdvancement(this, newLevel);
}
- if (level > oldLevel) {
- Bukkit.getPluginManager().callEvent(new PlayerLevelUpEvent(this, null, oldLevel, level));
- if (isOnline()) {
- Message.LEVEL_UP.send(this, "level", level);
- new SmallParticleEffect(getPlayer(), VParticle.INSTANT_EFFECT.get()); // TODO move to playerMessage
- }
- getStats().updateStats();
+ if (newLevel > oldLevel) {
+ setLevel(newLevel, PlayerLevelChangeEvent.Reason.LEVEL_UP); // Update 'level'
+ Message.LEVEL_UP.send(this, "level", level);
}
refreshVanillaExp();
@@ -990,79 +1082,9 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return profess == null ? MMOCore.plugin.classManager.getDefaultClass() : profess;
}
- /**
- * @deprecated Provide reason with {@link #giveMana(double, PlayerResourceUpdateEvent.UpdateReason)}
- */
- @Deprecated
- public void giveMana(double amount) {
- giveMana(amount, PlayerResourceUpdateEvent.UpdateReason.OTHER);
- }
-
- public void giveMana(double amount, PlayerResourceUpdateEvent.UpdateReason reason) {
-
- // Avoid calling useless event
- double max = getStats().getStat("MAX_MANA");
- double newest = Math.max(0, Math.min(mana + amount, max));
- if (mana == newest) return;
-
- PlayerResourceUpdateEvent event = new PlayerResourceUpdateEvent(this, PlayerResource.MANA, amount, reason);
- Bukkit.getPluginManager().callEvent(event);
- if (event.isCancelled()) return;
-
- // Use updated amount from Bukkit event
- mana = Math.max(0, Math.min(mana + event.getAmount(), max));
- }
-
- /**
- * @deprecated Provide reason with {@link #giveStamina(double, PlayerResourceUpdateEvent.UpdateReason)}
- */
- @Deprecated
- public void giveStamina(double amount) {
- giveStamina(amount, PlayerResourceUpdateEvent.UpdateReason.OTHER);
- }
-
- public void giveStamina(double amount, PlayerResourceUpdateEvent.UpdateReason reason) {
-
- // Avoid calling useless event
- double max = getStats().getStat("MAX_STAMINA");
- double newest = Math.max(0, Math.min(stamina + amount, max));
- if (stamina == newest) return;
-
- PlayerResourceUpdateEvent event = new PlayerResourceUpdateEvent(this, PlayerResource.STAMINA, amount, reason);
- Bukkit.getPluginManager().callEvent(event);
- if (event.isCancelled()) return;
-
- // Use updated amount from Bukkit event
- stamina = Math.max(0, Math.min(stamina + event.getAmount(), max));
- }
-
- /**
- * @deprecated Provide reason with {@link #giveStellium(double, PlayerResourceUpdateEvent.UpdateReason)}
- */
- @Deprecated
- public void giveStellium(double amount) {
- giveStellium(amount, PlayerResourceUpdateEvent.UpdateReason.OTHER);
- }
-
- public void giveStellium(double amount, PlayerResourceUpdateEvent.UpdateReason reason) {
-
- // Avoid calling useless event
- double max = getStats().getStat("MAX_STELLIUM");
- double newest = Math.max(0, Math.min(stellium + amount, max));
- if (stellium == newest) return;
-
- PlayerResourceUpdateEvent event = new PlayerResourceUpdateEvent(this, PlayerResource.STELLIUM, amount, reason);
- Bukkit.getPluginManager().callEvent(event);
- if (event.isCancelled()) return;
-
- // Use updated amount from Bukkit event
- stellium = Math.max(0, Math.min(stellium + event.getAmount(), max));
- }
-
- @Deprecated
@Override
- public double getHealth() {
- return isOnline() ? getPlayer().getHealth() : health;
+ public double getLastHealth() {
+ return lastHealth;
}
@Override
@@ -1079,10 +1101,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return stellium;
}
- public double getCachedHealth() {
- return health;
- }
-
public PlayerStats getStats() {
return playerStats;
}
@@ -1091,41 +1109,29 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return attributes;
}
- public void setHealth(double amount) {
- this.health = amount;
- }
+ public void loadResources(double lastHealth, double lastMana, double lastStamina, double lastStellium) {
- public void setMana(double amount) {
- mana = Math.max(0, Math.min(amount, getStats().getStat("MAX_MANA")));
- }
+ // Player started playing, update resources now
+ if (isSessionReady()) {
+ UtilityMethods.setHealth(getPlayer(), lastHealth);
+ setMana(lastMana, PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS);
+ setStamina(lastStamina, PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS);
+ setStellium(lastStellium, PlayerResourceUpdateEvent.UpdateReason.CHOOSE_CLASS);
+ }
- public void setStamina(double amount) {
- stamina = Math.max(0, Math.min(amount, getStats().getStat("MAX_STAMINA")));
- }
-
- public void setStellium(double amount) {
- stellium = Math.max(0, Math.min(amount, getStats().getStat("MAX_STELLIUM")));
- }
-
- @Deprecated
- public boolean isFullyLoaded() {
- return isSynchronized();
- }
-
- @Deprecated
- public void setFullyLoaded() {
- markAsSynchronized();
+ // Cache and load later
+ else {
+ this.lastHealth = lastHealth;
+ this.lastMana = lastMana;
+ this.lastStamina = lastStamina;
+ this.lastStellium = lastStellium;
+ }
}
public boolean isCasting() {
return skillCasting != null;
}
- @Deprecated
- public boolean setSkillCasting(@NotNull SkillCastingInstance skillCasting) {
- return setSkillCasting();
- }
-
/**
* @return If the PlayerEnterCastingModeEvent successfully put the player
* into casting mode, otherwise if the event is cancelled, returns false.
@@ -1173,38 +1179,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return true;
}
- @Deprecated
- public void displayActionBar(@NotNull String message) {
- displayActionBar(message, false);
- }
-
- @Deprecated
- public void displayActionBar(@NotNull String message, boolean raw) {
-
- // TODO add an option to disable action-bar properly in all casting modes
- if (ChatColor.stripColor(message).isEmpty()) return;
-
- // TODO move raw/not raw decision to MythicLib
- var handler = getMMOPlayerData().getActionBar();
- if (!raw) {
- handler.show(ActionBarPriority.NORMAL, message);
- } else {
- if (!handler.canShow(ActionBarPriority.NORMAL)) return;
- handler.show(ActionBarPriority.NORMAL, "");
- MythicLib.plugin.getVersion().getWrapper().sendActionBarRaw(getPlayer(), message);
- }
- }
-
- @Deprecated
- public void setAttribute(PlayerAttribute attribute, int value) {
- setAttribute(attribute.getId(), value);
- }
-
- @Deprecated
- public void setAttribute(String id, int value) {
- attributes.getInstance(id).setBase(value);
- }
-
@Override
public Map mapAttributeLevels() {
return getAttributes().mapPoints();
@@ -1226,16 +1200,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
skills.remove(skill);
}
- @Deprecated
- public boolean hasSkillUnlocked(RegisteredSkill skill) {
- return getProfess().hasSkill(skill.getHandler().getId()) && hasSkillUnlocked(getProfess().getSkill(skill.getHandler().getId()));
- }
-
- @Deprecated
- public boolean hasSkillUnlocked(ClassSkill skill) {
- return hasUnlockedLevel(skill);
- }
-
/**
* Checks for the player's level and compares it to the skill unlock level.
*
@@ -1304,11 +1268,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return found != null ? found.getClassSkill() : null;
}
- @Deprecated
- public void setBoundSkill(int slot, ClassSkill skill) {
- bindSkill(slot, skill);
- }
-
/**
* Binds a skill to the player.
*
@@ -1365,29 +1324,6 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return getCombat().isInCombat();
}
- /**
- * Loops through all the subclasses available to the player and
- * checks if they could potentially upgrade to one of these
- *
- * @return If the player can change its current class to
- * a subclass
- */
- @Deprecated
- public boolean canChooseSubclass() {
- for (Subclass subclass : getProfess().getSubclasses())
- if (getLevel() >= subclass.getLevel()) return true;
- return false;
- }
-
- /**
- * Everytime a player does a combat action, like taking
- * or dealing damage to an entity, this method is called.
- */
- @Deprecated
- public void updateCombat() {
- getCombat().update();
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -1401,6 +1337,8 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return getMMOPlayerData().hashCode();
}
+ //region Static methods
+
public static PlayerData get(@NotNull MMOPlayerData playerData) {
return get(playerData.getPlayer());
}
@@ -1448,4 +1386,259 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
public static Collection getAll() {
return MMOCore.plugin.playerDataManager.getLoaded();
}
+
+ //endregion
+
+ //region Deprecated
+
+ @Deprecated
+ public void takeLevels(int value) {
+ setLevel(level - value, PlayerLevelChangeEvent.Reason.UNKNOWN);
+ }
+
+ @Deprecated
+ public void setLevel(int level) {
+ setLevel(level, PlayerLevelChangeEvent.Reason.UNKNOWN);
+ }
+
+ @Deprecated
+ public void clearNodeStates(@NotNull SkillTree skillTree) {
+ clearStates(skillTree);
+ }
+
+ /**
+ * @see #setMana(double, PlayerResourceUpdateEvent.UpdateReason)
+ * @deprecated
+ */
+ @Deprecated
+ public void setMana(double amount) {
+ setMana(amount, PlayerResourceUpdateEvent.UpdateReason.UNKNOWN);
+ }
+
+ /**
+ * @see #setStamina(double, PlayerResourceUpdateEvent.UpdateReason)
+ * @deprecated
+ */
+ @Deprecated
+ public void setStamina(double amount) {
+ setStamina(amount, PlayerResourceUpdateEvent.UpdateReason.UNKNOWN);
+ }
+
+ /**
+ * @see #setStellium(double, PlayerResourceUpdateEvent.UpdateReason)
+ * @deprecated
+ */
+ @Deprecated
+ public void setStellium(double amount) {
+ setStellium(amount, PlayerResourceUpdateEvent.UpdateReason.UNKNOWN);
+ }
+
+ /**
+ * @see #loadResources(double, double, double, double)
+ * @deprecated
+ */
+ @Deprecated
+ public void setHealth(double amount) {
+ this.lastHealth = amount;
+ }
+
+ @Deprecated
+ public double getHealth() {
+ return getLastHealth();
+ }
+
+ @Deprecated
+ public double getCachedHealth() {
+ return getLastHealth();
+ }
+
+ /**
+ * @deprecated Provide reason with {@link #giveStellium(double, PlayerResourceUpdateEvent.UpdateReason)}
+ */
+ @Deprecated
+ public void giveStellium(double amount) {
+ giveStellium(amount, PlayerResourceUpdateEvent.UpdateReason.UNKNOWN);
+ }
+
+ /**
+ * @deprecated Provide reason with {@link #giveStamina(double, PlayerResourceUpdateEvent.UpdateReason)}
+ */
+ @Deprecated
+ public void giveStamina(double amount) {
+ giveStamina(amount, PlayerResourceUpdateEvent.UpdateReason.UNKNOWN);
+ }
+
+ /**
+ * @deprecated Provide reason with {@link #giveMana(double, PlayerResourceUpdateEvent.UpdateReason)}
+ */
+ @Deprecated
+ public void giveMana(double amount) {
+ giveMana(amount, PlayerResourceUpdateEvent.UpdateReason.UNKNOWN);
+ }
+
+ @Deprecated
+ public void setupRemovableTrigger() {
+ applyTemporaryTriggers();
+ }
+
+ @Deprecated
+ public int getPointSpent(SkillTree skillTree) {
+ return getPointsSpent(skillTree);
+ }
+
+ @Deprecated
+ public int getSkillTreePoint(String treeId) {
+ return getSkillTreePoints(treeId);
+ }
+
+ @Deprecated
+ public void clearSkillTrees() {
+ resetSkillTrees();
+ }
+
+ @Deprecated
+ public void resetTimesClaimed() {
+ tableItemClaims.clear();
+ }
+
+ @Deprecated
+ public void setClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item, int times) {
+ setClaims(object.getKey() + "." + table.getId() + "." + item.getId(), times);
+ }
+
+ @Deprecated
+ public int getClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item) {
+ return getClaims(object.getKey() + "." + table.getId() + "." + item.getId());
+ }
+
+ /**
+ * @see #heal(double, PlayerResourceUpdateEvent.UpdateReason)
+ * @deprecated Provide a heal reason with {@link #heal(double, PlayerResourceUpdateEvent.UpdateReason)}
+ */
+ @Deprecated
+ public void heal(double heal) {
+ this.heal(heal, PlayerResourceUpdateEvent.UpdateReason.UNKNOWN);
+ }
+
+ @Deprecated
+ public NodeState getNodeStatus(SkillTreeNode node) {
+ return getNodeState(node);
+ }
+
+ @Deprecated
+ public boolean setSkillCasting(@NotNull SkillCastingInstance skillCasting) {
+ return setSkillCasting();
+ }
+
+ @Deprecated
+ public boolean isFullyLoaded() {
+ return isSessionReady();
+ }
+
+ @Deprecated
+ public void setFullyLoaded() {
+ this.markSessionReady();
+ }
+
+ @Deprecated
+ public void setBoundSkill(int slot, ClassSkill skill) {
+ bindSkill(slot, skill);
+ }
+
+ /**
+ * Loops through all the subclasses available to the player and
+ * checks if they could potentially upgrade to one of these
+ *
+ * @return If the player can change its current class to
+ * a subclass
+ */
+ @Deprecated
+ public boolean canChooseSubclass() {
+ for (Subclass subclass : getProfess().getSubclasses())
+ if (getLevel() >= subclass.getLevel()) return true;
+ return false;
+ }
+
+ /**
+ * @see #hasUnlockedLevel(ClassSkill)
+ * @deprecated
+ */
+ @Deprecated
+ public boolean hasSkillUnlocked(RegisteredSkill skill) {
+ return getProfess().hasSkill(skill.getHandler().getId()) && hasSkillUnlocked(getProfess().getSkill(skill.getHandler().getId()));
+ }
+
+ /**
+ * @see #hasUnlockedLevel(ClassSkill)
+ * @deprecated
+ */
+ @Deprecated
+ public boolean hasSkillUnlocked(ClassSkill skill) {
+ return hasUnlockedLevel(skill);
+ }
+
+ /**
+ * Everytime a player does a combat action, like taking
+ * or dealing damage to an entity, this method is called.
+ *
+ * @see #getCombat()
+ * @deprecated
+ */
+ @Deprecated
+ public void updateCombat() {
+ getCombat().update();
+ }
+
+ @Deprecated
+ public void displayActionBar(@NotNull String message) {
+ getMMOPlayerData().getActionBar().show(ActionBarPriority.NORMAL, message);
+ }
+
+ @Deprecated
+ public void displayActionBar(@NotNull String message, boolean raw) {
+
+ // TODO add an option to disable action-bar properly in all casting modes
+ if (ChatColor.stripColor(message).isEmpty()) return;
+
+ // TODO move raw/not raw decision to MythicLib
+ var handler = getMMOPlayerData().getActionBar();
+ if (!raw) {
+ handler.show(ActionBarPriority.NORMAL, message);
+ } else {
+ if (!handler.canShow(ActionBarPriority.NORMAL)) return;
+ handler.show(ActionBarPriority.NORMAL, "");
+ MythicLib.plugin.getVersion().getWrapper().sendActionBarRaw(getPlayer(), message);
+ }
+ }
+
+ /**
+ * @see #getAttributes()
+ * @deprecated
+ */
+ @Deprecated
+ public void setAttribute(PlayerAttribute attribute, int value) {
+ setAttribute(attribute.getId(), value);
+ }
+
+ /**
+ * @see #getAttributes()
+ * @deprecated
+ */
+ @Deprecated
+ public void setAttribute(String id, int value) {
+ attributes.getInstance(id).setBase(value);
+ }
+
+ /**
+ * Counts the number of points spent in that skill tree
+ *
+ * @see #getPointsSpent(SkillTree)
+ * @deprecated
+ */
+ @Deprecated
+ public int countSkillTreePoints(@NotNull SkillTree skillTree) {
+ return nodeLevels.keySet().stream().filter(node -> node.getTree().equals(skillTree)).mapToInt(node -> nodeLevels.get(node) * node.getPointConsumption()).sum();
+ }
+
+ //endregion
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttribute.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttribute.java
index 206c05df..31f9f8c8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttribute.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttribute.java
@@ -2,13 +2,13 @@ package net.Indyuce.mmocore.api.player.attribute;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
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 org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java
index 9857c331..9ed01d55 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/attribute/PlayerAttributes.java
@@ -10,9 +10,9 @@ import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import io.lumine.mythic.lib.util.Closeable;
import io.lumine.mythic.lib.util.Lazy;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
@@ -189,7 +189,7 @@ public class PlayerAttributes {
public AttributeInstance(@NotNull String attributeId) {
this.id = attributeId;
this.enumName = UtilityMethods.enumName(this.id);
- this.attribute = Lazy.of(() -> MMOCore.plugin.attributeManager.get(this.id));
+ this.attribute = Lazy.persistent(() -> MMOCore.plugin.attributeManager.get(this.id));
}
/**
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java
index d775d29e..d5e110c7 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java
@@ -311,10 +311,15 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
}
@Override
- public ExpCurve getExpCurve() {
+ public @NotNull ExpCurve getExpCurve() {
return expCurve;
}
+ @NotNull
+ public Collection getSkills() {
+ return skills.values();
+ }
+
@NotNull
public ExperienceTable getExperienceTable() {
@@ -423,7 +428,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
return skillSlots;
}
- @NotNull
+ @Nullable
public ClassSkill getSkill(RegisteredSkill skill) {
return getSkill(skill.getHandler().getId());
}
@@ -469,11 +474,6 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
return calculateBaseStat(stat, level, null);
}
- @Deprecated
- public Collection getSkills() {
- return skills.values();
- }
-
@Deprecated
public ItemStack getIcon() {
return icon.toItemStack();
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
index b5b4747d..3dd7ce61 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
@@ -2,16 +2,16 @@ package net.Indyuce.mmocore.api.player.profess;
import io.lumine.mythic.lib.gson.JsonElement;
import io.lumine.mythic.lib.gson.JsonObject;
-import io.lumine.mythic.lib.version.Attributes;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
-import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.player.ClassDataContainer;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import org.bukkit.configuration.ConfigurationSection;
+import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.HashSet;
@@ -119,7 +119,7 @@ public class SavedClassInformation implements ClassDataContainer {
this.skillTreeReallocationPoints = data.getSkillTreeReallocationPoints();
this.skillReallocationPoints = data.getSkillReallocationPoints();
this.experience = data.getExperience();
- this.health = data.getHealth();
+ this.health = data.getLastHealth();
this.mana = data.getMana();
this.stellium = data.getStellium();
this.stamina = data.getStamina();
@@ -159,7 +159,7 @@ public class SavedClassInformation implements ClassDataContainer {
}
@Override
- public double getHealth() {
+ public double getLastHealth() {
return health;
}
@@ -284,7 +284,7 @@ public class SavedClassInformation implements ClassDataContainer {
* @param profess Target player class
* @param player Player changing class
*/
- public void load(PlayerClass profess, PlayerData player) {
+ public void load(@NotNull PlayerClass profess, @NotNull PlayerData player) {
/*
* Saves current class info inside a SavedClassInformation, only
@@ -310,7 +310,7 @@ public class SavedClassInformation implements ClassDataContainer {
* Reads this class info, applies it to the player. set class after
* changing level so the player stats can be calculated based on new level
*/
- player.setLevel(level);
+ player.setLevel(level, PlayerLevelChangeEvent.Reason.CHOOSE_CLASS);
player.setExperience(experience);
player.setSkillPoints(skillPoints);
player.setAttributePoints(attributePoints);
@@ -332,21 +332,17 @@ public class SavedClassInformation implements ClassDataContainer {
for (SkillTreeNode node : skillTree.getNodes())
player.setNodeLevel(node, nodeLevels.getOrDefault(node.getFullId(), 0));
- skillTree.setupNodeStates(player);
+ skillTree.resolveStates(player);
}
// Add the values to the times claimed table and claims the corresponding stat triggers.
- nodeTimesClaimed.forEach((str, val) -> player.setClaims(str, val));
+ nodeTimesClaimed.forEach(player::setClaims);
// Unload current class information
player.unloadClassInfo(profess);
// This needs to be done at the end to make sure the MAX_HEALTH/MAX_MANA/... stats are loaded.
- player.getPlayer().setHealth(MMOCoreUtils.fixResource(health, player.getPlayer().getAttribute(Attributes.MAX_HEALTH).getValue()));
- player.setHealth(health);
- player.setMana(mana);
- player.setStellium(stellium);
- player.setStamina(stamina);
+ player.loadResources(health, mana, stellium, stamina);
player.applyTemporaryTriggers();
player.getStats().updateStats();
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/Subclass.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/Subclass.java
index 9bfd4fde..117e9e14 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/Subclass.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/Subclass.java
@@ -1,6 +1,6 @@
package net.Indyuce.mmocore.api.player.profess;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
public class Subclass {
private final PlayerClass profess;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTrigger.java
index fca598b2..48aad6e8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTrigger.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.api.player.profess.event;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
-import org.apache.commons.lang.Validate;
import java.util.LinkedHashSet;
import java.util.List;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/LevelUpEventTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/LevelUpEventTrigger.java
index ffa0d53b..ad4293cb 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/LevelUpEventTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/LevelUpEventTrigger.java
@@ -1,6 +1,6 @@
package net.Indyuce.mmocore.api.player.profess.event.trigger;
-import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
@@ -10,32 +10,34 @@ import org.bukkit.event.EventPriority;
@Deprecated
public class LevelUpEventTrigger implements EventTriggerHandler {
- @Override
- public boolean handles(String event) {
- return event.startsWith("level-up");
- }
+ @Override
+ public boolean handles(String event) {
+ return event.startsWith("level-up");
+ }
- @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
- public void a(PlayerLevelUpEvent event) {
- PlayerData player = event.getData();
- PlayerClass profess = player.getProfess();
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void a(PlayerLevelChangeEvent event) {
+ PlayerData player = event.getData();
+ PlayerClass profess = player.getProfess();
- for(int i = event.getOldLevel(); i < event.getNewLevel(); i++) {
- int level = i + 1;
- if(event.hasProfession()) {
- String prof = event.getProfession().getId().toLowerCase();
- processTrigger(player, profess, "level-up-" + prof);
- processTrigger(player, profess, "level-up-" + prof + "-" + level);
- } else {
- processTrigger(player, profess, "level-up");
- processTrigger(player, profess, "level-up-" + level);
- if(profess.getMaxLevel() == level)
- processTrigger(player, profess, "level-up-max");
- }
- }
- }
-
- public void processTrigger(PlayerData player, PlayerClass profess, String trigger) {
- if(profess.hasEventTriggers(trigger)) profess.getEventTriggers(trigger).getTriggers().forEach(t -> t.apply(player));
- }
+ if (event.getReason() == PlayerLevelChangeEvent.Reason.LEVEL_UP)
+ for (int i = event.getOldLevel(); i < event.getNewLevel(); i++) {
+ int level = i + 1;
+ if (event.hasProfession()) {
+ String prof = event.getProfession().getId().toLowerCase();
+ processTrigger(player, profess, "level-up-" + prof);
+ processTrigger(player, profess, "level-up-" + prof + "-" + level);
+ } else {
+ processTrigger(player, profess, "level-up");
+ processTrigger(player, profess, "level-up-" + level);
+ if (profess.getMaxLevel() == level)
+ processTrigger(player, profess, "level-up-max");
+ }
+ }
+ }
+
+ public void processTrigger(PlayerData player, PlayerClass profess, String trigger) {
+ if (profess.hasEventTriggers(trigger))
+ profess.getEventTriggers(trigger).getTriggers().forEach(t -> t.apply(player));
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/MultipleLevelUpEventTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/MultipleLevelUpEventTrigger.java
index 20f4800b..a8fe537f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/MultipleLevelUpEventTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/MultipleLevelUpEventTrigger.java
@@ -1,6 +1,6 @@
package net.Indyuce.mmocore.api.player.profess.event.trigger;
-import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
@@ -18,31 +18,33 @@ public class MultipleLevelUpEventTrigger implements EventTriggerHandler {
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
- public void a(PlayerLevelUpEvent event) {
+ public void a(PlayerLevelChangeEvent event) {
PlayerData player = event.getData();
PlayerClass profess = player.getProfess();
- for(int i = event.getOldLevel(); i < event.getNewLevel(); i++) {
- int level = i + 1;
+ if (event.getReason() == PlayerLevelChangeEvent.Reason.LEVEL_UP)
+ for (int i = event.getOldLevel(); i < event.getNewLevel(); i++) {
+ int level = i + 1;
- for (String t : profess.getEventTriggers()){
- if (t.startsWith("level-up-multiple")) {
- String[] split = t.split("-");
- double multiple = Double.parseDouble(split[split.length-1]);
- if (level / multiple % 1 == 0) {
- DecimalFormat f = new DecimalFormat("#");
- if (event.hasProfession()) {
- processTrigger(player, profess, "level-up-multiple-" + event.getProfession().getId().toLowerCase() + "-" + f.format(multiple));
- } else {
- processTrigger(player, profess, "level-up-multiple-" + f.format(multiple));
- }
- }
- }
- }
- }
+ for (String t : profess.getEventTriggers()) {
+ if (t.startsWith("level-up-multiple")) {
+ String[] split = t.split("-");
+ double multiple = Double.parseDouble(split[split.length - 1]);
+ if (level / multiple % 1 == 0) {
+ DecimalFormat f = new DecimalFormat("#");
+ if (event.hasProfession()) {
+ processTrigger(player, profess, "level-up-multiple-" + event.getProfession().getId().toLowerCase() + "-" + f.format(multiple));
+ } else {
+ processTrigger(player, profess, "level-up-multiple-" + f.format(multiple));
+ }
+ }
+ }
+ }
+ }
}
public void processTrigger(PlayerData player, PlayerClass profess, String trigger) {
- if(profess.hasEventTriggers(trigger)) profess.getEventTriggers(trigger).getTriggers().forEach(t -> t.apply(player));
+ if (profess.hasEventTriggers(trigger))
+ profess.getEventTriggers(trigger).getTriggers().forEach(t -> t.apply(player));
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ManaDisplayOptions.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ManaDisplayOptions.java
index 2e238aec..59e02746 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ManaDisplayOptions.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ManaDisplayOptions.java
@@ -2,7 +2,7 @@ package net.Indyuce.mmocore.api.player.profess.resource;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.util.AltChar;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/PlayerResource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/PlayerResource.java
index 866aa650..c26e8d42 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/PlayerResource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/PlayerResource.java
@@ -5,7 +5,7 @@ import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.ClassOption;
import net.Indyuce.mmocore.api.quest.trigger.ManaTrigger;
-import net.Indyuce.mmocore.command.rpg.admin.ResourceCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.admin.ResourceCommandTreeNode;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -24,21 +24,21 @@ public enum PlayerResource {
(data, amount) -> data.giveMana(amount, PlayerResourceUpdateEvent.UpdateReason.REGENERATION),
(data, amount) -> data.giveMana(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
(data, amount) -> data.giveMana(-amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
- (data, amount) -> data.setMana(amount)),
+ (data, amount) -> data.setMana(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND)),
STAMINA(PlayerData::getStamina,
data -> data.getStats().getStat("MAX_STAMINA"),
(data, amount) -> data.giveStamina(amount, PlayerResourceUpdateEvent.UpdateReason.REGENERATION),
(data, amount) -> data.giveStamina(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
(data, amount) -> data.giveStamina(-amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
- (data, amount) -> data.setStamina(amount)),
+ (data, amount) -> data.setStamina(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND)),
STELLIUM(PlayerData::getStellium,
data -> data.getStats().getStat("MAX_STELLIUM"),
(data, amount) -> data.giveStellium(amount, PlayerResourceUpdateEvent.UpdateReason.REGENERATION),
(data, amount) -> data.giveStellium(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
(data, amount) -> data.giveStellium(-amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND),
- (data, amount) -> data.setStellium(amount));
+ (data, amount) -> data.setStellium(amount, PlayerResourceUpdateEvent.UpdateReason.COMMAND));
private final String regenStat, maxRegenStat;
private final ClassOption offCombatRegen;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ResourceRegeneration.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ResourceRegeneration.java
index 44429bbf..606ad08d 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ResourceRegeneration.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/resource/ResourceRegeneration.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.api.player.profess.resource;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.util.formula.FormulaFailsafeException;
import net.Indyuce.mmocore.util.formula.ScalingFormula;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import java.util.function.BiFunction;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/social/Request.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/social/Request.java
index 50d4e0ee..7a3d2cf6 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/social/Request.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/social/Request.java
@@ -1,8 +1,8 @@
package net.Indyuce.mmocore.api.player.social;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import java.util.UUID;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java
index 033feaeb..b036ba2d 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java
@@ -15,6 +15,7 @@ import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.player.stats.StatInfo;
import net.Indyuce.mmocore.skill.ClassSkill;
+// TODO merge with PlayerData? not really needed class
public class PlayerStats {
private final PlayerData data;
@@ -67,8 +68,9 @@ public class PlayerStats {
return data.getProfess().calculateBaseStat(stat, profession == null ? data.getLevel() : data.getCollectionSkills().getLevel(profession), data);
}
- public void updateStats() {
- updateStats(false);
+ @Deprecated
+ public void updateStats(boolean ignored) {
+ this.updateStats();
}
private static final String MODIFIER_KEY = "MMOCoreClass";
@@ -77,25 +79,19 @@ public class PlayerStats {
* Used to update MMOCore stat modifiers due to class and send them over to
* MythicLib. Must be ran everytime the player levels up, changes class or
* when the plugin reloads.
- *
- * Login scripts are a pretty special case of scripts/skills since they are
- * not loaded yet when MythicLib triggers them naturally. Therefore, they
- * need to be cast as soon as they are loaded into the MMOCore player data.
- *
- * @param castLoginScripts Should login scripts be cast
*/
- public synchronized void updateStats(boolean castLoginScripts) {
+ public synchronized void updateStats() {
// Update player stats
getMap().bufferUpdates(() -> {
for (String stat : MMOCore.plugin.statManager.getRegistered()) {
- final StatInstance instance = getMap().getInstance(stat);
+ final var instance = getMap().getInstance(stat);
// Remove modifiers due to class
instance.removeIf(MODIFIER_KEY::equals);
// Add newest one
- final double total = getBase(instance.getStat()) - instance.getBase();
+ final double total = getBase(instance.getStat()) - instance.getDefaultBase();
if (total != 0)
instance.registerModifier(new StatModifier(MODIFIER_KEY, instance.getStat(), total, ModifierType.FLAT, EquipmentSlot.OTHER, ModifierSource.OTHER));
}
@@ -115,18 +111,5 @@ public class PlayerStats {
skillMap.removeModifiers("MMOCoreClassScript");
for (PassiveSkill script : data.getProfess().getScripts())
if (script.getType() != TriggerType.LOGIN) skillMap.addModifier(script);
-
- // If data hasn't been synchronized yet, cast LOGIN scripts
- if (castLoginScripts) {
-
- // Call class login skills
- for (ClassSkill skill : data.getProfess().getSkills())
- if (skill.getSkill().getTrigger() == TriggerType.LOGIN)
- skill.toCastable(data).cast(data.getMMOPlayerData());
-
- // Call class login scripts
- for (PassiveSkill skill : data.getProfess().getScripts())
- if (skill.getType() == TriggerType.LOGIN) skill.getTriggeredSkill().cast(data.getMMOPlayerData());
- }
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java
index f55c0658..c36dfbf1 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/ObjectiveProgress.java
@@ -32,6 +32,11 @@ public abstract class ObjectiveProgress implements Closeable {
return questProgress;
}
+ public double getProgress() {
+ // default to 0, maybe ppl implemented quest objectives
+ return 0;
+ }
+
@Override
public void close() {
if (this instanceof Listener)
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java
index 815e7ff8..bb4e55e3 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/PlayerQuests.java
@@ -6,6 +6,7 @@ import io.lumine.mythic.lib.gson.JsonObject;
import io.lumine.mythic.lib.util.Closeable;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
+import org.apache.commons.lang3.Validate;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.boss.BarColor;
@@ -24,27 +25,25 @@ import java.util.logging.Level;
public class PlayerQuests implements Closeable {
private final PlayerData playerData;
private final Map finished = new HashMap<>();
-
- @Nullable
- private final BossBar bossbar;
private final NamespacedKey bossbarNamespacedKey;
+ @Nullable
+ private BossBar bossbar;
private QuestProgress current;
public PlayerQuests(PlayerData playerData) {
this.playerData = playerData;
- if (!MMOCore.plugin.configManager.disableQuestBossBar && playerData.isOnline()) {
- bossbarNamespacedKey = new NamespacedKey(MMOCore.plugin, "mmocore_quest_progress_" + playerData.getUniqueId().toString());
- bossbar = Bukkit.createBossBar(bossbarNamespacedKey, "", BarColor.PURPLE, BarStyle.SEGMENTED_20);
- bossbar.addPlayer(playerData.getPlayer());
- bossbar.setVisible(false); // Safety
+ bossbarNamespacedKey = new NamespacedKey(MMOCore.plugin, "quest_progress_" + playerData.getUniqueId());
+/*
+ Bukkit.getScheduler().runTaskTimer(MMOCore.plugin, () -> {
- // Bossbar is disabled
- } else {
- bossbarNamespacedKey = null;
- bossbar = null;
- }
+ Bukkit.broadcastMessage("bossbar=" + bossbar);
+ Bukkit.broadcastMessage("current=" + current);
+
+
+ }, 20, 20);
+ */
}
public PlayerQuests load(ConfigurationSection config) {
@@ -69,6 +68,8 @@ public class PlayerQuests implements Closeable {
return this;
}
+ //region DB
+
public void save(ConfigurationSection config) {
if (current != null) {
config.set("current.id", current.getQuest().getId());
@@ -93,7 +94,7 @@ public class PlayerQuests implements Closeable {
for (String key : finished.keySet())
fin.addProperty(key, finished.get(key));
- if (finished.size() != 0)
+ if (!finished.isEmpty())
json.add("finished", fin);
return json.toString();
}
@@ -114,6 +115,8 @@ public class PlayerQuests implements Closeable {
finished.put(entry.getKey(), entry.getValue().getAsLong());
}
+ //endregion DB
+
public QuestProgress getCurrent() {
return current;
}
@@ -135,6 +138,7 @@ public class PlayerQuests implements Closeable {
}
public void finishCurrent() {
+ Validate.notNull(current, "No ongoing quest");
finished.put(current.getQuest().getId(), System.currentTimeMillis());
start(null);
}
@@ -147,35 +151,36 @@ public class PlayerQuests implements Closeable {
return new Date(finished.get(quest.getId()));
}
- public void start(Quest quest) {
+ public void start(@Nullable Quest quest) {
// Close current objective progress if quest is active
- closeCurrentQuest();
+ cancelCurrentQuest();
// Apply newest quest
current = quest == null ? null : quest.generateNewProgress(playerData);
updateBossBar();
}
- public void closeCurrentQuest() {
- if (current == null)
- return;
+ public void cancelCurrentQuest() {
+ if (current == null) return;
current.getProgress().close();
current = null;
}
+ @Deprecated
+ public void closeCurrentQuest() {
+ cancelCurrentQuest();
+ }
+
@Override
public void close() {
// Remove boss bar
- if (bossbar != null) {
- bossbar.removeAll();
- Bukkit.removeBossBar(bossbarNamespacedKey);
- }
+ if (bossbar != null) deleteBossbar();
- // Close current objective progress
- closeCurrentQuest();
+ // Close only progress
+ if (current != null) current.getProgress().close();
}
public boolean checkCooldownAvailability(Quest quest) {
@@ -193,20 +198,50 @@ public class PlayerQuests implements Closeable {
return true;
}
- public void updateBossBar() {
+ //region Bossbar
- // Bossbar is disabled
- if (bossbar == null)
- return;
-
- if (!hasCurrent() || !current.getProgress().getObjective().hasLore()) {
- bossbar.setVisible(false);
- return;
- }
+ private boolean isBossbarRelevant() {
+ return !MMOCore.plugin.configManager.disableQuestBossBar
+ && current != null
+ && current.getQuest().usesBossbar();
+ }
+ private void initializeBossbar() {
+ Validate.isTrue(this.bossbar == null, "Tried to create a new bossbar while one already exists");
+ this.bossbar = Bukkit.createBossBar(bossbarNamespacedKey, "", BarColor.PURPLE, BarStyle.SEGMENTED_20);
+ bossbar.addPlayer(playerData.getPlayer());
bossbar.setVisible(true);
+ }
+
+ private void deleteBossbar() {
+ Validate.notNull(this.bossbar, "Bossbar is null");
+
+ bossbar.removeAll();
+ Bukkit.removeBossBar(bossbarNamespacedKey);
+ this.bossbar = null;
+ }
+
+ public void updateBossBar() {
+ final var flag = isBossbarRelevant();
+ final var enabled = bossbar != null;
+
+ // Initialize/remove if needed
+ if (enabled && !flag) deleteBossbar();
+ else if (!enabled && flag) initializeBossbar();
+
+ // Bossbar
+ if (bossbar == null) return;
+
+ final var bossbarProgress = current.getQuest().isObjectiveBossbar()
+ // Fine tuned progress
+ ? current.getProgress().getProgress()
+ // Based on objective number
+ : (double) current.getObjectiveNumber() / current.getQuest().getObjectives().size();
+
bossbar.setColor(current.getProgress().getObjective().getBarColor());
bossbar.setTitle(current.getFormattedLore());
- bossbar.setProgress((double) current.getObjectiveNumber() / current.getQuest().getObjectives().size());
+ bossbar.setProgress(bossbarProgress);
}
+
+ //endregion
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/Quest.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/Quest.java
index c8cd553b..0456f432 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/Quest.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/Quest.java
@@ -3,11 +3,11 @@ package net.Indyuce.mmocore.api.quest;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.PostLoadAction;
import io.lumine.mythic.lib.util.PreloadedObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.objective.Objective;
import net.Indyuce.mmocore.experience.Profession;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
@@ -20,6 +20,7 @@ public class Quest implements PreloadedObject {
private final List objectives = new ArrayList<>();
private final List lore;
private final int mainLevelRestriction;
+ private final boolean useBossbar, objectiveBossbar;
private final Map levelRestrictions = new HashMap<>();
// Cooldown in millis
@@ -40,6 +41,8 @@ public class Quest implements PreloadedObject {
cooldown = (long) (config.contains("delay") ? config.getDouble("delay") * 60 * 60 * 1000 : -1);
name = config.getString("name");
lore = config.getStringList("lore");
+ objectiveBossbar = config.getBoolean("bossbar.objective", true);
+ useBossbar = config.getBoolean("bossbar.enabled", true);
mainLevelRestriction = config.getInt("level-req.main");
@@ -80,6 +83,14 @@ public class Quest implements PreloadedObject {
return id;
}
+ public boolean usesBossbar() {
+ return useBossbar;
+ }
+
+ public boolean isObjectiveBossbar() {
+ return objectiveBossbar;
+ }
+
public String getName() {
return name;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/QuestProgress.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/QuestProgress.java
index ec6f2de3..59cb6c95 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/QuestProgress.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/QuestProgress.java
@@ -8,7 +8,7 @@ public class QuestProgress {
private final Quest quest;
private final PlayerData player;
- private int objective;
+ private int objectiveIndex;
private ObjectiveProgress objectiveProgress;
public QuestProgress(Quest quest, PlayerData player) {
@@ -19,7 +19,7 @@ public class QuestProgress {
this.quest = quest;
this.player = player;
- this.objective = objective;
+ this.objectiveIndex = objective;
objectiveProgress = nextObjective().newProgress(this);
}
@@ -32,7 +32,7 @@ public class QuestProgress {
}
public int getObjectiveNumber() {
- return objective;
+ return objectiveIndex;
}
public ObjectiveProgress getProgress() {
@@ -40,18 +40,19 @@ public class QuestProgress {
}
private Objective nextObjective() {
- return quest.getObjectives().get(objective);
+ return quest.getObjectives().get(objectiveIndex);
}
public void completeObjective() {
- objective++;
+ objectiveIndex++;
objectiveProgress.close();
- final ObjectiveProgress finishedObjectiveProgress = objectiveProgress;
+ final var finishedObjectiveProgress = objectiveProgress;
// Start next objective, or end quest.
- if (objective >= quest.getObjectives().size()) player.getQuestData().finishCurrent();
+ if (objectiveIndex >= quest.getObjectives().size()) player.getQuestData().finishCurrent();
else objectiveProgress = nextObjective().newProgress(this);
+ // Update bossbar
player.getQuestData().updateBossBar();
/*
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/ClickonObjective.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/ClickonObjective.java
index 18ccc59c..cc3c20a8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/ClickonObjective.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/ClickonObjective.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.api.quest.objective;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.quest.ObjectiveProgress;
import net.Indyuce.mmocore.api.quest.QuestProgress;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -31,13 +31,13 @@ public class ClickonObjective extends Objective {
}
@Override
- public ObjectiveProgress newProgress(QuestProgress questProgress) {
- return new GotoProgress(questProgress, this);
+ public GotoProgress newProgress(QuestProgress questProgress) {
+ return new GotoProgress(questProgress);
}
public class GotoProgress extends ObjectiveProgress implements Listener {
- public GotoProgress(QuestProgress questProgress, Objective objective) {
- super(questProgress, objective);
+ public GotoProgress(QuestProgress questProgress) {
+ super(questProgress, ClickonObjective.this);
}
@EventHandler
@@ -51,6 +51,11 @@ public class ClickonObjective extends Objective {
getQuestProgress().completeObjective();
}
+ @Override
+ public double getProgress() {
+ return 1d;
+ }
+
@Override
public String formatLore(String lore) {
return lore;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/GoToObjective.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/GoToObjective.java
index f0b868d5..426e64b8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/GoToObjective.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/GoToObjective.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.api.quest.objective;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.quest.ObjectiveProgress;
import net.Indyuce.mmocore.api.quest.QuestProgress;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -29,18 +29,20 @@ public class GoToObjective extends Objective {
}
@Override
- public ObjectiveProgress newProgress(QuestProgress questProgress) {
- return new GotoProgress(questProgress, this);
+ public GotoProgress newProgress(QuestProgress questProgress) {
+ return new GotoProgress(questProgress);
}
public class GotoProgress extends ObjectiveProgress implements Listener {
- public GotoProgress(QuestProgress questProgress, Objective objective) {
- super(questProgress, objective);
+ public GotoProgress(QuestProgress questProgress) {
+ super(questProgress, GoToObjective.this);
}
@EventHandler
public void a(PlayerMoveEvent event) {
- if (event.getFrom().getBlockX() == event.getTo().getBlockX() && event.getFrom().getBlockY() == event.getTo().getBlockY() && event.getFrom().getBlockZ() == event.getTo().getBlockZ())
+ if (event.getFrom().getBlockX() == event.getTo().getBlockX()
+ && event.getFrom().getBlockY() == event.getTo().getBlockY()
+ && event.getFrom().getBlockZ() == event.getTo().getBlockZ())
return;
Player player = event.getPlayer();
@@ -50,6 +52,11 @@ public class GoToObjective extends Objective {
}
}
+ @Override
+ public double getProgress() {
+ return 1d;
+ }
+
@Override
public String formatLore(String lore) {
return lore;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/KillMobObjective.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/KillMobObjective.java
index aaa12a8c..7945d9e6 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/KillMobObjective.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/KillMobObjective.java
@@ -23,26 +23,32 @@ public class KillMobObjective extends Objective {
}
@Override
- public ObjectiveProgress newProgress(QuestProgress questProgress) {
- return new KillMobProgress(questProgress, this);
+ public KillMobProgress newProgress(QuestProgress questProgress) {
+ return new KillMobProgress(questProgress);
}
public class KillMobProgress extends ObjectiveProgress implements Listener {
private int count;
- public KillMobProgress(QuestProgress questProgress, Objective objective) {
- super(questProgress, objective);
+ public KillMobProgress(QuestProgress questProgress) {
+ super(questProgress, KillMobObjective.this);
}
- @EventHandler
- public void a(PlayerKillEntityEvent event) {
- if(!getPlayer().isOnline()) return;
- if (event.getTarget().getType() == type && event.getPlayer().equals(getPlayer().getPlayer())) {
- count++;
- getQuestProgress().getPlayer().getQuestData().updateBossBar();
- if (count >= required)
- getQuestProgress().completeObjective();
- }
+ @EventHandler
+ public void a(PlayerKillEntityEvent event) {
+ if (!getPlayer().isOnline()) return;
+
+ if (event.getTarget().getType() == type && event.getPlayer().equals(getPlayer().getPlayer())) {
+ count++;
+ getQuestProgress().getPlayer().getQuestData().updateBossBar();
+ if (count >= required)
+ getQuestProgress().completeObjective();
+ }
+ }
+
+ @Override
+ public double getProgress() {
+ return (double) count / required;
}
@Override
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/MineBlockObjective.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/MineBlockObjective.java
index f5298398..743e05b8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/MineBlockObjective.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/MineBlockObjective.java
@@ -54,6 +54,11 @@ public class MineBlockObjective extends Objective {
}
}
+ @Override
+ public double getProgress() {
+ return (double) count / required;
+ }
+
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void b(CustomBlockMineEvent event) {
if(!getQuestProgress().getPlayer().isOnline()) return;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/Objective.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/Objective.java
index 3f23fa9e..197b0819 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/Objective.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/objective/Objective.java
@@ -1,11 +1,11 @@
package net.Indyuce.mmocore.api.quest.objective;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.quest.ObjectiveProgress;
import net.Indyuce.mmocore.api.quest.QuestProgress;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
-import org.apache.commons.lang.Validate;
import org.bukkit.boss.BarColor;
import org.bukkit.configuration.ConfigurationSection;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ExperienceTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ExperienceTrigger.java
index b065fdae..34acf59c 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ExperienceTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ExperienceTrigger.java
@@ -1,40 +1,37 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
import net.Indyuce.mmocore.experience.EXPSource;
-import net.Indyuce.mmocore.experience.SimpleExperienceObject;
-import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
-import org.apache.commons.lang.Validate;
-import org.jetbrains.annotations.NotNull;
+import net.Indyuce.mmocore.experience.Profession;
+import org.jetbrains.annotations.Nullable;
public class ExperienceTrigger extends Trigger {
- @NotNull
private final RandomAmount amount;
- @NotNull
private final EXPSource source;
- @NotNull
- private final ExperienceDispenser dispenser;
+ @Nullable
+ private final Profession profession;
public ExperienceTrigger(MMOLineConfig config) {
super(config);
config.validate("amount");
- if (config.contains("profession")) {
- String id = config.getString("profession").toLowerCase().replace("_", "-");
- Validate.isTrue(MMOCore.plugin.professionManager.has(id), "Could not find profession");
- dispenser = MMOCore.plugin.professionManager.get(id);
- } else
- dispenser = new SimpleExperienceObject();
+ if (config.contains("profession")) {
+ String id = config.getString("profession").toLowerCase().replace("_", "-");
+ Validate.isTrue(MMOCore.plugin.professionManager.has(id), "Could not find profession");
+ profession = MMOCore.plugin.professionManager.get(id);
+ } else profession = null;
amount = new RandomAmount(config.getString("amount"));
source = config.contains("source") ? EXPSource.valueOf(config.getString("source").toUpperCase()) : EXPSource.QUEST;
}
@Override
public void apply(PlayerData player) {
- dispenser.giveExperience(player, amount.calculate(), null, source);
- }
+ if (profession != null) profession.giveExperience(player, amount.calculate(), null, source);
+ else player.getProfess().giveExperience(player, amount.calculate(), null, source);
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/FromTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/FromTrigger.java
index fc2f7037..2e447839 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/FromTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/FromTrigger.java
@@ -2,9 +2,9 @@ package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.config.YamlFile;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import java.util.ArrayList;
import java.util.List;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ManaTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ManaTrigger.java
index 73a81b4b..5dd20445 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ManaTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/ManaTrigger.java
@@ -26,7 +26,7 @@ public class ManaTrigger extends Trigger {
// Set mana
else if (operation == Operation.SET)
- player.setMana(amount.calculate());
+ player.setMana(amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
// Take mana
else
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SkillModifierTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SkillModifierTrigger.java
index f29883a9..d75636eb 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SkillModifierTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SkillModifierTrigger.java
@@ -5,12 +5,12 @@ import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import io.lumine.mythic.lib.player.skillmod.SkillModifier;
import io.lumine.mythic.lib.skill.handler.SkillHandler;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.api.quest.trigger.api.Temporary;
import net.Indyuce.mmocore.skill.RegisteredSkill;
-import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import java.util.List;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SoundTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SoundTrigger.java
index b8c9f62b..2dabedb7 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SoundTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/SoundTrigger.java
@@ -1,27 +1,23 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
-import io.lumine.mythic.lib.version.Sounds;
+import io.lumine.mythic.lib.message.SoundReader;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.bukkit.Sound;
public class SoundTrigger extends Trigger {
- private final Sound sound;
- private final float vol, pitch;
+ private final SoundReader sound;
public SoundTrigger(MMOLineConfig config) {
super(config);
config.validate("sound");
- sound = Sounds.fromName(config.getString("sound").toUpperCase().replace("-", "_"));
- vol = config.contains("volume") ? (float) config.getDouble("volume") : 1f;
- pitch = config.contains("pitch") ? (float) config.getDouble("pitch") : 1f;
+ sound = new SoundReader(config);
}
@Override
public void apply(PlayerData player) {
if(!player.isOnline()) return;
- player.getPlayer().playSound(player.getPlayer().getLocation(), sound, vol, pitch);
+ sound.play(player.getPlayer());
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StaminaTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StaminaTrigger.java
index f60f0355..10371faf 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StaminaTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StaminaTrigger.java
@@ -7,30 +7,29 @@ import net.Indyuce.mmocore.api.quest.trigger.ManaTrigger.Operation;
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
public class StaminaTrigger extends Trigger {
- private final RandomAmount amount;
- private final Operation operation;
+ private final RandomAmount amount;
+ private final Operation operation;
- public StaminaTrigger(MMOLineConfig config) {
- super(config);
+ public StaminaTrigger(MMOLineConfig config) {
+ super(config);
- config.validate("amount");
- amount = new RandomAmount(config.getString("amount"));
- operation = config.contains("operation") ? Operation.valueOf(config.getString("operation").toUpperCase()) : Operation.GIVE;
- }
+ config.validate("amount");
+ amount = new RandomAmount(config.getString("amount"));
+ operation = config.contains("operation") ? Operation.valueOf(config.getString("operation").toUpperCase()) : Operation.GIVE;
+ }
- @Override
- public void apply(PlayerData player) {
+ @Override
+ public void apply(PlayerData player) {
- // Give stamina
- if (operation == Operation.GIVE)
- player.giveStamina(amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
+ // Give stamina
+ if (operation == Operation.GIVE)
+ player.giveStamina(amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
- // Set stamina
- else if (operation == Operation.SET)
- player.setStamina(amount.calculate());
+ // Set stamina
+ else if (operation == Operation.SET)
+ player.setStamina(amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
- // Take stamina
- else
- player.giveStamina(-amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
- }
+ // Take stamina
+ else player.giveStamina(-amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java
index 0b9ff987..e47516f2 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StatTrigger.java
@@ -3,10 +3,10 @@ package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
import io.lumine.mythic.lib.player.modifier.ModifierType;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.api.quest.trigger.api.Temporary;
-import org.apache.commons.lang.Validate;
public class StatTrigger extends Trigger implements Removable, Temporary {
private final StatModifier modifier;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StelliumTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StelliumTrigger.java
index fd97f1b3..445e155c 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StelliumTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/StelliumTrigger.java
@@ -7,30 +7,29 @@ import net.Indyuce.mmocore.api.quest.trigger.ManaTrigger.Operation;
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
public class StelliumTrigger extends Trigger {
- private final RandomAmount amount;
- private final Operation operation;
+ private final RandomAmount amount;
+ private final Operation operation;
- public StelliumTrigger(MMOLineConfig config) {
- super(config);
+ public StelliumTrigger(MMOLineConfig config) {
+ super(config);
- config.validate("amount");
- amount = new RandomAmount(config.getString("amount"));
- operation = config.contains("operation") ? Operation.valueOf(config.getString("operation").toUpperCase()) : Operation.GIVE;
- }
+ config.validate("amount");
+ amount = new RandomAmount(config.getString("amount"));
+ operation = config.contains("operation") ? Operation.valueOf(config.getString("operation").toUpperCase()) : Operation.GIVE;
+ }
- @Override
- public void apply(PlayerData player) {
+ @Override
+ public void apply(PlayerData player) {
- // Give stellium
- if (operation == Operation.GIVE)
- player.giveStellium(amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
+ // Give stellium
+ if (operation == Operation.GIVE)
+ player.giveStellium(amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
- // Set stellium
- else if (operation == Operation.SET)
- player.setStellium(amount.calculate());
+ // Set stellium
+ else if (operation == Operation.SET)
+ player.setStellium(amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
- // Take stellium
- else
- player.giveStellium(-amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
- }
+ // Take stellium
+ else player.giveStellium(-amount.calculate(), PlayerResourceUpdateEvent.UpdateReason.TRIGGER);
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java
index 3588795a..1212c630 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
-import org.apache.commons.lang.Validate;
public class UnlockSlotTrigger extends Trigger implements Removable {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java
index d4d9d516..80ab1ee1 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java
@@ -3,14 +3,17 @@ package net.Indyuce.mmocore.api.util;
import com.google.common.collect.MultimapBuilder;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
import io.lumine.mythic.lib.gson.JsonArray;
import io.lumine.mythic.lib.gson.JsonObject;
import io.lumine.mythic.lib.hologram.Hologram;
+import io.lumine.mythic.lib.util.lang3.Validate;
import io.lumine.mythic.lib.version.Attributes;
import io.lumine.mythic.lib.version.VEnchantment;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.MMOCommandEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.util.Icon;
-import org.apache.commons.lang.Validate;
import org.bukkit.*;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
@@ -51,6 +54,12 @@ public class MMOCoreUtils {
return player.getName() == null;
}
+ public static boolean callLegacyCommandEvent(PlayerData playerData, CommandTreeRoot command) {
+ final var called = new MMOCommandEvent(playerData, command);
+ Bukkit.getServer().getPluginManager().callEvent(called);
+ return called.isCancelled();
+ }
+
@Deprecated
public static String displayName(ItemStack item) {
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName()
@@ -62,7 +71,10 @@ public class MMOCoreUtils {
* @param maxStat Maximum value of resource
* @return Clamped resource value. If the provided current value is 0,
* this function will return the maximum resource value.
+ * @deprecated Not used anymore
+ * @see UtilityMethods#setHealth(LivingEntity, double)
*/
+ @Deprecated
public static double fixResource(double current, double maxStat) {
return current == 0 ? maxStat : Math.max(0, Math.min(current, maxStat));
}
@@ -125,6 +137,7 @@ public class MMOCoreUtils {
return material == Material.PLAYER_HEAD || material == Material.PLAYER_WALL_HEAD;
}
+ @Deprecated
public static void addAllItemFlags(@NotNull ItemMeta meta) {
meta.addItemFlags(ItemFlag.values());
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/math/formula/RandomAmount.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/math/formula/RandomAmount.java
index 6f4071e4..d5579e82 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/math/formula/RandomAmount.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/math/formula/RandomAmount.java
@@ -1,6 +1,6 @@
package net.Indyuce.mmocore.api.util.math.formula;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import java.util.Random;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/Arguments.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/Arguments.java
new file mode 100644
index 00000000..5515532a
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/Arguments.java
@@ -0,0 +1,137 @@
+package net.Indyuce.mmocore.command;
+
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.command.argument.ArgumentParseException;
+import io.lumine.mythic.lib.command.argument.PermissionException;
+import io.lumine.mythic.lib.util.lang3.Validate;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.quest.Quest;
+import net.Indyuce.mmocore.experience.Booster;
+import net.Indyuce.mmocore.experience.Profession;
+import net.Indyuce.mmocore.skill.RegisteredSkill;
+import net.Indyuce.mmocore.skilltree.tree.SkillTree;
+import net.Indyuce.mmocore.waypoint.Waypoint;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class Arguments {
+
+ public static final Argument<@NotNull PlayerClass> CLASS = new Argument<>("class",
+ (explorer, list) -> MMOCore.plugin.classManager.getAll().forEach(profess -> list.add(profess.getId())),
+ (explorer, input) -> {
+ final var profess = MMOCore.plugin.classManager.get(input.toUpperCase().replace("-", "_"));
+ if (profess == null) throw new ArgumentParseException("Could not find class with ID '" + input + "'");
+ return profess;
+ });
+
+ public static final Argument<@NotNull Waypoint> WAYPOINT = new Argument<>("waypoint",
+ (explorer, list) -> MMOCore.plugin.waypointManager.getAll().forEach(way -> list.add(way.getId())),
+ (explorer, input) -> {
+ final var waypoint = MMOCore.plugin.waypointManager.get(input);
+ if (waypoint == null)
+ throw new ArgumentParseException("Could not find waypoint with ID '" + input + "'");
+ return waypoint;
+ });
+
+ public static final Argument<@Nullable String> ACCEPT_OR_DENY_OPTIONAL = Argument.choices("accept/deny", "accept", "deny").withFallback(explorer -> null);
+
+ public static final Argument<@NotNull Player> PLAYER_IF_OP = new Argument<>("player",
+ (explorer, list) -> {
+ if (!explorer.getSender().hasPermission("mmocore.admin")) return;
+ Bukkit.getOnlinePlayers().forEach(online -> list.add(online.getName()));
+ },
+ (explorer, input) -> {
+ if (!explorer.getSender().hasPermission("mmocore.admin")) throw new PermissionException();
+
+ final var player = Bukkit.getPlayer(input);
+ Validate.notNull(player, "Could not find player " + input);
+ return player;
+ }, explorer -> {
+ if (explorer.getSender() instanceof Player) return (Player) explorer.getSender();
+ throw new ArgumentParseException("Please provide a player");
+ });
+
+ public static final Argument<@NotNull PlayerAttribute> ATTRIBUTE = new Argument<>("attribute",
+ (explorer, list) -> MMOCore.plugin.attributeManager.getAll().forEach(attribute -> list.add(attribute.getId())),
+ (explorer, input) -> {
+ final var attribute = MMOCore.plugin.attributeManager.get(input);
+ if (attribute == null)
+ throw new ArgumentParseException("Could not find attribute with ID '" + input + "'");
+ return attribute;
+ });
+
+ public static final Argument<@NotNull RegisteredSkill> SKILL = new Argument<>("skill",
+ (explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase())),
+ (explorer, input) -> {
+ final var skill = MMOCore.plugin.skillManager.getSkill(input);
+ if (skill == null) throw new ArgumentParseException("Could not find skill with ID '" + input + "'");
+ return skill;
+ });
+
+ public static final Argument PROFESSION = new Argument<>("profession/main", (explorer, list) -> {
+ MMOCore.plugin.professionManager.getAll().forEach(profession -> list.add(profession.getId()));
+ list.add("main");
+ }, (explorer, input) -> {
+ if (input.equalsIgnoreCase("main")) return null;
+ final var profession = MMOCore.plugin.professionManager.get(input);
+ if (profession == null) throw new ArgumentParseException("Could not find profession with ID '" + input + "'");
+ return profession;
+ });
+
+ public static final Argument BOOSTER = new Argument<>("booster_id",
+ (explorer, list) -> MMOCore.plugin.boosterManager.getActive().forEach(booster -> list.add(String.valueOf(booster.getUniqueId()))),
+ (explorer, input) -> {
+ try {
+ final var uuid = java.util.UUID.fromString(input);
+ for (Booster booster : MMOCore.plugin.boosterManager.getActive())
+ if (booster.getUniqueId().equals(uuid))
+ return booster;
+ throw new ArgumentParseException("Could not find active booster with ID '" + input + "'");
+ } catch (IllegalArgumentException exception) {
+ throw new ArgumentParseException("Invalid UUID '" + input + "'");
+ }
+ });
+
+ public static final Argument QUEST = new Argument<>("quest",
+ (explorer, list) -> MMOCore.plugin.questManager.getAll().forEach(quest -> list.add(quest.getId())),
+ (explorer, input) -> {
+ final var quest = MMOCore.plugin.questManager.get(input);
+ if (quest == null) throw new ArgumentParseException("Could not find quest with ID '" + input + "'");
+ return quest;
+ });
+
+ public static final Argument SKILL_TREE = new Argument<>("skill_tree_id",
+ (explorer, list) -> MMOCore.plugin.skillTreeManager.getAll().forEach(skillTree -> list.add(skillTree.getId())),
+ (explorer, input) -> {
+ final var skillTree = MMOCore.plugin.skillTreeManager.get(input);
+ if (skillTree == null)
+ throw new ArgumentParseException("Could not find skill tree with ID '" + input + "'");
+ return skillTree;
+ });
+
+ public static final String SKILL_TREE_GLOBAL_KEY = "global";
+
+ public static final Argument<@Nullable SkillTree> SKILL_TREE_OR_GLOBAL = new Argument<>("skill_tree_id",
+ (explorer, list) -> {
+ list.add("global");
+ MMOCore.plugin.skillTreeManager.getAll().forEach(skillTree -> list.add(skillTree.getId()));
+ },
+ (explorer, input) -> {
+ if (input.equalsIgnoreCase(SKILL_TREE_GLOBAL_KEY)) return null;
+ final var skillTree = MMOCore.plugin.skillTreeManager.get(input);
+ if (skillTree == null)
+ throw new ArgumentParseException("Could not find skill tree with ID '" + input + "' and not '" + SKILL_TREE_GLOBAL_KEY + "'");
+ return skillTree;
+ });
+
+ public static final Argument<@NotNull Integer> INDEX = Argument.AMOUNT_INT
+ .withKey("index")
+ .withAutoComplete((explorer, list) -> {
+ for (int j = 1; j <= 9; j++)
+ list.add(String.valueOf(j));
+ });
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/AttributesCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/AttributesCommand.java
deleted file mode 100644
index d1eb3f00..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/AttributesCommand.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class AttributesCommand extends RegisteredCommand {
- public AttributesCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.ATTRIBUTES);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.attributes"))
- return false;
-
- if (!(sender instanceof Player)) {
- sender.sendMessage(ChatColor.RED + "This command is for players only.");
- return true;
- }
-
- PlayerData data = PlayerData.get((Player) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "attributes");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if(!event.isCancelled()) InventoryManager.ATTRIBUTE_VIEW.newInventory(data).open();
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/ClassCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/ClassCommand.java
deleted file mode 100644
index 4b3ade0a..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/ClassCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class ClassCommand extends RegisteredCommand {
- public ClassCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.CLASS);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.class-select"))
- return false;
-
- Player player = args.length > 0 && sender.hasPermission("mmocore.admin") ? Bukkit.getPlayer(args[0]) : sender instanceof Player ? (Player) sender : null;
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Please specify a valid player.");
- return true;
- }
-
- PlayerData data = PlayerData.get(player);
- MMOCommandEvent event = new MMOCommandEvent(data, "class");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if(event.isCancelled()) return true;
- if (data.getProfess().getSubclasses().stream().anyMatch(sub -> sub.getLevel() <= data.getLevel()))
- InventoryManager.SUBCLASS_SELECT.newInventory(data).open();
- else
- InventoryManager.CLASS_SELECT.newInventory(data).open();
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/DepositCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/DepositCommand.java
deleted file mode 100644
index 0b64e473..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/DepositCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.gui.eco.DepositMenu;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class DepositCommand extends RegisteredCommand {
- public DepositCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.DEPOSIT);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.currency"))
- return false;
-
- Player player = args.length > 0 && sender.hasPermission("mmocore.admin") ? Bukkit.getPlayer(args[0]) : sender instanceof Player ? (Player) sender : null;
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Please specify a valid player.");
- return true;
- }
-
- // if (sender instanceof Player)
- // if (!isNearEnderchest(((Player) sender).getLocation())) {
- // sender.sendMessage(ConfigMessage.fromKey("stand-near-enderchest"));
- // return true;
- // }
-
- new DepositMenu(player).open();
- return true;
- }
-
- // private boolean isNearEnderchest(Location loc) {
- // for (int x = -5; x < 6; x++)
- // for (int y = -5; y < 6; y++)
- // for (int z = -5; z < 6; z++)
- // if (loc.clone().add(x, y, z).getBlock().getType() ==
- // Material.ENDER_CHEST)
- // return true;
- // return false;
- // }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/FriendsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/FriendsCommand.java
deleted file mode 100644
index 5fe651da..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/FriendsCommand.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.api.player.social.FriendRequest;
-import net.Indyuce.mmocore.api.player.social.Request;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import org.apache.commons.lang.Validate;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.UUID;
-
-public class FriendsCommand extends RegisteredCommand {
- public FriendsCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.FRIENDS);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.friends"))
- return false;
- if (!(sender instanceof Player)) {
- sender.sendMessage(ChatColor.RED + "This command is for players only.");
- return true;
- }
-
- PlayerData data = PlayerData.get((Player) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "friends");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (event.isCancelled()) return true;
-
- if (args.length > 1) {
-
- final @Nullable FriendRequest invite;
- if (args.length > 1)
-
- // Search by request ID
- try {
- final UUID uuid = UUID.fromString(args[1]);
- final Request req = MMOCore.plugin.requestManager.getRequest(uuid);
- Validate.isTrue(!req.isTimedOut() && req instanceof FriendRequest);
- Validate.isTrue(!data.hasFriend(req.getCreator().getUniqueId()));
- invite = (FriendRequest) req;
- } catch (Exception exception) {
- return true;
- }
-
- // Search by target player
- else
- invite = MMOCore.plugin.requestManager.findRequest(data, FriendRequest.class);
-
- // No invite found with given identifier/target player
- if (invite == null)
- return true;
-
- if (args[0].equalsIgnoreCase("accept"))
- invite.accept();
- if (args[0].equalsIgnoreCase("deny"))
- invite.deny();
- return true;
- }
-
- InventoryManager.FRIEND_LIST.newInventory(data).open();
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java
deleted file mode 100644
index 58728f1e..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/GuildCommand.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.api.player.social.Request;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.guild.provided.GuildInvite;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import org.apache.commons.lang.Validate;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.UUID;
-
-public class GuildCommand extends RegisteredCommand {
- public GuildCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.GUILD);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.guild"))
- return false;
- if (!(sender instanceof Player)) {
- sender.sendMessage(ChatColor.RED + "This command is for players only.");
- return true;
- }
-
- PlayerData data = PlayerData.get((OfflinePlayer) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "guild");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (event.isCancelled()) return true;
-
- if (args.length >= 1) {
-
- final @Nullable GuildInvite invite;
- if (args.length > 1)
-
- // Search by request ID
- try {
- final UUID uuid = UUID.fromString(args[1]);
- final Request req = MMOCore.plugin.requestManager.getRequest(uuid);
- Validate.isTrue(!req.isTimedOut() && req instanceof GuildInvite);
- invite = (GuildInvite) req;
- Validate.isTrue(MMOCore.plugin.nativeGuildManager.isRegistered(invite.getGuild()));
- } catch (Exception exception) {
- return true;
- }
-
- // Search by target player
- else
- invite = MMOCore.plugin.requestManager.findRequest(data, GuildInvite.class);
-
- // No invite found with given identifier/target player
- if (invite == null)
- return true;
-
- if (args[0].equalsIgnoreCase("accept"))
- invite.accept();
- if (args[0].equalsIgnoreCase("deny"))
- invite.deny();
- return true;
- }
-
- if (data.inGuild())
- InventoryManager.GUILD_VIEW.newInventory(data).open();
- else
- InventoryManager.GUILD_CREATION.newInventory(data).open();
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/MMOCoreCommandTreeRoot.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/MMOCoreCommandTreeRoot.java
deleted file mode 100644
index de02f0cb..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/MMOCoreCommandTreeRoot.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import io.lumine.mythic.lib.command.api.CommandTreeRoot;
-import io.lumine.mythic.lib.command.api.Parameter;
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.command.rpg.CastCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.CoinsCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.NoteCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.ReloadCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.admin.AdminCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.booster.BoosterCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.debug.DebugCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.quest.QuestCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.waypoint.WaypointsCommandTreeNode;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.TabCompleter;
-
-public class MMOCoreCommandTreeRoot extends CommandTreeRoot implements CommandExecutor, TabCompleter {
- public static final Parameter PROFESSION = new Parameter("", (explorer, list) -> {
- MMOCore.plugin.professionManager.getAll().forEach(profession -> list.add(profession.getId()));
- list.add("main");
- });
- public static final Parameter QUEST = new Parameter("",
- (explorer, list) -> MMOCore.plugin.questManager.getAll().forEach(quest -> list.add(quest.getId())));
-
- public MMOCoreCommandTreeRoot() {
- super("mmocore", "mmocore.admin");
-
- addChild(new ReloadCommandTreeNode(this));
- addChild(new CastCommandTreeNode(this));
- addChild(new CoinsCommandTreeNode(this));
- addChild(new NoteCommandTreeNode(this));
- addChild(new AdminCommandTreeNode(this));
- addChild(new DebugCommandTreeNode(this));
- addChild(new BoosterCommandTreeNode(this));
- addChild(new WaypointsCommandTreeNode(this));
- addChild(new QuestCommandTreeNode(this));
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PartyCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PartyCommand.java
deleted file mode 100644
index c55d3e7f..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PartyCommand.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.api.player.social.Request;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
-import net.Indyuce.mmocore.party.provided.PartyInvite;
-import org.apache.commons.lang.Validate;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.UUID;
-
-public class PartyCommand extends RegisteredCommand {
- public PartyCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.PARTY);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.party"))
- return false;
- if (!(sender instanceof Player)) {
- sender.sendMessage(ChatColor.RED + "This command is for players only.");
- return true;
- }
- if(!(MMOCore.plugin.partyModule instanceof MMOCorePartyModule)){
- sender.sendMessage(ChatColor.RED+"You can't use MMOCore party system as you delegated the party system to another plugin.");
- return true;
- }
-
- PlayerData data = PlayerData.get((OfflinePlayer) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "party");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (event.isCancelled()) return true;
-
- if (args.length > 0) {
-
- final @Nullable PartyInvite invite;
- if (args.length > 1)
-
- // Search by request ID
- try {
- final Request req = MMOCore.plugin.requestManager.getRequest(UUID.fromString(args[1]));
- Validate.isTrue(req instanceof PartyInvite && !req.isTimedOut());
- invite = (PartyInvite) req;
- Validate.isTrue(((MMOCorePartyModule) MMOCore.plugin.partyModule).isRegistered(invite.getParty()));
- } catch (Exception exception) {
- return true;
- }
-
- // Search by target player
- else
- invite = MMOCore.plugin.requestManager.findRequest(data, PartyInvite.class);
-
- // No invite found with given identifier/target player
- if (invite == null)
- return true;
-
- if (args[0].equalsIgnoreCase("accept"))
- invite.accept();
- else if (args[0].equalsIgnoreCase("deny"))
- invite.deny();
- return true;
- }
-
- if (data.getParty() != null)
- InventoryManager.PARTY_VIEW.newInventory(data).open();
- else
- InventoryManager.PARTY_CREATION.newInventory(data).open();
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PlayerStatsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PlayerStatsCommand.java
deleted file mode 100644
index 6fd8c2e1..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PlayerStatsCommand.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class PlayerStatsCommand extends RegisteredCommand {
- public PlayerStatsCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.PLAYER);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.profile"))
- return false;
- if (!(sender instanceof Player)) {
- sender.sendMessage(ChatColor.RED + "This command is for players only.");
- return true;
- }
-
- PlayerData data = PlayerData.get((Player) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "profile");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (!event.isCancelled()) InventoryManager.PLAYER_STATS.newInventory(data).open();
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java
deleted file mode 100644
index 5e445d4b..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/PvpModeCommand.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import io.lumine.mythic.lib.MythicLib;
-import io.lumine.mythic.lib.comp.flags.CustomFlag;
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.player.Message;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class PvpModeCommand extends RegisteredCommand {
- public PvpModeCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.PVP_MODE);
- }
-
- public static final String COOLDOWN_KEY = "PvpMode";
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!(sender instanceof Player)) {
- sender.sendMessage(ChatColor.RED + "This command is for players only.");
- return false;
- }
-
- if (!sender.hasPermission("mmocore.pvpmode")) {
- Message.NOT_ENOUGH_PERMS.send((Player) sender);
- return false;
- }
-
- final PlayerData playerData = PlayerData.get((Player) sender);
-
- // Command cooldown
- if (playerData.getCooldownMap().isOnCooldown(COOLDOWN_KEY)) {
- var remainingFormatted = MythicLib.plugin.getMMOConfig().decimal.format(playerData.getCooldownMap().getCooldown(COOLDOWN_KEY));
- Message.PVP_MODE_COOLDOWN.send((Player) sender, "remaining", remainingFormatted);
- return true;
- }
-
- playerData.getCombat().setPvpMode(!playerData.getCombat().isInPvpMode());
- playerData.getCooldownMap().applyCooldown(COOLDOWN_KEY, playerData.getCombat().isInPvpMode() ? MMOCore.plugin.configManager.pvpModeToggleOnCooldown : MMOCore.plugin.configManager.pvpModeToggleOffCooldown);
-
- // Toggling on when in PVP region
- // Give invulnerability for a short time
- if (playerData.getCombat().isInPvpMode() &&
- MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) {
- playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand);
- var timeFormatted = MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand);
- Message.PVP_MODE_TOGGLE_ON_INVULNERABLE.send((Player) sender, "time", timeFormatted);
- }
-
- // Just send message otherwise
- else {
- var currentPvpMode = playerData.getCombat().isInPvpMode();
- (currentPvpMode ? Message.PVP_MODE_TOGGLE_ON_SAFE : Message.PVP_MODE_TOGGLE_OFF_SAFE).send((Player) sender);
- }
-
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/QuestsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/QuestsCommand.java
deleted file mode 100644
index 939e0d61..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/QuestsCommand.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class QuestsCommand extends RegisteredCommand {
- public QuestsCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.QUESTS);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.quests"))
- return false;
- if (sender instanceof Player) {
- PlayerData data = PlayerData.get((Player) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "quests");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if(!event.isCancelled()) InventoryManager.QUEST_LIST.newInventory(data).open();
- }
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/SkillTreesCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/SkillTreesCommand.java
deleted file mode 100644
index bcba12b1..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/SkillTreesCommand.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import io.lumine.mythic.lib.UtilityMethods;
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import net.Indyuce.mmocore.player.Message;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.stream.Collectors;
-
-public class SkillTreesCommand extends RegisteredCommand {
- public SkillTreesCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.SKILL_TREES);
- }
-
- @Override
- public boolean execute(@NotNull CommandSender sender, @NotNull String label, String[] args) {
- if (!sender.hasPermission("mmocore.skilltrees")) return false;
- if (!(sender instanceof Player)) return false;
-
- final Player player = (Player) sender;
- PlayerData data = PlayerData.get(player);
- MMOCommandEvent event = new MMOCommandEvent(data, "skilltrees");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (event.isCancelled())
- return false;
-
- // Default skilltree command
- if (args.length == 0) {
- if (!MMOCore.plugin.configManager.enableGlobalSkillTreeGUI) {
- sender.sendMessage(ChatColor.RED + "Usage: /skilltrees ");
- return false;
- }
- if (!data.getProfess().getSkillTrees().isEmpty()) {
- InventoryManager.TREE_VIEW.newInventory(data).open();
- return true;
- } else {
- Message.NO_SKILL_TREE.send(player);
- return false;
- }
- }
-
- // Specific skilltree command
- if (args.length == 1) {
- if (!MMOCore.plugin.configManager.enableSpecificSkillTreeGUI) {
- sender.sendMessage(ChatColor.RED + "Usage: /skilltrees ");
- return false;
- }
-
- if (data.getProfess().getSkillTrees()
- .stream()
- .filter(skillTree -> UtilityMethods.ymlName(skillTree.getId()).equals(UtilityMethods.ymlName(args[0])))
- .collect(Collectors.toList())
- .size() != 0) {
- InventoryManager.SPECIFIC_TREE_VIEW.get(UtilityMethods.ymlName(args[0])).newInventory(data).open();
- return true;
- } else {
- sender.sendMessage(ChatColor.RED + "Your class does not have a skill tree with id: " + args[0]);
- return false;
- }
- } else {
- if (MMOCore.plugin.configManager.enableSpecificSkillTreeGUI)
- sender.sendMessage(ChatColor.RED + "Usage: /skilltrees ");
- else
- sender.sendMessage(ChatColor.RED + "Usage: /skilltrees");
- return false;
- }
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/SkillsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/SkillsCommand.java
deleted file mode 100644
index acba4ffa..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/SkillsCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import net.Indyuce.mmocore.player.Message;
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class SkillsCommand extends RegisteredCommand {
- public SkillsCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.SKILLS);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.skills")) return false;
-
- if (sender instanceof Player) {
- PlayerData data = PlayerData.get((Player) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "skills");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if (event.isCancelled()) return true;
-
- if (data.getUnlockedSkills().isEmpty()) {
- Message.NO_CLASS_SKILL.send((Player) sender);
- return true;
- }
-
- InventoryManager.SKILL_LIST.newInventory(data).open();
- }
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/ToggleableCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/ToggleableCommand.java
new file mode 100644
index 00000000..a52b41ba
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/ToggleableCommand.java
@@ -0,0 +1,107 @@
+package net.Indyuce.mmocore.command;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.util.config.YamlFile;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.command.builtin.*;
+import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
+import org.bukkit.configuration.ConfigurationSection;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Commands which can be disabled using commands.yml
+ */
+public enum ToggleableCommand {
+ PLAYER("player", "mmocore.profile", "Displays player stats", PlayerStatsCommand::new, "p", "profile"),
+ ATTRIBUTES("attributes", "mmocore.attributes", "Display and manage attributes", AttributesCommand::new, "att", "stats"),
+ CLASS("class", "mmocore.class-select", "Select a new class", ClassCommand::new, "c"),
+ WAYPOINTS("waypoints", "mmocore.waypoints", "Display discovered waypoints", WaypointsCommand::new, "wp"),
+ QUESTS("quests", "mmocore.quests", "Display available quests", QuestsCommand::new, "q", "journal"),
+ SKILLS("skills", "mmocore.skills", "Spend skill points to unlock new skills", SkillsCommand::new, "s"),
+ FRIENDS("friends", "mmocore.friends", "Show online/offline friends", FriendsCommand::new, "f"),
+ PARTY("party", "mmocore.party", "Invite players in a party to split exp", PartyCommand::new, () -> (MMOCore.plugin.partyModule instanceof MMOCorePartyModule)),
+ GUILD("guild", "mmocore.guild", "Show players in current guild", GuildCommand::new),
+ WITHDRAW("withdraw", "mmocore.currency", "Withdraw money into coins and notes", WithdrawCommand::new, () -> MMOCore.plugin.hasEconomy() && MMOCore.plugin.economy.isValid(), "w"),
+ SKILL_TREES("skilltrees", "mmocore.skilltrees", "Open up the skill tree menu", SkillTreesCommand::new, "st", "trees", "tree"),
+ DEPOSIT("deposit", "mmocore.currency", "Open the currency deposit menu", DepositCommand::new, "d"),
+ PVP_MODE("pvpmode", "mmocore.pvpmode", "Toggle on/off PVP mode.", PvpModeCommand::new, "pvp");
+
+ private final String mainLabel;
+ private final String description, permission;
+ private final Function generator;
+ private final List aliases;
+ private final Supplier enabled;
+
+ ToggleableCommand(@NotNull String mainLabel, @Nullable String permission, @NotNull String description, @NotNull Function generator, @NotNull String... aliases) {
+ this(mainLabel, permission, description, generator, null, aliases);
+ }
+
+ ToggleableCommand(@NotNull String mainLabel, @Nullable String permission, @NotNull String description, @NotNull Function generator, @Nullable Supplier enabled, @NotNull String... aliases) {
+ this.mainLabel = mainLabel;
+ this.permission = permission;
+ this.description = description;
+ this.generator = generator;
+ this.aliases = Arrays.asList(aliases);
+ this.enabled = enabled == null ? () -> true : enabled;
+ }
+
+ public String getMainLabel() {
+ return mainLabel;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getPermission() {
+ return permission;
+ }
+
+ public List getAliases() {
+ return aliases;
+ }
+
+ public String getConfigPath() {
+ return name().toLowerCase().replace("_", "-");
+ }
+
+ public boolean isEnabled() {
+ return enabled.get();
+ }
+
+ @Deprecated
+ public static void register() {
+ loadCommands();
+ }
+
+ public static void loadCommands() {
+
+ // Load default config file
+ final var config = new YamlFile(MMOCore.plugin, "commands");
+ if (!config.exists()) {
+ for (ToggleableCommand cmd : values()) {
+ final String path = cmd.getConfigPath();
+ config.getContent().set(path + ".main", cmd.mainLabel);
+ config.getContent().set(path + ".aliases", cmd.aliases);
+ config.getContent().set(path + ".description", cmd.description);
+ config.getContent().set(path + ".permission", cmd.permission);
+ config.getContent().set(path + ".verbose", "ALL");
+ }
+
+ config.save();
+ }
+
+ // Enable commands individually
+ final var commandMap = UtilityMethods.getCommandMap();
+ for (var cmd : values())
+ if (cmd.enabled.get() && config.getContent().contains(cmd.getConfigPath()))
+ commandMap.register("mmocore", cmd.generator.apply(config.getContent().getConfigurationSection(cmd.getConfigPath())).toBukkit());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/WaypointsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/WaypointsCommand.java
deleted file mode 100644
index 78b41708..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/WaypointsCommand.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import net.Indyuce.mmocore.api.event.MMOCommandEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.manager.InventoryManager;
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class WaypointsCommand extends RegisteredCommand {
- public WaypointsCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.WAYPOINTS);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (sender instanceof Player && sender.hasPermission("mmocore.waypoints")) {
- PlayerData data = PlayerData.get((Player) sender);
- MMOCommandEvent event = new MMOCommandEvent(data, "waypoints");
- Bukkit.getServer().getPluginManager().callEvent(event);
- if(!event.isCancelled()) InventoryManager.WAYPOINTS.newInventory(data).open();
- }
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/WithdrawCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/WithdrawCommand.java
deleted file mode 100644
index 243d56ee..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/WithdrawCommand.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package net.Indyuce.mmocore.command;
-
-import io.lumine.mythic.lib.api.player.MMOPlayerData;
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.eco.Withdraw;
-import net.Indyuce.mmocore.command.api.RegisteredCommand;
-import net.Indyuce.mmocore.command.api.ToggleableCommand;
-import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-public class WithdrawCommand extends RegisteredCommand {
- public WithdrawCommand(ConfigurationSection config) {
- super(config, ToggleableCommand.WITHDRAW);
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!sender.hasPermission("mmocore.currency"))
- return false;
-
- final Player player;
- if (args.length >= 2 && sender.hasPermission("mmocore.admin")) player = Bukkit.getPlayer(args[0]);
- else if (args.length == 1 && sender.hasPermission("mmocore.admin")) {
- Player tryFirstArg = Bukkit.getPlayer(args[0]);
- player = tryFirstArg != null ? tryFirstArg : sender instanceof Player ? (Player) sender : null;
- } else if (sender instanceof Player) player = (Player) sender;
- else player = null;
-
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Please specify a valid player.");
- return true;
- }
-
- int amount;
- try {
- if (args.length == 0) amount = 0;
- else amount = Integer.parseInt(args[args.length - 1]);
- Validate.isTrue(amount >= 0);
- } catch (IllegalArgumentException exception) {
- if (sender instanceof Player)
- Message.WITHDRAW_INVALID_AMOUNT.prepare("arg", args[0]).send((MMOPlayerData) sender);
- else sender.sendMessage(ChatColor.RED + "Please specify a valid number.");
- return true;
- }
-
- Withdraw request = new Withdraw(player);
-
- if (amount == 0) {
- request.open();
- return true;
- }
-
- int left = (int) MMOCore.plugin.economy.getEconomy().getBalance(player) - amount;
- if (left < 0) {
- Message.WITHDRAW_NOT_ENOUGH_MONEY.send(player, "left", -left);
- return true;
- }
-
- MMOCore.plugin.economy.getEconomy().withdrawPlayer(player, amount);
- request.withdrawAlgorithm(amount);
- Message.WITHDRAW_SUCCESS.send(player, "worth", amount);
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/CommandVerbose.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/CommandVerbose.java
deleted file mode 100644
index 52d9d572..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/CommandVerbose.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package net.Indyuce.mmocore.command.api;
-
-import io.lumine.mythic.lib.UtilityMethods;
-import net.Indyuce.mmocore.MMOCore;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.entity.Player;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.logging.Level;
-
-public class CommandVerbose {
- private final Map values = new HashMap<>();
-
- public void reload(ConfigurationSection config) {
- values.clear();
- for (CommandType type : CommandType.values())
- try {
- values.put(type, VerboseValue.valueOf(config.getString(UtilityMethods.ymlName(type.name()), "TRUE").toUpperCase()));
- } catch (IllegalArgumentException exception) {
- values.put(type, VerboseValue.TRUE);
- MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load command verbose action for " + type.name());
- }
- }
-
- public void handle(CommandSender sender, CommandType type, String verbose) {
- switch (values.getOrDefault(type, VerboseValue.FALSE)) {
- case FALSE:
- return;
- case TRUE:
- sender.sendMessage(verbose);
- break;
- case PLAYER:
- if (sender instanceof Player)
- sender.sendMessage(verbose);
- break;
- case CONSOLE:
- if (sender instanceof ConsoleCommandSender)
- sender.sendMessage(verbose);
- break;
- }
- }
-
- public static void verbose(CommandSender sender, CommandType cmd, String verbose) {
- MMOCore.plugin.configManager.commandVerbose.handle(sender, cmd, verbose);
- }
-
- public enum CommandType {
- ATTRIBUTE,
- SKILL,
- CLASS,
- EXPERIENCE,
- LEVEL,
- NOCD,
- POINTS,
- SKILL_TREE_POINTS,
- RESET,
- RESOURCE,
- WAYPOINT;
- }
-
- private enum VerboseValue {
- TRUE,
- PLAYER,
- CONSOLE,
- FALSE
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/RegisteredCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/RegisteredCommand.java
deleted file mode 100644
index dc7077c3..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/RegisteredCommand.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package net.Indyuce.mmocore.command.api;
-
-import org.bukkit.command.defaults.BukkitCommand;
-import org.bukkit.configuration.ConfigurationSection;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class RegisteredCommand extends BukkitCommand {
- public RegisteredCommand(@NotNull ConfigurationSection config, ToggleableCommand command) {
- super(config.getString("main"));
-
- setAliases(config.getStringList("aliases"));
- setDescription(config.getString("description", command.getDescription()));
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/ToggleableCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/ToggleableCommand.java
deleted file mode 100644
index 24dcc935..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/api/ToggleableCommand.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package net.Indyuce.mmocore.command.api;
-
-import io.lumine.mythic.lib.util.config.YamlFile;
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.command.*;
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandMap;
-import org.bukkit.configuration.ConfigurationSection;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.logging.Level;
-
-/**
- * Commands which can be disabled using commands.yml
- */
-public enum ToggleableCommand {
- PLAYER("player", "Displays player stats", config -> new PlayerStatsCommand(config), "p", "profile"),
- ATTRIBUTES("attributes", "Display and manage attributes", config -> new AttributesCommand(config), "att", "stats"),
- CLASS("class", "Select a new class", config -> new ClassCommand(config), "c"),
- WAYPOINTS("waypoints", "Display discovered waypoints", config -> new WaypointsCommand(config), "wp"),
- QUESTS("quests", "Display available quests", config -> new QuestsCommand(config), "q", "journal"),
- SKILLS("skills", "Spend skill points to unlock new skills", config -> new SkillsCommand(config), "s"),
- FRIENDS("friends", "Show online/offline friends", config -> new FriendsCommand(config), "f"),
- PARTY("party", "Invite players in a party to split exp", config -> new PartyCommand(config)),
- GUILD("guild", "Show players in current guild", config -> new GuildCommand(config)),
- WITHDRAW("withdraw", "Withdraw money into coins and notes", config -> new WithdrawCommand(config), v -> MMOCore.plugin.hasEconomy() && MMOCore.plugin.economy.isValid(), "w"),
- SKILL_TREES("skilltrees", "Open up the skill tree menu", config -> new SkillTreesCommand(config), "st", "trees", "tree"),
- DEPOSIT("deposit", "Open the currency deposit menu", config -> new DepositCommand(config), "d"),
- PVP_MODE("pvpmode", "Toggle on/off PVP mode.", config -> new PvpModeCommand(config), "pvp");
-
- private final String mainLabel;
- private final String description;
- private final Function generator;
- private final List aliases;
- private final Predicate enabled;
-
- ToggleableCommand(@NotNull String mainLabel, @NotNull String description, @NotNull Function generator, @NotNull String... aliases) {
- this(mainLabel, description, generator, null, aliases);
- }
-
- ToggleableCommand(@NotNull String mainLabel, @NotNull String description, @NotNull Function generator, @Nullable Predicate enabled, @NotNull String... aliases) {
- this.mainLabel = mainLabel;
- this.description = description;
- this.generator = generator;
- this.aliases = Arrays.asList(aliases);
- this.enabled = enabled == null ? v -> true : enabled;
- }
-
- public String getMainLabel() {
- return mainLabel;
- }
-
- public String getDescription() {
- return description;
- }
-
- public List getAliases() {
- return aliases;
- }
-
- public String getConfigPath() {
- return name().toLowerCase().replace("_", "-");
- }
-
- public boolean isEnabled() {
- return enabled.test(null);
- }
-
- public static void register() {
-
- // Load default config file
- if (!new File(MMOCore.plugin.getDataFolder(), "commands.yml").exists()) {
- final var config = new YamlFile(MMOCore.plugin, "commands");
-
- for (ToggleableCommand cmd : values()) {
- final String path = cmd.getConfigPath();
- config.getContent().set(path + ".main", cmd.mainLabel);
- config.getContent().set(path + ".aliases", cmd.aliases);
- config.getContent().set(path + ".description", cmd.description);
- }
-
- config.save();
- }
-
-
- try {
-
- // Find command map
- final Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap");
- commandMapField.setAccessible(true);
- final CommandMap commandMap = (CommandMap) commandMapField.get(Bukkit.getServer());
-
- // Enable commands individually
- final var config = new YamlFile(MMOCore.plugin, "commands").getContent();
- for (ToggleableCommand cmd : values())
- if (cmd.isEnabled() && config.contains(cmd.getConfigPath()))
- commandMap.register("mmocore", cmd.generator.apply(config.getConfigurationSection(cmd.getConfigPath())));
-
- } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException exception) {
- MMOCore.plugin.getLogger().log(Level.WARNING, "Unable to register custom commands:");
- exception.printStackTrace();
- }
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/AttributesCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/AttributesCommand.java
new file mode 100644
index 00000000..892707b6
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/AttributesCommand.java
@@ -0,0 +1,35 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class AttributesCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public AttributesCommand(@NotNull ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ final var playerData = PlayerData.get(player);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ InventoryManager.ATTRIBUTE_VIEW.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/ClassCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/ClassCommand.java
new file mode 100644
index 00000000..1a66c9f3
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/ClassCommand.java
@@ -0,0 +1,39 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class ClassCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public ClassCommand(@NotNull ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ final var playerData = PlayerData.get(player);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ // Main class or subclass
+ if (playerData.getProfess().getSubclasses().stream().anyMatch(sub -> sub.getLevel() <= playerData.getLevel()))
+ InventoryManager.SUBCLASS_SELECT.newInventory(playerData).open();
+ else InventoryManager.CLASS_SELECT.newInventory(playerData).open();
+
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/DepositCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/DepositCommand.java
new file mode 100644
index 00000000..a27c6e18
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/DepositCommand.java
@@ -0,0 +1,50 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.gui.eco.DepositMenu;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class DepositCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public DepositCommand(@NotNull ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ if (MMOCoreUtils.callLegacyCommandEvent(PlayerData.get(player), this)) return CommandResult.FAILURE;
+
+ // if (sender instanceof Player)
+ // if (!isNearEnderchest(((Player) sender).getLocation())) {
+ // sender.sendMessage(ConfigMessage.fromKey("stand-near-enderchest"));
+ // return true;
+ // }
+
+ new DepositMenu(player).open();
+ return CommandResult.SUCCESS;
+ }
+
+ // private boolean isNearEnderchest(Location loc) {
+ // for (int x = -5; x < 6; x++)
+ // for (int y = -5; y < 6; y++)
+ // for (int z = -5; z < 6; z++)
+ // if (loc.clone().add(x, y, z).getBlock().getType() ==
+ // Material.ENDER_CHEST)
+ // return true;
+ // return false;
+ // }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/FriendsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/FriendsCommand.java
new file mode 100644
index 00000000..fe4fe351
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/FriendsCommand.java
@@ -0,0 +1,75 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.util.lang3.Validate;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.social.FriendRequest;
+import net.Indyuce.mmocore.api.player.social.Request;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+public class FriendsCommand extends CommandTreeRoot {
+ private final Argument argAction;
+
+ public FriendsCommand(ConfigurationSection config) {
+ super(config);
+
+ argAction = addArgument(Arguments.ACCEPT_OR_DENY_OPTIONAL);
+ setOnlyForPlayers();
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var action = explorer.parse(argAction);
+
+ PlayerData playerData = PlayerData.get((Player) sender);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ // Open inventory
+ if (action == null) {
+ InventoryManager.FRIEND_LIST.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+
+ final @Nullable FriendRequest invite;
+ if (args.length > 1)
+
+ // Search by request ID
+ try {
+ final UUID uuid = UUID.fromString(args[1]);
+ final Request req = MMOCore.plugin.requestManager.getRequest(uuid);
+ Validate.isTrue(!req.isTimedOut() && req instanceof FriendRequest);
+ Validate.isTrue(!playerData.hasFriend(req.getCreator().getUniqueId()));
+ invite = (FriendRequest) req;
+ } catch (Exception exception) {
+ return CommandResult.FAILURE;
+ }
+
+ // Search by target player
+ else invite = MMOCore.plugin.requestManager.findRequest(playerData, FriendRequest.class);
+
+ // No invite found with given identifier/target player
+ if (invite == null) {
+ Message.FRIEND_NO_PENDING_INVITE.send(playerData);
+ return CommandResult.FAILURE;
+ }
+
+ if (args[0].equalsIgnoreCase("accept")) invite.accept();
+ if (args[0].equalsIgnoreCase("deny")) invite.deny();
+
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/GuildCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/GuildCommand.java
new file mode 100644
index 00000000..f27d5a90
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/GuildCommand.java
@@ -0,0 +1,76 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.util.lang3.Validate;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.social.Request;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.guild.provided.GuildInvite;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+public class GuildCommand extends CommandTreeRoot {
+ private final Argument argAction;
+
+ public GuildCommand(ConfigurationSection config) {
+ super(config);
+
+ argAction = addArgument(Arguments.ACCEPT_OR_DENY_OPTIONAL);
+ setOnlyForPlayers();
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var action = explorer.parse(argAction);
+
+ final var playerData = PlayerData.get((Player) sender);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ // Open guild inventory/creation
+ if (action == null) {
+ if (playerData.inGuild()) InventoryManager.GUILD_VIEW.newInventory(playerData).open();
+ else InventoryManager.GUILD_CREATION.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+
+ final @Nullable GuildInvite invite;
+ if (args.length > 1)
+
+ // Search by request ID
+ try {
+ final UUID uuid = UUID.fromString(args[1]);
+ final Request req = MMOCore.plugin.requestManager.getRequest(uuid);
+ Validate.isTrue(!req.isTimedOut() && req instanceof GuildInvite);
+ invite = (GuildInvite) req;
+ Validate.isTrue(MMOCore.plugin.nativeGuildManager.isRegistered(invite.getGuild()));
+ } catch (Exception exception) {
+ return CommandResult.FAILURE;
+ }
+
+ // Search by target player
+ else invite = MMOCore.plugin.requestManager.findRequest(playerData, GuildInvite.class);
+
+ // No invite found with given identifier/target player
+ if (invite == null) {
+ Message.GUILD_NO_PENDING_INVITE.send(playerData);
+ return CommandResult.FAILURE;
+ }
+
+ if (args[0].equalsIgnoreCase("accept")) invite.accept();
+ if (args[0].equalsIgnoreCase("deny")) invite.deny();
+
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PartyCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PartyCommand.java
new file mode 100644
index 00000000..c6a93d11
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PartyCommand.java
@@ -0,0 +1,76 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.util.lang3.Validate;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.social.Request;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
+import net.Indyuce.mmocore.party.provided.PartyInvite;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+public class PartyCommand extends CommandTreeRoot {
+ private final Argument argAction;
+
+ public PartyCommand(ConfigurationSection config) {
+ super(config);
+
+ argAction = addArgument(Arguments.ACCEPT_OR_DENY_OPTIONAL);
+ setOnlyForPlayers();
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var action = explorer.parse(argAction);
+
+ final var playerData = PlayerData.get((Player) sender);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ // Open inventory
+ if (action == null) {
+ if (playerData.getParty() != null) InventoryManager.PARTY_VIEW.newInventory(playerData).open();
+ else InventoryManager.PARTY_CREATION.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+
+ final @Nullable PartyInvite invite;
+ if (args.length > 1)
+
+ // Search by request ID
+ try {
+ final Request req = MMOCore.plugin.requestManager.getRequest(UUID.fromString(args[1]));
+ Validate.isTrue(req instanceof PartyInvite && !req.isTimedOut());
+ invite = (PartyInvite) req;
+ Validate.isTrue(((MMOCorePartyModule) MMOCore.plugin.partyModule).isRegistered(invite.getParty()));
+ } catch (Exception exception) {
+ return CommandResult.FAILURE;
+ }
+
+ // Search by target player
+ else invite = MMOCore.plugin.requestManager.findRequest(playerData, PartyInvite.class);
+
+ // No invite found with given identifier/target player
+ if (invite == null) {
+ Message.PARTY_NO_PENDING_INVITE.send(playerData);
+ return CommandResult.FAILURE;
+ }
+
+ if (args[0].equalsIgnoreCase("accept")) invite.accept();
+ else if (args[0].equalsIgnoreCase("deny")) invite.deny();
+
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PlayerStatsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PlayerStatsCommand.java
new file mode 100644
index 00000000..626d6c4c
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PlayerStatsCommand.java
@@ -0,0 +1,35 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class PlayerStatsCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public PlayerStatsCommand(@NotNull ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ final var playerData = PlayerData.get(player);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ InventoryManager.PLAYER_STATS.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PvpModeCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PvpModeCommand.java
new file mode 100644
index 00000000..9a130427
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/PvpModeCommand.java
@@ -0,0 +1,62 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.MythicLib;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.comp.flags.CustomFlag;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.player.CombatHandler;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class PvpModeCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public PvpModeCommand(ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ final PlayerData playerData = PlayerData.get(player);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ // Check command cooldown
+ if (playerData.getCooldownMap().isOnCooldown(CombatHandler.COOLDOWN_KEY)) {
+ var remainingFormatted = MythicLib.plugin.getMMOConfig().decimal.format(playerData.getCooldownMap().getCooldown(CombatHandler.COOLDOWN_KEY));
+ Message.PVP_MODE_COOLDOWN.send(playerData, "remaining", remainingFormatted);
+ return CommandResult.FAILURE;
+ }
+
+ playerData.getCombat().setPvpMode(!playerData.getCombat().isInPvpMode());
+ playerData.getCooldownMap().applyCooldown(CombatHandler.COOLDOWN_KEY, playerData.getCombat().isInPvpMode() ? MMOCore.plugin.configManager.pvpModeToggleOnCooldown : MMOCore.plugin.configManager.pvpModeToggleOffCooldown);
+
+ // Toggling on when in PVP region
+ // Give invulnerability for a short time
+ if (playerData.getCombat().isInPvpMode() &&
+ MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) {
+ playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand);
+ var timeFormatted = MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand);
+ Message.PVP_MODE_TOGGLE_ON_INVULNERABLE.send((Player) sender, "time", timeFormatted);
+ }
+
+ // Just send message otherwise
+ else {
+ var currentPvpMode = playerData.getCombat().isInPvpMode();
+ (currentPvpMode ? Message.PVP_MODE_TOGGLE_ON_SAFE : Message.PVP_MODE_TOGGLE_OFF_SAFE).send((Player) sender);
+ }
+
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/QuestsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/QuestsCommand.java
new file mode 100644
index 00000000..e79d86e1
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/QuestsCommand.java
@@ -0,0 +1,34 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class QuestsCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public QuestsCommand(ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ final var playerData = PlayerData.get(player);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ InventoryManager.QUEST_LIST.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/SkillTreesCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/SkillTreesCommand.java
new file mode 100644
index 00000000..7a4d9bd4
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/SkillTreesCommand.java
@@ -0,0 +1,58 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import net.Indyuce.mmocore.player.Message;
+import net.Indyuce.mmocore.skilltree.tree.SkillTree;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SkillTreesCommand extends CommandTreeRoot {
+ private final Argument argType;
+
+ public SkillTreesCommand(@NotNull ConfigurationSection config) {
+ super(config);
+
+ argType = addArgument(MMOCore.plugin.configManager.enableGlobalSkillTreeGUI ? Arguments.SKILL_TREE_OR_GLOBAL.withFallback(e -> null) : Arguments.SKILL_TREE);
+ setOnlyForPlayers();
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var data = PlayerData.get((Player) sender);
+ if (data.getProfess().getSkillTrees().isEmpty()) {
+ Message.NO_SKILL_TREE.send(data);
+ return CommandResult.FAILURE;
+ }
+
+ final @Nullable var opened = explorer.parse(argType); // null == global
+ if (MMOCoreUtils.callLegacyCommandEvent(data, this)) return CommandResult.FAILURE;
+
+ // Global skill tree view
+ if (opened == null) {
+ InventoryManager.TREE_VIEW.newInventory(data).open();
+ return CommandResult.FAILURE;
+ }
+
+ // Specific skill tree view
+ final var classHas = data.getProfess().getSkillTrees().stream().anyMatch(tree -> tree.getId().equals(opened.getId()));
+ if (!classHas) {
+ Message.NO_CLASS_SKILL_TREE.send(data);
+ return CommandResult.FAILURE;
+ }
+
+ InventoryManager.SPECIFIC_TREE_VIEW.get(UtilityMethods.kebabCase(opened.getId())).newInventory(data).open();
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/SkillsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/SkillsCommand.java
new file mode 100644
index 00000000..ef6e68cd
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/SkillsCommand.java
@@ -0,0 +1,41 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class SkillsCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public SkillsCommand(@NotNull ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ final var playerData = PlayerData.get(player);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ if (playerData.getUnlockedSkills().isEmpty()) {
+ Message.NO_CLASS_SKILL.send((Player) sender);
+ return CommandResult.FAILURE;
+ }
+
+ InventoryManager.SKILL_LIST.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/WaypointsCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/WaypointsCommand.java
new file mode 100644
index 00000000..b8bb495d
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/WaypointsCommand.java
@@ -0,0 +1,35 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class WaypointsCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+
+ public WaypointsCommand(ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+
+ final var playerData = PlayerData.get(player);
+ if (MMOCoreUtils.callLegacyCommandEvent(playerData, this)) return CommandResult.FAILURE;
+
+ InventoryManager.WAYPOINTS.newInventory(playerData).open();
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/WithdrawCommand.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/WithdrawCommand.java
new file mode 100644
index 00000000..a102c407
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/WithdrawCommand.java
@@ -0,0 +1,48 @@
+package net.Indyuce.mmocore.command.builtin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.eco.Withdraw;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class WithdrawCommand extends CommandTreeRoot {
+ private final Argument argPlayer;
+ private final Argument argAmount;
+
+ public WithdrawCommand(@NotNull ConfigurationSection config) {
+ super(config);
+
+ argPlayer = addArgument(Arguments.PLAYER_IF_OP);
+ argAmount = addArgument(Argument.AMOUNT_INT.withFallback(explorer -> 0));
+ }
+
+ @Override
+ @NotNull
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+ final var amount = explorer.parse(argAmount);
+
+ if (amount == 0) {
+ new Withdraw(player).open();
+ return CommandResult.SUCCESS;
+ }
+
+ int left = (int) MMOCore.plugin.economy.getEconomy().getBalance(player) - amount;
+ if (left < 0) {
+ Message.WITHDRAW_NOT_ENOUGH_MONEY.send(player, "left", -left);
+ return CommandResult.FAILURE;
+ }
+
+ MMOCore.plugin.economy.getEconomy().withdrawPlayer(player, amount);
+ new Withdraw(player).withdrawAlgorithm(amount);
+ Message.WITHDRAW_SUCCESS.send(player, "worth", amount);
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/AttributeCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/AttributeCommandTreeNode.java
new file mode 100644
index 00000000..1748938b
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/AttributeCommandTreeNode.java
@@ -0,0 +1,49 @@
+package net.Indyuce.mmocore.command.builtin.mmocore;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
+import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
+import net.Indyuce.mmocore.command.Arguments;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class AttributeCommandTreeNode extends CommandTreeNode {
+ public AttributeCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "attribute");
+
+ addChild(new ActionCommandTreeNode(this, "give", 1));
+ addChild(new ActionCommandTreeNode(this, "take", -1));
+ }
+
+ static class ActionCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argAttribute;
+ private final Argument argAmount;
+
+ private final int c;
+
+ public ActionCommandTreeNode(CommandTreeNode parent, String type, int coef) {
+ super(parent, type);
+
+ this.c = coef;
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argAttribute = addArgument(Arguments.ATTRIBUTE);
+ argAmount = addArgument(Argument.AMOUNT_INT);
+ }
+
+ @Override
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+ final var attribute = explorer.parse(argAttribute);
+ final var amount = explorer.parse(argAmount);
+
+ PlayerAttributes.AttributeInstance instance = PlayerData.get(player).getAttributes().getInstance(attribute);
+ instance.setBase(Math.min(attribute.getMax(), instance.getBase() + c * amount));
+ return explorer.success("&6" + player.getName() + "&e now has &6" + instance.getBase() + "&e points in " + attribute.getName() + ".");
+ }
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/CastCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/CastCommandTreeNode.java
new file mode 100644
index 00000000..a338caef
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/CastCommandTreeNode.java
@@ -0,0 +1,14 @@
+package net.Indyuce.mmocore.command.builtin.mmocore;
+
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.cast.FirstCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.cast.SpecificCommandTreeNode;
+
+public class CastCommandTreeNode extends CommandTreeNode {
+ public CastCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "cast");
+
+ addChild(new FirstCommandTreeNode(this));
+ addChild(new SpecificCommandTreeNode(this));
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/CoinsCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/CoinsCommandTreeNode.java
similarity index 75%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/CoinsCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/CoinsCommandTreeNode.java
index fc185d36..11ca6156 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/CoinsCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/CoinsCommandTreeNode.java
@@ -1,8 +1,9 @@
-package net.Indyuce.mmocore.command.rpg;
+package net.Indyuce.mmocore.command.builtin.mmocore;
import io.lumine.mythic.lib.api.util.SmartGive;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.util.item.CurrencyItemBuilder;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -10,17 +11,16 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
-
public class CoinsCommandTreeNode extends CommandTreeNode {
public CoinsCommandTreeNode(CommandTreeNode parent) {
super(parent, "coins");
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
+ addArgument(Argument.PLAYER);
+ addArgument(Argument.AMOUNT_INT);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/MMOCoreCommandTreeRoot.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/MMOCoreCommandTreeRoot.java
new file mode 100644
index 00000000..4ea52d8d
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/MMOCoreCommandTreeRoot.java
@@ -0,0 +1,31 @@
+package net.Indyuce.mmocore.command.builtin.mmocore;
+
+import io.lumine.mythic.lib.command.CommandTreeRoot;
+import net.Indyuce.mmocore.command.builtin.mmocore.admin.AdminCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.booster.BoosterCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.clazz.ClassCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.debug.DebugCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.quest.QuestCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.skill.SkillCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.skilltree.SkillTreeCommandNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.waypoint.WaypointsCommandTreeNode;
+
+public class MMOCoreCommandTreeRoot extends CommandTreeRoot {
+ public MMOCoreCommandTreeRoot() {
+ super("mmocore", "mmocore.admin");
+
+ addChild(new ReloadCommandTreeNode(this));
+ addChild(new CastCommandTreeNode(this));
+ addChild(new CoinsCommandTreeNode(this));
+ addChild(new NoteCommandTreeNode(this));
+ addChild(new SkillTreeCommandNode(this));
+ addChild(new AdminCommandTreeNode(this));
+ addChild(new DebugCommandTreeNode(this));
+ addChild(new BoosterCommandTreeNode(this));
+ addChild(new WaypointsCommandTreeNode(this));
+ addChild(new QuestCommandTreeNode(this));
+ addChild(new SkillCommandTreeNode(this));
+ addChild(new AttributeCommandTreeNode(this));
+ addChild(new ClassCommandTreeNode(this));
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/NoteCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/NoteCommandTreeNode.java
similarity index 69%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/NoteCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/NoteCommandTreeNode.java
index 2217cf2e..e731dbc1 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/NoteCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/NoteCommandTreeNode.java
@@ -1,27 +1,25 @@
-package net.Indyuce.mmocore.command.rpg;
+package net.Indyuce.mmocore.command.builtin.mmocore;
import io.lumine.mythic.lib.api.util.SmartGive;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.util.item.CurrencyItemBuilder;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import java.util.Arrays;
-
public class NoteCommandTreeNode extends CommandTreeNode {
public NoteCommandTreeNode(CommandTreeNode parent) {
super(parent, "note");
- addParameter(Parameter.PLAYER);
- addParameter(new Parameter("",
- (explorer, list) -> list.addAll(Arrays.asList("10", "20", "30", "40", "50", "60", "70", "80", "90", "100"))));
+ addArgument(Argument.PLAYER);
+ addArgument(Argument.AMOUNT_INT.withKey("worth"));
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/ReloadCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/ReloadCommandTreeNode.java
similarity index 77%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/ReloadCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/ReloadCommandTreeNode.java
index 81d6a660..5bbb8869 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/ReloadCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/ReloadCommandTreeNode.java
@@ -1,6 +1,7 @@
-package net.Indyuce.mmocore.command.rpg;
+package net.Indyuce.mmocore.command.builtin.mmocore;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
import net.Indyuce.mmocore.MMOCore;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -11,7 +12,7 @@ public class ReloadCommandTreeNode extends CommandTreeNode {
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
sender.sendMessage(ChatColor.YELLOW + "Reloading " + MMOCore.plugin.getName() + " " + MMOCore.plugin.getDescription().getVersion() + "...");
long ms = System.currentTimeMillis();
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/AdminCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/AdminCommandTreeNode.java
new file mode 100644
index 00000000..9b6faac6
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/AdminCommandTreeNode.java
@@ -0,0 +1,60 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
+
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
+import net.Indyuce.mmocore.command.builtin.mmocore.AttributeCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.admin.reset.ResetCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.skill.SkillCommandTreeNode;
+import net.Indyuce.mmocore.command.builtin.mmocore.slot.SlotCommandTreeNode;
+
+public class AdminCommandTreeNode extends CommandTreeNode {
+ public AdminCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "admin");
+
+ addChild(new HideActionBarCommandTreeNode(this));
+ addChild(new NoCooldownCommandTreeNode(this));
+ addChild(new ResetCommandTreeNode(this));
+ addChild(new InfoCommandTreeNode(this));
+ addChild(new LegacyClassCommandTreeNode(this));
+ addChild(new LegacyForceClassCommandTreeNode(this));
+ addChild(new ExportDataTreeNode(this));
+
+ addChild(new ExperienceCommandTreeNode(this));
+ addChild(new LevelCommandTreeNode(this));
+ addChild(new AttributeCommandTreeNode(this)); // Backwards compatibility
+ addChild(new SkillCommandTreeNode(this)); // Backwards compatibility
+ addChild(new SaveDataTreeNode(this));
+ addChild(new SlotCommandTreeNode(this));
+ addChild(new PointsCommandTreeNode("skill", this,
+ PlayerData::setSkillPoints,
+ PlayerData::giveSkillPoints,
+ PlayerData::getSkillPoints));
+ addChild(new PointsCommandTreeNode("class", this,
+ PlayerData::setClassPoints,
+ PlayerData::giveClassPoints,
+ PlayerData::getClassPoints));
+ addChild(new PointsCommandTreeNode("attribute", this,
+ PlayerData::setAttributePoints,
+ PlayerData::giveAttributePoints,
+ PlayerData::getAttributePoints));
+ 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, amount, skillTree) -> playerData.setSkillTreePoints(skillTree, amount),
+ (playerData, amount, skillTree) -> playerData.giveSkillTreePoints(skillTree, amount),
+ PlayerData::getSkillTreePoints));
+ for (PlayerResource res : PlayerResource.values())
+ addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExperienceCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExperienceCommandTreeNode.java
new file mode 100644
index 00000000..648c7d97
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExperienceCommandTreeNode.java
@@ -0,0 +1,85 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
+
+import io.lumine.mythic.lib.MythicLib;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.util.lang3.Validate;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.experience.EXPSource;
+import net.Indyuce.mmocore.experience.PlayerProfessions;
+import net.Indyuce.mmocore.experience.Profession;
+import net.Indyuce.mmocore.util.TriConsumer;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.function.BiConsumer;
+
+public class ExperienceCommandTreeNode extends CommandTreeNode {
+ public ExperienceCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "exp");
+
+ addChild(new ActionCommandTreeNode(this, "set", PlayerData::setExperience, PlayerProfessions::setExperience));
+ addChild(new ActionCommandTreeNode(this, "give", (data, value) -> data.giveExperience(value, EXPSource.COMMAND), (professions, profession,
+ value) -> professions.giveExperience(profession, value, EXPSource.COMMAND)));
+ addChild(new ActionCommandTreeNode(this, "take", (data, value) -> data.giveExperience(-value, EXPSource.COMMAND), (professions, profession,
+ value) -> professions.giveExperience(profession, -value, EXPSource.COMMAND)));
+ }
+
+ public static class ActionCommandTreeNode extends CommandTreeNode {
+ private final BiConsumer main;
+ private final TriConsumer profession;
+
+ public ActionCommandTreeNode(CommandTreeNode parent, String type, BiConsumer main,
+ TriConsumer profession) {
+ super(parent, type);
+
+ this.main = main;
+ this.profession = profession;
+
+ addArgument(Argument.PLAYER);
+ addArgument(Arguments.PROFESSION);
+ addArgument(Argument.AMOUNT_INT);
+ }
+
+ @Override
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ if (args.length < 6)
+ return CommandResult.THROW_USAGE;
+
+ Player player = Bukkit.getPlayer(args[3]);
+ if (player == null) {
+ return explorer.fail("Could not find the player called " + args[3] + ".");
+ }
+
+ long amount;
+ try {
+ amount = Long.parseLong(args[5]);
+ Validate.isTrue(amount >= 0);
+ } catch (RuntimeException exception) {
+ return explorer.fail( args[5] + " is not a valid number.");
+ }
+
+ PlayerData data = PlayerData.get(player);
+ if (args[4].equalsIgnoreCase("main")) {
+ main.accept(data, amount);
+ return explorer.success(ChatColor.GOLD + player.getName() + ChatColor.YELLOW
+ + " now has " + ChatColor.GOLD + MythicLib.plugin.getMMOConfig().decimal.format(data.getExperience()) + ChatColor.YELLOW + " EXP.");
+ }
+
+ String format = args[4].toLowerCase().replace("_", "-");
+ if (!MMOCore.plugin.professionManager.has(format)) {
+ return explorer.fail(format + " is not a valid profession.");
+ }
+
+ Profession profession = MMOCore.plugin.professionManager.get(format);
+ this.profession.accept(data.getCollectionSkills(), profession, amount);
+ return explorer.success(ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " now has " + ChatColor.GOLD
+ + data.getCollectionSkills().getExperience(profession) + ChatColor.YELLOW + " EXP in " + profession.getName() + ".");
+ }
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExportDataTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExportDataTreeNode.java
similarity index 58%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExportDataTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExportDataTreeNode.java
index c87e0ebf..4d1f1503 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExportDataTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExportDataTreeNode.java
@@ -1,11 +1,11 @@
-package net.Indyuce.mmocore.command.rpg.admin;
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
import io.lumine.mythic.lib.data.DataExport;
-import io.lumine.mythic.lib.data.sql.SQLDataSource;
import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler;
-import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler;
+import net.Indyuce.mmocore.manager.data.sql.SQLDatabaseImpl;
+import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
@@ -20,12 +20,12 @@ public class ExportDataTreeNode extends CommandTreeNode {
@Override
@NotNull
- public CommandResult execute(CommandSender sender, String[] strings) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
// Export YAML to SQL
final boolean result = new DataExport<>(MMOCore.plugin.playerDataManager, sender).start(
- () -> new YAMLPlayerDataHandler(MMOCore.plugin),
- () -> new SQLDataHandler(new SQLDataSource(MMOCore.plugin)));
+ YAMLDatabaseImpl::new,
+ SQLDatabaseImpl::new);
return result ? CommandResult.SUCCESS : CommandResult.FAILURE;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/HideActionBarCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/HideActionBarCommandTreeNode.java
similarity index 73%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/HideActionBarCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/HideActionBarCommandTreeNode.java
index 4a0c164a..b43709fa 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/HideActionBarCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/HideActionBarCommandTreeNode.java
@@ -1,7 +1,8 @@
-package net.Indyuce.mmocore.command.rpg.admin;
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import io.lumine.mythic.lib.message.actionbar.ActionBarPriority;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Bukkit;
@@ -13,12 +14,12 @@ public class HideActionBarCommandTreeNode extends CommandTreeNode {
public HideActionBarCommandTreeNode(CommandTreeNode parent) {
super(parent, "hideab");
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
+ addArgument(Argument.PLAYER);
+ addArgument(Argument.DURATION_TICKS);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/InfoCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/InfoCommandTreeNode.java
similarity index 86%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/InfoCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/InfoCommandTreeNode.java
index bb3b0600..3828fc08 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/InfoCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/InfoCommandTreeNode.java
@@ -1,8 +1,9 @@
-package net.Indyuce.mmocore.command.rpg.admin;
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
import io.lumine.mythic.lib.MythicLib;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.Profession;
@@ -15,11 +16,11 @@ public class InfoCommandTreeNode extends CommandTreeNode {
public InfoCommandTreeNode(CommandTreeNode parent) {
super(parent, "info");
- addParameter(Parameter.PLAYER);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LegacyClassCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LegacyClassCommandTreeNode.java
new file mode 100644
index 00000000..1cfe19da
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LegacyClassCommandTreeNode.java
@@ -0,0 +1,55 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @see net.Indyuce.mmocore.command.builtin.mmocore.clazz.ClassCommandTreeNode
+ * @deprecated
+ */
+@Deprecated
+public class LegacyClassCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argClass;
+
+ @Deprecated
+ public LegacyClassCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "class");
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argClass = addArgument(Arguments.CLASS);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+ PlayerClass profess = explorer.parse(argClass);
+ PlayerData data = PlayerData.get(player);
+ if (data.getProfess().equals(profess)) return CommandResult.SUCCESS;
+
+ PlayerChangeClassEvent called = new PlayerChangeClassEvent(data, profess, PlayerChangeClassEvent.Reason.COMMAND_SELECT);
+ Bukkit.getPluginManager().callEvent(called);
+ if (called.isCancelled()) return explorer.fail("Bukkit event canceled");
+
+ (data.hasSavedClass(profess) ? data.getClassInfo(profess)
+ : new SavedClassInformation(MMOCore.plugin.playerDataManager.getDefaultData())).load(profess, data);
+ if (data.isOnline()) {
+ Message.CLASS_SELECT.send(data, "class", profess.getName());
+ }
+
+ return explorer.success(ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " is now a " + ChatColor.GOLD + profess.getName() + ChatColor.YELLOW + ".");
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LegacyForceClassCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LegacyForceClassCommandTreeNode.java
new file mode 100644
index 00000000..c9e995f6
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LegacyForceClassCommandTreeNode.java
@@ -0,0 +1,58 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.command.Arguments;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @deprecated
+ * @see net.Indyuce.mmocore.command.builtin.mmocore.clazz.ForceCommandTreeNode
+ */
+@Deprecated
+public class LegacyForceClassCommandTreeNode extends CommandTreeNode {
+ public LegacyForceClassCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "force-class");
+
+ addArgument(Argument.PLAYER);
+ addArgument(Arguments.CLASS);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ if (args.length < 4)
+ return CommandResult.THROW_USAGE;
+
+ Player player = Bukkit.getPlayer(args[2]);
+ if (player == null) {
+ sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[2] + ".");
+ return CommandResult.FAILURE;
+ }
+
+ String format = args[3].toUpperCase().replace("-", "_");
+ if (!MMOCore.plugin.classManager.has(format)) {
+ sender.sendMessage(ChatColor.RED + "Could not find class " + format + ".");
+ return CommandResult.FAILURE;
+ }
+
+ PlayerClass profess = MMOCore.plugin.classManager.get(format);
+
+ PlayerData data = PlayerData.get(player);
+ final var called = new PlayerChangeClassEvent(data, profess, PlayerChangeClassEvent.Reason.COMMAND_FORCE);
+ Bukkit.getPluginManager().callEvent(called);
+ if (called.isCancelled()) return explorer.fail("Bukkit event canceled");
+
+ data.setClass(profess);
+ return explorer.success(ChatColor.GOLD + player.getName()
+ + ChatColor.YELLOW + " is now a " + ChatColor.GOLD + profess.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LevelCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LevelCommandTreeNode.java
new file mode 100644
index 00000000..8ac3bed7
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/LevelCommandTreeNode.java
@@ -0,0 +1,89 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.experience.EXPSource;
+import net.Indyuce.mmocore.experience.PlayerProfessions;
+import net.Indyuce.mmocore.experience.Profession;
+import net.Indyuce.mmocore.util.TriConsumer;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.function.BiConsumer;
+
+public class LevelCommandTreeNode extends CommandTreeNode {
+ public LevelCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "level");
+
+ addChild(new ActionCommandTreeNode(this, "set",
+ (player, newLevel) -> player.setLevel(newLevel, PlayerLevelChangeEvent.Reason.COMMAND),
+ (player, profession, amount) -> player.setLevel(profession, amount, PlayerLevelChangeEvent.Reason.COMMAND)));
+ addChild(new ActionCommandTreeNode(this, "give",
+ (data, value) -> data.giveLevels(value, EXPSource.COMMAND),
+ (professions, profession, value) -> professions.giveLevels(profession, value, EXPSource.COMMAND)));
+ addChild(new ActionCommandTreeNode(this, "take",
+ (playerData, amount) -> playerData.setLevel(playerData.getLevel() - amount, PlayerLevelChangeEvent.Reason.COMMAND),
+ (player, profession, amount) -> player.setLevel(profession, player.getLevel(profession) - amount, PlayerLevelChangeEvent.Reason.COMMAND)));
+ }
+
+ public static class ActionCommandTreeNode extends CommandTreeNode {
+ private final BiConsumer main;
+ private final TriConsumer profession;
+
+ public ActionCommandTreeNode(CommandTreeNode parent, String type, BiConsumer main,
+ TriConsumer profession) {
+ super(parent, type);
+
+ this.main = main;
+ this.profession = profession;
+
+ addArgument(Argument.PLAYER);
+ addArgument(Arguments.PROFESSION);
+ addArgument(Argument.AMOUNT_INT);
+ }
+
+ @Override
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ if (args.length < 6)
+ return CommandResult.THROW_USAGE;
+
+ Player player = Bukkit.getPlayer(args[3]);
+ if (player == null) {
+ sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
+ return CommandResult.FAILURE;
+ }
+
+ int amount;
+ try {
+ amount = Integer.parseInt(args[5]);
+ } catch (NumberFormatException exception) {
+ sender.sendMessage(ChatColor.RED + args[5] + " is not a valid number.");
+ return CommandResult.FAILURE;
+ }
+
+ PlayerData data = PlayerData.get(player);
+ if (args[4].equalsIgnoreCase("main")) {
+ main.accept(data, amount);
+
+ return explorer.success(ChatColor.GOLD + player.getName() + "&e is now Lvl &6" + data.getLevel());
+ }
+
+ String format = args[4].toLowerCase().replace("_", "-");
+ if (!MMOCore.plugin.professionManager.has(format)) {
+ return explorer.fail(format + " is not a valid profession.");
+ }
+
+ Profession profession = MMOCore.plugin.professionManager.get(format);
+ this.profession.accept(data.getCollectionSkills(), profession, amount);
+ return explorer.success(ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " is now Lvl " + ChatColor.GOLD
+ + data.getCollectionSkills().getLevel(profession) + ChatColor.YELLOW + " in " + profession.getName());
+ }
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/NoCooldownCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/NoCooldownCommandTreeNode.java
similarity index 57%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/NoCooldownCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/NoCooldownCommandTreeNode.java
index 94f0a0c0..b7539b2f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/NoCooldownCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/NoCooldownCommandTreeNode.java
@@ -1,9 +1,9 @@
-package net.Indyuce.mmocore.command.rpg.admin;
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -13,11 +13,11 @@ public class NoCooldownCommandTreeNode extends CommandTreeNode {
public NoCooldownCommandTreeNode(CommandTreeNode parent) {
super(parent, "nocd");
- addParameter(Parameter.PLAYER);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
@@ -29,8 +29,6 @@ public class NoCooldownCommandTreeNode extends CommandTreeNode {
PlayerData data = PlayerData.get(player);
data.noCooldown = !data.noCooldown;
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.NOCD,
- ChatColor.YELLOW + "NoCD " + (data.noCooldown ? "enabled" : "disabled") + " for " + player.getName() + ".");
- return CommandResult.SUCCESS;
+ return explorer.success(ChatColor.YELLOW + "NoCD " + (data.noCooldown ? "enabled" : "disabled") + " for " + player.getName());
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/PointsCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/PointsCommandTreeNode.java
similarity index 69%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/PointsCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/PointsCommandTreeNode.java
index 817bc186..42f47bd6 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/PointsCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/PointsCommandTreeNode.java
@@ -1,9 +1,9 @@
-package net.Indyuce.mmocore.command.rpg.admin;
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -35,12 +35,12 @@ public class PointsCommandTreeNode extends CommandTreeNode {
this.action = action;
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
+ addArgument(Argument.PLAYER);
+ addArgument(Argument.AMOUNT_INT);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 5)
return CommandResult.THROW_USAGE;
@@ -60,14 +60,8 @@ public class PointsCommandTreeNode extends CommandTreeNode {
PlayerData data = PlayerData.get(player);
action.accept(data, amount);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.POINTS, ChatColor.GOLD + player.getName()
- + ChatColor.YELLOW + " now has " + ChatColor.GOLD + get.apply(data) + ChatColor.YELLOW + " " + type + " points.");
- return CommandResult.SUCCESS;
+ return explorer.success(ChatColor.GOLD + player.getName()
+ + ChatColor.YELLOW + " now has " + ChatColor.GOLD + get.apply(data) + ChatColor.YELLOW + " " + type + " points.");
}
}
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ResourceCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ResourceCommandTreeNode.java
similarity index 69%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ResourceCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ResourceCommandTreeNode.java
index 0d919e57..6f7c39ab 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ResourceCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ResourceCommandTreeNode.java
@@ -1,11 +1,11 @@
-package net.Indyuce.mmocore.command.rpg.admin;
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.api.quest.trigger.ManaTrigger;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -34,12 +34,12 @@ public class ResourceCommandTreeNode extends CommandTreeNode {
this.action = action;
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
+ addArgument(Argument.PLAYER);
+ addArgument(Argument.AMOUNT_DOUBLE);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 5)
return CommandResult.THROW_USAGE;
@@ -59,15 +59,8 @@ public class ResourceCommandTreeNode extends CommandTreeNode {
PlayerData data = PlayerData.get(player);
resource.getConsumer(action).accept(data, amount);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESOURCE,
- ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " now has " + ChatColor.GOLD + resource.getCurrent(data)
- + ChatColor.YELLOW + " " + type + " points.");
- return CommandResult.SUCCESS;
+ return explorer.success(ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " now has " + ChatColor.GOLD + resource.getCurrent(data)
+ + ChatColor.YELLOW + " " + type + " points.");
}
}
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SaveDataTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SaveDataTreeNode.java
similarity index 60%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SaveDataTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SaveDataTreeNode.java
index 1e768f3e..aca0772d 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SaveDataTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SaveDataTreeNode.java
@@ -1,7 +1,9 @@
-package net.Indyuce.mmocore.command.rpg.admin;
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.data.SaveReason;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Bukkit;
@@ -16,11 +18,11 @@ public class SaveDataTreeNode extends CommandTreeNode {
public SaveDataTreeNode(CommandTreeNode parent) {
super(parent, "savedata");
- addParameter(Parameter.PLAYER);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
@@ -30,7 +32,7 @@ public class SaveDataTreeNode extends CommandTreeNode {
return CommandResult.FAILURE;
}
- MMOCore.plugin.playerDataManager.getDataHandler().saveData(PlayerData.get(player), false);
+ MMOCore.plugin.playerDataManager.saveData(PlayerData.get(player), SaveReason.AUTOSAVE);
return CommandResult.SUCCESS;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SkillTreePointsCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SkillTreePointsCommandTreeNode.java
new file mode 100644
index 00000000..0246999d
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SkillTreePointsCommandTreeNode.java
@@ -0,0 +1,63 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.admin;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.skilltree.tree.SkillTree;
+import net.Indyuce.mmocore.util.TriConsumer;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.BiFunction;
+
+public class SkillTreePointsCommandTreeNode extends CommandTreeNode {
+ private final BiFunction get;
+
+ public SkillTreePointsCommandTreeNode(CommandTreeNode parent,
+ TriConsumer set,
+ TriConsumer give,
+ BiFunction get) {
+ super(parent, "skill-tree-points");
+
+ addChild(new ActionCommandTreeNode(this, "give", give));
+ addChild(new ActionCommandTreeNode(this, "set", set));
+ this.get = get;
+ }
+
+ public class ActionCommandTreeNode extends CommandTreeNode {
+ private final TriConsumer action;
+
+ private final Argument argPlayer;
+ private final Argument argAmount;
+ private final Argument argType;
+
+ public ActionCommandTreeNode(CommandTreeNode parent, String id, TriConsumer action) {
+ super(parent, id);
+
+ this.action = action;
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argAmount = addArgument(Argument.AMOUNT_INT);
+ argType = addArgument(Arguments.SKILL_TREE_OR_GLOBAL);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+ final var amount = explorer.parse(argAmount);
+ final @Nullable var skillTree = explorer.parse(argType);
+
+ final var skillTreeName = skillTree == null ? "global" : skillTree.getId();
+ final var data = PlayerData.get(player);
+ action.accept(data, amount, skillTree);
+ return explorer.success(ChatColor.GOLD + player.getName()
+ + ChatColor.YELLOW + " now has " + ChatColor.GOLD + get.apply(data, skillTree) + ChatColor.YELLOW + " " + skillTreeName + " skill tree points.");
+ }
+ }
+
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/reset/ResetCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/reset/ResetCommandTreeNode.java
new file mode 100644
index 00000000..fcb89dd7
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/reset/ResetCommandTreeNode.java
@@ -0,0 +1,233 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.admin.reset;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
+import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
+import net.Indyuce.mmocore.experience.Profession;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashSet;
+
+public class ResetCommandTreeNode extends CommandTreeNode {
+ public ResetCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "reset");
+
+ addChild(new ResetClassesCommandTreeNode(this));
+ addChild(new ResetLevelsCommandTreeNode(this));
+ addChild(new ResetSkillsCommandTreeNode(this));
+ addChild(new ResetQuestsCommandTreeNode(this));
+ addChild(new ResetAttributesCommandTreeNode(this));
+ addChild(new ResetWaypointsCommandTreeNode(this));
+ addChild(new ResetSkillTreesCommandTreeNode(this));
+ addChild(new ResetAllCommandTreeNode(this));
+ }
+
+ abstract static class AbstractResetNode extends CommandTreeNode {
+ protected final Argument argPlayer;
+
+ public AbstractResetNode(CommandTreeNode parent, String name) {
+ super(parent, name);
+
+ argPlayer = addArgument(Argument.PLAYER);
+ }
+ }
+
+ static class ResetAllCommandTreeNode extends AbstractResetNode {
+ public ResetAllCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "all");
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+ final boolean givePoints = args.length > 4 && args[4].equalsIgnoreCase("-reallocate");
+
+ PlayerData data = PlayerData.get(player);
+ ResetClassesCommandTreeNode.resetClasses(data);
+ ResetLevelsCommandTreeNode.resetLevels(data);
+ ResetSkillsCommandTreeNode.resetSkills(data);
+ ResetQuestsCommandTreeNode.resetQuests(data);
+ ResetAttributesCommandTreeNode.resetAttributes(data, givePoints);
+ ResetWaypointsCommandTreeNode.resetWaypoints(data);
+ ResetSkillTreesCommandTreeNode.resetSkillTrees(data);
+ // Reset times-claimed not being properly emptied otherwise
+ data.getItemClaims().clear();
+ return explorer.success("Player data of &6" + player.getName() + "&e was successfully reset.");
+ }
+ }
+
+
+ static class ResetWaypointsCommandTreeNode extends AbstractResetNode {
+ public ResetWaypointsCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "waypoints");
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+
+ resetWaypoints(PlayerData.get(player));
+ return explorer.success("Waypoint data of &6" + player.getName() + "&e was successfully reset.");
+ }
+
+ static void resetWaypoints(@NotNull PlayerData playerData) {
+ playerData.getWaypoints().clear();
+ }
+ }
+
+ static class ResetQuestsCommandTreeNode extends AbstractResetNode {
+ public ResetQuestsCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "quests");
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+
+ resetQuests(PlayerData.get(player));
+ return explorer.success("Quest data of &6" + player.getName() + "&e was successfully reset.");
+ }
+
+ static void resetQuests(@NotNull PlayerData data) {
+ data.getQuestData().resetFinishedQuests();
+ data.getQuestData().start(null);
+ }
+ }
+
+ static class ResetSkillsCommandTreeNode extends AbstractResetNode {
+ public ResetSkillsCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "skills");
+
+ addArgument(Argument.PLAYER);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+
+ resetSkills(PlayerData.get(player));
+ return explorer.success("Skill data of &6" + player.getName() + "&e was successfully reset.");
+ }
+
+ static void resetSkills(@NotNull PlayerData data) {
+ data.mapSkillLevels().forEach((skill, ignored) -> data.resetSkillLevel(skill));
+ while (data.hasSkillBound(0)) data.unbindSkill(0);
+ data.setUnlockedItems(new HashSet<>()); // TODO class-specific unlockables etc.
+ }
+ }
+
+ static class ResetSkillTreesCommandTreeNode extends AbstractResetNode {
+ public ResetSkillTreesCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "skill-trees");
+
+ addArgument(Argument.PLAYER);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+
+ resetSkillTrees(PlayerData.get(player));
+ return explorer.success("Skill tree data of &6" + player.getName() + "&e was successfully reset.");
+ }
+
+ // TODO option to reallocate skill tree points instead of not giving any back
+ static void resetSkillTrees(@NotNull PlayerData data) {
+ data.resetSkillTrees();
+ }
+ }
+
+ static class ResetAttributesCommandTreeNode extends AbstractResetNode {
+ public ResetAttributesCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "attributes");
+
+ addArgument(new Argument<>("-reallocate", (explore, list) -> list.add("-reallocate"), (explore, input) -> input, explorer -> ""));
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+
+ final boolean givePoints = args.length > 4 && args[4].equalsIgnoreCase("-reallocate");
+ resetAttributes(PlayerData.get(player), givePoints);
+ return explorer.success("Attribute data of &6" + player.getName() + "&e was successfully reset.");
+ }
+
+ static void resetAttributes(@NotNull PlayerData data, boolean givePoints) {
+
+ // Give back attribute points
+ if (givePoints) {
+
+ int points = 0;
+ for (PlayerAttributes.AttributeInstance ins : data.getAttributes().getInstances()) {
+ points += ins.getBase();
+ ins.setBase(0);
+ }
+
+ data.giveAttributePoints(points);
+ return;
+ }
+
+ for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll()) {
+ attribute.resetAdvancement(data, true);
+ data.getAttributes().getInstance(attribute).setBase(0);
+ }
+ }
+ }
+
+ static class ResetLevelsCommandTreeNode extends AbstractResetNode {
+ public ResetLevelsCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "levels");
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+
+ resetLevels(PlayerData.get(player));
+ return explorer.success("Main and profession levels of &6" + player.getName() + "&e were successfully reset.");
+ }
+
+ static void resetLevels(@NotNull PlayerData data) {
+
+ // Class
+ data.setLevel(MMOCore.plugin.playerDataManager.getDefaultData().getLevel(), PlayerLevelChangeEvent.Reason.RESET);
+ data.setExperience(0);
+ data.getProfess().resetAdvancement(data, true);
+
+ // Professions
+ for (Profession profession : MMOCore.plugin.professionManager.getAll()) {
+ data.getCollectionSkills().setExperience(profession, 0);
+ data.getCollectionSkills().setLevel(profession, 0, PlayerLevelChangeEvent.Reason.RESET);
+ profession.resetAdvancement(data, true);
+ }
+ }
+ }
+
+ static class ResetClassesCommandTreeNode extends AbstractResetNode {
+ public ResetClassesCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "classes");
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+
+ resetClasses(PlayerData.get(player));
+ return explorer.success("Class data of &6" + player.getName() + "&e was successfully reset.");
+ }
+
+ static void resetClasses(@NotNull PlayerData data) {
+ MMOCore.plugin.classManager.getAll().forEach(data::unloadClassInfo);
+ MMOCore.plugin.playerDataManager.getDefaultData().apply(data, PlayerLevelChangeEvent.Reason.RESET);
+ data.setClass(MMOCore.plugin.classManager.getDefaultClass());
+ }
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/BoosterCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/BoosterCommandTreeNode.java
similarity index 51%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/BoosterCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/BoosterCommandTreeNode.java
index 400d9d15..7de64dbd 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/BoosterCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/BoosterCommandTreeNode.java
@@ -1,7 +1,6 @@
-package net.Indyuce.mmocore.command.rpg.booster;
+package net.Indyuce.mmocore.command.builtin.mmocore.booster;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import org.bukkit.command.CommandSender;
+import io.lumine.mythic.lib.command.CommandTreeNode;
public class BoosterCommandTreeNode extends CommandTreeNode {
public BoosterCommandTreeNode(CommandTreeNode parent) {
@@ -11,9 +10,4 @@ public class BoosterCommandTreeNode extends CommandTreeNode {
addChild(new ListCommandTreeNode(this));
addChild(new RemoveCommandTreeNode(this));
}
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/CreateCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/CreateCommandTreeNode.java
new file mode 100644
index 00000000..f73a7bdc
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/CreateCommandTreeNode.java
@@ -0,0 +1,67 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.booster;
+
+import io.lumine.mythic.lib.MythicLib;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.experience.Booster;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.Arrays;
+
+public class CreateCommandTreeNode extends CommandTreeNode {
+ public CreateCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "create");
+
+ addArgument(Arguments.PROFESSION);
+ addArgument(Argument.AMOUNT_DOUBLE
+ .withAutoComplete((explorer, list) -> list.addAll(Arrays.asList("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1"))));
+ addArgument(Argument.DURATION_TICKS);
+ addArgument(Argument.PLAYER_OR_SENDER);
+ }
+
+ @Override
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ if (args.length < 5)
+ return CommandResult.THROW_USAGE;
+
+ double extra;
+ try {
+ extra = Double.parseDouble(args[3]);
+ } catch (NumberFormatException exception) {
+ sender.sendMessage(ChatColor.RED + args[3] + " is not a valid number.");
+ return CommandResult.FAILURE;
+ }
+
+ long length;
+ try {
+ length = Long.parseLong(args[4]);
+ } catch (NumberFormatException exception) {
+ sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
+ return CommandResult.FAILURE;
+ }
+
+ var multFormatted = MythicLib.plugin.getMMOConfig().decimal.format(1 + extra);
+ if (args[2].equalsIgnoreCase("main")) {
+ MMOCore.plugin.boosterManager.register(new Booster(args.length > 5 ? args[5] : null, extra, length));
+ Message.NEW_EXP_BOOSTER_MAIN.send(Bukkit.getOnlinePlayers(), "multiplier", multFormatted);
+ return CommandResult.SUCCESS;
+ }
+
+ String format = args[2].toLowerCase().replace("_", "-");
+ if (!MMOCore.plugin.professionManager.has(format)) {
+ sender.sendMessage(ChatColor.RED + format + " is not a valid profession.");
+ return CommandResult.FAILURE;
+ }
+
+ var profession = MMOCore.plugin.professionManager.get(format);
+ MMOCore.plugin.boosterManager.register(new Booster(args.length > 5 ? args[5] : null, profession, extra, length));
+ Message.NEW_EXP_BOOSTER_PROFESSION.send(Bukkit.getOnlinePlayers(), "multiplier", multFormatted, "profession", profession.getName());
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/ListCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/ListCommandTreeNode.java
similarity index 85%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/ListCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/ListCommandTreeNode.java
index 3fb55b1a..065c3ee3 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/ListCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/ListCommandTreeNode.java
@@ -1,7 +1,8 @@
-package net.Indyuce.mmocore.command.rpg.booster;
+package net.Indyuce.mmocore.command.builtin.mmocore.booster;
import io.lumine.mythic.lib.MythicLib;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.experience.Booster;
@@ -15,7 +16,7 @@ public class ListCommandTreeNode extends CommandTreeNode {
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (!(sender instanceof Player))
return CommandResult.FAILURE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/RemoveCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/RemoveCommandTreeNode.java
similarity index 71%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/RemoveCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/RemoveCommandTreeNode.java
index 66b62683..a62919b4 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/RemoveCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/booster/RemoveCommandTreeNode.java
@@ -1,8 +1,9 @@
-package net.Indyuce.mmocore.command.rpg.booster;
+package net.Indyuce.mmocore.command.builtin.mmocore.booster;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.command.Arguments;
import net.Indyuce.mmocore.experience.Booster;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -14,12 +15,11 @@ public class RemoveCommandTreeNode extends CommandTreeNode {
public RemoveCommandTreeNode(CommandTreeNode parent) {
super(parent, "remove");
- addParameter(new Parameter("",
- (explorer, list) -> MMOCore.plugin.boosterManager.getActive().forEach(booster -> list.add("" + booster.getUniqueId().toString()))));
+ addArgument(Arguments.BOOSTER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/cast/FirstCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/cast/FirstCommandTreeNode.java
similarity index 80%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/cast/FirstCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/cast/FirstCommandTreeNode.java
index 41fa69b7..32cf2891 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/cast/FirstCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/cast/FirstCommandTreeNode.java
@@ -1,10 +1,12 @@
-package net.Indyuce.mmocore.command.rpg.cast;
+package net.Indyuce.mmocore.command.builtin.mmocore.cast;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
import net.Indyuce.mmocore.skill.ClassSkill;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -18,12 +20,12 @@ public class FirstCommandTreeNode extends CommandTreeNode {
public FirstCommandTreeNode(CommandTreeNode parent) {
super(parent, "first");
- addParameter(Parameter.PLAYER);
- addParameter(SpecificCommandTreeNode.INTEGER);
+ addArgument(Argument.PLAYER);
+ addArgument(Arguments.INDEX);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[2]);
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/cast/SpecificCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/cast/SpecificCommandTreeNode.java
similarity index 77%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/cast/SpecificCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/cast/SpecificCommandTreeNode.java
index 560d3777..30490f6b 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/cast/SpecificCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/cast/SpecificCommandTreeNode.java
@@ -1,29 +1,27 @@
-package net.Indyuce.mmocore.command.rpg.cast;
+package net.Indyuce.mmocore.command.builtin.mmocore.cast;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
import net.Indyuce.mmocore.skill.ClassSkill;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import java.util.Arrays;
-
public class SpecificCommandTreeNode extends CommandTreeNode {
- public static final Parameter INTEGER = new Parameter("slot", false, (explorer, list) -> list.addAll(Arrays.asList("1", "2", "3", "4", "5", "6")));
-
public SpecificCommandTreeNode(CommandTreeNode parent) {
super(parent, "specific");
- addParameter(Parameter.PLAYER);
- addParameter(INTEGER);
+ addArgument(Argument.PLAYER);
+ addArgument(Arguments.INDEX);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[2]);
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/ClassCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/ClassCommandTreeNode.java
new file mode 100644
index 00000000..674396c2
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/ClassCommandTreeNode.java
@@ -0,0 +1,14 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.clazz;
+
+import io.lumine.mythic.lib.command.CommandTreeNode;
+
+public class ClassCommandTreeNode extends CommandTreeNode {
+
+ public ClassCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "class");
+
+ addChild(new GetCommandTreeNode(this));
+ addChild(new SelectCommandTreeNode(this));
+ addChild(new ForceCommandTreeNode(this));
+ }
+}
\ No newline at end of file
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/ForceCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/ForceCommandTreeNode.java
new file mode 100644
index 00000000..c1ad6fba
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/ForceCommandTreeNode.java
@@ -0,0 +1,40 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.clazz;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.command.Arguments;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class ForceCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argClass;
+
+ public ForceCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "force");
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argClass = addArgument(Arguments.CLASS);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+ final var profess = explorer.parse(argClass);
+
+ final var playerData = PlayerData.get(player);
+
+ final var called = new PlayerChangeClassEvent(playerData, profess, PlayerChangeClassEvent.Reason.COMMAND_FORCE);
+ Bukkit.getPluginManager().callEvent(called);
+ if (called.isCancelled()) return explorer.fail("Bukkit event canceled");
+
+ playerData.setClass(profess);
+ return explorer.success("Class of player &6" + player.getName() + "&e forcefully set to &6" + profess.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/GetCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/GetCommandTreeNode.java
new file mode 100644
index 00000000..156ba875
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/GetCommandTreeNode.java
@@ -0,0 +1,27 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.clazz;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class GetCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+
+ public GetCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "get");
+
+ argPlayer = addArgument(Argument.PLAYER);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+ final var playerData = PlayerData.get(player);
+
+ return explorer.success("Player &6" + player.getName() + "&e currently has class &6" + playerData.getProfess().getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/SelectCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/SelectCommandTreeNode.java
new file mode 100644
index 00000000..42ff1d43
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/clazz/SelectCommandTreeNode.java
@@ -0,0 +1,46 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.clazz;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.player.Message;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class SelectCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argClass;
+
+ public SelectCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "select");
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argClass = addArgument(Arguments.CLASS);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+ final var profess = explorer.parse(argClass);
+
+ final var playerData = PlayerData.get(player);
+ final var called = new PlayerChangeClassEvent(playerData, profess, PlayerChangeClassEvent.Reason.COMMAND_SELECT);
+ Bukkit.getPluginManager().callEvent(called);
+ if (called.isCancelled()) return explorer.fail("Bukkit event canceled");
+
+ (playerData.hasSavedClass(profess)
+ ? playerData.getClassInfo(profess)
+ : new SavedClassInformation(MMOCore.plugin.playerDataManager.getDefaultData()))
+ .load(profess, playerData);
+ Message.CLASS_SELECT.send(playerData, "class", profess.getName()); // Send message
+ return explorer.success("Class of player &6" + player.getName() + "&e changed to &6" + profess.getName() + "&e.");
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/DebugCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/DebugCommandTreeNode.java
similarity index 61%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/DebugCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/DebugCommandTreeNode.java
index cd15daa2..f757e8cd 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/DebugCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/DebugCommandTreeNode.java
@@ -1,8 +1,7 @@
-package net.Indyuce.mmocore.command.rpg.debug;
+package net.Indyuce.mmocore.command.builtin.mmocore.debug;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
+import io.lumine.mythic.lib.command.CommandTreeNode;
import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
public class DebugCommandTreeNode extends CommandTreeNode {
public static final String commandPrefix = ChatColor.YELLOW + "[" + ChatColor.RED + "DEBUG" + ChatColor.GOLD + "] " + ChatColor.RESET;
@@ -13,9 +12,4 @@ public class DebugCommandTreeNode extends CommandTreeNode {
addChild(new StatValueCommandTreeNode(this));
addChild(new StatModifiersCommandTreeNode(this));
}
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/StatModifiersCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/StatModifiersCommandTreeNode.java
similarity index 76%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/StatModifiersCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/StatModifiersCommandTreeNode.java
index 411661fe..80d2b036 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/StatModifiersCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/StatModifiersCommandTreeNode.java
@@ -1,25 +1,27 @@
-package net.Indyuce.mmocore.command.rpg.debug;
+package net.Indyuce.mmocore.command.builtin.mmocore.debug;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.stat.StatInstance;
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
public class StatModifiersCommandTreeNode extends CommandTreeNode {
public StatModifiersCommandTreeNode(CommandTreeNode parent) {
super(parent, "statmods");
- addParameter(new Parameter("", (explorer, list) -> list.add("STAT_ID")));
+ addArgument(Argument.STAT);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/StatValueCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/StatValueCommandTreeNode.java
similarity index 75%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/StatValueCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/StatValueCommandTreeNode.java
index f582ab31..d15e883a 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/debug/StatValueCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/debug/StatValueCommandTreeNode.java
@@ -1,8 +1,9 @@
-package net.Indyuce.mmocore.command.rpg.debug;
+package net.Indyuce.mmocore.command.builtin.mmocore.debug;
import io.lumine.mythic.lib.UtilityMethods;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.player.stats.StatInfo;
import org.bukkit.ChatColor;
@@ -13,11 +14,11 @@ public class StatValueCommandTreeNode extends CommandTreeNode {
public StatValueCommandTreeNode(CommandTreeNode parent) {
super(parent, "statvalue");
- addParameter(new Parameter("", (explorer, list) -> list.add("STAT_ID")));
+ addArgument(Argument.STAT);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/CancelCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/CancelCommandTreeNode.java
similarity index 75%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/CancelCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/CancelCommandTreeNode.java
index d69bbd11..e2867fbf 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/CancelCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/CancelCommandTreeNode.java
@@ -1,7 +1,8 @@
-package net.Indyuce.mmocore.command.rpg.quest;
+package net.Indyuce.mmocore.command.builtin.mmocore.quest;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.PlayerQuests;
import org.bukkit.Bukkit;
@@ -13,11 +14,11 @@ public class CancelCommandTreeNode extends CommandTreeNode {
public CancelCommandTreeNode(CommandTreeNode parent) {
super(parent, "cancel");
- addParameter(Parameter.PLAYER);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/FinishCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/FinishCommandTreeNode.java
similarity index 76%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/FinishCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/FinishCommandTreeNode.java
index 5514bfbb..3f15092b 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/FinishCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/FinishCommandTreeNode.java
@@ -1,7 +1,8 @@
-package net.Indyuce.mmocore.command.rpg.quest;
+package net.Indyuce.mmocore.command.builtin.mmocore.quest;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.PlayerQuests;
import org.bukkit.Bukkit;
@@ -13,11 +14,11 @@ public class FinishCommandTreeNode extends CommandTreeNode {
public FinishCommandTreeNode(CommandTreeNode parent) {
super(parent, "finish");
- addParameter(Parameter.PLAYER);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/QuestCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/QuestCommandTreeNode.java
similarity index 51%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/QuestCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/QuestCommandTreeNode.java
index b79e4ff7..d1f7422f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/QuestCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/QuestCommandTreeNode.java
@@ -1,7 +1,6 @@
-package net.Indyuce.mmocore.command.rpg.quest;
+package net.Indyuce.mmocore.command.builtin.mmocore.quest;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import org.bukkit.command.CommandSender;
+import io.lumine.mythic.lib.command.CommandTreeNode;
public class QuestCommandTreeNode extends CommandTreeNode {
@@ -12,9 +11,4 @@ public class QuestCommandTreeNode extends CommandTreeNode {
addChild(new CancelCommandTreeNode(this));
addChild(new FinishCommandTreeNode(this));
}
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/StartCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/StartCommandTreeNode.java
similarity index 77%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/StartCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/StartCommandTreeNode.java
index ab16a7bf..3f5ea645 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/quest/StartCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/quest/StartCommandTreeNode.java
@@ -1,12 +1,13 @@
-package net.Indyuce.mmocore.command.rpg.quest;
+package net.Indyuce.mmocore.command.builtin.mmocore.quest;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.PlayerQuests;
import net.Indyuce.mmocore.api.quest.Quest;
-import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot;
+import net.Indyuce.mmocore.command.Arguments;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -16,12 +17,12 @@ public class StartCommandTreeNode extends CommandTreeNode {
public StartCommandTreeNode(CommandTreeNode parent) {
super(parent, "start");
- addParameter(Parameter.PLAYER);
- addParameter(MMOCoreCommandTreeRoot.QUEST);
+ addArgument(Argument.PLAYER);
+ addArgument(Arguments.QUEST);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/EditLevelCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/EditLevelCommandTreeNode.java
new file mode 100644
index 00000000..e734232d
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/EditLevelCommandTreeNode.java
@@ -0,0 +1,56 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.skill;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.skill.ClassSkill;
+import net.Indyuce.mmocore.skill.RegisteredSkill;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.function.BiFunction;
+
+public class EditLevelCommandTreeNode extends CommandTreeNode {
+ private final BiFunction change;
+
+ private final Argument argPlayer;
+ private final Argument argSkill;
+ private final Argument argLevel;
+
+ public EditLevelCommandTreeNode(CommandTreeNode parent, String type, BiFunction change) {
+ super(parent, type);
+
+ this.change = change;
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argSkill = addArgument(Arguments.SKILL);
+ argLevel = addArgument(Arguments.INDEX.withKey("level"));
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+ PlayerData playerData = PlayerData.get(player);
+ RegisteredSkill skill = explorer.parse(argSkill);
+ final var changeAmount = explorer.parse(argLevel);
+
+ // Find equivalent class skill
+ ClassSkill classSkill = null;
+ for (ClassSkill var : playerData.getProfess().getSkills())
+ if (var.getSkill().equals(skill)) {
+ classSkill = var;
+ break;
+ }
+
+ if (classSkill == null || classSkill.getUnlockLevel() > playerData.getLevel()) {
+ return explorer.fail(skill.getName() + " is not unlockable for " + player.getName() + ".");
+ }
+
+ final var newValue = change.apply(playerData.getSkillLevel(skill), changeAmount);
+ playerData.setSkillLevel(skill, newValue);
+ return explorer.success("&6" + player.getName() + "&e is now level &6" + newValue + "&e for " + skill.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/LevelCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/LevelCommandTreeNode.java
new file mode 100644
index 00000000..6609c9c5
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/LevelCommandTreeNode.java
@@ -0,0 +1,13 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.skill;
+
+import io.lumine.mythic.lib.command.CommandTreeNode;
+
+
+public class LevelCommandTreeNode extends CommandTreeNode {
+ public LevelCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "level");
+
+ addChild(new EditLevelCommandTreeNode(this, "give", Integer::sum));
+ addChild(new EditLevelCommandTreeNode(this, "set", (old, amount) -> amount));
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/LockCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/LockCommandTreeNode.java
new file mode 100644
index 00000000..6cf3f6e9
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/LockCommandTreeNode.java
@@ -0,0 +1,43 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.skill;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.skill.ClassSkill;
+import net.Indyuce.mmocore.skill.RegisteredSkill;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class LockCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argSkill;
+
+ public LockCommandTreeNode(CommandTreeNode parent, String id) {
+ super(parent, id);
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argSkill = addArgument(Arguments.SKILL);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+ PlayerData playerData = PlayerData.get(player);
+ RegisteredSkill regSkill = explorer.parse(argSkill);
+
+ ClassSkill skill = playerData.getProfess().getSkill(args[4]);
+ if (skill == null) {
+ return explorer.fail("Class " + playerData.getProfess().getName() + " doesn't have a skill called '" + regSkill.getName() + "'");
+ }
+
+ if (!playerData.hasUnlocked(skill)) {
+ return explorer.fail("Skill " + skill.getSkill().getName() + " already locked for " + player.getName());
+ }
+
+ playerData.lock(skill);
+ return explorer.success("Skill &6" + skill.getSkill().getName() + "&e unlocked for &6" + player.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/SkillCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/SkillCommandTreeNode.java
new file mode 100644
index 00000000..464bd517
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/SkillCommandTreeNode.java
@@ -0,0 +1,14 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.skill;
+
+import io.lumine.mythic.lib.command.CommandTreeNode;
+
+
+public class SkillCommandTreeNode extends CommandTreeNode {
+ public SkillCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "skill");
+
+ addChild(new LockCommandTreeNode(this, "lock"));
+ addChild(new UnlockCommandTreeNode(this, "unlock"));
+ addChild(new LevelCommandTreeNode(this));
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/UnlockCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/UnlockCommandTreeNode.java
new file mode 100644
index 00000000..48fca1ca
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skill/UnlockCommandTreeNode.java
@@ -0,0 +1,43 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.skill;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.skill.ClassSkill;
+import net.Indyuce.mmocore.skill.RegisteredSkill;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class UnlockCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argSkill;
+
+ public UnlockCommandTreeNode(CommandTreeNode parent, String id) {
+ super(parent, id);
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argSkill = addArgument(Arguments.SKILL);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ Player player = explorer.parse(argPlayer);
+ PlayerData playerData = PlayerData.get(player);
+ RegisteredSkill regSkill = explorer.parse(argSkill);
+
+ ClassSkill skill = playerData.getProfess().getSkill(regSkill);
+ if (skill == null) {
+ return explorer.fail("Class does not have skill '" + regSkill.getName() + "'");
+ }
+
+ if (playerData.hasUnlocked(skill)) {
+ return explorer.fail("Skill " + skill.getSkill().getName() + " already unlocked for " + player.getName());
+ }
+
+ playerData.unlock(skill);
+ return explorer.success("Skill &6" + skill.getSkill().getName() + "&e unlocked for &6" + player.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skilltree/OpenCommandNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skilltree/OpenCommandNode.java
new file mode 100644
index 00000000..82ef7a10
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skilltree/OpenCommandNode.java
@@ -0,0 +1,54 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.skilltree;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.manager.InventoryManager;
+import net.Indyuce.mmocore.skilltree.tree.SkillTree;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class OpenCommandNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argTree;
+
+ public OpenCommandNode(CommandTreeNode parent) {
+ super(parent, "open");
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argTree = addArgument(Arguments.SKILL_TREE_OR_GLOBAL).withFallback(explorer -> null);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final var player = explorer.parse(argPlayer);
+ final @Nullable var skillTree = explorer.parse(argTree);
+
+ final var playerData = PlayerData.get(player);
+ final var skillTrees = playerData.getProfess().getSkillTrees();
+ if (skillTrees.isEmpty()) {
+ return explorer.fail("Player class " + playerData.getProfess().getName() + " of " + player.getName() + " has no skill tree");
+ }
+
+ final var skillTreeName = skillTree == null ? "Global" : skillTree.getName();
+
+ // Global skill tree view
+ if (skillTree == null) {
+ InventoryManager.TREE_VIEW.newInventory(playerData).open();
+ return explorer.success("Skill tree &6" + skillTreeName + "&e opened for player &6" + player.getName());
+ }
+
+ // Specific skill tree view
+ if (skillTrees.stream().noneMatch(candidate -> skillTree.getId().equals(candidate.getId()))) {
+ return explorer.fail("Player class " + playerData.getProfess().getName() + " of " + player.getName() + " has no skill tree " + skillTree.getId());
+ }
+
+ InventoryManager.SPECIFIC_TREE_VIEW.get(UtilityMethods.kebabCase(skillTree.getId())).newInventory(playerData).open();
+ return explorer.success("Skill tree &6" + skillTreeName + "&e opened for player &6" + player.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skilltree/SkillTreeCommandNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skilltree/SkillTreeCommandNode.java
new file mode 100644
index 00000000..9cf94dc8
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/skilltree/SkillTreeCommandNode.java
@@ -0,0 +1,11 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.skilltree;
+
+import io.lumine.mythic.lib.command.CommandTreeNode;
+
+public class SkillTreeCommandNode extends CommandTreeNode {
+ public SkillTreeCommandNode(CommandTreeNode parent) {
+ super(parent, "skill-tree");
+
+ addChild(new OpenCommandNode(this));
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/BindSlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/BindSlotCommandTreeNode.java
new file mode 100644
index 00000000..28762e13
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/BindSlotCommandTreeNode.java
@@ -0,0 +1,50 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.slot;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.skill.ClassSkill;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class BindSlotCommandTreeNode extends CommandTreeNode {
+
+ public BindSlotCommandTreeNode(CommandTreeNode parent, String id) {
+ super(parent, id);
+
+ addArgument(Argument.PLAYER);
+ addArgument(Arguments.INDEX);
+ addArgument(Arguments.SKILL);
+ }
+
+ @Override
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ if (args.length < 6)
+ return CommandResult.THROW_USAGE;
+ Player player = Bukkit.getPlayer(args[3]);
+ if (player == null) {
+ sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
+ return CommandResult.FAILURE;
+ }
+ PlayerData playerData = PlayerData.get(player);
+ int slot;
+ try {
+ slot = Integer.parseInt(args[4]);
+ } catch (NumberFormatException e) {
+ sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
+ return CommandResult.FAILURE;
+ }
+ ClassSkill skill = playerData.getProfess().getSkill(args[5]);
+ if (skill == null) {
+ sender.sendMessage(ChatColor.RED + "The player's class doesn't have a skill called " + args[5] + ".");
+ return CommandResult.FAILURE;
+ }
+ playerData.bindSkill(slot, skill);
+
+ return explorer.success("Skill &6" + skill.getSkill().getHandler().getId() + "&e now bound to slot &6" + slot);
+ }
+}
\ No newline at end of file
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/LockSlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/LockSlotCommandTreeNode.java
new file mode 100644
index 00000000..6c2fe140
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/LockSlotCommandTreeNode.java
@@ -0,0 +1,50 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.slot;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.skill.binding.SkillSlot;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class LockSlotCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argIndex;
+
+ public LockSlotCommandTreeNode(CommandTreeNode parent, String id) {
+ super(parent, id);
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argIndex = addArgument(Arguments.INDEX);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final Player player = explorer.parse(argPlayer);
+ final PlayerData playerData = PlayerData.get(player);
+ final int slot = explorer.parse(argIndex);
+
+ if (slot <= 0) {
+ return explorer.fail("The slot can't be negative.");
+ }
+ SkillSlot skillSlot = playerData.getProfess().getSkillSlot(slot);
+ if (skillSlot == null) {
+ return explorer.fail("Skill slot with index " + slot + " was not found for player " + player.getName() + " with class " + playerData.getProfess().getId());
+ }
+
+ if (skillSlot.isUnlockedByDefault()) {
+ sender.sendMessage(ChatColor.RED + "You can't lock a skill that is unlocked by default.");
+ return CommandResult.FAILURE;
+ }
+ if (!playerData.hasUnlocked(skillSlot)) {
+ return explorer.fail("Skill slot " + skillSlot.getName() + " is already locked for " + player.getName());
+ }
+
+ playerData.lock(skillSlot);
+ return explorer.success("Skill slot &6" + skillSlot.getName() + "&e is now locked for &6" + player.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/SlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/SlotCommandTreeNode.java
new file mode 100644
index 00000000..bdaf438e
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/SlotCommandTreeNode.java
@@ -0,0 +1,15 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.slot;
+
+import io.lumine.mythic.lib.command.CommandTreeNode;
+
+
+public class SlotCommandTreeNode extends CommandTreeNode {
+ public SlotCommandTreeNode(CommandTreeNode parent) {
+ super(parent, "slot");
+
+ addChild(new LockSlotCommandTreeNode(this, "lock"));
+ addChild(new UnlockSlotCommandTreeNode(this, "unlock"));
+ addChild(new UnbindSlotCommandTreeNode(this, "unbind"));
+ addChild(new BindSlotCommandTreeNode(this, "bind"));
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/UnbindSlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/UnbindSlotCommandTreeNode.java
new file mode 100644
index 00000000..c41dd5af
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/UnbindSlotCommandTreeNode.java
@@ -0,0 +1,44 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.slot;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.skill.binding.BoundSkillInfo;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class UnbindSlotCommandTreeNode extends CommandTreeNode {
+
+ public UnbindSlotCommandTreeNode(CommandTreeNode parent, String id) {
+ super(parent, id);
+ addArgument(Argument.PLAYER);
+ addArgument(Argument.AMOUNT_INT);
+ }
+
+ @Override
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ if (args.length < 5)
+ return CommandResult.THROW_USAGE;
+ Player player = Bukkit.getPlayer(args[3]);
+ if (player == null) {
+ sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
+ return CommandResult.FAILURE;
+ }
+ PlayerData playerData = PlayerData.get(player);
+ int slot;
+ try {
+ slot = Integer.parseInt(args[4]);
+ } catch (NumberFormatException e) {
+ sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
+ return CommandResult.FAILURE;
+ }
+
+ final BoundSkillInfo found = playerData.unbindSkill(slot);
+ return explorer.success((found != null ?
+ "Skill " + ChatColor.GOLD + found.getClassSkill().getSkill().getName() + ChatColor.YELLOW + " was taken off the slot " + ChatColor.GOLD + slot :
+ "Could not find skill at slot " + ChatColor.GOLD + slot));
+ }
+}
\ No newline at end of file
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/UnlockSlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/UnlockSlotCommandTreeNode.java
new file mode 100644
index 00000000..eb91cb90
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/slot/UnlockSlotCommandTreeNode.java
@@ -0,0 +1,51 @@
+package net.Indyuce.mmocore.command.builtin.mmocore.slot;
+
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
+import net.Indyuce.mmocore.skill.binding.SkillSlot;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class UnlockSlotCommandTreeNode extends CommandTreeNode {
+ private final Argument argPlayer;
+ private final Argument argIndex;
+
+ public UnlockSlotCommandTreeNode(CommandTreeNode parent, String id) {
+ super(parent, id);
+
+ argPlayer = addArgument(Argument.PLAYER);
+ argIndex = addArgument(Arguments.INDEX);
+ }
+
+ @Override
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
+ final Player player = explorer.parse(argPlayer);
+ final PlayerData playerData = PlayerData.get(player);
+ final int slot = explorer.parse(argIndex);
+
+ if (slot <= 0) {
+ return explorer.fail("The slot can't be negative.");
+ }
+ SkillSlot skillSlot = playerData.getProfess().getSkillSlot(slot);
+ if (skillSlot == null) {
+ return explorer.fail("Skill slot with index " + slot + " was not found for player " + player.getName() + " with class " + playerData.getProfess().getId());
+ }
+
+ if (skillSlot.isUnlockedByDefault()) {
+ sender.sendMessage(ChatColor.RED + "You can't lock a skill that is unlocked by default.");
+ return CommandResult.FAILURE;
+ }
+
+ if (playerData.hasUnlocked(skillSlot)) {
+ return explorer.fail("Skill slot " + skillSlot.getName() + " is already unlocked" + " for " + player.getName());
+ }
+
+ playerData.unlock(skillSlot);
+ return explorer.success("Skill slot &6" + skillSlot.getName() + "&e is now unlocked for &6" + player.getName());
+ }
+}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/ItemCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/ItemCommandTreeNode.java
similarity index 73%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/ItemCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/ItemCommandTreeNode.java
index 5ca4d20a..df38d56e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/ItemCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/ItemCommandTreeNode.java
@@ -1,9 +1,11 @@
-package net.Indyuce.mmocore.command.rpg.waypoint;
+package net.Indyuce.mmocore.command.builtin.mmocore.waypoint;
import io.lumine.mythic.lib.api.util.SmartGive;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.command.Arguments;
import net.Indyuce.mmocore.util.item.WaypointBookBuilder;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -13,12 +15,12 @@ public class ItemCommandTreeNode extends CommandTreeNode {
public ItemCommandTreeNode(CommandTreeNode parent) {
super(parent, "item");
- addParameter(new Parameter("", (explorer, list) -> MMOCore.plugin.waypointManager.getAll().forEach(way -> list.add(way.getId()))));
- addParameter(Parameter.PLAYER);
+ addArgument(Arguments.WAYPOINT);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/LockCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/LockCommandTreeNode.java
similarity index 63%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/LockCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/LockCommandTreeNode.java
index 2f8e82b4..c6fa08c8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/LockCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/LockCommandTreeNode.java
@@ -1,27 +1,29 @@
-package net.Indyuce.mmocore.command.rpg.waypoint;
+package net.Indyuce.mmocore.command.builtin.mmocore.waypoint;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
+import net.Indyuce.mmocore.command.Arguments;
import net.Indyuce.mmocore.waypoint.Waypoint;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
public class LockCommandTreeNode extends CommandTreeNode {
public LockCommandTreeNode(CommandTreeNode parent) {
super(parent, "lock");
- addParameter(new Parameter("", (explorer, list) -> MMOCore.plugin.waypointManager.getAll().forEach(way -> list.add(way.getId()))));
- addParameter(Parameter.PLAYER);
+ addArgument(Arguments.WAYPOINT);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public @NotNull CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
@@ -43,9 +45,7 @@ public class LockCommandTreeNode extends CommandTreeNode {
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;
+ return explorer.success(ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " successfully locked " + ChatColor.GOLD + waypoint.getId());
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/OpenCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/OpenCommandTreeNode.java
similarity index 67%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/OpenCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/OpenCommandTreeNode.java
index 8d732c21..105bee9a 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/OpenCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/OpenCommandTreeNode.java
@@ -1,7 +1,8 @@
-package net.Indyuce.mmocore.command.rpg.waypoint;
+package net.Indyuce.mmocore.command.builtin.mmocore.waypoint;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.InventoryManager;
import org.bukkit.Bukkit;
@@ -13,11 +14,11 @@ public class OpenCommandTreeNode extends CommandTreeNode {
public OpenCommandTreeNode(CommandTreeNode parent) {
super(parent, "open");
- addParameter(Parameter.PLAYER);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/TeleportCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/TeleportCommandTreeNode.java
similarity index 71%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/TeleportCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/TeleportCommandTreeNode.java
index 1b6c8126..3ed8f0b9 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/TeleportCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/TeleportCommandTreeNode.java
@@ -1,8 +1,10 @@
-package net.Indyuce.mmocore.command.rpg.waypoint;
+package net.Indyuce.mmocore.command.builtin.mmocore.waypoint;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.command.Arguments;
import net.Indyuce.mmocore.waypoint.Waypoint;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -13,12 +15,12 @@ public class TeleportCommandTreeNode extends CommandTreeNode {
public TeleportCommandTreeNode(CommandTreeNode parent) {
super(parent, "teleport");
- addParameter(new Parameter("", (explorer, list) -> MMOCore.plugin.waypointManager.getAll().forEach(way -> list.add(way.getId()))));
- addParameter(Parameter.PLAYER);
+ addArgument(Arguments.WAYPOINT);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/UnlockCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/UnlockCommandTreeNode.java
similarity index 70%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/UnlockCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/UnlockCommandTreeNode.java
index 6da47970..3d6e5161 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/UnlockCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/UnlockCommandTreeNode.java
@@ -1,9 +1,11 @@
-package net.Indyuce.mmocore.command.rpg.waypoint;
+package net.Indyuce.mmocore.command.builtin.mmocore.waypoint;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import io.lumine.mythic.lib.command.api.Parameter;
+import io.lumine.mythic.lib.command.CommandTreeExplorer;
+import io.lumine.mythic.lib.command.CommandTreeNode;
+import io.lumine.mythic.lib.command.argument.Argument;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.command.Arguments;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -12,12 +14,12 @@ public class UnlockCommandTreeNode extends CommandTreeNode {
public UnlockCommandTreeNode(CommandTreeNode parent) {
super(parent, "unlock");
- addParameter(new Parameter("", (explorer, list) -> MMOCore.plugin.waypointManager.getAll().forEach(way -> list.add(way.getId()))));
- addParameter(Parameter.PLAYER);
+ addArgument(Arguments.WAYPOINT);
+ addArgument(Argument.PLAYER);
}
@Override
- public CommandResult execute(CommandSender sender, String[] args) {
+ public CommandResult execute(CommandTreeExplorer explorer, CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/WaypointsCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/WaypointsCommandTreeNode.java
similarity index 58%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/WaypointsCommandTreeNode.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/WaypointsCommandTreeNode.java
index 111c4431..65a6422a 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/waypoint/WaypointsCommandTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/waypoint/WaypointsCommandTreeNode.java
@@ -1,7 +1,6 @@
-package net.Indyuce.mmocore.command.rpg.waypoint;
+package net.Indyuce.mmocore.command.builtin.mmocore.waypoint;
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import org.bukkit.command.CommandSender;
+import io.lumine.mythic.lib.command.CommandTreeNode;
public class WaypointsCommandTreeNode extends CommandTreeNode {
public WaypointsCommandTreeNode(CommandTreeNode parent) {
@@ -13,9 +12,4 @@ public class WaypointsCommandTreeNode extends CommandTreeNode {
addChild(new ItemCommandTreeNode(this));
addChild(new LockCommandTreeNode(this));
}
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/CastCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/CastCommandTreeNode.java
deleted file mode 100644
index 1a60a3ef..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/CastCommandTreeNode.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.Indyuce.mmocore.command.rpg;
-
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.cast.FirstCommandTreeNode;
-import net.Indyuce.mmocore.command.rpg.cast.SpecificCommandTreeNode;
-import org.bukkit.command.CommandSender;
-import org.jetbrains.annotations.NotNull;
-
-public class CastCommandTreeNode extends CommandTreeNode {
- public CastCommandTreeNode(CommandTreeNode parent) {
- super(parent, "cast");
-
- addChild(new FirstCommandTreeNode(this));
- addChild(new SpecificCommandTreeNode(this));
- }
-
- @Override
- public @NotNull CommandResult execute(CommandSender commandSender, String[] strings) {
- return CommandResult.THROW_USAGE;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java
deleted file mode 100644
index a1148233..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AdminCommandTreeNode.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-import io.lumine.mythic.lib.command.api.CommandTreeNode;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
-import org.bukkit.command.CommandSender;
-
-public class AdminCommandTreeNode extends CommandTreeNode {
- public AdminCommandTreeNode(CommandTreeNode parent) {
- super(parent, "admin");
-
- addChild(new HideActionBarCommandTreeNode(this));
- addChild(new NoCooldownCommandTreeNode(this));
- addChild(new ResetCommandTreeNode(this));
- addChild(new InfoCommandTreeNode(this));
- addChild(new ClassCommandTreeNode(this));
- addChild(new ForceClassCommandTreeNode(this));
- addChild(new ExportDataTreeNode(this));
-
- addChild(new ExperienceCommandTreeNode(this));
- addChild(new LevelCommandTreeNode(this));
- addChild(new AttributeCommandTreeNode(this));
- addChild(new SkillCommandTreeNode(this));
- addChild(new SaveDataTreeNode(this));
- addChild(new SlotCommandTreeNode(this));
- addChild(new PointsCommandTreeNode("skill", this, PlayerData::setSkillPoints, PlayerData::giveSkillPoints, PlayerData::getSkillPoints));
- addChild(new PointsCommandTreeNode("class", this, PlayerData::setClassPoints, PlayerData::giveClassPoints, PlayerData::getClassPoints));
- addChild(new PointsCommandTreeNode("attribute", this, PlayerData::setAttributePoints, PlayerData::giveAttributePoints, PlayerData::getAttributePoints));
- 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::getSkillTreePoints));
- for (PlayerResource res : PlayerResource.values())
- addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AttributeCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AttributeCommandTreeNode.java
deleted file mode 100644
index 65088036..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/AttributeCommandTreeNode.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.api.player.attribute.PlayerAttribute;
-import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-public class AttributeCommandTreeNode extends CommandTreeNode {
- public AttributeCommandTreeNode(CommandTreeNode parent) {
- super(parent, "attribute");
-
- addChild(new ActionCommandTreeNode(this, "give", false));
- addChild(new ActionCommandTreeNode(this, "take", true));
- }
-
- public class ActionCommandTreeNode extends CommandTreeNode {
- private final int c;
-
- public ActionCommandTreeNode(CommandTreeNode parent, String type, boolean take) {
- super(parent, type);
-
- this.c = take ? -1 : 1;
-
- addParameter(Parameter.PLAYER);
- addParameter(new Parameter("",
- (explorer, list) -> MMOCore.plugin.attributeManager.getAll().forEach(attribute -> list.add(attribute.getId()))));
- addParameter(Parameter.AMOUNT);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 6)
- return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- String format = args[4].toLowerCase().replace("_", "-");
- if (!MMOCore.plugin.attributeManager.has(format)) {
- sender.sendMessage(ChatColor.RED + "Could not find the attribute called " + args[4] + ".");
- return CommandResult.FAILURE;
- }
- PlayerAttribute attribute = MMOCore.plugin.attributeManager.get(format);
-
- int amount;
- try {
- amount = Integer.parseInt(args[5]);
- } catch (Exception e) {
- sender.sendMessage(ChatColor.RED + args[5] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
-
- PlayerAttributes.AttributeInstance instance = PlayerData.get(player).getAttributes().getInstance(attribute);
- instance.setBase(Math.min(attribute.getMax(), instance.getBase() + c * amount));
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.ATTRIBUTE, ChatColor.GOLD + player.getName() + ChatColor.YELLOW
- + " now has " + ChatColor.GOLD + instance.getBase() + ChatColor.YELLOW + " " + attribute.getName() + ".");
- return CommandResult.SUCCESS;
- }
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ClassCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ClassCommandTreeNode.java
deleted file mode 100644
index 2525b81d..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ClassCommandTreeNode.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.event.PlayerChangeClassEvent;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.api.player.profess.PlayerClass;
-import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
-import net.Indyuce.mmocore.player.Message;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-public class ClassCommandTreeNode extends CommandTreeNode {
- public ClassCommandTreeNode(CommandTreeNode parent) {
- super(parent, "class");
-
- addParameter(Parameter.PLAYER);
- addParameter(
- new Parameter("", (explorer, list) -> MMOCore.plugin.classManager.getAll().forEach(profess -> list.add(profess.getId()))));
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4)
- return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[2]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[2] + ".");
- return CommandResult.FAILURE;
- }
-
- String format = args[3].toUpperCase().replace("-", "_");
- if (!MMOCore.plugin.classManager.has(format)) {
- sender.sendMessage(ChatColor.RED + "Could not find class " + format + ".");
- return CommandResult.FAILURE;
- }
-
- PlayerClass profess = MMOCore.plugin.classManager.get(format);
- PlayerData data = PlayerData.get(player);
- if (data.getProfess().equals(profess))
- return CommandResult.SUCCESS;
-
- PlayerChangeClassEvent called = new PlayerChangeClassEvent(data, profess);
- Bukkit.getPluginManager().callEvent(called);
- if (called.isCancelled())
- return CommandResult.SUCCESS;
-
- (data.hasSavedClass(profess) ? data.getClassInfo(profess)
- : new SavedClassInformation(MMOCore.plugin.playerDataManager.getDefaultData())).load(profess, data);
- if (data.isOnline()) {
- Message.CLASS_SELECT.send(data, "class", profess.getName());
- }
-
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.CLASS,
- ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " is now a " + ChatColor.GOLD + profess.getName() + ChatColor.YELLOW + ".");
- return CommandResult.SUCCESS;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExperienceCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExperienceCommandTreeNode.java
deleted file mode 100644
index d20d3d11..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ExperienceCommandTreeNode.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-import io.lumine.mythic.lib.MythicLib;
-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.MMOCoreCommandTreeRoot;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
-import net.Indyuce.mmocore.experience.EXPSource;
-import net.Indyuce.mmocore.experience.PlayerProfessions;
-import net.Indyuce.mmocore.experience.Profession;
-import net.Indyuce.mmocore.util.TriConsumer;
-import org.apache.commons.lang.Validate;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.function.BiConsumer;
-
-public class ExperienceCommandTreeNode extends CommandTreeNode {
- public ExperienceCommandTreeNode(CommandTreeNode parent) {
- super(parent, "exp");
-
- addChild(new ActionCommandTreeNode(this, "set", PlayerData::setExperience, PlayerProfessions::setExperience));
- addChild(new ActionCommandTreeNode(this, "give", (data, value) -> data.giveExperience(value, EXPSource.COMMAND), (professions, profession,
- value) -> professions.giveExperience(profession, value, EXPSource.COMMAND)));
- addChild(new ActionCommandTreeNode(this, "take", (data, value) -> data.giveExperience(-value, EXPSource.COMMAND), (professions, profession,
- value) -> professions.giveExperience(profession, -value, EXPSource.COMMAND)));
- }
-
- public static class ActionCommandTreeNode extends CommandTreeNode {
- private final BiConsumer main;
- private final TriConsumer profession;
-
- public ActionCommandTreeNode(CommandTreeNode parent, String type, BiConsumer main,
- TriConsumer profession) {
- super(parent, type);
-
- this.main = main;
- this.profession = profession;
-
- addParameter(Parameter.PLAYER);
- addParameter(MMOCoreCommandTreeRoot.PROFESSION);
- addParameter(Parameter.AMOUNT);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 6)
- return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- long amount;
- try {
- amount = Long.parseLong(args[5]);
- Validate.isTrue(amount >= 0);
- } catch (RuntimeException exception) {
- sender.sendMessage(ChatColor.RED + args[5] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
-
- PlayerData data = PlayerData.get(player);
- if (args[4].equalsIgnoreCase("main")) {
- main.accept(data, amount);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.EXPERIENCE, ChatColor.GOLD + player.getName() + ChatColor.YELLOW
- + " now has " + ChatColor.GOLD + MythicLib.plugin.getMMOConfig().decimal.format(data.getExperience()) + ChatColor.YELLOW + " EXP.");
- return CommandResult.SUCCESS;
- }
-
- String format = args[4].toLowerCase().replace("_", "-");
- if (!MMOCore.plugin.professionManager.has(format)) {
- sender.sendMessage(ChatColor.RED + format + " is not a valid profession.");
- return CommandResult.FAILURE;
- }
-
- Profession profession = MMOCore.plugin.professionManager.get(format);
- this.profession.accept(data.getCollectionSkills(), profession, amount);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.EXPERIENCE,
- ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " now has " + ChatColor.GOLD
- + data.getCollectionSkills().getExperience(profession) + ChatColor.YELLOW + " EXP in " + profession.getName() + ".");
- return CommandResult.SUCCESS;
- }
- }
-
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ForceClassCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ForceClassCommandTreeNode.java
deleted file mode 100644
index c05c7981..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ForceClassCommandTreeNode.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.api.player.profess.PlayerClass;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-public class ForceClassCommandTreeNode extends CommandTreeNode {
- public ForceClassCommandTreeNode(CommandTreeNode parent) {
- super(parent, "force-class");
-
- addParameter(Parameter.PLAYER);
- addParameter(
- new Parameter("", (explorer, list) -> MMOCore.plugin.classManager.getAll().forEach(profess -> list.add(profess.getId()))));
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4)
- return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[2]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[2] + ".");
- return CommandResult.FAILURE;
- }
-
- String format = args[3].toUpperCase().replace("-", "_");
- if (!MMOCore.plugin.classManager.has(format)) {
- sender.sendMessage(ChatColor.RED + "Could not find class " + format + ".");
- return CommandResult.FAILURE;
- }
-
- PlayerClass profess = MMOCore.plugin.classManager.get(format);
-
- PlayerData data = PlayerData.get(player);
- data.setClass(profess);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.CLASS, ChatColor.GOLD + player.getName()
- + ChatColor.YELLOW + " is now a " + ChatColor.GOLD + profess.getName() + ChatColor.YELLOW + ".");
- return CommandResult.SUCCESS;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/LevelCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/LevelCommandTreeNode.java
deleted file mode 100644
index bb5177a3..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/LevelCommandTreeNode.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.MMOCoreCommandTreeRoot;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
-import net.Indyuce.mmocore.experience.EXPSource;
-import net.Indyuce.mmocore.experience.PlayerProfessions;
-import net.Indyuce.mmocore.experience.Profession;
-import net.Indyuce.mmocore.util.TriConsumer;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.function.BiConsumer;
-
-public class LevelCommandTreeNode extends CommandTreeNode {
- public LevelCommandTreeNode(CommandTreeNode parent) {
- super(parent, "level");
-
- addChild(new ActionCommandTreeNode(this, "set", PlayerData::setLevel, PlayerProfessions::setLevel));
- addChild(new ActionCommandTreeNode(this, "give", (data, value) -> data.giveLevels(value, EXPSource.COMMAND), (professions, profession, value) -> professions.giveLevels(profession, value, EXPSource.COMMAND)));
- addChild(new ActionCommandTreeNode(this, "take", PlayerData::takeLevels, PlayerProfessions::takeLevels));
- }
-
- public static class ActionCommandTreeNode extends CommandTreeNode {
- private final BiConsumer main;
- private final TriConsumer profession;
-
- public ActionCommandTreeNode(CommandTreeNode parent, String type, BiConsumer main,
- TriConsumer profession) {
- super(parent, type);
-
- this.main = main;
- this.profession = profession;
-
- addParameter(Parameter.PLAYER);
- addParameter(MMOCoreCommandTreeRoot.PROFESSION);
- addParameter(Parameter.AMOUNT);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 6)
- return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- int amount;
- try {
- amount = Integer.parseInt(args[5]);
- } catch (NumberFormatException exception) {
- sender.sendMessage(ChatColor.RED + args[5] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
-
- PlayerData data = PlayerData.get(player);
- if (args[4].equalsIgnoreCase("main")) {
- main.accept(data, amount);
-
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.LEVEL, ChatColor.GOLD + player.getName()
- + ChatColor.YELLOW + " is now Lvl " + ChatColor.GOLD + data.getLevel() + ChatColor.YELLOW + ".");
- return CommandResult.SUCCESS;
- }
-
- String format = args[4].toLowerCase().replace("_", "-");
- if (!MMOCore.plugin.professionManager.has(format)) {
- sender.sendMessage(ChatColor.RED + format + " is not a valid profession.");
- return CommandResult.FAILURE;
- }
-
- Profession profession = MMOCore.plugin.professionManager.get(format);
- this.profession.accept(data.getCollectionSkills(), profession, amount);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.LEVEL,
- ChatColor.GOLD + player.getName() + ChatColor.YELLOW + " is now Lvl " + ChatColor.GOLD
- + data.getCollectionSkills().getLevel(profession) + ChatColor.YELLOW + " in " + profession.getName() + ".");
- return CommandResult.SUCCESS;
- }
- }
-
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ResetCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ResetCommandTreeNode.java
deleted file mode 100644
index bec1f7f0..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/ResetCommandTreeNode.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.api.player.attribute.PlayerAttribute;
-import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
-import net.Indyuce.mmocore.experience.Profession;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.HashSet;
-
-public class ResetCommandTreeNode extends CommandTreeNode {
- public ResetCommandTreeNode(CommandTreeNode parent) {
- super(parent, "reset");
-
- addChild(new ResetClassesCommandTreeNode(this));
- addChild(new ResetLevelsCommandTreeNode(this));
- addChild(new ResetSkillsCommandTreeNode(this));
- addChild(new ResetQuestsCommandTreeNode(this));
- addChild(new ResetAttributesCommandTreeNode(this));
- addChild(new ResetWaypointsCommandTreeNode(this));
- addChild(new ResetSkillTreesCommandTreeNode(this));
- addChild(new ResetAllCommandTreeNode(this));
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
-
- public static class ResetAllCommandTreeNode extends CommandTreeNode {
- public ResetAllCommandTreeNode(CommandTreeNode parent) {
- super(parent, "all");
-
- addParameter(Parameter.PLAYER);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- final boolean givePoints = args.length > 4 && args[4].equalsIgnoreCase("-reallocate");
-
- PlayerData data = PlayerData.get(player);
- ResetClassesCommandTreeNode.resetClasses(data);
- ResetLevelsCommandTreeNode.resetLevels(data);
- ResetSkillsCommandTreeNode.resetSkills(data);
- ResetQuestsCommandTreeNode.resetQuests(data);
- ResetAttributesCommandTreeNode.resetAttributes(data, givePoints);
- ResetWaypointsCommandTreeNode.resetWaypoints(data);
- ResetSkillTreesCommandTreeNode.resetSkillTrees(data);
- // Reset times-claimed not being properly emptied otherwise
- data.getItemClaims().clear();
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s data was successfully reset.");
- return CommandResult.SUCCESS;
- }
- }
-}
-
-class ResetWaypointsCommandTreeNode extends CommandTreeNode {
- public ResetWaypointsCommandTreeNode(CommandTreeNode parent) {
- super(parent, "waypoints");
-
- addParameter(Parameter.PLAYER);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- resetWaypoints(PlayerData.get(player));
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s waypoints were successfully reset.");
- return CommandResult.SUCCESS;
- }
-
- static void resetWaypoints(@NotNull PlayerData playerData) {
- playerData.getWaypoints().clear();
- }
-}
-
-class ResetQuestsCommandTreeNode extends CommandTreeNode {
- public ResetQuestsCommandTreeNode(CommandTreeNode parent) {
- super(parent, "quests");
-
- addParameter(Parameter.PLAYER);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- resetQuests(PlayerData.get(player));
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s quests were successfully reset.");
- return CommandResult.SUCCESS;
- }
-
- static void resetQuests(@NotNull PlayerData data) {
- data.getQuestData().resetFinishedQuests();
- data.getQuestData().start(null);
- }
-}
-
-class ResetSkillsCommandTreeNode extends CommandTreeNode {
- public ResetSkillsCommandTreeNode(CommandTreeNode parent) {
- super(parent, "skills");
-
- addParameter(Parameter.PLAYER);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- resetSkills(PlayerData.get(player));
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s skill data was successfully reset.");
- return CommandResult.SUCCESS;
- }
-
- static void resetSkills(@NotNull PlayerData data) {
- data.mapSkillLevels().forEach((skill, ignored) -> data.resetSkillLevel(skill));
- while (data.hasSkillBound(0)) data.unbindSkill(0);
- data.setUnlockedItems(new HashSet<>()); // TODO class-specific unlockables etc.
- }
-}
-
-class ResetSkillTreesCommandTreeNode extends CommandTreeNode {
- public ResetSkillTreesCommandTreeNode(CommandTreeNode parent) {
- super(parent, "skill-trees");
-
- addParameter(Parameter.PLAYER);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- resetSkillTrees(PlayerData.get(player));
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s skill-tree data was successfully reset.");
- return CommandResult.SUCCESS;
- }
-
- // TODO option to reallocate skill tree points instead of not giving any back
- static void resetSkillTrees(@NotNull PlayerData data) {
- data.resetSkillTrees();
- }
-}
-
-class ResetAttributesCommandTreeNode extends CommandTreeNode {
- public ResetAttributesCommandTreeNode(CommandTreeNode parent) {
- super(parent, "attributes");
-
- addParameter(Parameter.PLAYER);
- addParameter(new Parameter("(-reallocate)", (explore, list) -> list.add("-reallocate")));
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- final boolean givePoints = args.length > 4 && args[4].equalsIgnoreCase("-reallocate");
- resetAttributes(PlayerData.get(player), givePoints);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s attributes were successfully reset.");
- return CommandResult.SUCCESS;
- }
-
- static void resetAttributes(@NotNull PlayerData data, boolean givePoints) {
-
- // Give back attribute points
- if (givePoints) {
-
- int points = 0;
- for (PlayerAttributes.AttributeInstance ins : data.getAttributes().getInstances()) {
- points += ins.getBase();
- ins.setBase(0);
- }
-
- data.giveAttributePoints(points);
- return;
- }
-
- for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll()) {
- attribute.resetAdvancement(data, true);
- data.getAttributes().getInstance(attribute).setBase(0);
- }
- }
-}
-
-class ResetLevelsCommandTreeNode extends CommandTreeNode {
- public ResetLevelsCommandTreeNode(CommandTreeNode parent) {
- super(parent, "levels");
-
- addParameter(Parameter.PLAYER);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- resetLevels(PlayerData.get(player));
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s levels were successfully reset.");
- return CommandResult.SUCCESS;
- }
-
- static void resetLevels(@NotNull PlayerData data) {
-
- // Class
- data.setLevel(MMOCore.plugin.playerDataManager.getDefaultData().getLevel());
- data.setExperience(0);
- data.getProfess().resetAdvancement(data, true);
-
- // Professions
- for (Profession profession : MMOCore.plugin.professionManager.getAll()) {
- data.getCollectionSkills().setExperience(profession, 0);
- data.getCollectionSkills().setLevel(profession, 0);
- profession.resetAdvancement(data, true);
- }
- }
-}
-
-class ResetClassesCommandTreeNode extends CommandTreeNode {
- public ResetClassesCommandTreeNode(CommandTreeNode parent) {
- super(parent, "classes");
-
- addParameter(Parameter.PLAYER);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 4) return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- resetClasses(PlayerData.get(player));
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s classes were successfully reset.");
- return CommandResult.SUCCESS;
- }
-
- static void resetClasses(@NotNull PlayerData data) {
- MMOCore.plugin.classManager.getAll().forEach(data::unloadClassInfo);
- MMOCore.plugin.playerDataManager.getDefaultData().apply(data);
- data.setClass(MMOCore.plugin.classManager.getDefaultClass());
- }
-}
\ No newline at end of file
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillCommandTreeNode.java
deleted file mode 100644
index 17f70daa..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillCommandTreeNode.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.api.CommandVerbose;
-import net.Indyuce.mmocore.skill.ClassSkill;
-import net.Indyuce.mmocore.skill.RegisteredSkill;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.function.BiFunction;
-
-
-public class SkillCommandTreeNode extends CommandTreeNode {
- public SkillCommandTreeNode(CommandTreeNode parent) {
- super(parent, "skill");
-
- addChild(new LockSkillCommandTreeNode(this, "lock", true));
- addChild(new LockSkillCommandTreeNode(this, "unlock", false));
- addChild(new LevelCommandTreeNode(this, "give", (old, amount) -> old + amount));
- addChild(new LevelCommandTreeNode(this, "set", (old, amount) -> amount));
- }
-
- public class LevelCommandTreeNode extends CommandTreeNode {
- private final BiFunction change;
-
- public LevelCommandTreeNode(CommandTreeNode parent, String type, BiFunction change) {
- super(parent, type);
-
- this.change = change;
- addParameter(Parameter.PLAYER);
- addParameter(new Parameter("",
- (explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase()))));
- addParameter(Parameter.AMOUNT);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 6)
- return CommandResult.THROW_USAGE;
-
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
- PlayerData playerData = PlayerData.get(player);
-
- RegisteredSkill skill = MMOCore.plugin.skillManager.getSkill(args[4]);
- if (skill == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the skill called " + args[4] + ".");
- return CommandResult.FAILURE;
- }
-
-
- ClassSkill classSkill = null;
- for (ClassSkill var : playerData.getProfess().getSkills()) {
- if (var.getSkill().equals(skill))
- classSkill = var;
- }
-
- if (classSkill == null || classSkill.getUnlockLevel() > playerData.getLevel()) {
- sender.sendMessage(ChatColor.RED + skill.getName() + " is not unlockable for " + player.getName() + ".");
- return CommandResult.FAILURE;
- }
-
- int amount;
- try {
- amount = Integer.parseInt(args[5]);
- } catch (Exception e) {
- sender.sendMessage(ChatColor.RED + args[5] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
- int value = change.apply(playerData.getSkillLevel(skill), amount);
- playerData.setSkillLevel(skill, value);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + player.getName() + ChatColor.YELLOW
- + " is now level " + ChatColor.GOLD + value + ChatColor.YELLOW + " for " + skill.getName() + ".");
- return CommandResult.SUCCESS;
- }
- }
-
- public class LockSkillCommandTreeNode extends CommandTreeNode {
- private final boolean lock;
-
- public LockSkillCommandTreeNode(CommandTreeNode parent, String id, boolean lock) {
- super(parent, id);
- this.lock = lock;
- addParameter(Parameter.PLAYER);
- addParameter(new Parameter("",
- (explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase()))));
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 5)
- return CommandResult.THROW_USAGE;
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
- PlayerData playerData = PlayerData.get(player);
-
- ClassSkill skill = playerData.getProfess().getSkill(args[4]);
- if (skill == null) {
- sender.sendMessage(ChatColor.RED + "Class doesn't have a skill called " + args[4] + ".");
- return CommandResult.FAILURE;
- }
- if (lock) {
- if (!playerData.hasUnlocked(skill)) {
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "Skill " + skill.getSkill().getName() + " already locked for " + player.getName());
- return CommandResult.SUCCESS;
- }
- playerData.lock(skill);
-
- } else {
- if (playerData.hasUnlocked(skill)) {
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "Skill " + skill.getSkill().getName() + " already unlocked for " + player.getName());
- return CommandResult.SUCCESS;
- }
- playerData.unlock(skill);
- }
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "Skill " + ChatColor.GOLD + skill.getSkill().getName() + ChatColor.YELLOW + " now " + (lock ? "locked" : "unlocked") + " for " + ChatColor.GOLD + player.getName());
- return CommandResult.SUCCESS;
- }
- }
-
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillTreePointsCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillTreePointsCommandTreeNode.java
deleted file mode 100644
index 0cd195d0..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillTreePointsCommandTreeNode.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.api.CommandVerbose;
-import net.Indyuce.mmocore.util.TriConsumer;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.BiFunction;
-
-public class SkillTreePointsCommandTreeNode extends CommandTreeNode {
- BiFunction get;
-
- public SkillTreePointsCommandTreeNode(CommandTreeNode parent, TriConsumer set,
- TriConsumer give, BiFunction get) {
- super(parent, "skill-tree-points");
- addChild(new ActionCommandTreeNode(this, "give", give));
- addChild(new ActionCommandTreeNode(this, "set", set));
- this.get = get;
- }
-
- @Override
- public CommandResult execute(CommandSender commandSender, String[] strings) {
- return CommandResult.THROW_USAGE;
- }
-
- public class ActionCommandTreeNode extends CommandTreeNode {
- private final TriConsumer action;
-
-
- public ActionCommandTreeNode(CommandTreeNode parent, String id, TriConsumer action) {
- super(parent, id);
- this.action = action;
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
- addParameter(new Parameter("", ((explorer, list) -> {
- MMOCore.plugin.skillTreeManager.getAll().forEach(tree -> list.add(tree.getId()));
- list.add("global");
- })));
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 6)
- return CommandResult.THROW_USAGE;
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
-
- int amount;
- try {
- amount = Integer.parseInt(args[4]);
- } catch (Exception e) {
- sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
- List list = new ArrayList();
- MMOCore.plugin.skillTreeManager.getAll().forEach(tree -> list.add(tree.getId()));
- list.add("global");
-
- String id = args[5];
-
- if (!list.contains(id)) {
- sender.sendMessage("Could not find the type of points " + id + ".");
- return CommandResult.FAILURE;
- }
-
- PlayerData data = PlayerData.get(player);
- action.accept(data, amount, args[5]);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL_TREE_POINTS, ChatColor.GOLD + player.getName()
- + ChatColor.YELLOW + " now has " + ChatColor.GOLD + get.apply(data, id) + ChatColor.YELLOW + " " + id + " skill tree points.");
-
- return CommandResult.SUCCESS;
- }
- }
-
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java
deleted file mode 100644
index 06c82915..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.admin;
-
-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.api.CommandVerbose;
-import net.Indyuce.mmocore.skill.ClassSkill;
-import net.Indyuce.mmocore.skill.binding.BoundSkillInfo;
-import net.Indyuce.mmocore.skill.binding.SkillSlot;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-
-public class SlotCommandTreeNode extends CommandTreeNode {
- public SlotCommandTreeNode(CommandTreeNode parent) {
- super(parent, "slot");
- addChild(new LockSlotCommandTreeNode(this, "lock", true));
- addChild(new LockSlotCommandTreeNode(this, "unlock", false));
- addChild(new UnbindSlotCommandTreeNode(this, "unbind"));
- addChild(new BindSlotCommandTreeNode(this, "bind"));
- }
-
- public class LockSlotCommandTreeNode extends CommandTreeNode {
- private final boolean lock;
-
- public LockSlotCommandTreeNode(CommandTreeNode parent, String id, boolean lock) {
- super(parent, id);
- this.lock = lock;
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 5)
- return CommandResult.THROW_USAGE;
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
- PlayerData playerData = PlayerData.get(player);
- int slot;
- try {
- slot = Integer.parseInt(args[4]);
- } catch (NumberFormatException e) {
- sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
- if (slot <= 0) {
- sender.sendMessage(ChatColor.RED + "The slot can't be negative.");
- return CommandResult.FAILURE;
- }
- SkillSlot skillSlot = playerData.getProfess().getSkillSlot(slot);
- if (skillSlot == null) {
- sender.sendMessage(ChatColor.RED + "Skill slot with index " + slot + " was not found for player " + player.getName() + " with class " + playerData.getProfess().getId());
- return CommandResult.FAILURE;
- }
-
- if (skillSlot.isUnlockedByDefault()) {
- sender.sendMessage(ChatColor.RED + "You can't lock a skill that is unlocked by default.");
- return CommandResult.FAILURE;
- }
- if (lock) {
- if (!playerData.hasUnlocked(skillSlot)) {
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "The skill slot " + skillSlot.getName() + " is already locked for " + player.getName());
- return CommandResult.SUCCESS;
- }
- playerData.lock(skillSlot);
-
- } else {
- if (playerData.hasUnlocked(skillSlot)) {
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "The skill slot " + skillSlot.getName() + " is already unlocked" + " for " + player.getName());
- return CommandResult.SUCCESS;
- }
- playerData.unlock(skillSlot);
- }
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "The skill slot " + skillSlot.getName() + " is now " + (lock ? "locked" : "unlocked" + " for " + player.getName()));
- return CommandResult.SUCCESS;
- }
- }
-
-
- public class BindSlotCommandTreeNode extends CommandTreeNode {
-
- public BindSlotCommandTreeNode(CommandTreeNode parent, String id) {
- super(parent, id);
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
- addParameter(new Parameter("",
- (explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase()))));
-
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 6)
- return CommandResult.THROW_USAGE;
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
- PlayerData playerData = PlayerData.get(player);
- int slot;
- try {
- slot = Integer.parseInt(args[4]);
- } catch (NumberFormatException e) {
- sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
- ClassSkill skill = playerData.getProfess().getSkill(args[5]);
- if (skill == null) {
- sender.sendMessage(ChatColor.RED + "The player's class doesn't have a skill called " + args[5] + ".");
- return CommandResult.FAILURE;
- }
- playerData.bindSkill(slot, skill);
-
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "Skill " + ChatColor.GOLD + skill.getSkill().getHandler().getId() + ChatColor.YELLOW + " now bound to slot " + ChatColor.GOLD + slot);
- return CommandResult.SUCCESS;
- }
- }
-
- public class UnbindSlotCommandTreeNode extends CommandTreeNode {
-
- public UnbindSlotCommandTreeNode(CommandTreeNode parent, String id) {
- super(parent, id);
- addParameter(Parameter.PLAYER);
- addParameter(Parameter.AMOUNT);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 5)
- return CommandResult.THROW_USAGE;
- Player player = Bukkit.getPlayer(args[3]);
- if (player == null) {
- sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
- return CommandResult.FAILURE;
- }
- PlayerData playerData = PlayerData.get(player);
- int slot;
- try {
- slot = Integer.parseInt(args[4]);
- } catch (NumberFormatException e) {
- sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
- final BoundSkillInfo found = playerData.unbindSkill(slot);
- CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + (found != null ?
- "Skill " + ChatColor.GOLD + found.getClassSkill().getSkill().getName() + ChatColor.YELLOW + " was taken off the slot " + ChatColor.GOLD + slot :
- "Could not find skill at slot " + ChatColor.GOLD + slot));
- return CommandResult.SUCCESS;
- }
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- return CommandResult.THROW_USAGE;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/CreateCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/CreateCommandTreeNode.java
deleted file mode 100644
index a814250b..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/booster/CreateCommandTreeNode.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package net.Indyuce.mmocore.command.rpg.booster;
-
-import io.lumine.mythic.lib.MythicLib;
-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.command.MMOCoreCommandTreeRoot;
-import net.Indyuce.mmocore.experience.Booster;
-import net.Indyuce.mmocore.player.Message;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-
-import java.util.Arrays;
-
-public class CreateCommandTreeNode extends CommandTreeNode {
- public CreateCommandTreeNode(CommandTreeNode parent) {
- super(parent, "create");
-
- addParameter(MMOCoreCommandTreeRoot.PROFESSION);
- addParameter(new Parameter("",
- (explorer, list) -> list.addAll(Arrays.asList("0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1"))));
- addParameter(new Parameter("", (explorer, list) -> list.addAll(Arrays.asList("60", "300", "3600", "43200", "86400"))));
- addParameter(Parameter.PLAYER_OPTIONAL);
- }
-
- @Override
- public CommandResult execute(CommandSender sender, String[] args) {
- if (args.length < 5)
- return CommandResult.THROW_USAGE;
-
- double extra;
- try {
- extra = Double.parseDouble(args[3]);
- } catch (NumberFormatException exception) {
- sender.sendMessage(ChatColor.RED + args[3] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
-
- long length;
- try {
- length = Long.parseLong(args[4]);
- } catch (NumberFormatException exception) {
- sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
- return CommandResult.FAILURE;
- }
-
- var multFormatted = MythicLib.plugin.getMMOConfig().decimal.format(1 + extra);
- if (args[2].equalsIgnoreCase("main")) {
- MMOCore.plugin.boosterManager.register(new Booster(args.length > 5 ? args[5] : null, extra, length));
- Message.NEW_EXP_BOOSTER_MAIN.send(Bukkit.getOnlinePlayers(), "multiplier", multFormatted);
- return CommandResult.SUCCESS;
- }
-
- String format = args[2].toLowerCase().replace("_", "-");
- if (!MMOCore.plugin.professionManager.has(format)) {
- sender.sendMessage(ChatColor.RED + format + " is not a valid profession.");
- return CommandResult.FAILURE;
- }
-
- var profession = MMOCore.plugin.professionManager.get(format);
- MMOCore.plugin.boosterManager.register(new Booster(args.length > 5 ? args[5] : null, profession, extra, length));
- Message.NEW_EXP_BOOSTER_PROFESSION.send(Bukkit.getOnlinePlayers(), "multiplier", multFormatted, "profession", profession.getName());
- return CommandResult.SUCCESS;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/mythicmobs/load/MythicSkillTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/mythicmobs/load/MythicSkillTrigger.java
index 90b59722..fd756ebc 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/mythicmobs/load/MythicSkillTrigger.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/mythicmobs/load/MythicSkillTrigger.java
@@ -10,9 +10,9 @@ import io.lumine.mythic.bukkit.MythicBukkit;
import io.lumine.mythic.core.skills.SkillMetadataImpl;
import io.lumine.mythic.core.skills.SkillTriggers;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
-import org.apache.commons.lang.Validate;
import java.util.HashSet;
import java.util.Optional;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java
index 3a8c6c72..fb755002 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java
@@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.util.AltChar;
import io.lumine.mythic.lib.manager.StatManager;
+import io.lumine.mythic.lib.util.lang3.Validate;
import io.lumine.mythic.lib.version.Attributes;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.Indyuce.mmocore.MMOCore;
@@ -17,7 +18,6 @@ import net.Indyuce.mmocore.skill.CastableSkill;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skill.binding.BoundSkillInfo;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
@@ -76,9 +76,7 @@ public class RPGPlaceholders extends PlaceholderExpansion {
String id = identifier.substring(12);
RegisteredSkill skill = MMOCore.plugin.skillManager.getSkillOrThrow(id);
return String.valueOf(playerData.getSkillLevel(skill));
- }
-
- else if (identifier.startsWith("skill_tree_points_")) {
+ } else if (identifier.startsWith("skill_tree_points_")) {
int length = "skill_tree_points_".length();
String id = identifier.substring(length);
return String.valueOf(PlayerData.get(player).getSkillTreePoints(id));
@@ -106,7 +104,8 @@ public class RPGPlaceholders extends PlaceholderExpansion {
final String parameterId = ids[0];
final String skillId = ids[1];
final RegisteredSkill skill = Objects.requireNonNull(MMOCore.plugin.skillManager.getSkill(skillId), "Could not find skill with ID '" + skillId + "'");
- final CastableSkill castable = playerData.getProfess().getSkill(skill).toCastable(playerData);
+ final ClassSkill classSkill = Objects.requireNonNull(playerData.getProfess().getSkill(skill), "Class " + playerData.getProfess().getName() + " does not have skill with ID '" + skillId + "'");
+ final CastableSkill castable = classSkill.toCastable(playerData);
final double value = playerData.getMMOPlayerData().getSkillModifierMap().calculateValue(castable, parameterId);
return MythicLib.plugin.getMMOConfig().decimal.format(value);
} else if (identifier.startsWith("attribute_points_spent_")) {
@@ -128,11 +127,9 @@ public class RPGPlaceholders extends PlaceholderExpansion {
for (double j = 1; j < 20; j++)
format.append(ratio >= j ? ChatColor.RED : ratio >= j - .5 ? ChatColor.DARK_RED : ChatColor.DARK_GRAY).append(AltChar.listSquare);
return format.toString();
- }
-
- else if (identifier.equals("class_id"))
+ } else if (identifier.equals("class_id"))
return playerData.getProfess().getId();
- else if (identifier.equals("class"))
+ else if (identifier.equals("class"))
return playerData.getProfess().getName();
else if (identifier.startsWith("profession_percent_")) {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java
index 51d0c9e7..1257691a 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/ForceClassProfileDataModule.java
@@ -9,28 +9,36 @@ import fr.phoenixdevt.profiles.event.ProfileUnloadEvent;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.event.SynchronizedDataLoadEvent;
import io.lumine.mythic.lib.comp.profile.ProfileMode;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.InventoryManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
+import org.bukkit.NamespacedKey;
import org.bukkit.event.EventHandler;
import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.NotNull;
public class ForceClassProfileDataModule implements ProfileDataModule {
+ private final NamespacedKey key;
+
public ForceClassProfileDataModule() {
- final ProfileProvider> provider = Bukkit.getServicesManager().getRegistration(ProfileProvider.class).getProvider();
- provider.registerModule(this);
+ final var registration = Bukkit.getServicesManager().getRegistration(ProfileProvider.class);
+ Validate.notNull(registration, "Could not find ProfileAPI registration provider");
+ final var profileProvider = registration.getProvider();
+ profileProvider.registerModule(this);
+
+ this.key = new NamespacedKey(MMOCore.plugin, "force_class_select");
}
@Override
- public JavaPlugin getOwningPlugin() {
+ public @NotNull JavaPlugin getOwningPlugin() {
return MMOCore.plugin;
}
@Override
- public String getIdentifier() {
- return "mmocore_force_class";
+ public @NotNull NamespacedKey getId() {
+ return this.key;
}
/**
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java
index d64086e2..153bf6d2 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/profile/MMOCoreProfileDataModule.java
@@ -1,29 +1,21 @@
package net.Indyuce.mmocore.comp.profile;
import fr.phoenixdevt.profiles.ProfileDataModule;
-import fr.phoenixdevt.profiles.event.ProfileCreateEvent;
-import fr.phoenixdevt.profiles.event.ProfileRemoveEvent;
import fr.phoenixdevt.profiles.placeholder.PlaceholderProcessor;
import fr.phoenixdevt.profiles.placeholder.PlaceholderRequest;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
+import io.lumine.mythic.lib.module.MMOPlugin;
+import io.lumine.mythic.lib.profile.DefaultProfileDataModule;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.experience.Profession;
-import org.bukkit.event.EventHandler;
-import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.NotNull;
-public class MMOCoreProfileDataModule implements ProfileDataModule, PlaceholderProcessor {
-
- @Override
- public JavaPlugin getOwningPlugin() {
- return MMOCore.plugin;
- }
-
- @Override
- public String getIdentifier() {
- return "mmocore";
+public class MMOCoreProfileDataModule extends DefaultProfileDataModule implements PlaceholderProcessor {
+ public MMOCoreProfileDataModule(@NotNull MMOPlugin plugin) {
+ super(plugin);
}
@Override
@@ -31,6 +23,11 @@ public class MMOCoreProfileDataModule implements ProfileDataModule, PlaceholderP
return this;
}
+ @Override
+ public @NotNull String getPlaceholderPrefix() {
+ return "mmocore";
+ }
+
@Override
public void processPlaceholderRequest(PlaceholderRequest placeholderRequest) {
final PlayerData fictiveData = new PlayerData(new MMOPlayerData(placeholderRequest.getProfile().getUniqueId()));
@@ -50,14 +47,4 @@ public class MMOCoreProfileDataModule implements ProfileDataModule, PlaceholderP
placeholderRequest.validate();
});
}
-
- @EventHandler
- public void onProfileCreate(ProfileCreateEvent event) {
- event.validate(this);
- }
-
- @EventHandler
- public void onProfileDelete(ProfileRemoveEvent event) {
- event.validate(this);
- }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java
index 9bae04c2..ce3c9e21 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeHandler.java
@@ -12,7 +12,7 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.comp.flags.CustomFlag;
import io.lumine.mythic.lib.comp.flags.WorldGuardFlags;
import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.command.PvpModeCommand;
+import net.Indyuce.mmocore.player.CombatHandler;
import net.Indyuce.mmocore.player.Message;
import java.util.Objects;
@@ -52,7 +52,7 @@ public class PvPModeHandler extends MMOCoreFlagHandler {
if (!newPvpMode && lastPvpMode) {
// Apply cooldown
- playerData.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeRegionLeaveCooldown);
+ playerData.getMMOPlayerData().getCooldownMap().applyCooldown(CombatHandler.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeRegionLeaveCooldown);
// Send message
if (canSendMessage()) {
@@ -72,7 +72,7 @@ public class PvPModeHandler extends MMOCoreFlagHandler {
} else if (newPvpMode && !lastPvpMode) {
// Apply cooldown
- playerData.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeRegionEnterCooldown);
+ playerData.getMMOPlayerData().getCooldownMap().applyCooldown(CombatHandler.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeRegionEnterCooldown);
// Apply invulnerability
final boolean applyInvulnerability = playerData.getCombat().isInPvpMode() && playerData.getCombat().canQuitPvpMode();
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java
index 1cc5598f..b6305026 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/region/pvpmode/PvPModeListener.java
@@ -5,10 +5,10 @@ import com.sk89q.worldguard.session.handler.Handler;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.comp.flags.CustomFlag;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -78,7 +78,7 @@ public class PvPModeListener implements Listener {
if (event.getDamage() > 0) {
final var left = targetData.getCombat().getInvulnerableTill() - System.currentTimeMillis();
final var leftFormatted = MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d);
- Message.PVP_MODE_CANNOT_HIT_INVULNERABLE_TARGET.prepare("left", leftFormatted).send(source);
+ Message.PVP_MODE_CANNOT_HIT_INVULNERABLE_TARGET.send(source, "left", leftFormatted);
}
event.setCancelled(true);
return;
@@ -89,7 +89,7 @@ public class PvPModeListener implements Listener {
if (event.getDamage() > 0) {
final var left = sourceData.getCombat().getInvulnerableTill() - System.currentTimeMillis();
final var leftFormatted = MythicLib.plugin.getMMOConfig().decimal.format(left / 1000d);
- Message.PVP_MODE_CANNOT_HIT_INVULNERABLE_SELF.prepare("left", leftFormatted).send(source);
+ Message.PVP_MODE_CANNOT_HIT_INVULNERABLE_SELF.send(source, "left", leftFormatted);
}
event.setCancelled(true);
return;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/EXPSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/EXPSource.java
index 08ccf6c9..af16a3f9 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/EXPSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/EXPSource.java
@@ -37,6 +37,12 @@ public enum EXPSource {
*/
FISHING,
+ /**
+ * When professions level up and provide exp
+ * to the main class
+ */
+ PROFESSION_TO_CLASS,
+
/**
* Anything else
*/
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/ExpCurve.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/ExpCurve.java
index b51ea6af..a81422a5 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/ExpCurve.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/ExpCurve.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.experience;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import java.io.BufferedReader;
import java.io.File;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java
index d7222300..b575582e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java
@@ -4,18 +4,16 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.gson.JsonElement;
import io.lumine.mythic.lib.gson.JsonObject;
-import io.lumine.mythic.lib.version.VParticle;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent;
-import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
-import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
import net.Indyuce.mmocore.party.AbstractParty;
import net.Indyuce.mmocore.player.Message;
import net.Indyuce.mmocore.util.Language;
import net.Indyuce.mmocore.util.formula.FormulaFailsafeException;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@@ -129,12 +127,27 @@ public class PlayerProfessions {
return MMOCore.plugin.professionManager.has(id) ? MMOCore.plugin.professionManager.get(id).getExpCurve().getExperience(getLevel(id) + 1) : 0;
}
+ @Deprecated
public void setLevel(Profession profession, int value) {
- level.put(profession.getId(), value);
+ setLevel(profession, value, PlayerLevelChangeEvent.Reason.UNKNOWN);
}
- public void takeLevels(Profession profession, int value) {
- int current = level.getOrDefault(profession.getId(), 1);
+ public void setLevel(@NotNull Profession profession, int newLevel, @NotNull PlayerLevelChangeEvent.Reason reason) {
+ final var previousValue = level.put(profession.getId(), Math.max(1, newLevel));
+ final var oldLevel = previousValue == null ? 1 : Math.max(1, previousValue);
+
+ // Data loaded async (sync event, clashes) => no event called
+ if (reason != PlayerLevelChangeEvent.Reason.CHOOSE_PROFILE)
+ Bukkit.getPluginManager().callEvent(new PlayerLevelChangeEvent(playerData, profession, oldLevel, newLevel, reason));
+
+ if (getPlayerData().getMMOPlayerData().isPlaying()) {
+ playerData.getStats().updateStats();
+ }
+ }
+
+ @Deprecated
+ public void takeLevels(@NotNull Profession profession, int value) {
+ int current = Math.max(1, level.getOrDefault(profession.getId(), 1));
level.put(profession.getId(), Math.max(1, current - value));
}
@@ -181,7 +194,7 @@ public class PlayerProfessions {
// Apply buffs AFTER splitting exp
value *= (1 + playerData.getStats().getStat("ADDITIONAL_EXPERIENCE_" + UtilityMethods.enumName(profession.getId())) / 100) * MMOCore.plugin.boosterManager.getMultiplier(profession);
- var event = new PlayerExperienceGainEvent(playerData, profession, value, source);
+ final var event = new PlayerExperienceGainEvent(playerData, profession, value, source);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) return;
@@ -189,54 +202,53 @@ public class PlayerProfessions {
if (hologramLocation != null && profession.getOption(Profession.ProfessionOption.EXP_HOLOGRAMS))
MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), Language.EXP_HOLOGRAM.getFormat().replace("{exp}", MythicLib.plugin.getMMOConfig().decimal.format(event.getExperience())));
- exp.put(profession.getId(), Math.max(0, exp.getOrDefault(profession.getId(), 0d) + event.getExperience()));
- int level, oldLevel = getLevel(profession);
- double needed, exp;
+ var currentExp = Math.max(0d, exp.getOrDefault(profession.getId(), 0d) + event.getExperience());
+ final var oldLevel = getLevel(profession);
+ int newLevel = oldLevel;
+ double experienceNeeded;
/*
* Loop for exp overload when leveling up, will continue
- * looping until exp is 0 or max level has been reached
+ * looping until exp is 0 or max newLevel has been reached
*/
- boolean check = false;
- while ((exp = this.exp.get(profession.getId())) >= (needed = profession.getExpCurve().getExperience((level = getLevel(profession)) + 1))) {
+ while (currentExp >= (experienceNeeded = profession.getExpCurve().getExperience(newLevel))) {
+
if (hasReachedMaxLevel(profession)) {
- setExperience(profession, 0);
- check = true;
+ currentExp = 0;
break;
}
- this.exp.put(profession.getId(), exp - needed);
- this.level.put(profession.getId(), level + 1);
- check = true;
+ currentExp -= experienceNeeded;
+ newLevel++;
// Give main class exp
try {
- var mainExpGiven = profession.getExperience().evaluate(level, playerData);
- playerData.giveExperience(mainExpGiven, null);
+ var mainExpGiven = profession.getExperience().evaluate(newLevel, playerData);
+ playerData.giveExperience(mainExpGiven, EXPSource.PROFESSION_TO_CLASS);
} catch (FormulaFailsafeException exception) {
exception.log("Could not evaluate profession level-up exp for %s", profession.getId());
}
// Apply profession experience table
- profession.updateAdvancement(playerData, level);
+ profession.updateAdvancement(playerData, newLevel);
}
- if (check) {
- Bukkit.getPluginManager().callEvent(new PlayerLevelUpEvent(playerData, profession, oldLevel, level));
- new SmallParticleEffect(playerData.getPlayer(), VParticle.INSTANT_EFFECT.get()); // TODO move to playerMessage
- Message.PROFESSION_LEVEL_UP.send(playerData, "level", level, "profession", profession.getName());
- playerData.getStats().updateStats();
+ this.exp.put(profession.getId(), currentExp);
+
+ if (newLevel > oldLevel) {
+ setLevel(profession, newLevel, PlayerLevelChangeEvent.Reason.LEVEL_UP);
+ Message.PROFESSION_LEVEL_UP.send(playerData, "level", newLevel, "profession", profession.getName());
}
if (playerData.isOnline()) {
// Build exp bar
StringBuilder bar = new StringBuilder(ChatColor.BOLD.toString());
- int chars = (int) (exp / needed * 20);
+ int chars = (int) (currentExp / experienceNeeded * 20);
for (int j = 0; j < 20; j++)
bar.append(j == chars ? ChatColor.WHITE.toString() + ChatColor.BOLD : "").append("|");
- var ratioFormatted = MythicLib.plugin.getMMOConfig().decimal.format(exp / needed * 100);
+ var ratioFormatted = MythicLib.plugin.getMMOConfig().decimal.format(currentExp / experienceNeeded * 100);
Message.EXP_NOTIFICATION.send(playerData,
"profession", profession.getName(),
"progress", bar.toString(),
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java
index a78f75aa..a1a8435f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/Profession.java
@@ -3,11 +3,11 @@ package net.Indyuce.mmocore.experience;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.PostLoadAction;
import io.lumine.mythic.lib.util.PreloadedObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.util.formula.ScalingFormula;
-import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
@@ -158,6 +158,11 @@ public class Profession implements ExperienceObject, PreloadedObject {
}
}
+ @Override
+ public String toString() {
+ return "Profession{id='" + id + "', name='" + name + "'}";
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java
deleted file mode 100644
index 921d1438..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/SimpleExperienceObject.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.Indyuce.mmocore.experience;
-
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
-import org.bukkit.Location;
-import org.jetbrains.annotations.Nullable;
-
-public class SimpleExperienceObject implements ExperienceDispenser {
-
- @Override
- public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) {
- hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null : hologramLocation;
- playerData.giveExperience(experience, source, hologramLocation, true);
- }
-
- @Override
- public boolean shouldHandle(PlayerData playerData) {
- return true;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceItem.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceItem.java
index 44f177f6..40f3117f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceItem.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceItem.java
@@ -1,12 +1,12 @@
package net.Indyuce.mmocore.experience.droptable;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
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.quest.trigger.api.Removable;
import net.Indyuce.mmocore.api.quest.trigger.api.Temporary;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import java.util.ArrayList;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java
index 0f409d06..3e2760b9 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/droptable/ExperienceTable.java
@@ -1,8 +1,8 @@
package net.Indyuce.mmocore.experience.droptable;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.ExperienceObject;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java
index 7f610440..11f2a285 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ClimbExperienceSource.java
@@ -1,11 +1,11 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerMoveEvent;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/CraftItemExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/CraftItemExperienceSource.java
index 609ab875..246824d5 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/CraftItemExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/CraftItemExperienceSource.java
@@ -1,12 +1,12 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageDealtExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageDealtExperienceSource.java
index 467a160e..3a99283d 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageDealtExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageDealtExperienceSource.java
@@ -4,12 +4,12 @@ import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
import io.lumine.mythic.lib.damage.DamageType;
+import io.lumine.mythic.lib.util.lang3.Validate;
import io.lumine.mythic.lib.version.Attributes;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.event.EventHandler;
import java.util.Arrays;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageTakenExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageTakenExperienceSource.java
index e80e7294..6c7e5ff9 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageTakenExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/DamageTakenExperienceSource.java
@@ -3,13 +3,13 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.Lazy;
+import io.lumine.mythic.lib.util.lang3.Validate;
import io.lumine.mythic.lib.version.Attributes;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageEvent;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/EatExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/EatExperienceSource.java
index fe29dd74..6a69dbea 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/EatExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/EatExperienceSource.java
@@ -1,11 +1,11 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerItemConsumeEvent;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/FromExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/FromExperienceSource.java
index 1d71ed69..a04adb38 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/FromExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/FromExperienceSource.java
@@ -2,12 +2,12 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.config.YamlFile;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import java.util.ArrayList;
import java.util.List;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MoveExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MoveExperienceSource.java
index d8a9794e..aede4184 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MoveExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/MoveExperienceSource.java
@@ -1,11 +1,11 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ProjectileExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ProjectileExperienceSource.java
index d5e584d2..26c90104 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ProjectileExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ProjectileExperienceSource.java
@@ -3,11 +3,11 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.FlushableRegistry;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ResourceExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ResourceExperienceSource.java
index 587e587e..fdda8157 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ResourceExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/ResourceExperienceSource.java
@@ -2,16 +2,15 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.event.EventHandler;
-
-import static org.bukkit.event.EventPriority.HIGHEST;
+import org.bukkit.event.EventPriority;
public class ResourceExperienceSource extends SpecificExperienceSource {
private final PlayerResource resource;
@@ -43,16 +42,16 @@ public class ResourceExperienceSource extends SpecificExperienceSource {
- @EventHandler(priority = HIGHEST, ignoreCancelled = true)
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onResource(PlayerResourceUpdateEvent event) {
if (!UtilityMethods.isRealPlayer(event.getPlayer())) return;
PlayerData playerData = PlayerData.get(event.getPlayer());
- if (event.getAmount() >= 0) return;
+ if (event.getDifference() >= 0) return;
for (ResourceExperienceSource source : getSources())
if (source.matchesParameter(playerData, event.getResource()))
- source.giveExperience(playerData, -event.getAmount(), null);
+ source.giveExperience(playerData, -event.getDifference(), null);
}
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/RideExperienceSource.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/RideExperienceSource.java
index 7a877bb8..cddbca08 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/RideExperienceSource.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/experience/source/RideExperienceSource.java
@@ -2,11 +2,11 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java
index 16107409..57068bac 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java
@@ -7,10 +7,10 @@ import io.lumine.mythic.lib.gui.editable.GeneratedInventory;
import io.lumine.mythic.lib.gui.editable.item.ItemOptions;
import io.lumine.mythic.lib.gui.editable.item.SimpleItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java
index fb5d966d..31df828f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassConfirmation.java
@@ -7,6 +7,7 @@ import io.lumine.mythic.lib.gui.editable.item.InventoryItem;
import io.lumine.mythic.lib.gui.editable.item.PhysicalItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.GoBackItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
@@ -14,7 +15,6 @@ import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
import net.Indyuce.mmocore.player.ClassDataContainer;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
@@ -108,7 +108,7 @@ public class ClassConfirmation extends AbstractClassSelect {
@Override
public void onClick(@NotNull ClassConfirmationInventory inv, @NotNull InventoryClickEvent event) {
- PlayerChangeClassEvent called = new PlayerChangeClassEvent(inv.playerData, inv.profess);
+ PlayerChangeClassEvent called = new PlayerChangeClassEvent(inv.playerData, inv.profess, PlayerChangeClassEvent.Reason.GUI);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled()) return;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java
index e97faa4d..cf678f8a 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java
@@ -11,6 +11,7 @@ import io.lumine.mythic.lib.gui.editable.item.PhysicalItem;
import io.lumine.mythic.lib.gui.editable.item.SimpleItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
import io.lumine.mythic.lib.manager.StatManager;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
@@ -18,7 +19,6 @@ import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.experience.Booster;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.party.AbstractParty;
-import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/QuestViewer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/QuestViewer.java
index e57ee2f3..6033a62f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/QuestViewer.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/QuestViewer.java
@@ -9,13 +9,13 @@ import io.lumine.mythic.lib.gui.editable.item.SimpleItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.NextPageItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.PreviousPageItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.Quest;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java
index 08eefc45..f1aea017 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java
@@ -10,13 +10,13 @@ import io.lumine.mythic.lib.gui.editable.item.PhysicalItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.NextPageItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.PreviousPageItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.player.Message;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skill.binding.SkillSlot;
-import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/eco/GoldPouch.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/eco/GoldPouch.java
index 4f5cf49a..a8d40169 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/eco/GoldPouch.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/eco/GoldPouch.java
@@ -1,13 +1,13 @@
package net.Indyuce.mmocore.gui.eco;
+import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.gui.PluginInventory;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.util.Language;
import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
import org.bukkit.Material;
-import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
@@ -28,7 +28,7 @@ public class GoldPouch extends PluginInventory {
@Override
public Inventory getInventory() {
- Inventory inv = Bukkit.createInventory(this, 18, ChatColor.UNDERLINE + "Gold Pouch");
+ Inventory inv = Bukkit.createInventory(this, 18, MythicLib.plugin.parseColors(Language.GOLD_POUCH_UI_NAME.getFormat()));
inv.setContents(MMOCoreUtils.itemStackArrayFromBase64(nbt.getString("RpgPouchInventory")));
return lastBukkitInventory = inv;
}
@@ -52,12 +52,11 @@ public class GoldPouch extends PluginInventory {
event.setCancelled(true);
// in deposit menu
- if (event.getSlot() < 18) {
- int empty = player.getInventory().firstEmpty();
- if (empty < 0)
- return;
+ if (event.getRawSlot() < 18) {
+ final var empty = player.getInventory().firstEmpty();
+ if (empty < 0) return;
- player.playSound(player.getLocation(), Sound.ENTITY_SHULKER_TELEPORT, 1, 2);
+ //player.playSound(player.getLocation(), Sound.ENTITY_SHULKER_TELEPORT, 1, 2);
player.getInventory().addItem(event.getCurrentItem());
event.getInventory().setItem(event.getSlot(), null);
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java
index 2a36080e..b4a0aed2 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java
@@ -13,7 +13,7 @@ import io.lumine.mythic.lib.gui.util.IconOptions;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.player.Message;
-import net.Indyuce.mmocore.skilltree.IntegerCoordinates;
+import net.Indyuce.mmocore.skilltree.IntCoords;
import net.Indyuce.mmocore.skilltree.NodeState;
import net.Indyuce.mmocore.skilltree.ParentType;
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
@@ -22,7 +22,6 @@ import net.Indyuce.mmocore.skilltree.display.NodeDisplayInfo;
import net.Indyuce.mmocore.skilltree.display.PathDisplayInfo;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import org.bukkit.ChatColor;
-import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
@@ -37,6 +36,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
public class SkillTreeViewer extends EditableInventory {
protected DisplayMap icons;
@@ -101,7 +101,7 @@ public class SkillTreeViewer extends EditableInventory {
@Override
public Placeholders getPlaceholders(SkillTreeInventory inv, int n) {
Placeholders holders = new Placeholders();
- holders.register("skill-tree-points", inv.playerData.getSkillTreePoints(inv.getSkillTree().getId()));
+ holders.register("skill-tree-points", inv.playerData.getSkillTreePoints(inv.getSkillTree()));
holders.register("global-points", inv.playerData.getSkillTreePoints("global"));
holders.register("realloc-points", inv.playerData.getSkillTreeReallocationPoints());
int maxPointSpent = inv.getSkillTree().getMaxPointSpent();
@@ -126,11 +126,10 @@ public class SkillTreeViewer extends EditableInventory {
}
int reallocated = inv.playerData.getPointsSpent(inv.skillTree);
- // Remove all the nodeStates progress
inv.playerData.giveSkillTreePoints(inv.skillTree.getId(), reallocated);
inv.playerData.giveSkillTreeReallocationPoints(-1);
inv.playerData.resetSkillTree(inv.skillTree);
- inv.skillTree.setupNodeStates(inv.playerData);
+ inv.skillTree.resolveStates(inv.playerData);
Message.SKILL_TREE_REALLOCATE.send(inv.playerData, "points", inv.playerData.getSkillTreePoints(inv.skillTree.getId()), "skill-tree", inv.skillTree.getName());
inv.open();
}
@@ -218,7 +217,7 @@ public class SkillTreeViewer extends EditableInventory {
ItemStack item = super.getDisplayedItem(inv, ItemOptions.material(n, skillTree.getItem()));
ItemMeta meta = item.getItemMeta();
- meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); // Hardcore 'hide-flags' on
+ meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); // Hardcode 'hide-flags' on
meta.setDisplayName(skillTree.getName());
meta.setCustomModelData(skillTree.getCustomModelData());
PersistentDataContainer container = meta.getPersistentDataContainer();
@@ -303,7 +302,7 @@ public class SkillTreeViewer extends EditableInventory {
@Override
public void preprocessLore(@NotNull SkillTreeInventory inv, int n, @NotNull List lore) {
- IntegerCoordinates coordinates = inv.getCoordinates(n);
+ IntCoords coordinates = inv.getCoordinates(n);
if (!inv.getSkillTree().isNode(coordinates)) return;
SkillTreeNode node = inv.getSkillTree().getNode(coordinates);
@@ -313,8 +312,8 @@ public class SkillTreeViewer extends EditableInventory {
if (str.contains("{node-lore}")) {
lore.remove(i);
List shaded = node.getLore(inv.playerData);
- var _i = i;
- shaded.forEach(s -> lore.add(_i, str.replace("{node-lore}", s)));
+ var _i = new AtomicInteger(i);
+ shaded.forEach(s -> lore.add(_i.getAndIncrement(), str.replace("{node-lore}", s)));
i += shaded.size();
} else if (str.contains("{strong-parents}")) {
lore.remove(i);
@@ -345,10 +344,11 @@ public class SkillTreeViewer extends EditableInventory {
*/
@Override
public ItemStack getDisplayedItem(SkillTreeInventory inv, int n) {
- IntegerCoordinates coordinates = inv.getCoordinates(n);
- if (!inv.getSkillTree().isPathOrNode(coordinates)) return new ItemStack(Material.AIR);
+ IntCoords coordinates = inv.getCoordinates(n);
+
+ IconOptions icon = inv.computeIcon(coordinates);
+ if (icon == null) return null; // Neither a path nor a node
- IconOptions icon = inv.getIcon(coordinates);
ItemStack item = super.getDisplayedItem(inv, new ItemOptions(n, icon));
ItemMeta meta = item.getItemMeta();
@@ -376,6 +376,7 @@ public class SkillTreeViewer extends EditableInventory {
* Soft&Strong children lore for the node
*/
public List getParentsLore(SkillTreeInventory inv, SkillTreeNode node, Collection parents) {
+ // TODO why is this hardcoded >:(
List lore = new ArrayList<>();
for (SkillTreeNode parent : parents) {
int level = inv.playerData.getNodeLevel(parent);
@@ -386,7 +387,7 @@ public class SkillTreeViewer extends EditableInventory {
}
@Override
- public Placeholders getPlaceholders(SkillTreeInventory inv, int n) {
+ public @NotNull Placeholders getPlaceholders(SkillTreeInventory inv, int n) {
Placeholders holders = new Placeholders();
holders.register("skill-tree", inv.getSkillTree().getName());
boolean isNode = inv.getSkillTree().isNode(inv.getCoordinates(n));
@@ -399,10 +400,10 @@ public class SkillTreeViewer extends EditableInventory {
holders.register("name", node.getName());
holders.register("max-children", node.getMaxChildren());
holders.register("point-consumed", node.getPointConsumption());
- holders.register("display-type", node.getNodeType());
- } else {
+ //holders.register("display-type", node.getNodeType());
+ } /*else {
holders.register("display-type", inv.skillTree.getPath(inv.getCoordinates(n)).getPathType());
- }
+ }*/
int maxPointSpent = inv.getSkillTree().getMaxPointSpent();
holders.register("max-point-spent", maxPointSpent == Integer.MAX_VALUE ? "∞" : maxPointSpent);
holders.register("point-spent", inv.playerData.getPointsSpent(inv.getSkillTree()));
@@ -419,10 +420,10 @@ public class SkillTreeViewer extends EditableInventory {
final PersistentDataContainer container = event.getCurrentItem().getItemMeta().getPersistentDataContainer();
final int x = container.get(new NamespacedKey(MMOCore.plugin, "coordinates.x"), PersistentDataType.INTEGER);
final int y = container.get(new NamespacedKey(MMOCore.plugin, "coordinates.y"), PersistentDataType.INTEGER);
- if (!inv.skillTree.isNode(new IntegerCoordinates(x, y))) return;
+ if (!inv.skillTree.isNode(new IntCoords(x, y))) return;
// Higher number of points spent in SKILL TREE (not node)
- final SkillTreeNode node = inv.skillTree.getNode(new IntegerCoordinates(x, y));
+ final SkillTreeNode node = inv.skillTree.getNode(new IntCoords(x, y));
if (inv.playerData.getPointsSpent(inv.skillTree) >= inv.skillTree.getMaxPointSpent()) {
Message.SKILL_TREE_MAX_POINTS_SPENT.send(inv.playerData);
return;
@@ -517,16 +518,25 @@ public class SkillTreeViewer extends EditableInventory {
return playerData;
}
- public IconOptions getIcon(@NotNull IntegerCoordinates coordinates) {
- if (skillTree.isNode(coordinates)) {
- var node = skillTree.getNode(coordinates);
- var nodeShape = node.getNodeType();
- var nodeState = playerData.getNodeState(node);
+ @Deprecated
+ public IconOptions getIcon(IntCoords coordinates) {
+ return computeIcon(coordinates);
+ }
+
+ @Nullable
+ public IconOptions computeIcon(@NotNull IntCoords coordinates) {
+
+ // Is this a node?
+ final var node = skillTree.getNodeOrNull(coordinates);
+ if (node != null) {
+ final var nodeShape = skillTree.getNodeShape(node);
+ final var nodeState = playerData.getNodeState(node);
var displayInfo = new NodeDisplayInfo(nodeShape, nodeState);
// Node > skill tree > skill tree UI
var icon = DisplayMap.getIcon(displayInfo, node.getIcons(), skillTree.getIcons(), icons);
if (icon == null && nodeState == NodeState.MAXED_OUT) {
+ // Fallback to UNLOCKED if no MAXED_OUT icon found
displayInfo = new NodeDisplayInfo(nodeShape, NodeState.UNLOCKED);
icon = DisplayMap.getIcon(displayInfo, node.getIcons(), skillTree.getIcons(), icons);
}
@@ -534,11 +544,13 @@ public class SkillTreeViewer extends EditableInventory {
//Validate.notNull(icon, "Node " + node.getFullId() + " has no icon for shape " + nodeShape + " and state " + nodeState);
return icon;
- } else {
- var path = skillTree.getPath(coordinates);
- var pathShape = path.getPathType();
- var pathStatus = path.getStatus(playerData);
- var displayInfo = new PathDisplayInfo(pathShape, pathStatus);
+ }
+
+ final var edge = skillTree.getPath(coordinates);
+ if (edge != null) {
+ final var pathState = playerData.getPathState(edge);
+ final var pathShape = edge.getShape(coordinates);
+ final var displayInfo = new PathDisplayInfo(pathShape, pathState);
// Skill tree > Skill tree UI
var icon = DisplayMap.getIcon(displayInfo, skillTree.getIcons(), icons);
@@ -547,6 +559,9 @@ public class SkillTreeViewer extends EditableInventory {
return icon;
}
+
+ // Neither a node or a path
+ return null;
}
@NotNull
@@ -555,11 +570,11 @@ public class SkillTreeViewer extends EditableInventory {
return guiName.replace("{skill-tree-name}", skillTree.getName()).replace("{skill-tree-id}", skillTree.getId());
}
- public IntegerCoordinates getCoordinates(int n) {
+ public IntCoords getCoordinates(int n) {
int slot = slots.get(n);
int deltaX = (slot - minSlot) % 9;
int deltaY = (slot - minSlot) / 9;
- IntegerCoordinates coordinates = new IntegerCoordinates(getX() + deltaX, getY() + deltaY);
+ IntCoords coordinates = new IntCoords(getX() + deltaX, getY() + deltaY);
return coordinates;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java
index f33ef01f..4b950cbf 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java
@@ -9,6 +9,7 @@ import io.lumine.mythic.lib.gui.editable.item.builtin.NextPageItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.PreviousPageItem;
import io.lumine.mythic.lib.gui.editable.placeholder.ErrorPlaceholders;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerActivity;
import net.Indyuce.mmocore.api.player.PlayerData;
@@ -18,7 +19,6 @@ import net.Indyuce.mmocore.api.util.input.PlayerInput.InputType;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildAdmin.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildAdmin.java
index 5a02ffeb..12a01fa4 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildAdmin.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildAdmin.java
@@ -7,13 +7,13 @@ import io.lumine.mythic.lib.gui.editable.item.InventoryItem;
import io.lumine.mythic.lib.gui.editable.item.PhysicalItem;
import io.lumine.mythic.lib.gui.editable.item.SimpleItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.input.ChatInput;
import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java
index 22e76575..cc540d65 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/guild/EditableGuildView.java
@@ -9,6 +9,7 @@ import io.lumine.mythic.lib.gui.editable.item.SimpleItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.NextPageItem;
import io.lumine.mythic.lib.gui.editable.item.builtin.PreviousPageItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
@@ -17,7 +18,6 @@ import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.manager.data.OfflinePlayerData;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/party/EditablePartyView.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/party/EditablePartyView.java
index d28b65d1..ca7122a9 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/party/EditablePartyView.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/party/EditablePartyView.java
@@ -7,6 +7,7 @@ import io.lumine.mythic.lib.gui.editable.item.InventoryItem;
import io.lumine.mythic.lib.gui.editable.item.PhysicalItem;
import io.lumine.mythic.lib.gui.editable.item.SimpleItem;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.input.ChatInput;
@@ -14,7 +15,6 @@ import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import net.Indyuce.mmocore.party.provided.Party;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/ChestAlgorithmOptions.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/ChestAlgorithmOptions.java
index 9940857d..985a2954 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/ChestAlgorithmOptions.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/ChestAlgorithmOptions.java
@@ -1,6 +1,6 @@
package net.Indyuce.mmocore.loot.chest;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.configuration.ConfigurationSection;
public class ChestAlgorithmOptions {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChest.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChest.java
index 24394969..466d1927 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChest.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChest.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.loot.chest;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.player.Message;
import net.Indyuce.mmocore.util.HashableLocation;
-import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java
index 4c61dacd..328a5066 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/LootChestRegion.java
@@ -1,12 +1,12 @@
package net.Indyuce.mmocore.loot.chest;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.LootChestSpawnEvent;
import net.Indyuce.mmocore.api.player.PlayerActivity;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.loot.LootBuilder;
import net.Indyuce.mmocore.loot.RandomWeightedRoll;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/RegionBounds.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/RegionBounds.java
index 4dabbc74..3f1f0305 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/RegionBounds.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/RegionBounds.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.loot.chest;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/TierEffect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/TierEffect.java
index d44be8b5..733d8bd2 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/TierEffect.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/TierEffect.java
@@ -1,8 +1,8 @@
package net.Indyuce.mmocore.loot.chest;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.loot.chest.particle.ChestParticleEffect;
-import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.configuration.ConfigurationSection;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/DistanceCondition.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/DistanceCondition.java
index 04041349..bd0eae5f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/DistanceCondition.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/DistanceCondition.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.loot.chest.condition;
import io.lumine.mythic.lib.api.MMOLineConfig;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/FromCondition.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/FromCondition.java
index 9a841efc..5452af30 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/FromCondition.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/FromCondition.java
@@ -2,8 +2,8 @@ package net.Indyuce.mmocore.loot.chest.condition;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.config.YamlFile;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
-import org.apache.commons.lang.Validate;
import java.util.ArrayList;
import java.util.List;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/TimeCondition.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/TimeCondition.java
index 06ef7667..6d11201b 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/TimeCondition.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/TimeCondition.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.loot.chest.condition;
import io.lumine.mythic.lib.api.MMOLineConfig;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
public class TimeCondition extends Condition {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/WeatherCondition.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/WeatherCondition.java
index 6c7cec45..3e24c7bb 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/WeatherCondition.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/condition/WeatherCondition.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.loot.chest.condition;
import io.lumine.mythic.lib.api.MMOLineConfig;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
public class WeatherCondition extends Condition {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/CastingParticle.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/CastingParticle.java
index 84b76c29..71464692 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/CastingParticle.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/CastingParticle.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.loot.chest.particle;
import io.lumine.mythic.lib.UtilityMethods;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/SmallParticleEffect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/SmallParticleEffect.java
index 9502604c..fceaab20 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/SmallParticleEffect.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/chest/particle/SmallParticleEffect.java
@@ -6,32 +6,40 @@ import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.scheduler.BukkitRunnable;
+@Deprecated
public class SmallParticleEffect extends BukkitRunnable {
- private final Location loc;
- private final Particle particle;
- private final double r;
+ private final Location loc;
+ private final Particle particle;
+ private final double r;
- private double t;
+ private double t;
- public SmallParticleEffect(Entity entity, Particle particle) {
- this(entity, particle, .7);
- }
+ /**
+ * Causes problems with versions inconsistencies. For instance, SPELL requires
+ * different extra data types based on versions. It's safer to move that to
+ * MythicLib and give more configurability to the user, and better, until now
+ * that was hardcoded, which is pretty sadge
+ */
+ @Deprecated
+ public SmallParticleEffect(Entity entity, Particle particle) {
+ this(entity, particle, .7);
+ }
- public SmallParticleEffect(Entity entity, Particle particle, double r) {
- this.loc = entity.getLocation().add(0, .5, 0);
- this.particle = particle;
- this.r = r;
+ public SmallParticleEffect(Entity entity, Particle particle, double r) {
+ this.loc = entity.getLocation().add(0, .5, 0);
+ this.particle = particle;
+ this.r = r;
- runTaskTimer(MMOCore.plugin, 0, 1);
- }
+ runTaskTimer(MMOCore.plugin, 0, 1);
+ }
- public void run() {
- if (t > Math.PI * 2)
- cancel();
+ public void run() {
+ if (t > Math.PI * 2)
+ cancel();
- for (int k = 0; k < 3; k++) {
- t += Math.PI / 10;
- loc.getWorld().spawnParticle(particle, loc.clone().add(r * Math.cos(t), t / Math.PI / 2, r * Math.sin(t)), 0);
- }
- }
+ for (int k = 0; k < 3; k++) {
+ t += Math.PI / 10;
+ loc.getWorld().spawnParticle(particle, loc.clone().add(r * Math.cos(t), t / Math.PI / 2, r * Math.sin(t)), 0);
+ }
+ }
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/DropTable.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/DropTable.java
index 956b5bf5..a33a42c2 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/DropTable.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/DropTable.java
@@ -3,12 +3,12 @@ package net.Indyuce.mmocore.loot.droptable;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.PostLoadAction;
import io.lumine.mythic.lib.util.PreloadedObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.loot.LootBuilder;
import net.Indyuce.mmocore.loot.chest.condition.Condition;
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/DropTableDropItem.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/DropTableDropItem.java
index 298fe263..76e54efb 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/DropTableDropItem.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/DropTableDropItem.java
@@ -1,12 +1,12 @@
package net.Indyuce.mmocore.loot.droptable.dropitem;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.loot.LootBuilder;
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
import net.Indyuce.mmocore.loot.droptable.DropTable;
-import org.apache.commons.lang.Validate;
public class DropTableDropItem extends DropItem {
private final DropTable dropTable;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ActionBarManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ActionBarManager.java
index 17f17478..f384a9a7 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ActionBarManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ActionBarManager.java
@@ -35,7 +35,7 @@ public class ActionBarManager extends BukkitRunnable {
for (var player : PlayerData.getAll()) {
// Basic checks
- if (!player.isOnline() || player.getPlayer().isDead()) continue;
+ if (!player.isOnline() || player.getPlayer().isDead() || !player.getMMOPlayerData().isPlaying()) continue;
// Check if action bar resource is free (small perf optimisation)
var handler = player.getMMOPlayerData().getActionBar();
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java
index 1054011a..9d105bea 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java
@@ -1,15 +1,16 @@
package net.Indyuce.mmocore.manager;
import io.lumine.mythic.lib.util.FileUtils;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.profess.ClassOption;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
import net.Indyuce.mmocore.api.player.profess.event.trigger.*;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.logging.Level;
@@ -29,6 +30,7 @@ public class ClassManager implements MMOCoreManager {
*/
private final Set triggerHandlers = new HashSet<>();
+ @SuppressWarnings("deprecation")
public ClassManager() {
registerEvent(new LevelUpEventTrigger());
registerEvent(new AttackEventTrigger());
@@ -52,6 +54,7 @@ public class ClassManager implements MMOCoreManager {
return map.containsKey(id);
}
+ @Nullable
public PlayerClass get(String id) {
return map.get(id);
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java
index edde4139..380a4c5e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java
@@ -8,7 +8,6 @@ import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.util.input.ChatInput;
import net.Indyuce.mmocore.api.util.input.PlayerInput;
import net.Indyuce.mmocore.api.util.input.PlayerInput.InputType;
-import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.player.Message;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
@@ -24,8 +23,6 @@ import java.util.List;
import java.util.logging.Level;
public class ConfigManager {
- public final CommandVerbose commandVerbose = new CommandVerbose();
-
public boolean overrideVanillaExp, canCreativeCast, passiveSkillsNeedBinding, cobbleGeneratorXP, saveDefaultClassInfo, splitMainExp, splitProfessionExp, disableQuestBossBar,
pvpModeEnabled, pvpModeInvulnerabilityCanDamage, forceClassSelection, enableGlobalSkillTreeGUI, enableSpecificSkillTreeGUI, waypointAutoPathCalculation, waypointLinkReciprocity;
public String partyChatPrefix, noSkillBoundPlaceholder;
@@ -122,7 +119,6 @@ public class ConfigManager {
Message.loadMessagesFromConfig();
final ConfigurationSection config = MMOCore.plugin.getConfig();
- commandVerbose.reload(MMOCore.plugin.getConfig().getConfigurationSection("command-verbose"));
messages = new YamlFile(MMOCore.plugin, "messages").getContent(); // Backwards compatibility.
partyChatPrefix = MMOCore.plugin.getConfig().getString("party.chat-prefix");
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java
index 7a7d4e26..44cb2ca8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ExperienceManager.java
@@ -1,12 +1,12 @@
package net.Indyuce.mmocore.manager;
import io.lumine.mythic.lib.util.FileUtils;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.experience.ExpCurve;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java
index 9707f780..9dc74c52 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/MMOLoadManager.java
@@ -2,6 +2,7 @@ package net.Indyuce.mmocore.manager;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.gson.JsonParseException;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.block.BlockType;
import net.Indyuce.mmocore.api.load.DefaultMMOLoader;
import net.Indyuce.mmocore.api.load.MMOLoader;
@@ -11,7 +12,6 @@ import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.loot.chest.condition.Condition;
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import java.util.ArrayList;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/QuestManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/QuestManager.java
index 19169232..878e1ba7 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/QuestManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/QuestManager.java
@@ -1,9 +1,10 @@
package net.Indyuce.mmocore.manager;
import io.lumine.mythic.lib.util.FileUtils;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.quest.Quest;
-import org.apache.commons.lang.Validate;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.LinkedHashMap;
@@ -17,6 +18,7 @@ public class QuestManager implements MMOCoreManager {
quests.put(quest.getId(), quest);
}
+ @Nullable
public Quest get(String id) {
return quests.get(id);
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/RestrictionManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/RestrictionManager.java
index a777a429..86fe4c3e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/RestrictionManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/RestrictionManager.java
@@ -6,9 +6,9 @@ import io.lumine.mythic.lib.api.itemtype.ItemType;
import io.lumine.mythic.lib.util.PostLoadAction;
import io.lumine.mythic.lib.util.PreloadedObject;
import io.lumine.mythic.lib.util.config.YamlFile;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.block.BlockType;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillManager.java
index c5c9290d..23b286ee 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillManager.java
@@ -5,12 +5,12 @@ import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.skill.handler.SkillHandler;
import io.lumine.mythic.lib.util.FileUtils;
import io.lumine.mythic.lib.util.config.YamlFile;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skill.list.Ambers;
import net.Indyuce.mmocore.skill.list.Neptune_Gift;
import net.Indyuce.mmocore.skill.list.Sneaky_Picky;
-import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -100,6 +100,16 @@ public class SkillManager implements MMOCoreManager {
// Load skills
FileUtils.loadObjectsFromFolder(MMOCore.plugin, "skills", true, (name, config) -> {
final SkillHandler> handler = MythicLib.plugin.getSkills().getHandler(UtilityMethods.enumName(name));
+
+ try {
+ Validate.isTrue(handler == null);
+ for (var script : MythicLib.plugin.getSkills().getScripts())
+ if (UtilityMethods.kebabCase(script.getId()).equals(name)) return;
+ } catch (Throwable ignored) {
+ // TODO j'ai chié dans la colle, plein de .yml en trop a cause des scripts non publics!
+ // A absolument enlever lors de la maj centralisation des skills ML/MMOItems/MMOCores
+ }
+
Validate.notNull(handler, "Could not find skill handler with ID '" + UtilityMethods.enumName(name) + "'");
final RegisteredSkill skill = new RegisteredSkill(handler, config);
this.skills.put(handler.getId(), skill);
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java
index 6f1cc2aa..c8fa6129 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java
@@ -2,13 +2,13 @@ package net.Indyuce.mmocore.manager;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.util.FileUtils;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.manager.registry.MMOCoreRegister;
import net.Indyuce.mmocore.skilltree.ParentType;
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import net.Indyuce.mmocore.skilltree.tree.SkillTreeType;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,14 +55,7 @@ public class SkillTreeManager extends MMOCoreRegister {
@NotNull
public SkillTree loadSkillTree(@NotNull ConfigurationSection config) {
Validate.notNull(config, "Config cannot be null");
-
- final SkillTreeType type;
- try {
- type = SkillTreeType.valueOf(UtilityMethods.enumName(config.getString("type", "custom")));
- } catch (RuntimeException exception) {
- throw new IllegalArgumentException("Not a valid skill tree type");
- }
-
+ final var type = UtilityMethods.prettyValueOf(SkillTreeType::valueOf, config.getString("type", "custom"), "No skill tree type '%s'");
return type.construct(config);
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/WaypointManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/WaypointManager.java
index dc46483e..4c30c4ad 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/WaypointManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/WaypointManager.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.manager;
import io.lumine.mythic.lib.util.FileUtils;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.waypoint.Waypoint;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java
index cb027c86..a82fe222 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java
@@ -1,19 +1,21 @@
package net.Indyuce.mmocore.manager.data;
+import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.data.SynchronizedDataManager;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.comp.profile.MMOCoreProfileDataModule;
-import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler;
import net.Indyuce.mmocore.player.DefaultPlayerData;
import org.bukkit.configuration.ConfigurationSection;
+import org.jetbrains.annotations.NotNull;
public class PlayerDataManager extends SynchronizedDataManager {
private DefaultPlayerData defaultData = DefaultPlayerData.DEFAULT;
public PlayerDataManager(MMOCore plugin) {
- super(plugin, new YAMLPlayerDataHandler(plugin));
+ super(plugin);
}
@Override
@@ -23,13 +25,19 @@ public class PlayerDataManager extends SynchronizedDataManager {
- public MMOCoreDataSynchronizer(SQLDataHandler handler, PlayerData data) {
- super("mmocore_playerdata", "uuid", handler.getDataSource(), data);
- }
-
- @Override
- public void loadData(ResultSet result) throws SQLException {
-
- // Reset stats linked to triggers
- getData().resetTriggerStats();
-
- getData().setClassPoints(result.getInt("class_points"));
- getData().setSkillPoints(result.getInt("skill_points"));
- getData().setSkillReallocationPoints(result.getInt("skill_reallocation_points"));
- getData().setSkillTreeReallocationPoints(result.getInt("skill_tree_reallocation_points"));
- getData().setAttributePoints(result.getInt("attribute_points"));
- getData().setAttributeReallocationPoints(result.getInt("attribute_realloc_points"));
- getData().setLevel(result.getInt("level"));
- getData().setExperience(result.getDouble("experience"));
-
- if (!isEmpty(result.getString("class")))
- getData().setClass(MMOCore.plugin.classManager.get(result.getString("class")));
-
- if (!isEmpty(result.getString("times_claimed"))) {
- JsonObject json = MythicLib.plugin.getGson().fromJson(result.getString("times_claimed"), JsonObject.class);
- json.entrySet().forEach(entry -> getData().getItemClaims().put(entry.getKey(), entry.getValue().getAsInt()));
- }
- if (!isEmpty(result.getString("skill_tree_points"))) {
- JsonObject json = MythicLib.plugin.getGson().fromJson(result.getString("skill_tree_points"), JsonObject.class);
- for (SkillTree skillTree : MMOCore.plugin.skillTreeManager.getAll()) {
- getData().setSkillTreePoints(skillTree.getId(), json.has(skillTree.getId()) ? json.get(skillTree.getId()).getAsInt() : 0);
- }
- getData().setSkillTreePoints("global", json.has("global") ? json.get("global").getAsInt() : 0);
- }
-
- if (!isEmpty(result.getString("skill_tree_levels"))) {
- JsonObject json = MythicLib.plugin.getGson().fromJson(result.getString("skill_tree_levels"), JsonObject.class);
- for (SkillTreeNode skillTreeNode : MMOCore.plugin.skillTreeManager.getAllNodes()) {
- getData().setNodeLevel(skillTreeNode, json.has(skillTreeNode.getFullId()) ? json.get(skillTreeNode.getFullId()).getAsInt() : 0);
- }
- }
- Set unlockedItems = new HashSet<>();
- if (!isEmpty(result.getString("unlocked_items"))) {
- JsonArray unlockedItemsArray = MythicLib.plugin.getGson().fromJson(result.getString("unlocked_items"), JsonArray.class);
- for (JsonElement item : unlockedItemsArray)
- unlockedItems.add(item.getAsString());
- }
- getData().setUnlockedItems(unlockedItems);
- if (!isEmpty(result.getString("guild"))) {
- final Guild guild = MMOCore.plugin.nativeGuildManager.getGuild(result.getString("guild"));
- if (guild != null && guild.hasMember(getData().getUniqueId())) getData().setGuild(guild);
- }
- if (!isEmpty(result.getString("attributes"))) getData().getAttributes().load(result.getString("attributes"));
- if (getData().isOnline())
- MMOCore.plugin.attributeManager.getAll().forEach(attribute -> getData().getAttributes().getInstance(attribute).updateStats());
- if (!isEmpty(result.getString("professions")))
- getData().getCollectionSkills().load(result.getString("professions"));
- if (!isEmpty(result.getString("quests"))) getData().getQuestData().load(result.getString("quests"));
- getData().getQuestData().updateBossBar();
- if (!isEmpty(result.getString("waypoints")))
- getData().getWaypoints().addAll(MMOCoreUtils.jsonArrayToList(result.getString("waypoints")));
- if (!isEmpty(result.getString("friends")))
- MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> getData().getFriends().add(UUID.fromString(str)));
- if (!isEmpty(result.getString("skills"))) {
- JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("skills"), JsonObject.class);
- for (Map.Entry entry : object.entrySet())
- getData().setSkillLevel(entry.getKey(), entry.getValue().getAsInt());
- }
- if (!isEmpty(result.getString("bound_skills"))) {
- JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("bound_skills"), JsonObject.class);
- for (Map.Entry entry : object.entrySet()) {
- ClassSkill skill = getData().getProfess().getSkill(entry.getValue().getAsString());
- if (skill != null) getData().bindSkill(Integer.parseInt(entry.getKey()), skill);
- }
- }
- if (!isEmpty(result.getString("class_info"))) {
- JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("class_info"), JsonObject.class);
- for (Map.Entry entry : object.entrySet()) {
- try {
- PlayerClass profess = MMOCore.plugin.classManager.get(entry.getKey());
- Validate.notNull(profess, "Could not find class '" + entry.getKey() + "'");
- getData().applyClassInfo(profess, new SavedClassInformation(entry.getValue().getAsJsonObject()));
- } catch (IllegalArgumentException exception) {
- MMOCore.log(Level.WARNING, "Could not load class info '" + entry.getKey() + "': " + exception.getMessage());
- }
- }
- }
-
- /*
- * These should be loaded after to make sure that the
- * MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded.
- */
- getData().setHealth(result.getDouble("health"));
- getData().setMana(result.getDouble("mana"));
- getData().setStamina(result.getDouble("stamina"));
- getData().setStellium(result.getDouble("stellium"));
-
- UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", getData().getProfess().getId(), getData().getLevel()));
- }
-
- private boolean isEmpty(@Nullable String str) {
- return str == null
- || str.isEmpty()
- || str.equalsIgnoreCase("null")
- || str.equals("{}")
- || str.equals("[]");
- }
-
- @Override
- public void loadEmptyData() {
- MMOCore.plugin.playerDataManager.getDefaultData().apply(getData());
- UtilityMethods.debug(MMOCore.plugin, "SQL", "Loaded DEFAULT data for: '" + getData().getUniqueId() + "' as no saved data was found.");
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java
index 430701cc..51d6c3c9 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/PlayerDataTableUpdater.java
@@ -1,11 +1,11 @@
package net.Indyuce.mmocore.manager.data.sql;
-import io.lumine.mythic.lib.data.sql.SQLDataSource;
+import io.lumine.mythic.lib.data.SaveReason;
import io.lumine.mythic.lib.gson.JsonArray;
import io.lumine.mythic.lib.gson.JsonObject;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler;
+import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -15,50 +15,29 @@ import java.sql.SQLException;
import java.util.*;
import java.util.logging.Level;
-/**
- * @deprecated Not implemented yet
- */
-@Deprecated
public class PlayerDataTableUpdater {
private final PlayerData playerData;
- private final SQLDataSource provider;
+ private final SQLDatabaseImpl provider;
private final UUID effectiveId;
private final Map requestMap = new HashMap<>();
- public PlayerDataTableUpdater(SQLDataSource provider, PlayerData playerData) {
+ public PlayerDataTableUpdater(SQLDatabaseImpl provider, PlayerData playerData) {
this.playerData = playerData;
this.provider = provider;
this.effectiveId = playerData.getEffectiveId();
}
- public void executeRequest(boolean autosave) {
- final String request = "INSERT INTO mmocore_playerdata(uuid, " + formatCollection(requestMap.keySet(), false)
+ public void executeRequest(@NotNull SaveReason saveReason) {
+ final String request = "INSERT INTO " + provider.getUserDataTableName() + "(" + SQLDatabaseImpl.UUID_FIELD_NAME + ", " + formatCollection(requestMap.keySet(), false)
+ ") VALUES('" + effectiveId + "'," + formatCollection(requestMap.values(), true) + ")" +
" ON DUPLICATE KEY UPDATE " + formatMap() + ";";
- try {
- final Connection connection = provider.getConnection();
- try {
- final PreparedStatement statement = connection.prepareStatement(request);
- try {
- statement.executeUpdate();
- } catch (SQLException exception) {
- MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead");
- new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, autosave);
- exception.printStackTrace();
- } finally {
- statement.close();
- }
- } catch (SQLException exception) {
- MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead");
- new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, autosave);
- exception.printStackTrace();
- } finally {
- connection.close();
- }
+ try (Connection connection = provider.getConnection()) {
+ final PreparedStatement statement = connection.prepareStatement(request);
+ statement.executeUpdate();
} catch (SQLException exception) {
MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead");
- new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, autosave);
+ new YAMLDatabaseImpl().saveData(playerData, saveReason);
exception.printStackTrace();
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java
deleted file mode 100644
index 2d6cd4ff..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package net.Indyuce.mmocore.manager.data.sql;
-
-import io.lumine.mythic.lib.UtilityMethods;
-import io.lumine.mythic.lib.data.sql.SQLDataSource;
-import io.lumine.mythic.lib.data.sql.SQLSynchronizedDataHandler;
-import io.lumine.mythic.lib.gson.JsonArray;
-import io.lumine.mythic.lib.gson.JsonObject;
-import net.Indyuce.mmocore.MMOCore;
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
-import net.Indyuce.mmocore.manager.data.OfflinePlayerData;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.sql.SQLException;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-public class SQLDataHandler extends SQLSynchronizedDataHandler {
- public SQLDataHandler(SQLDataSource dataSource) {
- super(dataSource);
- }
-
- private static final String[] NEW_COLUMNS = new String[]{
- "times_claimed", "LONGTEXT",
- "is_saved", "TINYINT",
- "skill_reallocation_points", "INT(11)",
- "skill_tree_reallocation_points", "INT(11)",
- "skill_tree_points", "LONGTEXT",
- "skill_tree_levels", "LONGTEXT",
- "unlocked_items", "LONGTEXT",
- "health", "FLOAT",
- "mana", "FLOAT",
- "stamina", "FLOAT",
- "stellium", "FLOAT"};
-
- @Override
- public void setup() {
-
- // Fully create table
- getDataSource().executeUpdateAsync("CREATE TABLE IF NOT EXISTS mmocore_playerdata(uuid VARCHAR(36)," +
- "class_points INT(11) DEFAULT 0," +
- "skill_points INT(11) DEFAULT 0," +
- "attribute_points INT(11) DEFAULT 0," +
- "attribute_realloc_points INT(11) DEFAULT 0," +
- "skill_reallocation_points INT(11) DEFAULT 0," +
- "skill_tree_reallocation_points INT(11) DEFAULT 0," +
- "skill_tree_points LONGTEXT," +
- "skill_tree_levels LONGTEXT," +
- "level INT(11) DEFAULT 1," +
- "experience DOUBLE PRECISION DEFAULT 0," +
- "class VARCHAR(20)," +
- "guild VARCHAR(20)," +
- "last_login LONG," +
- "attributes LONGTEXT," +
- "professions LONGTEXT," +
- "times_claimed LONGTEXT," +
- "quests LONGTEXT," +
- "waypoints LONGTEXT," +
- "friends LONGTEXT," +
- "skills LONGTEXT," +
- "bound_skills LONGTEXT," +
- "health FLOAT," +
- "mana FLOAT," +
- "stamina FLOAT," +
- "stellium FLOAT," +
- "unlocked_items LONGTEXT," +
- "class_info LONGTEXT," +
- "is_saved TINYINT," +
- "PRIMARY KEY (uuid));");
-
- // Add columns that might not be here by default
- for (int i = 0; i < NEW_COLUMNS.length; i += 2) {
- final String columnName = NEW_COLUMNS[i];
- final String dataType = NEW_COLUMNS[i + 1];
- getDataSource().getResultAsync("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = 'mmocore_playerdata' AND COLUMN_NAME = '" + columnName + "'", result -> {
- try {
- if (!result.next())
- getDataSource().executeUpdate("ALTER TABLE mmocore_playerdata ADD COLUMN " + columnName + " " + dataType);
- } catch (SQLException exception) {
- exception.printStackTrace();
- }
- });
- }
-
- // Modify exp to be a double precision instead
- getDataSource().executeUpdateAsync("ALTER TABLE mmocore_playerdata MODIFY COLUMN experience DOUBLE PRECISION");
- }
-
- @Override
- public MMOCoreDataSynchronizer newDataSynchronizer(PlayerData playerData) {
- return new MMOCoreDataSynchronizer(this, playerData);
- }
-
- @Override
- public void saveData(PlayerData data, boolean autosave) {
- final UUID effectiveId = data.getEffectiveId();
- UtilityMethods.debug(MMOCore.plugin, "SQL", "Saving data for: '" + effectiveId + "'...");
-
- final PlayerDataTableUpdater updater = new PlayerDataTableUpdater(getDataSource(), data);
- updater.addData("class_points", data.getClassPoints());
- updater.addData("skill_points", data.getSkillPoints());
- updater.addData("skill_reallocation_points", data.getSkillReallocationPoints());
- updater.addData("attribute_points", data.getAttributePoints());
- updater.addData("attribute_realloc_points", data.getAttributeReallocationPoints());
- updater.addData("skill_tree_reallocation_points", data.getSkillTreeReallocationPoints());
- updater.addData("health", data.getHealth());
- updater.addData("mana", data.getMana());
- updater.addData("stellium", data.getStellium());
- updater.addData("stamina", data.getStamina());
- updater.addData("level", data.getLevel());
- updater.addData("experience", data.getExperience());
- updater.addData("class", data.getProfess().getId());
- updater.addData("last_login", data.getLastLogin());
- updater.addData("guild", data.hasGuild() ? data.getGuild().getId() : null);
- updater.addJSONArray("waypoints", data.getWaypoints());
- updater.addJSONArray("friends", data.getFriends().stream().map(UUID::toString).collect(Collectors.toList()));
- updater.addJSONObject("bound_skills", data.mapBoundSkills().entrySet());
- updater.addJSONObject("skills", data.mapSkillLevels().entrySet());
- updater.addJSONObject("times_claimed", data.getItemClaims().entrySet());
- updater.addJSONObject("skill_tree_points", data.mapSkillTreePoints().entrySet());
- updater.addJSONObject("skill_tree_levels", data.getNodeLevelsEntrySet());
- updater.addData("attributes", data.getAttributes().toJson().toString());
- updater.addData("professions", data.getCollectionSkills().toJsonString());
- updater.addData("quests", data.getQuestData().toJsonString());
- updater.addData("class_info", createClassInfoData(data).toString());
- updater.addJSONArray("unlocked_items", data.getUnlockedItems());
- if (!autosave)
- updater.addData("is_saved", 1);
-
- updater.executeRequest(autosave);
-
- UtilityMethods.debug(MMOCore.plugin, "SQL", "Saved data for: " + effectiveId);
- UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel()));
- }
-
- private JsonObject createClassInfoData(PlayerData playerData) {
- final JsonObject json = new JsonObject();
- for (String c : playerData.getSavedClasses()) {
- final SavedClassInformation info = playerData.getClassInfo(c);
- JsonObject classinfo = new JsonObject();
- classinfo.addProperty("level", info.getLevel());
- classinfo.addProperty("experience", info.getExperience());
- classinfo.addProperty("skill-points", info.getSkillPoints());
- classinfo.addProperty("attribute-points", info.getAttributePoints());
- classinfo.addProperty("attribute-realloc-points", info.getAttributeReallocationPoints());
- classinfo.addProperty("skill-reallocation-points", info.getSkillReallocationPoints());
- classinfo.addProperty("skill-tree-reallocation-points", info.getSkillTreeReallocationPoints());
- classinfo.addProperty("health", info.getHealth());
- classinfo.addProperty("mana", info.getMana());
- classinfo.addProperty("stamina", info.getStamina());
- classinfo.addProperty("stellium", info.getStellium());
-
- JsonArray array = new JsonArray();
- for (String unlockedItem : playerData.getUnlockedItems()) {
- array.add(unlockedItem);
- }
- classinfo.add("unlocked-items", array);
-
- JsonObject skillinfo = new JsonObject();
- for (String skill : info.getSkillKeys())
- skillinfo.addProperty(skill, info.getSkillLevel(skill));
- classinfo.add("skill", skillinfo);
-
- JsonObject attributeInfo = new JsonObject();
- for (String attribute : info.getAttributeKeys())
- attributeInfo.addProperty(attribute, info.getAttributeLevel(attribute));
- classinfo.add("attribute", attributeInfo);
-
- JsonObject nodeLevelsInfo = new JsonObject();
- for (String node : info.getNodeKeys())
- nodeLevelsInfo.addProperty(node, info.getNodeLevel(node));
- classinfo.add("node-levels", nodeLevelsInfo);
-
- JsonObject skillTreePointsInfo = new JsonObject();
- for (String skillTreeId : info.getSkillTreePointsKeys())
- skillTreePointsInfo.addProperty(skillTreeId, info.getSkillTreePoints(skillTreeId));
- classinfo.add("skill-tree-points", skillTreePointsInfo);
-
- JsonObject boundSkillInfo = new JsonObject();
- for (int slot : info.mapBoundSkills().keySet())
- boundSkillInfo.addProperty(String.valueOf(slot), info.mapBoundSkills().get(slot));
- classinfo.add("bound-skills", boundSkillInfo);
-
- json.add(c, classinfo);
- }
-
- return json;
- }
-
- private boolean isEmpty(@Nullable String str) {
- return str == null || str.equalsIgnoreCase("null") || str.equalsIgnoreCase("{}") || str.equalsIgnoreCase("[]") || str.equalsIgnoreCase("");
- }
-
- @NotNull
- @Override
- public OfflinePlayerData getOffline(UUID uuid) {
- return new SQLOfflinePlayerData(uuid);
- }
-}
-
-
-
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDatabaseImpl.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDatabaseImpl.java
new file mode 100644
index 00000000..af686973
--- /dev/null
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDatabaseImpl.java
@@ -0,0 +1,309 @@
+package net.Indyuce.mmocore.manager.data.sql;
+
+import io.lumine.mythic.lib.MythicLib;
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.data.DataLoadResult;
+import io.lumine.mythic.lib.data.SaveReason;
+import io.lumine.mythic.lib.data.sql.SQLDatabase;
+import io.lumine.mythic.lib.gson.JsonArray;
+import io.lumine.mythic.lib.gson.JsonElement;
+import io.lumine.mythic.lib.gson.JsonObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
+import net.Indyuce.mmocore.api.util.MMOCoreUtils;
+import net.Indyuce.mmocore.guild.provided.Guild;
+import net.Indyuce.mmocore.manager.data.OfflinePlayerData;
+import net.Indyuce.mmocore.skill.ClassSkill;
+import net.Indyuce.mmocore.skilltree.SkillTreeNode;
+import net.Indyuce.mmocore.skilltree.tree.SkillTree;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.stream.Collectors;
+
+public class SQLDatabaseImpl extends SQLDatabase {
+ public static final String UUID_FIELD_NAME = "uuid";
+
+ public SQLDatabaseImpl() {
+ super(MMOCore.plugin, UUID_FIELD_NAME);
+ }
+
+ private static final String[] NEW_COLUMNS = new String[]{
+ "times_claimed", "LONGTEXT",
+ "is_saved", "TINYINT",
+ "skill_reallocation_points", "INT(11)",
+ "skill_tree_reallocation_points", "INT(11)",
+ "skill_tree_points", "LONGTEXT",
+ "skill_tree_levels", "LONGTEXT",
+ "unlocked_items", "LONGTEXT",
+ "health", "FLOAT",
+ "mana", "FLOAT",
+ "stamina", "FLOAT",
+ "stellium", "FLOAT"};
+
+ @Override
+ public void setup() {
+
+ // Fully create table
+ executeUpdate("CREATE TABLE IF NOT EXISTS " + userdataTableName + "("
+ + UUID_FIELD_NAME + " VARCHAR(36)," +
+ "class_points INT(11) DEFAULT 0," +
+ "skill_points INT(11) DEFAULT 0," +
+ "attribute_points INT(11) DEFAULT 0," +
+ "attribute_realloc_points INT(11) DEFAULT 0," +
+ "skill_reallocation_points INT(11) DEFAULT 0," +
+ "skill_tree_reallocation_points INT(11) DEFAULT 0," +
+ "skill_tree_points LONGTEXT," +
+ "skill_tree_levels LONGTEXT," +
+ "level INT(11) DEFAULT 1," +
+ "experience DOUBLE PRECISION DEFAULT 0," +
+ "class VARCHAR(20)," +
+ "guild VARCHAR(20)," +
+ "last_login LONG," +
+ "attributes LONGTEXT," +
+ "professions LONGTEXT," +
+ "times_claimed LONGTEXT," +
+ "quests LONGTEXT," +
+ "waypoints LONGTEXT," +
+ "friends LONGTEXT," +
+ "skills LONGTEXT," +
+ "bound_skills LONGTEXT," +
+ "health FLOAT," +
+ "mana FLOAT," +
+ "stamina FLOAT," +
+ "stellium FLOAT," +
+ "unlocked_items LONGTEXT," +
+ "class_info LONGTEXT," +
+ "is_saved TINYINT," +
+ "PRIMARY KEY (uuid));");
+
+ // Add columns that might not be here by default
+ for (int i = 0; i < NEW_COLUMNS.length; i += 2) {
+ final var columnName = NEW_COLUMNS[i];
+ final var dataType = NEW_COLUMNS[i + 1];
+ executeQuery("SELECT * FROM `information_schema`.`COLUMNS` WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?", result -> {
+ if (!result.next())
+ executeUpdate("ALTER TABLE " + userdataTableName + " ADD COLUMN " + columnName + " " + dataType);
+ }, databaseName, userdataTableName, columnName);
+ }
+
+ // Modify exp to be a double precision instead
+ executeUpdate("ALTER TABLE `" + userdataTableName + "` MODIFY COLUMN experience DOUBLE PRECISION");
+ }
+
+ @Override
+ protected @NotNull DataLoadResult loadDataFromResultSet(@NotNull PlayerData playerData, @NotNull ResultSet result, boolean force) throws SQLException {
+
+ // Reset stats linked to triggers
+ playerData.resetTriggerStats();
+
+ playerData.setClassPoints(result.getInt("class_points"));
+ playerData.setSkillPoints(result.getInt("skill_points"));
+ playerData.setSkillReallocationPoints(result.getInt("skill_reallocation_points"));
+ playerData.setSkillTreeReallocationPoints(result.getInt("skill_tree_reallocation_points"));
+ playerData.setAttributePoints(result.getInt("attribute_points"));
+ playerData.setAttributeReallocationPoints(result.getInt("attribute_realloc_points"));
+ playerData.setLevel(result.getInt("level"), PlayerLevelChangeEvent.Reason.CHOOSE_PROFILE);
+ playerData.setExperience(result.getDouble("experience"));
+
+ if (!isEmpty(result.getString("class")))
+ playerData.setClass(MMOCore.plugin.classManager.get(result.getString("class")));
+
+ if (!isEmpty(result.getString("times_claimed"))) {
+ JsonObject json = MythicLib.plugin.getGson().fromJson(result.getString("times_claimed"), JsonObject.class);
+ json.entrySet().forEach(entry -> playerData.getItemClaims().put(entry.getKey(), entry.getValue().getAsInt()));
+ }
+ if (!isEmpty(result.getString("skill_tree_points"))) {
+ JsonObject json = MythicLib.plugin.getGson().fromJson(result.getString("skill_tree_points"), JsonObject.class);
+ for (SkillTree skillTree : MMOCore.plugin.skillTreeManager.getAll()) {
+ playerData.setSkillTreePoints(skillTree.getId(), json.has(skillTree.getId()) ? json.get(skillTree.getId()).getAsInt() : 0);
+ }
+ playerData.setSkillTreePoints("global", json.has("global") ? json.get("global").getAsInt() : 0);
+ }
+
+ if (!isEmpty(result.getString("skill_tree_levels"))) {
+ JsonObject json = MythicLib.plugin.getGson().fromJson(result.getString("skill_tree_levels"), JsonObject.class);
+ for (SkillTreeNode skillTreeNode : MMOCore.plugin.skillTreeManager.getAllNodes()) {
+ playerData.setNodeLevel(skillTreeNode, json.has(skillTreeNode.getFullId()) ? json.get(skillTreeNode.getFullId()).getAsInt() : 0);
+ }
+ }
+ Set unlockedItems = new HashSet<>();
+ if (!isEmpty(result.getString("unlocked_items"))) {
+ JsonArray unlockedItemsArray = MythicLib.plugin.getGson().fromJson(result.getString("unlocked_items"), JsonArray.class);
+ for (JsonElement item : unlockedItemsArray)
+ unlockedItems.add(item.getAsString());
+ }
+ playerData.setUnlockedItems(unlockedItems);
+ if (!isEmpty(result.getString("guild"))) {
+ final Guild guild = MMOCore.plugin.nativeGuildManager.getGuild(result.getString("guild"));
+ if (guild != null && guild.hasMember(playerData.getUniqueId())) playerData.setGuild(guild);
+ }
+ if (!isEmpty(result.getString("attributes"))) playerData.getAttributes().load(result.getString("attributes"));
+ if (playerData.isOnline())
+ MMOCore.plugin.attributeManager.getAll().forEach(attribute -> playerData.getAttributes().getInstance(attribute).updateStats());
+ if (!isEmpty(result.getString("professions")))
+ playerData.getCollectionSkills().load(result.getString("professions"));
+ if (!isEmpty(result.getString("quests"))) playerData.getQuestData().load(result.getString("quests"));
+ playerData.getQuestData().updateBossBar();
+ if (!isEmpty(result.getString("waypoints")))
+ playerData.getWaypoints().addAll(MMOCoreUtils.jsonArrayToList(result.getString("waypoints")));
+ if (!isEmpty(result.getString("friends")))
+ MMOCoreUtils.jsonArrayToList(result.getString("friends")).forEach(str -> playerData.getFriends().add(UUID.fromString(str)));
+ if (!isEmpty(result.getString("skills"))) {
+ JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("skills"), JsonObject.class);
+ for (Map.Entry entry : object.entrySet())
+ playerData.setSkillLevel(entry.getKey(), entry.getValue().getAsInt());
+ }
+ if (!isEmpty(result.getString("bound_skills"))) {
+ JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("bound_skills"), JsonObject.class);
+ for (Map.Entry entry : object.entrySet()) {
+ ClassSkill skill = playerData.getProfess().getSkill(entry.getValue().getAsString());
+ if (skill != null) playerData.bindSkill(Integer.parseInt(entry.getKey()), skill);
+ }
+ }
+ if (!isEmpty(result.getString("class_info"))) {
+ JsonObject object = MythicLib.plugin.getGson().fromJson(result.getString("class_info"), JsonObject.class);
+ for (Map.Entry entry : object.entrySet()) {
+ try {
+ PlayerClass profess = MMOCore.plugin.classManager.get(entry.getKey());
+ Validate.notNull(profess, "Could not find class '" + entry.getKey() + "'");
+ playerData.applyClassInfo(profess, new SavedClassInformation(entry.getValue().getAsJsonObject()));
+ } catch (IllegalArgumentException exception) {
+ MMOCore.log(Level.WARNING, "Could not load class info '" + entry.getKey() + "': " + exception.getMessage());
+ }
+ }
+ }
+
+ /*
+ * These should be loaded after to make sure that the
+ * MAX_MANA, MAX_STAMINA & MAX_STELLIUM stats are already loaded.
+ */
+ playerData.loadResources(result.getDouble("health"), result.getDouble("mana"), result.getDouble("stamina"), result.getDouble("stellium"));
+
+ UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", playerData.getProfess().getId(), playerData.getLevel()));
+ return new DataLoadResult(DataLoadResult.Type.SUCCESS, false, force);
+ }
+
+ @Override
+ public void saveData(PlayerData data, @NotNull SaveReason saveReason) {
+ final UUID effectiveId = data.getEffectiveId();
+ UtilityMethods.debug(MMOCore.plugin, "SQL", "Saving data for: '" + effectiveId + "'...");
+
+ final PlayerDataTableUpdater updater = new PlayerDataTableUpdater(this, data);
+ updater.addData("class_points", data.getClassPoints());
+ updater.addData("skill_points", data.getSkillPoints());
+ updater.addData("skill_reallocation_points", data.getSkillReallocationPoints());
+ updater.addData("attribute_points", data.getAttributePoints());
+ updater.addData("attribute_realloc_points", data.getAttributeReallocationPoints());
+ updater.addData("skill_tree_reallocation_points", data.getSkillTreeReallocationPoints());
+ updater.addData("health", data.getLastHealth());
+ updater.addData("mana", data.getMana());
+ updater.addData("stellium", data.getStellium());
+ updater.addData("stamina", data.getStamina());
+ updater.addData("level", data.getLevel());
+ updater.addData("experience", data.getExperience());
+ updater.addData("class", data.getProfess().getId());
+ updater.addData("last_login", data.getLastLogin());
+ updater.addData("guild", data.hasGuild() ? data.getGuild().getId() : null);
+ updater.addJSONArray("waypoints", data.getWaypoints());
+ updater.addJSONArray("friends", data.getFriends().stream().map(UUID::toString).collect(Collectors.toList()));
+ updater.addJSONObject("bound_skills", data.mapBoundSkills().entrySet());
+ updater.addJSONObject("skills", data.mapSkillLevels().entrySet());
+ updater.addJSONObject("times_claimed", data.getItemClaims().entrySet());
+ updater.addJSONObject("skill_tree_points", data.mapSkillTreePoints().entrySet());
+ updater.addJSONObject("skill_tree_levels", data.getNodeLevelsEntrySet());
+ updater.addData("attributes", data.getAttributes().toJson().toString());
+ updater.addData("professions", data.getCollectionSkills().toJsonString());
+ updater.addData("quests", data.getQuestData().toJsonString());
+ updater.addData("class_info", createClassInfoData(data).toString());
+ updater.addJSONArray("unlocked_items", data.getUnlockedItems());
+ if (saveReason != SaveReason.AUTOSAVE) updater.addData("is_saved", 1);
+
+ updater.executeRequest(saveReason);
+
+ UtilityMethods.debug(MMOCore.plugin, "SQL", "Saved data for: " + effectiveId);
+ UtilityMethods.debug(MMOCore.plugin, "SQL", String.format("{ class: %s, level: %d }", data.getProfess().getId(), data.getLevel()));
+ }
+
+ private JsonObject createClassInfoData(PlayerData playerData) {
+ final JsonObject json = new JsonObject();
+ for (String c : playerData.getSavedClasses()) {
+ final SavedClassInformation info = playerData.getClassInfo(c);
+ JsonObject classinfo = new JsonObject();
+ classinfo.addProperty("level", info.getLevel());
+ classinfo.addProperty("experience", info.getExperience());
+ classinfo.addProperty("skill-points", info.getSkillPoints());
+ classinfo.addProperty("attribute-points", info.getAttributePoints());
+ classinfo.addProperty("attribute-realloc-points", info.getAttributeReallocationPoints());
+ classinfo.addProperty("skill-reallocation-points", info.getSkillReallocationPoints());
+ classinfo.addProperty("skill-tree-reallocation-points", info.getSkillTreeReallocationPoints());
+ classinfo.addProperty("health", info.getLastHealth());
+ classinfo.addProperty("mana", info.getMana());
+ classinfo.addProperty("stamina", info.getStamina());
+ classinfo.addProperty("stellium", info.getStellium());
+
+ JsonArray array = new JsonArray();
+ for (String unlockedItem : playerData.getUnlockedItems()) {
+ array.add(unlockedItem);
+ }
+ classinfo.add("unlocked-items", array);
+
+ JsonObject skillinfo = new JsonObject();
+ for (String skill : info.getSkillKeys())
+ skillinfo.addProperty(skill, info.getSkillLevel(skill));
+ classinfo.add("skill", skillinfo);
+
+ JsonObject attributeInfo = new JsonObject();
+ for (String attribute : info.getAttributeKeys())
+ attributeInfo.addProperty(attribute, info.getAttributeLevel(attribute));
+ classinfo.add("attribute", attributeInfo);
+
+ JsonObject nodeLevelsInfo = new JsonObject();
+ for (String node : info.getNodeKeys())
+ nodeLevelsInfo.addProperty(node, info.getNodeLevel(node));
+ classinfo.add("node-levels", nodeLevelsInfo);
+
+ JsonObject skillTreePointsInfo = new JsonObject();
+ for (String skillTreeId : info.getSkillTreePointsKeys())
+ skillTreePointsInfo.addProperty(skillTreeId, info.getSkillTreePoints(skillTreeId));
+ classinfo.add("skill-tree-points", skillTreePointsInfo);
+
+ JsonObject boundSkillInfo = new JsonObject();
+ for (int slot : info.mapBoundSkills().keySet())
+ boundSkillInfo.addProperty(String.valueOf(slot), info.mapBoundSkills().get(slot));
+ classinfo.add("bound-skills", boundSkillInfo);
+
+ json.add(c, classinfo);
+ }
+
+ return json;
+ }
+
+ private boolean isEmpty(@Nullable String str) {
+ return str == null
+ || str.isEmpty()
+ || str.equalsIgnoreCase("null")
+ || str.equalsIgnoreCase("{}")
+ || str.equalsIgnoreCase("[]");
+ }
+
+ @NotNull
+ @Override
+ public OfflinePlayerData getOffline(UUID uuid) {
+ return new SQLOfflinePlayerData(uuid);
+ }
+}
+
+
+
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java
index 0dd2ae9c..44edf6a7 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLOfflinePlayerData.java
@@ -22,7 +22,7 @@ public class SQLOfflinePlayerData implements OfflinePlayerData {
public SQLOfflinePlayerData(UUID uuid) {
this.uuid = uuid;
/*
- provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + uuid + "';", (result) -> {
+ provider.getResult("SELECT * FROM "+DATA_TABLE_NAME+" WHERE uuid = '" + uuid + "';", (result) -> {
try {
MythicLib.debug("MMOCoreSQL", "Loading OFFLINE data for '" + uuid + "'.");
if (!result.next()) {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDatabaseImpl.java
similarity index 89%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDatabaseImpl.java
index 23dba480..58da095b 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataHandler.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLDatabaseImpl.java
@@ -1,7 +1,10 @@
package net.Indyuce.mmocore.manager.data.yaml;
-import io.lumine.mythic.lib.data.yaml.YAMLSynchronizedDataHandler;
+import io.lumine.mythic.lib.data.DataLoadResult;
+import io.lumine.mythic.lib.data.yaml.YAMLFlatDatabase;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
@@ -10,9 +13,7 @@ import net.Indyuce.mmocore.manager.data.OfflinePlayerData;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -20,9 +21,9 @@ import java.util.UUID;
import java.util.logging.Level;
import java.util.stream.Collectors;
-public class YAMLPlayerDataHandler extends YAMLSynchronizedDataHandler {
- public YAMLPlayerDataHandler(Plugin owning) {
- super(owning);
+public class YAMLDatabaseImpl extends YAMLFlatDatabase {
+ public YAMLDatabaseImpl() {
+ super(MMOCore.plugin);
}
@Override
@@ -36,15 +37,15 @@ public class YAMLPlayerDataHandler extends YAMLSynchronizedDataHandler map = new HashMap<>();
+ /**
+ * Registered block infos
+ */
+ private final Map map = new HashMap<>();
- /**
- * Blocks that are regenerating and that must be refreshed whenever the
- * server reloads or shuts down not to hurt the world map
- */
- private final Set active = new HashSet<>();
+ /**
+ * Blocks that are regenerating and that must be refreshed whenever the
+ * server reloads or shuts down not to hurt the world map
+ */
+ private final Set active = new HashSet<>();
- /**
- * Stores conditions which must be met to apply custom mining
- */
- private final List customMineConditions = new ArrayList<>();
+ /**
+ * Stores conditions which must be met to apply custom mining
+ */
+ private final List customMineConditions = new ArrayList<>();
- /**
- * List of functions which let MMOCore recognize what block a player is
- * currently breaking
- */
- private final List>> blockTypes = new ArrayList<>();
+ /**
+ * List of functions which let MMOCore recognize what block a player is
+ * currently breaking
+ */
+ private final List>> blockTypes = new ArrayList<>();
- private boolean enabled, protectVanillaBlocks, enableToolRestrictions;
+ private boolean enabled, protectVanillaBlocks, enableToolRestrictions;
- public CustomBlockManager() {
- super("on-mine");
+ public CustomBlockManager() {
+ super("on-mine");
- registerBlockType(block -> MMOCoreUtils.isPlayerHead(block.getType()) ? Optional.of(new SkullBlockType(block)) : Optional.empty());
- }
+ registerBlockType(block -> MMOCoreUtils.isPlayerHead(block.getType()) ? Optional.of(new SkullBlockType(block)) : Optional.empty());
+ registerBlockType(block -> block.getType() == Material.NOTE_BLOCK ? Optional.of(new NoteBlockType(block)) : Optional.empty());
+ registerBlockType(block -> isMushroom(block.getType()) ? Optional.of(new MushroomBlockType(block)) : Optional.empty());
+ }
- public void registerBlockType(Function> function) {
- blockTypes.add(function);
- }
+ private static boolean isMushroom(Material material) {
+ return material == Material.MUSHROOM_STEM
+ || material == Material.BROWN_MUSHROOM_BLOCK
+ || material == Material.RED_MUSHROOM_BLOCK;
+ }
- public void register(@NotNull BlockInfo regen) {
- map.put(regen.getBlock(), regen);
- }
+ public void registerBlockType(Function> function) {
+ blockTypes.add(function);
+ }
- /**
- * Checks if the behaviour of a block was changed by a specific profession
- * (different drop tables, block regen..)
+ public void register(@NotNull BlockInfo regen) {
+ map.put(regen.getBlock(), regen);
+ }
+
+ /**
+ * Checks if the behaviour of a block was changed by a specific profession
+ * (different drop tables, block regen..)
*
- * @param block Block to check
+ * @param block Block to check
* @return The new block behaviour or null if no new behaviour
*/
@Nullable
@@ -85,72 +91,72 @@ public class CustomBlockManager extends SpecificProfessionManager {
return new VanillaBlockType(block);
}
- /**
- * Used when a block is being broken and MMOCore needs to regen it after X
- * seconds. Also places the temporary block at the block location
- *
- * @param info Block info
- * @param scheduleRegen If block regeneration should be scheduled or not. If
- * the block broken is a temporary block and is part of
- * a "block chain", no regen should be scheduled as
- * there is already one
- */
- public void initialize(BlockInfo.RegeneratingBlock info, boolean scheduleRegen) {
- if (scheduleRegen) {
- active.add(info);
- Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> regen(info, false), info.getRegeneratingBlock().getRegenerationInfo().getTime());
- }
+ /**
+ * Used when a block is being broken and MMOCore needs to regen it after X
+ * seconds. Also places the temporary block at the block location
+ *
+ * @param info Block info
+ * @param scheduleRegen If block regeneration should be scheduled or not. If
+ * the block broken is a temporary block and is part of
+ * a "block chain", no regen should be scheduled as
+ * there is already one
+ */
+ public void initialize(BlockInfo.RegeneratingBlock info, boolean scheduleRegen) {
+ if (scheduleRegen) {
+ active.add(info);
+ Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> regen(info, false), info.getRegeneratingBlock().getRegenerationInfo().getTime());
+ }
- if (info.getRegeneratingBlock().getRegenerationInfo().hasTemporaryBlock())
- info.getRegeneratingBlock().getRegenerationInfo().getTemporaryBlock().place(info);
- }
+ if (info.getRegeneratingBlock().getRegenerationInfo().hasTemporaryBlock())
+ info.getRegeneratingBlock().getRegenerationInfo().getTemporaryBlock().place(info);
+ }
- /**
- * Called when a block regens, either due to regen timer or because the
- * server shuts down.
- *
- * @param info Block which must be regened
- * @param shutdown Must be set to true if the server is shutting down. When
- * the server shuts down, it iterates through active blocks.
- * This prevents any issue when editing lists being iterated
- */
- private void regen(BlockInfo.RegeneratingBlock info, boolean shutdown) {
+ /**
+ * Called when a block regens, either due to regen timer or because the
+ * server shuts down.
+ *
+ * @param info Block which must be regened
+ * @param shutdown Must be set to true if the server is shutting down. When
+ * the server shuts down, it iterates through active blocks.
+ * This prevents any issue when editing lists being iterated
+ */
+ private void regen(BlockInfo.RegeneratingBlock info, boolean shutdown) {
- // Get the chunk and load it async if needed.
- PaperLib.getChunkAtAsync(info.getLocation()).whenComplete((chunk, ex) -> {
- info.getRegeneratingBlock().getBlock().regenerate(info);
- info.getLocation().getBlock().getState().update();
- if (!shutdown)
- active.remove(info);
- });
- }
+ // Get the chunk and load it async if needed.
+ PaperLib.getChunkAtAsync(info.getLocation()).whenComplete((chunk, ex) -> {
+ info.getRegeneratingBlock().getBlock().regenerate(info);
+ info.getLocation().getBlock().getState().update();
+ if (!shutdown)
+ active.remove(info);
+ });
+ }
- /**
- * Called when the server disables so every mined block which was in timer
- * are reset and put back in place.
- */
- public void resetRemainingBlocks() {
- active.forEach(info -> regen(info, true));
- }
+ /**
+ * Called when the server disables so every mined block which was in timer
+ * are reset and put back in place.
+ */
+ public void resetRemainingBlocks() {
+ active.forEach(info -> regen(info, true));
+ }
- /**
- * @param block Potentially vanilla block being broken by a player
- * @return Returns if the block being broken is a temporary block. If
- * it is, players should not be able to break it
- */
- public boolean isTemporaryBlock(Block block) {
- Location loc = block.getLocation();
- for (BlockInfo.RegeneratingBlock info : active)
- if (info.getLocation().getBlockX() == loc.getBlockX() && info.getLocation().getBlockY() == loc.getBlockY()
- && info.getLocation().getBlockZ() == loc.getBlockZ())
- return true;
+ /**
+ * @param block Potentially vanilla block being broken by a player
+ * @return Returns if the block being broken is a temporary block. If
+ * it is, players should not be able to break it
+ */
+ public boolean isTemporaryBlock(Block block) {
+ Location loc = block.getLocation();
+ for (BlockInfo.RegeneratingBlock info : active)
+ if (info.getLocation().getBlockX() == loc.getBlockX() && info.getLocation().getBlockY() == loc.getBlockY()
+ && info.getLocation().getBlockZ() == loc.getBlockZ())
+ return true;
- return false;
- }
+ return false;
+ }
- public boolean isEnabled(Entity entity) {
- return isEnabled(entity, entity.getLocation());
- }
+ public boolean isEnabled(Entity entity) {
+ return isEnabled(entity, entity.getLocation());
+ }
public boolean isEnabled(Entity entity, Location loc) {
@@ -170,28 +176,28 @@ public class CustomBlockManager extends SpecificProfessionManager {
@Override
public void loadProfessionConfiguration(ConfigurationSection config) {
- for (String key : config.getKeys(false))
- try {
- register(new BlockInfo(config.getConfigurationSection(key)));
- } catch (IllegalArgumentException exception) {
- MMOCore.log(Level.WARNING, "Could not load custom block '" + key + "': " + exception.getMessage());
- }
- }
+ for (String key : config.getKeys(false))
+ try {
+ register(new BlockInfo(config.getConfigurationSection(key)));
+ } catch (IllegalArgumentException exception) {
+ MMOCore.log(Level.WARNING, "Could not load custom block '" + key + "': " + exception.getMessage());
+ }
+ }
- public boolean protectVanillaBlocks() {
- return protectVanillaBlocks;
- }
+ public boolean protectVanillaBlocks() {
+ return protectVanillaBlocks;
+ }
public boolean hasToolRestrictions() {
return enableToolRestrictions;
}
- @Override
- public void initialize(boolean clearBefore) {
- if (clearBefore) {
- customMineConditions.clear();
- map.clear();
- }
+ @Override
+ public void initialize(boolean clearBefore) {
+ if (clearBefore) {
+ customMineConditions.clear();
+ map.clear();
+ }
final var config = MMOCore.plugin.getConfig().getConfigurationSection("custom-mining");
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ExperienceSourceManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ExperienceSourceManager.java
index f08b02f3..038419e4 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ExperienceSourceManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ExperienceSourceManager.java
@@ -1,9 +1,9 @@
package net.Indyuce.mmocore.manager.profession;
import io.lumine.mythic.lib.util.Closeable;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java
index 4c8b1e26..fa5841a2 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java
@@ -1,13 +1,13 @@
package net.Indyuce.mmocore.manager.profession;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.loot.RandomWeightedRoll;
import net.Indyuce.mmocore.loot.chest.condition.Condition;
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
import net.Indyuce.mmocore.loot.fishing.FishingDropItem;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Player;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ProfessionManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ProfessionManager.java
index 4cc56524..a2511adc 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ProfessionManager.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/profession/ProfessionManager.java
@@ -1,12 +1,13 @@
package net.Indyuce.mmocore.manager.profession;
import io.lumine.mythic.lib.util.FileUtils;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.manager.MMOCoreManager;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.logging.Level;
@@ -40,6 +41,7 @@ public class ProfessionManager implements MMOCoreManager {
}
}
+ @Nullable
public Profession get(String id) {
return professions.get(id);
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/registry/MMOCoreRegister.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/registry/MMOCoreRegister.java
index 68b8bae8..b15bfe5e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/registry/MMOCoreRegister.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/registry/MMOCoreRegister.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.manager.registry;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.manager.MMOCoreManager;
-import org.apache.commons.lang.Validate;
import java.util.Collection;
import java.util.HashMap;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/MythicDungeonsPartyModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/MythicDungeonsPartyModule.java
index de59bd3c..f7e4dcae 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/MythicDungeonsPartyModule.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/MythicDungeonsPartyModule.java
@@ -1,11 +1,11 @@
package net.Indyuce.mmocore.party.compat;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.party.AbstractParty;
import net.Indyuce.mmocore.party.PartyModule;
import net.playavalon.mythicdungeons.api.MythicDungeonsService;
import net.playavalon.mythicdungeons.player.party.partysystem.MythicParty;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/PartiesPartyModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/PartiesPartyModule.java
index e66b78b7..c3de3ff6 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/PartiesPartyModule.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/compat/PartiesPartyModule.java
@@ -37,9 +37,14 @@ public class PartiesPartyModule implements PartyModule, Listener {
@EventHandler
public void onPlayerJoin(BukkitPartiesPlayerPostJoinEvent event) {
- int membersSize = event.getParty().getMembers().size();
- event.getParty().getOnlineMembers()
- .forEach(p -> PartyUtils.updateStatBonuses(PlayerData.get(p.getPlayerUUID()), membersSize));
+ // !!! async event !!!
+ Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
+ final var memberCount = event.getParty().getMembers().size();
+ event.getParty().getOnlineMembers().forEach(member -> {
+ final var playerData = PlayerData.get(member.getPlayerUUID());
+ PartyUtils.updateStatBonuses(playerData, memberCount);
+ });
+ });
}
@EventHandler
@@ -52,8 +57,7 @@ public class PartiesPartyModule implements PartyModule, Listener {
PartyUtils.clearStatBonuses(event.getPartyPlayer().getPlayerUUID());
// Update stats for online members
- event.getParty().getOnlineMembers()
- .forEach(p -> PartyUtils.updateStatBonuses(PlayerData.get(p.getPlayerUUID()), memberCount));
+ event.getParty().getOnlineMembers().forEach(p -> PartyUtils.updateStatBonuses(PlayerData.get(p.getPlayerUUID()), memberCount));
}
private static class CustomParty implements AbstractParty {
@@ -66,8 +70,7 @@ public class PartiesPartyModule implements PartyModule, Listener {
@Override
public boolean hasMember(Player player) {
for (PartyPlayer member : party.getOnlineMembers())
- if (member.getPlayerUUID().equals(player.getUniqueId()))
- return true;
+ if (member.getPlayerUUID().equals(player.getUniqueId())) return true;
return false;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/provided/MMOCorePartyModule.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/provided/MMOCorePartyModule.java
index eded7965..a1277d5e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/provided/MMOCorePartyModule.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/party/provided/MMOCorePartyModule.java
@@ -1,12 +1,12 @@
package net.Indyuce.mmocore.party.provided;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.social.PartyChatEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.party.AbstractParty;
import net.Indyuce.mmocore.party.PartyModule;
import net.Indyuce.mmocore.player.Message;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -68,13 +68,14 @@ public class MMOCorePartyModule implements PartyModule, Listener {
event.setCancelled(true);
- // Running it in a delayed task is recommended
+ // Run it on main server thread
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
- var rawMessage = event.getMessage().substring(MMOCore.plugin.configManager.partyChatPrefix.length());
- var message = Message.PARTY_CHAT.prepare("player", data.getPlayer().getName(), "message", rawMessage);
- var called = new PartyChatEvent(party, data, message.getRawContent());
+ final var rawMessage = event.getMessage().substring(MMOCore.plugin.configManager.partyChatPrefix.length());
+ final var called = new PartyChatEvent(party, data, rawMessage);
Bukkit.getPluginManager().callEvent(called);
- if (!called.isCancelled()) party.getOnlineMembers().forEach(member -> message.send(member.getPlayer()));
+ if (called.isCancelled() || called.getMessage() == null) return;
+
+ party.getOnlineMembers().forEach(member -> Message.PARTY_CHAT.send(member.getPlayer(), "player", data.getPlayer().getName(), "message", called.getMessage()));
});
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/ClassDataContainer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/ClassDataContainer.java
index 6b5405d8..bc9b1d6d 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/ClassDataContainer.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/ClassDataContainer.java
@@ -25,7 +25,7 @@ public interface ClassDataContainer {
int getSkillTreeReallocationPoints();
- double getHealth();
+ double getLastHealth();
double getMana();
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java
index 540108f0..79843eb6 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/CombatHandler.java
@@ -1,11 +1,10 @@
package net.Indyuce.mmocore.player;
import io.lumine.mythic.lib.util.Closeable;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.PlayerCombatEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.command.PvpModeCommand;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
@@ -20,6 +19,8 @@ public class CombatHandler implements Closeable {
@Nullable
private BukkitTask task;
+ public static final String COOLDOWN_KEY = "PvpMode";
+
public CombatHandler(PlayerData player) {
this.player = player;
}
@@ -27,7 +28,7 @@ public class CombatHandler implements Closeable {
public void update() {
lastHit = System.currentTimeMillis();
invulnerableTill = 0;
- player.getMMOPlayerData().getCooldownMap().applyCooldown(PvpModeCommand.COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeCombatCooldown);
+ player.getMMOPlayerData().getCooldownMap().applyCooldown(COOLDOWN_KEY, MMOCore.plugin.configManager.pvpModeCombatCooldown);
// Simply refreshing
if (isInCombat()) {
@@ -120,6 +121,6 @@ public class CombatHandler implements Closeable {
// Necessary steps when entering a town.
lastHit = 0;
invulnerableTill = 0;
- player.getMMOPlayerData().getCooldownMap().resetCooldown(PvpModeCommand.COOLDOWN_KEY);
+ player.getMMOPlayerData().getCooldownMap().resetCooldown(COOLDOWN_KEY);
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/DefaultPlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/DefaultPlayerData.java
index 32880789..0ddffcc0 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/DefaultPlayerData.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/DefaultPlayerData.java
@@ -1,8 +1,9 @@
package net.Indyuce.mmocore.player;
-import io.lumine.mythic.lib.version.Attributes;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.configuration.ConfigurationSection;
+import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.HashSet;
@@ -53,7 +54,7 @@ public class DefaultPlayerData implements ClassDataContainer {
}
@Override
- public double getHealth() {
+ public double getLastHealth() {
return health;
}
@@ -136,8 +137,13 @@ public class DefaultPlayerData implements ClassDataContainer {
return new HashMap<>();
}
- public void apply(PlayerData player) {
- player.setLevel(level);
+ @Deprecated
+ public void apply(PlayerData playerData) {
+ this.apply(playerData, PlayerLevelChangeEvent.Reason.UNKNOWN);
+ }
+
+ public void apply(@NotNull PlayerData player, @NotNull PlayerLevelChangeEvent.Reason reason) {
+ player.setLevel(level, reason);
player.setExperience(0);
player.setClassPoints(classPoints);
player.setSkillPoints(skillPoints);
@@ -145,10 +151,6 @@ public class DefaultPlayerData implements ClassDataContainer {
player.setAttributeReallocationPoints(attrReallocPoints);
player.setSkillTreeReallocationPoints(skillTreeReallocPoints);
player.setSkillReallocationPoints(skillReallocPoints);
- if (player.isOnline())
- player.getPlayer().setHealth(Math.min(health, player.getPlayer().getAttribute(Attributes.MAX_HEALTH).getValue()));
- player.setMana(mana);
- player.setStamina(stamina);
- player.setStellium(stellium);
+ player.loadResources(health, mana, stamina, stellium);
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/Message.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/Message.java
index cefd200e..7a78647c 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/Message.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/player/Message.java
@@ -2,7 +2,6 @@ package net.Indyuce.mmocore.player;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.message.PlayerMessage;
-import io.lumine.mythic.lib.message.ReadyMessage;
import io.lumine.mythic.lib.message.type.EmptyMessage;
import io.lumine.mythic.lib.util.config.YamlFile;
import io.lumine.mythic.lib.util.config.YamlUtils;
@@ -31,6 +30,7 @@ public enum Message {
GUILD_IS_FULL,
GUILD_KICK_PLAYER("kick-from-guild"),
GUILD_JOINED_OTHER,
+ GUILD_NO_PENDING_INVITE,
ALREADY_IN_GUILD,
SENT_GUILD_INVITE,
GUILD_FAIL_CREATION_INVALID_CHARS("fail-guild-creation.invalid-characters"),
@@ -64,6 +64,7 @@ public enum Message {
// Friends
FRIEND_REQUEST,
FRIEND_REQUEST_COOLDOWN,
+ FRIEND_NO_PENDING_INVITE,
FRIEND_NOT_ONLINE_PLAYER("not-online-player"),
FRIEND_CANT_FRIEND_YOURSELF("cant-request-to-yourself"),
FRIEND_SENT_REQUEST("sent-friend-request"),
@@ -80,6 +81,7 @@ public enum Message {
PARTY_CREATED,
PARTY_TRANSFER_OWNERSHIP("transfer-party-ownership"),
PARTY_IS_FULL,
+ PARTY_NO_PENDING_INVITE,
PARTY_NOT_ONLINE_PLAYER("not-online-player"),
PARTY_INVITE_COOLDOWN,
PARTY_LEAVE,
@@ -142,6 +144,7 @@ public enum Message {
// Skill trees
NO_SKILL_TREE,
+ NO_CLASS_SKILL_TREE,
NO_SKILL_TREE_POINTS_SPENT,
NOT_SKILL_TREE_REALLOCATION_POINT,
SKILL_TREE_SWITCH,
@@ -204,14 +207,8 @@ public enum Message {
this.candidates = array;
}
- @NotNull
- public ReadyMessage prepare(@NotNull Object... placeholders) {
- return this.wrapped.prepare(null, placeholders);
- }
-
public void send(@NotNull Iterable players, @NotNull Object... placeholders) {
- final var message = this.wrapped.prepare(null, placeholders);
- for (var player : players) message.send(player);
+ for (var player : players) this.send(player, placeholders);
}
public void send(@NotNull Player player, @NotNull Object... placeholders) {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ExperienceMechanic.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ExperienceMechanic.java
index 6382fac3..5b70d6d8 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ExperienceMechanic.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ExperienceMechanic.java
@@ -4,23 +4,20 @@ import io.lumine.mythic.lib.script.mechanic.type.TargetMechanic;
import io.lumine.mythic.lib.skill.SkillMetadata;
import io.lumine.mythic.lib.util.DoubleFormula;
import io.lumine.mythic.lib.util.configobject.ConfigObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.EXPSource;
-import net.Indyuce.mmocore.experience.SimpleExperienceObject;
-import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
-import org.apache.commons.lang.Validate;
+import net.Indyuce.mmocore.experience.Profession;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
public class ExperienceMechanic extends TargetMechanic {
- @NotNull
private final DoubleFormula amount;
- @NotNull
private final EXPSource source;
- @NotNull
- private final ExperienceDispenser dispenser;
+ @Nullable
+ private final Profession profession;
public ExperienceMechanic(ConfigObject config) {
super(config);
@@ -31,9 +28,8 @@ public class ExperienceMechanic extends TargetMechanic {
if (config.contains("profession")) {
String id = config.getString("profession").toLowerCase().replace("_", "-");
Validate.isTrue(MMOCore.plugin.professionManager.has(id), "Could not find profession");
- dispenser = MMOCore.plugin.professionManager.get(id);
- } else
- dispenser = new SimpleExperienceObject();
+ profession = MMOCore.plugin.professionManager.get(id);
+ } else profession = null;
source = config.contains("source") ? EXPSource.valueOf(config.getString("source").toUpperCase()) : EXPSource.QUEST;
}
@@ -41,6 +37,8 @@ public class ExperienceMechanic extends TargetMechanic {
public void cast(SkillMetadata meta, Entity target) {
Validate.isTrue(target instanceof Player, "Target is not a player");
PlayerData targetData = PlayerData.get(target.getUniqueId());
- dispenser.giveExperience(targetData, amount.evaluate(meta), null, source);
+
+ if (profession != null) profession.giveExperience(targetData, amount.evaluate(meta), null, source);
+ else targetData.getProfess().giveExperience(targetData, amount.evaluate(meta), null, source);
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ManaMechanic.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ManaMechanic.java
index a58010c3..f92eea26 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ManaMechanic.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/ManaMechanic.java
@@ -5,9 +5,9 @@ import io.lumine.mythic.lib.script.mechanic.type.TargetMechanic;
import io.lumine.mythic.lib.skill.SkillMetadata;
import io.lumine.mythic.lib.util.DoubleFormula;
import io.lumine.mythic.lib.util.configobject.ConfigObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -30,11 +30,8 @@ public class ManaMechanic extends TargetMechanic {
public void cast(SkillMetadata meta, Entity target) {
Validate.isTrue(target instanceof Player, "Target is not a player");
PlayerData targetData = PlayerData.get(target.getUniqueId());
- if (operation == Operation.GIVE)
- targetData.giveMana(amount.evaluate(meta), reason);
- else if (operation == Operation.SET)
- targetData.setMana(amount.evaluate(meta));
- else if (operation == Operation.TAKE)
- targetData.giveMana(-amount.evaluate(meta), reason);
+ if (operation == Operation.GIVE) targetData.giveMana(amount.evaluate(meta), reason);
+ else if (operation == Operation.SET) targetData.setMana(amount.evaluate(meta), reason);
+ else if (operation == Operation.TAKE) targetData.giveMana(-amount.evaluate(meta), reason);
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StaminaMechanic.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StaminaMechanic.java
index 4ec84bac..3cd1459e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StaminaMechanic.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StaminaMechanic.java
@@ -5,9 +5,9 @@ import io.lumine.mythic.lib.script.mechanic.type.TargetMechanic;
import io.lumine.mythic.lib.skill.SkillMetadata;
import io.lumine.mythic.lib.util.DoubleFormula;
import io.lumine.mythic.lib.util.configobject.ConfigObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -30,11 +30,8 @@ public class StaminaMechanic extends TargetMechanic {
public void cast(SkillMetadata meta, Entity target) {
Validate.isTrue(target instanceof Player, "Target is not a player");
PlayerData targetData = PlayerData.get(target.getUniqueId());
- if (operation == Operation.GIVE)
- targetData.giveStamina(amount.evaluate(meta), reason);
- else if (operation == Operation.SET)
- targetData.setStamina(amount.evaluate(meta));
- else if (operation == Operation.TAKE)
- targetData.giveStamina(-amount.evaluate(meta), reason);
+ if (operation == Operation.GIVE) targetData.giveStamina(amount.evaluate(meta), reason);
+ else if (operation == Operation.SET) targetData.setStamina(amount.evaluate(meta), reason);
+ else if (operation == Operation.TAKE) targetData.giveStamina(-amount.evaluate(meta), reason);
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StelliumMechanic.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StelliumMechanic.java
index 3e94f40c..77112f7f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StelliumMechanic.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/script/mechanic/StelliumMechanic.java
@@ -5,9 +5,9 @@ import io.lumine.mythic.lib.script.mechanic.type.TargetMechanic;
import io.lumine.mythic.lib.skill.SkillMetadata;
import io.lumine.mythic.lib.util.DoubleFormula;
import io.lumine.mythic.lib.util.configobject.ConfigObject;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -30,11 +30,8 @@ public class StelliumMechanic extends TargetMechanic {
public void cast(SkillMetadata meta, Entity target) {
Validate.isTrue(target instanceof Player, "Target is not a player");
PlayerData targetData = PlayerData.get(target.getUniqueId());
- if (operation == Operation.GIVE)
- targetData.giveStellium(amount.evaluate(meta), reason);
- else if (operation == Operation.SET)
- targetData.setStellium(amount.evaluate(meta));
- else if (operation == Operation.TAKE)
- targetData.giveStellium(-amount.evaluate(meta), reason);
+ if (operation == Operation.GIVE) targetData.giveStellium(amount.evaluate(meta), reason);
+ else if (operation == Operation.SET) targetData.setStellium(amount.evaluate(meta), reason);
+ else if (operation == Operation.TAKE) targetData.giveStellium(-amount.evaluate(meta), reason);
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
index f78ac0f4..14450c74 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
@@ -5,15 +5,16 @@ import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
import io.lumine.mythic.lib.player.cooldown.CooldownObject;
import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.skill.PassiveSkill;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
import net.Indyuce.mmocore.player.Unlockable;
import net.Indyuce.mmocore.util.formula.FormulaFailsafeException;
import net.Indyuce.mmocore.util.formula.ScalingFormula;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -146,7 +147,7 @@ public class ClassSkill implements CooldownObject, Unlockable {
return Objects.requireNonNull(parameters.get(parameter), "Could not find parameter called '" + parameter + "'");
}
- public double getParameter(@NotNull String parameter, int level, @NotNull PlayerData caster) {
+ public double getParameter(@NotNull String parameter, int level, @Nullable PlayerData caster) {
try {
return getParameterFormula(parameter).evaluate(level, caster);
} catch (FormulaFailsafeException exception) {
@@ -165,14 +166,14 @@ public class ClassSkill implements CooldownObject, Unlockable {
}
@NotNull
- public List calculateLore(PlayerData data, int x) {
+ public List calculateLore(PlayerData data, int skillLevel) {
// Calculate placeholders
var placeholders = new Placeholders();
// Skill parameters
for (var param : parameters.keySet()) {
- var baseValue = getParameter(param, data);
+ var baseValue = getParameter(param, skillLevel, data);
var modifiedValue = data.getMMOPlayerData().getSkillModifierMap().calculateValue(skill.getHandler(), baseValue, param);
var formatted = skill.getDecimalFormat(param).format(modifiedValue);
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java
index 4a126d84..065165dc 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java
@@ -2,10 +2,10 @@ package net.Indyuce.mmocore.skill.binding;
import io.lumine.mythic.lib.player.skill.PassiveSkill;
import io.lumine.mythic.lib.util.Closeable;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.SkillModifierTrigger;
import net.Indyuce.mmocore.skill.ClassSkill;
-import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/SkillSlot.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/SkillSlot.java
index 4cbb72b3..63bfb22f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/SkillSlot.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/SkillSlot.java
@@ -1,13 +1,13 @@
package net.Indyuce.mmocore.skill.binding;
import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.SkillModifierTrigger;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
import net.Indyuce.mmocore.player.Unlockable;
import net.Indyuce.mmocore.skill.ClassSkill;
-import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.Nullable;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/ComboMap.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/ComboMap.java
index 677cbc3c..1c3f6dd9 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/ComboMap.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/ComboMap.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.skill.cast;
import io.lumine.mythic.lib.UtilityMethods;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingHandler.java
index 56a6f6fb..02ec4e66 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingHandler.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingHandler.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.skill.cast;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.api.player.PlayerData;
-import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java
index 6c262a12..d861f608 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java
@@ -1,10 +1,10 @@
package net.Indyuce.mmocore.skill.cast;
import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.skill.binding.BoundSkillInfo;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java
index c2f4c28f..ba9fa481 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingMode.java
@@ -1,11 +1,11 @@
package net.Indyuce.mmocore.skill.cast;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.skill.cast.handler.KeyCombos;
import net.Indyuce.mmocore.skill.cast.handler.SkillBar;
import net.Indyuce.mmocore.skill.cast.handler.SkillCastingDisabled;
import net.Indyuce.mmocore.skill.cast.handler.SkillScroller;
-import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java
index 182ad350..82fb826e 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java
@@ -3,6 +3,7 @@ package net.Indyuce.mmocore.skill.cast.handler;
import io.lumine.mythic.lib.api.event.skill.PlayerCastSkillEvent;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
+import io.lumine.mythic.lib.message.actionbar.ActionBarPriority;
import io.lumine.mythic.lib.player.PlayerMetadata;
import io.lumine.mythic.lib.skill.result.SkillResult;
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
@@ -195,7 +196,11 @@ public class KeyCombos extends SkillCastingHandler {
public void onTick() {
if (actionBarOptions != null) if (actionBarOptions.isSubtitle)
getCaster().getPlayer().sendTitle(" ", actionBarOptions.format(this), 0, 20, 0);
- else getCaster().displayActionBar(actionBarOptions.format(this));
+ else {
+ var handler = caster.getMMOPlayerData().getActionBar();
+ if (!handler.canShow(ActionBarPriority.NORMAL)) return;
+ handler.show(ActionBarPriority.NORMAL, actionBarOptions.format(this));
+ }
}
/**
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java
index 6335c69c..f9469f79 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java
@@ -3,6 +3,7 @@ package net.Indyuce.mmocore.skill.cast.handler;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
+import io.lumine.mythic.lib.message.actionbar.ActionBarPriority;
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
import io.lumine.mythic.lib.util.SoundObject;
import net.Indyuce.mmocore.MMOCore;
@@ -127,7 +128,10 @@ public class SkillScroller extends SkillCastingHandler {
public void onTick() {
final String skillName = getSelected().getSkill().getName();
final String actionBarFormat = MythicLib.plugin.getPlaceholderParser().parse(getCaster().getPlayer(), SkillScroller.this.actionBarFormat.replace("{selected}", skillName));
- getCaster().displayActionBar(actionBarFormat);
+
+ var handler = caster.getMMOPlayerData().getActionBar();
+ if (!handler.canShow(ActionBarPriority.NORMAL)) return;
+ handler.show(ActionBarPriority.NORMAL, actionBarFormat);
}
public ClassSkill getSelected() {
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/list/Neptune_Gift.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/list/Neptune_Gift.java
index 555c071a..09f6565f 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/list/Neptune_Gift.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/list/Neptune_Gift.java
@@ -1,6 +1,5 @@
package net.Indyuce.mmocore.skill.list;
-import io.lumine.mythic.lib.player.skill.PassiveSkill;
import io.lumine.mythic.lib.skill.SkillMetadata;
import io.lumine.mythic.lib.skill.handler.SkillHandler;
import io.lumine.mythic.lib.skill.result.def.SimpleSkillResult;
@@ -28,14 +27,19 @@ public class Neptune_Gift extends SkillHandler implements Lis
throw new RuntimeException("Not supported");
}
- @EventHandler
+ @EventHandler(ignoreCancelled = true)
public void a(PlayerResourceUpdateEvent event) {
- if (event.getPlayer().getLocation().getBlock().getType() == Material.WATER) {
- PassiveSkill skill = event.getData().getMMOPlayerData().getPassiveSkillMap().getSkill(this);
- if (skill == null)
- return;
+ if (event.getReason().isRegeneration()) return;
+ if (event.getPlayer().getLocation().getBlock().getType() != Material.WATER) return;
- event.setAmount(event.getAmount() * (1 + event.getData().getMMOPlayerData().getSkillModifierMap().calculateValue(skill.getTriggeredSkill(), "extra") / 100));
- }
+ final var skill = event.getData().getMMOPlayerData().getPassiveSkillMap().getSkill(this);
+ if (skill == null) return; // No skill
+
+ final var regenerated = event.getDifference();
+ if (regenerated < 0) return; // WTH? loosing resource
+
+ final var extraModifier = event.getData().getMMOPlayerData().getSkillModifierMap().calculateValue(skill.getTriggeredSkill(), "extra");
+ final var extraRegen = regenerated * extraModifier / 100;
+ event.setNewAmount(event.getNewAmount() + extraRegen);
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/IntegerCoordinates.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/IntCoords.java
similarity index 71%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/IntegerCoordinates.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/IntCoords.java
index c3744245..6c510929 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/IntegerCoordinates.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/IntCoords.java
@@ -1,6 +1,6 @@
package net.Indyuce.mmocore.skilltree;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -8,22 +8,27 @@ import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Objects;
-public class IntegerCoordinates {
+public class IntCoords {
private final int x, y;
- public IntegerCoordinates(int x, int y) {
+ public IntCoords(int x, int y) {
this.x = x;
this.y = y;
}
@Deprecated
- public IntegerCoordinates(String str) {
+ public IntCoords(String str) {
String[] split = str.split("\\.");
Validate.isTrue(split.length == 2, "Invalid format");
x = Integer.parseInt(split[0]);
y = Integer.parseInt(split[1]);
}
+ @NotNull
+ public IntCoords offset(int x, int y) {
+ return new IntCoords(this.x + x, this.y + y);
+ }
+
public int getX() {
return x;
}
@@ -33,15 +38,15 @@ public class IntegerCoordinates {
}
@NotNull
- public IntegerCoordinates add(@NotNull IntegerCoordinates other) {
- return new IntegerCoordinates(x + other.x, y + other.y);
+ public IntCoords add(@NotNull IntCoords other) {
+ return new IntCoords(x + other.x, y + other.y);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- IntegerCoordinates that = (IntegerCoordinates) o;
+ IntCoords that = (IntCoords) o;
return x == that.x && y == that.y;
}
@@ -56,18 +61,18 @@ public class IntegerCoordinates {
}
@NotNull
- public static IntegerCoordinates from(@Nullable Object object) {
+ public static IntCoords from(@Nullable Object object) {
Validate.notNull(object, "Could not read coordinates");
if (object instanceof ConfigurationSection) {
final ConfigurationSection config = (ConfigurationSection) object;
- return new IntegerCoordinates(config.getInt("x"), config.getInt("y"));
+ return new IntCoords(config.getInt("x"), config.getInt("y"));
}
if (object instanceof String) {
final String[] split = ((String) object).split("[:.,]");
Validate.isTrue(split.length > 1, "Must provide two coordinates, X and Y, got " + Arrays.asList(split));
- return new IntegerCoordinates(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
+ return new IntCoords(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
}
throw new RuntimeException("Needs either a string or configuration section");
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentInformation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentInformation.java
index de94a529..3d07ec0c 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentInformation.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentInformation.java
@@ -1,23 +1,145 @@
package net.Indyuce.mmocore.skilltree;
+import net.Indyuce.mmocore.skilltree.display.PathShape;
+import org.apache.commons.lang3.Validate;
+import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Objects;
+import java.util.Set;
+/**
+ * Holds information about a parent/child node in a skill tree.
+ * `relative` can hold either a parent or child node. There is
+ * always one `parent` counterpart for every `child` instance of this class.
+ *
+ * If we represent the skill tree by a graph where edges are skill tree
+ * "nodes", then this class represents an edge in that graph.
+ *
+ * @author jules
+ */
public class ParentInformation {
- private final SkillTreeNode node;
+ private final SkillTreeNode child, parent;
private final ParentType type;
- private final int level;
+ private final int minLevel;
+ private final boolean reciprocal;
- public ParentInformation(SkillTreeNode node, ParentType type, int level) {
- this.node = node;
+ private final Map elements = new HashMap<>();
+
+ public ParentInformation(@NotNull SkillTreeNode child, @NotNull SkillTreeNode parent) {
+ this(child, parent, ParentType.SOFT, false, 1);
+ }
+
+ public ParentInformation(@NotNull SkillTreeNode child,
+ @NotNull SkillTreeNode parent,
+ @NotNull ParentType type,
+ boolean reciprocal,
+ int minLevel) {
+ this.child = child;
+ this.parent = parent;
this.type = type;
- this.level = level;
+ this.reciprocal = reciprocal;
+ this.minLevel = Math.max(1, minLevel);
+ }
+
+ public ParentInformation(@NotNull SkillTreeNode child,
+ @NotNull SkillTreeNode parent,
+ @NotNull ParentType type,
+ @NotNull ConfigurationSection config) {
+ this.child = child;
+ this.parent = parent;
+ this.type = type;
+ this.reciprocal = false;
+ this.minLevel = Math.max(1, config.getInt("level"));
+
+ // Read paths
+ if (config.contains("paths")) {
+ final var pathListRaw = config.getStringList("paths");
+ pathListRaw.forEach(string -> this.elements.put(IntCoords.from(string), null));
+ }
+
+ // All paths are loaded => cache their shapes
+ for (var element : this.elements.keySet()) {
+ final var previousValue = this.elements.put(element, computePathShape(element));
+ Validate.isTrue(previousValue == null, "Path shape already computed?");
+ }
}
@NotNull
- public SkillTreeNode getNode() {
- return node;
+ public PathShape getShape(@NotNull IntCoords coordinates) {
+ final var shape = this.elements.get(coordinates);
+ Validate.notNull(shape, "No path element at " + coordinates);
+ return shape;
+ }
+
+ @Deprecated
+ public void addElement(@NotNull IntCoords coordinates) {
+ Validate.isTrue(!this.elements.containsKey(coordinates), "Path element already present at " + coordinates);
+ this.elements.put(coordinates, null); // Place new
+ this.elements.replaceAll((e, v) -> computePathShape(e)); // Update all
+ }
+
+ /**
+ * Defines the method for computing the shape of a path element ie
+ * whether it goes up, right, up-right, etc. based on the presence
+ * of other path elements around it.
+ *
+ * @param coordinates Coordinates of the path element to compute the shape for
+ * @return Shape of the path element
+ */
+ @NotNull
+ private PathShape computePathShape(@NotNull IntCoords coordinates) {
+
+ final var upCoords = new IntCoords(coordinates.getX(), coordinates.getY() - 1);
+ final var downCoords = new IntCoords(coordinates.getX(), coordinates.getY() + 1);
+ final var rightCoords = new IntCoords(coordinates.getX() + 1, coordinates.getY());
+ final var leftCoords = new IntCoords(coordinates.getX() - 1, coordinates.getY());
+
+ final var hasUp = this.elements.containsKey(upCoords) || upCoords.equals(parent.getCoordinates()) || upCoords.equals(child.getCoordinates());
+ final var hasDown = this.elements.containsKey(downCoords) || downCoords.equals(parent.getCoordinates()) || downCoords.equals(child.getCoordinates());
+ final var hasRight = this.elements.containsKey(rightCoords) || rightCoords.equals(parent.getCoordinates()) || rightCoords.equals(child.getCoordinates());
+ final var hasLeft = this.elements.containsKey(leftCoords) || leftCoords.equals(parent.getCoordinates()) || leftCoords.equals(child.getCoordinates());
+
+ if ((hasUp || hasDown) && !hasLeft && !hasRight) return PathShape.UP;
+ else if ((hasRight || hasLeft) && !hasUp && !hasDown) return PathShape.RIGHT;
+ else if (hasUp && hasRight) return PathShape.UP_RIGHT;
+ else if (hasUp && hasLeft) return PathShape.UP_LEFT;
+ else if (hasDown && hasRight) return PathShape.DOWN_RIGHT;
+ else if (hasDown && hasLeft) return PathShape.DOWN_LEFT;
+
+ return PathShape.DEFAULT;
+ }
+
+ public boolean isSymmetrical() {
+ return reciprocal;
+ }
+
+ @NotNull
+ public Set getElements() {
+ return elements.keySet();
+ }
+
+ @Override
+ public String toString() {
+ return "ParentInformation{" +
+ "child=" + child +
+ ", parent=" + parent +
+ ", type=" + type +
+ ", minLevel=" + minLevel +
+ ", elements=" + elements +
+ '}';
+ }
+
+ @NotNull
+ public SkillTreeNode getParent() {
+ return parent;
+ }
+
+ @NotNull
+ public SkillTreeNode getChild() {
+ return child;
}
@NotNull
@@ -25,8 +147,12 @@ public class ParentInformation {
return type;
}
+ /**
+ * @return Minimum level of parent node required
+ * for the child node to be reachable.
+ */
public int getLevel() {
- return level;
+ return minLevel;
}
@Override
@@ -34,11 +160,33 @@ public class ParentInformation {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ParentInformation that = (ParentInformation) o;
- return Objects.equals(node, that.node) && type == that.type;
+ // Big Hypothesis = there are NO two edges with the same child, parent and type.
+ return Objects.equals(child, that.child) && Objects.equals(parent, that.parent) && type == that.type;
}
@Override
public int hashCode() {
- return Objects.hash(node, type);
+ return Objects.hash(child, parent, type);
+ }
+
+ @NotNull
+ public static ParentInformation fromConfig(@NotNull SkillTreeNode child,
+ @NotNull SkillTreeNode parent,
+ @NotNull ParentType parentType,
+ @NotNull Object configObject) {
+ Validate.notNull(configObject, "Cannot load parent info from null object");
+
+ // From simple int, no path.
+ if (configObject instanceof Integer) {
+ // TODO try to infer paths from 'paths' config for backwards compatibility
+ return new ParentInformation(child, parent, parentType, false, (Integer) configObject);
+ }
+
+ // From config section
+ if (configObject instanceof ConfigurationSection) {
+ return new ParentInformation(child, parent, parentType, (ConfigurationSection) configObject);
+ }
+
+ throw new IllegalArgumentException("Cannot load parent from " + configObject.getClass().getName());
}
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java
index 4e4a5b02..28730015 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java
@@ -1,8 +1,11 @@
package net.Indyuce.mmocore.skilltree;
import io.lumine.mythic.lib.MythicLib;
+import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders;
import io.lumine.mythic.lib.gui.util.IconOptions;
+import io.lumine.mythic.lib.util.PostLoadAction;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.EXPSource;
@@ -13,7 +16,6 @@ import net.Indyuce.mmocore.skilltree.display.DisplayMap;
import net.Indyuce.mmocore.skilltree.display.NodeDisplayInfo;
import net.Indyuce.mmocore.skilltree.display.NodeShape;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
-import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
@@ -23,13 +25,14 @@ import java.util.*;
import java.util.stream.Collectors;
// We must use generics to get the type of the corresponding tree
+
public class SkillTreeNode implements ExperienceObject {
private final SkillTree tree;
private final String name, id;
private final String permissionRequired;
private final int pointConsumption;
private final DisplayMap icons;
- private final IntegerCoordinates coordinates;
+ private final IntCoords coordinates;
private final int maxLevel, maxChildren;
private final ExperienceTable experienceTable;
private final List children = new ArrayList<>();
@@ -38,11 +41,42 @@ public class SkillTreeNode implements ExperienceObject {
private boolean root;
- public SkillTreeNode(SkillTree tree, ConfigurationSection config) {
+ private final PostLoadAction postLoadAction = new PostLoadAction(config -> {
+
+ // Load children
+ // Requires other nodes to be loaded first
+ loadRelatives(true, config);
+
+ // Load parents. Both work, one way or the other
+ // Requires other nodes to be loaded first
+ loadRelatives(false, config);
+ });
+
+ private void loadRelatives(boolean nodeIsParent, @NotNull ConfigurationSection config) {
+ final var configPath = nodeIsParent ? "children" : "parents";
+
+ if (config.isConfigurationSection(configPath))
+ for (var parentTypeRaw : config.getConfigurationSection(configPath).getKeys(false)) {
+ final var section = config.getConfigurationSection(configPath + "." + parentTypeRaw);
+ Validate.notNull(section, "Could not read " + configPath + " of type '" + parentTypeRaw + "'");
+ final ParentType parentType = UtilityMethods.prettyValueOf(ParentType::valueOf, parentTypeRaw, "No parent type called '%s'");
+
+ for (var relativeId : section.getKeys(false)) {
+ final var relative = SkillTreeNode.this.tree.getNode(relativeId);
+ final var child = nodeIsParent ? relative : this;
+ final var parent = nodeIsParent ? this : relative;
+ child.addParent(ParentInformation.fromConfig(child, parent, parentType, section.get(relativeId)));
+ }
+ }
+ }
+
+ public SkillTreeNode(@NotNull SkillTree tree, @NotNull ConfigurationSection config) {
Validate.notNull(config, "Config cannot be null");
this.id = config.getName();
this.tree = tree;
+ postLoadAction.cacheConfig(config);
+
// Load icons for node states
this.icons = DisplayMap.from(config.getConfigurationSection("display"));
@@ -70,7 +104,7 @@ public class SkillTreeNode implements ExperienceObject {
Validate.isTrue(maxLevel > 0, "Max level must be positive");
maxChildren = config.getInt("max-children", 0);
Validate.isTrue(maxChildren >= 0, "Max children must positive or zero");
- coordinates = IntegerCoordinates.from(config.get("coordinates"));
+ coordinates = IntCoords.from(config.get("coordinates"));
}
public SkillTree getTree() {
@@ -81,12 +115,23 @@ public class SkillTreeNode implements ExperienceObject {
return root;
}
- public void addParent(@NotNull SkillTreeNode parent, @NotNull ParentType parentType, int requiredLevel) {
- parents.add(new ParentInformation(parent, parentType, requiredLevel));
+ @NotNull
+ public PostLoadAction getPostLoadAction() {
+ return postLoadAction;
}
- public void addChild(@NotNull SkillTreeNode child, @NotNull ParentType parentType, int requiredLevel) {
- children.add(new ParentInformation(child, parentType, requiredLevel));
+ /**
+ * Registers this relation both as a parent and child relation in the right
+ * registers of the parent and child nodes.
+ *
+ * Note that the {@link #children} and {@link #parents} maps are only
+ * modified through this method.
+ */
+ public void addParent(@NotNull ParentInformation parentInfo) {
+ Validate.isTrue(parentInfo.getChild().equals(this), "#addParent(..) must be called on child node");
+
+ parents.add(parentInfo);
+ parentInfo.getParent().children.add(parentInfo);
}
public void setRoot() {
@@ -97,24 +142,9 @@ public class SkillTreeNode implements ExperienceObject {
return pointConsumption;
}
- public int getParentNeededLevel(SkillTreeNode parent) {
- for (ParentInformation entry : parents)
- if (entry.getNode().equals(parent))
- return entry.getLevel();
- throw new RuntimeException("Could not find parent " + parent.getId() + " for node " + id);
- }
-
- @Deprecated
- public int getParentNeededLevel(SkillTreeNode parent, ParentType parentType) {
- for (ParentInformation entry : parents)
- if (entry.getNode().equals(parent) && entry.getType() == parentType)
- return entry.getLevel();
- return 0;
- }
-
public boolean hasParent(SkillTreeNode parent) {
- for (ParentInformation entry : parents)
- if (entry.getNode() == parent) return true;
+ for (var edge : parents)
+ if (edge.getParent().equals(parent)) return true;
return false;
}
@@ -135,12 +165,6 @@ public class SkillTreeNode implements ExperienceObject {
return parents;
}
- @NotNull
- @Deprecated
- public List getParents(ParentType parentType) {
- return parents.stream().filter(integer -> integer.getType() == parentType).map(ParentInformation::getNode).collect(Collectors.toList());
- }
-
@NotNull
public List getChildren() {
return children;
@@ -155,7 +179,7 @@ public class SkillTreeNode implements ExperienceObject {
/**
* @return Full node identifier, containing both the node identifier AND
- * the skill tree identifier, like "combat_extra_strength"
+ * the skill tree identifier, like "combat_extra_strength"
*/
@NotNull
public String getFullId() {
@@ -168,7 +192,7 @@ public class SkillTreeNode implements ExperienceObject {
}
@NotNull
- public IntegerCoordinates getCoordinates() {
+ public IntCoords getCoordinates() {
return coordinates;
}
@@ -195,30 +219,6 @@ public class SkillTreeNode implements ExperienceObject {
return experienceTable != null;
}
- public NodeShape getNodeType() {
- boolean up = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1));
- boolean down = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1));
- boolean right = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY()));
- boolean left = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX() - 1, coordinates.getY()));
-
- if (up && right && down && left) return NodeShape.UP_RIGHT_DOWN_LEFT;
- else if (up && right && down) return NodeShape.UP_RIGHT_DOWN;
- else if (up && right && left) return NodeShape.UP_RIGHT_LEFT;
- else if (up && down && left) return NodeShape.UP_DOWN_LEFT;
- else if (down && right && left) return NodeShape.DOWN_RIGHT_LEFT;
- else if (up && right) return NodeShape.UP_RIGHT;
- else if (up && down) return NodeShape.UP_DOWN;
- else if (up && left) return NodeShape.UP_LEFT;
- else if (down && right) return NodeShape.DOWN_RIGHT;
- else if (down && left) return NodeShape.DOWN_LEFT;
- else if (right && left) return NodeShape.RIGHT_LEFT;
- else if (up) return NodeShape.UP;
- else if (down) return NodeShape.DOWN;
- else if (right) return NodeShape.RIGHT;
- else if (left) return NodeShape.LEFT;
- return NodeShape.NO_PATH;
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -277,6 +277,52 @@ public class SkillTreeNode implements ExperienceObject {
//region Deprecated
+ @Deprecated
+ public void loadLegacyPathSection(@NotNull ConfigurationSection section) {
+ for (var childId : section.getKeys(false)) {
+ final var child = tree.getNode(childId);
+ Validate.notNull(child, "Could not find child node '" + childId + "' for path");
+
+ // Find corresponding edge
+ ParentInformation edge = null;
+ for (var existingEdge : children)
+ if (existingEdge.getChild().equals(child)) {
+ edge = existingEdge;
+ break;
+ }
+ if (edge == null) {
+ MMOCore.log("Could not find parent-child relation between '" + id + "' and '" + childId + "'. Did you forget to add it in the 'parents' or 'children' section?");
+ continue;
+ }
+
+ final var subsection = section.getConfigurationSection(childId);
+ for (var pathKey : subsection.getKeys(false)) {
+ final var coords = IntCoords.from(subsection.get(pathKey));
+ edge.addElement(coords);
+ }
+ }
+ }
+
+ @Deprecated
+ public int getParentNeededLevel(SkillTreeNode parent) {
+ for (var edge : parents)
+ if (edge.getParent().equals(parent)) return edge.getLevel();
+ throw new RuntimeException("Could not find parent " + parent.getId() + " for node " + id);
+ }
+
+ @NotNull
+ @Deprecated
+ public List getParents(ParentType parentType) {
+ return parents.stream().filter(integer -> integer.getType() == parentType).map(ParentInformation::getParent).collect(Collectors.toList());
+ }
+
+ @Deprecated
+ public int getParentNeededLevel(SkillTreeNode parent, ParentType parentType) {
+ for (var edge : parents)
+ if (edge.getParent().equals(parent) && edge.getType() == parentType) return edge.getLevel();
+ return 0;
+ }
+
@Deprecated
public boolean hasIcon(NodeState status) {
return getIcon(status) != null;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java
deleted file mode 100644
index 53165356..00000000
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package net.Indyuce.mmocore.skilltree;
-
-import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.skilltree.display.PathShape;
-import net.Indyuce.mmocore.skilltree.tree.SkillTree;
-
-public class SkillTreePath {
- private final SkillTree tree;
- private final IntegerCoordinates coordinates;
- private final SkillTreeNode from;
- private final SkillTreeNode to;
-
- public SkillTreePath(SkillTree tree, IntegerCoordinates coordinates, SkillTreeNode from, SkillTreeNode skillTreeNode) {
- this.tree = tree;
- this.coordinates = coordinates;
- this.from = from;
- to = skillTreeNode;
- }
-
- /**
- * Defines the status of a path between two nodes, which is determined
- * by the pair of states of the two nodes.
- */
- public PathState getStatus(PlayerData playerData) {
- var from = playerData.getNodeState(this.from);
- var to = playerData.getNodeState(this.to);
-
- // Either one is fully locked => gray out path
- if (from == NodeState.FULLY_LOCKED || to == NodeState.FULLY_LOCKED) return PathState.FULLY_LOCKED;
-
- // Both are unlocked => path is taken, unlocked
- if (from.isUnlocked() && to.isUnlocked()) return PathState.UNLOCKED;
-
- // One of them is unlocked, other one is unlockable => path is not taken yet, but can be
- if ((from == NodeState.UNLOCKABLE && to.isUnlocked()) || (from.isUnlocked() && to == NodeState.UNLOCKABLE))
- return PathState.UNLOCKABLE;
-
- // Otherwise, locked path
- return PathState.LOCKED;
- }
-
- public PathShape getPathType() {
- IntegerCoordinates upCoor = new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1);
- IntegerCoordinates downCoor = new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1);
- IntegerCoordinates rightCoor = new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY());
- IntegerCoordinates leftCoor = new IntegerCoordinates(coordinates.getX() - 1, coordinates.getY());
- boolean hasUp = tree.isPath(upCoor) || upCoor.equals(from.getCoordinates()) || upCoor.equals(to.getCoordinates());
- boolean hasDown = tree.isPath(downCoor) || downCoor.equals(from.getCoordinates()) || downCoor.equals(to.getCoordinates());
- boolean hasRight = tree.isPath(rightCoor) || rightCoor.equals(from.getCoordinates()) || rightCoor.equals(to.getCoordinates());
- boolean hasLeft = tree.isPath(leftCoor) || leftCoor.equals(from.getCoordinates()) || leftCoor.equals(to.getCoordinates());
-
- if ((hasUp || hasDown) && !hasLeft && !hasRight) {
- return PathShape.UP;
- } else if ((hasRight || hasLeft) && !hasUp && !hasDown) {
- return PathShape.RIGHT;
- } else if (hasUp && hasRight) {
- return PathShape.UP_RIGHT;
- } else if (hasUp && hasLeft) {
- return PathShape.UP_LEFT;
- } else if (hasDown && hasRight) {
- return PathShape.DOWN_RIGHT;
- } else if (hasDown && hasLeft) {
- return PathShape.DOWN_LEFT;
- }
- return PathShape.DEFAULT;
- }
-}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java
index 7bdc173a..e00773ee 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java
@@ -3,7 +3,6 @@ package net.Indyuce.mmocore.skilltree.display;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.gui.util.IconOptions;
import net.Indyuce.mmocore.skilltree.NodeState;
-import net.Indyuce.mmocore.skilltree.PathState;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java
index be3b641e..7543ad84 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java
@@ -1,6 +1,5 @@
package net.Indyuce.mmocore.skilltree.display;
-import net.Indyuce.mmocore.skilltree.PathState;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
@@ -15,7 +14,7 @@ public class PathDisplayInfo {
}
@NotNull
- public PathState getStatus() {
+ public PathState getState() {
return state;
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathState.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathState.java
similarity index 80%
rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathState.java
rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathState.java
index 3c5c743e..38bd13e2 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathState.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathState.java
@@ -1,10 +1,5 @@
-package net.Indyuce.mmocore.skilltree;
+package net.Indyuce.mmocore.skilltree.display;
-import net.Indyuce.mmocore.api.player.PlayerData;
-
-/**
- * @see SkillTreePath#getStatus(PlayerData)
- */
public enum PathState {
/**
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ProximitySkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ProximitySkillTree.java
index ad550afd..884d19b1 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ProximitySkillTree.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ProximitySkillTree.java
@@ -1,6 +1,7 @@
package net.Indyuce.mmocore.skilltree.tree;
-import net.Indyuce.mmocore.skilltree.IntegerCoordinates;
+import net.Indyuce.mmocore.skilltree.IntCoords;
+import net.Indyuce.mmocore.skilltree.ParentInformation;
import net.Indyuce.mmocore.skilltree.ParentType;
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
import org.bukkit.configuration.ConfigurationSection;
@@ -10,20 +11,20 @@ public class ProximitySkillTree extends SkillTree {
super(config);
// Neighbors are marked as soft parents
- for (SkillTreeNode node : nodes.values())
- for (IntegerCoordinates relative : RELATIVES) {
+ for (var node : nodes.values())
+ for (var relative : RELATIVES) {
final SkillTreeNode neighbor = this.getNodeOrNull(node.getCoordinates().add(relative));
if (neighbor != null) {
- node.addParent(neighbor, ParentType.SOFT, 1);
- neighbor.addChild(node, ParentType.SOFT, 1);
+ final var parentInfo = new ParentInformation(node, neighbor, ParentType.SOFT, true,1);
+ node.addParent(parentInfo);
}
}
}
- private static final IntegerCoordinates[] RELATIVES = {
- new IntegerCoordinates(1, 0),
- new IntegerCoordinates(-1, 0),
- new IntegerCoordinates(0, 1),
- new IntegerCoordinates(0, -1)
+ private static final IntCoords[] RELATIVES = {
+ new IntCoords(1, 0),
+ new IntCoords(-1, 0),
+ new IntCoords(0, 1),
+ new IntCoords(0, -1)
};
}
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java
index be1c7070..2b277896 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java
@@ -3,12 +3,14 @@ package net.Indyuce.mmocore.skilltree.tree;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.gui.util.IconOptions;
+import io.lumine.mythic.lib.util.lang3.Validate;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.registry.RegisteredObject;
import net.Indyuce.mmocore.skilltree.*;
import net.Indyuce.mmocore.skilltree.display.DisplayMap;
-import org.apache.commons.lang.Validate;
+import net.Indyuce.mmocore.skilltree.display.NodeShape;
+import net.Indyuce.mmocore.skilltree.display.PathState;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
@@ -41,9 +43,6 @@ public abstract class SkillTree implements RegisteredObject {
protected final List roots = new ArrayList<>();
protected final DisplayMap icons;
- protected final Map coordNodes = new HashMap<>();
- protected final Map coordPaths = new HashMap<>();
-
public SkillTree(@NotNull ConfigurationSection config) {
this.id = Objects.requireNonNull(config.getString("id"), "Could not find skill tree id");
this.name = MythicLib.plugin.parseColors(Objects.requireNonNull(config.getString("name"), "Could not find skill tree name"));
@@ -59,54 +58,31 @@ public abstract class SkillTree implements RegisteredObject {
ConfigurationSection section = config.getConfigurationSection("nodes." + key);
SkillTreeNode node = new SkillTreeNode(this, section);
nodes.put(node.getId(), node);
- coordNodes.put(node.getCoordinates(), node);
+ nodeByCoordinate.put(node.getCoordinates(), node);
if (node.isRoot()) roots.add(node);
- } catch (Exception e) {
- MMOCore.log("Couldn't load skill tree node " + id + "." + key + ": " + e.getMessage());
+ } catch (Exception exception) {
+ MMOCore.log(Level.WARNING, "Couldn't load skill tree node " + id + "." + key + ": " + exception.getMessage());
}
- // Load paths
- for (String from : config.getConfigurationSection("nodes").getKeys(false)) {
- ConfigurationSection section = config.getConfigurationSection("nodes." + from);
- if (section.contains("paths")) {
- for (String to : section.getConfigurationSection("paths").getKeys(false)) {
- SkillTreeNode node1 = nodes.get(to);
- if (node1 == null) {
- MMOCore.log("Couldn't find node " + to + " for path in node " + from + ".");
- continue;
- }
- for (String pathKey : section.getConfigurationSection("paths." + to).getKeys(false)) {
- IntegerCoordinates coordinates = IntegerCoordinates.from(section.get("paths." + to + "." + pathKey));
- coordPaths.put(coordinates, new SkillTreePath(this, coordinates, nodes.get(from), node1));
- }
- }
+ // Post load all nodes (relatives)
+ for (var node : nodes.values())
+ try {
+ node.getPostLoadAction().performAction();
+ node.getParents().forEach(parentInfo -> parentInfo.getElements().forEach(coords -> this.pathByCoordinate.put(coords, parentInfo)));
+ } catch (Exception exception) {
+ MMOCore.log(Level.WARNING, "Couldn't post-load skill tree node " + id + "." + node.getId() + ": " + exception.getMessage());
+ exception.printStackTrace(); // TODO remove
}
- }
+
+ // [Syntax Deprecated] Load legacy "paths" section
+ loadLegacyPaths(config);
+
+ // Resolve node shapes
+ resolveNodeShapes();
// Load icons
this.icons = DisplayMap.from(config.getConfigurationSection("display"));
-
- // Setup children and parents for each node
- for (SkillTreeNode node : nodes.values())
- try {
- if (config.isConfigurationSection("nodes." + node.getId() + ".parents"))
- for (String key : config.getConfigurationSection("nodes." + node.getId() + ".parents").getKeys(false)) {
- final ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents." + key);
- if (section != null) {
- final ParentType parentType = ParentType.valueOf(UtilityMethods.enumName(key));
-
- for (String parentId : section.getKeys(false)) {
- final SkillTreeNode parent = getNode(parentId);
- final int level = section.getInt(parentId);
- node.addParent(parent, parentType, level);
- parent.addChild(node, parentType, level);
- }
- }
- }
- } catch (RuntimeException exception) {
- MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load parents of skill tree node '" + node.getId() + "': " + exception.getMessage());
- }
}
public List getLore() {
@@ -130,21 +106,46 @@ public abstract class SkillTree implements RegisteredObject {
return roots;
}
+ //region Resolving states and shapes
+
+ private final Map nodeShapes = new HashMap<>();
+
+ @NotNull
+ public NodeShape getNodeShape(@NotNull SkillTreeNode node) {
+ return Objects.requireNonNull(nodeShapes.get(node), "Missing node shape");
+ }
+
+ private void resolveNodeShapes() {
+ for (var node : nodes.values()) nodeShapes.put(node, resolveNodeShape(node));
+ }
+
/**
- * TODO Write documentation
+ * Resets all states saved for the nodes and edges of
+ * this skill tree and recomputes them from scratch solely
+ * based on the nodes unlocked (node level map) by the
+ * player and points spent in each of them.
+ *
* TODO Use some collection and progressively filter out the nodes to avoid useless iterations
*
* Let:
+ * - A the number of path elements (not edges)
* - V denote the number of nodes in the skill tree
- * - P the number of parents any node, has at most
+ * - P the number of parents any node has, at most
* - C the number of children any node has, at most
*
- * This algorithm runs in O(V * P * C)
+ * This algorithm runs in O(V * P * C). In Minecraft nodes
+ * can't have more than 4 children or parents which makes
+ * it O(V).
+ *
+ * @author jules
*/
- public void setupNodeStates(@NotNull PlayerData playerData) {
+ public void resolveStates(@NotNull PlayerData playerData) {
+ playerData.clearStates(this);
+ resolveNodeStates(playerData);
+ resolvePathStates(playerData);
+ }
- // Reinitialization
- playerData.clearNodeStates(this);
+ private void resolveNodeStates(@NotNull PlayerData playerData) {
// If the player has already spent the maximum amount of points in this skill tree.
final boolean skillTreeLocked = playerData.getPointsSpent(this) >= this.maxPointSpent;
@@ -153,25 +154,27 @@ public abstract class SkillTree implements RegisteredObject {
// PASS 1
//
// Initialization. Mark all nodes either locked or unlocked
- for (SkillTreeNode node : nodes.values())
- playerData.setNodeState(node, playerData.getNodeLevel(node) > 0 ? NodeState.UNLOCKED : lockState);
+ // Mark nodes as "Maxed out" if maximum level is reached.
+ for (var node : nodes.values()) {
+ final var nodeLevel = playerData.getNodeLevel(node);
+ playerData.setNodeState(node, nodeLevel == 0 ? lockState : nodeLevel == node.getMaxLevel() ? NodeState.MAXED_OUT : NodeState.UNLOCKED);
+ }
if (skillTreeLocked) return;
// PASS 2
//
- // Apply basic unreachability rules in O(V * [C + P])
+ // Apply level 1-unreachability rules in O(V * [C + P])
// It has to differ from pass 1 because it uses results from pass 1.
- final Stack unreachable = new Stack<>();
- final Set updated = new HashSet<>();
+ final var unreachable = new Stack();
- for (SkillTreeNode node : nodes.values()) {
+ for (var node : nodes.values()) {
// INCOMPATIBILITY RULES
//
// Any node with an unlocked incompatible parent is made unreachable.
- for (ParentInformation parent : node.getParents())
- if (parent.getType() == ParentType.INCOMPATIBLE && playerData.getNodeState(parent.getNode()) == NodeState.UNLOCKED) {
+ for (var edge : node.getParents())
+ if (edge.getType() == ParentType.INCOMPATIBLE && playerData.getNodeState(edge.getParent()).isUnlocked()) {
unreachable.add(node);
break;
}
@@ -184,13 +187,14 @@ public abstract class SkillTree implements RegisteredObject {
if (maxChildren > 0) {
int unlocked = 0;
- final List locked = new ArrayList<>();
+ final var locked = new ArrayList();
- for (ParentInformation child : node.getChildren())
- switch (playerData.getNodeState(child.getNode())) {
+ for (var edge : node.getChildren())
+ switch (playerData.getNodeState(edge.getChild())) {
case LOCKED:
- locked.add(child.getNode());
+ locked.add(edge.getChild());
break;
+ case MAXED_OUT:
case UNLOCKED:
unlocked++;
break;
@@ -202,17 +206,18 @@ public abstract class SkillTree implements RegisteredObject {
// PASS 3
//
- // Propagate unreachability in O(V * C * P)
+ // Propagate level 1-unreachability in O(V * C * P)
// Unreachability is transitive, if one node is unreachable, all subsequent
// child nodes are all unreachable.
+ final var unreachableCheck = new HashSet();
while (!unreachable.empty()) {
- final SkillTreeNode node = unreachable.pop();
+ final var node = unreachable.pop();
- updated.add(node);
+ unreachableCheck.add(node);
playerData.setNodeState(node, NodeState.FULLY_LOCKED);
- for (ParentInformation child : node.getChildren()) // Propagate
- if (!updated.contains(child.getNode()) && isUnreachable(child.getNode(), playerData))
- unreachable.push(child.getNode());
+ for (var edge : node.getChildren()) // Propagate
+ if (!unreachableCheck.contains(edge.getChild()) && isUnreachable(edge.getChild(), playerData))
+ unreachable.push(edge.getChild());
}
// PASS 4
@@ -221,7 +226,7 @@ public abstract class SkillTree implements RegisteredObject {
// because the distance between the set of all unlocked nodes and the set
// of all unlockable nodes is at most 1 (unlockability is not "transitive")
pass4:
- for (SkillTreeNode node : nodes.values()) {
+ for (var node : nodes.values()) {
if (playerData.getNodeState(node) != NodeState.LOCKED) continue;
// ROOT NODES
@@ -239,12 +244,12 @@ public abstract class SkillTree implements RegisteredObject {
// One soft parent of any node must be unlocked for the node to be unlockable.
boolean soft = false, hasSoft = false;
- for (ParentInformation parent : node.getParents()) {
- if (parent.getType() == ParentType.STRONG && playerData.getNodeLevel(parent.getNode()) < parent.getLevel())
+ for (var edge : node.getParents()) {
+ if (edge.getType() == ParentType.STRONG && playerData.getNodeLevel(edge.getParent()) < edge.getLevel())
continue pass4; // Keep the node locked
- else if (!soft && parent.getType() == ParentType.SOFT) {
+ else if (!soft && edge.getType() == ParentType.SOFT) {
hasSoft = true;
- if (playerData.getNodeLevel(parent.getNode()) >= parent.getLevel())
+ if (playerData.getNodeLevel(edge.getParent()) >= edge.getLevel())
soft = true; // Cannot continue, must check for other strong parents
}
}
@@ -252,16 +257,78 @@ public abstract class SkillTree implements RegisteredObject {
// At least one soft parent!
if (!hasSoft || soft) playerData.setNodeState(node, NodeState.UNLOCKABLE);
}
+ }
+
+ private void resolvePathStates(@NotNull PlayerData playerData) {
// PASS 5
//
- // I'm not sure this is the best place to do that but it works just fine.
- // Mark unlocked nodes as maxed out if maximum number of points spent
- for (var node : nodes.values())
- if (playerData.getNodeState(node) == NodeState.UNLOCKED && playerData.getNodeLevel(node) >= node.getMaxLevel())
- playerData.setNodeState(node, NodeState.MAXED_OUT);
+ // Resolve path states. Iterate through parents of nodes (children would work too)
+ // TODO merge this with steps 1 to 4 (my brain is fried atm)
+ for (var node : nodeByCoordinate.values())
+ for (var edge : node.getParents())
+ playerData.setPathState(edge, resolvePathState(playerData, edge));
}
+ @NotNull
+ private PathState resolvePathState(@NotNull PlayerData playerData, @NotNull ParentInformation edge) {
+
+ final var from = playerData.getNodeState(edge.getParent());
+ final var to = playerData.getNodeState(edge.getChild());
+ final var symm = edge.isSymmetrical();
+
+ // Gray out path if target is fully locked
+ // If symmetrical, check again after permutation
+ if (to == NodeState.FULLY_LOCKED || (symm && from == NodeState.FULLY_LOCKED))
+ return PathState.FULLY_LOCKED;
+
+ // Both are unlocked => path is taken, unlocked
+ // Symmetric relation so 'symm' does not matter
+ if (from.isUnlocked() && to.isUnlocked()) return PathState.UNLOCKED;
+
+ // If source is unlocked and target unlockable => UNLOCKABLE
+ // If symmetrical, check again after permutation
+ if ((from.isUnlocked() && to == NodeState.UNLOCKABLE) || (symm && (to.isUnlocked() && from == NodeState.UNLOCKABLE)))
+ return PathState.UNLOCKABLE;
+
+ // Locked path by default
+ return PathState.LOCKED;
+ }
+
+ @NotNull
+ private NodeShape resolveNodeShape(@NotNull SkillTreeNode node) {
+ final var coordinates = node.getCoordinates();
+
+ final var upCoords = new IntCoords(coordinates.getX(), coordinates.getY() - 1);
+ final var downCoords = new IntCoords(coordinates.getX(), coordinates.getY() + 1);
+ final var rightCoords = new IntCoords(coordinates.getX() + 1, coordinates.getY());
+ final var leftCoords = new IntCoords(coordinates.getX() - 1, coordinates.getY());
+
+ final var up = this.nodeByCoordinate.containsKey(upCoords) || this.pathByCoordinate.containsKey(upCoords);
+ final var down = this.nodeByCoordinate.containsKey(downCoords) || this.pathByCoordinate.containsKey(downCoords);
+ final var right = this.nodeByCoordinate.containsKey(rightCoords) || this.pathByCoordinate.containsKey(rightCoords);
+ final var left = this.nodeByCoordinate.containsKey(leftCoords) || this.pathByCoordinate.containsKey(leftCoords);
+
+ if (up && right && down && left) return NodeShape.UP_RIGHT_DOWN_LEFT;
+ else if (up && right && down) return NodeShape.UP_RIGHT_DOWN;
+ else if (up && right && left) return NodeShape.UP_RIGHT_LEFT;
+ else if (up && down && left) return NodeShape.UP_DOWN_LEFT;
+ else if (down && right && left) return NodeShape.DOWN_RIGHT_LEFT;
+ else if (up && right) return NodeShape.UP_RIGHT;
+ else if (up && down) return NodeShape.UP_DOWN;
+ else if (up && left) return NodeShape.UP_LEFT;
+ else if (down && right) return NodeShape.DOWN_RIGHT;
+ else if (down && left) return NodeShape.DOWN_LEFT;
+ else if (right && left) return NodeShape.RIGHT_LEFT;
+ else if (up) return NodeShape.UP;
+ else if (down) return NodeShape.DOWN;
+ else if (right) return NodeShape.RIGHT;
+ else if (left) return NodeShape.LEFT;
+ return NodeShape.NO_PATH;
+ }
+
+ //endregion
+
private boolean isUnreachable(@NotNull SkillTreeNode node, @NotNull PlayerData playerData) {
// UNREACHABILITY RULES
@@ -271,12 +338,12 @@ public abstract class SkillTree implements RegisteredObject {
// This rule is the logical opposite of the reachability rule.
boolean soft = false, hasSoft = false;
- for (ParentInformation parent : node.getParents()) {
- if (parent.getType() == ParentType.STRONG && playerData.getNodeState(parent.getNode()) == NodeState.FULLY_LOCKED)
+ for (var edge : node.getParents()) {
+ if (edge.getType() == ParentType.STRONG && playerData.getNodeState(edge.getParent()) == NodeState.FULLY_LOCKED)
return true;
- else if (!soft && parent.getType() == ParentType.SOFT) {
+ else if (!soft && edge.getType() == ParentType.SOFT) {
hasSoft = true;
- if (playerData.getNodeState(parent.getNode()) != NodeState.FULLY_LOCKED)
+ if (playerData.getNodeState(edge.getParent()) != NodeState.FULLY_LOCKED)
soft = true; // Cannot continue, must check for other strong parents
}
}
@@ -284,18 +351,7 @@ public abstract class SkillTree implements RegisteredObject {
return hasSoft && !soft;
}
- public boolean isNode(@NotNull IntegerCoordinates coordinates) {
- return coordNodes.containsKey(coordinates);
- }
-
- public boolean isPath(@NotNull IntegerCoordinates coordinates) {
- return coordPaths.containsKey(coordinates);
- }
-
- public boolean isPathOrNode(IntegerCoordinates coordinates) {
- return isNode(coordinates) || isPath(coordinates);
- }
-
+ @NotNull
public Material getItem() {
return item;
}
@@ -305,29 +361,38 @@ public abstract class SkillTree implements RegisteredObject {
return id;
}
+ @NotNull
public String getName() {
return name;
}
+ @NotNull
public Collection getNodes() {
return nodes.values();
}
+ //region Geometry
+
+ protected final Map nodeByCoordinate = new HashMap<>();
+ protected final Map pathByCoordinate = new HashMap<>();
+
@NotNull
- public SkillTreeNode getNode(@NotNull IntegerCoordinates coords) {
- return Objects.requireNonNull(coordNodes.get(coords), "Could not find node in tree '" + id + "' with coordinates '" + coords + "'");
+ public SkillTreeNode getNode(@NotNull IntCoords coords) {
+ return Objects.requireNonNull(nodeByCoordinate.get(coords), "Could not find node in tree '" + id + "' with coordinates '" + coords + "'");
}
@Nullable
- public SkillTreeNode getNodeOrNull(@NotNull IntegerCoordinates coords) {
- return coordNodes.get(coords);
+ public SkillTreeNode getNodeOrNull(@NotNull IntCoords coords) {
+ return nodeByCoordinate.get(coords);
}
- @NotNull
- public SkillTreePath getPath(@NotNull IntegerCoordinates coords) {
- return Objects.requireNonNull(coordPaths.get(coords), "Could not find path in tree '" + id + "' with coordinates '" + coords + "'");
+ @Nullable
+ public ParentInformation getPath(@NotNull IntCoords coords) {
+ return pathByCoordinate.get(coords);
}
+ //endregion
+
@NotNull
public SkillTreeNode getNode(@NotNull String name) {
return Objects.requireNonNull(nodes.get(name), "Could not find node in tree '" + id + "' with name '" + name + "'");
@@ -338,10 +403,6 @@ public abstract class SkillTree implements RegisteredObject {
return icons;
}
- public boolean isNode(String name) {
- return nodes.containsKey(name);
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -357,6 +418,51 @@ public abstract class SkillTree implements RegisteredObject {
//region Deprecated
+ @Deprecated
+ private void loadLegacyPaths(ConfigurationSection config) {
+
+ int warnings = 0;
+
+ for (var node : nodes.values()) {
+ final var section = config.getConfigurationSection("nodes." + node.getId() + ".paths");
+ if (section == null) continue;
+ if (warnings++ < 3) {
+ // Warn max 3 times
+ MMOCore.log("You are using deprecated syntax for skill tree node '" + id + "' of skill tree '"
+ + this.getId() + "'. You may update your config to use the 'parents' section instead of the 'paths' section. " +
+ "Please visit 'https://gitlab.com/phoenix-dvpmt/mmocore/-/wikis/Skill%20Trees' to read about this new syntax");
+ }
+ node.loadLegacyPathSection(section);
+ }
+
+ // Repopulate pathByCoordinate map
+ if (warnings > 0)
+ for (var node : nodes.values())
+ node.getParents().forEach(parentInfo -> parentInfo.getElements().forEach(coords -> this.pathByCoordinate.put(coords, parentInfo)));
+ }
+
+ @Deprecated
+ public boolean isNode(@NotNull IntCoords coordinates) {
+ // TODO remove usage
+ return nodeByCoordinate.containsKey(coordinates);
+ }
+
+ @Deprecated
+ public boolean isPath(@NotNull IntCoords coordinates) {
+ // TODO remove usage
+ return pathByCoordinate.containsKey(coordinates);
+ }
+
+ @Deprecated
+ public boolean isNode(String name) {
+ return nodes.containsKey(name);
+ }
+
+ @Deprecated
+ public boolean isPathOrNode(IntCoords coordinates) {
+ return isNode(coordinates) || isPath(coordinates);
+ }
+
@Deprecated
public static SkillTree loadSkillTree(ConfigurationSection config) {
return MMOCore.plugin.skillTreeManager.loadSkillTree(config);
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java
index 63b215b3..d79d3a13 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java
@@ -2,7 +2,7 @@ package net.Indyuce.mmocore.util;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.gui.editable.item.ItemOptions;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Language.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Language.java
index c85899dd..8dd850ba 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Language.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Language.java
@@ -11,6 +11,7 @@ import java.util.logging.Level;
public enum Language {
EXP_HOLOGRAM,
CAUGHT_FISH,
+ GOLD_POUCH_UI_NAME,
FISH_OUT_WATER,
FISH_OUT_WATER_CRIT,
NO_SKILL_PLACEHOLDER;
diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/item/ConfigItem.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/item/ConfigItem.java
index 7ebd0d18..a0d23662 100644
--- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/item/ConfigItem.java
+++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/item/ConfigItem.java
@@ -1,7 +1,7 @@
package net.Indyuce.mmocore.util.item;
import io.lumine.mythic.lib.UtilityMethods;
-import org.apache.commons.lang.Validate;
+import io.lumine.mythic.lib.util.lang3.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.Nullable;
diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ClassScriptListener.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ClassScriptListener.java
index 66d70333..8342b7c9 100644
--- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ClassScriptListener.java
+++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/ClassScriptListener.java
@@ -3,7 +3,7 @@ package net.Indyuce.mmocore.listener;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
-import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
import net.Indyuce.mmocore.script.trigger.MMOCoreTriggerType;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
@@ -29,13 +29,14 @@ public class ClassScriptListener implements Listener {
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
- public void onLevelUp(PlayerLevelUpEvent event) {
+ public void onLevelUp(PlayerLevelChangeEvent event) {
// With delay
- Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
- final MMOPlayerData caster = event.getData().getMMOPlayerData();
- caster.triggerSkills(MMOCoreTriggerType.LEVEL_UP, null);
- });
+ if (event.getReason() == PlayerLevelChangeEvent.Reason.LEVEL_UP)
+ Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
+ final MMOPlayerData caster = event.getData().getMMOPlayerData();
+ caster.triggerSkills(MMOCoreTriggerType.LEVEL_UP, null);
+ });
}
/* @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java
index 2d4bf4a7..5a5fc9b6 100644
--- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java
+++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/GuildListener.java
@@ -22,15 +22,17 @@ public class GuildListener implements Listener {
event.setCancelled(true);
- // Run it sync
+ // Run it on main server thread
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
- var rawMessage = event.getMessage().substring(MMOCore.plugin.nativeGuildManager.getConfig().getPrefix().length());
- var message = Message.GUILD_CHAT.prepare("player", data.getPlayer().getName(), "tag", data.getGuild().getTag(), "message", rawMessage);
- GuildChatEvent called = new GuildChatEvent(data, message.getRawContent());
+ final var rawMessage = event.getMessage().substring(MMOCore.plugin.nativeGuildManager.getConfig().getPrefix().length());
+ final var called = new GuildChatEvent(data, rawMessage);
Bukkit.getPluginManager().callEvent(called);
- if (!called.isCancelled()) data.getGuild().forEachMember(member -> {
+ if (called.isCancelled() || called.getMessage() == null) return;
+
+ data.getGuild().forEachMember(member -> {
Player online = Bukkit.getPlayer(member);
- if (online != null) message.send(online);
+ if (online != null)
+ Message.GUILD_CHAT.send(online, "player", data.getPlayer().getName(), "tag", data.getGuild().getTag(), "message", called.getMessage());
});
});
}
diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java
index ad489953..fc27a529 100644
--- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java
+++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/PlayerListener.java
@@ -2,13 +2,12 @@ package net.Indyuce.mmocore.listener;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
-import io.lumine.mythic.lib.api.event.SynchronizedDataLoadEvent;
-import io.lumine.mythic.lib.version.Attributes;
import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent;
+import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
-import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -20,35 +19,6 @@ import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
public class PlayerListener implements Listener {
- /**
- * Script ran when the full MMO plugin data is synchronized. Player Health
- * is only updated now otherwise other MMO plugins would not have the time
- * to register their stats beforehand.
- */
- @EventHandler(priority = EventPriority.HIGHEST)
- public void a(SynchronizedDataLoadEvent event) {
- if (event.syncIsFull()) {
- final PlayerData playerData = PlayerData.get(event.getHolder().getUniqueId());
- final Player player = playerData.getPlayer();
-
- playerData.setupSkillTrees();
- playerData.applyTemporaryTriggers();
- playerData.getStats().updateStats(true); // TODO maybe duplicate?
-
- /*
- * If the player is not dead and the health is 0, this means that the data was
- * missing from the database, and it should give full health to the player. It
- * must account for the edge case where the player is dead.
- */
- if (playerData.isOnline() && !player.isDead()) {
- final double cachedHealth = playerData.getCachedHealth(),
- maxHealth = player.getAttribute(Attributes.MAX_HEALTH).getValue(),
- fixedHealth = MMOCoreUtils.fixResource(cachedHealth, maxHealth);
- player.setHealth(fixedHealth);
- }
- }
- }
-
/**
* Updates the player's combat log data every time he hits an entity, or
* gets hit by an entity or a projectile sent by another entity
@@ -79,12 +49,19 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void resourceBukkitInterface(PlayerResourceUpdateEvent event) {
if (event.getResource() == PlayerResource.HEALTH) {
- final EntityRegainHealthEvent bukkitEvent = new EntityRegainHealthEvent(event.getPlayer(), event.getAmount(), RegainReason.CUSTOM);
+ final var bukkitEvent = new EntityRegainHealthEvent(event.getPlayer(), event.getDifference(), RegainReason.CUSTOM);
Bukkit.getPluginManager().callEvent(bukkitEvent);
// Update event values
- event.setAmount(bukkitEvent.getAmount());
+ event.setNewAmount(event.getOldAmount() + bukkitEvent.getAmount());
event.setCancelled(bukkitEvent.isCancelled());
}
}
+
+ @SuppressWarnings("deprecation")
+ @EventHandler
+ public void backwardsCompatibilityEvent(PlayerLevelChangeEvent event) {
+ if (event.getReason() == PlayerLevelChangeEvent.Reason.LEVEL_UP)
+ Bukkit.getPluginManager().callEvent(new PlayerLevelUpEvent(event.getData(), event.getProfession(), event.getOldLevel(), event.getNewLevel()));
+ }
}
diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/WaypointsListener.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/WaypointsListener.java
index 44a45c1b..6c6c393a 100644
--- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/WaypointsListener.java
+++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/WaypointsListener.java
@@ -1,10 +1,8 @@
package net.Indyuce.mmocore.listener;
import io.lumine.mythic.lib.api.item.NBTItem;
-import io.lumine.mythic.lib.version.VParticle;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
-import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.player.Message;
import net.Indyuce.mmocore.waypoint.Waypoint;
@@ -34,8 +32,6 @@ public class WaypointsListener implements Listener {
PlayerData playerData = PlayerData.get(player);
if (waypoint.hasOption(WaypointOption.UNLOCKABLE) && !playerData.hasWaypoint(waypoint)) {
playerData.unlockWaypoint(waypoint);
- new SmallParticleEffect(player, VParticle.WITCH.get()); // TODO move to PlayerMessage
- Message.WAYPOINT_UNLOCK.send(playerData, "waypoint", waypoint.getName());
return;
}
diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/profession/PlayerCollectStats.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/profession/PlayerCollectStats.java
index 7cc6e58d..64e55247 100644
--- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/profession/PlayerCollectStats.java
+++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/profession/PlayerCollectStats.java
@@ -2,10 +2,10 @@ package net.Indyuce.mmocore.listener.profession;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.version.Sounds;
import io.lumine.mythic.lib.version.VParticle;
import io.lumine.mythic.lib.version.VPotionEffectType;
import net.Indyuce.mmocore.api.event.CustomBlockMineEvent;
-import net.Indyuce.mmocore.loot.chest.particle.SmallParticleEffect;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -22,10 +22,14 @@ public class PlayerCollectStats implements Listener {
public void a(CustomBlockMineEvent event) {
Player player = event.getPlayer();
+ // TODO de-hardcode these into custom stats using scripts or whatever
+
// Give haste if right enchant
double h = event.getData().getStats().getStat("GATHERING_HASTE");
if (h > 0 && RANDOM.nextDouble() < h * .045) {
- new SmallParticleEffect(player, VParticle.INSTANT_EFFECT.get());
+ // Not version compliant
+ //new SmallParticleEffect(player, VParticle.FIREWORK.get());
+ player.playSound(player.getLocation(), Sounds.ENTITY_EXPERIENCE_ORB_PICKUP, 0.5f, 1.5f);
UtilityMethods.forcePotionEffect(player, VPotionEffectType.HASTE.get(), h / 2, (int) (1 + h / 7));
}
diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml
index 6ff725b2..a1026055 100644
--- a/MMOCore-Dist/src/main/resources/config.yml
+++ b/MMOCore-Dist/src/main/resources/config.yml
@@ -26,6 +26,8 @@ mysql:
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
+ userdata-table-name: 'mmocore_playerdata'
+
# The default values for all playerdata
# All new players will start with these values
default-playerdata:
@@ -35,10 +37,10 @@ default-playerdata:
skill-realloc-points: 0
attribute-points: 0
attribute-realloc-points: 0
- health: 20
- mana: 0
- stellium: 0
- stamina: 0
+ health: 1000 # High enough so that the player
+ mana: 1000 # starts with full hp/mana/...
+ stellium: 1000 # These values will be clamped to
+ stamina: 1000 # max resource value!
custom-mining:
@@ -295,8 +297,10 @@ combat-log:
- WITHER
# Whether or not the default class should save information (level,
-# skills, etc.) when selecting a new class
-save-default-class-info: false
+# skills, etc.) when selecting a new class. Turn this off if you
+# do not plan on using the Default player class if, for instance,
+# players are asked to select a class right away on login.
+save-default-class-info: true
waypoints:
@@ -325,28 +329,6 @@ resource-bar-colors:
stamina-half: 'DARK_GREEN'
stamina-empty: 'WHITE'
-# Whether the admin commands should display
-# the result of the command when ran.
-# For Example: "Players Level is now 10."
-#
-# Accepted Values:
-# true - Always verbose
-# player - Only verbose when ran from a player
-# console - Only verbose when ran from console
-# false - Never verbose
-command-verbose:
- attribute: true
- skill: true
- class: true
- experience: true
- level: true
- nocd: true
- skill-tree-points: true
- points: true
- reset: true
- resource: true
- waypoint: true
-
# Requires WorldGuard to work. Do NOT enable unless
# you have WG to avoid weird interact rule issues!
#
diff --git a/MMOCore-Dist/src/main/resources/default/gui/attribute-view.yml b/MMOCore-Dist/src/main/resources/default/gui/attribute-view.yml
index 10576f5a..661ea9a1 100644
--- a/MMOCore-Dist/src/main/resources/default/gui/attribute-view.yml
+++ b/MMOCore-Dist/src/main/resources/default/gui/attribute-view.yml
@@ -1,4 +1,3 @@
-
# GUI display name
name: Player Attributes
@@ -8,68 +7,68 @@ name: Player Attributes
slots: 27
items:
- reallocate:
- slots: [26]
- function: reallocation
- # You can set custom model data int and string here
- #custom_model_data_string: 'something'
- #custom_model_data: 1234
- item: CAULDRON
- name: '&aAttribute Points'
- lore:
- - ''
- - 'You have spent a total of &6{total}&7 attribute points.'
- - '&7Right click to reallocate them.'
- - ''
- - '&eCosts 1 attribute reallocation point.'
- - '&e◆ Attribute Reallocation Points: &6{points}'
- str:
- slots: [11]
- function: attribute_strength
- name: '&a{name}'
- item: GOLDEN_APPLE
- lore: # {buffs} returns amount of buffs
- - ''
- - '&7Points Spent: &6{spent}&7/&6{max}'
- - '&7Current {name}: &6&l{current}'
- - ''
- - '&8When Leveled Up:'
- - '&7 +{buff_weapon_damage}% Weapon Damage (&a+{total_weapon_damage}%&7)'
- - '&7 +{buff_max_health}% Max Health (&a+{total_max_health}%&7)'
- - ''
- - '&eClick to level up for 1 attribute point.'
- - '&e◆ Current Attribute Points: {attribute_points}'
- dex:
- slots: [13]
- function: attribute_dexterity
- name: '&a{name}'
- item: LEATHER_BOOTS
- hide-flags: true
- lore:
- - ''
- - '&7Points Spent: &6{spent}&7/&6{max}'
- - '&7Current {name}: &6&l{current}'
- - ''
- - '&8When Leveled Up:'
- - '&7 +{buff_physical_damage}% Physical Damage (&a+{total_physical_damage}%&7)'
- - '&7 +{buff_projectile_damage}% Projectile Damage (&a+{total_projectile_damage}%&7)'
- - '&7 +{buff_attack_speed}% Attack Speed (&a+{total_attack_speed}%&7)'
- - ''
- - '&eClick to level up for 1 attribute point.'
- - '&e◆ Current Attribute Points: {attribute_points}'
- int:
- slots: [15]
- function: attribute_intelligence
- name: '&a{name}'
- item: BOOK
- lore:
- - ''
- - '&7Points Spent: &6{spent}&7/&6{max}'
- - '&7Current {name}: &6&l{current}'
- - ''
- - '&8When Leveled Up:'
- - '&7 +{buff_magic_damage}% Magic Damage (&a+{total_magic_damage}%&7)'
- - '&7 +{buff_cooldown_reduction}% Cooldown Reduction (&a+{total_cooldown_reduction}%&7)'
- - ''
- - '&eClick to level up for 1 attribute point.'
- - '&e◆ Current Attribute Points: {attribute_points}'
+ reallocate:
+ slots: [ 26 ]
+ function: reallocation
+ # You can set custom model data int and string here
+ #custom_model_data_string: 'something'
+ #custom_model_data: 1234
+ item: CAULDRON
+ name: '&aAttribute Points'
+ lore:
+ - ''
+ - 'You have spent a total of &6{total}&7 attribute points.'
+ - '&7Right click to reallocate them.'
+ - ''
+ - '&eCosts 1 attribute reallocation point.'
+ - '&e◆ Attribute Reallocation Points: &6{points}'
+ str:
+ slots: [ 11 ]
+ function: attribute_strength
+ name: '&a{name}'
+ item: GOLDEN_APPLE
+ lore: # {buffs} returns amount of buffs
+ - ''
+ - '&7Points Spent: &6{spent}&7/&6{max}'
+ - '&7Current {name}: &6&l{current}'
+ - ''
+ - '&8When Leveled Up:'
+ - '&7 +{buff_weapon_damage}% Weapon Damage (&a+{total_weapon_damage}%&7)'
+ - '&7 +{buff_max_health}% Max Health (&a+{total_max_health}%&7)'
+ - ''
+ - '&eClick to level up for 1 attribute point.'
+ - '&e◆ Current Attribute Points: {attribute_points}'
+ dex:
+ slots: [ 13 ]
+ function: attribute_dexterity
+ name: '&a{name}'
+ item: LEATHER_BOOTS
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - ''
+ - '&7Points Spent: &6{spent}&7/&6{max}'
+ - '&7Current {name}: &6&l{current}'
+ - ''
+ - '&8When Leveled Up:'
+ - '&7 +{buff_physical_damage}% Physical Damage (&a+{total_physical_damage}%&7)'
+ - '&7 +{buff_projectile_damage}% Projectile Damage (&a+{total_projectile_damage}%&7)'
+ - '&7 +{buff_attack_speed}% Attack Speed (&a+{total_attack_speed}%&7)'
+ - ''
+ - '&eClick to level up for 1 attribute point.'
+ - '&e◆ Current Attribute Points: {attribute_points}'
+ int:
+ slots: [ 15 ]
+ function: attribute_intelligence
+ name: '&a{name}'
+ item: BOOK
+ lore:
+ - ''
+ - '&7Points Spent: &6{spent}&7/&6{max}'
+ - '&7Current {name}: &6&l{current}'
+ - ''
+ - '&8When Leveled Up:'
+ - '&7 +{buff_magic_damage}% Magic Damage (&a+{total_magic_damage}%&7)'
+ - '&7 +{buff_cooldown_reduction}% Cooldown Reduction (&a+{total_cooldown_reduction}%&7)'
+ - ''
+ - '&eClick to level up for 1 attribute point.'
+ - '&e◆ Current Attribute Points: {attribute_points}'
diff --git a/MMOCore-Dist/src/main/resources/default/gui/class-select.yml b/MMOCore-Dist/src/main/resources/default/gui/class-select.yml
index 4c83add0..5039eab9 100644
--- a/MMOCore-Dist/src/main/resources/default/gui/class-select.yml
+++ b/MMOCore-Dist/src/main/resources/default/gui/class-select.yml
@@ -1,4 +1,3 @@
-
# GUI display name
name: Class Selection
@@ -8,55 +7,53 @@ slots: 27
items:
- class-rogue:
- slots: [11]
- function: class-rogue
- name: '&a&lThe Rogue'
- hide-flags: true
- # You can set custom model data int and string here
- #custom-model-data-string: 'whatever'
- #custom-model-data: 1234
- lore:
- - '{lore}'
- - ''
- - '{attribute-lore}'
+ class-rogue:
+ slots: [ 11 ]
+ function: class-rogue
+ name: '&a&lThe Rogue'
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ # You can set custom model data int and string here
+ #custom-model-data-string: 'whatever'
+ #custom-model-data: 1234
+ lore:
+ - '{lore}'
+ - ''
+ - '{attribute-lore}'
- class-mage:
- slots: [12]
- function: class-mage
- name: '&a&lThe Mage'
- hide-flags: true
- lore:
- - '{lore}'
- - ''
- - '{attribute-lore}'
+ class-mage:
+ slots: [ 12 ]
+ function: class-mage
+ name: '&a&lThe Mage'
+ lore:
+ - '{lore}'
+ - ''
+ - '{attribute-lore}'
- class-marksman:
- slots: [13]
- function: class-marksman
- name: '&a&lThe Marksman'
- hide-flags: true
- lore:
- - '{lore}'
- - ''
- - '{attribute-lore}'
+ class-marksman:
+ slots: [ 13 ]
+ function: class-marksman
+ name: '&a&lThe Marksman'
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - '{lore}'
+ - ''
+ - '{attribute-lore}'
- class-warrior:
- slots: [14]
- function: class-warrior
- name: '&a&lThe Warrior'
- hide-flags: true
- lore:
- - '{lore}'
- - ''
- - '{attribute-lore}'
+ class-warrior:
+ slots: [ 14 ]
+ function: class-warrior
+ name: '&a&lThe Warrior'
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - '{lore}'
+ - ''
+ - '{attribute-lore}'
- class-paladin:
- slots: [15]
- function: class-paladin
- name: '&a&lThe Paladin'
- hide-flags: true
- lore:
- - '{lore}'
- - ''
- - '{attribute-lore}'
+ class-paladin:
+ slots: [ 15 ]
+ function: class-paladin
+ name: '&a&lThe Paladin'
+ lore:
+ - '{lore}'
+ - ''
+ - '{attribute-lore}'
diff --git a/MMOCore-Dist/src/main/resources/default/gui/player-stats.yml b/MMOCore-Dist/src/main/resources/default/gui/player-stats.yml
index 19b1efc9..b39cae2b 100644
--- a/MMOCore-Dist/src/main/resources/default/gui/player-stats.yml
+++ b/MMOCore-Dist/src/main/resources/default/gui/player-stats.yml
@@ -1,4 +1,3 @@
-
# GUI display name
name: Your Character
@@ -7,243 +6,241 @@ name: Your Character
slots: 54
items:
- mining_profession:
- slots: [10]
- function: profession_mining
- item: IRON_PICKAXE
- name: '&aMining'
- hide-flags: true
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oMining unlocks rare ores and raw materials.'
- - '&7&oThis is vital to your rise in power and strength,'
- - '&7&omine frequently for unique and rare drops.'
- # You can set custom model data int and string here
- #custom_model_data_string: 'something'
- #custom_model_data: 1234
- woodcutting_profession:
- slots: [11]
- function: profession_woodcutting
- item: IRON_AXE
- name: '&aWoodcutting'
- hide-flags: true
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oThough it may seem like a boring task, woodcutting'
- - '&7&ois vital to obtaining materials used for crafting and trade,'
- - '&7&oand will help give you the upper hand in the arcane ways.'
- farming_profession:
- slots: [12]
- function: profession_farming
- item: IRON_HOE
- name: '&aFarming'
- hide-flags: true
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oWith tons of new food and consumable recipes,'
- - '&7&oyou will need to stay on top of the crops in order'
- - '&7&oto obtain the best food and drinks to keep yourself healthy.'
- fishing_profession:
- slots: [19]
- function: profession_fishing
- item: FISHING_ROD
- name: '&aFishing'
- hide-flags: true
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oFishing may give you unique drops you'
- - '&7&ocan''t find anywhere else. The more you'
- - '&7&ofish, the easier it becomes to find these.'
- - ''
- - '&7Fishing Strength: &c%mmocore_stat_fishing_strength%%'
- - '&7Crit Fishing Rate: &c%mmocore_stat_critical_fishing_chance%%'
- - '&7Crit Failure Rate: &c%mmocore_stat_critical_fishing_failure_chance%%'
- alchemy_profession:
- slots: [20]
- function: profession_alchemy
- item: BREWING_STAND
- name: '&aAlchemy'
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oIn a world where you are no longer limited to'
- - '&7&osimple potions, try learning tons of new brewing'
- - '&7&orecipes to give yourself the edge on the battlefield.'
- smithing_profession:
- slots: [21]
- function: profession_smithing
- item: ANVIL
- name: '&aSmithing'
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oStabbing enemies and having them laugh is the worst,'
- - '&7&oPractice makes perfect when it comes to smithing.'
- - '&7&o&nWar is won by the man with the pointiest stick.'
- enchanting_profession:
- slots: [28]
- function: profession_enchanting
- item: ENCHANTED_BOOK
- name: '&aEnchanting'
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oLorem ipsum dolor sit amet, consectetur'
- - '&7&oadipiscing elit. Proin malesuada maximus massa,'
- - '&7&osodales imperdiet sapien fermentum at.'
- smelting_profession:
- slots: [29]
- function: profession_smelting
- item: FURNACE
- name: '&aSmelting'
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - ''
- - '&7&oSinging your eyebrows will become standard.'
- - '&7&oYour long hours over the heat will make you'
- - '&7&ofaster and more efficient with your oven.'
- boost_display:
- slots: [47,48,49,50,51]
- function: boost
- item: BARRIER
+ mining_profession:
+ slots: [ 10 ]
+ function: profession_mining
+ item: IRON_PICKAXE
+ name: '&aMining'
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oMining unlocks rare ores and raw materials.'
+ - '&7&oThis is vital to your rise in power and strength,'
+ - '&7&omine frequently for unique and rare drops.'
+ # You can set custom model data int and string here
+ #custom_model_data_string: 'something'
+ #custom_model_data: 1234
+ woodcutting_profession:
+ slots: [ 11 ]
+ function: profession_woodcutting
+ item: IRON_AXE
+ name: '&aWoodcutting'
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oThough it may seem like a boring task, woodcutting'
+ - '&7&ois vital to obtaining materials used for crafting and trade,'
+ - '&7&oand will help give you the upper hand in the arcane ways.'
+ farming_profession:
+ slots: [ 12 ]
+ function: profession_farming
+ item: IRON_HOE
+ name: '&aFarming'
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oWith tons of new food and consumable recipes,'
+ - '&7&oyou will need to stay on top of the crops in order'
+ - '&7&oto obtain the best food and drinks to keep yourself healthy.'
+ fishing_profession:
+ slots: [ 19 ]
+ function: profession_fishing
+ item: FISHING_ROD
+ name: '&aFishing'
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oFishing may give you unique drops you'
+ - '&7&ocan''t find anywhere else. The more you'
+ - '&7&ofish, the easier it becomes to find these.'
+ - ''
+ - '&7Fishing Strength: &c%mmocore_stat_fishing_strength%%'
+ - '&7Crit Fishing Rate: &c%mmocore_stat_critical_fishing_chance%%'
+ - '&7Crit Failure Rate: &c%mmocore_stat_critical_fishing_failure_chance%%'
+ alchemy_profession:
+ slots: [ 20 ]
+ function: profession_alchemy
+ item: BREWING_STAND
+ name: '&aAlchemy'
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oIn a world where you are no longer limited to'
+ - '&7&osimple potions, try learning tons of new brewing'
+ - '&7&orecipes to give yourself the edge on the battlefield.'
+ smithing_profession:
+ slots: [ 21 ]
+ function: profession_smithing
+ item: ANVIL
+ name: '&aSmithing'
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oStabbing enemies and having them laugh is the worst,'
+ - '&7&oPractice makes perfect when it comes to smithing.'
+ - '&7&o&nWar is won by the man with the pointiest stick.'
+ enchanting_profession:
+ slots: [ 28 ]
+ function: profession_enchanting
+ item: ENCHANTED_BOOK
+ name: '&aEnchanting'
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oLorem ipsum dolor sit amet, consectetur'
+ - '&7&oadipiscing elit. Proin malesuada maximus massa,'
+ - '&7&osodales imperdiet sapien fermentum at.'
+ smelting_profession:
+ slots: [ 29 ]
+ function: profession_smelting
+ item: FURNACE
+ name: '&aSmelting'
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - ''
+ - '&7&oSinging your eyebrows will become standard.'
+ - '&7&oYour long hours over the heat will make you'
+ - '&7&ofaster and more efficient with your oven.'
+ boost_display:
+ slots: [ 47,48,49,50,51 ]
+ function: boost
+ item: BARRIER
- # Language options
- booster_expired: '&cExpired!'
+ # Language options
+ booster_expired: '&cExpired!'
- no-boost:
- item: GRAY_STAINED_GLASS_PANE
- name: '&aNo Booster'
- lore: {}
-
- # Profession experience boosters
- profession:
- item: EXPERIENCE_BOTTLE
- name: '&aEXP Boost'
- lore:
- - '&7Amount: &6+{value}%'
- - '&7Time left: &6{left}'
- - '&7Profession: &6{profession}'
- - '&7'
- - '&eStarted by {author}'
-
- # Main class experience boosters
- main-level:
- item: EXPERIENCE_BOTTLE
- name: '&aEXP Boost'
- lore:
- - '&7Amount: &6+{value}%'
- - '&7Time left: &6{left}'
- - '&7'
- - '&eStarted by {author}'
- boost_next_page:
- slots: [52]
- function: boost-next
- item: PLAYER_HEAD
- texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTliZjMyOTJlMTI2YTEwNWI1NGViYTcxM2FhMWIxNTJkNTQxYTFkODkzODgyOWM1NjM2NGQxNzhlZDIyYmYifX19
- name: '&aNext'
- lore: {}
- boost_prev_page:
- slots: [46]
- function: boost-previous
- item: PLAYER_HEAD
- texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==
- name: '&aPrevious'
- lore: {}
- party_info:
- slots: [16]
- function: party
- item: CAKE
- name: '&aParty Morale'
- lore:
- - '&7&oPlaying with your friends'
- - '&7&ogreatly encourages you!'
- - ''
- - '&7Party Bonuses ({count}):'
- - '&8+{buff_additional_experience}% Experience Earned!'
- - '&8+{buff_health_regeneration} Health Regeneration'
- player_progression:
- slots: [15]
- function: profile
- item: PLAYER_HEAD
- name: '&e{player}'
- lore:
- - ''
- - '&7Current Level: &e{level}'
- - '&7Progression: &e{exp} / {next_level}'
- - '&8[&e{progress}&8] &e{percent}%'
- - '&7Skill Points: &6{skill_points}'
- - ''
- - '&7Current Class: &c{class}'
- - '&7Class Points: &c{class_points}'
- attribute_physical:
- slots: [32]
- function: stats
- name: '&cPhysical'
- item: GOLDEN_APPLE
- hide-flags: true
- lore:
- - ''
- - 'Current Strength: &c&l{attribute_strength}'
- - ''
- - '✦ Attack Damage: &c{attack_damage} &7(&c{attack_damage_base} &7+ &c{attack_damage_extra}&7)'
- - '✦ Attack Speed: &c{attack_speed} &7(&c{attack_speed_base} &7+ &c{attack_speed_extra}&7)'
- - ''
- - '❤ Max Health: &c{max_health} &7(&c{max_health_base} &7+ &c{max_health_extra}&7)'
- - '❤ Health Regen: &c{health_regeneration} &7(&c{health_regeneration_base} &7+ &c{health_regeneration_extra}&7)'
- - ''
- - '✤ Max Stamina: &9{max_stamina} &7(&9{max_stamina_base} &7+ &9{max_stamina_extra}&7)'
- - '✤ Stamina Regen: &9{stamina_regeneration} &7(&9{stamina_regeneration_base} &7+ &9{stamina_regeneration_extra}&7)'
- - ''
- - '❖ Armor: &c{armor} &7(&c{armor_base} &7+ &c{armor_extra}&7)'
- - '❖ Armor Toughness: &c{armor_toughness} &7(&c{armor_toughness_base} &7+ &c{armor_toughness_extra}&7)'
- attribute_dexterity:
- slots: [33]
- function: stats
- name: '&aDexterity'
- item: LEATHER_BOOTS
- hide-flags: true
- lore:
- - ''
- - 'Current Dexterity: &a&l{attribute_dexterity}'
- - ''
- - '✤ Knockback Resistance: &f{knockback_resistance} &7(&f{knockback_resistance_base} &7+ &f{knockback_resistance_extra}&7)'
- - '✤ Movement Speed: &f{movement_speed} &7(&f{movement_speed_base} &7+ &f{movement_speed_extra}&7)'
- - '✤ Speed Malus Reduction: &f{speed_malus_reduction}% &7(&f{speed_malus_reduction_base} &7+ &f{speed_malus_reduction_extra}&7)'
- attribute_intelligence:
- slots: [34]
- function: stats
- name: '&bIntellect'
- item: BOOK
- hide-flags: true
- lore:
- - ''
- - 'Current Intelligence: &b&l{attribute_intelligence}'
- - ''
- - '✤ Max Mana: &9{max_mana} &7(&9{max_mana_base} &7+ &9{max_mana_extra}&7)'
- - '✤ Mana Regen: &9{mana_regeneration} &7(&9{mana_regeneration_base} &7+ &9{mana_regeneration_extra}&7)'
- - ''
- - '✤ Skill Cooldown Reduction: &9{cooldown_reduction} &7(&9{cooldown_reduction_base} &7+ &9{cooldown_reduction_extra}&7)'
- - '✤ Extra Experience: &9{additional_experience} &7(&9{additional_experience_base} &7+ &9{additional_experience_extra}&7)'
- - ''
- - '❊ Max Stellium: &9{max_stellium} &7(&9{max_stellium_base} &7+ &9{max_stellium_extra}&7)'
- - '❊ Stellium Regen: &9{stellium_regeneration} &7(&9{stellium_regeneration_base} &7+ &9{stellium_regeneration_extra}&7)'
+ no-boost:
+ item: GRAY_STAINED_GLASS_PANE
+ name: '&aNo Booster'
+ lore: { }
+
+ # Profession experience boosters
+ profession:
+ item: EXPERIENCE_BOTTLE
+ name: '&aEXP Boost'
+ lore:
+ - '&7Amount: &6+{value}%'
+ - '&7Time left: &6{left}'
+ - '&7Profession: &6{profession}'
+ - '&7'
+ - '&eStarted by {author}'
+
+ # Main class experience boosters
+ main-level:
+ item: EXPERIENCE_BOTTLE
+ name: '&aEXP Boost'
+ lore:
+ - '&7Amount: &6+{value}%'
+ - '&7Time left: &6{left}'
+ - '&7'
+ - '&eStarted by {author}'
+ boost_next_page:
+ slots: [ 52 ]
+ function: boost-next
+ item: PLAYER_HEAD
+ texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTliZjMyOTJlMTI2YTEwNWI1NGViYTcxM2FhMWIxNTJkNTQxYTFkODkzODgyOWM1NjM2NGQxNzhlZDIyYmYifX19
+ name: '&aNext'
+ lore: { }
+ boost_prev_page:
+ slots: [ 46 ]
+ function: boost-previous
+ item: PLAYER_HEAD
+ texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==
+ name: '&aPrevious'
+ lore: { }
+ party_info:
+ slots: [ 16 ]
+ function: party
+ item: CAKE
+ name: '&aParty Morale'
+ lore:
+ - '&7&oPlaying with your friends'
+ - '&7&ogreatly encourages you!'
+ - ''
+ - '&7Party Bonuses ({count}):'
+ - '&8+{buff_additional_experience}% Experience Earned!'
+ - '&8+{buff_health_regeneration} Health Regeneration'
+ player_progression:
+ slots: [ 15 ]
+ function: profile
+ item: PLAYER_HEAD
+ name: '&e{player}'
+ lore:
+ - ''
+ - '&7Current Level: &e{level}'
+ - '&7Progression: &e{exp} / {next_level}'
+ - '&8[&e{progress}&8] &e{percent}%'
+ - '&7Skill Points: &6{skill_points}'
+ - ''
+ - '&7Current Class: &c{class}'
+ - '&7Class Points: &c{class_points}'
+ attribute_physical:
+ slots: [ 32 ]
+ function: stats
+ name: '&cPhysical'
+ item: GOLDEN_APPLE
+ lore:
+ - ''
+ - 'Current Strength: &c&l{attribute_strength}'
+ - ''
+ - '✦ Attack Damage: &c{attack_damage} &7(&c{attack_damage_base} &7+ &c{attack_damage_extra}&7)'
+ - '✦ Attack Speed: &c{attack_speed} &7(&c{attack_speed_base} &7+ &c{attack_speed_extra}&7)'
+ - ''
+ - '❤ Max Health: &c{max_health} &7(&c{max_health_base} &7+ &c{max_health_extra}&7)'
+ - '❤ Health Regen: &c{health_regeneration} &7(&c{health_regeneration_base} &7+ &c{health_regeneration_extra}&7)'
+ - ''
+ - '✤ Max Stamina: &9{max_stamina} &7(&9{max_stamina_base} &7+ &9{max_stamina_extra}&7)'
+ - '✤ Stamina Regen: &9{stamina_regeneration} &7(&9{stamina_regeneration_base} &7+ &9{stamina_regeneration_extra}&7)'
+ - ''
+ - '❖ Armor: &c{armor} &7(&c{armor_base} &7+ &c{armor_extra}&7)'
+ - '❖ Armor Toughness: &c{armor_toughness} &7(&c{armor_toughness_base} &7+ &c{armor_toughness_extra}&7)'
+ attribute_dexterity:
+ slots: [ 33 ]
+ function: stats
+ name: '&aDexterity'
+ item: LEATHER_BOOTS
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
+ lore:
+ - ''
+ - 'Current Dexterity: &a&l{attribute_dexterity}'
+ - ''
+ - '✤ Knockback Resistance: &f{knockback_resistance} &7(&f{knockback_resistance_base} &7+ &f{knockback_resistance_extra}&7)'
+ - '✤ Movement Speed: &f{movement_speed} &7(&f{movement_speed_base} &7+ &f{movement_speed_extra}&7)'
+ - '✤ Speed Malus Reduction: &f{speed_malus_reduction}% &7(&f{speed_malus_reduction_base} &7+ &f{speed_malus_reduction_extra}&7)'
+ attribute_intelligence:
+ slots: [ 34 ]
+ function: stats
+ name: '&bIntellect'
+ item: BOOK
+ lore:
+ - ''
+ - 'Current Intelligence: &b&l{attribute_intelligence}'
+ - ''
+ - '✤ Max Mana: &9{max_mana} &7(&9{max_mana_base} &7+ &9{max_mana_extra}&7)'
+ - '✤ Mana Regen: &9{mana_regeneration} &7(&9{mana_regeneration_base} &7+ &9{mana_regeneration_extra}&7)'
+ - ''
+ - '✤ Skill Cooldown Reduction: &9{cooldown_reduction} &7(&9{cooldown_reduction_base} &7+ &9{cooldown_reduction_extra}&7)'
+ - '✤ Extra Experience: &9{additional_experience} &7(&9{additional_experience_base} &7+ &9{additional_experience_extra}&7)'
+ - ''
+ - '❊ Max Stellium: &9{max_stellium} &7(&9{max_stellium_base} &7+ &9{max_stellium_extra}&7)'
+ - '❊ Stellium Regen: &9{stellium_regeneration} &7(&9{stellium_regeneration_base} &7+ &9{stellium_regeneration_extra}&7)'
diff --git a/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml b/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml
index 4cb8bf1e..30cce5a7 100644
--- a/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml
+++ b/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml
@@ -11,7 +11,7 @@ items:
function: skill
name: '&a{skill} &6[{level}]'
- hide-flags: true
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
# You can set custom model data int and string here
#custom_model_data_string: 'something'
#custom_model_data: 1234
diff --git a/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml b/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml
index d3e2b747..24bf04fe 100644
--- a/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml
+++ b/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml
@@ -86,7 +86,7 @@ items:
# You can set custom model data int and string here
#custom_model_data_string: 'something'
#custom_model_data: 1234
- hide-flags: true
+ item-flags: [ 'HIDE_ATTRIBUTES' ]
#The lore that will be displayed after the lore of the node.
#The {node-lore} placeholder will be replaced by the lore specified in the skill tree node config.
#All the placeholders you see here can also be used in the node lore.
@@ -108,7 +108,7 @@ items:
- ''
- '&e◆ Points Spent:&6 {point-spent}&e/&6{max-point-spent}'
- '&e◆ Available: &6{skill-tree-points} &e+ &6{global-points} &eGlobal'
- path-lore: []
+ path-lore: [ ]
#This is the name that will be displayed for each status.
status-names:
diff --git a/MMOCore-Dist/src/main/resources/default/messages.yml b/MMOCore-Dist/src/main/resources/default/messages.yml
index 332da041..69348963 100644
--- a/MMOCore-Dist/src/main/resources/default/messages.yml
+++ b/MMOCore-Dist/src/main/resources/default/messages.yml
@@ -4,6 +4,9 @@
level-up:
sound: ENTITY_PLAYER_LEVELUP,1,2
+ # Runs a script on level up. This script is implemented
+ # inside file MythicLib/scripts/mmocore_scripts.yml
+ script: mmocore_level_up_effect
message:
- ''
- '&eCongratulations, you reached level &6{level}&e!'
@@ -76,7 +79,7 @@ no-skill-placeholder: 'No Skill Bound' # Can only be a string
# PvP Mode
###################################################
pvp-mode:
- cooldown: '&cPlease wait {remaining} seconds to use this command again.'
+ cooldown: '&cPlease wait {remaining}s before using this command again.'
# When you cannot hit another player
cannot-hit:
@@ -156,6 +159,9 @@ leave-combat: '%&aYou left combat.'
waypoint:
unlock:
message: '&eYou unlocked the &6{waypoint} &ewaypoint!'
+ # Runs a script on waypoint unlock. This script is implemented
+ # inside file MythicLib/scripts/mmocore_scripts.yml
+ script: mmocore_waypoint_unlock_effect
sound: UI_TOAST_CHALLENGE_COMPLETE,1,1.2
unlock-book:
message: '&eYou unlocked the &6{waypoint} &ewaypoint!'
@@ -183,6 +189,7 @@ waypoint:
# Economy features
###################################################
+gold-pouch-ui-name: 'Gold Pouch'
deposit:
success:
message: '&eYou successfully deposited &6{worth}g&e.'
@@ -212,6 +219,9 @@ friend-cant-friend-yourself:
friend-already:
message: '&cYou are already friends with {player}.'
sound: ENTITY_VILLAGER_NO
+friend-no-pending-invite:
+ message: '&cYou do not have any pending friend request.'
+ sound: ENTITY_VILLAGER_NO
friend-request-denied:
message: '&cYou denied the friend request from &6{player}&c.'
@@ -228,10 +238,12 @@ friend-sent-request:
sound: ENTITY_EXPERIENCE_ORB_PICKUP
friend-now: '&eYou are now friends with &6{player}&e.'
friend-request:
- - '{"text":""}'
- - '{"text":"&6{player} &ejust sent you a friend request!"}'
- - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/friends accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/friends deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
- - '{"text":""}'
+ json: true
+ format:
+ - '{"text":""}'
+ - '{"text":"&6{player} &ejust sent you a friend request!"}'
+ - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/friends accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/friends deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
+ - '{"text":""}'
###################################################
# Parties
@@ -242,16 +254,21 @@ party-send-invite:
message: '&eYou sent a party invite to &6{player}&e.'
sound: ENTITY_EXPERIENCE_ORB_PICKUP
party-invite:
- - '{"text":""}'
- - '{"text":"&6{player} &ehas invited you to their party!"}'
- - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/party accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/party deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
- - '{"text":""}'
+ json: true
+ format:
+ - '{"text":""}'
+ - '{"text":"&6{player} &ehas invited you to their party!"}'
+ - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/party accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/party deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
+ - '{"text":""}'
party-joined: '&eYou successfully joined &6{owner}&e''s party.'
party-joined-other: '&6{player}&e joined your party!'
party-created:
message: '&eYou successfully created a party.'
sound: ENTITY_EXPERIENCE_ORB_PICKUP
+party-no-pending-invite:
+ message: '&cYou do not have any pending party invite.'
+ sound: ENTITY_VILLAGER_NO
party-is-full:
message: '&cSorry, your party is full.'
sound: ENTITY_VILLAGER_NO
@@ -286,12 +303,17 @@ sent-guild-invite:
guild-not-online-player:
message: '&c{player} is not online.'
sound: ENTITY_VILLAGER_NO
+guild-no-pending-invite:
+ message: '&cYou do not have any pending guild invite.'
+ sound: ENTITY_VILLAGER_NO
already-in-guild: '&c{player} is already in your guild.'
guild-invite:
- - '{"text":""}'
- - '{"text":"&6{player} &ehas invited you to their guild!"}'
- - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/guild accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/guild deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
- - '{"text":""}'
+ json: true
+ format:
+ - '{"text":""}'
+ - '{"text":"&6{player} &ehas invited you to their guild!"}'
+ - '[{"text":" "},{"text":"&8[&a&lACCEPT&8]","clickEvent":{"action":"run_command","value":"/guild accept {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to accept!"}},{"text":"&r "},{"text":"&8[&c&lDENY&8]","clickEvent":{"action":"run_command","value":"/guild deny {uuid}"},"hoverEvent":{"action":"show_text","value":"&eClick to deny."}}]'
+ - '{"text":""}'
guild-is-full: '&cSorry, your guild is full.'
guild-joined: '&eYou successfully joined &6{owner}&e''s guild.'
guild-joined-other: '&6{player}&e joined your guild!'
@@ -436,7 +458,10 @@ not-skill-tree-reallocation-point:
message: '&cYou do not have 1 skill tree reallocation point.'
sound: ENTITY_VILLAGER_NO,1,2
no-skill-tree:
- message: '&cYour class doesn''t have any skill tree.'
+ message: '&cYour class does not have any skill tree.'
+ sound: ENTITY_VILLAGER_NO,1,2
+no-class-skill-tree:
+ message: '&cThis skill tree is not available to your class.'
sound: ENTITY_VILLAGER_NO,1,2
skill-tree-max-points-spent:
message: '&cYou reached the maximum points you can spend. You need to reallocate your points to rollback.'
diff --git a/MMOCore-Dist/src/main/resources/default/quests/adv-begins.yml b/MMOCore-Dist/src/main/resources/default/quests/adv-begins.yml
index 724db33d..968b343c 100644
--- a/MMOCore-Dist/src/main/resources/default/quests/adv-begins.yml
+++ b/MMOCore-Dist/src/main/resources/default/quests/adv-begins.yml
@@ -1,30 +1,37 @@
-
# Display options
name: 'The Beginning of an Adventure'
lore:
-- 'Yet another quest example.'
-- ''
-- '&eRewards:'
-- '&7► Stone Tools'
-- '&7► 30 EXP'
+ - 'Yet another quest example.'
+ - ''
+ - '&eRewards:'
+ - '&7► Stone Tools'
+ - '&7► 30 EXP'
# Parent quests
parent:
-- 'tutorial'
+ - 'tutorial'
+
+bossbar:
+ # Enable bossbar during the quest
+ enabled: true
+ # If true, it will display the percent of progress of the
+ # current objective. If false, it will display the percent of
+ # total quest progress (for instance, 33% = 1/3 objectives completed).
+ objective: true
# Quest objectives
objectives:
- 1:
- type: 'goto{world="world";x=120;y=46;z=652;range=10}'
- lore: 'Head to the camp.'
- triggers:
- - 'message{format="Good job!"}'
- 2:
- type: 'talkto{npc=0}'
- lore: 'Go talk to the Blacksmith.'
- triggers:
- - 'message{format="The blacksmith told you to come see me... ?"}'
- - 'item{type=STONE_SWORD}'
- - 'item{type=STONE_AXE}'
- - 'item{type=STONE_PICKAXE}'
- - 'experience{amount=30}'
+ 1:
+ type: 'goto{world="world";x=120;y=46;z=652;range=10}'
+ lore: 'Head to the camp.'
+ triggers:
+ - 'message{format="Good job!"}'
+ 2:
+ type: 'talkto{npc=0}'
+ lore: 'Go talk to the Blacksmith.'
+ triggers:
+ - 'message{format="The blacksmith told you to come see me... ?"}'
+ - 'item{type=STONE_SWORD}'
+ - 'item{type=STONE_AXE}'
+ - 'item{type=STONE_PICKAXE}'
+ - 'experience{amount=30}'
diff --git a/MMOCore-Dist/src/main/resources/default/quests/fetch-mango.yml b/MMOCore-Dist/src/main/resources/default/quests/fetch-mango.yml
index f71d4ef8..7a86c957 100644
--- a/MMOCore-Dist/src/main/resources/default/quests/fetch-mango.yml
+++ b/MMOCore-Dist/src/main/resources/default/quests/fetch-mango.yml
@@ -19,6 +19,14 @@ parent: []
# Put it to 0 to make it instantly redoable.
delay: 0
+bossbar:
+ # Enable bossbar during the quest
+ enabled: true
+ # If true, it will display the percent of progress of the
+ # current objective. If false, it will display the percent of
+ # total quest progress (for instance, 33% = 1/3 objectives completed).
+ objective: true
+
# Objectives the player needs to
# complete. Once they're all complete,
# the quest will end.
diff --git a/MMOCore-Dist/src/main/resources/default/quests/tutorial.yml b/MMOCore-Dist/src/main/resources/default/quests/tutorial.yml
index f3faaed5..64722d20 100644
--- a/MMOCore-Dist/src/main/resources/default/quests/tutorial.yml
+++ b/MMOCore-Dist/src/main/resources/default/quests/tutorial.yml
@@ -27,6 +27,14 @@ parent: []
# Put it to 0 to make it instantly redoable.
delay: 12
+bossbar:
+ # Enable bossbar during the quest
+ enabled: true
+ # If true, it will display the percent of progress of the
+ # current objective. If false, it will display the percent of
+ # total quest progress (for instance, 33% = 1/3 objectives completed).
+ objective: true
+
# Objectives the player needs to
# complete. Once they're all complete,
# the quest will end.
diff --git a/MMOCore-Dist/src/main/resources/default/skills/shulker-missile.yml b/MMOCore-Dist/src/main/resources/default/skills/shulker-missile.yml
new file mode 100644
index 00000000..802f4e47
--- /dev/null
+++ b/MMOCore-Dist/src/main/resources/default/skills/shulker-missile.yml
@@ -0,0 +1,35 @@
+name: Shulker Missile
+lore:
+ - 'Shoots four shulker projectiles that'
+ - 'explode on impact, dealing &c{damage} &7damage and'
+ - 'inflicting &cLevitation &7for &c{effect-duration}s&7.'
+ - ''
+ - '&e{cooldown}s Cooldown'
+ - '&9Costs {mana} {mana_name}'
+material: SHULKER_SHELL
+
+parameters:
+ timer: 0
+ delay:
+ base: 2
+ per-level: -0.1
+ mana:
+ base: 8
+ per-level: 1
+ stamina: 0
+ cooldown:
+ base: 2
+ per-level: 1
+
+ # Duration of shulker projectile in seconds
+ duration:
+ base: 4
+ per-level: 0
+ #Optional: The decimal format used for this skill parameter.
+ decimal-format: '0.#'
+ damage:
+ base: 5
+ per-level: 1
+ effect-duration:
+ base: 2
+ per-level: 0