From f3d21e466d8352f689a6e0c0f4e4c58de3303007 Mon Sep 17 00:00:00 2001 From: XiaoMoMi <972454774@qq.com> Date: Wed, 3 Jul 2024 02:55:33 +0800 Subject: [PATCH] checkpoint - 21 --- .../api/BukkitCustomFishingPlugin.java | 2 +- .../api/event/FishHookLandEvent.java | 105 ---------- ...nEvent.java => FishingHookStateEvent.java} | 62 +++--- .../api/event/LavaFishingEvent.java | 97 --------- .../api/mechanic/action/ActionTrigger.java | 3 + .../mechanic/competition/CompetitionGoal.java | 9 + .../api/mechanic/config/BaitConfigParser.java | 4 +- .../mechanic/config/BlockConfigParser.java | 4 +- .../api/mechanic/config/ConfigManager.java | 5 + .../api/mechanic/config/ConfigType.java | 2 + .../mechanic/config/EnchantConfigParser.java | 6 +- .../mechanic/config/EntityConfigParser.java | 4 +- .../api/mechanic/config/HookConfigParser.java | 4 +- .../api/mechanic/config/ItemConfigParser.java | 2 + .../api/mechanic/config/RodConfigParser.java | 2 + .../api/mechanic/config/UtilConfigParser.java | 4 +- .../api/mechanic/context/ContextKeys.java | 7 +- .../mechanic/fishing/CustomFishingHook.java | 182 +++++++++++++++- .../api/mechanic/fishing/FishingGears.java | 198 +++++++++++------- .../fishing/hook/LavaFishingMechanic.java | 21 +- .../fishing/hook/VanillaMechanic.java | 13 +- .../fishing/hook/VoidFishingMechanic.java | 11 +- .../api/mechanic/item/ItemManager.java | 5 +- .../api/mechanic/item/MechanicType.java | 15 +- .../api/mechanic/loot/LootImpl.java | 2 +- .../api/mechanic/loot/LootType.java | 7 +- .../api/mechanic/misc/value/MathValue.java | 7 + .../misc/value/RangedMathValueImpl.java | 31 +++ .../customfishing/api}/util/EventUtils.java | 2 +- .../common/helper/AdventureHelper.java | 4 + .../common/locale/StandardLocales.java | 1 + .../bukkit/BukkitCustomFishingPluginImpl.java | 10 +- .../bukkit/action/BukkitActionManager.java | 70 ++++++- .../bukkit/block/BukkitBlockManager.java | 2 +- .../actionbar/ActionBarSender.java | 2 +- .../competition/bossbar/BossBarSender.java | 2 +- .../bukkit/config/BukkitConfigManager.java | 25 ++- .../bukkit/entity/BukkitEntityManager.java | 8 +- .../bukkit/event/BukkitEventManager.java | 12 +- .../bukkit/fishing/BukkitFishingManager.java | 59 ++++-- .../integration/BukkitIntegrationManager.java | 1 - .../bukkit/item/BukkitItemManager.java | 35 +++- core/src/main/resources/config.yml | 4 +- .../main/resources/contents/item/default.yml | 6 + core/src/main/resources/translations/en.yml | 1 + gradle.properties | 2 +- 46 files changed, 657 insertions(+), 403 deletions(-) delete mode 100644 api/src/main/java/net/momirealms/customfishing/api/event/FishHookLandEvent.java rename api/src/main/java/net/momirealms/customfishing/api/event/{FishingLootPreSpawnEvent.java => FishingHookStateEvent.java} (56%) delete mode 100644 api/src/main/java/net/momirealms/customfishing/api/event/LavaFishingEvent.java create mode 100644 api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/RangedMathValueImpl.java rename {core/src/main/java/net/momirealms/customfishing/bukkit => api/src/main/java/net/momirealms/customfishing/api}/util/EventUtils.java (96%) diff --git a/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java b/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java index c3d97acd..c604390e 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java +++ b/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java @@ -205,5 +205,5 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin, public abstract void enable(); - public abstract void debug(String message); + public abstract void debug(Object message); } 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 deleted file mode 100644 index dc9a1daa..00000000 --- a/api/src/main/java/net/momirealms/customfishing/api/event/FishHookLandEvent.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import net.momirealms.customfishing.api.mechanic.effect.Effect; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -/** - * This class represents an event that occurs when a fishing hook lands in either lava or water. - */ -public class FishHookLandEvent extends PlayerEvent { - - private static final HandlerList handlerList = new HandlerList(); - private final Target target; - private final FishHook fishHook; - private final Effect effect; - private final boolean isFirst; - - /** - * Constructs a new FishHookLandEvent. - * - * @param who The player who triggered the event. - * @param target The target where the fishing hook has landed (LAVA or WATER). - * @param hook The fishing hook entity. - * @param initialEffect The initial effect - */ - public FishHookLandEvent(@NotNull Player who, Target target, FishHook hook, boolean isFirst, Effect initialEffect) { - super(who); - this.target = target; - this.fishHook = hook; - this.effect = initialEffect; - this.isFirst = isFirst; - } - - /** - * Gets the target where the fishing hook has landed. - * - * @return The target, which can be either LAVA or WATER. - */ - public Target getTarget() { - return target; - } - - /** - * Gets the fish hook bukkit entity - * - * @return fish hook - */ - public FishHook getFishHook() { - return fishHook; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - /** - * Is the first try of one fishing catch - * - * @return is first try - */ - public boolean isFirst() { - return isFirst; - } - - /** - * Get the fishing effect - * It's not advised to modify this value without checking "isFirst()" since this event can be trigger multiple times in one fishing catch - * - * @return fishing effect - */ - public Effect getEffect() { - return effect; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - public enum Target { - LAVA, - WATER - } -} diff --git a/api/src/main/java/net/momirealms/customfishing/api/event/FishingLootPreSpawnEvent.java b/api/src/main/java/net/momirealms/customfishing/api/event/FishingHookStateEvent.java similarity index 56% rename from api/src/main/java/net/momirealms/customfishing/api/event/FishingLootPreSpawnEvent.java rename to api/src/main/java/net/momirealms/customfishing/api/event/FishingHookStateEvent.java index 41409832..cde4df5c 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/event/FishingLootPreSpawnEvent.java +++ b/api/src/main/java/net/momirealms/customfishing/api/event/FishingHookStateEvent.java @@ -17,52 +17,46 @@ package net.momirealms.customfishing.api.event; -import org.bukkit.Location; +import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -public class FishingLootPreSpawnEvent extends PlayerEvent implements Cancellable { +public class FishingHookStateEvent extends PlayerEvent { private static final HandlerList handlerList = new HandlerList(); - private final Location location; - private final ItemStack itemStack; - private boolean isCancelled; + private final FishHook fishHook; + private final State state; - public FishingLootPreSpawnEvent(@NotNull Player who, Location location, ItemStack itemStack) { + public FishingHookStateEvent(@NotNull Player who, FishHook hook, State state) { super(who); - this.itemStack = itemStack; - this.location = location; - this.isCancelled = false; - } - - @Override - public boolean isCancelled() { - return isCancelled; - } - - @Override - public void setCancelled(boolean cancel) { - isCancelled = cancel; - } - - public Location getLocation() { - return location; - } - - public ItemStack getItemStack() { - return itemStack; - } - - @Override - public @NotNull HandlerList getHandlers() { - return handlerList; + this.fishHook = hook; + this.state = state; } public static HandlerList getHandlerList() { return handlerList; } + + public FishHook getFishHook() { + return fishHook; + } + + public State getState() { + return state; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + + public enum State { + BITE, + ESCAPE, + LURE, + LAND + } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/event/LavaFishingEvent.java b/api/src/main/java/net/momirealms/customfishing/api/event/LavaFishingEvent.java deleted file mode 100644 index bc961c17..00000000 --- a/api/src/main/java/net/momirealms/customfishing/api/event/LavaFishingEvent.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -/** - * This class represents an event that occurs when a player fishes in lava. - */ -public class LavaFishingEvent extends PlayerEvent implements Cancellable { - - private static final HandlerList handlerList = new HandlerList(); - private final State state; - private boolean isCancelled; - private final FishHook hook; - - /** - * Constructs a new LavaFishingEvent. - * - * @param who The player who triggered the event. - * @param state The state of the fishing action (REEL_IN, CAUGHT_FISH, or BITE). - * @param hook The FishHook entity associated with the fishing action. - */ - public LavaFishingEvent(@NotNull Player who, State state, FishHook hook) { - super(who); - this.state = state; - this.isCancelled = false; - this.hook = hook; - } - - /** - * Gets the state of the fishing action. - * - * @return The fishing state, which can be REEL_IN, CAUGHT_FISH, or BITE. - */ - public State getState() { - return state; - } - - /** - * Gets the FishHook entity associated with the fishing action. - * - * @return The FishHook entity used in the fishing action. - */ - public FishHook getHook() { - return hook; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - @Override - public boolean isCancelled() { - return isCancelled; - } - - @Override - public void setCancelled(boolean cancel) { - isCancelled = cancel; - } - - /** - * An enumeration representing possible states of the fishing action (REEL_IN, CAUGHT_FISH, BITE). - */ - public enum State { - REEL_IN, - CAUGHT_FISH, - BITE - } -} 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 f98abee3..3b981bb1 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 @@ -25,8 +25,11 @@ public enum ActionTrigger { CAST, BITE, LAND, + LURE, + ESCAPE, ACTIVATE, TIMER, INTERACT, + REEL, NEW_SIZE_RECORD } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java index 9180f366..699e9286 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java @@ -47,6 +47,15 @@ public final class CompetitionGoal { }), () -> Optional.ofNullable(StandardLocales.GOAL_MAX_SIZE).orElse("max_size") ); + public static final CompetitionGoal MIN_SIZE = new CompetitionGoal( + "min_size", + ((rankingProvider, player, score) -> { + if (rankingProvider.getPlayerScore(player) > score) { + rankingProvider.setData(player, score); + } + }), + () -> Optional.ofNullable(StandardLocales.GOAL_MIN_SIZE).orElse("min_size") + ); public static final CompetitionGoal TOTAL_SIZE = new CompetitionGoal( "total_size", (RankingProvider::refreshData), diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BaitConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BaitConfigParser.java index c485f6cb..19908a7f 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BaitConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BaitConfigParser.java @@ -9,6 +9,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.common.config.node.Node; import net.momirealms.customfishing.common.item.Item; import org.bukkit.entity.Player; @@ -101,7 +102,7 @@ public class BaitConfigParser { public EffectModifier getEffectModifier() { EffectModifier.Builder builder = EffectModifier.builder() .id(id) - .type(MechanicType.ROD); + .type(MechanicType.BAIT); for (Consumer consumer : effectBuilderConsumers) { consumer.accept(builder); } @@ -119,6 +120,7 @@ public class BaitConfigParser { public Loot getLoot() { Loot.Builder builder = Loot.builder() .id(id) + .type(LootType.ITEM) .lootBaseEffect(getBaseEffect()); for (Consumer consumer : lootBuilderConsumers) { consumer.accept(builder); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BlockConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BlockConfigParser.java index 5835d911..8b1f97e1 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BlockConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/BlockConfigParser.java @@ -7,6 +7,7 @@ import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect; import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.common.config.node.Node; import java.util.ArrayList; @@ -85,6 +86,7 @@ public class BlockConfigParser { public Loot getLoot() { Loot.Builder builder = Loot.builder() .id(id) + .type(LootType.BLOCK) .lootBaseEffect(getBaseEffect()); for (Consumer consumer : lootBuilderConsumers) { consumer.accept(builder); @@ -95,7 +97,7 @@ public class BlockConfigParser { public EventCarrier getEventCarrier() { EventCarrier.Builder builder = EventCarrier.builder() .id(id) - .type(MechanicType.LOOT); + .type(MechanicType.BLOCK); for (Consumer consumer : eventBuilderConsumers) { consumer.accept(builder); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java index 489c47aa..4cef39a1 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java @@ -66,6 +66,7 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable { protected boolean enableVoidFishing; protected int voidMinTime; protected int voidMaxTime; + protected int multipleLootSpawnDelay; protected boolean restrictedSizeRange; protected List durabilityLore; protected boolean allowMultipleTotemType; @@ -160,6 +161,10 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable { return instance.voidMaxTime; } + public static int multipleLootSpawnDelay() { + return instance.multipleLootSpawnDelay; + } + public static boolean restrictedSizeRange() { return instance.restrictedSizeRange; } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java index 41306848..d27803b7 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java @@ -25,6 +25,7 @@ public class ConfigType { public static final ConfigType ENTITY = of( "entity", (id, section, functions) -> { + MechanicType.register(id, MechanicType.ENTITY); EntityConfigParser config = new EntityConfigParser(id, section, functions); BukkitCustomFishingPlugin.getInstance().getEntityManager().registerEntity(config.getEntity()); BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot()); @@ -35,6 +36,7 @@ public class ConfigType { public static final ConfigType BLOCK = of( "block", (id, section, functions) -> { + MechanicType.register(id, MechanicType.BLOCK); BlockConfigParser config = new BlockConfigParser(id, section, functions); BukkitCustomFishingPlugin.getInstance().getBlockManager().registerBlock(config.getBlock()); BukkitCustomFishingPlugin.getInstance().getLootManager().registerLoot(config.getLoot()); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EnchantConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EnchantConfigParser.java index a8ba5850..0ab2cdf8 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EnchantConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EnchantConfigParser.java @@ -4,11 +4,9 @@ import dev.dejvokep.boostedyaml.block.implementation.Section; import net.momirealms.customfishing.api.mechanic.config.function.ConfigParserFunction; import net.momirealms.customfishing.api.mechanic.config.function.EffectModifierParserFunction; import net.momirealms.customfishing.api.mechanic.config.function.EventParserFunction; -import net.momirealms.customfishing.api.mechanic.config.function.TotemParserFunction; import net.momirealms.customfishing.api.mechanic.effect.EffectModifier; import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.item.MechanicType; -import net.momirealms.customfishing.api.mechanic.totem.TotemConfig; import net.momirealms.customfishing.common.config.node.Node; import java.util.ArrayList; @@ -58,7 +56,7 @@ public class EnchantConfigParser { public EventCarrier getEventCarrier() { EventCarrier.Builder builder = EventCarrier.builder() .id(id) - .type(MechanicType.TOTEM); + .type(MechanicType.ENCHANT); for (Consumer consumer : eventBuilderConsumers) { consumer.accept(builder); } @@ -68,7 +66,7 @@ public class EnchantConfigParser { public EffectModifier getEffectModifier() { EffectModifier.Builder builder = EffectModifier.builder() .id(id) - .type(MechanicType.TOTEM); + .type(MechanicType.ENCHANT); for (Consumer consumer : effectBuilderConsumers) { consumer.accept(builder); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EntityConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EntityConfigParser.java index 2cd67230..36d74d2d 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EntityConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/EntityConfigParser.java @@ -7,6 +7,7 @@ import net.momirealms.customfishing.api.mechanic.entity.EntityConfig; import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.common.config.node.Node; import java.util.ArrayList; @@ -85,6 +86,7 @@ public class EntityConfigParser { public Loot getLoot() { Loot.Builder builder = Loot.builder() .id(id) + .type(LootType.ENTITY) .lootBaseEffect(getBaseEffect()); for (Consumer consumer : lootBuilderConsumers) { consumer.accept(builder); @@ -95,7 +97,7 @@ public class EntityConfigParser { public EventCarrier getEventCarrier() { EventCarrier.Builder builder = EventCarrier.builder() .id(id) - .type(MechanicType.LOOT); + .type(MechanicType.ENTITY); for (Consumer consumer : eventBuilderConsumers) { consumer.accept(builder); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/HookConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/HookConfigParser.java index 51355a81..a6171b07 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/HookConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/HookConfigParser.java @@ -10,6 +10,7 @@ import net.momirealms.customfishing.api.mechanic.hook.HookConfig; import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.common.config.node.Node; import net.momirealms.customfishing.common.item.Item; import org.bukkit.entity.Player; @@ -108,7 +109,7 @@ public class HookConfigParser { public EffectModifier getEffectModifier() { EffectModifier.Builder builder = EffectModifier.builder() .id(id) - .type(MechanicType.ROD); + .type(MechanicType.HOOK); for (Consumer consumer : effectBuilderConsumers) { consumer.accept(builder); } @@ -135,6 +136,7 @@ public class HookConfigParser { public Loot getLoot() { Loot.Builder builder = Loot.builder() .id(id) + .type(LootType.ITEM) .lootBaseEffect(getBaseEffect()); for (Consumer consumer : lootBuilderConsumers) { consumer.accept(builder); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ItemConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ItemConfigParser.java index f4453968..d644349e 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ItemConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ItemConfigParser.java @@ -8,6 +8,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.common.config.node.Node; import net.momirealms.customfishing.common.item.Item; import org.bukkit.entity.Player; @@ -92,6 +93,7 @@ public class ItemConfigParser { public Loot getLoot() { Loot.Builder builder = Loot.builder() .id(id) + .type(LootType.ITEM) .lootBaseEffect(getBaseEffect()); for (Consumer consumer : lootBuilderConsumers) { consumer.accept(builder); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/RodConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/RodConfigParser.java index eb3ffde5..ce979f8b 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/RodConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/RodConfigParser.java @@ -9,6 +9,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.common.config.node.Node; import net.momirealms.customfishing.common.item.Item; import org.bukkit.Material; @@ -120,6 +121,7 @@ public class RodConfigParser { public Loot getLoot() { Loot.Builder builder = Loot.builder() .id(id) + .type(LootType.ITEM) .lootBaseEffect(getBaseEffect()); for (Consumer consumer : lootBuilderConsumers) { consumer.accept(builder); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/UtilConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/UtilConfigParser.java index ce94e89e..afacdb33 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/UtilConfigParser.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/UtilConfigParser.java @@ -9,6 +9,7 @@ import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.common.config.node.Node; import net.momirealms.customfishing.common.item.Item; import org.bukkit.entity.Player; @@ -91,7 +92,7 @@ public class UtilConfigParser { public EventCarrier getEventCarrier() { EventCarrier.Builder builder = EventCarrier.builder() .id(id) - .type(MechanicType.BAIT); + .type(MechanicType.UTIL); for (Consumer consumer : eventBuilderConsumers) { consumer.accept(builder); } @@ -118,6 +119,7 @@ public class UtilConfigParser { public Loot getLoot() { Loot.Builder builder = Loot.builder() .id(id) + .type(LootType.ITEM) .lootBaseEffect(getBaseEffect()); for (Consumer consumer : lootBuilderConsumers) { consumer.accept(builder); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java index d621d12f..cf13229b 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/context/ContextKeys.java @@ -18,6 +18,7 @@ package net.momirealms.customfishing.api.mechanic.context; import net.momirealms.customfishing.api.mechanic.competition.CompetitionGoal; +import net.momirealms.customfishing.api.mechanic.loot.LootType; import org.bukkit.Location; import java.util.Objects; @@ -30,6 +31,8 @@ public class ContextKeys { public static final ContextKeys Z = of("z", Integer.class); public static final ContextKeys WORLD = of("world", String.class); public static final ContextKeys ID = of("id", String.class); + public static final ContextKeys LOOT = of("loot", LootType.class); + public static final ContextKeys NICK = of("nick", String.class); public static final ContextKeys OPEN_WATER = of("open_water", Boolean.class); public static final ContextKeys TYPE = of("type", String.class); public static final ContextKeys SIZE = of("SIZE", Float.class); @@ -48,7 +51,9 @@ public class ContextKeys { public static final ContextKeys SECOND = of("second", String.class); public static final ContextKeys SECONDS = of("seconds", Integer.class); public static final ContextKeys PLAYER = of("player", String.class); - public static final ContextKeys SCORE = of("score", String.class); + public static final ContextKeys SCORE_FORMATTED = of("score_formatted", String.class); + public static final ContextKeys SCORE = of("score", Double.class); + public static final ContextKeys CUSTOM_SCORE = of("custom_score", Double.class); public static final ContextKeys RANK = of("rank", String.class); public static final ContextKeys HOOK_LOCATION = of("hook_location", Location.class); public static final ContextKeys HOOK_X = of("hook_x", Integer.class); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/CustomFishingHook.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/CustomFishingHook.java index a1608e6d..8384df19 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/CustomFishingHook.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/CustomFishingHook.java @@ -1,34 +1,49 @@ package net.momirealms.customfishing.api.mechanic.fishing; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.competition.CompetitionGoal; +import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.api.mechanic.context.ContextKeys; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.effect.EffectModifier; import net.momirealms.customfishing.api.mechanic.fishing.hook.HookMechanic; import net.momirealms.customfishing.api.mechanic.fishing.hook.LavaFishingMechanic; import net.momirealms.customfishing.api.mechanic.fishing.hook.VanillaMechanic; import net.momirealms.customfishing.api.mechanic.fishing.hook.VoidFishingMechanic; +import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; +import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; +import net.momirealms.customfishing.common.helper.AdventureHelper; import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask; import net.momirealms.customfishing.common.util.TriConsumer; import net.momirealms.customfishing.common.util.TriFunction; +import org.bukkit.Statistic; import org.bukkit.entity.FishHook; +import org.bukkit.entity.Item; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.Optional; public class CustomFishingHook { + private final BukkitCustomFishingPlugin plugin; private final FishHook hook; private final SchedulerTask task; private final FishingGears gears; + private final Context context; + private Effect tempFinalEffect; private HookMechanic hookMechanic; private Loot nextLoot; - private Context context; private static TriFunction, Effect, List> mechanicProviders = defaultMechanicProviders(); @@ -46,8 +61,10 @@ public class CustomFishingHook { CustomFishingHook.mechanicProviders = mechanicProviders; } - public CustomFishingHook(FishHook hook, FishingGears gears, Context context) { + public CustomFishingHook(BukkitCustomFishingPlugin plugin, FishHook hook, FishingGears gears, Context context) { this.gears = gears; + this.gears.trigger(ActionTrigger.CAST, context); + this.plugin = plugin; this.hook = hook; // once it becomes a custom hook, the wait time is controlled by plugin this.context = context; @@ -59,10 +76,10 @@ public class CustomFishingHook { } } List enabledMechanics = mechanicProviders.apply(hook, context, effect); - this.task = BukkitCustomFishingPlugin.getInstance().getScheduler().sync().runRepeating(() -> { + this.task = plugin.getScheduler().sync().runRepeating(() -> { // destroy if hook is invalid if (!hook.isValid()) { - BukkitCustomFishingPlugin.getInstance().getFishingManager().destroy(hook.getOwnerUniqueId()); + plugin.getFishingManager().destroy(hook.getOwnerUniqueId()); return; } if (this.hookMechanic != null) { @@ -85,14 +102,25 @@ public class CustomFishingHook { consumer.accept(tempEffect, context, 1); } } + + context.arg(ContextKeys.HOOK_LOCATION, hook.getLocation()); + context.arg(ContextKeys.HOOK_X, hook.getLocation().getBlockX()); + context.arg(ContextKeys.HOOK_Y, hook.getLocation().getBlockY()); + context.arg(ContextKeys.HOOK_Z, hook.getLocation().getBlockZ()); + // get the next loot - Loot loot = BukkitCustomFishingPlugin.getInstance().getLootManager().getNextLoot(effect, context); + Loot loot = plugin.getLootManager().getNextLoot(effect, context); if (loot == null) { - BukkitCustomFishingPlugin.getInstance().debug("No loot available for player " + context.getHolder().getName()); + plugin.debug("No loot available for player " + context.getHolder().getName()); return; } this.nextLoot = loot; - BukkitCustomFishingPlugin.getInstance().debug("Next loot: " + loot.id()); + + context.arg(ContextKeys.ID, loot.id()); + context.arg(ContextKeys.NICK, loot.nick()); + context.arg(ContextKeys.LOOT, loot.type()); + + plugin.debug("Next loot: " + loot.id()); // get its basic properties Effect baseEffect = loot.baseEffect().toEffect(context); tempEffect.combine(baseEffect); @@ -104,6 +132,8 @@ public class CustomFishingHook { } // start the mechanic mechanic.start(tempEffect); + + this.tempFinalEffect = tempEffect; } } } @@ -134,15 +164,147 @@ public class CustomFishingHook { public void onReelIn() { if (hookMechanic != null) { if (!hookMechanic.isHooked()) { + gears.trigger(ActionTrigger.REEL, context); destroy(); - System.out.println("fail"); } else { - System.out.println("succeed"); + if (nextLoot.disableGame()) { + handleSuccessfulFishing(); + destroy(); + } else { + handleSuccessfulFishing(); + destroy(); + } } + } else { + gears.trigger(ActionTrigger.REEL, context); + destroy(); } } public void onBite() { - gears.bite(); + gears.trigger(ActionTrigger.BITE, context); + } + + public void onLand() { + gears.trigger(ActionTrigger.LAND, context); + } + + public void onEscape() { + gears.trigger(ActionTrigger.ESCAPE, context); + } + + public void onLure() { + gears.trigger(ActionTrigger.LURE, context); + } + + private void handleFailedFishing() { + + // update the hook location + context.arg(ContextKeys.HOOK_LOCATION, hook.getLocation()); + context.arg(ContextKeys.HOOK_X, hook.getLocation().getBlockX()); + context.arg(ContextKeys.HOOK_Y, hook.getLocation().getBlockY()); + context.arg(ContextKeys.HOOK_Z, hook.getLocation().getBlockZ()); + + gears.trigger(ActionTrigger.FAILURE, context); + + String id = context.arg(ContextKeys.ID); + BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, MechanicType.getTypeByID(id), ActionTrigger.FAILURE); + } + + private void handleSuccessfulFishing() { + + // update the hook location + context.arg(ContextKeys.HOOK_LOCATION, hook.getLocation()); + context.arg(ContextKeys.HOOK_X, hook.getLocation().getBlockX()); + context.arg(ContextKeys.HOOK_Y, hook.getLocation().getBlockY()); + context.arg(ContextKeys.HOOK_Z, hook.getLocation().getBlockZ()); + + LootType lootType = context.arg(ContextKeys.LOOT); + Objects.requireNonNull(lootType, "Missing loot type"); + Objects.requireNonNull(tempFinalEffect, "Missing final effects"); + switch (lootType) { + case ITEM -> { + int amount = (int) tempFinalEffect.multipleLootChance(); + amount += Math.random() < (tempFinalEffect.multipleLootChance() - amount) ? 2 : 1; + for (int i = 0; i < amount; i++) { + plugin.getScheduler().sync().runLater(() -> { + Item item = plugin.getItemManager().dropItemLoot(context, gears.getItem(FishingGears.GearType.ROD).stream().findAny().orElseThrow().right(), hook); + if (item != null) { + if (Objects.equals(context.arg(ContextKeys.NICK), "UNDEFINED")) { + ItemStack stack = item.getItemStack(); + Optional displayName = plugin.getItemManager().wrap(stack).displayName(); + if (displayName.isPresent()) { + context.arg(ContextKeys.NICK, AdventureHelper.jsonToMiniMessage(displayName.get())); + } else { + context.arg(ContextKeys.NICK, ""); + } + } + } + handleSuccess(); + }, (long) ConfigManager.multipleLootSpawnDelay() * i, hook.getLocation()); + } + } + case BLOCK -> { + BukkitCustomFishingPlugin.getInstance().getBlockManager().summonBlockLoot(context); + handleSuccess(); + } + case ENTITY -> { + BukkitCustomFishingPlugin.getInstance().getEntityManager().summonEntityLoot(context); + handleSuccess(); + } + } + + gears.trigger(ActionTrigger.SUCCESS, context); + } + + private void handleSuccess() { + FishingCompetition competition = BukkitCustomFishingPlugin.getInstance().getCompetitionManager().getOnGoingCompetition(); + if (competition != null && RequirementManager.isSatisfied(context, competition.getConfig().joinRequirements())) { + Double customScore = context.arg(ContextKeys.CUSTOM_SCORE); + if (customScore != null) { + competition.refreshData(context.getHolder(), customScore); + context.arg(ContextKeys.SCORE_FORMATTED, String.format("%.2f", customScore)); + context.arg(ContextKeys.SCORE, customScore); + } else { + double score = 0; + if (competition.getGoal() == CompetitionGoal.CATCH_AMOUNT) { + score = 1; + competition.refreshData(context.getHolder(), score); + } else if (competition.getGoal() == CompetitionGoal.MAX_SIZE || competition.getGoal() == CompetitionGoal.MIN_SIZE) { + Float size = context.arg(ContextKeys.SIZE); + if (size != null) { + competition.refreshData(context.getHolder(), size); + } + } else if (competition.getGoal() == CompetitionGoal.TOTAL_SCORE) { + score = nextLoot.score().evaluate(context); + if (score != 0) { + competition.refreshData(context.getHolder(), score); + } + } + context.arg(ContextKeys.SCORE_FORMATTED, String.format("%.2f", score)); + context.arg(ContextKeys.SCORE, score); + } + } else { + context.arg(ContextKeys.SCORE_FORMATTED, "0.0"); + context.arg(ContextKeys.SCORE, 0d); + } + + String id = context.arg(ContextKeys.ID); + Player player = context.getHolder(); + MechanicType type = MechanicType.getTypeByID(id); + BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, type, ActionTrigger.SUCCESS); + player.setStatistic(Statistic.FISH_CAUGHT, player.getStatistic(Statistic.FISH_CAUGHT) + 1); + if (!nextLoot.disableStats()) { + BukkitCustomFishingPlugin.getInstance().getStorageManager().getOnlineUser(player.getUniqueId()).ifPresent( + userData -> { + userData.statistics().addAmount(id, 1); + Optional.ofNullable(context.arg(ContextKeys.SIZE)).ifPresent(size -> { + if (userData.statistics().updateSize(id, size)) { + BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, id, type, ActionTrigger.NEW_SIZE_RECORD); + } + }); + } + ); + } } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java index 6226a179..43cb902b 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java @@ -1,6 +1,7 @@ package net.momirealms.customfishing.api.mechanic.fishing; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.context.ContextKeys; @@ -9,7 +10,10 @@ import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; import net.momirealms.customfishing.api.storage.user.UserData; import net.momirealms.customfishing.common.util.Pair; +import net.momirealms.customfishing.common.util.TriConsumer; +import org.bukkit.GameMode; import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -18,12 +22,24 @@ import org.jetbrains.annotations.NotNull; import java.util.*; import java.util.function.BiConsumer; -import java.util.function.Consumer; public class FishingGears { + private static final Map, ItemStack>> triggers = new HashMap<>(); + + static { + triggers.put(ActionTrigger.CAST, ((type, context, itemStack) -> type.castFunction.accept(context, itemStack))); + triggers.put(ActionTrigger.REEL, ((type, context, itemStack) -> type.reelFunction.accept(context, itemStack))); + triggers.put(ActionTrigger.LAND, ((type, context, itemStack) -> type.landFunction.accept(context, itemStack))); + triggers.put(ActionTrigger.ESCAPE, ((type, context, itemStack) -> type.escapeFunction.accept(context, itemStack))); + triggers.put(ActionTrigger.LURE, ((type, context, itemStack) -> type.lureFunction.accept(context, itemStack))); + triggers.put(ActionTrigger.SUCCESS, ((type, context, itemStack) -> type.successFunction.accept(context, itemStack))); + triggers.put(ActionTrigger.FAILURE, ((type, context, itemStack) -> type.failureFunction.accept(context, itemStack))); + triggers.put(ActionTrigger.BITE, ((type, context, itemStack) -> type.biteFunction.accept(context, itemStack))); + } + private static BiConsumer, FishingGears> fishingGearsConsumers = defaultFishingGearsConsumers(); - private final HashMap> gears = new HashMap<>(); + private final HashMap>> gears = new HashMap<>(); private final ArrayList modifiers = new ArrayList<>(); private boolean canFish = true; @@ -39,42 +55,12 @@ public class FishingGears { return canFish; } - public void cast() { - for (Map.Entry> entry : gears.entrySet()) { - for (ItemStack itemStack : entry.getValue()) { - entry.getKey().castFunction.accept(itemStack); - } - } - } - - public void reel() { - for (Map.Entry> entry : gears.entrySet()) { - for (ItemStack itemStack : entry.getValue()) { - entry.getKey().reelFunction.accept(itemStack); - } - } - } - - public void succeed() { - for (Map.Entry> entry : gears.entrySet()) { - for (ItemStack itemStack : entry.getValue()) { - entry.getKey().successFunction.accept(itemStack); - } - } - } - - public void fail() { - for (Map.Entry> entry : gears.entrySet()) { - for (ItemStack itemStack : entry.getValue()) { - entry.getKey().failureFunction.accept(itemStack); - } - } - } - - public void bite() { - for (Map.Entry> entry : gears.entrySet()) { - for (ItemStack itemStack : entry.getValue()) { - entry.getKey().biteFunction.accept(itemStack); + public void trigger(ActionTrigger trigger, Context context) { + for (Map.Entry>> entry : gears.entrySet()) { + for (Pair itemPair : entry.getValue()) { + BukkitCustomFishingPlugin.getInstance().debug(entry.getKey() + " | " + itemPair.left() + " | " + trigger); + triggers.get(trigger).accept(entry.getKey(), context, itemPair.right()); + BukkitCustomFishingPlugin.getInstance().getEventManager().trigger(context, itemPair.left(), entry.getKey().getType(), trigger); } } } @@ -85,7 +71,7 @@ public class FishingGears { } @NotNull - public Collection getItem(GearType type) { + public Collection> getItem(GearType type) { return gears.getOrDefault(type, List.of()); } @@ -98,7 +84,7 @@ public class FishingGears { // set rod boolean rodOnMainHand = mainHandItem.getType() == Material.FISHING_ROD; String rodID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(rodOnMainHand ? mainHandItem : offHandItem); - fishingGears.gears.put(GearType.ROD, List.of(rodOnMainHand ? mainHandItem : offHandItem)); + fishingGears.gears.put(GearType.ROD, List.of(Pair.of(rodID, rodOnMainHand ? mainHandItem : offHandItem))); context.arg(ContextKeys.ROD, rodID); BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(rodID, MechanicType.ROD).ifPresent(fishingGears.modifiers::add); @@ -114,7 +100,7 @@ public class FishingGears { String anotherItemID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(rodOnMainHand ? offHandItem : mainHandItem); MechanicType type = MechanicType.getTypeByID(anotherItemID); if (type == MechanicType.BAIT) { - fishingGears.gears.put(GearType.BAIT, List.of(rodOnMainHand ? offHandItem : mainHandItem)); + fishingGears.gears.put(GearType.BAIT, List.of(Pair.of(anotherItemID, rodOnMainHand ? offHandItem : mainHandItem))); context.arg(ContextKeys.BAIT, anotherItemID); BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(anotherItemID, MechanicType.BAIT).ifPresent(fishingGears.modifiers::add); hasBait = true; @@ -133,7 +119,7 @@ public class FishingGears { String bagItemID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(itemInBag); MechanicType bagItemType = MechanicType.getTypeByID(bagItemID); if (!hasBait && bagItemType == MechanicType.BAIT) { - fishingGears.gears.put(GearType.BAIT, List.of(itemInBag)); + fishingGears.gears.put(GearType.BAIT, List.of(Pair.of(bagItemID, itemInBag))); context.arg(ContextKeys.BAIT, bagItemID); BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(bagItemID, MechanicType.BAIT).ifPresent(fishingGears.modifiers::add); hasBait = true; @@ -143,9 +129,9 @@ public class FishingGears { } } if (!uniqueUtils.isEmpty()) { - ArrayList utils = new ArrayList<>(); + ArrayList> utils = new ArrayList<>(); for (Map.Entry entry : uniqueUtils.entrySet()) { - utils.add(entry.getValue()); + utils.add(Pair.of(entry.getKey(), entry.getValue())); BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(entry.getKey(), MechanicType.UTIL).ifPresent(fishingGears.modifiers::add); } fishingGears.gears.put(GearType.UTIL, utils); @@ -178,70 +164,118 @@ public class FishingGears { public static class GearType { - public static final GearType ROD = new GearType("rod", - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> BukkitCustomFishingPlugin.getInstance().getItemManager().decreaseDurability(itemStack, 1, false)), - (itemStack -> {})); + public static final GearType ROD = new GearType(MechanicType.ROD, + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> { + if (context.getHolder().getGameMode() != GameMode.CREATIVE) + BukkitCustomFishingPlugin.getInstance().getItemManager().decreaseDurability(itemStack, 1, false); + }), + ((context, itemStack) -> { + if (context.getHolder().getGameMode() != GameMode.CREATIVE) + BukkitCustomFishingPlugin.getInstance().getItemManager().decreaseDurability(itemStack, 1, false); + }), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}) + ); - public static final GearType BAIT = new GearType("bait", - (itemStack -> itemStack.setAmount(itemStack.getAmount() - 1)), - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {})); + public static final GearType BAIT = new GearType(MechanicType.BAIT, + ((context, itemStack) -> { + if (context.getHolder().getGameMode() != GameMode.CREATIVE) + itemStack.setAmount(itemStack.getAmount() - 1); + }), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}) + ); - public static final GearType HOOK = new GearType("hook", - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {})); + public static final GearType HOOK = new GearType(MechanicType.HOOK, + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}) + ); - public static final GearType UTIL = new GearType("util", - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {}), - (itemStack -> {})); + public static final GearType UTIL = new GearType(MechanicType.UTIL, + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}), + ((context, itemStack) -> {}) + ); - private final String type; - private Consumer castFunction; - private Consumer reelFunction; - private Consumer biteFunction; - private Consumer successFunction; - private Consumer failureFunction; + private final MechanicType type; + private BiConsumer, ItemStack> castFunction; + private BiConsumer, ItemStack> reelFunction; + private BiConsumer, ItemStack> biteFunction; + private BiConsumer, ItemStack> successFunction; + private BiConsumer, ItemStack> failureFunction; + private BiConsumer, ItemStack> lureFunction; + private BiConsumer, ItemStack> escapeFunction; + private BiConsumer, ItemStack> landFunction; - public GearType(String type, Consumer castFunction, Consumer reelFunction, Consumer biteFunction, Consumer successFunction, Consumer failureFunction) { + public GearType(MechanicType type, + BiConsumer, ItemStack> castFunction, BiConsumer, ItemStack> reelFunction, + BiConsumer, ItemStack> biteFunction, BiConsumer, ItemStack> successFunction, + BiConsumer, ItemStack> failureFunction, BiConsumer, ItemStack> lureFunction, + BiConsumer, ItemStack> escapeFunction, BiConsumer, ItemStack> landFunction + ) { this.type = type; this.castFunction = castFunction; this.reelFunction = reelFunction; this.biteFunction = biteFunction; this.successFunction = successFunction; this.failureFunction = failureFunction; + this.landFunction = landFunction; + this.lureFunction = lureFunction; + this.escapeFunction = escapeFunction; } - public void castFunction(Consumer castFunction) { + public void castFunction(BiConsumer, ItemStack> castFunction) { this.castFunction = castFunction; } - public void reelFunction(Consumer reelFunction) { + public void reelFunction(BiConsumer, ItemStack> reelFunction) { this.reelFunction = reelFunction; } - public void biteFunction(Consumer biteFunction) { + public void biteFunction(BiConsumer, ItemStack> biteFunction) { this.biteFunction = biteFunction; } - public void successFunction(Consumer successFunction) { + public void successFunction(BiConsumer, ItemStack> successFunction) { this.successFunction = successFunction; } - public void failureFunction(Consumer failureFunction) { + public void failureFunction(BiConsumer, ItemStack> failureFunction) { this.failureFunction = failureFunction; } + public void escapeFunction(BiConsumer, ItemStack> escapeFunction) { + this.escapeFunction = escapeFunction; + } + + public void lureFunction(BiConsumer, ItemStack> lureFunction) { + this.lureFunction = lureFunction; + } + + public void landFunction(BiConsumer, ItemStack> landFunction) { + this.landFunction = landFunction; + } + @Override public boolean equals(Object object) { if (this == object) return true; @@ -257,6 +291,10 @@ public class FishingGears { @Override public String toString() { + return type.toString(); + } + + public MechanicType getType() { return type; } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/LavaFishingMechanic.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/LavaFishingMechanic.java index 6282fa75..ecdf0f34 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/LavaFishingMechanic.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/LavaFishingMechanic.java @@ -2,11 +2,13 @@ package net.momirealms.customfishing.api.mechanic.fishing.hook; import io.papermc.paper.block.fluid.FluidData; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.event.FishingHookStateEvent; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.context.ContextKeys; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.effect.EffectProperties; +import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask; import net.momirealms.customfishing.common.util.RandomUtils; import org.bukkit.*; @@ -34,6 +36,7 @@ public class LavaFishingMechanic implements HookMechanic { private float fishAngle; private int currentState; private int jumpTimer; + private boolean firstTime = true; public LavaFishingMechanic(FishHook hook, Effect gearsEffect, Context context) { this.hook = hook; @@ -46,6 +49,9 @@ public class LavaFishingMechanic implements HookMechanic { if (!(boolean) gearsEffect.properties().getOrDefault(EffectProperties.LAVA_FISHING, false)) { return false; } + if (hook.isInLava()) { + return true; + } float lavaHeight = 0F; FluidData fluidData = this.hook.getWorld().getFluidData(this.hook.getLocation()); if (fluidData.getFluidType() == Fluid.LAVA || fluidData.getFluidType() == Fluid.FLOWING_LAVA) { @@ -56,6 +62,9 @@ public class LavaFishingMechanic implements HookMechanic { @Override public boolean shouldStop() { + if (hook.isInLava()) { + return false; + } return hook.isOnGround() || (hook.getLocation().getBlock().getType() != Material.LAVA && hook.getLocation().getBlock().getRelative(BlockFace.DOWN).getType() != Material.LAVA); } @@ -66,6 +75,7 @@ public class LavaFishingMechanic implements HookMechanic { @Override public void start(Effect finalEffect) { + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LAND)); this.setWaitTime(finalEffect); this.task = BukkitCustomFishingPlugin.getInstance().getScheduler().sync().runRepeating(() -> { float lavaHeight = 0F; @@ -79,7 +89,6 @@ public class LavaFishingMechanic implements HookMechanic { this.jumpTimer++; if (this.jumpTimer >= 4) { this.jumpTimer = 0; - Vector previousVector = this.hook.getVelocity(); this.hook.setVelocity(new Vector(0,0.24,0)); } } @@ -91,7 +100,7 @@ public class LavaFishingMechanic implements HookMechanic { this.currentState = 0; } } else { - if (this.hook.getY() % 1 <= lavaHeight) { + if (this.hook.getY() % 1 <= lavaHeight || this.hook.isInLava()) { Vector previousVector = this.hook.getVelocity(); this.hook.setVelocity(new Vector(previousVector.getX() * 0.6, Math.min(0.1, Math.max(-0.1, previousVector.getY() + 0.1)), previousVector.getZ() * 0.6)); this.currentState = 1; @@ -102,6 +111,10 @@ public class LavaFishingMechanic implements HookMechanic { this.tempEntity = this.hook.getWorld().spawn(this.hook.getLocation().clone().subtract(0,1,0), ArmorStand.class); this.setTempEntityProperties(this.tempEntity); this.hook.setHookedEntity(this.tempEntity); + if (!firstTime) { + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.ESCAPE)); + } + firstTime = false; } } float f; @@ -132,6 +145,7 @@ public class LavaFishingMechanic implements HookMechanic { this.nibble = RandomUtils.generateRandomInt(20, 40); this.hooked = true; hook.getWorld().playSound(hook.getLocation(), Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 0.25F, 1.0F + (RandomUtils.generateRandomFloat(0,1)-RandomUtils.generateRandomFloat(0,1)) * 0.4F); + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.BITE)); if (this.tempEntity != null && this.tempEntity.isValid()) { this.tempEntity.remove(); } @@ -141,6 +155,7 @@ public class LavaFishingMechanic implements HookMechanic { if (this.timeUntilLured <= 0) { this.fishAngle = RandomUtils.generateRandomFloat(0F, 360F); this.timeUntilHooked = RandomUtils.generateRandomInt(20, 80); + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LURE)); } } else { setWaitTime(finalEffect); @@ -166,7 +181,7 @@ public class LavaFishingMechanic implements HookMechanic { private void setWaitTime(Effect effect) { int before = ThreadLocalRandom.current().nextInt(ConfigManager.lavaMaxTime() - ConfigManager.lavaMinTime() + 1) + ConfigManager.lavaMinTime(); - int after = Math.max(1, (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder())); + int after = Math.max(ConfigManager.lavaMinTime(), (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder())); BukkitCustomFishingPlugin.getInstance().debug("Wait time: " + before + " -> " + after + " ticks"); this.timeUntilLured = after; } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VanillaMechanic.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VanillaMechanic.java index 304ecdc8..4b5e3baa 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VanillaMechanic.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VanillaMechanic.java @@ -1,11 +1,13 @@ package net.momirealms.customfishing.api.mechanic.fishing.hook; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.event.FishingHookStateEvent; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.context.ContextKeys; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.effect.EffectProperties; +import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask; import net.momirealms.sparrow.heart.SparrowHeart; import org.bukkit.entity.FishHook; @@ -42,6 +44,7 @@ public class VanillaMechanic implements HookMechanic { @Override public void start(Effect finalEffect) { + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LAND)); setWaitTime(hook, finalEffect); this.task = BukkitCustomFishingPlugin.getInstance().getScheduler().sync().runRepeating(() -> { if (isHooked) { @@ -66,7 +69,7 @@ public class VanillaMechanic implements HookMechanic { hook.setWaitTime(after); } else { int before = ThreadLocalRandom.current().nextInt(ConfigManager.waterMaxTime() - ConfigManager.waterMinTime() + 1) + ConfigManager.waterMinTime(); - int after = Math.max(1, (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder())); + int after = Math.max(ConfigManager.waterMinTime(), (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder())); hook.setWaitTime(after); BukkitCustomFishingPlugin.getInstance().debug("Wait time: " + before + " -> " + after + " ticks"); } @@ -82,4 +85,12 @@ public class VanillaMechanic implements HookMechanic { public void destroy() { if (this.task != null) this.task.cancel(); } + + public void onBite() { + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.BITE)); + } + + public void onFailedAttempt() { + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.ESCAPE)); + } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VoidFishingMechanic.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VoidFishingMechanic.java index 328fcd92..20a0488e 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VoidFishingMechanic.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/hook/VoidFishingMechanic.java @@ -1,11 +1,13 @@ package net.momirealms.customfishing.api.mechanic.fishing.hook; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.event.FishingHookStateEvent; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.context.ContextKeys; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.effect.EffectProperties; +import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask; import net.momirealms.customfishing.common.util.RandomUtils; import org.bukkit.NamespacedKey; @@ -59,6 +61,7 @@ public class VoidFishingMechanic implements HookMechanic { @Override public void start(Effect finalEffect) { + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LAND)); this.setWaitTime(finalEffect); this.tempEntity = hook.getWorld().spawn(hook.getLocation().clone().subtract(0,1,0), ArmorStand.class); this.setTempEntityProperties(this.tempEntity); @@ -69,7 +72,6 @@ public class VoidFishingMechanic implements HookMechanic { if (timer >= 16) timer = 0; hook.getWorld().spawnParticle(Particle.END_ROD, hook.getX() + 0.5 * Math.cos(timer * 22.5D * 0.017453292F), hook.getY() - 0.15, hook.getZ() + 0.5 * Math.sin(timer * 22.5D * 0.017453292F), 0,0,0,0); } - if (this.nibble > 0) { --this.nibble; if (this.nibble % 4 == 0) { @@ -83,6 +85,7 @@ public class VoidFishingMechanic implements HookMechanic { this.timeUntilLured = 0; this.timeUntilHooked = 0; this.hooked = false; + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.ESCAPE)); } } else { float f; @@ -113,6 +116,7 @@ public class VoidFishingMechanic implements HookMechanic { this.nibble = RandomUtils.generateRandomInt(20, 40); this.hooked = true; hook.getWorld().playSound(hook.getLocation(), Sound.ITEM_TRIDENT_THUNDER, 0.25F, 1.0F + (RandomUtils.generateRandomFloat(0,1)-RandomUtils.generateRandomFloat(0,1)) * 0.4F); + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.BITE)); } } else if (timeUntilLured > 0) { timeUntilLured--; @@ -130,11 +134,12 @@ public class VoidFishingMechanic implements HookMechanic { d0 = hook.getX() + Math.sin(f1) * f2 * 0.1D; d1 = hook.getY(); d2 = hook.getZ() + Math.cos(f1) * f2 * 0.1D; - hook.getWorld().spawnParticle(Particle.DRAGON_BREATH, d0, d1, d2, 2 + RandomUtils.generateRandomInt(0,2), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D); + hook.getWorld().spawnParticle(Particle.DRAGON_BREATH, d0, d1, d2, 2 + RandomUtils.generateRandomInt(0,1), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D); } if (this.timeUntilLured <= 0) { this.fishAngle = RandomUtils.generateRandomFloat(0F, 360F); this.timeUntilHooked = RandomUtils.generateRandomInt(20, 80); + EventUtils.fireAndForget(new FishingHookStateEvent(context.getHolder(), hook, FishingHookStateEvent.State.LURE)); } } else { setWaitTime(finalEffect); @@ -160,7 +165,7 @@ public class VoidFishingMechanic implements HookMechanic { private void setWaitTime(Effect effect) { int before = ThreadLocalRandom.current().nextInt(ConfigManager.voidMaxTime() - ConfigManager.voidMinTime() + 1) + ConfigManager.voidMinTime(); - int after = Math.max(1, (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder())); + int after = Math.max(ConfigManager.voidMinTime(), (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder())); BukkitCustomFishingPlugin.getInstance().debug("Wait time: " + before + " -> " + after + " ticks"); this.timeUntilLured = after; } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemManager.java index a26303c6..45fa79e6 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemManager.java @@ -23,6 +23,7 @@ import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.common.item.ItemFactory; import net.momirealms.customfishing.common.plugin.CustomFishingPlugin; import net.momirealms.customfishing.common.plugin.feature.Reloadable; +import org.bukkit.entity.FishHook; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -56,7 +57,7 @@ public interface ItemManager extends Reloadable { MechanicType getItemType(@NotNull String id); @Nullable - Item dropItemLoot(@NotNull Context context); + Item dropItemLoot(@NotNull Context context, ItemStack rod, FishHook hook); void decreaseDurability(ItemStack itemStack, int amount, boolean incorrectUsage); @@ -65,4 +66,6 @@ public interface ItemManager extends Reloadable { ItemProvider[] getItemProviders(); Collection getItemIDs(); + + net.momirealms.customfishing.common.item.Item wrap(ItemStack itemStack); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/MechanicType.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/MechanicType.java index 90c3d336..415ca26f 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/MechanicType.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/MechanicType.java @@ -1,5 +1,6 @@ package net.momirealms.customfishing.api.mechanic.item; +import net.kyori.adventure.util.Index; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -17,6 +18,8 @@ public class MechanicType { public static final MechanicType BAIT = of("bait"); public static final MechanicType HOOK = of("hook"); public static final MechanicType TOTEM = of("totem"); + public static final MechanicType ENTITY = of("entity"); + public static final MechanicType BLOCK = of("block"); public static final MechanicType ENCHANT = of("enchant"); private final String type; @@ -29,10 +32,20 @@ public class MechanicType { return type; } - public static MechanicType of(String type) { + private static MechanicType of(String type) { return new MechanicType(type); } + public static MechanicType[] values() { + return new MechanicType[]{LOOT, ROD, UTIL, BAIT, HOOK, TOTEM, ENCHANT, ENTITY, BLOCK}; + } + + private static final Index INDEX = Index.create(MechanicType::getType, values()); + + public static Index index() { + return INDEX; + } + @ApiStatus.Internal public static void register(String id, MechanicType type) { MechanicType previous = types.put(id, type); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootImpl.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootImpl.java index a758065f..4e0491dc 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootImpl.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootImpl.java @@ -102,7 +102,7 @@ public class LootImpl implements Loot { private boolean disableStatistics = DEFAULT_DISABLE_STATS; private boolean showInFinder = DEFAULT_SHOW_IN_FINDER; private String id = null; - private String nick = null; + private String nick = "UNDEFINED"; private StatisticsKeys statisticsKeys = null; private MathValue score = DEFAULT_SCORE; private String[] groups = new String[0]; diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootType.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootType.java index 2a12c643..9d0a967b 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootType.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootType.java @@ -21,5 +21,10 @@ public enum LootType { ITEM, ENTITY, - BLOCK + BLOCK; + + @Override + public String toString() { + return name(); + } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/MathValue.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/MathValue.java index 58687f4a..4e81c549 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/MathValue.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/MathValue.java @@ -58,6 +58,10 @@ public interface MathValue { return new PlainMathValueImpl<>(value); } + static MathValue ranged(String value) { + return new RangedMathValueImpl<>(value); + } + /** * Automatically creates a MathValue based on the given object. * If the object is a String, it is treated as a mathematical expression. @@ -70,6 +74,9 @@ public interface MathValue { */ static MathValue auto(Object o) { if (o instanceof String s) { + if (s.contains("~")) { + return ranged(s); + } try { return plain(Double.parseDouble(s)); } catch (NumberFormatException e) { diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/RangedMathValueImpl.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/RangedMathValueImpl.java new file mode 100644 index 00000000..1be03baa --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/misc/value/RangedMathValueImpl.java @@ -0,0 +1,31 @@ +package net.momirealms.customfishing.api.mechanic.misc.value; + +import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.common.util.RandomUtils; + +public class RangedMathValueImpl implements MathValue { + + private final double min; + private final double max; + + public RangedMathValueImpl(String value) { + String[] split = value.split("~"); + if (split.length != 2) { + throw new IllegalArgumentException("Correct ranged format `a~b`"); + } + double min = Double.parseDouble(split[0]); + double max = Double.parseDouble(split[1]); + if (min > max) { + double temp = max; + max = min; + min = temp; + } + this.min = min; + this.max = max; + } + + @Override + public double evaluate(Context context) { + return RandomUtils.generateRandomDouble(min, max); + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/util/EventUtils.java b/api/src/main/java/net/momirealms/customfishing/api/util/EventUtils.java similarity index 96% rename from core/src/main/java/net/momirealms/customfishing/bukkit/util/EventUtils.java rename to api/src/main/java/net/momirealms/customfishing/api/util/EventUtils.java index 26f0bb74..33a4d4ea 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/util/EventUtils.java +++ b/api/src/main/java/net/momirealms/customfishing/api/util/EventUtils.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.util; +package net.momirealms.customfishing.api.util; import org.bukkit.Bukkit; import org.bukkit.event.Cancellable; diff --git a/common/src/main/java/net/momirealms/customfishing/common/helper/AdventureHelper.java b/common/src/main/java/net/momirealms/customfishing/common/helper/AdventureHelper.java index c04d9bcb..c5d9ad2b 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/helper/AdventureHelper.java +++ b/common/src/main/java/net/momirealms/customfishing/common/helper/AdventureHelper.java @@ -76,6 +76,10 @@ public class AdventureHelper { return "" + text + ""; } + public static String jsonToMiniMessage(String json) { + return getInstance().miniMessageStrict.serialize(getInstance().gsonComponentSerializer.deserialize(json)); + } + public static String legacyToMiniMessage(String legacy) { StringBuilder stringBuilder = new StringBuilder(); char[] chars = legacy.toCharArray(); diff --git a/common/src/main/java/net/momirealms/customfishing/common/locale/StandardLocales.java b/common/src/main/java/net/momirealms/customfishing/common/locale/StandardLocales.java index c88475a1..54e61596 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/locale/StandardLocales.java +++ b/common/src/main/java/net/momirealms/customfishing/common/locale/StandardLocales.java @@ -10,6 +10,7 @@ public class StandardLocales { public static String GOAL_CATCH_AMOUNT; public static String GOAL_TOTAL_SCORE; public static String GOAL_MAX_SIZE; + public static String GOAL_MIN_SIZE; public static String FORMAT_SECOND = "s"; public static String FORMAT_MINUTE = "m"; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java index 56a40083..7e907c4b 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java @@ -1,10 +1,12 @@ package net.momirealms.customfishing.bukkit; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.event.CustomFishingReloadEvent; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.misc.cooldown.CoolDownManager; import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager; +import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.bukkit.action.BukkitActionManager; import net.momirealms.customfishing.bukkit.bag.BukkitBagManager; import net.momirealms.customfishing.bukkit.block.BukkitBlockManager; @@ -51,7 +53,7 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { private final PluginLogger logger; private ChatCatcherManager chatCatcherManager; private BukkitCommandManager commandManager; - private Consumer debugger; + private Consumer debugger; public BukkitCustomFishingPluginImpl(Plugin boostrap) { super(boostrap); @@ -139,7 +141,7 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { this.placeholderManager.reload(); this.configManager.reload(); // after ConfigManager - this.debugger = ConfigManager.debug() ? (s) -> logger.info("[DEBUG] " + s) : (s) -> {}; + this.debugger = ConfigManager.debug() ? (s) -> logger.info("[DEBUG] " + s.toString()) : (s) -> {}; this.actionManager.reload(); this.requirementManager.reload(); @@ -160,6 +162,8 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { this.effectManager.load(); this.hookManager.load(); this.totemManager.load(); + + EventUtils.fireAndForget(new CustomFishingReloadEvent(this)); } @Override @@ -217,7 +221,7 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { } @Override - public void debug(String message) { + public void debug(Object message) { this.debugger.accept(message); } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/action/BukkitActionManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/action/BukkitActionManager.java index 6ceba5d5..9d8c879e 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/action/BukkitActionManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/action/BukkitActionManager.java @@ -140,6 +140,7 @@ public class BukkitActionManager implements ActionManager { this.registerPluginExpAction(); this.registerSoundAction(); this.registerHologramAction(); + this.registerFakeItemAction(); this.registerTitleAction(); } @@ -159,7 +160,7 @@ public class BukkitActionManager implements ActionManager { List messages = ListUtils.toList(args); return context -> { if (Math.random() > chance) return; - String random = messages.get(RandomUtils.generateRandomInt(0, messages.size())); + String random = messages.get(RandomUtils.generateRandomInt(0, messages.size() - 1)); random = BukkitPlaceholderManager.getInstance().parse(context.getHolder(), random, context.placeholderMap()); Audience audience = plugin.getSenderFactory().getAudience(context.getHolder()); audience.sendMessage(AdventureHelper.miniMessage(random)); @@ -299,7 +300,7 @@ public class BukkitActionManager implements ActionManager { List texts = ListUtils.toList(args); return context -> { if (Math.random() > chance) return; - String random = texts.get(RandomUtils.generateRandomInt(0, texts.size())); + String random = texts.get(RandomUtils.generateRandomInt(0, texts.size() - 1)); random = plugin.getPlaceholderManager().parse(context.getHolder(), random, context.placeholderMap()); Audience audience = plugin.getSenderFactory().getAudience(context.getHolder()); audience.sendActionBar(AdventureHelper.miniMessage(random)); @@ -340,7 +341,7 @@ public class BukkitActionManager implements ActionManager { return context -> { if (Math.random() > chance) return; final Player player = context.getHolder(); - player.getLocation().getWorld().spawn(player.getLocation(), ExperienceOrb.class, e -> e.setExperience((int) value.evaluate(context))); + player.getLocation().getWorld().spawn(player.getLocation().clone().add(0,0.5,0), ExperienceOrb.class, e -> e.setExperience((int) value.evaluate(context))); }; }); registerAction("exp", (args, chance) -> { @@ -348,7 +349,7 @@ public class BukkitActionManager implements ActionManager { return context -> { if (Math.random() > chance) return; final Player player = context.getHolder(); - player.giveExp((int) value.evaluate(context)); + player.giveExp((int) Math.round(value.evaluate(context))); Audience audience = plugin.getSenderFactory().getAudience(player); AdventureHelper.playSound(audience, Sound.sound(Key.key("minecraft:entity.experience_orb.pickup"), Sound.Source.PLAYER, 1, 1)); }; @@ -696,8 +697,8 @@ public class BukkitActionManager implements ActionManager { int fadeOut = section.getInt("fade-out", 10); return context -> { if (Math.random() > chance) return; - TextValue title = TextValue.auto(titles.get(RandomUtils.generateRandomInt(0, titles.size()))); - TextValue subtitle = TextValue.auto(subtitles.get(RandomUtils.generateRandomInt(0, subtitles.size()))); + TextValue title = TextValue.auto(titles.get(RandomUtils.generateRandomInt(0, titles.size() - 1))); + TextValue subtitle = TextValue.auto(subtitles.get(RandomUtils.generateRandomInt(0, subtitles.size() - 1))); final Player player = context.getHolder(); Audience audience = plugin.getSenderFactory().getAudience(player); AdventureHelper.sendTitle(audience, @@ -745,6 +746,60 @@ public class BukkitActionManager implements ActionManager { }); } + private void registerFakeItemAction() { + registerAction("fake-item", ((args, chance) -> { + if (args instanceof Section section) { + String itemID = section.getString("item", ""); + String[] split = itemID.split(":"); + if (split.length >= 2) itemID = split[split.length - 1]; + MathValue duration = MathValue.auto(section.get("duration", 20)); + boolean position = !section.getString("position", "player").equals("player"); + MathValue x = MathValue.auto(section.get("x", 0)); + MathValue y = MathValue.auto(section.get("y", 0)); + MathValue z = MathValue.auto(section.get("z", 0)); + MathValue yaw = MathValue.auto(section.get("yaw", 0)); + int range = section.getInt("range", 0); + boolean opposite = section.getBoolean("opposite-yaw", false); + String finalItemID = itemID; + return context -> { + if (Math.random() > chance) return; + Player owner = context.getHolder(); + Location location = position ? requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)).clone() : owner.getLocation().clone(); + location.add(x.evaluate(context), y.evaluate(context) - 1, z.evaluate(context)); + if (opposite) location.setYaw(-owner.getLocation().getYaw()); + else location.setYaw((float) yaw.evaluate(context)); + FakeArmorStand armorStand = SparrowHeart.getInstance().createFakeArmorStand(location); + armorStand.invisible(true); + armorStand.equipment(EquipmentSlot.HEAD, plugin.getItemManager().buildInternal(context, finalItemID)); + ArrayList viewers = new ArrayList<>(); + if (range > 0) { + for (Entity player : location.getWorld().getNearbyEntities(location, range, range, range, entity -> entity instanceof Player)) { + double distance = LocationUtils.getDistance(player.getLocation(), location); + if (distance <= range) { + viewers.add((Player) player); + } + } + } else { + viewers.add(owner); + } + for (Player player : viewers) { + armorStand.spawn(player); + } + plugin.getScheduler().asyncLater(() -> { + for (Player player : viewers) { + if (player.isOnline() && player.isValid()) { + armorStand.destroy(player); + } + } + }, (long) (duration.evaluate(context) * 50), TimeUnit.MILLISECONDS); + }; + } else { + plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at fake-item action which is expected to be `Section`"); + return EmptyAction.INSTANCE; + } + })); + } + private void registerHologramAction() { registerAction("hologram", ((args, chance) -> { if (args instanceof Section section) { @@ -758,8 +813,7 @@ public class BukkitActionManager implements ActionManager { return context -> { if (Math.random() > chance) return; Player owner = context.getHolder(); - - Location location = position ? requireNonNull(context.arg(ContextKeys.LOCATION)).clone() : owner.getLocation().clone(); + Location location = position ? requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)).clone() : owner.getLocation().clone(); location.add(x.evaluate(context), y.evaluate(context), z.evaluate(context)); FakeArmorStand armorStand = SparrowHeart.getInstance().createFakeArmorStand(location); armorStand.invisible(true); diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/block/BukkitBlockManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/block/BukkitBlockManager.java index 6389067a..149017ac 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/block/BukkitBlockManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/block/BukkitBlockManager.java @@ -336,7 +336,7 @@ public class BukkitBlockManager implements BlockManager, Listener { if (tuple.left().evaluate(context) > Math.random()) { ItemStack itemStack = plugin.getItemManager().buildAny(context, tuple.mid()); if (itemStack != null) { - itemStack.setAmount(RandomUtils.generateRandomInt((int) tuple.right().left().evaluate(context), (int) (tuple.right().right().evaluate(context) + 1))); + itemStack.setAmount(RandomUtils.generateRandomInt((int) tuple.right().left().evaluate(context), (int) (tuple.right().right().evaluate(context)))); inventory.setItem(unused.pop(), itemStack); } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarSender.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarSender.java index 7b14039d..fae38ebf 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarSender.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/actionbar/ActionBarSender.java @@ -63,7 +63,7 @@ public class ActionBarSender { @SuppressWarnings("DuplicatedCode") private void updatePrivatePlaceholders() { - this.privateContext.arg(ContextKeys.SCORE, String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()))); + this.privateContext.arg(ContextKeys.SCORE_FORMATTED, String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()))); int rank = competition.getRanking().getPlayerRank(player.getName()); this.privateContext.arg(ContextKeys.RANK, rank != -1 ? String.valueOf(rank) : StandardLocales.COMPETITION_NO_RANK); this.privateContext.combine(competition.getPublicContext()); diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarSender.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarSender.java index b5b95be0..1ce345a4 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarSender.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/bossbar/BossBarSender.java @@ -73,7 +73,7 @@ public class BossBarSender { @SuppressWarnings("DuplicatedCode") private void updatePrivatePlaceholders() { - this.privateContext.arg(ContextKeys.SCORE, String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()))); + this.privateContext.arg(ContextKeys.SCORE_FORMATTED, String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()))); int rank = competition.getRanking().getPlayerRank(player.getName()); this.privateContext.arg(ContextKeys.RANK, rank != -1 ? String.valueOf(rank) : StandardLocales.COMPETITION_NO_RANK); this.privateContext.combine(competition.getPublicContext()); diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java index 607c55f1..140440ab 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java @@ -16,6 +16,8 @@ import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.context.ContextKeys; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.effect.EffectProperties; +import net.momirealms.customfishing.api.mechanic.event.EventManager; +import net.momirealms.customfishing.api.mechanic.item.MechanicType; import net.momirealms.customfishing.api.mechanic.misc.value.MathValue; import net.momirealms.customfishing.api.mechanic.misc.value.TextValue; import net.momirealms.customfishing.api.mechanic.requirement.Requirement; @@ -148,6 +150,8 @@ public class BukkitConfigManager extends ConfigManager { enableBag = config.getBoolean("mechanics.fishing-bag.enable", true); + multipleLootSpawnDelay = config.getInt("mechanics.multiple-loot-spawn-delay", 4); + Section placeholderSection = config.getSection("other-settings.placeholder-register"); if (placeholderSection != null) { for (Map.Entry entry : placeholderSection.getStringRouteMappedValues(false).entrySet()) { @@ -159,12 +163,31 @@ public class BukkitConfigManager extends ConfigManager { globalEffects = new ArrayList<>(); Section globalEffectSection = config.getSection("mechanics.global-effects"); - if (globalEffectSection != null) + if (globalEffectSection != null) { for (Map.Entry entry : globalEffectSection.getStringRouteMappedValues(false).entrySet()) { if (entry.getValue() instanceof Section innerSection) { globalEffects.add(parseEffect(innerSection)); } } + } + + EventManager.GLOBAL_ACTIONS.clear(); + EventManager.GLOBAL_TIMES_ACTION.clear(); + Section globalEvents = config.getSection("mechanics.global-events"); + if (globalEvents != null) { + for (Map.Entry entry : globalEvents.getStringRouteMappedValues(false).entrySet()) { + MechanicType type = MechanicType.index().value(entry.getKey()); + if (entry.getValue() instanceof Section inner) { + Map[]> actionMap = new HashMap<>(); + for (Map.Entry innerEntry : inner.getStringRouteMappedValues(false).entrySet()) { + if (innerEntry.getValue() instanceof Section actionSection) { + actionMap.put(ActionTrigger.valueOf(innerEntry.getKey().toUpperCase(Locale.ENGLISH)), plugin.getActionManager().parseActions(actionSection)); + } + } + EventManager.GLOBAL_ACTIONS.put(type, actionMap); + } + } + } } private void loadConfigs() { diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/entity/BukkitEntityManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/entity/BukkitEntityManager.java index b612455f..26179261 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/entity/BukkitEntityManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/entity/BukkitEntityManager.java @@ -116,8 +116,12 @@ public class BukkitEntityManager implements EntityManager { } else { entity = entityProviders.get("vanilla").spawn(hookLocation, entityID, config.propertyMap()); } - Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(config.horizontalVector().evaluate(context) - 1); - vector = vector.setY((vector.getY() + 0.2) * config.verticalVector().evaluate(context)); + double d0 = playerLocation.getX() - hookLocation.getX(); + double d1 = playerLocation.getY() - hookLocation.getY(); + double d2 = playerLocation.getZ() - hookLocation.getZ(); + double d3 = config.horizontalVector().evaluate(context); + double d4 = config.verticalVector().evaluate(context); + Vector vector = new Vector(d0 * 0.1D * d3, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D * d4, d2 * 0.1D * d3); entity.setVelocity(vector); return entity; } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/event/BukkitEventManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/event/BukkitEventManager.java index 402dc63e..1ac5b3b4 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/event/BukkitEventManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/event/BukkitEventManager.java @@ -36,18 +36,18 @@ public class BukkitEventManager implements EventManager, Listener { @Override public void load() { - Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap()); + Bukkit.getPluginManager().registerEvents(this, this.plugin.getBoostrap()); } @Override public Optional getEventCarrier(String id, MechanicType type) { - return Optional.ofNullable(carriers.get(type.getType() + ":" + id)); + return Optional.ofNullable(this.carriers.get(type.getType() + ":" + id)); } @Override public boolean registerEventCarrier(EventCarrier carrier) { - if (carriers.containsKey(carrier.id())) return false; - carriers.put(carrier.type().getType() + ":" + carrier.id(), carrier); + if (this.carriers.containsKey(carrier.id())) return false; + this.carriers.put(carrier.type().getType() + ":" + carrier.id(), carrier); return true; } @@ -60,8 +60,8 @@ public class BukkitEventManager implements EventManager, Listener { ItemStack itemStack = event.getPlayer().getInventory().getItemInMainHand(); if (itemStack.getType() == Material.AIR || itemStack.getAmount() == 0) return; - String id = plugin.getItemManager().getItemID(itemStack); - Optional.ofNullable(carriers.get(id)).ifPresent(carrier -> { + String id = this.plugin.getItemManager().getItemID(itemStack); + Optional.ofNullable(this.carriers.get(id)).ifPresent(carrier -> { carrier.trigger(Context.player(event.getPlayer()), ActionTrigger.INTERACT); }); } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BukkitFishingManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BukkitFishingManager.java index c082c9c0..915813d1 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BukkitFishingManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BukkitFishingManager.java @@ -1,14 +1,16 @@ package net.momirealms.customfishing.bukkit.fishing; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.event.FishingHookStateEvent; import net.momirealms.customfishing.api.event.RodCastEvent; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.fishing.CustomFishingHook; import net.momirealms.customfishing.api.mechanic.fishing.FishingGears; import net.momirealms.customfishing.api.mechanic.fishing.FishingManager; +import net.momirealms.customfishing.api.mechanic.fishing.hook.VanillaMechanic; import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; -import net.momirealms.customfishing.bukkit.util.EventUtils; +import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.common.helper.VersionHelper; import org.bukkit.Bukkit; import org.bukkit.GameMode; @@ -127,9 +129,30 @@ public class BukkitFishingManager implements FishingManager, Listener { case CAUGHT_FISH -> onCaughtFish(event); case BITE -> onBite(event); case IN_GROUND -> onInGround(event); + case FAILED_ATTEMPT -> onFailedAttempt(event); } } + // for vanilla mechanics + private void onFailedAttempt(PlayerFishEvent event) { + Player player = event.getPlayer(); + getFishHook(player).ifPresent(hook -> { + if (hook.getCurrentHookMechanic() instanceof VanillaMechanic vanillaMechanic) { + vanillaMechanic.onFailedAttempt(); + } + }); + } + + // for vanilla mechanics + private void onBite(PlayerFishEvent event) { + Player player = event.getPlayer(); + getFishHook(player).ifPresent(hook -> { + if (hook.getCurrentHookMechanic() instanceof VanillaMechanic vanillaMechanic) { + vanillaMechanic.onBite(); + } + }); + } + private void onCaughtEntity(PlayerFishEvent event) { final Player player = event.getPlayer(); getFishHook(player).ifPresent(hook -> { @@ -138,7 +161,8 @@ public class BukkitFishingManager implements FishingManager, Listener { Objects.requireNonNull(NamespacedKey.fromString("temp-entity", plugin.getBoostrap())), PersistentDataType.STRING ) != null) { - + event.setCancelled(true); + hook.onReelIn(); } }); } @@ -146,20 +170,15 @@ public class BukkitFishingManager implements FishingManager, Listener { private void onReelIn(PlayerFishEvent event) { Player player = event.getPlayer(); getFishHook(player).ifPresent(hook -> { + event.setCancelled(true); hook.onReelIn(); }); } - private void onBite(PlayerFishEvent event) { - Player player = event.getPlayer(); - getFishHook(player).ifPresent(hook -> { - hook.onBite(); - }); - } - private void onCaughtFish(PlayerFishEvent event) { Player player = event.getPlayer(); getFishHook(player).ifPresent(hook -> { + event.setCancelled(true); hook.onReelIn(); }); } @@ -169,24 +188,19 @@ public class BukkitFishingManager implements FishingManager, Listener { Player player = event.getPlayer(); Context context = Context.player(player); FishingGears gears = new FishingGears(context); - if (!RequirementManager.isSatisfied(context, ConfigManager.mechanicRequirements())) { this.destroy(player.getUniqueId()); return; } - if (!gears.canFish()) { event.setCancelled(true); return; } - if (EventUtils.fireAndCheckCancel(new RodCastEvent(event, gears))) { return; } - - plugin.debug(context.toString()); - gears.cast(); - CustomFishingHook customHook = new CustomFishingHook(hook, gears, context); + plugin.debug(context); + CustomFishingHook customHook = new CustomFishingHook(plugin, hook, gears, context); this.castHooks.put(player.getUniqueId(), customHook); } @@ -202,6 +216,19 @@ public class BukkitFishingManager implements FishingManager, Listener { } } + @EventHandler + public void onHookStateChange(FishingHookStateEvent event) { + Player player = event.getPlayer(); + getFishHook(player).ifPresent(hook -> { + switch (event.getState()) { + case BITE -> hook.onBite(); + case LAND -> hook.onLand(); + case ESCAPE -> hook.onEscape(); + case LURE -> hook.onLure(); + } + }); + } + @Override public void destroy(UUID uuid) { this.getFishHook(uuid).ifPresent(hook -> { diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/integration/BukkitIntegrationManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/integration/BukkitIntegrationManager.java index 579dd7f8..536a5ccb 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/integration/BukkitIntegrationManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/integration/BukkitIntegrationManager.java @@ -27,7 +27,6 @@ import net.momirealms.customfishing.bukkit.integration.enchant.AdvancedEnchantme import net.momirealms.customfishing.bukkit.integration.enchant.VanillaEnchantmentsProvider; import net.momirealms.customfishing.bukkit.integration.entity.ItemsAdderEntityProvider; import net.momirealms.customfishing.bukkit.integration.entity.MythicEntityProvider; -import net.momirealms.customfishing.bukkit.integration.entity.VanillaEntityProvider; import net.momirealms.customfishing.bukkit.integration.item.*; import net.momirealms.customfishing.bukkit.integration.level.*; import net.momirealms.customfishing.bukkit.integration.quest.BattlePassQuest; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemManager.java index 2493cc78..2b25acfd 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemManager.java @@ -1,7 +1,6 @@ package net.momirealms.customfishing.bukkit.item; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.event.FishingLootPreSpawnEvent; import net.momirealms.customfishing.api.event.FishingLootSpawnEvent; import net.momirealms.customfishing.api.integration.ExternalProvider; import net.momirealms.customfishing.api.integration.ItemProvider; @@ -15,12 +14,14 @@ import net.momirealms.customfishing.bukkit.integration.item.CustomFishingItemPro import net.momirealms.customfishing.bukkit.util.ItemUtils; import net.momirealms.customfishing.bukkit.util.LocationUtils; import net.momirealms.customfishing.common.item.Item; +import net.momirealms.sparrow.heart.SparrowHeart; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; import org.bukkit.block.Skull; +import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.EventHandler; @@ -152,19 +153,28 @@ public class BukkitItemManager implements ItemManager, Listener { @Nullable @Override - @SuppressWarnings("all") - public org.bukkit.entity.Item dropItemLoot(@NotNull Context context) { + public org.bukkit.entity.Item dropItemLoot(@NotNull Context context, ItemStack rod, FishHook hook) { String id = requireNonNull(context.arg(ContextKeys.ID)); - ItemStack itemStack = requireNonNull(buildInternal(context, id)); + ItemStack itemStack; + if (id.equals("vanilla")) { + itemStack = SparrowHeart.getInstance().getFishingLoot(context.getHolder(), hook, rod).stream().findAny().orElseThrow(() -> new RuntimeException("new EntityItem would throw if for whatever reason (mostly shitty datapacks) the fishing loot turns out to be empty")); + } else { + itemStack = requireNonNull(buildInternal(context, id)); + } + + if (itemStack.getType() == Material.AIR) { + return null; + } + Player player = context.getHolder(); Location playerLocation = player.getLocation(); Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)); - FishingLootPreSpawnEvent preSpawnEvent = new FishingLootPreSpawnEvent(player, hookLocation, itemStack); - Bukkit.getPluginManager().callEvent(preSpawnEvent); - if (preSpawnEvent.isCancelled()) { - return null; - } + double d0 = playerLocation.getX() - hookLocation.getX(); + double d1 = playerLocation.getY() - hookLocation.getY(); + double d2 = playerLocation.getZ() - hookLocation.getZ(); + double d3 = 0.1D; + Vector vector = new Vector(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); org.bukkit.entity.Item itemEntity = hookLocation.getWorld().dropItem(hookLocation, itemStack); FishingLootSpawnEvent spawnEvent = new FishingLootSpawnEvent(player, hookLocation, itemEntity); @@ -181,8 +191,6 @@ public class BukkitItemManager implements ItemManager, Listener { itemEntity.setInvulnerable(false); }, 1, TimeUnit.SECONDS); - Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(0.105); - vector = vector.setY((vector.getY() + 0.22) * 1.18); itemEntity.setVelocity(vector); return itemEntity; @@ -346,4 +354,9 @@ public class BukkitItemManager implements ItemManager, Listener { public Collection getItemIDs() { return items.keySet(); } + + @Override + public Item wrap(ItemStack itemStack) { + return factory.wrap(itemStack); + } } diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 0276375c..cd2cf471 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -122,7 +122,7 @@ mechanics: value: duration: 35 position: other - item: util:lava_effect + item: lava_effect priority_2: conditions: lava-fishing: false @@ -132,7 +132,7 @@ mechanics: value: duration: 35 position: other - item: util:water_effect + item: water_effect # Global properties which would help you reduce duplicated lines global-loot-property: diff --git a/core/src/main/resources/contents/item/default.yml b/core/src/main/resources/contents/item/default.yml index dde3b933..f863f46e 100644 --- a/core/src/main/resources/contents/item/default.yml +++ b/core/src/main/resources/contents/item/default.yml @@ -12,6 +12,12 @@ vanilla: disable-stat: true group: - river + events: + success: + action_mending: + type: mending + value: 1~7 + chance: 1.0 # Some rubbish stick: tag: false diff --git a/core/src/main/resources/translations/en.yml b/core/src/main/resources/translations/en.yml index 3e6fdf9b..b71b4b1b 100644 --- a/core/src/main/resources/translations/en.yml +++ b/core/src/main/resources/translations/en.yml @@ -60,6 +60,7 @@ competition.no_player: "No Player" competition.no_rank: "No Rank" competition.goal.catch_amount: "Fish count caught" competition.goal.max_size: "Largest fish caught" +competition.goal.min_size: "Smallest fish caught" competition.goal.total_score: "Cumulative score of fish caught" competition.goal.total_size: "Total length of fish caught" format.day: "d" diff --git a/gradle.properties b/gradle.properties index 619998a3..7cd04790 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ h2_driver_version=2.2.224 sqlite_driver_version=3.46.0.0 adventure_bundle_version=4.17.0 adventure_platform_version=4.3.3 -sparrow_heart_version=0.20 +sparrow_heart_version=0.21 cloud_core_version=2.0.0-rc.2 cloud_services_version=2.0.0-rc.2 cloud_brigadier_version=2.0.0-beta.8