diff --git a/build.gradle.kts b/build.gradle.kts index d583c3dd..da23b011 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java `maven-publish` - id("io.papermc.paperweight.userdev") version "1.5.10" + id("io.papermc.paperweight.userdev") version "1.7.3" id("com.github.johnrengelman.shadow") version "7.1.2" } @@ -56,22 +56,22 @@ repositories { } dependencies { - paperDevBundle("1.20.2-R0.1-SNAPSHOT") - implementation("net.kyori:adventure-api:4.14.0") + paperDevBundle("1.21.1-R0.1-SNAPSHOT") + implementation("net.kyori:adventure-api:4.17.0") compileOnly("com.github.luben:zstd-jni:1.5.0-4") compileOnly("redis.clients:jedis:5.1.3") - paperweight.paperDevBundle("1.20.2-R0.1-SNAPSHOT") - compileOnly("com.comphenix.protocol:ProtocolLib:5.1.0") + paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") + compileOnly("com.comphenix.protocol:ProtocolLib:5.3.0") compileOnly("com.github.MilkBowl:VaultAPI:1.7.1") - compileOnly("me.clip:placeholderapi:2.11.4") - compileOnly("com.palmergames.bukkit.towny:towny:0.100.0.0") - compileOnly("pl.betoncraft:betonquest:1.12.10") - compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9-SNAPSHOT") + compileOnly("me.clip:placeholderapi:2.11.6") + compileOnly("com.palmergames.bukkit.towny:towny:0.100.4.0") + compileOnly("org.betonquest:betonquest:2.1.3") + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.12") compileOnly("io.lumine:Mythic-Dist:5.4.1") } group = "net.laboulangerie" -version = "2.3.1" +version = "2.3.2" description = "LaBoulangerieMmo" java.sourceCompatibility = JavaVersion.VERSION_17 diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/LaBoulangerieMmo.java b/src/main/java/net/laboulangerie/laboulangeriemmo/LaBoulangerieMmo.java index f6c6bdce..29ec7aaf 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/LaBoulangerieMmo.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/LaBoulangerieMmo.java @@ -6,6 +6,13 @@ import java.util.Arrays; import java.util.Locale; import java.util.logging.Level; +import org.betonquest.betonquest.BetonQuest; +import org.betonquest.betonquest.Instruction; +import org.betonquest.betonquest.api.quest.PlayerQuestFactory; +import org.betonquest.betonquest.api.quest.condition.PlayerCondition; +import org.betonquest.betonquest.api.quest.condition.PlayerConditionFactory; +import org.betonquest.betonquest.api.quest.event.Event; +import org.betonquest.betonquest.exceptions.InstructionParseException; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; import net.laboulangerie.laboulangeriemmo.api.ability.AbilitiesRegistry; @@ -26,10 +33,10 @@ import net.laboulangerie.laboulangeriemmo.core.blockus.BlockusManager; import net.laboulangerie.laboulangeriemmo.core.blockus.redis.RedisBlockusHolder; import net.laboulangerie.laboulangeriemmo.core.combo.ComboDispatcher; +import net.laboulangerie.laboulangeriemmo.core.json.GsonSerializer; import net.laboulangerie.laboulangeriemmo.core.mapleaderboard.LeaderBoardManager; import net.laboulangerie.laboulangeriemmo.core.particles.EffectRegistry; import net.laboulangerie.laboulangeriemmo.expansions.MmoExpansion; -import net.laboulangerie.laboulangeriemmo.json.GsonSerializer; import net.laboulangerie.laboulangeriemmo.listener.AbilitiesRegisterer; import net.laboulangerie.laboulangeriemmo.listener.GrindingListener; import net.laboulangerie.laboulangeriemmo.listener.MmoListener; @@ -37,7 +44,6 @@ import net.laboulangerie.laboulangeriemmo.listener.XpBoostListener; import net.laboulangerie.laboulangeriemmo.utils.WolrdGuardSupport; import net.milkbowl.vault.economy.Economy; -import pl.betoncraft.betonquest.BetonQuest; public class LaBoulangerieMmo extends JavaPlugin { public static LaBoulangerieMmo PLUGIN; @@ -115,8 +121,31 @@ public void onEnable() { } if (getServer().getPluginManager().getPlugin("BetonQuest") != null) { - BetonQuest.getInstance().registerConditions("lbmmo_level", LevelCondition.class); - BetonQuest.getInstance().registerEvents("lbmmo_xp", XpEvent.class); + BetonQuest.getInstance().getQuestRegistries().getConditionTypes().register("lbmmo_level", new PlayerConditionFactory() { + @Override + public PlayerCondition parsePlayer(Instruction instruction) throws InstructionParseException { + int level; + try { + level = Integer.parseInt(instruction.getPart(2)); + } catch (Exception e) { + throw new InstructionParseException("You didn't pass an integer value to lbmmo_level condition"); + } + return new LevelCondition(instruction.getPart(1), level); + } + }, null); + BetonQuest.getInstance().getQuestRegistries().getEventTypes().register("lbmmo_xp", new PlayerQuestFactory() { + @Override + public Event parsePlayer(Instruction instruction) throws InstructionParseException { + char op = instruction.getPart(2).charAt(0); + double xp; + try { + xp = Double.parseDouble(instruction.getPart(2).substring(1)); + } catch (Exception e) { + throw new InstructionParseException("You didn't pass a decimal value to lbmmo_level condition"); + } + return new XpEvent(instruction.getPart(0), op, xp); + } + }); getLogger().info("Hooked in BetonQuest!"); } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/CooldownsHolder.java b/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/CooldownsHolder.java index 142a5ff4..94514d17 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/CooldownsHolder.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/CooldownsHolder.java @@ -3,14 +3,13 @@ import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; - import net.laboulangerie.laboulangeriemmo.LaBoulangerieMmo; import net.laboulangerie.laboulangeriemmo.api.ability.AbilityArchetype; +import net.laboulangerie.laboulangeriemmo.core.json.GsonSerializable; -public class CooldownsHolder { +public class CooldownsHolder implements GsonSerializable { private HashMap cooldowns; public CooldownsHolder() { @@ -35,18 +34,15 @@ public List getCooldowns(String abilityId) { }).collect(Collectors.toList()); } - public HashMap getArchetypeCooldowns(String abilityId) { - return (HashMap) cooldowns.entrySet().stream() + /** + * Maps every talent that has this ability to the last time it was used for each of them + * @param abilityId + * @return key is the talent identifier associated to this instance of the ability and value is the time elapsed since it's last use + */ + public HashMap getTimeSinceUsed(String abilityId) { + return (HashMap) cooldowns.entrySet().stream() .filter(entry -> entry.getKey().endsWith("/" + abilityId)) - .collect(Collectors.toMap(e -> LaBoulangerieMmo.talentsRegistry - .getTalent(e.getKey().split("/")[0]).abilitiesArchetypes - .get(e.getKey().split("/")[1]), - Entry::getValue)) - .entrySet().stream() - .collect(Collectors.toMap(Entry::getKey, - e -> e.getKey().cooldownUnit.convert( - new Date().getTime() - e.getValue().getTime(), - TimeUnit.MILLISECONDS))); + .collect(Collectors.toMap(e -> e.getKey().split("/")[0], e -> new Date().getTime()-e.getValue().getTime())); } public boolean isCooldownElapsed(AbilityArchetype ability, String talentId) { @@ -81,4 +77,20 @@ public boolean hasUsed(String abilityId) { private String getId(AbilityArchetype ability, String talentId) { return talentId + "/" + ability.identifier; } + + public HashMap getCooldowns() { + return cooldowns; + } + + /** + * Intended for internal use (data deserialisation) + * + * Will set the cooldowns to match the given { @link HashMap } if the + * internal one is empty. + * @param cooldowns + */ + public void setCooldowns(HashMap cooldowns) { + if (!this.cooldowns.isEmpty()) return; + this.cooldowns = cooldowns; + } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayer.java b/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayer.java index 8db363cc..4c861da9 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayer.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayer.java @@ -22,12 +22,12 @@ import net.laboulangerie.laboulangeriemmo.api.ability.AbilityArchetype; import net.laboulangerie.laboulangeriemmo.api.talent.Talent; import net.laboulangerie.laboulangeriemmo.api.talent.TalentArchetype; -import net.laboulangerie.laboulangeriemmo.core.PostProcessingEnabler; import net.laboulangerie.laboulangeriemmo.core.XpCountDown; +import net.laboulangerie.laboulangeriemmo.core.json.GsonSerializable; +import net.laboulangerie.laboulangeriemmo.core.json.PostProcessingEnabler; import net.laboulangerie.laboulangeriemmo.core.particles.EffectRegistry; import net.laboulangerie.laboulangeriemmo.events.PlayerEarnsXpEvent; import net.laboulangerie.laboulangeriemmo.events.PlayerLevelUpEvent; -import net.laboulangerie.laboulangeriemmo.json.GsonSerializable; public class MmoPlayer implements GsonSerializable, PostProcessingEnabler.PostProcessable { private transient FileConfiguration config = LaBoulangerieMmo.PLUGIN.getConfig(); diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayerManager.java b/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayerManager.java index c667fb46..6498621f 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayerManager.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/api/player/MmoPlayerManager.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.logging.Level; import java.util.stream.Stream; import com.google.gson.JsonSyntaxException; @@ -13,7 +14,7 @@ import org.bukkit.entity.Player; import net.laboulangerie.laboulangeriemmo.LaBoulangerieMmo; -import net.laboulangerie.laboulangeriemmo.json.GsonSerializer; +import net.laboulangerie.laboulangeriemmo.core.json.GsonSerializer; import net.laboulangerie.laboulangeriemmo.utils.FileUtils; public class MmoPlayerManager { @@ -57,7 +58,11 @@ public void loadPlayerData(OfflinePlayer player) { try { File file = new File(playersFolder, uniqueId + ".json"); - if (!file.exists()) throw new JsonSyntaxException("hacky"); + if (!file.exists()) { + MmoPlayer mmoPlayer = new MmoPlayer(player); + playersMap.put(uniqueId, mmoPlayer); + return; + } String json = FileUtils.read(file); if (!json.equals("")) { @@ -65,8 +70,9 @@ public void loadPlayerData(OfflinePlayer player) { playersMap.put(uniqueId, mmoPlayer); } } catch (JsonSyntaxException e) { - MmoPlayer mmoPlayer = new MmoPlayer(player); - playersMap.put(uniqueId, mmoPlayer); + LaBoulangerieMmo.PLUGIN.getLogger().log(Level.SEVERE, "Failed to load player data, disabling plugin to preserve saves's integrity."); + e.printStackTrace(); + Bukkit.getPluginManager().disablePlugin(LaBoulangerieMmo.PLUGIN); } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/LevelCondition.java b/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/LevelCondition.java index f725ee58..b3d20d19 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/LevelCondition.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/LevelCondition.java @@ -1,36 +1,26 @@ package net.laboulangerie.laboulangeriemmo.betonquest; -import java.util.UUID; - -import org.bukkit.Bukkit; - +import org.betonquest.betonquest.api.profiles.Profile; +import org.betonquest.betonquest.api.quest.condition.PlayerCondition; +import org.betonquest.betonquest.exceptions.QuestRuntimeException; import net.laboulangerie.laboulangeriemmo.LaBoulangerieMmo; import net.laboulangerie.laboulangeriemmo.api.player.MmoPlayer; -import pl.betoncraft.betonquest.Instruction; -import pl.betoncraft.betonquest.api.Condition; -import pl.betoncraft.betonquest.exceptions.InstructionParseException; -import pl.betoncraft.betonquest.exceptions.QuestRuntimeException; - -public class LevelCondition extends Condition { - @SuppressWarnings("deprecation") - public LevelCondition(Instruction instruction) { - super(instruction); +public class LevelCondition implements PlayerCondition { + private String talentName; + private int level; + public LevelCondition(String talentName, int level) { + this.talentName = talentName; + this.level = level; } - + @Override - protected Boolean execute(String playerID) throws QuestRuntimeException { + public boolean check(Profile profile) throws QuestRuntimeException { MmoPlayer mmoPlayer = LaBoulangerieMmo.PLUGIN.getMmoPlayerManager() - .getPlayer(Bukkit.getPlayer(UUID.fromString(playerID))); + .getPlayer(profile.getPlayer().getPlayer()); if (mmoPlayer == null) return false; // Shouldn't happen but just in case - - String talentName = ""; - try { - talentName = instruction.getPart(1); - } catch (InstructionParseException e) { - e.printStackTrace(); - } - return instruction.getAllNumbers().get(0) <= mmoPlayer.getTalent(talentName).getLevel(); + + return level <= mmoPlayer.getTalent(talentName).getLevel(); } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/XpEvent.java b/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/XpEvent.java index bac7cf0e..25eba425 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/XpEvent.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/betonquest/XpEvent.java @@ -1,56 +1,39 @@ package net.laboulangerie.laboulangeriemmo.betonquest; -import java.util.UUID; - -import org.bukkit.Bukkit; - +import org.betonquest.betonquest.api.profiles.Profile; +import org.betonquest.betonquest.api.quest.event.Event; +import org.betonquest.betonquest.exceptions.QuestRuntimeException; import net.laboulangerie.laboulangeriemmo.LaBoulangerieMmo; import net.laboulangerie.laboulangeriemmo.api.player.MmoPlayer; -import pl.betoncraft.betonquest.Instruction; -import pl.betoncraft.betonquest.api.QuestEvent; -import pl.betoncraft.betonquest.exceptions.InstructionParseException; -import pl.betoncraft.betonquest.exceptions.QuestRuntimeException; -public class XpEvent extends QuestEvent { +public class XpEvent implements Event { + String talentName; + char op; + double xp; - @SuppressWarnings("deprecation") - public XpEvent(Instruction instruction) throws InstructionParseException { - super(instruction); + public XpEvent(String talentName, char op, double xp) { + this.talentName = talentName; + this.op = op; + this.xp = xp; } @Override - protected Void execute(String playerID) throws QuestRuntimeException { + public void execute(Profile profile) throws QuestRuntimeException { MmoPlayer mmoPlayer = LaBoulangerieMmo.PLUGIN.getMmoPlayerManager() - .getPlayer(Bukkit.getPlayer(UUID.fromString(playerID))); - if (mmoPlayer == null) return null; // Shouldn't happen but just in case + .getPlayer(profile.getPlayer().getPlayer()); + if (mmoPlayer == null) return; // Shouldn't happen but just in case - String talentName = ""; - String rawValue = ""; - try { - talentName = instruction.getPart(1); - rawValue = instruction.getPart(2); - } catch (InstructionParseException e) { - e.printStackTrace(); - } - double value = 0; - try { - value = Double.parseDouble(rawValue.substring(1)); - } catch (NumberFormatException error) { - throw new QuestRuntimeException("Unable to parse given value to a decimal number", - error); - } - switch (rawValue.charAt(0)) { + switch (op) { case '+': - mmoPlayer.getTalent(talentName).incrementXp(value); + mmoPlayer.getTalent(talentName).incrementXp(xp); break; case '-': - mmoPlayer.getTalent(talentName).decrementXp(value); + mmoPlayer.getTalent(talentName).decrementXp(xp); break; default: - throw new QuestRuntimeException("Unknown operation: " + rawValue.charAt(0) + throw new QuestRuntimeException("Unknown operation: " + op + ", should be either '+' or '-'"); } - return null; } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/farmer/NatureTouch.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/farmer/NatureTouch.java index 526e9302..70fc2c09 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/farmer/NatureTouch.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/farmer/NatureTouch.java @@ -68,7 +68,7 @@ public void run() { updatedBlock.setType(cropMaterial); updatedBlock.getWorld().spawnParticle( - Particle.VILLAGER_HAPPY, + Particle.HAPPY_VILLAGER, updatedBlock.getLocation().toCenterLocation().add(0, -0.2, 0), 5, 0.1, 0.1, 0.1); } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/FastMine.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/FastMine.java index d8b3a8e1..b8fff37e 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/FastMine.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/FastMine.java @@ -44,7 +44,7 @@ public void trigger(Event baseEvent, int level) { player.sendMessage( "§eVous gagnez Haste " + (amplifier + 1) + " pendant " + duration + " secondes"); player.addPotionEffect( - new PotionEffect(PotionEffectType.FAST_DIGGING, duration * 20, amplifier, true)); + new PotionEffect(PotionEffectType.HASTE, duration * 20, amplifier, true)); EffectRegistry.playEffect("default", player); } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/MarkedBlocksManager.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/MarkedBlocksManager.java index 374fd519..f93e2efd 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/MarkedBlocksManager.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/mining/MarkedBlocksManager.java @@ -7,20 +7,18 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.AbstractStructure; -import com.comphenix.protocol.events.InternalStructure; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.utility.MinecraftReflection; +import com.comphenix.protocol.wrappers.EnumWrappers.ChatFormatting; import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedDataValue; import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry; +import com.comphenix.protocol.wrappers.WrappedTeamParameters; import net.minecraft.world.entity.EntityType; public class MarkedBlocksManager { @@ -29,9 +27,9 @@ public class MarkedBlocksManager { private int idCount = 100000; private String[] teamsIdentifier = {"DIAMOND_ORE", "IRON_ORE", "COAL_ORE", "GOLD_ORE", "LAPIS_ORE", "REDSTONE_ORE", "EMERALD_ORE", "COPPER_ORE", "ANCIENT_DEBRIS", "NETHER_GOLD_ORE", "BUDDING_AMETHYST"}; - private ChatColor[] teamsColor = - {ChatColor.AQUA, ChatColor.GRAY, ChatColor.BLACK, ChatColor.YELLOW, ChatColor.DARK_BLUE, ChatColor.RED, - ChatColor.GREEN, ChatColor.GOLD, ChatColor.DARK_GRAY, ChatColor.YELLOW, ChatColor.DARK_PURPLE}; + private ChatFormatting[] teamsColor = + {ChatFormatting.AQUA, ChatFormatting.GRAY, ChatFormatting.BLACK, ChatFormatting.YELLOW, ChatFormatting.DARK_BLUE, ChatFormatting.RED, + ChatFormatting.GREEN, ChatFormatting.GOLD, ChatFormatting.DARK_GRAY, ChatFormatting.YELLOW, ChatFormatting.DARK_PURPLE}; public void markBlock(Block block, Player player) { BlockWatcher blockWatcher = markedBlocks.get(block); @@ -124,20 +122,20 @@ public void colorize(Block block, Player player) { public void setupTeams(Player player) { // https://github.com/lucko/helper/blob/master/helper/src/main/java/me/lucko/helper/scoreboard/PacketScoreboardTeam.java for (int i = 0; i < teamsIdentifier.length; i++) { PacketContainer team = new PacketContainer(PacketType.Play.Server.SCOREBOARD_TEAM); - AbstractStructure struct = team.getOptionalStructures().readSafely(0).get(); team.getStrings().write(0, teamsIdentifier[i]); // team id team.getIntegers().write(0, 0x0);// Mode: 0 = CREATE - struct.getStrings().write(0, "always") // name tag visibility rules - .write(1, "never"); // collisions rules - struct.getIntegers().write(0, 0x02); // flags - struct.getChatComponents().write(0, WrappedChatComponent.fromText("")) - .write(1, WrappedChatComponent.fromText("")).write(2, WrappedChatComponent.fromText("")); - struct.getEnumModifier(ChatColor.class, MinecraftReflection.getMinecraftClass("EnumChatFormat")).write(0, - teamsColor[i]); - - team.getOptionalStructures().write(0, Optional.of((InternalStructure) struct)); + WrappedTeamParameters params = WrappedTeamParameters.newBuilder() + .nametagVisibility("always") + .collisionRule("never") + .displayName(WrappedChatComponent.fromText("")) + .suffix(WrappedChatComponent.fromText("")) + .prefix(WrappedChatComponent.fromText("")) + .color(this.teamsColor[i]) + .options(0x02).build(); + team.getOptionalTeamParameters().write(0, Optional.of(params)); + team.getSpecificModifier(Collection.class).write(0, Collections.emptyList()); // entities ProtocolLibrary.getProtocolManager().sendServerPacket(player, team); } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/Dodging.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/Dodging.java index 4b3e0428..9040f53d 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/Dodging.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/Dodging.java @@ -1,7 +1,7 @@ package net.laboulangerie.laboulangeriemmo.core.abilities.thehunter; import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.event.Event; import org.bukkit.util.Vector; @@ -12,6 +12,7 @@ import net.laboulangerie.laboulangeriemmo.events.ComboCompletedEvent; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; public class Dodging extends AbilityExecutor { @@ -49,7 +50,7 @@ public void trigger(Event baseEvent, int level) { f4 *= f6 / f5; player.setVelocity(new Vector((double) f2, (double) f3, (double) f4)); - human.startAutoSpinAttack(20); + human.startAutoSpinAttack(20, 20, ItemStack.EMPTY); player.getWorld().playSound(player.getLocation(), Sound.ITEM_TRIDENT_RIPTIDE_1, 1, 1); } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/FireBow.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/FireBow.java index 22e69a97..bc542437 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/FireBow.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/FireBow.java @@ -37,7 +37,7 @@ public boolean shouldTrigger(Event baseEvent) { boolean hasFlameBow = event.getPlayer().getInventory().contains(Material.BOW) && event.getPlayer().getInventory().all(Material.BOW).values().stream() .map(item -> item.hasItemMeta() - && item.getItemMeta().hasEnchant(Enchantment.ARROW_FIRE)) + && item.getItemMeta().hasEnchant(Enchantment.FLAME)) .reduce(false, (result, hasEnchant) -> (result == true) || hasEnchant); return new KeyStreak(ComboKey.RIGHT, ComboKey.LEFT, ComboKey.LEFT) @@ -111,7 +111,7 @@ private static void putFire(Location location) { private static void explosion(Player shooter, Location location, int power) { final World world = location.getWorld(); - TNTPrimed tnt = (TNTPrimed) world.spawnEntity(location, EntityType.PRIMED_TNT); + TNTPrimed tnt = (TNTPrimed) world.spawnEntity(location, EntityType.TNT); tnt.setIsIncendiary(true); tnt.setSource(shooter); tnt.setFuseTicks(0); diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/hiding/ArmorHider.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/hiding/ArmorHider.java index 64e6f2af..aa69a04e 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/hiding/ArmorHider.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/thehunter/hiding/ArmorHider.java @@ -4,7 +4,7 @@ import java.util.List; import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/DoubleDropLog.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/DoubleDropLog.java index ef823a16..8e2fd877 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/DoubleDropLog.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/DoubleDropLog.java @@ -48,7 +48,7 @@ public void trigger(Event baseEvent, int level) { if (shouldDrop) { Location location = block.getLocation(); - location.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, location.toCenterLocation().add(0, -0.2, 0), 5, + location.getWorld().spawnParticle(Particle.HAPPY_VILLAGER, location.toCenterLocation().add(0, -0.2, 0), 5, 0.1, 0.1, 0.1); location.getWorld().dropItemNaturally(location, droppedItem); } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/Stun.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/Stun.java index 1b3e161a..ce6274a4 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/Stun.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/abilities/woodcutting/Stun.java @@ -50,19 +50,19 @@ public void trigger(Event baseEvent, int level) { boolean shouldStun = false; boolean shouldBlind = false; int durationSeconds = 2; - PotionEffect slownessEffect = new PotionEffect(PotionEffectType.SLOW, PotionEffect.INFINITE_DURATION, 1, true, + PotionEffect slownessEffect = new PotionEffect(PotionEffectType.SLOWNESS, PotionEffect.INFINITE_DURATION, 1, true, false); if (level >= getTier(2) && random <= TIER_3_CHANCE) { shouldStun = true; shouldBlind = true; durationSeconds = 3; - slownessEffect = new PotionEffect(PotionEffectType.SLOW, PotionEffect.INFINITE_DURATION, 3, true, false); + slownessEffect = new PotionEffect(PotionEffectType.SLOWNESS, PotionEffect.INFINITE_DURATION, 3, true, false); } else if (level >= getTier(1) && random <= TIER_2_CHANCE) { shouldStun = true; shouldBlind = true; durationSeconds = 5; - slownessEffect = new PotionEffect(PotionEffectType.SLOW, PotionEffect.INFINITE_DURATION, 2, true, false); + slownessEffect = new PotionEffect(PotionEffectType.SLOWNESS, PotionEffect.INFINITE_DURATION, 2, true, false); } else if (random <= TIER_1_CHANCE) shouldStun = true; @@ -76,8 +76,8 @@ public void trigger(Event baseEvent, int level) { Bukkit.getScheduler().runTaskLater(LaBoulangerieMmo.PLUGIN, new Runnable() { @Override public void run() { - entity.removePotionEffect(PotionEffectType.JUMP); - entity.removePotionEffect(PotionEffectType.SLOW); + entity.removePotionEffect(PotionEffectType.JUMP_BOOST); + entity.removePotionEffect(PotionEffectType.SLOWNESS); entity.removePotionEffect(PotionEffectType.BLINDNESS); } }, durationSeconds * 20); diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/DateSerializer.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/DateSerializer.java new file mode 100644 index 00000000..f0b32b5e --- /dev/null +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/DateSerializer.java @@ -0,0 +1,62 @@ +package net.laboulangerie.laboulangeriemmo.core.json; + +import java.lang.reflect.Type; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map.Entry; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import net.laboulangerie.laboulangeriemmo.api.player.CooldownsHolder; + +public class DateSerializer implements JsonSerializer, JsonDeserializer { + + @Override + public JsonElement serialize(CooldownsHolder cooldownsHolder, Type type, JsonSerializationContext jsonCtx) { + JsonObject obj = new JsonObject(); + JsonObject cooldownsJson = new JsonObject(); + for (Entry entry : cooldownsHolder.getCooldowns().entrySet()) { + cooldownsJson.addProperty(entry.getKey(), entry.getValue().getTime()); + } + obj.add("cooldowns", cooldownsJson); + return obj; + } + + @Override + public CooldownsHolder deserialize(JsonElement json, Type type, JsonDeserializationContext jsonCtx) throws JsonParseException { + CooldownsHolder holder = new CooldownsHolder(); + HashMap map = new HashMap<>(); + + if (json.getAsJsonObject().has("cooldowns")) { + JsonObject cooldownsJson = json.getAsJsonObject().get("cooldowns").getAsJsonObject(); + boolean shouldAttemptDateConversion = true; + + for (Entry entry : cooldownsJson.asMap().entrySet()) { + // Date serialization format changed somewhere between java 17 and 21 + if (shouldAttemptDateConversion && entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isString()) { + SimpleDateFormat formater = new SimpleDateFormat("MMM dd, yyyy, hh:mm:ss a", Locale.US); + + try { + map.put(entry.getKey(), formater.parse(entry.getValue().getAsString())); + } catch (ParseException e) { + e.printStackTrace(); + } + } else { + shouldAttemptDateConversion = false; + map.put(entry.getKey(), Date.from(Instant.ofEpochMilli(entry.getValue().getAsLong()))); + } + } + } + + holder.setCooldowns(map); + return holder; + } +} diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/GsonSerializable.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/GsonSerializable.java new file mode 100644 index 00000000..f50811cf --- /dev/null +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/GsonSerializable.java @@ -0,0 +1,4 @@ +package net.laboulangerie.laboulangeriemmo.core.json; + +public interface GsonSerializable { +} diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/json/GsonSerializer.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/GsonSerializer.java similarity index 65% rename from src/main/java/net/laboulangerie/laboulangeriemmo/json/GsonSerializer.java rename to src/main/java/net/laboulangerie/laboulangeriemmo/core/json/GsonSerializer.java index 2a12680d..876d35a1 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/json/GsonSerializer.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/GsonSerializer.java @@ -1,10 +1,9 @@ -package net.laboulangerie.laboulangeriemmo.json; +package net.laboulangerie.laboulangeriemmo.core.json; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; - -import net.laboulangerie.laboulangeriemmo.core.PostProcessingEnabler; +import net.laboulangerie.laboulangeriemmo.api.player.CooldownsHolder; public class GsonSerializer { @@ -12,7 +11,9 @@ public class GsonSerializer { public GsonSerializer() { gson = new GsonBuilder().setPrettyPrinting().serializeNulls() - .registerTypeAdapterFactory(new PostProcessingEnabler()).create(); + .registerTypeAdapterFactory(new PostProcessingEnabler()) + .registerTypeAdapter(CooldownsHolder.class, new DateSerializer()) + .create(); } public String serialize(GsonSerializable serializable) { diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/PostProcessingEnabler.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/PostProcessingEnabler.java similarity index 94% rename from src/main/java/net/laboulangerie/laboulangeriemmo/core/PostProcessingEnabler.java rename to src/main/java/net/laboulangerie/laboulangeriemmo/core/json/PostProcessingEnabler.java index bb04f69f..4872993a 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/PostProcessingEnabler.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/json/PostProcessingEnabler.java @@ -1,4 +1,4 @@ -package net.laboulangerie.laboulangeriemmo.core; +package net.laboulangerie.laboulangeriemmo.core.json; import java.io.IOException; diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/mapleaderboard/LeaderBoardRenderer.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/mapleaderboard/LeaderBoardRenderer.java index b80fcd5b..d3f3374b 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/mapleaderboard/LeaderBoardRenderer.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/mapleaderboard/LeaderBoardRenderer.java @@ -14,8 +14,7 @@ import org.bukkit.map.MapView; import org.bukkit.map.MinecraftFont; import org.jetbrains.annotations.NotNull; - -import net.laboulangerie.laboulangeriemmo.json.GsonSerializable; +import net.laboulangerie.laboulangeriemmo.core.json.GsonSerializable; public class LeaderBoardRenderer extends MapRenderer implements GsonSerializable { private transient boolean done = false; diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/ArrowEffect.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/ArrowEffect.java index 2a1672cf..2c86d5f2 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/ArrowEffect.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/ArrowEffect.java @@ -34,7 +34,7 @@ public void run() { } if (fireArrow != null && fireArrow.getAbilityLevel() == 2) { - world.spawnParticle(Particle.FIREWORKS_SPARK, entity.getLocation(), 0, 0, 0, 0, 8); + world.spawnParticle(Particle.FIREWORK, entity.getLocation(), 0, 0, 0, 0, 8); createHelix(fireArrow.getArrow().getLocation(), 2, 0.5f); } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/HelixEffect.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/HelixEffect.java index c81c5197..bdea29e8 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/HelixEffect.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/HelixEffect.java @@ -20,7 +20,7 @@ public void run() { double x = radius * Math.cos(i * 0.1); double z = radius * Math.sin(i * 0.1); Particle.DustOptions dustOptions = new Particle.DustOptions(Color.ORANGE, 2); - world.spawnParticle(Particle.REDSTONE, location.getX() + x, location.getY() + y, + world.spawnParticle(Particle.DUST, location.getX() + x, location.getY() + y, location.getZ() + z, 3, 1, 0.6, 0, dustOptions); i++; if (y >= 3) cancel(); diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/InvisibleParticles.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/InvisibleParticles.java index d6669f3f..785f6de1 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/InvisibleParticles.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/InvisibleParticles.java @@ -26,10 +26,11 @@ public void run() { if (block.getType().equals(Material.AIR)) return; printLocation.getWorld() - .spawnParticle( - Particle.TOWN_AURA, new Location(printLocation.getWorld(), - printLocation.getX(), printLocation.getY(), printLocation.getZ()), - 5); + .spawnParticle( + Particle.MYCELIUM, new Location(printLocation.getWorld(), + printLocation.getX(), printLocation.getY(), printLocation.getZ()), + 5 + ); } } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/StunEffect.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/StunEffect.java index fd6bdec3..7eb23f34 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/StunEffect.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/StunEffect.java @@ -22,7 +22,7 @@ public void run() { double x = radius * Math.cos(i * 0.2); double z = radius * Math.sin(i * 0.2); - world.spawnParticle(Particle.VILLAGER_ANGRY, location.getX() + x, livingEntity.getEyeLocation().getY() - 0.25, + world.spawnParticle(Particle.ANGRY_VILLAGER, location.getX() + x, livingEntity.getEyeLocation().getY() - 0.25, location.getZ() + z, 1, 0, 0, 0); i++; diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/TrailEffect.java b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/TrailEffect.java index ffc97a3a..0910fc43 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/TrailEffect.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/core/particles/TrailEffect.java @@ -13,7 +13,7 @@ public TrailEffect(Entity entity) { @Override public void run() { - world.spawnParticle(Particle.FIREWORKS_SPARK, entity.getLocation(), 0, 0, 0, 0, 8); + world.spawnParticle(Particle.FIREWORK, entity.getLocation(), 0, 0, 0, 0, 8); i++; if (i == 4) cancel(); } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/json/GsonSerializable.java b/src/main/java/net/laboulangerie/laboulangeriemmo/json/GsonSerializable.java deleted file mode 100644 index a970d6d0..00000000 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/json/GsonSerializable.java +++ /dev/null @@ -1,4 +0,0 @@ -package net.laboulangerie.laboulangeriemmo.json; - -public interface GsonSerializable { -} diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/listener/ServerListener.java b/src/main/java/net/laboulangerie/laboulangeriemmo/listener/ServerListener.java index c9320158..b57d96ae 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/listener/ServerListener.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/listener/ServerListener.java @@ -83,18 +83,18 @@ public void onRiptideHit(EntityDamageByEntityEvent event) { return; } - Optional> ability = mmoPlayer.getCooldowns().getArchetypeCooldowns("dodging") - .entrySet().stream().filter(e -> e.getValue() <= 1).findFirst(); // 1 is the duration of the - // spin attack + Optional> ability = mmoPlayer.getCooldowns().getTimeSinceUsed("dodging") + .entrySet().stream().filter(e -> e.getValue() <= 1000).findFirst(); // 1000 is the duration of the spin attack if (ability.isEmpty()) return; + AbilityArchetype archetype = LaBoulangerieMmo.talentsRegistry.getTalent(ability.get().getKey()).abilitiesArchetypes.get("dodging"); if (Utils.getAttackDamage(player, player.getInventory().getItemInMainHand()) > 0) event.setDamage(Utils.getAttackDamage(player, player.getInventory().getItemInMainHand()) - + (ability.get().getKey().getTier(1) > player.getLevel() ? 1 : 4)); + + (archetype.getTier(1) > player.getLevel() ? 1 : 4)); event.getEntity().setVelocity(player.getLocation().getDirection() - .multiply(ability.get().getKey().getTier(1) > player.getLevel() ? 3 : 5)); + .multiply(archetype.getTier(1) > player.getLevel() ? 3 : 5)); } @EventHandler @@ -118,7 +118,7 @@ public void onProjectileShoot(EntityShootBowEvent event) { if (event.getProjectile().getFireTicks() > 0) EffectRegistry.playEffect("arrow", event.getProjectile()); if (event.getEntity() instanceof Player player && event.getProjectile() instanceof AbstractArrow arrow - && event.getBow().hasItemMeta() && event.getBow().getItemMeta().hasEnchant(Enchantment.ARROW_FIRE)) + && event.getBow().hasItemMeta() && event.getBow().getItemMeta().hasEnchant(Enchantment.FLAME)) FireArrow.shoot(player, arrow); } diff --git a/src/main/java/net/laboulangerie/laboulangeriemmo/utils/Utils.java b/src/main/java/net/laboulangerie/laboulangeriemmo/utils/Utils.java index 9259fd7c..d09d088a 100644 --- a/src/main/java/net/laboulangerie/laboulangeriemmo/utils/Utils.java +++ b/src/main/java/net/laboulangerie/laboulangeriemmo/utils/Utils.java @@ -1,32 +1,26 @@ package net.laboulangerie.laboulangeriemmo.utils; -import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import java.util.Collection; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; +import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import com.google.common.collect.Multimap; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.ai.attributes.Attribute; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.ai.attributes.Attributes; public class Utils { public static double getAttackDamage(Player player, ItemStack itemStack) { + double damages = player.getAttribute(org.bukkit.attribute.Attribute.GENERIC_ATTACK_DAMAGE).getValue(); - net.minecraft.world.item.ItemStack craftItemStack = - CraftItemStack.asNMSCopy(player.getInventory().getItem(player.getInventory().getHeldItemSlot())); - net.minecraft.world.item.Item item = craftItemStack.getItem(); - double damages = player.getAttribute(org.bukkit.attribute.Attribute.GENERIC_ATTACK_DAMAGE).getValue() - 7; - if (item instanceof net.minecraft.world.item.SwordItem || item instanceof net.minecraft.world.item.TieredItem - || item instanceof net.minecraft.world.item.TridentItem) { - - Multimap attributes = - craftItemStack.getItem().getDefaultAttributeModifiers(EquipmentSlot.MAINHAND); - damages += ((AttributeModifier) attributes.get(Attributes.ATTACK_DAMAGE).toArray()[0]).getAmount() + 1; + Multimap attributesMap = itemStack.getType().getDefaultAttributeModifiers(EquipmentSlot.HAND); + Collection modifiers = attributesMap.get(Attribute.GENERIC_ATTACK_DAMAGE); + if (!modifiers.isEmpty()) { + damages += ((AttributeModifier) modifiers.toArray()[0]).getAmount() + 0.7; + } - if (itemStack.getEnchantmentLevel(Enchantment.DAMAGE_ALL) != 0) { - damages += 0.5 * itemStack.getEnchantmentLevel(Enchantment.DAMAGE_ALL) + 0.5; - } + if (itemStack.getEnchantmentLevel(Enchantment.SHARPNESS) != 0) { + damages += 0.5 * itemStack.getEnchantmentLevel(Enchantment.SHARPNESS) + 0.5; } return damages; diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 718ec4e0..b16b9007 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: LaBoulangerieMmo -version: 2.3.0 +version: 2.3.2 main: net.laboulangerie.laboulangeriemmo.LaBoulangerieMmo -api-version: 1.19 +api-version: 1.21 authors: [TheHunter365, Grooble_, Pikachuz3, PainOchoco, BlackoutBurst, SunshineDev] depend: [ProtocolLib, Vault] softdepend: [PlaceholderAPI, Towny, BetonQuest, WorldGuard, MythicMobs]