diff --git a/MMOCore-API/pom.xml b/MMOCore-API/pom.xml index 55c8a06d..0b691ac3 100644 --- a/MMOCore-API/pom.xml +++ b/MMOCore-API/pom.xml @@ -113,6 +113,16 @@ + + + + org.jetbrains + annotations + 24.1.0 + + + + @@ -132,14 +142,15 @@ - commons-lang - commons-lang - 2.6 + org.jetbrains + annotations + 26.0.2-1 provided true + io.papermc paperlib @@ -175,7 +186,7 @@ fr.phoenixdevt Profile-API - 1.1-SNAPSHOT + 1.1.1-SNAPSHOT provided true @@ -183,7 +194,7 @@ me.clip placeholderapi - 2.9.2 + 2.11.6 provided true @@ -362,7 +373,8 @@ me.glaremasters Guilds - 3.5.6.0 + 3.5.7.1 + stripped provided true diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index ee1eaaf7..8052c9c0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -2,16 +2,17 @@ package net.Indyuce.mmocore; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; -import io.lumine.mythic.lib.data.sql.SQLDataSource; +import io.lumine.mythic.lib.data.SynchronizedDataManager; import io.lumine.mythic.lib.metrics.bukkit.Metrics; +import io.lumine.mythic.lib.module.MMOPlugin; import io.lumine.mythic.lib.player.modifier.PlayerModifier; -import io.lumine.mythic.lib.util.MMOPlugin; +import io.lumine.mythic.lib.util.lang3.Validate; import io.lumine.mythic.lib.version.SpigotPlugin; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.attribute.AttributeModifier; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; -import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot; -import net.Indyuce.mmocore.command.api.ToggleableCommand; +import net.Indyuce.mmocore.command.ToggleableCommand; +import net.Indyuce.mmocore.command.builtin.mmocore.MMOCoreCommandTreeRoot; import net.Indyuce.mmocore.comp.citizens.CitizenInteractEventListener; import net.Indyuce.mmocore.comp.citizens.CitizensMMOLoader; import net.Indyuce.mmocore.comp.mythicmobs.MythicHook; @@ -37,7 +38,8 @@ import net.Indyuce.mmocore.manager.data.DataProvider; import net.Indyuce.mmocore.manager.data.GuildDataManager; import net.Indyuce.mmocore.manager.data.LegacyDataProvider; import net.Indyuce.mmocore.manager.data.PlayerDataManager; -import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler; +import net.Indyuce.mmocore.manager.data.sql.SQLDatabaseImpl; +import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl; import net.Indyuce.mmocore.manager.profession.*; import net.Indyuce.mmocore.manager.social.BoosterManager; import net.Indyuce.mmocore.manager.social.PartyManager; @@ -52,7 +54,6 @@ import net.Indyuce.mmocore.script.mechanic.StaminaMechanic; import net.Indyuce.mmocore.script.mechanic.StelliumMechanic; import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import net.Indyuce.mmocore.skill.trigger.MMOCoreTriggerType; -import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.event.EventPriority; @@ -151,10 +152,7 @@ public class MMOCore extends MMOPlugin { getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')"); } - if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) { - final SQLDataSource dataSource = new SQLDataSource(this); - playerDataManager.setDataHandler(new SQLDataHandler(dataSource)); - } + playerDataManager.setupDatabase(SQLDatabaseImpl::new, YAMLDatabaseImpl::new); if (getConfig().isConfigurationSection("default-playerdata")) playerDataManager.loadDefaultData(getConfig().getConfigurationSection("default-playerdata")); @@ -192,9 +190,8 @@ public class MMOCore extends MMOPlugin { for (PlayerData player : PlayerData.getAll()) if (player.isOnline() && !player.getPlayer().isDead()) for (PlayerResource resource : PlayerResource.values()) { - double regenAmount = player.getProfess().getHandler(resource).getRegen(player); - if (regenAmount != 0) - resource.regen(player, regenAmount); + final var regenAmount = player.getProfess().getHandler(resource).getRegen(player); + if (regenAmount != 0) resource.regen(player, regenAmount); } } }.runTaskTimer(MMOCore.plugin, 100, 20); @@ -263,7 +260,7 @@ public class MMOCore extends MMOPlugin { nativeGuildManager.load(); // Toggleable Commands - ToggleableCommand.register(); + ToggleableCommand.loadCommands(); // Register MMOCore command what soever MMOCoreCommandTreeRoot mmoCoreCommand = new MMOCoreCommandTreeRoot(); @@ -348,4 +345,9 @@ public class MMOCore extends MMOPlugin { public boolean hasEconomy() { return economy != null && economy.isValid(); } + + @Override + public @NotNull SynchronizedDataManager getRawPlayerDataManager() { + return this.playerDataManager; + } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/ConfigMessage.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/ConfigMessage.java index 9dc8c3ee..6d3fd02d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/ConfigMessage.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/ConfigMessage.java @@ -1,11 +1,12 @@ package net.Indyuce.mmocore.api; import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.message.actionbar.ActionBarPriority; +import io.lumine.mythic.lib.util.lang3.Validate; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; -import org.apache.commons.lang.Validate; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -162,7 +163,7 @@ public class ConfigMessage { // Handle special case with player data + action bar if (playerData != null && playerData.isOnline() && actionbar) { - playerData.displayActionBar(rawMessage, raw); + playerData.getMMOPlayerData().getActionBar().show(ActionBarPriority.NORMAL, rawMessage); return; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java index f8253a94..59c49ee0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java @@ -6,6 +6,7 @@ import io.lumine.mythic.lib.skill.handler.SkillHandler; import io.lumine.mythic.lib.skill.result.SkillResult; import io.lumine.mythic.lib.skill.trigger.TriggerMetadata; import io.lumine.mythic.lib.skill.trigger.TriggerType; +import io.lumine.mythic.lib.util.lang3.Validate; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.guild.GuildModule; @@ -14,7 +15,6 @@ import net.Indyuce.mmocore.party.PartyModule; import net.Indyuce.mmocore.skill.CastableSkill; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skill.RegisteredSkill; -import org.apache.commons.lang.Validate; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/BlockInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/BlockInfo.java index c56047e2..2634f5de 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/BlockInfo.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/BlockInfo.java @@ -4,11 +4,11 @@ import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.api.condition.type.BlockCondition; import io.lumine.mythic.lib.api.condition.type.MMOCondition; +import io.lumine.mythic.lib.util.lang3.Validate; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.quest.trigger.Trigger; import net.Indyuce.mmocore.loot.LootBuilder; import net.Indyuce.mmocore.loot.droptable.DropTable; -import org.apache.commons.lang.Validate; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/MushroomBlockType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/MushroomBlockType.java new file mode 100644 index 00000000..7da7a9da --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/block/MushroomBlockType.java @@ -0,0 +1,86 @@ +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.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.MultipleFacing; +import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public class MushroomBlockType implements BlockType { + private final Set faces; + private final Material type; + + public MushroomBlockType(MMOLineConfig config) { + config.validateKeys("faces", "type"); + + this.type = UtilityMethods.prettyValueOf(Material::valueOf, config.getString("type"), "No material with ID %s"); + var split = config.getString("faces").split("\\,"); + faces = new HashSet<>(); + for (int j = 0; j < split.length; j++) + faces.add(UtilityMethods.prettyValueOf(BlockFace::valueOf, split[j], "No block face with ID %s")); + } + + public MushroomBlockType(@NotNull Block block) { + final var state = (MultipleFacing) block.getBlockData(); + this.type = block.getType(); + this.faces = state.getAllowedFaces(); + } + + public Set 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