From 7f9cc4f2c00006f7c6a1cb7daa534ca81536bc52 Mon Sep 17 00:00:00 2001 From: XiaoMoMi <972454774@qq.com> Date: Sat, 9 Sep 2023 03:29:37 +0800 Subject: [PATCH] events and actions --- .../api/event/FishHookLandEvent.java | 36 ++++++ .../customfishing/api/event/RodCastEvent.java | 9 +- .../api/manager/ActionManager.java | 5 + .../api/manager/FishingManager.java | 10 ++ .../api/manager/LootManager.java | 1 - .../api/mechanic/GlobalSettings.java | 64 +++++++++ .../api/mechanic/action/ActionTrigger.java | 3 +- .../api/mechanic/condition/Condition.java | 44 +++---- .../condition/FishingPreparation.java | 86 ++++++++----- .../api/mechanic/effect/EffectCarrier.java | 6 + .../api/mechanic/loot/CFLoot.java | 11 ++ .../customfishing/api/mechanic/loot/Loot.java | 3 + .../api/mechanic/statistic/Statistics.java | 42 +++--- .../customfishing/api/util/WeightUtils.java | 7 +- .../command/CommandManagerImpl.java | 4 +- .../command/sub/DebugCommand.java | 117 +++++++++++++++++ .../papi/PlaceholderManagerImpl.java | 13 +- .../mechanic/action/ActionManagerImpl.java | 100 ++++++++++++++- .../mechanic/competition/Competition.java | 5 +- .../mechanic/effect/EffectManagerImpl.java | 1 + .../mechanic/fishing/FishingManagerImpl.java | 121 +++++++++++------- .../mechanic/fishing/HookCheckTimerTask.java | 34 ++--- .../mechanic/game/GameManagerImpl.java | 1 + .../mechanic/loot/LootManagerImpl.java | 61 +-------- .../requirement/RequirementManagerImpl.java | 29 ++++- .../customfishing/setting/Config.java | 18 +-- .../customfishing/util/ArmorStandUtils.java | 21 ++- plugin/src/main/resources/config.yml | 54 +++++--- .../main/resources/contents/loots/default.yml | 86 ++++++------- .../resources/contents/minigames/default.yml | 22 ++-- .../main/resources/contents/rods/default.yml | 6 + 31 files changed, 713 insertions(+), 307 deletions(-) create mode 100644 api/src/main/java/net/momirealms/customfishing/api/event/FishHookLandEvent.java create mode 100644 api/src/main/java/net/momirealms/customfishing/api/mechanic/GlobalSettings.java create mode 100644 plugin/src/main/java/net/momirealms/customfishing/command/sub/DebugCommand.java diff --git a/api/src/main/java/net/momirealms/customfishing/api/event/FishHookLandEvent.java b/api/src/main/java/net/momirealms/customfishing/api/event/FishHookLandEvent.java new file mode 100644 index 00000000..aa72f14a --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/event/FishHookLandEvent.java @@ -0,0 +1,36 @@ +package net.momirealms.customfishing.api.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; + +public class FishHookLandEvent extends PlayerEvent { + + private static final HandlerList handlerList = new HandlerList(); + private final Target target; + + public FishHookLandEvent(@NotNull Player who, Target target) { + super(who); + this.target = target; + } + + public Target getTarget() { + return target; + } + + public static HandlerList getHandlerList() { + return handlerList; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + + public enum Target { + LAVA, + WATER + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java b/api/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java index 185dd7a9..1f81c4dc 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java +++ b/api/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java @@ -17,6 +17,7 @@ package net.momirealms.customfishing.api.event; +import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; import net.momirealms.customfishing.api.mechanic.effect.Effect; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; @@ -29,12 +30,14 @@ public class RodCastEvent extends PlayerEvent implements Cancellable { private final Effect effect; private boolean isCancelled; private final PlayerFishEvent event; + private final FishingPreparation preparation; private static final HandlerList handlerList = new HandlerList(); - public RodCastEvent(PlayerFishEvent event, Effect effect) { + public RodCastEvent(PlayerFishEvent event, FishingPreparation fishingPreparation, Effect effect) { super(event.getPlayer()); this.effect = effect; this.event = event; + this.preparation = fishingPreparation; } @Override @@ -51,6 +54,10 @@ public class RodCastEvent extends PlayerEvent implements Cancellable { return handlerList; } + public FishingPreparation getPreparation() { + return preparation; + } + @NotNull @Override public HandlerList getHandlers() { diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/ActionManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/ActionManager.java index 347583cc..1f03df63 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/ActionManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/ActionManager.java @@ -19,8 +19,11 @@ package net.momirealms.customfishing.api.manager; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionFactory; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import org.bukkit.configuration.ConfigurationSection; +import java.util.HashMap; + public interface ActionManager { boolean registerAction(String type, ActionFactory actionFactory); @@ -29,6 +32,8 @@ public interface ActionManager { Action getAction(ConfigurationSection section); + HashMap getActionMap(ConfigurationSection section); + Action[] getActions(ConfigurationSection section); ActionFactory getActionBuilder(String type); diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/FishingManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/FishingManager.java index 6c4911e4..b481379c 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/FishingManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/FishingManager.java @@ -18,6 +18,7 @@ package net.momirealms.customfishing.api.manager; import net.momirealms.customfishing.api.mechanic.TempFishingState; +import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.game.GameInstance; import net.momirealms.customfishing.api.mechanic.game.GameSettings; @@ -25,7 +26,10 @@ import net.momirealms.customfishing.api.mechanic.game.GamingPlayer; import net.momirealms.customfishing.api.mechanic.loot.Loot; import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import java.util.Collection; +import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -42,6 +46,12 @@ public interface FishingManager { void processGameResult(GamingPlayer gamingPlayer); + Collection getPossibleLootKeys(FishingPreparation fishingPreparation); + + @NotNull Map getPossibleLootKeysWithWeight(Effect initialEffect, FishingPreparation fishingPreparation); + + Loot getNextLoot(Effect initialEffect, FishingPreparation fishingPreparation); + void startFishingGame(Player player, Loot loot, Effect effect); void startFishingGame(Player player, GameSettings settings, GameInstance gameInstance); diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/LootManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/LootManager.java index cd58dcdc..13784a58 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/LootManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/LootManager.java @@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable; import java.util.List; public interface LootManager { - Loot getGlobalLootProperties(); @Nullable List getLootGroup(String key); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/GlobalSettings.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/GlobalSettings.java new file mode 100644 index 00000000..debdb241 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/GlobalSettings.java @@ -0,0 +1,64 @@ +package net.momirealms.customfishing.api.mechanic; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.HashMap; +import java.util.Map; + +public class GlobalSettings { + + public static HashMap lootActions = new HashMap<>(); + public static HashMap rodActions = new HashMap<>(); + public static HashMap baitActions = new HashMap<>(); + + public static void load(ConfigurationSection section) { + if (section == null) return; + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection inner) { + HashMap map = CustomFishingPlugin.get().getActionManager().getActionMap(inner); + switch (entry.getKey()) { + case "loot" -> lootActions = map; + case "rod" -> rodActions = map; + case "bait" -> baitActions = map; + } + } + } + } + + public static void unload() { + lootActions.clear(); + rodActions.clear(); + baitActions.clear(); + } + + public static void triggerLootActions(ActionTrigger trigger, Condition condition) { + Action[] actions = lootActions.get(trigger); + if (actions != null) { + for (Action action : actions) { + action.trigger(condition); + } + } + } + + public static void triggerRodActions(ActionTrigger trigger, Condition condition) { + Action[] actions = rodActions.get(trigger); + if (actions != null) { + for (Action action : actions) { + action.trigger(condition); + } + } + } + + public static void triggerBaitActions(ActionTrigger trigger, Condition condition) { + Action[] actions = baitActions.get(trigger); + if (actions != null) { + for (Action action : actions) { + action.trigger(condition); + } + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java index 6f52519f..ce587152 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java @@ -23,5 +23,6 @@ public enum ActionTrigger { FAILURE, HOOK, CONSUME, - CAST + CAST, + BITE, LAND } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/Condition.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/Condition.java index 9c7487c8..da8e37c1 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/Condition.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/Condition.java @@ -27,20 +27,9 @@ import java.util.Map; public class Condition { - @Nullable - protected final Location location; - @Nullable - protected final Player player; - @NotNull - protected final Map args; - - public Condition() { - this(null, null, new HashMap<>()); - } - - public Condition(HashMap args) { - this(null, null, args); - } + protected @NotNull Location location; + protected final @NotNull Player player; + protected final @NotNull Map args; public Condition(Player player) { this(player.getLocation(), player, new HashMap<>()); @@ -50,26 +39,31 @@ public class Condition { this(player.getLocation(), player, args); } - public Condition(@Nullable Location location, @Nullable Player player, @NotNull Map args) { + public Condition(@NotNull Location location, @NotNull Player player, @NotNull Map args) { this.location = location; this.player = player; this.args = args; - if (player != null) - this.args.put("{player}", player.getName()); - if (location != null) { - this.args.put("{x}", String.valueOf(location.getX())); - this.args.put("{y}", String.valueOf(location.getY())); - this.args.put("{z}", String.valueOf(location.getZ())); - this.args.put("{world}", location.getWorld().getName()); - } + this.args.put("{player}", player.getName()); + this.args.put("{x}", String.valueOf(location.getX())); + this.args.put("{y}", String.valueOf(location.getY())); + this.args.put("{z}", String.valueOf(location.getZ())); + this.args.put("{world}", location.getWorld().getName()); } - @Nullable + public void setLocation(@NotNull Location location) { + this.location = location; + this.args.put("{x}", String.valueOf(location.getX())); + this.args.put("{y}", String.valueOf(location.getY())); + this.args.put("{z}", String.valueOf(location.getZ())); + this.args.put("{world}", location.getWorld().getName()); + } + + @NotNull public Location getLocation() { return location; } - @Nullable + @NotNull public Player getPlayer() { return player; } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/FishingPreparation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/FishingPreparation.java index 9a2a5844..30b0ac60 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/FishingPreparation.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/FishingPreparation.java @@ -18,6 +18,9 @@ package net.momirealms.customfishing.api.mechanic.condition; import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.GlobalSettings; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier; import org.bukkit.Material; @@ -34,14 +37,12 @@ import java.util.List; public class FishingPreparation extends Condition { - private final boolean rodOnMainHand; - private final @NotNull ItemStack rodItemStack; - private final @NotNull String rodItemID; + private @Nullable EffectCarrier baitEffect; private final @Nullable EffectCarrier rodEffect; private @Nullable ItemStack baitItemStack; - private @Nullable String baitItemID; - private @Nullable EffectCarrier baitEffect; + private final @NotNull ItemStack rodItemStack; private final List utilEffects; + private final Effect enchantEffect; private boolean canFish = true; public FishingPreparation(Player player, CustomFishingPlugin plugin) { @@ -52,18 +53,18 @@ public class FishingPreparation extends Condition { ItemStack offHandItem = playerInventory.getItemInOffHand(); this.utilEffects = new ArrayList<>(); - this.rodOnMainHand = mainHandItem.getType() == Material.FISHING_ROD; - this.rodItemStack = this.rodOnMainHand ? mainHandItem : offHandItem; - this.rodItemID = plugin.getItemManager().getAnyItemID(this.rodItemStack); - this.rodEffect = plugin.getEffectManager().getEffect("rod", this.rodItemID); - super.insertArg("{rod}", this.rodItemID); + this.enchantEffect = plugin.getEffectManager().getInitialEffect(); + boolean rodOnMainHand = mainHandItem.getType() == Material.FISHING_ROD; + this.rodItemStack = rodOnMainHand ? mainHandItem : offHandItem; + String rodItemID = plugin.getItemManager().getAnyItemID(this.rodItemStack); + this.rodEffect = plugin.getEffectManager().getEffect("rod", rodItemID); + super.insertArg("{rod}", rodItemID); - String baitItemID = plugin.getItemManager().getAnyItemID(this.rodOnMainHand ? offHandItem : mainHandItem); + String baitItemID = plugin.getItemManager().getAnyItemID(rodOnMainHand ? offHandItem : mainHandItem); EffectCarrier baitEffect = plugin.getEffectManager().getEffect("bait", baitItemID); if (baitEffect != null) { - this.baitItemID = baitItemID; - this.baitItemStack = this.rodOnMainHand ? offHandItem : mainHandItem; + this.baitItemStack = rodOnMainHand ? offHandItem : mainHandItem; this.baitEffect = baitEffect; } @@ -75,10 +76,9 @@ public class FishingPreparation extends Condition { ItemStack itemInBag = fishingBag.getItem(i); String bagItemID = plugin.getItemManager().getItemID(itemInBag); if (bagItemID == null) continue; - if (this.baitItemID == null) { + if (this.baitEffect == null) { EffectCarrier effect = plugin.getEffectManager().getEffect("bait", bagItemID); if (effect != null) { - this.baitItemID = bagItemID; this.baitItemStack = itemInBag; this.baitEffect = effect; continue; @@ -98,7 +98,7 @@ public class FishingPreparation extends Condition { this.canFish = false; return; } - super.insertArg("{bait}", this.baitItemID); + super.insertArg("{bait}", this.baitEffect.getKey().value()); } if (this.rodEffect != null) { @@ -107,10 +107,13 @@ public class FishingPreparation extends Condition { return; } } - } - public boolean isRodOnMainHand() { - return rodOnMainHand; + for (String enchant : plugin.getIntegrationManager().getEnchantments(rodItemStack)) { + EffectCarrier enchantEffect = plugin.getEffectManager().getEffect("enchant", enchant); + if (enchantEffect != null && enchantEffect.isConditionMet(this)) { + this.enchantEffect.merge(enchantEffect.getEffect()); + } + } } @NotNull @@ -118,39 +121,54 @@ public class FishingPreparation extends Condition { return rodItemStack; } - @NotNull - public String getRodItemID() { - return rodItemID; - } - @Nullable public ItemStack getBaitItemStack() { return baitItemStack; } @Nullable - public String getBaitItemID() { - return baitItemID; + public EffectCarrier getBaitEffect() { + return baitEffect; + } + + @Nullable + public EffectCarrier getRodEffect() { + return rodEffect; } public boolean canFish() { return this.canFish; } - @NotNull - @Override - public Player getPlayer() { - return super.player; - } - - public Effect mergeEffect(Effect effect) { + public void mergeEffect(Effect effect) { if (this.rodEffect != null) effect.merge(this.rodEffect.getEffect()); + if (this.enchantEffect != null) + effect.merge(this.enchantEffect); if (this.baitEffect != null) effect.merge(this.baitEffect.getEffect()); for (EffectCarrier util : utilEffects) { effect.merge(util.getEffect()); } - return effect; + } + + public void triggerActions(ActionTrigger actionTrigger) { + GlobalSettings.triggerRodActions(actionTrigger, this); + if (rodEffect != null) { + Action[] actions = rodEffect.getActions(actionTrigger); + if (actions != null) + for (Action action : actions) { + action.trigger(this); + } + } + + if (baitEffect != null) { + GlobalSettings.triggerBaitActions(actionTrigger, this); + Action[] actions = baitEffect.getActions(actionTrigger); + if (actions != null) + for (Action action : actions) { + action.trigger(this); + } + } } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectCarrier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectCarrier.java index 24cb1f49..c2842b24 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectCarrier.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectCarrier.java @@ -5,6 +5,7 @@ import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.condition.Condition; import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import org.jetbrains.annotations.Nullable; import java.util.Map; @@ -70,6 +71,11 @@ public class EffectCarrier { return actionMap; } + @Nullable + public Action[] getActions(ActionTrigger trigger) { + return actionMap.get(trigger); + } + public boolean isPersist() { return persist; } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java index ad3869b8..d47f7863 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java @@ -3,6 +3,7 @@ package net.momirealms.customfishing.api.mechanic.loot; import net.momirealms.customfishing.api.CustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.condition.Condition; import net.momirealms.customfishing.api.mechanic.game.GameConfig; import org.jetbrains.annotations.NotNull; @@ -167,6 +168,16 @@ public class CFLoot implements Loot { return actionMap.get(actionTrigger); } + @Override + public void triggerActions(ActionTrigger actionTrigger, Condition condition) { + Action[] actions = getActions(actionTrigger); + if (actions != null) { + for (Action action : actions) { + action.trigger(condition); + } + } + } + @Override public Action[] getSuccessTimesActions(int times) { return successTimesActionMap.get(times); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java index cbd9b5a4..13f840c5 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java @@ -19,6 +19,7 @@ package net.momirealms.customfishing.api.mechanic.loot; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.condition.Condition; import net.momirealms.customfishing.api.mechanic.game.GameConfig; import org.jetbrains.annotations.NotNull; @@ -87,6 +88,8 @@ public interface Loot { */ Action[] getActions(ActionTrigger actionTrigger); + void triggerActions(ActionTrigger actionTrigger, Condition condition); + /** * get actions when succeeding in fishing for certain times * @param times times diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java index 33940d02..a2c72056 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java @@ -22,38 +22,27 @@ import net.momirealms.customfishing.api.data.StatisticData; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; import net.momirealms.customfishing.api.mechanic.loot.Loot; -import org.bukkit.configuration.ConfigurationSection; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class Statistics { @SerializedName("statistic_map") - private final HashMap statisticMap; + private final ConcurrentHashMap statisticMap; private int total; - public Statistics() { - this.statisticMap = new HashMap<>(); - this.total = 0; - } - - public Statistics(ConfigurationSection section) { - this.statisticMap = new HashMap<>(); - this.total = 0; - for (String key : section.getKeys(false)) { - int amount = section.getInt(key); - total += amount; - statisticMap.put(key, amount); - } - } - public Statistics(StatisticData statisticData) { - this.statisticMap = new HashMap<>(statisticData.statisticMap); + this.statisticMap = new ConcurrentHashMap<>(statisticData.statisticMap); this.total = statisticMap.values().stream().mapToInt(Integer::intValue).sum(); } - public void addLootAmount(Loot loot, FishingPreparation fishingPreparation, int amount) { + public synchronized void addLootAmount(Loot loot, FishingPreparation fishingPreparation, int amount) { + if (amount == 1) { + addSingleLootAmount(loot, fishingPreparation); + return; + } Integer previous = statisticMap.get(loot.getID()); if (previous == null) previous = 0; int after = previous + amount; @@ -75,6 +64,19 @@ public class Statistics { } } + private void addSingleLootAmount(Loot loot, FishingPreparation fishingPreparation) { + Integer previous = statisticMap.get(loot.getID()); + if (previous == null) previous = 0; + int after = previous + 1; + statisticMap.put(loot.getID(), after); + total += 1; + Action[] actions = loot.getSuccessTimesActionMap().get(after); + if (actions != null) + for (Action action : actions) { + action.trigger(fishingPreparation); + } + } + public int getLootAmount(String key) { Integer amount = statisticMap.get(key); return amount == null ? 0 : amount; @@ -88,7 +90,7 @@ public class Statistics { statisticMap.clear(); } - public HashMap getStatisticMap() { + public Map getStatisticMap() { return statisticMap; } diff --git a/api/src/main/java/net/momirealms/customfishing/api/util/WeightUtils.java b/api/src/main/java/net/momirealms/customfishing/api/util/WeightUtils.java index db352aa6..3e14c754 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/util/WeightUtils.java +++ b/api/src/main/java/net/momirealms/customfishing/api/util/WeightUtils.java @@ -19,7 +19,10 @@ package net.momirealms.customfishing.api.util; import net.momirealms.customfishing.api.common.Pair; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; public class WeightUtils { @@ -37,7 +40,7 @@ public class WeightUtils { return getRandom(weights, available, index); } - public static T getRandom(HashMap map) { + public static T getRandom(Map map) { List available = new ArrayList<>(); double[] weights = new double[map.size()]; int index = 0; diff --git a/plugin/src/main/java/net/momirealms/customfishing/command/CommandManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/command/CommandManagerImpl.java index ce9cedf6..0f305c0e 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/command/CommandManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/command/CommandManagerImpl.java @@ -26,6 +26,7 @@ import net.momirealms.customfishing.adventure.AdventureManagerImpl; import net.momirealms.customfishing.api.CustomFishingPlugin; import net.momirealms.customfishing.api.manager.CommandManager; import net.momirealms.customfishing.command.sub.CompetitionCommand; +import net.momirealms.customfishing.command.sub.DebugCommand; import net.momirealms.customfishing.command.sub.FishingBagCommand; import net.momirealms.customfishing.command.sub.ItemCommand; import net.momirealms.customfishing.setting.Locale; @@ -47,7 +48,8 @@ public class CommandManagerImpl implements CommandManager { .withSubcommands( getReloadCommand(), CompetitionCommand.INSTANCE.getCompetitionCommand(), - ItemCommand.INSTANCE.getItemCommand() + ItemCommand.INSTANCE.getItemCommand(), + DebugCommand.INSTANCE.getDebugCommand() ) .register(); diff --git a/plugin/src/main/java/net/momirealms/customfishing/command/sub/DebugCommand.java b/plugin/src/main/java/net/momirealms/customfishing/command/sub/DebugCommand.java new file mode 100644 index 00000000..d58e448e --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/command/sub/DebugCommand.java @@ -0,0 +1,117 @@ +package net.momirealms.customfishing.command.sub; + +import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.IStringTooltip; +import dev.jorel.commandapi.StringTooltip; +import dev.jorel.commandapi.arguments.ArgumentSuggestions; +import dev.jorel.commandapi.arguments.BooleanArgument; +import net.momirealms.biomeapi.BiomeAPI; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.integration.SeasonInterface; +import net.momirealms.customfishing.api.manager.AdventureManager; +import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; +import net.momirealms.customfishing.api.mechanic.effect.Effect; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class DebugCommand { + + public static DebugCommand INSTANCE = new DebugCommand(); + + public CommandAPICommand getDebugCommand() { + return new CommandAPICommand("debug") + .withSubcommands( + getLootChanceCommand(), + getBiomeCommand(), + getSeasonCommand() + ); + } + + public CommandAPICommand getBiomeCommand() { + return new CommandAPICommand("biome") + .executesPlayer((player, arg) -> { + AdventureManagerImpl.getInstance().sendMessage(player, BiomeAPI.getBiome(player.getLocation())); + }); + } + + public CommandAPICommand getSeasonCommand() { + return new CommandAPICommand("season") + .executesPlayer((player, arg) -> { + SeasonInterface seasonInterface = CustomFishingPlugin.get().getIntegrationManager().getSeasonInterface(); + if (seasonInterface == null) { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, "NO SEASON PLUGIN"); + return; + } + AdventureManagerImpl.getInstance().sendMessage(player, seasonInterface.getSeason(player.getLocation().getWorld())); + }); + } + + public CommandAPICommand getLootChanceCommand() { + return new CommandAPICommand("loot-chance") + .withArguments(new BooleanArgument("lava fishing").replaceSuggestions(ArgumentSuggestions.stringsWithTooltips(info -> + new IStringTooltip[] { + StringTooltip.ofString("true", "loots in lava"), + StringTooltip.ofString("false", "loots in water") + }))) + .executesPlayer((player, arg) -> { + Effect initialEffect = CustomFishingPlugin.get().getEffectManager().getInitialEffect(); + FishingPreparation fishingPreparation = new FishingPreparation(player, CustomFishingPlugin.get()); + boolean inLava = (boolean) arg.getOrDefault("lava fishing", false); + fishingPreparation.insertArg("{lava}", String.valueOf(inLava)); + fishingPreparation.mergeEffect(initialEffect); + //TODO apply totems + + var map = CustomFishingPlugin.get().getFishingManager().getPossibleLootKeysWithWeight(initialEffect, fishingPreparation); + List loots = new ArrayList<>(); + double sum = 0; + for (Map.Entry entry : map.entrySet()) { + double weight = entry.getValue(); + String loot = entry.getKey(); + if (weight <= 0) continue; + loots.add(new LootWithWeight(loot, weight)); + sum += weight; + } + LootWithWeight[] lootArray = loots.toArray(new LootWithWeight[0]); + quickSort(lootArray, 0,lootArray.length - 1); + AdventureManager adventureManager = AdventureManagerImpl.getInstance(); + adventureManager.sendMessage(player, "---------- results ---------"); + for (LootWithWeight loot : lootArray) { + adventureManager.sendMessage(player, "GET'>" +loot.key() + ": " + String.format("%.2f", loot.weight()*100/sum) + "% (" + String.format("%.2f", loot.weight()) + ")"); + } + adventureManager.sendMessage(player, "----------- end -----------"); + }); + } + + public record LootWithWeight(String key, double weight) { + } + + public static void quickSort(LootWithWeight[] loot, int low, int high) { + if (low < high) { + int pi = partition(loot, low, high); + quickSort(loot, low, pi - 1); + quickSort(loot, pi + 1, high); + } + } + + public static int partition(LootWithWeight[] loot, int low, int high) { + double pivot = loot[high].weight(); + int i = low - 1; + for (int j = low; j <= high - 1; j++) { + if (loot[j].weight() > pivot) { + i++; + swap(loot, i, j); + } + } + swap(loot, i + 1, high); + return i + 1; + } + + public static void swap(LootWithWeight[] loot, int i, int j) { + LootWithWeight temp = loot[i]; + loot[i] = loot[j]; + loot[j] = temp; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java index 59253928..e54cf7ac 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java @@ -24,6 +24,10 @@ import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -32,7 +36,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -public class PlaceholderManagerImpl implements PlaceholderManager { +public class PlaceholderManagerImpl implements PlaceholderManager, Listener { private static PlaceholderManagerImpl instance; private final CustomFishingPlugin plugin; @@ -59,18 +63,25 @@ public class PlaceholderManagerImpl implements PlaceholderManager { public void load() { if (competitionPapi != null) competitionPapi.load(); if (statisticsPapi != null) statisticsPapi.load(); + Bukkit.getPluginManager().registerEvents(this, plugin); loadCustomPlaceholders(); } public void unload() { if (competitionPapi != null) competitionPapi.unload(); if (statisticsPapi != null) statisticsPapi.unload(); + HandlerList.unregisterAll(this); } public void disable() { this.customPlaceholderMap.clear(); } + @EventHandler + public void onQuit(PlayerQuitEvent event) { + cachedPlaceholders.remove(event.getPlayer().getUniqueId()); + } + public void loadCustomPlaceholders() { YamlConfiguration config = plugin.getConfig("config.yml"); ConfigurationSection section = config.getConfigurationSection("other-settings.placeholder-register"); diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java index 5659b13f..d71c14b1 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java @@ -23,16 +23,21 @@ import net.momirealms.customfishing.adventure.AdventureManagerImpl; import net.momirealms.customfishing.api.CustomFishingPlugin; import net.momirealms.customfishing.api.common.Pair; import net.momirealms.customfishing.api.manager.ActionManager; +import net.momirealms.customfishing.api.mechanic.GlobalSettings; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionExpansion; import net.momirealms.customfishing.api.mechanic.action.ActionFactory; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.requirement.Requirement; import net.momirealms.customfishing.api.util.LogUtils; import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.util.ArmorStandUtils; import net.momirealms.customfishing.util.ClassUtils; import net.momirealms.customfishing.util.ConfigUtils; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Player; import org.bukkit.potion.PotionEffect; @@ -73,20 +78,30 @@ public class ActionManagerImpl implements ActionManager { this.registerDelayedAction(); this.registerConditionalAction(); this.registerPriorityAction(); + this.registerLevelAction(); + this.registerHologramAction(); + this.registerFakeItemAction(); } public void load() { this.loadExpansions(); + this.loadGlobalEventActions(); } public void unload() { - + GlobalSettings.unload(); } public void disable() { + unload(); this.actionBuilderMap.clear(); } + private void loadGlobalEventActions() { + YamlConfiguration config = plugin.getConfig("config.yml"); + GlobalSettings.load(config.getConfigurationSection("mechanics.global-events")); + } + @Override public boolean registerAction(String type, ActionFactory actionFactory) { if (this.actionBuilderMap.containsKey(type)) return false; @@ -104,6 +119,21 @@ public class ActionManagerImpl implements ActionManager { return getActionBuilder(section.getString("type")).build(section.get("value"), section.getDouble("chance", 1d)); } + @Override + public HashMap getActionMap(ConfigurationSection section) { + HashMap actionMap = new HashMap<>(); + if (section == null) return actionMap; + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + actionMap.put( + ActionTrigger.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)), + getActions(innerSection) + ); + } + } + return actionMap; + } + @Nullable @Override public Action[] getActions(ConfigurationSection section) { @@ -247,6 +277,62 @@ public class ActionManagerImpl implements ActionManager { }); } + private void registerHologramAction() { + registerAction("hologram", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + String text = section.getString("text", ""); + int duration = section.getInt("duration", 20); + boolean position = section.getString("position", "hook").equals("hook"); + double x = section.getDouble("x"); + double y = section.getDouble("y"); + double z = section.getDouble("z"); + return condition -> { + if (Math.random() > chance) return; + Player player = condition.getPlayer(); + Location location = position ? condition.getLocation() : player.getLocation(); + ArmorStandUtils.sendHologram( + condition.getPlayer(), + location.clone().add(x, y, z), + AdventureManagerImpl.getInstance().getComponentFromMiniMessage( + PlaceholderManagerImpl.getInstance().parse(player, text, condition.getArgs()) + ), + duration + ); + }; + } else { + LogUtils.warn("Illegal value format found at action: hologram"); + return null; + } + }); + } + + private void registerFakeItemAction() { + registerAction("fake-item", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + String[] itemSplit = section.getString("item", "").split(":", 2); + int duration = section.getInt("duration", 20); + boolean position = section.getString("position", "hook").equals("hook"); + double x = section.getDouble("x"); + double y = section.getDouble("y"); + double z = section.getDouble("z"); + return condition -> { + if (Math.random() > chance) return; + Player player = condition.getPlayer(); + Location location = position ? condition.getLocation() : player.getLocation(); + ArmorStandUtils.sendFakeItem( + condition.getPlayer(), + location.clone().add(x, y, z), + plugin.getItemManager().build(player, itemSplit[0], itemSplit[1], condition.getArgs()), + duration + ); + }; + } else { + LogUtils.warn("Illegal value format found at action: hologram"); + return null; + } + }); + } + private void registerChainAction() { registerAction("chain", (args, chance) -> { List actions = new ArrayList<>(); @@ -357,6 +443,17 @@ public class ActionManagerImpl implements ActionManager { }); } + private void registerLevelAction() { + registerAction("level", (args, chance) -> { + int level = (int) args; + return condition -> { + if (Math.random() > chance) return; + Player player = condition.getPlayer(); + player.setLevel(Math.max(0, player.getLevel() + level)); + }; + }); + } + @SuppressWarnings("all") private void registerSoundAction() { registerAction("sound", (args, chance) -> { @@ -452,6 +549,7 @@ public class ActionManagerImpl implements ActionManager { }); } + @SuppressWarnings("ResultOfMethodCallIgnored") private void loadExpansions() { File expansionFolder = new File(plugin.getDataFolder(), EXPANSION_FOLDER); if (!expansionFolder.exists()) diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java index f4522a8a..9560e47e 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java @@ -82,9 +82,10 @@ public class Competition implements FishingCompetition { this.actionBarManager.load(); } + Action[] actions = config.getStartActions(); if (actions != null) { - Condition condition = new Condition(); + Condition condition = new Condition(null, null, new HashMap<>()); for (Action action : actions) { action.trigger(condition); } @@ -171,7 +172,7 @@ public class Competition implements FishingCompetition { // do end actions Action[] actions = config.getEndActions(); if (actions != null) { - Condition condition = new Condition(new HashMap<>(publicPlaceholders)); + Condition condition = new Condition(null, null, new HashMap<>(publicPlaceholders)); for (Action action : actions) { action.trigger(condition); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java index fe94c720..908d49b9 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java @@ -108,6 +108,7 @@ public class EffectManagerImpl implements EffectManager { .key(key) .requirements(plugin.getRequirementManager().getRequirements(section.getConfigurationSection("requirements"), true)) .effect(getEffectFromSection(section.getConfigurationSection("effects"))) + .actionMap(plugin.getActionManager().getActionMap(section.getConfigurationSection("events"))) .build(); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java index 21630e20..468c2182 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java @@ -26,13 +26,13 @@ import net.momirealms.customfishing.api.event.LavaFishingEvent; import net.momirealms.customfishing.api.event.RodCastEvent; import net.momirealms.customfishing.api.manager.FishingManager; import net.momirealms.customfishing.api.manager.RequirementManager; +import net.momirealms.customfishing.api.mechanic.GlobalSettings; import net.momirealms.customfishing.api.mechanic.TempFishingState; -import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; +import net.momirealms.customfishing.api.mechanic.condition.Condition; import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; import net.momirealms.customfishing.api.mechanic.effect.Effect; -import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier; import net.momirealms.customfishing.api.mechanic.game.GameConfig; import net.momirealms.customfishing.api.mechanic.game.GameInstance; import net.momirealms.customfishing.api.mechanic.game.GameSettings; @@ -41,7 +41,6 @@ import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.mechanic.loot.Modifier; import net.momirealms.customfishing.api.util.LogUtils; import net.momirealms.customfishing.api.util.WeightUtils; -import net.momirealms.customfishing.mechanic.loot.LootManagerImpl; import net.momirealms.customfishing.mechanic.requirement.RequirementManagerImpl; import net.momirealms.customfishing.setting.Config; import org.bukkit.Bukkit; @@ -56,12 +55,10 @@ import org.bukkit.event.inventory.InventoryPickupItemEvent; import org.bukkit.event.player.*; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class FishingManagerImpl implements Listener, FishingManager { @@ -202,6 +199,19 @@ public class FishingManagerImpl implements Listener, FishingManager { } } + @EventHandler + public void onConsumeItem(PlayerItemConsumeEvent event) { + if (event.isCancelled()) return; + ItemStack itemStack = event.getItem(); + String id = plugin.getItemManager().getAnyItemID(itemStack); + Loot loot = plugin.getLootManager().getLoot(id); + if (loot != null) { + Condition condition = new Condition(event.getPlayer()); + GlobalSettings.triggerLootActions(ActionTrigger.CONSUME, condition); + loot.triggerActions(ActionTrigger.CONSUME, condition); + } + } + @Override public boolean removeHook(UUID uuid) { FishHook hook = hookCacheMap.remove(uuid); @@ -248,16 +258,11 @@ public class FishingManagerImpl implements Listener, FishingManager { fishingPreparation.mergeEffect(initialEffect); // Apply enchants - for (String enchant : plugin.getIntegrationManager().getEnchantments(fishingPreparation.getRodItemStack())) { - EffectCarrier enchantEffect = plugin.getEffectManager().getEffect("enchant", enchant); - if (enchantEffect != null && enchantEffect.isConditionMet(fishingPreparation)) { - initialEffect.merge(enchantEffect.getEffect()); - } - } + //TODO Apply totem effects // Call custom event - RodCastEvent rodCastEvent = new RodCastEvent(event, initialEffect); + RodCastEvent rodCastEvent = new RodCastEvent(event, fishingPreparation, initialEffect); Bukkit.getPluginManager().callEvent(rodCastEvent); if (rodCastEvent.isCancelled()) { return; @@ -271,15 +276,15 @@ public class FishingManagerImpl implements Listener, FishingManager { // Reduce amount & Send animation var baitItem = fishingPreparation.getBaitItemStack(); if (baitItem != null) { - if (Config.enableBaitAnimation) { - ItemStack cloned = baitItem.clone(); - cloned.setAmount(1); - new BaitAnimationTask(plugin, player, fishHook, cloned); - } + ItemStack cloned = baitItem.clone(); + cloned.setAmount(1); + new BaitAnimationTask(plugin, player, fishHook, cloned); baitItem.setAmount(baitItem.getAmount() - 1); } // Arrange hook check task this.hookCheckMap.put(player.getUniqueId(), new HookCheckTimerTask(this, fishHook, fishingPreparation, initialEffect)); + // trigger actions + fishingPreparation.triggerActions(ActionTrigger.CAST); } private void onCaughtEntity(PlayerFishEvent event) { @@ -343,6 +348,8 @@ public class FishingManagerImpl implements Listener, FishingManager { // put vanilla loot in map this.vanillaLootMap.put(uuid, item.getItemStack()); } + loot.triggerActions(ActionTrigger.HOOK, temp.getPreparation()); + temp.getPreparation().triggerActions(ActionTrigger.HOOK); if (!loot.disableGame()) { // start the game if the loot has a game event.setCancelled(true); @@ -379,12 +386,12 @@ public class FishingManagerImpl implements Listener, FishingManager { if (temp != null) { var loot = temp.getLoot(); - Action[] actions = loot.getActions(ActionTrigger.HOOK); - if (actions != null) - for (Action action : actions) - action.trigger(temp.getPreparation()); + loot.triggerActions(ActionTrigger.BITE, temp.getPreparation()); + temp.getPreparation().triggerActions(ActionTrigger.BITE); if (loot.instanceGame() && !loot.disableGame()) { + loot.triggerActions(ActionTrigger.HOOK, temp.getPreparation()); + temp.getPreparation().triggerActions(ActionTrigger.HOOK); startFishingGame(player, loot, temp.getEffect()); } } @@ -414,9 +421,12 @@ public class FishingManagerImpl implements Listener, FishingManager { var temp = this.tempFishingStateMap.get(uuid); if (temp != null ) { - if (!temp.getLoot().disableGame()) { + Loot loot = temp.getLoot(); + loot.triggerActions(ActionTrigger.HOOK, temp.getPreparation()); + temp.getPreparation().triggerActions(ActionTrigger.HOOK); + if (!loot.disableGame()) { event.setCancelled(true); - startFishingGame(player, temp.getLoot(), temp.getEffect()); + startFishingGame(player, loot, temp.getEffect()); } else { success(temp, event.getHook()); } @@ -454,7 +464,15 @@ public class FishingManagerImpl implements Listener, FishingManager { gamingPlayer.cancel(); gamingPlayerMap.remove(uuid); - plugin.getScheduler().runTaskSync(fishHook::remove, fishHook.getLocation()); + plugin.getScheduler().runTaskSync(() -> { + fishHook.remove(); + ItemStack rod = tempFishingState.getPreparation().getRodItemStack(); + PlayerItemDamageEvent damageEvent = new PlayerItemDamageEvent(player, rod, 1); + Bukkit.getPluginManager().callEvent(damageEvent); + if (damageEvent.isCancelled()) { + return; + } + }, fishHook.getLocation()); } public void fail(TempFishingState state, FishHook hook) { @@ -482,15 +500,10 @@ public class FishingManagerImpl implements Listener, FishingManager { return; } - Action[] globalActions = LootManagerImpl.GlobalSetting.globalLootProperties.getActions(ActionTrigger.FAILURE); - if (globalActions != null) - for (Action action : globalActions) - action.trigger(fishingPreparation); + GlobalSettings.triggerLootActions(ActionTrigger.FAILURE, fishingPreparation); + loot.triggerActions(ActionTrigger.FAILURE, fishingPreparation); + fishingPreparation.triggerActions(ActionTrigger.FAILURE); - Action[] actions = loot.getActions(ActionTrigger.FAILURE); - if (actions != null) - for (Action action : actions) - action.trigger(fishingPreparation); }, hook.getLocation()); } @@ -579,28 +592,35 @@ public class FishingManagerImpl implements Listener, FishingManager { fishingPreparation.insertArg("{score}","-1"); } - Action[] globalActions = LootManagerImpl.GlobalSetting.globalLootProperties.getActions(ActionTrigger.SUCCESS); - if (globalActions != null) - for (Action action : globalActions) - action.trigger(fishingPreparation); - - Action[] actions = loot.getActions(ActionTrigger.SUCCESS); - if (actions != null) - for (Action action : actions) - action.trigger(fishingPreparation); + // events and actions + GlobalSettings.triggerLootActions(ActionTrigger.SUCCESS, fishingPreparation); + loot.triggerActions(ActionTrigger.SUCCESS, fishingPreparation); + fishingPreparation.triggerActions(ActionTrigger.SUCCESS); player.setStatistic( Statistic.FISH_CAUGHT, player.getStatistic(Statistic.FISH_CAUGHT) + 1 ); + + if (!loot.disableStats()) + Optional.ofNullable( + plugin.getStatisticsManager() + .getStatistics(player.getUniqueId()) + ).ifPresent(it -> it.addLootAmount(loot, fishingPreparation, 1)); } - @Nullable - public Loot getNextLoot(Effect initialEffect, FishingPreparation fishingPreparation) { - HashMap lootWithWeight = plugin.getRequirementManager().getLootWithWeight(fishingPreparation); + @Override + public Collection getPossibleLootKeys (FishingPreparation fishingPreparation) { + return plugin.getRequirementManager().getLootWithWeight(fishingPreparation).keySet(); + } + + @NotNull + @Override + public Map getPossibleLootKeysWithWeight(Effect initialEffect, FishingPreparation fishingPreparation) { + Map lootWithWeight = plugin.getRequirementManager().getLootWithWeight(fishingPreparation); if (lootWithWeight.size() == 0) { LogUtils.warn(String.format("No Loot found at %s for Player %s!", fishingPreparation.getPlayer().getLocation(), fishingPreparation.getPlayer().getName())); - return null; + return new HashMap<>(); } Player player = fishingPreparation.getPlayer(); @@ -608,8 +628,13 @@ public class FishingManagerImpl implements Listener, FishingManager { double previous = lootWithWeight.getOrDefault(pair.left(), 0d); lootWithWeight.put(pair.left(), pair.right().modify(player, previous)); } + return lootWithWeight; + } - String key = WeightUtils.getRandom(lootWithWeight); + @Override + @Nullable + public Loot getNextLoot(Effect initialEffect, FishingPreparation fishingPreparation) { + String key = WeightUtils.getRandom(getPossibleLootKeysWithWeight(initialEffect, fishingPreparation)); Loot loot = plugin.getLootManager().getLoot(key); if (loot == null) { LogUtils.warn(String.format("Loot %s doesn't exist!", key)); diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java index bb502f4c..ef8ed6db 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java @@ -21,14 +21,15 @@ import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; import net.momirealms.customfishing.adventure.AdventureManagerImpl; import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.event.FishHookLandEvent; import net.momirealms.customfishing.api.event.LavaFishingEvent; import net.momirealms.customfishing.api.mechanic.TempFishingState; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.scheduler.CancellableTask; import net.momirealms.customfishing.setting.Config; -import net.momirealms.customfishing.util.ArmorStandUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -59,6 +60,7 @@ public class HookCheckTimerTask implements Runnable { private boolean reserve; private int jumpTimer; private Entity hookedEntity; + private Loot loot; public HookCheckTimerTask( FishingManagerImpl manager, @@ -94,14 +96,11 @@ public class HookCheckTimerTask implements Runnable { return; } if (firstTime) { - this.fishingPreparation.insertArg("in-lava", "true"); - if (Config.enableSplashAnimation) - ArmorStandUtils.sendAnimationToPlayer( - fishingPreparation.getPlayer(), - fishHook.getLocation(), - CustomFishingPlugin.get().getItemManager().build(null, "util", Config.lavaSplashItem), - Config.splashAnimationTime - ); + this.fishingPreparation.setLocation(fishHook.getLocation()); + this.fishingPreparation.insertArg("{lava}", "true"); + this.fishingPreparation.triggerActions(ActionTrigger.LAND); + FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.LAVA); + Bukkit.getPluginManager().callEvent(event); firstTime = false; this.setTempState(); } @@ -127,16 +126,13 @@ public class HookCheckTimerTask implements Runnable { return; } if (fishHook.isInWater()) { + this.fishingPreparation.setLocation(fishHook.getLocation()); + this.fishingPreparation.insertArg("{lava}", "false"); + this.fishingPreparation.triggerActions(ActionTrigger.LAND); + FishHookLandEvent event = new FishHookLandEvent(fishingPreparation.getPlayer(), FishHookLandEvent.Target.WATER); + Bukkit.getPluginManager().callEvent(event); // if the hook is in water // then cancel the task - this.fishingPreparation.insertArg("in-lava", "false"); - if (Config.enableSplashAnimation) - ArmorStandUtils.sendAnimationToPlayer( - fishingPreparation.getPlayer(), - fishHook.getLocation(), - CustomFishingPlugin.get().getItemManager().build(null, "util", Config.waterSplashItem), - Config.splashAnimationTime - ); this.destroy(); this.setTempState(); return; @@ -161,6 +157,7 @@ public class HookCheckTimerTask implements Runnable { Loot nextLoot = manager.getNextLoot(initialEffect, fishingPreparation); if (nextLoot == null) return; + this.loot = nextLoot; fishingPreparation.insertArg("{nick}", nextLoot.getNick()); fishingPreparation.insertArg("{loot}", nextLoot.getID()); CustomFishingPlugin.get().getScheduler().runTaskAsync(() -> manager.setTempFishingState(fishingPreparation.getPlayer(), new TempFishingState( @@ -198,6 +195,9 @@ public class HookCheckTimerTask implements Runnable { return; } + this.loot.triggerActions(ActionTrigger.BITE, fishingPreparation); + this.fishingPreparation.triggerActions(ActionTrigger.BITE); + this.fishHooked = true; this.removeTempEntity(); diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java index 4b974208..26ade37c 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java @@ -104,6 +104,7 @@ public class GameManagerImpl implements GameManager { @Override @Nullable public GameConfig getGameConfig(String key) { + if (key == null) return null; return gameConfigMap.get(key); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java index f88d27d8..5cc96b8c 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java @@ -20,7 +20,6 @@ package net.momirealms.customfishing.mechanic.loot; import net.momirealms.customfishing.api.CustomFishingPlugin; import net.momirealms.customfishing.api.manager.LootManager; import net.momirealms.customfishing.api.mechanic.action.Action; -import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.loot.CFLoot; import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.mechanic.loot.LootType; @@ -40,16 +39,6 @@ public class LootManagerImpl implements LootManager { private final HashMap lootMap; private final HashMap> lootGroupMap; - public static class GlobalSetting { - public static CFLoot globalLootProperties; - public static boolean disableStats; - public static boolean disableGames; - public static boolean instantGame; - public static boolean showInFinder; - public static String gameGroup; - public static String[] lootGroup; - } - public LootManagerImpl(CustomFishingPlugin plugin) { this.plugin = plugin; this.lootMap = new HashMap<>(); @@ -57,7 +46,6 @@ public class LootManagerImpl implements LootManager { } public void load() { - this.loadGlobalLootProperties(); this.loadLootsFromPluginFolder(); } @@ -95,11 +83,6 @@ public class LootManagerImpl implements LootManager { } } - @Override - public Loot getGlobalLootProperties() { - return GlobalSetting.globalLootProperties; - } - @Nullable @Override public List getLootGroup(String key) { @@ -112,21 +95,6 @@ public class LootManagerImpl implements LootManager { return lootMap.get(key); } - private void loadGlobalLootProperties() { - YamlConfiguration config = plugin.getConfig("config.yml"); - GlobalSetting.globalLootProperties = getSingleSectionItem( - Objects.requireNonNull(config.getConfigurationSection("mechanics.global-loot-properties")), - "GLOBAL", - "global" - ); - GlobalSetting.disableStats = GlobalSetting.globalLootProperties.disableStats(); - GlobalSetting.disableGames = GlobalSetting.globalLootProperties.disableGame(); - GlobalSetting.instantGame = GlobalSetting.globalLootProperties.instanceGame(); - GlobalSetting.showInFinder = GlobalSetting.globalLootProperties.showInFinder(); - GlobalSetting.lootGroup = GlobalSetting.globalLootProperties.getLootGroup(); - GlobalSetting.gameGroup = GlobalSetting.globalLootProperties.getGameConfigKey(); - } - private void loadSingleFile(File file, String namespace) { YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file); for (Map.Entry entry : yaml.getValues(false).entrySet()) { @@ -154,33 +122,18 @@ public class LootManagerImpl implements LootManager { private CFLoot getSingleSectionItem(ConfigurationSection section, String namespace, String key) { return new CFLoot.Builder(key, LootType.valueOf(namespace.toUpperCase(Locale.ENGLISH))) - .disableStats(section.getBoolean("disable-stat", GlobalSetting.disableStats)) - .disableGames(section.getBoolean("disable-game", GlobalSetting.disableGames)) - .instantGame(section.getBoolean("instant-game", GlobalSetting.instantGame)) - .showInFinder(section.getBoolean("show-in-fishfinder", GlobalSetting.showInFinder)) - .gameConfig(section.getString("game-group", GlobalSetting.gameGroup)) - .lootGroup(ConfigUtils.stringListArgs(Optional.ofNullable(section.get("loot-group")).orElse(GlobalSetting.lootGroup)).toArray(new String[0])) + .disableStats(section.getBoolean("disable-stat", false)) + .disableGames(section.getBoolean("disable-game", false)) + .instantGame(section.getBoolean("instant-game", false)) + .showInFinder(section.getBoolean("show-in-fishfinder", true)) + .gameConfig(section.getString("game-group")) + .lootGroup(ConfigUtils.stringListArgs(section.get("loot-group")).toArray(new String[0])) .nick(section.getString("nick", section.getString("display.name", key))) - .addActions(getActionMap(section.getConfigurationSection("events"))) + .addActions(plugin.getActionManager().getActionMap(section.getConfigurationSection("events"))) .addTimesActions(getTimesActionMap(section.getConfigurationSection("events.success-times"))) .build(); } - - private HashMap getActionMap(ConfigurationSection section) { - HashMap actionMap = new HashMap<>(); - if (section == null) return actionMap; - for (Map.Entry entry : section.getValues(false).entrySet()) { - if (entry.getValue() instanceof ConfigurationSection innerSection) { - actionMap.put( - ActionTrigger.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)), - plugin.getActionManager().getActions(innerSection) - ); - } - } - return actionMap; - } - private HashMap getTimesActionMap(ConfigurationSection section) { HashMap actionMap = new HashMap<>(); if (section == null) return actionMap; diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java index ba39d91e..2315c0e5 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java @@ -117,6 +117,8 @@ public class RequirementManagerImpl implements RequirementManager { this.registerCompareRequirement(); this.registerAndRequirement(); this.registerOrRequirement(); + this.registerLevelRequirement(); + this.registerRandomRequirement(); } public ConditionalLoots getConditionalLoots(ConfigurationSection section) { @@ -302,7 +304,7 @@ public class RequirementManagerImpl implements RequirementManager { registerRequirement("in-lava", (args, actions, advanced) -> { boolean inLava = (boolean) args; return condition -> { - String current = condition.getArgs().get("in-lava"); + String current = condition.getArgs().get("{lava}"); if (current.equals(String.valueOf(inLava))) return true; if (advanced) triggerActions(actions, condition); @@ -311,6 +313,31 @@ public class RequirementManagerImpl implements RequirementManager { }); } + private void registerLevelRequirement() { + registerRequirement("level", (args, actions, advanced) -> { + int level = (int) args; + return condition -> { + int current = condition.getPlayer().getLevel(); + if (current >= level) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerRandomRequirement() { + registerRequirement("random", (args, actions, advanced) -> { + double random = ConfigUtils.getDoubleValue(args); + return condition -> { + if (Math.random() < random) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + private void registerBiomeRequirement() { registerRequirement("biome", (args, actions, advanced) -> { HashSet biomes = new HashSet<>(ConfigUtils.stringListArgs(args)); diff --git a/plugin/src/main/java/net/momirealms/customfishing/setting/Config.java b/plugin/src/main/java/net/momirealms/customfishing/setting/Config.java index e1969d4a..6766dd92 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/setting/Config.java +++ b/plugin/src/main/java/net/momirealms/customfishing/setting/Config.java @@ -68,13 +68,6 @@ public class Config { public static String bagTitle; public static List bagWhiteListItems; - // Animation - public static boolean enableBaitAnimation; - public static boolean enableSplashAnimation; - public static int splashAnimationTime; - public static String lavaSplashItem; - public static String waterSplashItem; - // Lava fishing public static int lavaMinTime; public static int lavaMaxTime; @@ -88,9 +81,10 @@ public class Config { public static boolean redisRanking; public static int placeholderLimit; - // + // Data save interval public static int dataSaveInterval; + // Legacy color code support public static boolean legacyColorSupport; public static void load() { @@ -108,7 +102,7 @@ public class Config { .builder() .setVersioning(new BasicVersioning("config-version")) .addIgnoredRoute(configVersion, "mechanics.mechanic-requirements", '.') - .addIgnoredRoute(configVersion, "mechanics.global-loot-properties", '.') + .addIgnoredRoute(configVersion, "mechanics.global-events", '.') .build() ); loadSettings(CustomFishingPlugin.getInstance().getConfig("config.yml")); @@ -139,12 +133,6 @@ public class Config { lavaMinTime = config.getInt("mechanics.lava-fishing.min-wait-time", 100); lavaMaxTime = config.getInt("mechanics.lava-fishing.max-wait-time", 600); - enableSplashAnimation = config.getBoolean("mechanics.animation.splash.enable", true); - enableBaitAnimation = config.getBoolean("mechanics.animation.bait.enable", true); - waterSplashItem = config.getString("mechanics.animation.splash.water"); - lavaSplashItem = config.getString("mechanics.animation.splash.lava"); - splashAnimationTime = config.getInt("mechanics.animation.splash.duration"); - vanillaMechanicIfNoLoot = config.getBoolean("mechanics.vanilla-mechanic-if-no-loot.enable", false); noLootActions = CustomFishingPlugin.get().getActionManager().getActions(config.getConfigurationSection("mechanics.vanilla-mechanic-if-no-loot.actions")); diff --git a/plugin/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java index d9288c8f..559ed0bf 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java +++ b/plugin/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java @@ -21,7 +21,7 @@ import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.wrappers.*; import com.google.common.collect.Lists; -import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.momirealms.customfishing.CustomFishingPluginImpl; import net.momirealms.customfishing.api.CustomFishingPlugin; @@ -73,14 +73,14 @@ public class ArmorStandUtils { metaPacket.getDataValueCollectionModifier().write(0, wrappedDataValueList); } - public static PacketContainer getMetaPacket(int id, String text) { + public static PacketContainer getMetaPacket(int id, Component component) { PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); metaPacket.getIntegers().write(0, id); if (CustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_R2()) { - WrappedDataWatcher wrappedDataWatcher = createDataWatcher(text); + WrappedDataWatcher wrappedDataWatcher = createDataWatcher(component); setValueList(metaPacket, wrappedDataWatcher); } else { - metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(text).getWatchableObjects()); + metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(component).getWatchableObjects()); } return metaPacket; } @@ -95,11 +95,11 @@ public class ArmorStandUtils { return wrappedDataWatcher; } - public static WrappedDataWatcher createDataWatcher(String text) { + public static WrappedDataWatcher createDataWatcher(Component component) { WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher(); WrappedDataWatcher.Serializer serializer1 = WrappedDataWatcher.Registry.get(Boolean.class); WrappedDataWatcher.Serializer serializer2 = WrappedDataWatcher.Registry.get(Byte.class); - wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true)), Optional.of(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(text))).getHandle())); + wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true)), Optional.of(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(component)).getHandle())); wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), true); wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, serializer2), (byte) 0x01); byte flag = 0x20; @@ -116,11 +116,18 @@ public class ArmorStandUtils { return equipPacket; } - public static void sendAnimationToPlayer(Player player, Location location, ItemStack itemStack, int time) { + public static void sendFakeItem(Player player, Location location, ItemStack itemStack, int time) { int id = new Random().nextInt(Integer.MAX_VALUE); CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0))); CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getMetaPacket(id)); CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getEquipPacket(id, itemStack)); CustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), time * 50L, TimeUnit.MILLISECONDS); } + + public static void sendHologram(Player player, Location location, Component component, int time) { + int id = new Random().nextInt(Integer.MAX_VALUE); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0))); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getMetaPacket(id, component)); + CustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), time * 50L, TimeUnit.MILLISECONDS); + } } \ No newline at end of file diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml index bf4c9ba0..46cb067f 100644 --- a/plugin/src/main/resources/config.yml +++ b/plugin/src/main/resources/config.yml @@ -21,14 +21,10 @@ mechanics: value: - blacklist_world - # Global loot properties - global-loot-properties: - show-in-fishfinder: true - disable-stat: false - disable-game: false - instant-game: false - prevent-grabbing: false - events: + # global event settings + global-events: + bait: {} + loot: success: title_action: type: random-title @@ -60,7 +56,37 @@ mechanics: stay: 30 fade-out: 10 chance: 1.0 - + rod: + land: + priority_action: + type: priority + value: + priority_1: + conditions: + in-lava: true + actions: + fake_item_action: + type: fake-item + value: + duration: 35 + position: hook + item: util:lava_effect + y: 0 + x: 0 + z: 0 + priority_2: + conditions: + in-lava: false + actions: + fake_item_action: + type: fake-item + value: + duration: 35 + position: hook + item: util:water_effect + y: 0 + x: 0 + z: 0 # Fishing bag is where players can store their baits, utils and rods (Fish optional) fishing-bag: # Enable @@ -79,16 +105,6 @@ mechanics: min-wait-time: 100 max-wait-time: 600 - # Animation settings - animation: - splash: - enable: true - water: water_effect - lava: lava_effect - duration: 25 - bait: - enable: true - # Competition settings competition: # Use redis for cross server data synchronization diff --git a/plugin/src/main/resources/contents/loots/default.yml b/plugin/src/main/resources/contents/loots/default.yml index 06af7e95..5b551d5e 100644 --- a/plugin/src/main/resources/contents/loots/default.yml +++ b/plugin/src/main/resources/contents/loots/default.yml @@ -11,7 +11,7 @@ rubbish: disable-game: true instant-game: false prevent-grabbing: false - action: + events: success: mending: type: mending @@ -27,7 +27,7 @@ tuna_fish: - Tuna is a kind of healthy food. - 'size: {size}cm' custom-model-data: 50001 - action: + events: success: action_mending: type: mending @@ -47,7 +47,7 @@ tuna_fish_silver_star: - Tuna is a kind of healthy food. - 'size: {size}cm' custom-model-data: 50002 - action: + events: success: action_mending: type: mending @@ -67,7 +67,7 @@ tuna_fish_golden_star: - Tuna is a kind of healthy food. - 'size: {size}cm' custom-model-data: 50003 - action: + events: success: action_mending: type: mending @@ -90,7 +90,7 @@ pike_fish: - water and inland freshwater lakes - 'size: {size}cm' custom-model-data: 50004 - action: + events: success: action_mending: type: mending @@ -113,7 +113,7 @@ pike_fish_silver_star: - water and inland freshwater lakes - 'size: {size}cm' custom-model-data: 50005 - action: + events: success: action_mending: type: mending @@ -136,7 +136,7 @@ pike_fish_golden_star: - water and inland freshwater lakes - 'size: {size}cm' custom-model-data: 50006 - action: + events: success: action_mending: type: mending @@ -158,7 +158,7 @@ gold_fish: price: base: 70 custom-model-data: 50007 - action: + events: success: action_mending: type: mending @@ -177,7 +177,7 @@ gold_fish_silver_star: price: base: 80 custom-model-data: 50008 - action: + events: success: action_mending: type: mending @@ -196,7 +196,7 @@ gold_fish_golden_star: price: base: 100 custom-model-data: 50009 - action: + events: success: action_mending: type: mending @@ -212,7 +212,7 @@ perch_fish: - foraging at dusk and early morning - 'size: {size}cm' custom-model-data: 50010 - action: + events: success: action_mending: type: mending @@ -233,7 +233,7 @@ perch_fish_silver_star: - foraging at dusk and early morning - 'size: {size}cm' custom-model-data: 50011 - action: + events: success: action_mending: type: mending @@ -254,7 +254,7 @@ perch_fish_golden_star: - foraging at dusk and early morning - 'size: {size}cm' custom-model-data: 50012 - action: + events: success: action_mending: type: mending @@ -275,7 +275,7 @@ mullet_fish: - to treat spleen and stomach weakness - 'size: {size}cm' custom-model-data: 50013 - action: + events: success: action_mending: type: mending @@ -296,7 +296,7 @@ mullet_fish_silver_star: - to treat spleen and stomach weakness - 'size: {size}cm' custom-model-data: 50014 - action: + events: success: action_mending: type: mending @@ -317,7 +317,7 @@ mullet_fish_golden_star: - to treat spleen and stomach weakness - 'size: {size}cm' custom-model-data: 50015 - action: + events: success: action_mending: type: mending @@ -338,7 +338,7 @@ sardine_fish: - Therefore, sardine are also called "smart food" - 'size: {size}cm' custom-model-data: 50016 - action: + events: success: action_mending: type: mending @@ -358,7 +358,7 @@ sardine_fish_silver_star: - Therefore, sardine are also called "smart food" - 'size: {size}cm' custom-model-data: 50017 - action: + events: success: action_mending: type: mending @@ -378,7 +378,7 @@ sardine_fish_golden_star: - Therefore, sardine are also called "smart food" - 'size: {size}cm' custom-model-data: 50018 - action: + events: success: action_mending: type: mending @@ -398,7 +398,7 @@ carp_fish: - One of the most common edible fish - 'size: {size}cm' custom-model-data: 50019 - action: + events: success: action_mending: type: mending @@ -417,7 +417,7 @@ carp_fish_silver_star: - One of the most common edible fish - 'size: {size}cm' custom-model-data: 50020 - action: + events: success: action_mending: type: mending @@ -436,7 +436,7 @@ carp_fish_golden_star: - One of the most common edible fish - 'size: {size}cm' custom-model-data: 50021 - action: + events: success: action_mending: type: mending @@ -456,7 +456,7 @@ cat_fish: - sharp jaw teeth, short intestine and stomach - 'size: {size}cm' custom-model-data: 50022 - action: + events: success: action_mending: type: mending @@ -476,7 +476,7 @@ cat_fish_silver_star: - sharp jaw teeth, short intestine and stomach - 'size: {size}cm' custom-model-data: 50023 - action: + events: success: action_mending: type: mending @@ -496,7 +496,7 @@ cat_fish_golden_star: - sharp jaw teeth, short intestine and stomach - 'size: {size}cm' custom-model-data: 50024 - action: + events: success: action_mending: type: mending @@ -517,7 +517,7 @@ octopus: - People often use pots to catch octopus - 'size: {size}cm' custom-model-data: 50025 - action: + events: success: action_mending: type: mending @@ -537,7 +537,7 @@ octopus_silver_star: - People often use pots to catch octopus - 'size: {size}cm' custom-model-data: 50026 - action: + events: success: action_mending: type: mending @@ -557,7 +557,7 @@ octopus_golden_star: - People often use pots to catch octopus - 'size: {size}cm' custom-model-data: 50027 - action: + events: success: action_mending: type: mending @@ -577,7 +577,7 @@ sunfish: - It only has one huge head - 'size: {size}cm' custom-model-data: 50028 - action: + events: success: action_mending: type: mending @@ -596,7 +596,7 @@ sunfish_silver_star: - It only has one huge head - 'size: {size}cm' custom-model-data: 50029 - action: + events: success: action_mending: type: mending @@ -615,7 +615,7 @@ sunfish_golden_star: - It only has one huge head - 'size: {size}cm' custom-model-data: 50030 - action: + events: success: action_mending: type: mending @@ -635,7 +635,7 @@ red_snapper_fish: - with a male as the "head of the family" - 'size: {size}cm' custom-model-data: 50031 - action: + events: success: action_mending: type: mending @@ -656,7 +656,7 @@ red_snapper_fish_silver_star: - with a male as the "head of the family" - 'size: {size}cm' custom-model-data: 50032 - action: + events: success: action_mending: type: mending @@ -677,7 +677,7 @@ red_snapper_fish_golden_star: - with a male as the "head of the family" - 'size: {size}cm' custom-model-data: 50033 - action: + events: success: action_mending: type: mending @@ -697,7 +697,7 @@ salmon_void_fish: lore: - A fish from the hell custom-model-data: 50034 - action: + events: success: action_mending: type: mending @@ -714,7 +714,7 @@ salmon_void_fish_silver_star: lore: - A fish from the hell custom-model-data: 50035 - action: + events: success: action_mending: type: mending @@ -732,7 +732,7 @@ salmon_void_fish_golden_star: - A fish from the hell group: gold custom-model-data: 50036 - action: + events: success: action_mending: type: mending @@ -751,7 +751,7 @@ woodskip_fish: - live in pools deep in the forest - 'size: {size}cm' custom-model-data: 50037 - action: + events: success: action_mending: type: mending @@ -771,7 +771,7 @@ woodskip_fish_silver_star: - live in pools deep in the forest - 'size: {size}cm' custom-model-data: 50038 - action: + events: success: action_mending: type: mending @@ -791,7 +791,7 @@ woodskip_fish_golden_star: - live in pools deep in the forest - 'size: {size}cm' custom-model-data: 50039 - action: + events: success: action_mending: type: mending @@ -812,7 +812,7 @@ sturgeon_fish: - population. Females can live up to 150 years - 'size: {size}cm' custom-model-data: 50040 - action: + events: success: action_mending: type: mending @@ -832,7 +832,7 @@ sturgeon_fish_silver_star: - population. Females can live up to 150 years - 'size: {size}cm' custom-model-data: 50041 - action: + events: success: action_mending: type: mending @@ -852,7 +852,7 @@ sturgeon_fish_golden_star: - population. Females can live up to 150 years - 'size: {size}cm' custom-model-data: 50042 - action: + events: success: action_mending: type: mending diff --git a/plugin/src/main/resources/contents/minigames/default.yml b/plugin/src/main/resources/contents/minigames/default.yml index 0a17a354..402281d1 100644 --- a/plugin/src/main/resources/contents/minigames/default.yml +++ b/plugin/src/main/resources/contents/minigames/default.yml @@ -5,7 +5,7 @@ ###################################### rainbow_1: game-type: accurate_click - title: '<#B22222>RED!' + title: '<#fd4036>RED!' subtitle: font: 'customfishing:default' bar: '뀋' @@ -24,7 +24,7 @@ rainbow_1: 7: 0 rainbow_2: game-type: accurate_click - title: '<#FFA500>ORANGE!' + title: '<#ffa449>ORANGE!' subtitle: font: 'customfishing:default' bar: '뀋' @@ -43,7 +43,7 @@ rainbow_2: 7: 0 rainbow_3: game-type: accurate_click - title: '<#FFFF00>YELLOW!' + title: '<#ffca4c>YELLOW!' subtitle: font: 'customfishing:default' bar: '뀋' @@ -62,7 +62,7 @@ rainbow_3: 7: 0 rainbow_4: game-type: accurate_click - title: 'GREEN!' + title: '<#34f250>GREEN!' subtitle: font: 'customfishing:default' bar: '뀋' @@ -81,7 +81,7 @@ rainbow_4: 7: 0 rainbow_5: game-type: accurate_click - title: '<#00FFFF>AQUA!' + title: '<#34f2d5>AQUA!' subtitle: font: 'customfishing:default' bar: '뀋' @@ -100,7 +100,7 @@ rainbow_5: 7: 0 rainbow_6: game-type: accurate_click - title: '<#1E90FF>BLUE!' + title: '<#34f2d5>BLUE!' subtitle: font: 'customfishing:default' bar: '뀋' @@ -119,7 +119,7 @@ rainbow_6: 7: 0 rainbow_7: game-type: accurate_click - title: '<#9400D3>PURPLE!' + title: '<#c96cff>PURPLE!' subtitle: font: 'customfishing:default' bar: '뀋' @@ -583,10 +583,4 @@ tension_game: - '뀖' - '뀗' - '뀘' - - '뀙' - -###################################### -# Burst # -# When the fish is hooked, you need # -# to click quickly in limited time # -###################################### + - '뀙' \ No newline at end of file diff --git a/plugin/src/main/resources/contents/rods/default.yml b/plugin/src/main/resources/contents/rods/default.yml index 205d31e8..3c60dec4 100644 --- a/plugin/src/main/resources/contents/rods/default.yml +++ b/plugin/src/main/resources/contents/rods/default.yml @@ -1,3 +1,9 @@ +# Vanilla fishing rod properties +FISHING_ROD: + tag: false + material: fishing_rod + +# Custom rods wooden_rod: material: fishing_rod display: