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 7a2f497f..e3489b87 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java +++ b/api/src/main/java/net/momirealms/customfishing/api/BukkitCustomFishingPlugin.java @@ -19,8 +19,10 @@ package net.momirealms.customfishing.api; import net.momirealms.customfishing.api.integration.IntegrationManager; import net.momirealms.customfishing.api.mechanic.action.ActionManager; +import net.momirealms.customfishing.api.mechanic.block.BlockManager; import net.momirealms.customfishing.api.mechanic.competition.CompetitionManager; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; +import net.momirealms.customfishing.api.mechanic.entity.EntityManager; import net.momirealms.customfishing.api.mechanic.event.EventManager; import net.momirealms.customfishing.api.mechanic.item.ItemManager; import net.momirealms.customfishing.api.mechanic.loot.LootManager; @@ -28,6 +30,7 @@ import net.momirealms.customfishing.api.mechanic.market.MarketManager; import net.momirealms.customfishing.api.mechanic.misc.cooldown.CoolDownManager; import net.momirealms.customfishing.api.mechanic.misc.placeholder.PlaceholderManager; import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; +import net.momirealms.customfishing.api.mechanic.statistic.StatisticsManager; import net.momirealms.customfishing.api.storage.StorageManager; import net.momirealms.customfishing.common.plugin.CustomFishingPlugin; import net.momirealms.customfishing.common.plugin.scheduler.AbstractJavaScheduler; @@ -61,6 +64,9 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin { protected StorageManager storageManager; protected LootManager lootManager; protected CoolDownManager coolDownManager; + protected EntityManager entityManager; + protected BlockManager blockManager; + protected StatisticsManager statisticsManager; public BukkitCustomFishingPlugin() { instance = this; @@ -131,10 +137,22 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin { return lootManager; } + public EntityManager getEntityManager() { + return entityManager; + } + + public BlockManager getBlockManager() { + return blockManager; + } + public CoolDownManager getCoolDownManager() { return coolDownManager; } + public StatisticsManager getStatisticsManager() { + return statisticsManager; + } + public Plugin getBoostrap() { return boostrap; } diff --git a/api/src/main/java/net/momirealms/customfishing/api/integration/BlockProvider.java b/api/src/main/java/net/momirealms/customfishing/api/integration/BlockProvider.java index daf7b11e..f0bed0fd 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/integration/BlockProvider.java +++ b/api/src/main/java/net/momirealms/customfishing/api/integration/BlockProvider.java @@ -18,6 +18,7 @@ package net.momirealms.customfishing.api.integration; import net.momirealms.customfishing.api.mechanic.block.BlockDataModifier; +import net.momirealms.customfishing.api.mechanic.context.Context; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; @@ -35,12 +36,12 @@ public interface BlockProvider extends ExternalProvider { /** * Generates BlockData for a given player based on a block ID and a list of modifiers. * - * @param player The player for whom the block data is generated. + * @param context The player for whom the block data is generated. * @param id The unique identifier for the block. * @param modifiers A list of {@link BlockDataModifier} objects to apply to the block data. * @return The generated {@link BlockData} for the specified block ID and modifiers. */ - BlockData blockData(@NotNull Player player, @NotNull String id, List modifiers); + BlockData blockData(@NotNull Context context, @NotNull String id, List modifiers); /** * Retrieves the unique block ID associated with a given block. diff --git a/api/src/main/java/net/momirealms/customfishing/api/integration/IntegrationManager.java b/api/src/main/java/net/momirealms/customfishing/api/integration/IntegrationManager.java index a72a9247..fa1ec030 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/integration/IntegrationManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/integration/IntegrationManager.java @@ -17,9 +17,13 @@ package net.momirealms.customfishing.api.integration; +import net.momirealms.customfishing.common.util.Pair; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + /** * Interface for managing integration providers in the custom fishing API. * This allows for the registration and retrieval of various types of providers @@ -68,12 +72,11 @@ public interface IntegrationManager { boolean registerSeasonProvider(@NotNull SeasonProvider seasonProvider); /** - * Unregisters a SeasonProvider by its ID. + * Unregisters the SeasonProvider. * - * @param id the ID of the SeasonProvider to unregister * @return true if unregistration is successful, false otherwise */ - boolean unregisterSeasonProvider(@NotNull String id); + boolean unregisterSeasonProvider(); boolean registerEntityProvider(@NotNull EntityProvider entityProvider); @@ -104,4 +107,14 @@ public interface IntegrationManager { */ @Nullable SeasonProvider getSeasonProvider(); + + List> getEnchantments(ItemStack itemStack); + + boolean registerItemProvider(@NotNull ItemProvider itemProvider); + + boolean unregisterItemProvider(@NotNull String id); + + boolean registerBlockProvider(@NotNull BlockProvider block); + + boolean unregisterBlockProvider(@NotNull String id); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifier.java index 42408839..6830a4e5 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifier.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifier.java @@ -17,11 +17,12 @@ package net.momirealms.customfishing.api.mechanic.block; +import net.momirealms.customfishing.api.mechanic.context.Context; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; @FunctionalInterface public interface BlockDataModifier { - void apply(Player player, BlockData blockData); + void apply(Context context, BlockData blockData); } \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockManager.java new file mode 100644 index 00000000..bbc341a7 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockManager.java @@ -0,0 +1,37 @@ +/* + * 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.mechanic.block; + +import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.common.plugin.feature.Reloadable; +import org.bukkit.block.Block; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface BlockManager extends Reloadable { + + boolean registerBlock(@NotNull String id, @NotNull BlockConfig block); + + @Nullable + FallingBlock summonBlockLoot(@NotNull Context context); + + @NotNull + String getBlockID(@NotNull Block block); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java index eb9964bc..d4007c31 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java @@ -17,11 +17,12 @@ package net.momirealms.customfishing.api.mechanic.block; +import net.momirealms.customfishing.api.mechanic.context.Context; import org.bukkit.block.BlockState; import org.bukkit.entity.Player; @FunctionalInterface public interface BlockStateModifier { - void apply(Player player, BlockState blockState); + void apply(Context context, BlockState blockState); } \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/EmptyBlockDataModifier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/EmptyBlockDataModifier.java new file mode 100644 index 00000000..b67bd45e --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/EmptyBlockDataModifier.java @@ -0,0 +1,14 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import net.momirealms.customfishing.api.mechanic.context.Context; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; + +public class EmptyBlockDataModifier implements BlockDataModifier { + + public static final BlockDataModifier INSTANCE = new EmptyBlockDataModifier(); + + @Override + public void apply(Context context, BlockData blockData) { + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/EmptyBlockStateModifier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/EmptyBlockStateModifier.java new file mode 100644 index 00000000..68558c7b --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/EmptyBlockStateModifier.java @@ -0,0 +1,14 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import net.momirealms.customfishing.api.mechanic.context.Context; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Player; + +public class EmptyBlockStateModifier implements BlockStateModifier { + + public static final EmptyBlockStateModifier INSTANCE = new EmptyBlockStateModifier(); + + @Override + public void apply(Context context, BlockState blockState) { + } +} 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 63a3fa04..0aab4209 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 @@ -51,6 +51,14 @@ public abstract class ConfigManager implements ConfigLoader { return null; } + public static String[] itemDetectOrder() { + return new String[0]; + } + + public static String[] blockDetectOrder() { + return new String[0]; + } + public void registerLootParser(Function> function, String... nodes) { registerNodeFunction(nodes, new LootParserFunction(function)); } 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 2dbd4519..9f9c49c4 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 @@ -48,6 +48,10 @@ public class ContextKeys { public static final ContextKeys PLAYER = of("player", String.class); public static final ContextKeys SCORE = of("score", String.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); + public static final ContextKeys HOOK_Y = of("hook_y", Integer.class); + public static final ContextKeys HOOK_Z = of("hook_z", Integer.class); private final String key; private final Class type; diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectManager.java new file mode 100644 index 00000000..c251a38f --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectManager.java @@ -0,0 +1,13 @@ +package net.momirealms.customfishing.api.mechanic.effect; + +import net.momirealms.customfishing.common.plugin.feature.Reloadable; +import net.momirealms.customfishing.common.util.Key; + +import java.util.Optional; + +public interface EffectManager extends Reloadable { + + boolean registerEffectModifier(Key key, EffectModifier effect); + + Optional getEffectModifier(Key key); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectModifier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectModifier.java new file mode 100644 index 00000000..64f810d4 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectModifier.java @@ -0,0 +1,67 @@ +package net.momirealms.customfishing.api.mechanic.effect; + +import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.function.BiConsumer; + +/** + * EffectModifier interface for modifying effects in the CustomFishing plugin. + * This interface allows defining conditions and modifications for effects applied to players. + */ +public interface EffectModifier { + + /** + * Returns an array of requirements that must be met by a Player for the effect to be applied. + * + * @return an array of requirements + */ + Requirement[] requirements(); + + /** + * Returns a list of modifiers that apply changes to an effect within a given context. + * + * @return a list of effect modifiers + */ + List>> modifiers(); + + /** + * Creates and returns a new Builder instance for constructing EffectModifier instances. + * + * @return a new Builder instance + */ + static Builder builder() { + return new EffectModifierImpl.BuilderImpl(); + } + + /** + * Builder interface for constructing EffectModifier instances. + */ + interface Builder { + + /** + * Sets the requirements for the EffectModifier being built. + * + * @param requirements a list of requirements + * @return the current Builder instance + */ + Builder requirements(List> requirements); + + /** + * Sets the modifiers for the EffectModifier being built. + * + * @param modifiers a list of effect modifiers + * @return the current Builder instance + */ + Builder modifiers(List>> modifiers); + + /** + * Builds and returns the EffectModifier instance. + * + * @return the built EffectModifier instance + */ + EffectModifier build(); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectModifierImpl.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectModifierImpl.java new file mode 100644 index 00000000..62be8fee --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/EffectModifierImpl.java @@ -0,0 +1,50 @@ +package net.momirealms.customfishing.api.mechanic.effect; + +import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; + +public class EffectModifierImpl implements EffectModifier { + + private final Requirement[] requirements; + private final List>> modifiers; + + public EffectModifierImpl(Requirement[] requirements, List>> modifiers) { + this.requirements = requirements; + this.modifiers = modifiers; + } + + @Override + public Requirement[] requirements() { + return requirements; + } + + @Override + public List>> modifiers() { + return modifiers; + } + + public static class BuilderImpl implements Builder { + private final List> requirements = new ArrayList<>(); + private final List>> modifiers = new ArrayList<>(); + @Override + public Builder requirements(List> requirements) { + this.requirements.addAll(requirements); + return this; + } + @Override + public Builder modifiers(List>> modifiers) { + this.modifiers.addAll(modifiers); + return this; + } + @Override + @SuppressWarnings("unchecked") + public EffectModifier build() { + return new EffectModifierImpl(this.requirements.toArray(new Requirement[0]), this.modifiers); + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/entity/EntityManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/entity/EntityManager.java index 45b88fbb..ba29e793 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/entity/EntityManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/entity/EntityManager.java @@ -17,17 +17,29 @@ package net.momirealms.customfishing.api.mechanic.entity; -import net.momirealms.customfishing.api.mechanic.loot.Loot; -import org.bukkit.Location; +import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.common.plugin.feature.Reloadable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; -public interface EntityManager { +import java.util.Optional; + +/** + * EntityManager interface for managing custom entities in the fishing plugin. + */ +public interface EntityManager extends Reloadable { /** - * Summons an entity based on the given loot configuration to a specified location. + * Retrieves the configuration for a custom entity by its identifier. * - * @param hookLocation The location where the entity will be summoned, typically where the fishing hook is. - * @param playerLocation The location of the player who triggered the entity summoning. - * @param loot The loot configuration that defines the entity to be summoned. + * @param id The unique identifier of the entity configuration. + * @return An Optional containing the EntityConfig if found, or an empty Optional if not found. */ - void summonEntity(Location hookLocation, Location playerLocation, Loot loot); -} + Optional getEntity(String id); + + boolean registerEntity(String id, EntityConfig entity); + + @Nullable + Entity summonEntityLoot(Context context); +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/event/EventManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/event/EventManager.java index cf2a5729..3de94226 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/event/EventManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/event/EventManager.java @@ -5,6 +5,7 @@ import net.momirealms.customfishing.api.mechanic.action.ActionManager; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.item.ItemType; +import net.momirealms.customfishing.common.plugin.feature.Reloadable; import org.bukkit.entity.Player; import java.util.HashMap; @@ -12,24 +13,70 @@ import java.util.Map; import java.util.Optional; import java.util.TreeMap; -public interface EventManager { +/** + * EventManager interface for managing events and their associated actions within the custom fishing plugin. + * It provides methods to register, retrieve, and trigger events based on different conditions. + */ +public interface EventManager extends Reloadable { + /** + * A map storing global actions for different item types and triggers. + */ Map[]>> GLOBAL_ACTIONS = new HashMap<>(); + /** + * A map storing global timed actions for different item types and triggers. + */ Map[]>>> GLOBAL_TIMES_ACTION = new HashMap<>(); + /** + * Retrieves an EventCarrier by its identifier. + * + * @param id The unique identifier of the event carrier. + * @return An Optional containing the EventCarrier if found, or an empty Optional if not found. + */ Optional getEventCarrier(String id); + /** + * Registers a new EventCarrier with a specified identifier. + * + * @param id The unique identifier of the event carrier. + * @param carrier The EventCarrier to be registered. + * @return True if the registration was successful, false otherwise. + */ boolean registerEventCarrier(String id, EventCarrier carrier); + /** + * Triggers an event for a given context, identifier, and trigger. + * + * @param context The context in which the event is triggered. + * @param id The unique identifier of the event carrier. + * @param trigger The trigger that initiates the event. + */ default void trigger(Context context, String id, ActionTrigger trigger) { getEventCarrier(id).ifPresent(carrier -> trigger(context, carrier, trigger)); } + /** + * Triggers an event for a given context, identifier, trigger, and a range of times. + * + * @param context The context in which the event is triggered. + * @param id The unique identifier of the event carrier. + * @param trigger The trigger that initiates the event. + * @param previousTimes The previous times count for the event. + * @param afterTimes The after times count for the event. + */ default void trigger(Context context, String id, ActionTrigger trigger, int previousTimes, int afterTimes) { getEventCarrier(id).ifPresent(carrier -> trigger(context, carrier, trigger, previousTimes, afterTimes)); } + /** + * Triggers the event actions for a given context and trigger on a specified carrier. + * + * @param context The context in which the event is triggered. + * @param carrier The event carrier. + * @param trigger The trigger that initiates the event. + */ static void trigger(Context context, EventCarrier carrier, ActionTrigger trigger) { if (!carrier.disableGlobalActions()) { triggerGlobalActions(context, carrier.type(), trigger); @@ -37,6 +84,15 @@ public interface EventManager { carrier.trigger(context, trigger); } + /** + * Triggers the event actions for a given context, trigger, and times range on a specified carrier. + * + * @param context The context in which the event is triggered. + * @param carrier The event carrier. + * @param trigger The trigger that initiates the event. + * @param previousTimes The previous times count for the event. + * @param afterTimes The after times count for the event. + */ static void trigger(Context context, EventCarrier carrier, ActionTrigger trigger, int previousTimes, int afterTimes) { if (!carrier.disableGlobalActions()) { triggerGlobalActions(context, carrier.type(), trigger, previousTimes, afterTimes); @@ -44,12 +100,28 @@ public interface EventManager { carrier.trigger(context, trigger, previousTimes, afterTimes); } + /** + * Triggers global actions for a given context, item type, and trigger. + * + * @param context The context in which the event is triggered. + * @param type The type of item that triggered the event. + * @param trigger The trigger that initiates the event. + */ static void triggerGlobalActions(Context context, ItemType type, ActionTrigger trigger) { Optional.ofNullable(GLOBAL_ACTIONS.get(type)) .flatMap(actionTriggerMap -> Optional.ofNullable(actionTriggerMap.get(trigger))) .ifPresent(action -> ActionManager.trigger(context, action)); } + /** + * Triggers global timed actions for a given context, item type, trigger, and times range. + * + * @param context The context in which the event is triggered. + * @param type The type of item that triggered the event. + * @param trigger The trigger that initiates the event. + * @param previousTimes The previous times count for the event. + * @param afterTimes The after times count for the event. + */ static void triggerGlobalActions(Context context, ItemType type, ActionTrigger trigger, int previousTimes, int afterTimes) { Optional.ofNullable(GLOBAL_TIMES_ACTION.get(type)) .flatMap(actionTriggerMap -> Optional.ofNullable(actionTriggerMap.get(trigger))) diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/CustomFishingItem.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/CustomFishingItem.java index b112f043..cf7ac3ae 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/CustomFishingItem.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/CustomFishingItem.java @@ -24,7 +24,7 @@ public interface CustomFishingItem { * Returns a list of tag consumers which are functions that take an item and context as parameters * and perform some operation on them. * - * @return a set of BiConsumer instances. + * @return a list of BiConsumer instances. */ List, Context>> tagConsumers(); 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 b913b130..62617a29 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 @@ -19,16 +19,29 @@ package net.momirealms.customfishing.api.mechanic.item; import net.kyori.adventure.key.Key; import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.common.plugin.feature.Reloadable; +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; -public interface ItemManager { +public interface ItemManager extends Reloadable { + + boolean registerItem(@NotNull Key key, @NotNull CustomFishingItem item); @Nullable - ItemStack buildInternal(Context context, Key key); + ItemStack buildInternal(@NotNull Context context, @NotNull Key key); - ItemStack buildAny(Context context, String item); + @Nullable + ItemStack buildAny(@NotNull Context context, @NotNull String item); - String getCustomFishingItemID(ItemStack itemStack); + @NotNull + String getItemID(@NotNull ItemStack itemStack); + + @Nullable + String getCustomFishingItemID(@NotNull ItemStack itemStack); + + @Nullable + Item dropItemLoot(@NotNull Context context); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/StatisticsManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/StatisticsManager.java index 44286c34..3d044bcf 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/StatisticsManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/StatisticsManager.java @@ -17,18 +17,13 @@ package net.momirealms.customfishing.api.mechanic.statistic; -import org.jetbrains.annotations.Nullable; +import net.momirealms.customfishing.common.plugin.feature.Reloadable; +import org.jetbrains.annotations.NotNull; import java.util.List; -public interface StatisticsManager { +public interface StatisticsManager extends Reloadable { - /** - * Get a list of strings associated with a specific key in a category map. - * - * @param key The key to look up in the category map. - * @return A list of strings associated with the key or null if the key is not found. - */ - @Nullable + @NotNull List getCategoryMembers(String key); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/storage/user/UserData.java b/api/src/main/java/net/momirealms/customfishing/api/storage/user/UserData.java index 8a46f319..73bd1cec 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/storage/user/UserData.java +++ b/api/src/main/java/net/momirealms/customfishing/api/storage/user/UserData.java @@ -17,12 +17,13 @@ package net.momirealms.customfishing.api.storage.user; +import net.momirealms.customfishing.api.mechanic.statistic.FishingStatistics; import net.momirealms.customfishing.api.storage.data.EarningData; import net.momirealms.customfishing.api.storage.data.PlayerData; import java.util.UUID; -public interface UserData { +public interface UserData { /** * Get the username @@ -57,7 +58,7 @@ public interface UserData { * * @return statistics */ - Statistics getStatistics(); + FishingStatistics getStatistics(); /** * If the user is online on current server diff --git a/common/src/main/java/net/momirealms/customfishing/common/helper/VersionHelper.java b/common/src/main/java/net/momirealms/customfishing/common/helper/VersionHelper.java index 82fabd6e..1ca6c826 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/helper/VersionHelper.java +++ b/common/src/main/java/net/momirealms/customfishing/common/helper/VersionHelper.java @@ -17,9 +17,6 @@ package net.momirealms.customfishing.common.helper; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; -import org.bukkit.Bukkit; - import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; diff --git a/common/src/main/java/net/momirealms/customfishing/common/item/AbstractItem.java b/common/src/main/java/net/momirealms/customfishing/common/item/AbstractItem.java index f8b3ede0..34f9ac19 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/item/AbstractItem.java +++ b/common/src/main/java/net/momirealms/customfishing/common/item/AbstractItem.java @@ -67,6 +67,16 @@ public class AbstractItem implements Item { return this; } + @Override + public boolean hasTag(Object... path) { + return factory.hasTag(item, path); + } + + @Override + public boolean removeTag(Object... path) { + return factory.removeTag(item, path); + } + @Override public I getItem() { return factory.getItem(item); diff --git a/common/src/main/java/net/momirealms/customfishing/common/item/Item.java b/common/src/main/java/net/momirealms/customfishing/common/item/Item.java index 7ec36416..11084e9e 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/item/Item.java +++ b/common/src/main/java/net/momirealms/customfishing/common/item/Item.java @@ -23,6 +23,10 @@ public interface Item { Item setTag(Object value, Object... path); + boolean hasTag(Object... path); + + boolean removeTag(Object... path); + I getItem(); I load(); diff --git a/common/src/main/java/net/momirealms/customfishing/common/item/ItemFactory.java b/common/src/main/java/net/momirealms/customfishing/common/item/ItemFactory.java index 8f8e48e7..5472629e 100644 --- a/common/src/main/java/net/momirealms/customfishing/common/item/ItemFactory.java +++ b/common/src/main/java/net/momirealms/customfishing/common/item/ItemFactory.java @@ -23,6 +23,10 @@ public abstract class ItemFactory

{ protected abstract void setTag(R item, Object value, Object... path); + protected abstract boolean hasTag(R item, Object... path); + + protected abstract boolean removeTag(R item, Object... path); + protected abstract void update(R item); protected abstract I load(R item); diff --git a/common/src/main/java/net/momirealms/customfishing/common/plugin/feature/Reloadable.java b/common/src/main/java/net/momirealms/customfishing/common/plugin/feature/Reloadable.java new file mode 100644 index 00000000..6a207a23 --- /dev/null +++ b/common/src/main/java/net/momirealms/customfishing/common/plugin/feature/Reloadable.java @@ -0,0 +1,19 @@ +package net.momirealms.customfishing.common.plugin.feature; + +public interface Reloadable { + + default void reload() { + unload(); + load(); + } + + default void unload() { + } + + default void load() { + } + + default void disable() { + unload(); + } +} diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/VanillaBlockProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/VanillaBlockProvider.java deleted file mode 100644 index ac5296b2..00000000 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/VanillaBlockProvider.java +++ /dev/null @@ -1,52 +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.bukkit.compatibility.block; - -import net.momirealms.customfishing.api.integration.BlockProvider; -import net.momirealms.customfishing.api.mechanic.block.BlockDataModifier; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Locale; - -public class VanillaBlockProvider implements BlockProvider { - - @Override - public String identifier() { - return "vanilla"; - } - - @Override - public BlockData blockData(@NotNull Player player, @NotNull String id, List modifiers) { - BlockData blockData = Material.valueOf(id.toUpperCase(Locale.ENGLISH)).createBlockData(); - for (BlockDataModifier modifier : modifiers) { - modifier.apply(player, blockData); - } - return blockData; - } - - @Override - public @Nullable String blockID(@NotNull Block block) { - return block.getType().name(); - } -} diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/VaultHook.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/VaultHook.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/VaultHook.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/VaultHook.java index 4bf0ec62..a186bd92 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/VaultHook.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/VaultHook.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility; +package net.momirealms.customfishing.bukkit.integration; import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/ItemsAdderBlockProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/block/ItemsAdderBlockProvider.java similarity index 84% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/ItemsAdderBlockProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/block/ItemsAdderBlockProvider.java index 4d207327..14b4de98 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/ItemsAdderBlockProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/block/ItemsAdderBlockProvider.java @@ -15,11 +15,12 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.block; +package net.momirealms.customfishing.bukkit.integration.block; import dev.lone.itemsadder.api.CustomBlock; import net.momirealms.customfishing.api.integration.BlockProvider; import net.momirealms.customfishing.api.mechanic.block.BlockDataModifier; +import net.momirealms.customfishing.api.mechanic.context.Context; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; @@ -35,10 +36,10 @@ public class ItemsAdderBlockProvider implements BlockProvider { } @Override - public BlockData blockData(@NotNull Player player, @NotNull String id, List modifiers) { + public BlockData blockData(@NotNull Context context, @NotNull String id, List modifiers) { BlockData blockData = CustomBlock.getBaseBlockData(id); for (BlockDataModifier modifier : modifiers) { - modifier.apply(player, blockData); + modifier.apply(context, blockData); } return blockData; } diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/OraxenBlockProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/block/OraxenBlockProvider.java similarity index 85% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/OraxenBlockProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/block/OraxenBlockProvider.java index e63a095f..2f5701f2 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/block/OraxenBlockProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/block/OraxenBlockProvider.java @@ -15,12 +15,13 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.block; +package net.momirealms.customfishing.bukkit.integration.block; import io.th0rgal.oraxen.api.OraxenBlocks; import io.th0rgal.oraxen.mechanics.Mechanic; import net.momirealms.customfishing.api.integration.BlockProvider; import net.momirealms.customfishing.api.mechanic.block.BlockDataModifier; +import net.momirealms.customfishing.api.mechanic.context.Context; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; @@ -36,7 +37,7 @@ public class OraxenBlockProvider implements BlockProvider { } @Override - public BlockData blockData(@NotNull Player player, @NotNull String id, List modifiers) { + public BlockData blockData(@NotNull Context context, @NotNull String id, List modifiers) { return null; } diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/AdvancedEnchantmentsProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/enchant/AdvancedEnchantmentsProvider.java similarity index 95% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/AdvancedEnchantmentsProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/enchant/AdvancedEnchantmentsProvider.java index afd5d741..db8c0ab8 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/AdvancedEnchantmentsProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/enchant/AdvancedEnchantmentsProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.enchant; +package net.momirealms.customfishing.bukkit.integration.enchant; import net.advancedplugins.ae.api.AEAPI; import net.momirealms.customfishing.api.integration.EnchantmentProvider; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/VanillaEnchantmentsProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/enchant/VanillaEnchantmentsProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/VanillaEnchantmentsProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/enchant/VanillaEnchantmentsProvider.java index c74a7015..a604f1e1 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/enchant/VanillaEnchantmentsProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/enchant/VanillaEnchantmentsProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.enchant; +package net.momirealms.customfishing.bukkit.integration.enchant; import net.momirealms.customfishing.api.integration.EnchantmentProvider; import net.momirealms.customfishing.common.util.Pair; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/ItemsAdderEntityProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/ItemsAdderEntityProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/ItemsAdderEntityProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/ItemsAdderEntityProvider.java index c5755b61..2b26586a 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/ItemsAdderEntityProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/ItemsAdderEntityProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.entity; +package net.momirealms.customfishing.bukkit.integration.entity; import dev.lone.itemsadder.api.CustomEntity; import net.momirealms.customfishing.api.integration.EntityProvider; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/MythicEntityProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/MythicEntityProvider.java similarity index 97% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/MythicEntityProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/MythicEntityProvider.java index 8c915953..78824e7c 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/MythicEntityProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/MythicEntityProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.entity; +package net.momirealms.customfishing.bukkit.integration.entity; import io.lumine.mythic.api.adapters.AbstractLocation; import io.lumine.mythic.api.mobs.MythicMob; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/VanillaEntityProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/VanillaEntityProvider.java similarity index 95% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/VanillaEntityProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/VanillaEntityProvider.java index 53c50d47..90b53afb 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/entity/VanillaEntityProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/entity/VanillaEntityProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.entity; +package net.momirealms.customfishing.bukkit.integration.entity; import net.momirealms.customfishing.api.integration.EntityProvider; import org.bukkit.Location; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/CustomFishingItemProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/CustomFishingItemProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/CustomFishingItemProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/CustomFishingItemProvider.java index 4e6cf55e..a5148f5c 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/CustomFishingItemProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/CustomFishingItemProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import net.kyori.adventure.key.Key; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ItemsAdderItemProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/ItemsAdderItemProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ItemsAdderItemProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/ItemsAdderItemProvider.java index 8d4d323a..a8a5f3f3 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ItemsAdderItemProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/ItemsAdderItemProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import dev.lone.itemsadder.api.CustomStack; import net.momirealms.customfishing.api.integration.ItemProvider; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MMOItemsItemProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/MMOItemsItemProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MMOItemsItemProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/MMOItemsItemProvider.java index c3751d40..603fedb1 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MMOItemsItemProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/MMOItemsItemProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import io.lumine.mythic.lib.api.item.NBTItem; import net.Indyuce.mmoitems.MMOItems; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/McMMOTreasureProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/McMMOTreasureProvider.java similarity index 98% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/McMMOTreasureProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/McMMOTreasureProvider.java index 1ac7f942..3bc1f622 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/McMMOTreasureProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/McMMOTreasureProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import net.momirealms.customfishing.api.integration.ItemProvider; import org.bukkit.Material; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MythicMobsItemProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/MythicMobsItemProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MythicMobsItemProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/MythicMobsItemProvider.java index 09ff2823..fd277c2d 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/MythicMobsItemProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/MythicMobsItemProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import io.lumine.mythic.bukkit.MythicBukkit; import net.momirealms.customfishing.api.integration.ItemProvider; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/NeigeItemsItemProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/NeigeItemsItemProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/NeigeItemsItemProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/NeigeItemsItemProvider.java index a7a26a9a..e6001a06 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/NeigeItemsItemProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/NeigeItemsItemProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import net.momirealms.customfishing.api.integration.ItemProvider; import org.bukkit.entity.Player; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/OraxenItemProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/OraxenItemProvider.java similarity index 95% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/OraxenItemProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/OraxenItemProvider.java index 0cac29e0..a709ac1d 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/OraxenItemProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/OraxenItemProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import io.th0rgal.oraxen.api.OraxenItems; import io.th0rgal.oraxen.items.ItemBuilder; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ZaphkielItemImpl.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/ZaphkielItemProvider.java similarity index 90% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ZaphkielItemImpl.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/ZaphkielItemProvider.java index 10420b43..ea2ddb2e 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/item/ZaphkielItemImpl.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/item/ZaphkielItemProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.item; +package net.momirealms.customfishing.bukkit.integration.item; import ink.ptms.zaphkiel.ZapAPI; import ink.ptms.zaphkiel.Zaphkiel; @@ -27,11 +27,11 @@ import org.jetbrains.annotations.NotNull; import java.util.Objects; -public class ZaphkielItemImpl implements ItemProvider { +public class ZaphkielItemProvider implements ItemProvider { private final ZapAPI zapAPI; - public ZaphkielItemImpl() { + public ZaphkielItemProvider() { this.zapAPI = Zaphkiel.INSTANCE.api(); } diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AuraSkillsLevelerProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/AuraSkillsLevelerProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AuraSkillsLevelerProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/AuraSkillsLevelerProvider.java index de7556ee..3d514064 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AuraSkillsLevelerProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/AuraSkillsLevelerProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.level; +package net.momirealms.customfishing.bukkit.integration.level; import dev.aurelium.auraskills.api.AuraSkillsApi; import dev.aurelium.auraskills.api.registry.NamespacedId; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AureliumSkillsProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/AureliumSkillsProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AureliumSkillsProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/AureliumSkillsProvider.java index 60cbb65a..ef484833 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/AureliumSkillsProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/AureliumSkillsProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.level; +package net.momirealms.customfishing.bukkit.integration.level; import com.archyx.aureliumskills.api.AureliumAPI; import com.archyx.aureliumskills.leveler.Leveler; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoJobsLevelerProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/EcoJobsLevelerProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoJobsLevelerProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/EcoJobsLevelerProvider.java index 5e524c28..1edea7dd 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoJobsLevelerProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/EcoJobsLevelerProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.level; +package net.momirealms.customfishing.bukkit.integration.level; import com.willfp.ecojobs.api.EcoJobsAPI; import com.willfp.ecojobs.jobs.Job; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoSkillsLevelerProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/EcoSkillsLevelerProvider.java similarity index 95% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoSkillsLevelerProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/EcoSkillsLevelerProvider.java index 62e00b53..e36765f2 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/EcoSkillsLevelerProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/EcoSkillsLevelerProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.level; +package net.momirealms.customfishing.bukkit.integration.level; import com.willfp.ecoskills.api.EcoSkillsAPI; import com.willfp.ecoskills.skills.Skills; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/JobsRebornLevelerProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/JobsRebornLevelerProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/JobsRebornLevelerProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/JobsRebornLevelerProvider.java index afc82b5e..a093a83a 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/JobsRebornLevelerProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/JobsRebornLevelerProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.level; +package net.momirealms.customfishing.bukkit.integration.level; import com.gamingmesh.jobs.Jobs; import com.gamingmesh.jobs.container.Job; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/MMOCoreLevelerProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/MMOCoreLevelerProvider.java similarity index 95% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/MMOCoreLevelerProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/MMOCoreLevelerProvider.java index a33fcc7f..ecbadf20 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/MMOCoreLevelerProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/MMOCoreLevelerProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.level; +package net.momirealms.customfishing.bukkit.integration.level; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/McMMOLevelerProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/McMMOLevelerProvider.java similarity index 95% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/McMMOLevelerProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/McMMOLevelerProvider.java index f11a88bc..174f80a2 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/level/McMMOLevelerProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/level/McMMOLevelerProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.level; +package net.momirealms.customfishing.bukkit.integration.level; import com.gmail.nossr50.api.ExperienceAPI; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CompetitionPapi.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/CompetitionPapi.java similarity index 98% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CompetitionPapi.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/CompetitionPapi.java index 5c54690e..b7f2d615 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CompetitionPapi.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/CompetitionPapi.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.papi; +package net.momirealms.customfishing.bukkit.integration.papi; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CustomFishingPapi.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/CustomFishingPapi.java similarity index 98% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CustomFishingPapi.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/CustomFishingPapi.java index 43a8d541..f161b63e 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/CustomFishingPapi.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/CustomFishingPapi.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.papi; +package net.momirealms.customfishing.bukkit.integration.papi; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/StatisticsPapi.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/StatisticsPapi.java similarity index 98% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/StatisticsPapi.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/StatisticsPapi.java index 0cbd1677..ed6a1fec 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/papi/StatisticsPapi.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/papi/StatisticsPapi.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.papi; +package net.momirealms.customfishing.bukkit.integration.papi; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BattlePassQuest.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/BattlePassQuest.java similarity index 97% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BattlePassQuest.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/BattlePassQuest.java index 4a74884e..99ba5285 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BattlePassQuest.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/BattlePassQuest.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.quest; +package net.momirealms.customfishing.bukkit.integration.quest; import io.github.battlepass.BattlePlugin; import io.github.battlepass.api.events.server.PluginReloadEvent; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BetonQuestQuest.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/BetonQuestQuest.java similarity index 99% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BetonQuestQuest.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/BetonQuestQuest.java index 925eaea7..af21b06d 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/BetonQuestQuest.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/BetonQuestQuest.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.quest; +package net.momirealms.customfishing.bukkit.integration.quest; import net.momirealms.customfishing.api.event.FishingResultEvent; import org.betonquest.betonquest.BetonQuest; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/ClueScrollsQuest.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/ClueScrollsQuest.java similarity index 97% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/ClueScrollsQuest.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/ClueScrollsQuest.java index 49a9273b..99045ec3 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/quest/ClueScrollsQuest.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/quest/ClueScrollsQuest.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.quest; +package net.momirealms.customfishing.bukkit.integration.quest; import com.electro2560.dev.cluescrolls.api.*; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/AdvancedSeasonsProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/AdvancedSeasonsProvider.java similarity index 87% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/AdvancedSeasonsProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/AdvancedSeasonsProvider.java index 3a4e823e..dcae10cb 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/AdvancedSeasonsProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/AdvancedSeasonsProvider.java @@ -1,4 +1,4 @@ -package net.momirealms.customfishing.bukkit.compatibility.season; +package net.momirealms.customfishing.bukkit.integration.season; import net.advancedplugins.seasons.api.AdvancedSeasonsAPI; import net.momirealms.customfishing.api.integration.SeasonProvider; @@ -10,7 +10,7 @@ public class AdvancedSeasonsProvider implements SeasonProvider { private final AdvancedSeasonsAPI api; - public AdvancedSeasonsProvider(AdvancedSeasonsAPI api) { + public AdvancedSeasonsProvider() { this.api = new AdvancedSeasonsAPI(); } diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/CustomCropsSeasonProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/CustomCropsSeasonProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/CustomCropsSeasonProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/CustomCropsSeasonProvider.java index 5390024e..ce5a2856 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/CustomCropsSeasonProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/CustomCropsSeasonProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.season; +package net.momirealms.customfishing.bukkit.integration.season; import net.momirealms.customcrops.api.CustomCropsPlugin; import net.momirealms.customcrops.api.mechanic.world.season.Season; diff --git a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsProvider.java b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/RealisticSeasonsProvider.java similarity index 96% rename from compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsProvider.java rename to compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/RealisticSeasonsProvider.java index ed370438..f62cc591 100644 --- a/compatibility/src/main/java/net/momirealms/customfishing/bukkit/compatibility/season/RealisticSeasonsProvider.java +++ b/compatibility/src/main/java/net/momirealms/customfishing/bukkit/integration/season/RealisticSeasonsProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.bukkit.compatibility.season; +package net.momirealms.customfishing.bukkit.integration.season; import me.casperge.realisticseasons.api.SeasonsAPI; import net.momirealms.customfishing.api.integration.SeasonProvider; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java deleted file mode 100644 index 861e3270..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/BukkitCustomFishingPluginImpl.java +++ /dev/null @@ -1,291 +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.bukkit; - -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.event.CustomFishingReloadEvent; -import net.momirealms.customfishing.api.mechanic.misc.cooldown.CoolDownManager; -import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager; -import net.momirealms.customfishing.bukkit.bag.BukkitBagManager; -import net.momirealms.customfishing.bukkit.block.BukkitBlockManager; -import net.momirealms.customfishing.bukkit.compatibility.BukkitIntegrationManager; -import net.momirealms.customfishing.bukkit.competition.BukkitCompetitionManager; -import net.momirealms.customfishing.bukkit.effect.BukkitEffectManager; -import net.momirealms.customfishing.bukkit.entity.BukkitEntityManager; -import net.momirealms.customfishing.bukkit.fishing.BukkitFishingManager; -import net.momirealms.customfishing.bukkit.game.BukkitGameManager; -import net.momirealms.customfishing.bukkit.hook.BukkitHookManager; -import net.momirealms.customfishing.bukkit.item.ItemManagerImpl; -import net.momirealms.customfishing.bukkit.loot.LootManagerImpl; -import net.momirealms.customfishing.bukkit.market.BukkitMarketManager; -import net.momirealms.customfishing.bukkit.misc.ChatCatcherManager; -import net.momirealms.customfishing.bukkit.statistic.BukkitStatisticsManager; -import net.momirealms.customfishing.bukkit.storage.BukkitStorageManager; -import net.momirealms.customfishing.bukkit.totem.BukkitTotemManager; -import net.momirealms.customfishing.common.helper.VersionHelper; -import org.bstats.bukkit.Metrics; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin { - - private static ProtocolManager protocolManager; - private CoolDownManager coolDownManager; - private ChatCatcherManager chatCatcherManager; - private DependencyManager dependencyManager; - - public BukkitCustomFishingPluginImpl() { - super(); - } - - @Override - public void onLoad() { - this.versionManager = new VersionHelper(this); - this.dependencyManager = new DependencyManagerImpl(this, new ReflectionClassPathAppender(this.getClassLoader())); - this.dependencyManager.loadDependencies(new ArrayList<>( - List.of( - Dependency.GSON, - Dependency.SLF4J_API, - Dependency.SLF4J_SIMPLE, - Dependency.BOOSTED_YAML, - Dependency.EXP4J, - Dependency.MYSQL_DRIVER, - Dependency.MARIADB_DRIVER, - Dependency.MONGODB_DRIVER_SYNC, - Dependency.MONGODB_DRIVER_CORE, - Dependency.MONGODB_DRIVER_BSON, - Dependency.JEDIS, - Dependency.COMMONS_POOL_2, - Dependency.COMMONS_LANG_3, - Dependency.H2_DRIVER, - Dependency.SQLITE_DRIVER, - Dependency.BSTATS_BASE, - Dependency.HIKARI, - Dependency.BSTATS_BUKKIT, - versionManager.isMojmap() ? Dependency.COMMAND_API_MOJMAP : Dependency.COMMAND_API - ) - )); - } - - @Override - public void onEnable() { - protocolManager = ProtocolLibrary.getProtocolManager(); - - NBTUtils.disableNBTAPILogs(); - ReflectionUtils.load(); - - this.actionManager = new ActionManagerImpl(this); - this.adventure = new AdventureHelper(this); - this.bagManager = new BukkitBagManager(this); - this.blockManager = new BukkitBlockManager(this); - this.commandManager = new CommandManagerImpl(this); - this.effectManager = new BukkitEffectManager(this); - this.fishingManager = new BukkitFishingManager(this); - this.gameManager = new BukkitGameManager(this); - this.itemManager = new ItemManagerImpl(this); - this.lootManager = new LootManagerImpl(this); - this.marketManager = new BukkitMarketManager(this); - this.entityManager = new BukkitEntityManager(this); - this.placeholderManager = new BukkitPlaceholderManager(this); - this.requirementManager = new RequirementManagerImpl(this); - this.scheduler = new SchedulerImpl(this); - this.storageManager = new BukkitStorageManager(this); - this.competitionManager = new BukkitCompetitionManager(this); - this.integrationManager = new BukkitIntegrationManager(this); - this.statisticsManager = new BukkitStatisticsManager(this); - this.coolDownManager = new CoolDownManager(this); - this.totemManager = new BukkitTotemManager(this); - this.hookManager = new BukkitHookManager(this); - this.chatCatcherManager = new ChatCatcherManager(this); - this.reload(); - super.initialized = true; - - if (CFConfig.metrics) new Metrics(this, 16648); - if (CFConfig.updateChecker) - this.versionManager.checkUpdate().thenAccept(result -> { - if (!result) this.getAdventure().sendConsoleMessage("[CustomFishing] You are using the latest version."); - else this.getAdventure().sendConsoleMessage("[CustomFishing] Update is available: https://polymart.org/resource/2723"); - }); - } - - @Override - public void onDisable() { - if (this.adventure != null) ((AdventureHelper) this.adventure).close(); - if (this.bagManager != null) ((BukkitBagManager) this.bagManager).disable(); - if (this.blockManager != null) ((BukkitBlockManager) this.blockManager).disable(); - if (this.effectManager != null) ((BukkitEffectManager) this.effectManager).disable(); - if (this.fishingManager != null) ((BukkitFishingManager) this.fishingManager).disable(); - if (this.gameManager != null) ((BukkitGameManager) this.gameManager).disable(); - if (this.itemManager != null) ((ItemManagerImpl) this.itemManager).disable(); - if (this.lootManager != null) ((LootManagerImpl) this.lootManager).disable(); - if (this.marketManager != null) ((BukkitMarketManager) this.marketManager).disable(); - if (this.entityManager != null) ((BukkitEntityManager) this.entityManager).disable(); - if (this.requirementManager != null) ((RequirementManagerImpl) this.requirementManager).disable(); - if (this.scheduler != null) ((SchedulerImpl) this.scheduler).shutdown(); - if (this.integrationManager != null) ((BukkitIntegrationManager) this.integrationManager).disable(); - if (this.competitionManager != null) ((BukkitCompetitionManager) this.competitionManager).disable(); - if (this.storageManager != null) ((BukkitStorageManager) this.storageManager).disable(); - if (this.placeholderManager != null) ((BukkitPlaceholderManager) this.placeholderManager).disable(); - if (this.statisticsManager != null) ((BukkitStatisticsManager) this.statisticsManager).disable(); - if (this.actionManager != null) ((ActionManagerImpl) this.actionManager).disable(); - if (this.totemManager != null) ((BukkitTotemManager) this.totemManager).disable(); - if (this.hookManager != null) ((BukkitHookManager) this.hookManager).disable(); - if (this.coolDownManager != null) this.coolDownManager.disable(); - if (this.chatCatcherManager != null) this.chatCatcherManager.disable(); - if (this.commandManager != null) this.commandManager.unload(); - HandlerList.unregisterAll(this); - } - - /** - * Reload the plugin - */ - @Override - public void reload() { - CFConfig.load(); - CFLocale.load(); - ((SchedulerImpl) this.scheduler).reload(); - ((RequirementManagerImpl) this.requirementManager).unload(); - ((RequirementManagerImpl) this.requirementManager).load(); - ((ActionManagerImpl) this.actionManager).unload(); - ((ActionManagerImpl) this.actionManager).load(); - ((BukkitGameManager) this.gameManager).unload(); - ((BukkitGameManager) this.gameManager).load(); - ((ItemManagerImpl) this.itemManager).unload(); - ((ItemManagerImpl) this.itemManager).load(); - ((LootManagerImpl) this.lootManager).unload(); - ((LootManagerImpl) this.lootManager).load(); - ((BukkitFishingManager) this.fishingManager).unload(); - ((BukkitFishingManager) this.fishingManager).load(); - ((BukkitTotemManager) this.totemManager).unload(); - ((BukkitTotemManager) this.totemManager).load(); - ((BukkitEffectManager) this.effectManager).unload(); - ((BukkitEffectManager) this.effectManager).load(); - ((BukkitMarketManager) this.marketManager).unload(); - ((BukkitMarketManager) this.marketManager).load(); - ((BukkitBagManager) this.bagManager).unload(); - ((BukkitBagManager) this.bagManager).load(); - ((BukkitBlockManager) this.blockManager).unload(); - ((BukkitBlockManager) this.blockManager).load(); - ((BukkitEntityManager) this.entityManager).unload(); - ((BukkitEntityManager) this.entityManager).load(); - ((BukkitCompetitionManager) this.competitionManager).unload(); - ((BukkitCompetitionManager) this.competitionManager).load(); - ((BukkitStorageManager) this.storageManager).reload(); - ((BukkitStatisticsManager) this.statisticsManager).unload(); - ((BukkitStatisticsManager) this.statisticsManager).load(); - ((BukkitPlaceholderManager) this.placeholderManager).unload(); - ((BukkitPlaceholderManager) this.placeholderManager).load(); - ((BukkitHookManager) this.hookManager).unload(); - ((BukkitHookManager) this.hookManager).load(); - this.commandManager.unload(); - this.commandManager.load(); - this.coolDownManager.unload(); - this.coolDownManager.load(); - this.chatCatcherManager.unload(); - this.chatCatcherManager.load(); - - CustomFishingReloadEvent event = new CustomFishingReloadEvent(this); - Bukkit.getPluginManager().callEvent(event); - } - - /** - * Retrieves a YAML configuration from a file within the plugin's data folder. - * - * @param file The name of the configuration file. - * @return A YamlConfiguration object representing the configuration. - */ - @Override - public YamlConfiguration getConfig(String file) { - File config = new File(this.getDataFolder(), file); - if (!config.exists()) this.saveResource(file, false); - return YamlConfiguration.loadConfiguration(config); - } - - /** - * Checks if a specified plugin is enabled on the Bukkit server. - * - * @param plugin The name of the plugin to check. - * @return True if the plugin is enabled, false otherwise. - */ - @Override - public boolean isHookedPluginEnabled(String plugin) { - return Bukkit.getPluginManager().isPluginEnabled(plugin); - } - - /** - * Outputs a debugging message if the debug mode is enabled. - * - * @param message The debugging message to be logged. - */ - @Override - public void debug(String message) { - if (!CFConfig.debug) return; - LogUtils.info(message); - } - - /** - * Gets the CoolDownManager instance associated with the plugin. - * - * @return The CoolDownManager instance. - */ - public CoolDownManager getCoolDownManager() { - return coolDownManager; - } - - /** - * Gets the ChatCatcherManager instance associated with the plugin. - * - * @return The ChatCatcherManager instance. - */ - public ChatCatcherManager getChatCatcherManager() { - return chatCatcherManager; - } - - public DependencyManager getDependencyManager() { - return dependencyManager; - } - - /** - * Retrieves the ProtocolManager instance used for managing packets. - * - * @return The ProtocolManager instance. - */ - @NotNull - public static ProtocolManager getProtocolManager() { - return protocolManager; - } - - public static void sendPacket(Player player, PacketContainer packet) { - protocolManager.sendServerPacket(player, packet); - } - - public static void sendPackets(Player player, PacketContainer... packets) { - List bundle = new ArrayList<>(Arrays.asList(packets)); - PacketContainer bundlePacket = new PacketContainer(PacketType.Play.Server.BUNDLE); - bundlePacket.getPacketBundles().write(0, bundle); - sendPacket(player, bundlePacket); - } -} 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 95bd19d1..eabf4049 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 @@ -12,7 +12,9 @@ import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlacehol 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; -import net.momirealms.customfishing.bukkit.compatibility.VaultHook; +import net.momirealms.customfishing.bukkit.integration.VaultHook; +import net.momirealms.customfishing.bukkit.util.ItemUtils; +import net.momirealms.customfishing.bukkit.util.LocationUtils; import net.momirealms.customfishing.bukkit.util.PlayerUtils; import net.momirealms.customfishing.common.helper.AdventureHelper; import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask; @@ -20,8 +22,6 @@ import net.momirealms.customfishing.common.util.ClassUtils; import net.momirealms.customfishing.common.util.ListUtils; import net.momirealms.customfishing.common.util.Pair; import net.momirealms.customfishing.common.util.RandomUtils; -import net.momirealms.customfishing.bukkit.util.ItemUtils; -import net.momirealms.customfishing.bukkit.util.LocationUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Entity; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/bag/BukkitBagManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/bag/BukkitBagManager.java index 6c6b8fcc..3dac475a 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/bag/BukkitBagManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/bag/BukkitBagManager.java @@ -17,7 +17,6 @@ package net.momirealms.customfishing.bukkit.bag; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager; @@ -45,12 +44,12 @@ public class BukkitBagManager implements BagManager, Listener { private final BukkitCustomFishingPlugin plugin; private final HashMap tempEditMap; - private Action[] collectLootActions; - private Action[] bagFullActions; + private Action[] collectLootActions; + private Action[] bagFullActions; private boolean bagStoreLoots; private String bagTitle; private List bagWhiteListItems; - private Requirement[] collectRequirements; + private Requirement[] collectRequirements; public BukkitBagManager(BukkitCustomFishingPluginImpl plugin) { this.plugin = plugin; 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 1de3199e..53384c06 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 @@ -17,27 +17,27 @@ package net.momirealms.customfishing.bukkit.block; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; +import dev.dejvokep.boostedyaml.block.implementation.Section; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.common.Pair; -import net.momirealms.customfishing.api.common.Tuple; import net.momirealms.customfishing.api.integration.BlockProvider; import net.momirealms.customfishing.api.mechanic.block.*; -import net.momirealms.customfishing.api.mechanic.loot.Loot; -import net.momirealms.customfishing.bukkit.compatibility.block.VanillaBlockProvider; -import net.momirealms.customfishing.bukkit.util.ConfigUtils; +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.misc.value.MathValue; +import net.momirealms.customfishing.common.util.Pair; +import net.momirealms.customfishing.common.util.RandomUtils; +import net.momirealms.customfishing.common.util.Tuple; import org.bukkit.*; -import org.bukkit.block.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.Container; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; import org.bukkit.block.data.Rotatable; -import org.bukkit.block.data.type.Campfire; -import org.bukkit.block.data.type.Farmland; import org.bukkit.block.data.type.NoteBlock; -import org.bukkit.block.data.type.TurtleEgg; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Ageable; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -49,61 +49,77 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.io.File; import java.util.*; import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; + +import static java.util.Objects.requireNonNull; public class BukkitBlockManager implements BlockManager, Listener { private final BukkitCustomFishingPlugin plugin; - private final HashMap blockLibraryMap; - private BlockProvider[] blockDetectionArray; - private final HashMap blockConfigMap; - private final HashMap dataBuilderMap; - private final HashMap stateBuilderMap; + private final HashMap blockProviders = new HashMap<>(); + private final HashMap blocks = new HashMap<>(); + private final HashMap dataFactories = new HashMap<>(); + private final HashMap stateFactories = new HashMap<>(); + private BlockProvider[] blockDetectArray; public BukkitBlockManager(BukkitCustomFishingPluginImpl plugin) { this.plugin = plugin; - this.blockLibraryMap = new HashMap<>(); - this.blockConfigMap = new HashMap<>(); - this.dataBuilderMap = new HashMap<>(); - this.stateBuilderMap = new HashMap<>(); this.registerInbuiltProperties(); - this.registerBlockLibrary(new VanillaBlockProvider()); + this.registerBlockProvider(new BlockProvider() { + @Override + public String identifier() { + return "vanilla"; + } + @Override + public BlockData blockData(@NotNull Context context, @NotNull String id, List modifiers) { + BlockData blockData = Material.valueOf(id.toUpperCase(Locale.ENGLISH)).createBlockData(); + for (BlockDataModifier modifier : modifiers) + modifier.apply(context, blockData); + return blockData; + } + @NotNull + @Override + public String blockID(@NotNull Block block) { + return block.getType().name(); + } + }); } + @Override + public boolean registerBlock(@NotNull String id, @NotNull BlockConfig block) { + if (blocks.containsKey(id)) return false; + blocks.put(id, block); + return true; + } + + @Override public void load() { - this.loadConfig(); - Bukkit.getPluginManager().registerEvents(this, plugin); + Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap()); this.resetBlockDetectionOrder(); } + @Override public void unload() { HandlerList.unregisterAll(this); - HashMap tempMap = new HashMap<>(this.blockConfigMap); - this.blockConfigMap.clear(); - for (Map.Entry entry : tempMap.entrySet()) { - if (entry.getValue().isPersist()) { - tempMap.put(entry.getKey(), entry.getValue()); - } - } + this.blocks.clear(); } + @Override public void disable() { - this.blockLibraryMap.clear(); + this.blockProviders.clear(); } private void resetBlockDetectionOrder() { ArrayList list = new ArrayList<>(); - for (String plugin : CFConfig.itemDetectOrder) { - BlockProvider library = blockLibraryMap.get(plugin); - if (library != null) { + for (String plugin : ConfigManager.blockDetectOrder()) { + BlockProvider library = blockProviders.get(plugin); + if (library != null) list.add(library); - } } - this.blockDetectionArray = list.toArray(new BlockProvider[0]); + this.blockDetectArray = list.toArray(new BlockProvider[0]); } /** @@ -117,7 +133,7 @@ public class BukkitBlockManager implements BlockManager, Listener { // Retrieve a custom string value stored in the entity's persistent data container. String temp = event.getEntity().getPersistentDataContainer().get( - Objects.requireNonNull(NamespacedKey.fromString("block", BukkitCustomFishingPlugin.get())), + requireNonNull(NamespacedKey.fromString("block", plugin.getBoostrap())), PersistentDataType.STRING ); @@ -128,8 +144,8 @@ public class BukkitBlockManager implements BlockManager, Listener { String[] split = temp.split(";"); // If no BlockConfig is found for the specified key, return without further action. - BlockConfigImpl blockConfigImpl = blockConfigMap.get(split[0]); - if (blockConfigImpl == null) return; + BlockConfig blockConfig= blocks.get(split[0]); + if (blockConfig == null) return; // If the player is not online or not found, remove the entity and set the block to air Player player = Bukkit.getPlayer(split[1]); @@ -138,254 +154,107 @@ public class BukkitBlockManager implements BlockManager, Listener { event.getBlock().setType(Material.AIR); return; } + + Context context = Context.player(player); Location location = event.getBlock().getLocation(); // Apply block state modifiers from the BlockConfig to the block 1 tick later. - plugin.getScheduler().runTaskSyncLater(() -> { + plugin.getScheduler().sync().runLater(() -> { BlockState state = location.getBlock().getState(); - for (BlockStateModifier modifier : blockConfigImpl.stateModifiers()) { - modifier.apply(player, state); + for (BlockStateModifier modifier : blockConfig.stateModifiers()) { + modifier.apply(context, state); } - }, location, 50, TimeUnit.MILLISECONDS); + }, 1, location); } - /** - * Registers a BlockLibrary instance. - * This method associates a BlockLibrary with its unique identification and adds it to the registry. - * - * @param blockProvider The BlockLibrary instance to register. - * @return True if the registration was successful (the identification is not already registered), false otherwise. - */ - @Override - public boolean registerBlockLibrary(BlockProvider blockProvider) { - if (this.blockLibraryMap.containsKey(blockProvider.identification())) return false; - this.blockLibraryMap.put(blockProvider.identification(), blockProvider); + public boolean registerBlockProvider(BlockProvider blockProvider) { + if (this.blockProviders.containsKey(blockProvider.identifier())) return false; + this.blockProviders.put(blockProvider.identifier(), blockProvider); this.resetBlockDetectionOrder(); return true; } - /** - * Unregisters a BlockLibrary instance by its identification. - * This method removes a BlockLibrary from the registry based on its unique identification. - * - * @param identification The unique identification of the BlockLibrary to unregister. - * @return True if the BlockLibrary was successfully unregistered, false if it was not found. - */ - @Override - public boolean unregisterBlockLibrary(String identification) { - boolean success = blockLibraryMap.remove(identification) != null; + public boolean unregisterBlockProvider(String identification) { + boolean success = blockProviders.remove(identification) != null; if (success) this.resetBlockDetectionOrder(); return success; } - /** - * Registers a BlockDataModifierBuilder for a specific type. - * This method associates a BlockDataModifierBuilder with its type and adds it to the registry. - * - * @param type The type of the BlockDataModifierBuilder to register. - * @param builder The BlockDataModifierBuilder instance to register. - * @return True if the registration was successful (the type is not already registered), false otherwise. - */ - @Override - public boolean registerBlockDataModifierBuilder(String type, BlockDataModifierFactory builder) { - if (dataBuilderMap.containsKey(type)) return false; - dataBuilderMap.put(type, builder); + public boolean registerBlockDataModifierBuilder(String type, BlockDataModifierFactory factory) { + if (this.dataFactories.containsKey(type)) return false; + this.dataFactories.put(type, factory); return true; } - /** - * Registers a BlockStateModifierBuilder for a specific type. - * This method associates a BlockStateModifierBuilder with its type and adds it to the registry. - * - * @param type The type of the BlockStateModifierBuilder to register. - * @param builder The BlockStateModifierBuilder instance to register. - * @return True if the registration was successful (the type is not already registered), false otherwise. - */ - @Override - public boolean registerBlockStateModifierBuilder(String type, BlockStateModifierFactory builder) { - if (stateBuilderMap.containsKey(type)) return false; - stateBuilderMap.put(type, builder); + public boolean registerBlockStateModifierBuilder(String type, BlockStateModifierFactory factory) { + if (stateFactories.containsKey(type)) return false; + this.stateFactories.put(type, factory); return true; } - /** - * Unregisters a BlockDataModifierBuilder with the specified type. - * - * @param type The type of the BlockDataModifierBuilder to unregister. - * @return True if the BlockDataModifierBuilder was successfully unregistered, false otherwise. - */ - @Override public boolean unregisterBlockDataModifierBuilder(String type) { - return dataBuilderMap.remove(type) != null; + return this.dataFactories.remove(type) != null; } - /** - * Unregisters a BlockStateModifierBuilder with the specified type. - * - * @param type The type of the BlockStateModifierBuilder to unregister. - * @return True if the BlockStateModifierBuilder was successfully unregistered, false otherwise. - */ - @Override public boolean unregisterBlockStateModifierBuilder(String type) { - return stateBuilderMap.remove(type) != null; + return this.stateFactories.remove(type) != null; } private void registerInbuiltProperties() { this.registerDirectional(); this.registerStorage(); this.registerRotatable(); - this.registerTurtleEggs(); - this.registerMoisture(); this.registerNoteBlock(); - this.registerCampfire(); - this.registerAge(); } - /** - * Loads configuration files from the plugin's data folder and processes them. - * Configuration files are organized by type (e.g., "block"). - */ - @SuppressWarnings("DuplicatedCode") - private void loadConfig() { - Deque fileDeque = new ArrayDeque<>(); - for (String type : List.of("block")) { - File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type); - if (!typeFolder.exists()) { - if (!typeFolder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false); - } - fileDeque.push(typeFolder); - while (!fileDeque.isEmpty()) { - File file = fileDeque.pop(); - File[] files = file.listFiles(); - if (files == null) continue; - for (File subFile : files) { - if (subFile.isDirectory()) { - fileDeque.push(subFile); - } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) { - this.loadSingleFile(subFile); - } - } - } - } - } - - /** - * Loads configuration data from a single YAML file and processes it to create BlockConfig instances. - * - * @param file The YAML file to load and process. - */ - private void loadSingleFile(File file) { - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (Map.Entry entry : config.getValues(false).entrySet()) { - if (entry.getValue() instanceof ConfigurationSection section) { - - // Check if the "block" is null and log a warning if so. - String blockID = section.getString("block"); - if (blockID == null) { - LogUtils.warn("Block can't be null. File:" + file.getAbsolutePath() + "; Section:" + section.getCurrentPath()); - continue; - } - List dataModifiers = new ArrayList<>(); - List stateModifiers = new ArrayList<>(); - - // If a "properties" section exists, process its entries. - ConfigurationSection property = section.getConfigurationSection("properties"); - if (property != null) { - for (Map.Entry innerEntry : property.getValues(false).entrySet()) { - BlockDataModifierFactory dataBuilder = dataBuilderMap.get(innerEntry.getKey()); - if (dataBuilder != null) { - dataModifiers.add(dataBuilder.build(innerEntry.getValue())); - continue; - } - BlockStateModifierFactory stateBuilder = stateBuilderMap.get(innerEntry.getKey()); - if (stateBuilder != null) { - stateModifiers.add(stateBuilder.build(innerEntry.getValue())); - } - } - } - - // Create a BlockConfig instance with the processed data and add it to the blockConfigMap. - BlockConfigImpl blockConfigImpl = new BlockConfigImpl.Builder() - .blockID(blockID) - .persist(false) - .horizontalVector(section.getDouble("velocity.horizontal", 1.1)) - .verticalVector(section.getDouble("velocity.vertical", 1.2)) - .dataModifiers(dataModifiers) - .stateModifiers(stateModifiers) - .build(); - blockConfigMap.put(entry.getKey(), blockConfigImpl); - } - } - } - - /** - * Summons a falling block at a specified location based on the provided loot. - * This method spawns a falling block at the given hookLocation with specific properties determined by the loot. - * - * @param player The player who triggered the action. - * @param hookLocation The location where the hook is positioned. - * @param playerLocation The location of the player. - * @param loot The loot to be associated with the summoned block. - */ @Override - public void summonBlock(Player player, Location hookLocation, Location playerLocation, Loot loot) { - BlockConfigImpl config = blockConfigMap.get(loot.getID()); - if (config == null) { - LogUtils.warn("Block: " + loot.getID() + " doesn't exist."); - return; - } + @Nullable + public FallingBlock summonBlockLoot(@NotNull Context context) { + String id = context.arg(ContextKeys.ID); + BlockConfig config = requireNonNull(blocks.get(id), "Block " + id + " not found"); String blockID = config.blockID(); BlockData blockData; if (blockID.contains(":")) { String[] split = blockID.split(":", 2); - String lib = split[0]; - String id = split[1]; - blockData = blockLibraryMap.get(lib).blockData(player, id, config.dataModifier()); + BlockProvider provider = requireNonNull(blockProviders.get(split[0]), "BlockProvider " + split[0] + " doesn't exist"); + blockData = requireNonNull(provider.blockData(context, split[1], config.dataModifier()), "Block " + split[1] + " doesn't exist"); } else { - blockData = blockLibraryMap.get("vanilla").blockData(player, blockID, config.dataModifier()); + blockData = blockProviders.get("vanilla").blockData(context, blockID, config.dataModifier()); } - FallingBlock fallingBlock = hookLocation.getWorld().spawnFallingBlock(hookLocation, blockData); + Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)); + Location playerLocation = requireNonNull(context.getHolder()).getLocation(); + FallingBlock fallingBlock = hookLocation.getWorld().spawn(hookLocation, FallingBlock.class, (fb -> fb.setBlockData(blockData))); fallingBlock.getPersistentDataContainer().set( - Objects.requireNonNull(NamespacedKey.fromString("block", BukkitCustomFishingPlugin.get())), + requireNonNull(NamespacedKey.fromString("block", plugin.getBoostrap())), PersistentDataType.STRING, - loot.getID() + ";" + player.getName() + id + ";" + context.getHolder().getName() ); - Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.horizontalVector()) - 1); - vector = vector.setY((vector.getY() + 0.2) * config.verticalVector()); + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.horizontalVector().evaluate(context)) - 1); + vector = vector.setY((vector.getY() + 0.2) * config.verticalVector().evaluate(context)); fallingBlock.setVelocity(vector); + return fallingBlock; } - /** - * Retrieves the block ID associated with a given Block instance using block detection order. - * This method iterates through the configured block detection order to find the block's ID - * by checking different BlockLibrary instances in the specified order. - * - * @param block The Block instance for which to retrieve the block ID. - * @return The block ID - */ @Override @NotNull - public String getAnyPluginBlockID(Block block) { - for (BlockProvider blockProvider : blockDetectionArray) { + public String getBlockID(@NotNull Block block) { + for (BlockProvider blockProvider : blockDetectArray) { String id = blockProvider.blockID(block); - if (id != null) { - return id; - } + if (id != null) return id; } // Should not reach this because vanilla library would always work return "AIR"; } private void registerDirectional() { - this.registerBlockDataModifierBuilder("directional-4", (args) -> (player, blockData) -> { + this.registerBlockDataModifierBuilder("directional-4", (args) -> (context, blockData) -> { boolean arg = (boolean) args; if (arg && blockData instanceof Directional directional) { directional.setFacing(BlockFace.values()[ThreadLocalRandom.current().nextInt(0, 4)]); } }); - this.registerBlockDataModifierBuilder("directional-6", (args) -> (player, blockData) -> { + this.registerBlockDataModifierBuilder("directional-6", (args) -> (context, blockData) -> { boolean arg = (boolean) args; if (arg && blockData instanceof Directional directional) { directional.setFacing(BlockFace.values()[ThreadLocalRandom.current().nextInt(0, 6)]); @@ -393,32 +262,10 @@ public class BukkitBlockManager implements BlockManager, Listener { }); } - private void registerMoisture() { - this.registerBlockDataModifierBuilder("moisture", (args) -> { - int arg = (int) args; - return (player, blockData) -> { - if (blockData instanceof Farmland farmland) { - farmland.setMoisture(arg); - } - }; - }); - } - - private void registerCampfire() { - this.registerBlockDataModifierBuilder("campfire", (args) -> { - boolean arg = (boolean) args; - return (player, blockData) -> { - if (blockData instanceof Campfire campfire) { - campfire.setSignalFire(arg); - } - }; - }); - } - private void registerRotatable() { this.registerBlockDataModifierBuilder("rotatable", (args) -> { boolean arg = (boolean) args; - return (player, blockData) -> { + return (context, blockData) -> { if (arg && blockData instanceof Rotatable rotatable) { rotatable.setRotation(BlockFace.values()[ThreadLocalRandom.current().nextInt(BlockFace.values().length)]); } @@ -428,99 +275,64 @@ public class BukkitBlockManager implements BlockManager, Listener { private void registerNoteBlock() { this.registerBlockDataModifierBuilder("noteblock", (args) -> { - if (args instanceof ConfigurationSection section) { + if (args instanceof Section section) { var instrument = Instrument.valueOf(section.getString("instrument")); var note = new Note(section.getInt("note")); - return (player, blockData) -> { + return (context, blockData) -> { if (blockData instanceof NoteBlock noteBlock) { noteBlock.setNote(note); noteBlock.setInstrument(instrument); } }; } else { - LogUtils.warn("Invalid property format found at block noteblock."); - return null; + plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at noteblock property which should be Section"); + return EmptyBlockDataModifier.INSTANCE; } }); } - private void registerAge() { - this.registerBlockDataModifierBuilder("age", (args) -> { - int arg = (int) args; - return (player, blockData) -> { - if (blockData instanceof Ageable ageable) { - ageable.setAge(arg); - } - }; - }); - } - - private void registerTurtleEggs() { - this.registerBlockDataModifierBuilder("turtle-eggs", (args) -> { - int arg = (int) args; - return (player, blockData) -> { - if (blockData instanceof TurtleEgg egg) { - egg.setEggs(arg); - } - }; - }); - } - private void registerStorage() { this.registerBlockStateModifierBuilder("storage", (args) -> { - if (args instanceof ConfigurationSection section) { - ArrayList>> tempChanceList = new ArrayList<>(); - for (Map.Entry entry : section.getValues(false).entrySet()) { + if (args instanceof Section section) { + List, String, Pair, MathValue>>> contents = new ArrayList<>(); + for (Map.Entry entry : section.getStringRouteMappedValues(false).entrySet()) { if (entry.getValue() instanceof ConfigurationSection inner) { String item = inner.getString("item"); - Pair amountPair = ConfigUtils.splitStringIntegerArgs(inner.getString("amount","1~1"), "~"); - double chance = inner.getDouble("chance", 1); - tempChanceList.add(Tuple.of(chance, item, amountPair)); + String[] split = inner.getString("amount","1~1").split("~"); + Pair, MathValue> amountPair = Pair.of(MathValue.auto(split[0]), MathValue.auto(split[1])); + MathValue chance = MathValue.auto(inner.get("chance", 1d)); + contents.add(Tuple.of(chance, item, amountPair)); } } - return (player, blockState) -> { - if (blockState instanceof Chest chest) { - setInventoryItems(tempChanceList, player, chest.getInventory()); - return; - } - if (blockState instanceof Barrel barrel) { - setInventoryItems(tempChanceList, player, barrel.getInventory()); - return; - } - if (blockState instanceof ShulkerBox shulkerBox) { - setInventoryItems(tempChanceList, player, shulkerBox.getInventory()); - return; + return (context, blockState) -> { + if (blockState instanceof Container container) { + setInventoryItems(contents, context, container.getInventory()); } }; } else { - LogUtils.warn("Invalid property format found at block storage."); - return null; + plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at storage property which should be Section"); + return EmptyBlockStateModifier.INSTANCE; } }); } - /** - * Sets items in the BLOCK's inventory based on chance and configuration. - * - * @param tempChanceList A list of tuples containing chance, item ID, and quantity range for each item. - * @param player The inventory items are being set. - * @param inventory The inventory where the items will be placed. - */ private void setInventoryItems( - ArrayList>> tempChanceList, - Player player, + List, String, Pair, MathValue>>> contents, + Context context, Inventory inventory ) { LinkedList unused = new LinkedList<>(); - for (int i = 0; i < 27; i++) { + for (int i = 0; i < inventory.getSize(); i++) { unused.add(i); } Collections.shuffle(unused); - for (Tuple> tuple : tempChanceList) { - ItemStack itemStack = plugin.getItemManager().buildAnyPluginItemByID(player, tuple.getMid()); - itemStack.setAmount(ThreadLocalRandom.current().nextInt(tuple.getRight().left(), tuple.getRight().right() + 1)); - if (tuple.getLeft() > Math.random()) { - inventory.setItem(unused.pop(), itemStack); + for (Tuple, String, Pair, MathValue>> tuple : contents) { + if (tuple.getLeft().evaluate(context) > Math.random()) { + ItemStack itemStack = plugin.getItemManager().buildAny(context, tuple.getMid()); + if (itemStack != null) { + itemStack.setAmount(RandomUtils.generateRandomInt((int) tuple.getRight().left().evaluate(context), (int) (tuple.getRight().right().evaluate(context) + 1))); + inventory.setItem(unused.pop(), itemStack); + } } } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/BukkitIntegrationManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/BukkitIntegrationManager.java deleted file mode 100644 index c7a6e03a..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/compatibility/BukkitIntegrationManager.java +++ /dev/null @@ -1,271 +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.bukkit.compatibility; - -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.integration.EnchantmentProvider; -import net.momirealms.customfishing.api.integration.IntegrationManager; -import net.momirealms.customfishing.api.integration.LevelerProvider; -import net.momirealms.customfishing.api.integration.SeasonProvider; -import net.momirealms.customfishing.bukkit.compatibility.block.ItemsAdderBlockProvider; -import net.momirealms.customfishing.bukkit.compatibility.enchant.AdvancedEnchantmentsProvider; -import net.momirealms.customfishing.bukkit.compatibility.enchant.VanillaEnchantmentsProvider; -import net.momirealms.customfishing.bukkit.compatibility.entity.ItemsAdderEntityProvider; -import net.momirealms.customfishing.bukkit.compatibility.entity.MythicEntityProvider; -import net.momirealms.customfishing.bukkit.compatibility.item.*; -import net.momirealms.customfishing.bukkit.compatibility.level.*; -import net.momirealms.customfishing.bukkit.compatibility.quest.BattlePassQuest; -import net.momirealms.customfishing.bukkit.compatibility.quest.BetonQuestQuest; -import net.momirealms.customfishing.bukkit.compatibility.quest.ClueScrollsQuest; -import net.momirealms.customfishing.bukkit.compatibility.season.CustomCropsSeasonProvider; -import net.momirealms.customfishing.bukkit.compatibility.season.RealisticSeasonsProvider; -import org.bukkit.Bukkit; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class BukkitIntegrationManager implements IntegrationManager { - - private final BukkitCustomFishingPlugin plugin; - private final HashMap levelPluginMap; - private final HashMap enchantmentPluginMap; - private SeasonProvider seasonProvider; - - public BukkitIntegrationManager(BukkitCustomFishingPlugin plugin) { - this.plugin = plugin; - this.levelPluginMap = new HashMap<>(); - this.enchantmentPluginMap = new HashMap<>(); - this.load(); - } - - public void disable() { - this.enchantmentPluginMap.clear(); - this.levelPluginMap.clear(); - } - - public void load() { - if (Bukkit.getPluginManager().getPlugin("ItemsAdder") != null) { - plugin.getItemManager().registerItemLibrary(new ItemsAdderItemProvider()); - plugin.getBlockManager().registerBlockLibrary(new ItemsAdderBlockProvider()); - plugin.getEntityManager().registerEntityProvider(new ItemsAdderEntityProvider()); - hookMessage("ItemsAdder"); - } - if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) { - plugin.getItemManager().registerItemLibrary(new MMOItemsItemProvider()); - hookMessage("MMOItems"); - } - if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) { - plugin.getItemManager().registerItemLibrary(new OraxenItemProvider()); - hookMessage("Oraxen"); - } - if (plugin.isHookedPluginEnabled("Zaphkiel")) { - plugin.getItemManager().registerItemLibrary(new ZaphkielItemImpl()); - hookMessage("Zaphkiel"); - } - if (plugin.isHookedPluginEnabled("NeigeItems")) { - plugin.getItemManager().registerItemLibrary(new NeigeItemsItemProvider()); - hookMessage("NeigeItems"); - } - if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) { - plugin.getItemManager().registerItemLibrary(new MythicMobsItemProvider()); - plugin.getEntityManager().registerEntityProvider(new MythicEntityProvider()); - hookMessage("MythicMobs"); - } - if (plugin.isHookedPluginEnabled("EcoJobs")) { - registerLevelerProvider("EcoJobs", new EcoJobsLevelerProvider()); - hookMessage("EcoJobs"); - } - if (plugin.isHookedPluginEnabled("EcoSkills")) { - registerLevelerProvider("EcoSkills", new EcoSkillsLevelerProvider()); - hookMessage("EcoSkills"); - } - if (Bukkit.getPluginManager().getPlugin("Jobs") != null) { - registerLevelerProvider("JobsReborn", new JobsRebornLevelerProvider()); - hookMessage("JobsReborn"); - } - if (plugin.isHookedPluginEnabled("MMOCore")) { - registerLevelerProvider("MMOCore", new MMOCoreLevelerProvider()); - hookMessage("MMOCore"); - } - if (plugin.isHookedPluginEnabled("mcMMO")) { - try { - plugin.getItemManager().registerItemLibrary(new McMMOTreasureProvider()); - } catch (ClassNotFoundException | NoSuchMethodException e) { - LogUtils.warn("Failed to initialize mcMMO Treasure"); - } - registerLevelerProvider("mcMMO", new McMMOLevelerProvider()); - hookMessage("mcMMO"); - } - if (plugin.isHookedPluginEnabled("AureliumSkills")) { - registerLevelerProvider("AureliumSkills", new AureliumSkillsProvider()); - hookMessage("AureliumSkills"); - } - if (plugin.isHookedPluginEnabled("AuraSkills")) { - registerLevelerProvider("AuraSkills", new AuraSkillsLevelerProvider()); - hookMessage("AuraSkills"); - } - if (plugin.isHookedPluginEnabled("EcoEnchants")) { - this.enchantmentPluginMap.put("EcoEnchants", new VanillaEnchantmentsProvider()); - hookMessage("EcoEnchants"); - } else { - this.enchantmentPluginMap.put("vanilla", new VanillaEnchantmentsProvider()); - } - if (plugin.isHookedPluginEnabled("AdvancedEnchantments")) { - this.enchantmentPluginMap.put("AdvancedEnchantments", new AdvancedEnchantmentsProvider()); - hookMessage("AdvancedEnchantments"); - } - if (plugin.isHookedPluginEnabled("RealisticSeasons")) { - this.seasonProvider = new RealisticSeasonsProvider(); - } else if (plugin.isHookedPluginEnabled("CustomCrops")) { - this.seasonProvider = new CustomCropsSeasonProvider(); - } - if (plugin.isHookedPluginEnabled("Vault")) { - VaultHook.initialize(); - } - if (plugin.isHookedPluginEnabled("BattlePass")){ - BattlePassQuest battlePassQuest = new BattlePassQuest(); - battlePassQuest.register(); - hookMessage("BattlePass"); - } - if (plugin.isHookedPluginEnabled("ClueScrolls")) { - ClueScrollsQuest clueScrollsQuest = new ClueScrollsQuest(); - clueScrollsQuest.register(); - hookMessage("ClueScrolls"); - } - if (plugin.isHookedPluginEnabled("BetonQuest")) { - BetonQuestQuest.register(); - hookMessage("BetonQuest"); - } - } - - /** - * Registers a level plugin with the specified name. - * - * @param plugin The name of the level plugin. - * @param level The implementation of the LevelInterface. - * @return true if the registration was successful, false if the plugin name is already registered. - */ - @Override - public boolean registerLevelerProvider(String plugin, LevelerProvider level) { - if (levelPluginMap.containsKey(plugin)) return false; - levelPluginMap.put(plugin, level); - return true; - } - - /** - * Unregisters a level plugin with the specified name. - * - * @param plugin The name of the level plugin to unregister. - * @return true if the unregistration was successful, false if the plugin name is not found. - */ - @Override - public boolean unregisterLevelerProvider(String plugin) { - return levelPluginMap.remove(plugin) != null; - } - - /** - * Registers an enchantment provided by a plugin. - * - * @param plugin The name of the plugin providing the enchantment. - * @param enchantment The enchantment to register. - * @return true if the registration was successful, false if the enchantment name is already in use. - */ - @Override - public boolean registerEnchantment(String plugin, EnchantmentProvider enchantment) { - if (enchantmentPluginMap.containsKey(plugin)) return false; - enchantmentPluginMap.put(plugin, enchantment); - return true; - } - - /** - * Unregisters an enchantment provided by a plugin. - * - * @param plugin The name of the plugin providing the enchantment. - * @return true if the enchantment was successfully unregistered, false if the enchantment was not found. - */ - @Override - public boolean unregisterEnchantment(String plugin) { - return enchantmentPluginMap.remove(plugin) != null; - } - - private void hookMessage(String plugin) { - LogUtils.info( plugin + " hooked!"); - } - - /** - * Get the LevelInterface provided by a plugin. - * - * @param plugin The name of the plugin providing the LevelInterface. - * @return The LevelInterface provided by the specified plugin, or null if the plugin is not registered. - */ - @Override - @Nullable - public LevelerProvider getLevelPlugin(String plugin) { - return levelPluginMap.get(plugin); - } - - /** - * Get an enchantment plugin by its plugin name. - * - * @param plugin The name of the enchantment plugin. - * @return The enchantment plugin interface, or null if not found. - */ - @Override - @Nullable - public EnchantmentProvider getEnchantmentPlugin(String plugin) { - return enchantmentPluginMap.get(plugin); - } - - /** - * Get a list of enchantment keys with level applied to the given ItemStack. - * - * @param itemStack The ItemStack to check for enchantments. - * @return A list of enchantment names applied to the ItemStack. - */ - @Override - public List getEnchantments(ItemStack itemStack) { - ArrayList list = new ArrayList<>(); - for (EnchantmentProvider enchantmentProvider : enchantmentPluginMap.values()) { - list.addAll(enchantmentProvider.getEnchants(itemStack)); - } - return list; - } - - /** - * Get the current season interface, if available. - * - * @return The current season interface, or null if not available. - */ - @Nullable - public SeasonProvider getSeasonInterface() { - return seasonProvider; - } - - /** - * Set the current season interface. - * - * @param season The season interface to set. - */ - @Override - public void setSeasonInterface(SeasonProvider season) { - this.seasonProvider = season; - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java index 997e0e35..54e18722 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/competition/BukkitCompetitionManager.java @@ -116,7 +116,6 @@ public class BukkitCompetitionManager implements CompetitionManager { YamlDocument document = plugin.getConfigManager().loadData(file); for (Map.Entry entry : document.getStringRouteMappedValues(false).entrySet()) { if (entry.getValue() instanceof Section section) { - CompetitionConfig.Builder builder = CompetitionConfig.builder() .key(entry.getKey()) .goal(CompetitionGoal.index().value(section.getString("goal", "TOTAL_SCORE").toLowerCase(Locale.ENGLISH))) @@ -128,7 +127,6 @@ public class BukkitCompetitionManager implements CompetitionManager { .startActions(plugin.getActionManager().parseActions(section.getSection("start-actions"))) .endActions(plugin.getActionManager().parseActions(section.getSection("end-actions"))) .skipActions(plugin.getActionManager().parseActions(section.getSection("skip-actions")));; - if (section.getBoolean("bossbar.enable", false)) { builder.bossBarConfig( BossBarConfig.builder() @@ -142,7 +140,6 @@ public class BukkitCompetitionManager implements CompetitionManager { .build() ); } - if (section.getBoolean("actionbar.enable", false)) { builder.actionBarConfig( ActionBarConfig.builder() @@ -154,7 +151,6 @@ public class BukkitCompetitionManager implements CompetitionManager { .build() ); } - CompetitionConfig competitionConfig = builder.build(); List> timePairs = section.getStringList("start-time") .stream().map(it -> { 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 c1aa176a..7b14039d 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 @@ -84,7 +84,7 @@ public class ActionBarSender { DynamicText text = texts[counter % (texts.length)]; updatePrivatePlaceholders(); text.update(this.privateContext.placeholderMap()); - audience.sendActionBar(AdventureHelper.miniMessage().deserialize(text.getLatestValue())); + audience.sendActionBar(AdventureHelper.miniMessage(text.getLatestValue())); } }, 50, 50, TimeUnit.MILLISECONDS); } 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 81d804cf..b5b95be0 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 @@ -63,7 +63,7 @@ public class BossBarSender { texts[i].update(privateContext.placeholderMap()); } bossBar = BossBar.bossBar( - AdventureHelper.miniMessage().deserialize(texts[0].getLatestValue()), + AdventureHelper.miniMessage(texts[0].getLatestValue()), competition.getProgress(), config.color(), config.overlay(), @@ -95,7 +95,7 @@ public class BossBarSender { DynamicText text = texts[counter % (texts.length)]; updatePrivatePlaceholders(); if (text.update(privateContext.placeholderMap())) { - bossBar.name(AdventureHelper.miniMessage().deserialize(text.getLatestValue())); + bossBar.name(AdventureHelper.miniMessage(text.getLatestValue())); } bossBar.progress(competition.getProgress()); } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigLoader.java b/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigLoader.java index 4930000e..afdc3d2d 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigLoader.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigLoader.java @@ -88,27 +88,27 @@ public class BukkitConfigLoader extends ConfigManager { this.registerBaseEffectParser(object -> { MathValue mathValue = MathValue.auto(object); return builder -> builder.difficultyAdder(mathValue); - }, "base-difficulty-adder"); + }, "base-effects", "difficulty-adder"); this.registerBaseEffectParser(object -> { MathValue mathValue = MathValue.auto(object); return builder -> builder.difficultyMultiplier(mathValue); - }, "base-difficulty-multiplier"); + }, "base-effects", "difficulty-multiplier"); this.registerBaseEffectParser(object -> { MathValue mathValue = MathValue.auto(object); return builder -> builder.gameTimeAdder(mathValue); - }, "base-game-time-adder"); + }, "base-effects", "game-time-adder"); this.registerBaseEffectParser(object -> { MathValue mathValue = MathValue.auto(object); return builder -> builder.gameTimeMultiplier(mathValue); - }, "base-game-time-multiplier"); + }, "base-effects", "game-time-multiplier"); this.registerBaseEffectParser(object -> { MathValue mathValue = MathValue.auto(object); return builder -> builder.waitTimeAdder(mathValue); - }, "base-wait-time-adder"); + }, "base-effects", "wait-time-adder"); this.registerBaseEffectParser(object -> { MathValue mathValue = MathValue.auto(object); return builder -> builder.waitTimeMultiplier(mathValue); - }, "base-wait-time-multiplier"); + }, "base-effects", "wait-time-multiplier"); } private void registerBuiltInLootParser() { diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/effect/BukkitEffectManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/effect/BukkitEffectManager.java index be2667fd..108e9030 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/effect/BukkitEffectManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/effect/BukkitEffectManager.java @@ -18,371 +18,35 @@ package net.momirealms.customfishing.bukkit.effect; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.common.Key; -import net.momirealms.customfishing.api.common.Pair; -import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffectImpl; -import net.momirealms.customfishing.api.mechanic.misc.value.MathValue; -import net.momirealms.customfishing.api.mechanic.requirement.Requirement; -import net.momirealms.customfishing.mechanic.misc.value.PlainMathValue; -import net.momirealms.customfishing.bukkit.util.ConfigUtils; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import net.momirealms.customfishing.api.mechanic.effect.EffectManager; +import net.momirealms.customfishing.api.mechanic.effect.EffectModifier; +import net.momirealms.customfishing.common.util.Key; -import java.io.File; -import java.util.*; +import java.util.HashMap; +import java.util.Optional; public class BukkitEffectManager implements EffectManager { private final BukkitCustomFishingPlugin plugin; - - private final HashMap effectMap; + private final HashMap effectModifiers = new HashMap<>(); public BukkitEffectManager(BukkitCustomFishingPlugin plugin) { this.plugin = plugin; - this.effectMap = new HashMap<>(); } public void disable() { - this.effectMap.clear(); + this.effectModifiers.clear(); } - /** - * Registers an EffectCarrier with a unique Key. - * - * @param key The unique Key associated with the EffectCarrier. - * @param effect The EffectCarrier to be registered. - * @return True if the registration was successful, false if the Key already exists. - */ @Override - public boolean registerEffectCarrier(Key key, EffectCarrier effect) { - if (effectMap.containsKey(key)) return false; - this.effectMap.put(key, effect); + public boolean registerEffectModifier(Key key, EffectModifier effect) { + if (effectModifiers.containsKey(key)) return false; + this.effectModifiers.put(key, effect); return true; } - /** - * Unregisters an EffectCarrier associated with the specified Key. - * - * @param key The unique Key of the EffectCarrier to unregister. - * @return True if the EffectCarrier was successfully unregistered, false if the Key does not exist. - */ @Override - public boolean unregisterEffectCarrier(Key key) { - return this.effectMap.remove(key) != null; - } - - /** - * Checks if an EffectCarrier with the specified namespace and id exists. - * - * @param namespace The namespace of the EffectCarrier. - * @param id The unique identifier of the EffectCarrier. - * @return True if an EffectCarrier with the given namespace and id exists, false otherwise. - */ - @Override - public boolean hasEffectCarrier(String namespace, String id) { - return effectMap.containsKey(Key.of(namespace, id)); - } - - /** - * Retrieves an EffectCarrier with the specified namespace and id. - * - * @param namespace The namespace of the EffectCarrier. - * @param id The unique identifier of the EffectCarrier. - * @return The EffectCarrier with the given namespace and id, or null if it doesn't exist. - */ - @Nullable - @Override - public EffectCarrier getEffectCarrier(String namespace, String id) { - return effectMap.get(Key.of(namespace, id)); - } - - public void load() { - this.loadFiles(); - this.loadGlobalEffects(); - } - - /** - * Loads EffectCarrier configurations from YAML files in different content folders. - * EffectCarrier configurations are organized by type (rod, bait, enchant, util, totem, hook) in separate folders. - * Each YAML file within these folders is processed to populate the effectMap. - */ - @SuppressWarnings("DuplicatedCode") - private void loadFiles() { - Deque fileDeque = new ArrayDeque<>(); - for (String type : List.of("rod", "bait", "enchant", "util", "totem", "hook")) { - File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type); - if (!typeFolder.exists()) { - if (!typeFolder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false); - } - fileDeque.push(typeFolder); - while (!fileDeque.isEmpty()) { - File file = fileDeque.pop(); - File[] files = file.listFiles(); - if (files == null) continue; - for (File subFile : files) { - if (subFile.isDirectory()) { - fileDeque.push(subFile); - } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) { - this.loadSingleFile(subFile, type); - } - } - } - } - } - - /** - * Loads EffectCarrier configurations from a YAML file and populates the effectMap. - * - * @param file The YAML file to load configurations from. - * @param namespace The namespace to use when creating keys for EffectCarriers. - */ - private void loadSingleFile(File file, String namespace) { - YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file); - for (Map.Entry entry : yaml.getValues(false).entrySet()) { - String value = entry.getKey(); - if (entry.getValue() instanceof ConfigurationSection section) { - Key key = Key.of(namespace, value); - EffectCarrier item = getEffectCarrierFromSection(key, section); - if (item != null) - effectMap.put(key, item); - } - } - } - - /** - * Parses a ConfigurationSection to create an EffectCarrier based on the specified key and configuration. - * - * @param key The key that uniquely identifies the EffectCarrier. - * @param section The ConfigurationSection containing the EffectCarrier configuration. - * @return An EffectCarrier instance based on the key and configuration, or null if the section is null. - */ - @Override - @Nullable - public EffectCarrier getEffectCarrierFromSection(Key key, ConfigurationSection section) { - if (section == null) return null; - return new EffectCarrier.Builder() - .key(key) - .requirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), true)) - .effect(getEffectModifiers(section.getConfigurationSection("effects"))) - .actionMap(plugin.getActionManager().getActionMap(section.getConfigurationSection("events"))) - .build(); - } - - public void unload() { - HashMap temp = new HashMap<>(effectMap); - effectMap.clear(); - for (Map.Entry entry : temp.entrySet()) { - if (entry.getValue().isPersist()) { - effectMap.put(entry.getKey(), entry.getValue()); - } - } - } - - /** - * Retrieves the initial FishingEffect that represents no special effects. - * - * @return The initial FishingEffect. - */ - @NotNull - @Override - public FishingEffect getInitialEffect() { - return new FishingEffect(); - } - - /** - * Retrieves a list of modifiers based on specified loot groups. - * - * @param modList A list of strings containing group modifiers in the format "group:modifier". - * @return A list of pairs where each pair represents a loot item and its associated modifier. - */ - private List> getGroupModifiers(List modList) { - List> result = new ArrayList<>(); - for (String group : modList) { - String[] split = group.split(":",2); - String key = split[0]; - List members = plugin.getLootManager().getGroupMembers(key); - if (members == null) { - LogUtils.warn("Group " + key + " doesn't contain any loot. The effect would not take effect."); - return result; - } - for (String loot : members) { - result.add(Pair.of(loot, ConfigUtils.getModifier(split[1]))); - } - } - return result; - } - - /** - * Parses a ConfigurationSection to retrieve an array of EffectModifiers. - * - * @param section The ConfigurationSection to parse. - * @return An array of EffectModifiers based on the values found in the section. - */ - @NotNull - @Override - public EffectModifier[] getEffectModifiers(ConfigurationSection section) { - if (section == null) return new EffectModifier[0]; - ArrayList modifiers = new ArrayList<>(); - for (Map.Entry entry: section.getValues(false).entrySet()) { - if (entry.getValue() instanceof ConfigurationSection inner) { - EffectModifier effectModifier = getEffectModifier(inner); - if (effectModifier != null) - modifiers.add(effectModifier); - } - } - return modifiers.toArray(new EffectModifier[0]); - } - - @Override - public LootBaseEffectImpl getBaseEffect(ConfigurationSection section) { - if (section == null) return new LootBaseEffectImpl( - new PlainMathValue(0), new PlainMathValue(1d), - new PlainMathValue(0), new PlainMathValue(1d), - new PlainMathValue(0), new PlainMathValue(1d) - ); - MathValue waitTime = section.contains("wait-time") ? ConfigUtils.getValue(section.get("wait-time")) : new PlainMathValue(0); - MathValue difficulty = section.contains("difficulty") ? ConfigUtils.getValue(section.get("difficulty")) : new PlainMathValue(0); - MathValue gameTime = section.contains("game-time") ? ConfigUtils.getValue(section.get("game-time")) : new PlainMathValue(0); - MathValue waitTimeMultiplier = section.contains("wait-time-multiplier") ? ConfigUtils.getValue(section.get("wait-time-multiplier")) : new PlainMathValue(1); - MathValue difficultyMultiplier = section.contains("difficulty-multiplier") ? ConfigUtils.getValue(section.get("difficulty-multiplier")) : new PlainMathValue(1); - MathValue gameTimeMultiplier = section.contains("game-time-multiplier") ? ConfigUtils.getValue(section.get("game-time-multiplier")) : new PlainMathValue(1); - return new LootBaseEffectImpl( - waitTime, waitTimeMultiplier, - difficulty, difficultyMultiplier, - gameTime, gameTimeMultiplier - ); - } - - private void loadGlobalEffects() { - YamlConfiguration config = plugin.getConfig("config.yml"); - ConfigurationSection section = config.getConfigurationSection("mechanics.global-effects"); - GlobalSettings.setEffects(getEffectModifiers(section)); - } - - /** - * Parses a ConfigurationSection to create an EffectModifier based on the specified type and configuration. - * - * @param section The ConfigurationSection containing the effect modifier configuration. - * @return An EffectModifier instance based on the type and configuration. - */ - @Override - @Nullable - public EffectModifier getEffectModifier(ConfigurationSection section) { - String type = section.getString("type"); - if (type == null) return null; - switch (type) { - case "weight-mod" -> { - var modList = ConfigUtils.getModifiers(section.getStringList("value")); - return ((effect, condition) -> { - effect.addWeightModifier(modList); - }); - } - case "weight-mod-ignore-conditions" -> { - var modList = ConfigUtils.getModifiers(section.getStringList("value")); - return ((effect, condition) -> { - effect.addWeightModifierIgnored(modList); - }); - } - case "group-mod" -> { - var modList = getGroupModifiers(section.getStringList("value")); - return ((effect, condition) -> { - effect.addWeightModifier(modList); - }); - } - case "group-mod-ignore-conditions" -> { - var modList = getGroupModifiers(section.getStringList("value")); - return ((effect, condition) -> { - effect.addWeightModifierIgnored(modList); - }); - } - case "wait-time" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setWaitTime(effect.waitTimeAdder() + value.get(condition.getPlayer(), condition.getArgs())); - }); - } - case "hook-time", "wait-time-multiplier" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setWaitTimeMultiplier(effect.getWaitTimeMultiplier() + value.get(condition.getPlayer(), condition.getArgs()) - 1); - }); - } - case "difficulty" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setDifficulty(effect.difficultyAdder() + value.get(condition.getPlayer(), condition.getArgs())); - }); - } - case "difficulty-multiplier", "difficulty-bonus" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setDifficultyMultiplier(effect.difficultyMultiplier() + value.get(condition.getPlayer(), condition.getArgs()) - 1); - }); - } - case "multiple-loot" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setMultipleLootChance(effect.multipleLootChance() + value.get(condition.getPlayer(), condition.getArgs())); - }); - } - case "score" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setScore(effect.scoreAdder() + value.get(condition.getPlayer(), condition.getArgs())); - }); - } - case "score-bonus", "score-multiplier" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setScoreMultiplier(effect.scoreMultiplier() + value.get(condition.getPlayer(), condition.getArgs()) - 1); - }); - } - case "size" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setSize(effect.sizeAdder() + value.get(condition.getPlayer(), condition.getArgs())); - }); - } - case "size-bonus", "size-multiplier" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setSizeMultiplier(effect.sizeMultiplier() + value.get(condition.getPlayer(), condition.getArgs()) - 1); - }); - } - case "game-time" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setGameTime(effect.gameTimeAdder() + value.get(condition.getPlayer(), condition.getArgs())); - }); - } - case "game-time-bonus", "game-time-multiplier" -> { - var value = ConfigUtils.getValue(section.get("value")); - return ((effect, condition) -> { - effect.setGameTimeMultiplier(effect.gameTimeMultiplier() + value.get(condition.getPlayer(), condition.getArgs()) - 1); - }); - } - case "lava-fishing" -> { - return ((effect, condition) -> effect.setLavaFishing(true)); - } - case "conditional" -> { - Requirement[] requirements = plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("conditions"), true); - EffectModifier[] modifiers = getEffectModifiers(section.getConfigurationSection("effects")); - return ((effect, condition) -> { - for (Requirement requirement : requirements) - if (!requirement.check(condition)) - return; - for (EffectModifier modifier : modifiers) { - modifier.modify(effect, condition); - } - }); - } - default -> { - LogUtils.warn("Effect " + type + " doesn't exist."); - return null; - } - } + public Optional getEffectModifier(Key key) { + return Optional.ofNullable(this.effectModifiers.get(key)); } } 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 00e744fd..332b5731 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 @@ -19,162 +19,98 @@ package net.momirealms.customfishing.bukkit.entity; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.integration.EntityProvider; -import net.momirealms.customfishing.api.mechanic.entity.EntityConfigImpl; +import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.api.mechanic.context.ContextKeys; +import net.momirealms.customfishing.api.mechanic.entity.EntityConfig; import net.momirealms.customfishing.api.mechanic.entity.EntityManager; -import net.momirealms.customfishing.api.mechanic.loot.Loot; -import net.momirealms.customfishing.bukkit.compatibility.entity.VanillaEntityProvider; import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.util.*; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +import static java.util.Objects.requireNonNull; public class BukkitEntityManager implements EntityManager { private final BukkitCustomFishingPlugin plugin; - private final HashMap entityLibraryMap; - private final HashMap entityConfigMap; + private final HashMap entityProviders = new HashMap<>(); + private final HashMap entities = new HashMap<>(); public BukkitEntityManager(BukkitCustomFishingPlugin plugin) { this.plugin = plugin; - this.entityLibraryMap = new HashMap<>(); - this.entityConfigMap = new HashMap<>(); - this.registerEntityProvider(new VanillaEntityProvider()); - } - - public void load() { - this.loadConfig(); - } - - public void unload() { - HashMap tempMap = new HashMap<>(this.entityConfigMap); - this.entityConfigMap.clear(); - for (Map.Entry entry : tempMap.entrySet()) { - if (entry.getValue().isPersist()) { - tempMap.put(entry.getKey(), entry.getValue()); + this.registerEntityProvider(new EntityProvider() { + @Override + public String identifier() { + return "vanilla"; } - } + @NotNull + @Override + public Entity spawn(@NotNull Location location, @NotNull String id, @NotNull Map propertyMap) { + return location.getWorld().spawnEntity(location, EntityType.valueOf(id.toUpperCase(Locale.ENGLISH))); + } + }); } - /** - * Registers an entity library for use in the plugin. - * - * @param entityProvider The entity library to register. - * @return {@code true} if the entity library was successfully registered, {@code false} if it already exists. - */ @Override - public boolean registerEntityProvider(EntityProvider entityProvider) { - if (entityLibraryMap.containsKey(entityProvider.identifier())) return false; - else entityLibraryMap.put(entityProvider.identifier(), entityProvider); + public void unload() { + this.entities.clear(); + } + + @Override + public void disable() { + unload(); + this.entityProviders.clear(); + } + + @Override + public Optional getEntity(String id) { + return Optional.ofNullable(this.entities.get(id)); + } + + @Override + public boolean registerEntity(String id, EntityConfig entity) { + if (entities.containsKey(id)) return false; + this.entities.put(id, entity); return true; } - /** - * Unregisters an entity library by its identification key. - * - * @param identification The identification key of the entity library to unregister. - * @return {@code true} if the entity library was successfully unregistered, {@code false} if it does not exist. - */ + public boolean registerEntityProvider(EntityProvider entityProvider) { + if (entityProviders.containsKey(entityProvider.identifier())) return false; + else entityProviders.put(entityProvider.identifier(), entityProvider); + return true; + } + + public boolean unregisterEntityProvider(String id) { + return entityProviders.remove(id) != null; + } + + @Nullable @Override - public boolean unregisterEntityProvider(String identification) { - return entityLibraryMap.remove(identification) != null; - } - - /** - * Load configuration files for entity properties. - */ - @SuppressWarnings("DuplicatedCode") - private void loadConfig() { - Deque fileDeque = new ArrayDeque<>(); - for (String type : List.of("entity")) { - File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type); - if (!typeFolder.exists()) { - if (!typeFolder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false); - } - fileDeque.push(typeFolder); - while (!fileDeque.isEmpty()) { - File file = fileDeque.pop(); - File[] files = file.listFiles(); - if (files == null) continue; - for (File subFile : files) { - if (subFile.isDirectory()) { - fileDeque.push(subFile); - } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) { - this.loadSingleFile(subFile); - } - } - } - } - } - - /** - * Load a single entity configuration file. - * - * @param file The YAML file to load. - */ - private void loadSingleFile(File file) { - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (Map.Entry entry : config.getValues(false).entrySet()) { - if (entry.getValue() instanceof ConfigurationSection section) { - String entityID = section.getString("entity"); - if (entityID == null) { - LogUtils.warn("Entity can't be null. File:" + file.getAbsolutePath() + "; Section:" + section.getCurrentPath()); - continue; - } - HashMap propertyMap = new HashMap<>(); - ConfigurationSection property = section.getConfigurationSection("properties"); - if (property != null) { - propertyMap.putAll(property.getValues(false)); - } - EntityConfigImpl entityConfigImpl = new EntityConfigImpl.BuilderImpl() - .entityID(entityID) - .persist(false) - .horizontalVector(section.getDouble("velocity.horizontal", 1.1)) - .verticalVector(section.getDouble("velocity.vertical", 1.2)) - .propertyMap(propertyMap) - .build(); - entityConfigMap.put(entry.getKey(), entityConfigImpl); - } - } - } - - public void disable() { - unload(); - this.entityConfigMap.clear(); - this.entityLibraryMap.clear(); - } - - /** - * Summons an entity based on the given loot configuration to a specified location. - * - * @param hookLocation The location where the entity will be summoned, typically where the fishing hook is. - * @param playerLocation The location of the player who triggered the entity summoning. - * @param loot The loot configuration that defines the entity to be summoned. - */ - @Override - public void summonEntity(Location hookLocation, Location playerLocation, Loot loot) { - EntityConfigImpl config = entityConfigMap.get(loot.getID()); - if (config == null) { - LogUtils.warn("Entity: " + loot.getID() + " doesn't exist."); - return; - } + public Entity summonEntityLoot(Context context) { + String id = context.arg(ContextKeys.ID); + EntityConfig config = requireNonNull(entities.get(id), "Entity " + id + " not found"); + Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)); + Location playerLocation = requireNonNull(context.getHolder().getLocation()); String entityID = config.getEntityID(); Entity entity; if (entityID.contains(":")) { String[] split = entityID.split(":", 2); - String identification = split[0]; - String id = split[1]; - EntityProvider library = entityLibraryMap.get(identification); - entity = library.spawn(hookLocation, id, config.getPropertyMap()); + EntityProvider provider = requireNonNull(entityProviders.get(split[0]), "EntityProvider " + split[0] + " doesn't exist"); + entity = requireNonNull(provider.spawn(hookLocation, split[1], config.getPropertyMap()), "Entity " + entityID + " doesn't exist"); } else { - entity = entityLibraryMap.get("vanilla").spawn(hookLocation, entityID, config.getPropertyMap()); + entity = entityProviders.get("vanilla").spawn(hookLocation, entityID, config.getPropertyMap()); } Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1); vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector()); 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 53c0de5d..d32afe46 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 @@ -1,32 +1,73 @@ package net.momirealms.customfishing.bukkit.event; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.event.EventCarrier; import net.momirealms.customfishing.api.mechanic.event.EventManager; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; import java.util.HashMap; import java.util.Optional; -public class BukkitEventManager implements EventManager { +public class BukkitEventManager implements EventManager, Listener { - private final HashMap carrierMap = new HashMap<>(); - private BukkitCustomFishingPlugin plugin; + private final HashMap carriers = new HashMap<>(); + private final BukkitCustomFishingPlugin plugin; public BukkitEventManager(BukkitCustomFishingPlugin plugin) { this.plugin = plugin; } + @Override + public void unload() { + this.carriers.clear(); + HandlerList.unregisterAll(this); + } + + @Override + public void load() { + Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap()); + } + @Override public Optional getEventCarrier(String id) { - return Optional.ofNullable(carrierMap.get(id)); + return Optional.ofNullable(carriers.get(id)); } @Override public boolean registerEventCarrier(String id, EventCarrier carrier) { - if (carrierMap.containsKey(id)) { - return false; - } - carrierMap.put(id, carrier); + if (carriers.containsKey(id)) return false; + carriers.put(id, carrier); return true; } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + if (event.getHand() != EquipmentSlot.HAND) + return; + if (event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_AIR && event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK) + return; + 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 -> { + carrier.trigger(Context.player(event.getPlayer()), ActionTrigger.INTERACT); + }); + } + + @EventHandler (ignoreCancelled = true) + public void onConsumeItem(PlayerItemConsumeEvent event) { + Optional.ofNullable(carriers.get(plugin.getItemManager().getItemID(event.getItem()))) + .ifPresent(carrier -> carrier.trigger(Context.player(event.getPlayer()), ActionTrigger.CONSUME)); + } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BaitAnimationTask.java b/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BaitAnimationTask.java deleted file mode 100644 index 736c1da6..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BaitAnimationTask.java +++ /dev/null @@ -1,84 +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.bukkit.fishing; - -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.scheduler.CancellableTask; -import net.momirealms.customfishing.bukkit.util.FakeItemUtils; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; - -/** - * A task responsible for animating bait when it's attached to a fishing hook. - */ -public class BaitAnimationTask implements Runnable { - - private final CancellableTask cancellableTask; - private final int entityID; - private final Player player; - private final FishHook fishHook; - - /** - * Constructs a new BaitAnimationTask. - * - * @param plugin The CustomFishingPlugin instance. - * @param player The player who cast the fishing rod. - * @param fishHook The FishHook entity. - * @param baitItem The bait ItemStack. - */ - public BaitAnimationTask(BukkitCustomFishingPlugin plugin, Player player, FishHook fishHook, ItemStack baitItem) { - this.player = player; - this.fishHook = fishHook; - entityID = ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE); - if (plugin.getVersionManager().isVersionNewerThan1_19_4()) { - BukkitCustomFishingPluginImpl.sendPackets(player, FakeItemUtils.getSpawnPacket(entityID, fishHook.getLocation()), FakeItemUtils.getMetaPacket(entityID, baitItem)); - } else { - BukkitCustomFishingPluginImpl.sendPacket(player, FakeItemUtils.getSpawnPacket(entityID, fishHook.getLocation())); - BukkitCustomFishingPluginImpl.sendPacket(player, FakeItemUtils.getMetaPacket(entityID, baitItem)); - } - this.cancellableTask = plugin.getScheduler().runTaskAsyncTimer(this, 50, 50, TimeUnit.MILLISECONDS); - } - - @Override - public void run() { - if ( fishHook == null - || fishHook.isOnGround() - || fishHook.isInLava() - || fishHook.isInWater() - || !fishHook.isValid() - ) { - cancelAnimation(); - } else { - BukkitCustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getVelocityPacket(entityID, fishHook.getVelocity())); - BukkitCustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getTpPacket(entityID, fishHook.getLocation())); - } - } - - /** - * Cancels the bait animation and cleans up resources. - */ - private void cancelAnimation() { - cancellableTask.cancel(); - BukkitCustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getDestroyPacket(entityID)); - } -} 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 deleted file mode 100644 index 2016da5d..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/BukkitFishingManager.java +++ /dev/null @@ -1,872 +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.bukkit.fishing; - -import com.destroystokyo.paper.event.player.PlayerJumpEvent; -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; -import net.momirealms.customfishing.api.common.Pair; -import net.momirealms.customfishing.api.event.FishingResultEvent; -import net.momirealms.customfishing.api.event.LavaFishingEvent; -import net.momirealms.customfishing.api.event.RodCastEvent; -import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; -import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; -import net.momirealms.customfishing.api.mechanic.effect.Effect; -import net.momirealms.customfishing.api.mechanic.fishing.FishingManager; -import net.momirealms.customfishing.api.mechanic.game.BasicGameConfig; -import net.momirealms.customfishing.api.mechanic.game.GameInstance; -import net.momirealms.customfishing.api.mechanic.game.GameSettings; -import net.momirealms.customfishing.api.mechanic.game.GamingPlayer; -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.api.util.WeightUtils; -import net.momirealms.customfishing.bukkit.util.ItemUtils; -import org.bukkit.*; -import org.bukkit.entity.*; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.*; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.persistence.PersistentDataType; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class BukkitFishingManager implements Listener, FishingManager { - - private final BukkitCustomFishingPluginImpl plugin; - private final ConcurrentHashMap hookCacheMap; - private final ConcurrentHashMap hookCheckMap; - private final ConcurrentHashMap tempFishingStateMap; - private final ConcurrentHashMap gamingPlayerMap; - private final ConcurrentHashMap> vanillaLootMap; - - public BukkitFishingManager(BukkitCustomFishingPluginImpl plugin) { - this.plugin = plugin; - this.hookCacheMap = new ConcurrentHashMap<>(); - this.tempFishingStateMap = new ConcurrentHashMap<>(); - this.gamingPlayerMap = new ConcurrentHashMap<>(); - this.hookCheckMap = new ConcurrentHashMap<>(); - this.vanillaLootMap = new ConcurrentHashMap<>(); - } - - public void load() { - Bukkit.getPluginManager().registerEvents(this, plugin); - } - - public void unload() { - HandlerList.unregisterAll(this); - for (FishHook hook : hookCacheMap.values()) { - hook.remove(); - } - for (HookCheckTimerTask task : hookCheckMap.values()) { - task.destroy(); - } - for (GamingPlayer gamingPlayer : gamingPlayerMap.values()) { - gamingPlayer.cancel(); - } - this.hookCacheMap.clear(); - this.tempFishingStateMap.clear(); - this.gamingPlayerMap.clear(); - this.hookCheckMap.clear(); - } - - public void disable() { - unload(); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onFishMONITOR(PlayerFishEvent event) { - if (CFConfig.eventPriority != EventPriority.MONITOR) return; - this.selectState(event); - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onFishHIGHEST(PlayerFishEvent event) { - if (CFConfig.eventPriority != EventPriority.HIGHEST) return; - this.selectState(event); - } - - @EventHandler(priority = EventPriority.HIGH) - public void onFishHIGH(PlayerFishEvent event) { - if (CFConfig.eventPriority != EventPriority.HIGH) return; - this.selectState(event); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onFishNORMAL(PlayerFishEvent event) { - if (CFConfig.eventPriority != EventPriority.NORMAL) return; - this.selectState(event); - } - - @EventHandler(priority = EventPriority.LOW) - public void onFishLOW(PlayerFishEvent event) { - if (CFConfig.eventPriority != EventPriority.LOW) return; - this.selectState(event); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onFishLOWEST(PlayerFishEvent event) { - if (CFConfig.eventPriority != EventPriority.LOWEST) return; - this.selectState(event); - } - - @EventHandler - public void onQuit(PlayerQuitEvent event) { - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - this.removeHook(uuid); - this.removeTempFishingState(player); - this.removeHookCheckTask(player); - this.vanillaLootMap.remove(uuid); - GamingPlayer gamingPlayer = gamingPlayerMap.remove(player.getUniqueId()); - if (gamingPlayer != null) { - gamingPlayer.cancel(); - } - } - - /** - * Known bug: This is a Minecraft packet limitation - * When you fish, both left click air and right click air - * are triggered. And you can't cancel the left click event. - */ - @EventHandler (ignoreCancelled = false) - public void onLeftClick(PlayerInteractEvent event) { - if (event.getAction() != Action.LEFT_CLICK_AIR) - return; - if (event.getMaterial() != Material.FISHING_ROD) - return; - if (event.getHand() != EquipmentSlot.HAND) - return; - GamingPlayer gamingPlayer = gamingPlayerMap.get(event.getPlayer().getUniqueId()); - if (gamingPlayer != null) { - if (gamingPlayer.onLeftClick()) - event.setCancelled(true); - } - } - - @EventHandler (ignoreCancelled = true) - public void onSwapHand(PlayerSwapHandItemsEvent event) { - GamingPlayer gamingPlayer = gamingPlayerMap.get(event.getPlayer().getUniqueId()); - if (gamingPlayer != null) { - if (gamingPlayer.onSwapHand()) - event.setCancelled(true); - } - } - - @EventHandler - public void onJump(PlayerJumpEvent event) { - if (event.isCancelled()) return; - GamingPlayer gamingPlayer = gamingPlayerMap.get(event.getPlayer().getUniqueId()); - if (gamingPlayer != null) { - if (gamingPlayer.onJump()) - event.setCancelled(true); - } - } - - @EventHandler - public void onSneak(PlayerToggleSneakEvent event) { - if (event.isCancelled()) return; - if (!event.isSneaking()) return; - GamingPlayer gamingPlayer = gamingPlayerMap.get(event.getPlayer().getUniqueId()); - if (gamingPlayer != null) { - if (gamingPlayer.onSneak()) - event.setCancelled(true); - } - } - - @EventHandler - public void onChat(AsyncPlayerChatEvent event) { - if (event.isCancelled()) return; - GamingPlayer gamingPlayer = gamingPlayerMap.get(event.getPlayer().getUniqueId()); - if (gamingPlayer != null) { - if (gamingPlayer.onChat(event.getMessage())) - event.setCancelled(true); - } - } - - /** - * Removes a fishing hook entity associated with a given UUID. - * - * @param uuid The UUID of the fishing hook entity to be removed. - * @return {@code true} if the fishing hook was successfully removed, {@code false} otherwise. - */ - @Override - public boolean removeHook(UUID uuid) { - FishHook hook = hookCacheMap.remove(uuid); - if (hook != null && hook.isValid()) { - plugin.getScheduler().runTaskSync(hook::remove, hook.getLocation()); - return true; - } else { - return false; - } - } - - /** - * Retrieves a FishHook object associated with the provided player's UUID - * - * @param uuid The UUID of the player - * @return fishhook entity, null if not exists - */ - @Override - @Nullable - public FishHook getHook(UUID uuid) { - FishHook fishHook = hookCacheMap.get(uuid); - if (fishHook != null) { - if (!fishHook.isValid()) { - hookCacheMap.remove(uuid); - return null; - } else { - return fishHook; - } - } - return null; - } - - /** - * Selects the appropriate fishing state based on the provided PlayerFishEvent and triggers the corresponding action. - * - * @param event The PlayerFishEvent that represents the fishing action. - */ - public void selectState(PlayerFishEvent event) { - if (event.isCancelled()) return; - switch (event.getState()) { - case FISHING -> onCastRod(event); - case REEL_IN -> onReelIn(event); - case CAUGHT_ENTITY -> onCaughtEntity(event); - case CAUGHT_FISH -> onCaughtFish(event); - case BITE -> onBite(event); - case IN_GROUND -> onInGround(event); - } - } - - /** - * Handle the event when the fishing hook lands on the ground. - * - * @param event The PlayerFishEvent that occurred. - */ - private void onInGround(PlayerFishEvent event) { - final Player player = event.getPlayer(); - FishHook hook = event.getHook(); - if (player.getGameMode() != GameMode.CREATIVE) { - ItemStack itemStack = player.getInventory().getItemInMainHand(); - if (itemStack.getType() != Material.FISHING_ROD) itemStack = player.getInventory().getItemInOffHand(); - if (itemStack.getType() == Material.FISHING_ROD) { - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound compound = nbtItem.getCompound("CustomFishing"); - if (compound != null && compound.hasTag("max_dur")) { - event.setCancelled(true); - hook.remove(); - ItemUtils.decreaseDurability(player, itemStack, 2, true); - } - } - } - } - - /** - * Handle the event when a player casts a fishing rod. - * - * @param event The PlayerFishEvent that occurred. - */ - public void onCastRod(PlayerFishEvent event) { - var player = event.getPlayer(); - var fishingPreparation = new FishingPreparationImpl(player, plugin); - if (!fishingPreparation.canFish()) { - event.setCancelled(true); - return; - } - // Check mechanic requirements - if (!RequirementManager.isRequirementMet( - fishingPreparation, RequirementManagerImpl.mechanicRequirements - )) { - this.removeTempFishingState(player); - return; - } - FishingEffect initialEffect = plugin.getEffectManager().getInitialEffect(); - // Merge totem effects - EffectCarrier totemEffect = plugin.getTotemManager().getTotemEffect(player.getLocation()); - if (totemEffect != null) - for (EffectModifier modifier : totemEffect.getEffectModifiers()) { - modifier.modify(initialEffect, fishingPreparation); - } - - // Call custom event - RodCastEvent rodCastEvent = new RodCastEvent(event, fishingPreparation, initialEffect); - Bukkit.getPluginManager().callEvent(rodCastEvent); - if (rodCastEvent.isCancelled()) { - return; - } - - // Store fishhook entity and apply the effects - final FishHook fishHook = event.getHook(); - this.hookCacheMap.put(player.getUniqueId(), fishHook); - - // Reduce amount & Send animation - var baitItem = fishingPreparation.getBaitItemStack(); - if (baitItem != null) { - ItemStack cloned = baitItem.clone(); - cloned.setAmount(1); - new BaitAnimationTask(plugin, player, fishHook, cloned); - baitItem.setAmount(baitItem.getAmount() - 1); - } - - // Arrange hook check task - this.hookCheckMap.put(player.getUniqueId(), new HookCheckTimerTask(this, fishHook, fishingPreparation, initialEffect)); - // trigger actions - fishingPreparation.triggerActions(ActionTrigger.CAST); - } - - /** - * Handle the event when a player catches an entity. - * - * @param event The PlayerFishEvent that occurred. - */ - private void onCaughtEntity(PlayerFishEvent event) { - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - - Entity entity = event.getCaught(); - if ((entity instanceof ArmorStand armorStand) - && armorStand.getPersistentDataContainer().get( - Objects.requireNonNull(NamespacedKey.fromString("lavafishing", plugin)), - PersistentDataType.STRING - ) != null) { - // The hook is hooked into the temp entity - // This might be called both not in game and in game - LavaFishingEvent lavaFishingEvent = new LavaFishingEvent(player, LavaFishingEvent.State.REEL_IN, event.getHook()); - Bukkit.getPluginManager().callEvent(lavaFishingEvent); - if (lavaFishingEvent.isCancelled()) { - event.setCancelled(true); - return; - } - - GamingPlayer gamingPlayer = gamingPlayerMap.get(uuid); - if (gamingPlayer != null) { - // in game - if (gamingPlayer.onRightClick()) - event.setCancelled(true); - } else { - // not in game - HookCheckTimerTask task = hookCheckMap.get(uuid); - if (task != null) - task.destroy(); - else - // should not reach this but in case - entity.remove(); - } - return; - } - - if (player.getGameMode() != GameMode.CREATIVE) { - ItemStack itemStack = player.getInventory().getItemInMainHand(); - if (itemStack.getType() != Material.FISHING_ROD) itemStack = player.getInventory().getItemInOffHand(); - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound != null && nbtCompound.hasTag("max_dur")) { - event.getHook().remove(); - event.setCancelled(true); - ItemUtils.decreaseDurability(player, itemStack, 5, true); - } - } - } - - /** - * Handle the event when a player catches a fish. - * - * @param event The PlayerFishEvent that occurred. - */ - private void onCaughtFish(PlayerFishEvent event) { - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - if (!(event.getCaught() instanceof Item item)) - return; - - // If player is playing the game - GamingPlayer gamingPlayer = gamingPlayerMap.get(uuid); - if (gamingPlayer != null) { - if (gamingPlayer.onRightClick()) - event.setCancelled(true); - return; - } - - // If player is not playing the game - var temp = this.getTempFishingState(uuid); - if (temp != null) { - var loot = temp.getLoot(); - if (loot.getID().equals("vanilla")) { - // put vanilla loot in map - this.vanillaLootMap.put(uuid, Pair.of(item.getItemStack(), event.getExpToDrop())); - } - var fishingPreparation = temp.getPreparation(); - loot.triggerActions(ActionTrigger.HOOK, fishingPreparation); - fishingPreparation.triggerActions(ActionTrigger.HOOK); - if (!loot.disableGame()) { - // start the game if the loot has a game - if (startFishingGame(player, fishingPreparation, temp.getEffect())) { - event.setCancelled(true); - } - } else { - // remove temp state if fishing game not exists - this.removeTempFishingState(player); - var hook = event.getHook(); - // If the game is disabled, then do success actions - success(temp, hook); - // Cancel the event because loots can be multiple and unique - event.setCancelled(true); - hook.remove(); - } - return; - } - } - - /** - * Handle the event when a player receives a bite on their fishing hook. - * - * @param event The PlayerFishEvent that occurred. - */ - private void onBite(PlayerFishEvent event) { - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - - // If player is already in game - // then ignore the event - GamingPlayer gamingPlayer = getGamingPlayer(uuid); - if (gamingPlayer != null) { - return; - } - - // If the loot's game is instant - TempFishingState temp = getTempFishingState(uuid); - if (temp != null) { - var loot = temp.getLoot(); - var fishingPreparation = temp.getPreparation(); - fishingPreparation.setLocation(event.getHook().getLocation()); - - if (!loot.disableGlobalAction()) - GlobalSettings.triggerLootActions(ActionTrigger.BITE, fishingPreparation); - loot.triggerActions(ActionTrigger.BITE, fishingPreparation); - fishingPreparation.triggerActions(ActionTrigger.BITE); - - if (loot.instantGame() && !loot.disableGame()) { - if (!loot.disableGlobalAction()) - GlobalSettings.triggerLootActions(ActionTrigger.HOOK, fishingPreparation); - loot.triggerActions(ActionTrigger.HOOK, fishingPreparation); - fishingPreparation.triggerActions(ActionTrigger.HOOK); - startFishingGame(player, fishingPreparation, temp.getEffect()); - } - } - } - - /** - * Handle the event when a player reels in their fishing line. - * - * @param event The PlayerFishEvent that occurred. - */ - private void onReelIn(PlayerFishEvent event) { - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - - // If player is in game - GamingPlayer gamingPlayer = getGamingPlayer(uuid); - if (gamingPlayer != null) { - if (gamingPlayer.onRightClick()) - event.setCancelled(true); - return; - } - - // If player is lava fishing - HookCheckTimerTask hookTask = hookCheckMap.get(uuid); - if (hookTask != null && hookTask.isFishHooked()) { - LavaFishingEvent lavaFishingEvent = new LavaFishingEvent(player, LavaFishingEvent.State.CAUGHT_FISH, event.getHook()); - Bukkit.getPluginManager().callEvent(lavaFishingEvent); - if (lavaFishingEvent.isCancelled()) { - event.setCancelled(true); - return; - } - - var temp = getTempFishingState(uuid); - if (temp != null ) { - Loot loot = temp.getLoot(); - var fishingPreparation = temp.getPreparation(); - if (!loot.disableGlobalAction()) - GlobalSettings.triggerLootActions(ActionTrigger.HOOK, fishingPreparation); - loot.triggerActions(ActionTrigger.HOOK, fishingPreparation); - fishingPreparation.triggerActions(ActionTrigger.HOOK); - if (!loot.disableGame()) { - event.setCancelled(true); - startFishingGame(player, fishingPreparation, temp.getEffect()); - } else { - success(temp, event.getHook()); - } - } - return; - } - } - - /** - * Removes the temporary fishing state associated with a player. - * - * @param player The player whose temporary fishing state should be removed. - */ - @Override - public TempFishingState removeTempFishingState(Player player) { - return this.tempFishingStateMap.remove(player.getUniqueId()); - } - - /** - * Processes the game result for a gaming player - * - * @param gamingPlayer The gaming player whose game result should be processed. - */ - @Override - public void processGameResult(GamingPlayer gamingPlayer) { - final Player player = gamingPlayer.getPlayer(); - final UUID uuid = player.getUniqueId(); - FishHook fishHook = hookCacheMap.remove(uuid); - if (fishHook == null) { - LogUtils.warn("Unexpected situation: Can't get player's fish hook when processing game results."); - return; - } - TempFishingState tempFishingState = removeTempFishingState(player); - if (tempFishingState == null) { - LogUtils.warn("Unexpected situation: Can't get player's fishing state when processing game results."); - return; - } - Effect bonus = gamingPlayer.getEffectReward(); - if (bonus != null) - tempFishingState.getEffect().merge(bonus); - - gamingPlayer.cancel(); - gamingPlayerMap.remove(uuid); - plugin.getScheduler().runTaskSync(() -> { - - if (gamingPlayer.isSuccessful()) { - success(tempFishingState, fishHook); - } else { - fail(tempFishingState, fishHook); - } - - fishHook.remove(); - - }, fishHook.getLocation()); - } - - public void fail(TempFishingState state, FishHook hook) { - var loot = state.getLoot(); - var fishingPreparation = state.getPreparation(); - - if (loot.getID().equals("vanilla")) { - Pair pair = this.vanillaLootMap.remove(fishingPreparation.getPlayer().getUniqueId()); - if (pair != null) { - fishingPreparation.insertArg("{nick}", ""); - fishingPreparation.insertArg("{loot}", pair.left().getType().toString()); - } - } - - // call event - FishingResultEvent fishingResultEvent = new FishingResultEvent( - fishingPreparation.getPlayer(), - FishingResultEvent.Result.FAILURE, - hook, - loot, - fishingPreparation.getArgs() - ); - Bukkit.getPluginManager().callEvent(fishingResultEvent); - if (fishingResultEvent.isCancelled()) { - return; - } - - if (!loot.disableGlobalAction()) - GlobalSettings.triggerLootActions(ActionTrigger.FAILURE, fishingPreparation); - loot.triggerActions(ActionTrigger.FAILURE, fishingPreparation); - fishingPreparation.triggerActions(ActionTrigger.FAILURE); - - if (state.getPreparation().getPlayer().getGameMode() != GameMode.CREATIVE) { - ItemUtils.decreaseHookDurability(fishingPreparation.getRodItemStack(), 1, true); - } - } - - /** - * Handle the success of a fishing attempt, including spawning loot, calling events, and executing success actions. - * - * @param state The temporary fishing state containing information about the loot and effect. - * @param hook The FishHook entity associated with the fishing attempt. - */ - public void success(TempFishingState state, FishHook hook) { - var loot = state.getLoot(); - var effect = state.getEffect(); - var fishingPreparation = state.getPreparation(); - var player = fishingPreparation.getPlayer(); - fishingPreparation.insertArg("{size-multiplier}", String.valueOf(effect.sizeMultiplier())); - fishingPreparation.insertArg("{size-fixed}", String.valueOf(effect.sizeAdder())); - int amount; - if (loot.getType() == LootType.ITEM) { - amount = (int) effect.multipleLootChance(); - amount += Math.random() < (effect.multipleLootChance() - amount) ? 2 : 1; - } else { - amount = 1; - } - fishingPreparation.insertArg("{amount}", String.valueOf(amount)); - - // call event - FishingResultEvent fishingResultEvent = new FishingResultEvent( - player, - FishingResultEvent.Result.SUCCESS, - hook, - loot, - fishingPreparation.getArgs() - ); - Bukkit.getPluginManager().callEvent(fishingResultEvent); - if (fishingResultEvent.isCancelled()) { - return; - } - - switch (loot.getType()) { - case ITEM -> { - // build the items for multiple times instead of using setAmount() to make sure that each item is unique - if (loot.getID().equals("vanilla")) { - Pair pair = vanillaLootMap.remove(player.getUniqueId()); - if (pair != null) { - fishingPreparation.insertArg("{nick}", ""); - for (int i = 0; i < amount; i++) { - plugin.getScheduler().runTaskSyncLater(() -> { - plugin.getItemManager().dropItem(player, hook.getLocation(), player.getLocation(), pair.left().clone(), fishingPreparation); - doSuccessActions(loot, effect, fishingPreparation, player); - if (pair.right() > 0) { - player.giveExp(pair.right(), true); - AdventureHelper.getInstance().sendSound(player, Sound.Source.PLAYER, Key.key("minecraft:entity.experience_orb.pickup"), 1, 1); - } - }, hook.getLocation(), (long) CFConfig.multipleLootSpawnDelay * i); - } - } - } else { - for (int i = 0; i < amount; i++) { - plugin.getScheduler().runTaskSyncLater(() -> { - ItemStack item = plugin.getItemManager().buildInternal(player, "item", loot.getID(), fishingPreparation.getArgs()); - if (item == null) { - LogUtils.warn(String.format("Item %s not exists", loot.getID())); - return; - } - plugin.getItemManager().dropItem(player, hook.getLocation(), player.getLocation(), item, fishingPreparation); - doSuccessActions(loot, effect, fishingPreparation, player); - }, hook.getLocation(), (long) CFConfig.multipleLootSpawnDelay * i); - } - } - } - case ENTITY -> { - plugin.getEntityManager().summonEntity(hook.getLocation(), player.getLocation(), loot); - doSuccessActions(loot, effect, fishingPreparation, player); - } - case BLOCK -> { - plugin.getBlockManager().summonBlock(player, hook.getLocation(), player.getLocation(), loot); - doSuccessActions(loot, effect, fishingPreparation, player); - } - } - - if (player.getGameMode() != GameMode.CREATIVE) { - ItemStack rod = state.getPreparation().getRodItemStack(); - ItemUtils.decreaseHookDurability(rod, 1, false); - ItemUtils.decreaseDurability(player, rod, 1, true); - } - } - - /** - * Execute success-related actions after a successful fishing attempt, including updating competition data, triggering events and actions, and updating player statistics. - * - * @param loot The loot that was successfully caught. - * @param effect The effect applied during fishing. - * @param fishingPreparation The fishing preparation containing preparation data. - * @param player The player who successfully caught the loot. - */ - private void doSuccessActions(Loot loot, Effect effect, FishingPreparation fishingPreparation, Player player) { - FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition(); - if (competition != null && RequirementManager.isRequirementMet(fishingPreparation, competition.getConfig().getJoinRequirements())) { - String scoreStr = fishingPreparation.getArg("{CUSTOM_SCORE}"); - if (scoreStr != null) { - competition.refreshData(player, Double.parseDouble(scoreStr)); - } else { - double score = 0; - switch (competition.getGoal()) { - case CATCH_AMOUNT -> { - score = 1; - competition.refreshData(player, score); - } - case MAX_SIZE, TOTAL_SIZE -> { - String size = fishingPreparation.getArg("{SIZE}"); - if (size != null) { - score = Double.parseDouble(size); - competition.refreshData(player, score); - } else { - score = 0; - } - } - case TOTAL_SCORE -> { - score = loot.getScore(); - if (score > 0) { - score = score * effect.scoreMultiplier() + effect.scoreAdder(); - competition.refreshData(player, score); - } else { - score = 0; - } - } - } - fishingPreparation.insertArg("{score}", String.format("%.2f", score)); - fishingPreparation.insertArg("{SCORE}", String.valueOf(score)); - } - } - - // events and actions - if (!loot.disableGlobalAction()) - GlobalSettings.triggerLootActions(ActionTrigger.SUCCESS, fishingPreparation); - loot.triggerActions(ActionTrigger.SUCCESS, fishingPreparation); - fishingPreparation.triggerActions(ActionTrigger.SUCCESS); - - player.setStatistic( - Statistic.FISH_CAUGHT, - player.getStatistic(Statistic.FISH_CAUGHT) + 1 - ); - - if (!loot.disableStats()) - Optional.ofNullable( - plugin.getStatisticsManager() - .getStatistics(player.getUniqueId()) - ).ifPresent(it -> { - it.addLootAmount(loot, fishingPreparation, 1); - String size = fishingPreparation.getArg("{SIZE}"); - if (size != null) - if (it.setSizeIfHigher(loot.getStatisticKey().sizeKey(), Float.parseFloat(size))) { - if (!loot.disableGlobalAction()) - GlobalSettings.triggerLootActions(ActionTrigger.NEW_SIZE_RECORD, fishingPreparation); - loot.triggerActions(ActionTrigger.NEW_SIZE_RECORD, fishingPreparation); - } - }); - } - - /** - * Starts a fishing game for the specified player with the given condition and effect. - * - * @param player The player starting the fishing game. - * @param playerContext The condition used to determine the game. - * @param effect The effect applied to the game. - */ - @Override - public boolean startFishingGame(Player player, PlayerContext playerContext, Effect effect) { - Map gameWithWeight = plugin.getGameManager().getGameWithWeight(playerContext); - String random = WeightUtils.getRandom(gameWithWeight); - Pair gamePair = plugin.getGameManager().getGameInstance(random); - if (random == null) { - LogUtils.warn("No game is available for player:" + player.getName() + " location:" + playerContext.getLocation()); - return false; - } - if (gamePair == null) { - LogUtils.warn(String.format("Game %s doesn't exist.", random)); - return false; - } - plugin.debug("Game: " + random); - return startFishingGame(player, Objects.requireNonNull(gamePair.left().getGameSetting(effect)), gamePair.right()); - } - - /** - * Starts a fishing game for the specified player with the given settings and game instance. - * - * @param player The player starting the fishing game. - * @param settings The game settings for the fishing game. - * @param gameInstance The instance of the fishing game to start. - */ - @Override - public boolean startFishingGame(Player player, GameSettings settings, GameInstance gameInstance) { - plugin.debug("Difficulty:" + settings.difficulty()); - plugin.debug("Time:" + settings.time()); - FishHook hook = getHook(player.getUniqueId()); - if (hook != null) { - this.gamingPlayerMap.put(player.getUniqueId(), gameInstance.start(player, hook, settings)); - return true; - } else { - LogUtils.warn("It seems that player " + player.getName() + " is not fishing. Fishing game failed to start."); - return false; - } - } - - /** - * Checks if a player with the given UUID has cast their fishing hook. - * - * @param uuid The UUID of the player to check. - * @return {@code true} if the player has cast their fishing hook, {@code false} otherwise. - */ - @Override - public boolean hasPlayerCastHook(UUID uuid) { - FishHook fishHook = hookCacheMap.get(uuid); - if (fishHook == null) return false; - if (!fishHook.isValid()) { - hookCacheMap.remove(uuid); - return false; - } - return true; - } - - /** - * Sets the temporary fishing state for a player. - * - * @param player The player for whom to set the temporary fishing state. - * @param tempFishingState The temporary fishing state to set for the player. - */ - @Override - public void setTempFishingState(Player player, TempFishingState tempFishingState) { - tempFishingStateMap.put(player.getUniqueId(), tempFishingState); - } - - public void removeHookCheckTask(Player player) { - hookCheckMap.remove(player.getUniqueId()); - } - - /** - * Gets the {@link GamingPlayer} object associated with the given UUID. - * - * @param uuid The UUID of the player. - * @return The {@link GamingPlayer} object if found, or {@code null} if not found. - */ - @Override - @Nullable - public GamingPlayer getGamingPlayer(UUID uuid) { - return gamingPlayerMap.get(uuid); - } - - /** - * Gets the {@link TempFishingState} object associated with the given UUID. - * - * @param uuid The UUID of the player. - * @return The {@link TempFishingState} object if found, or {@code null} if not found. - */ - @Override - @Nullable - public TempFishingState getTempFishingState(UUID uuid) { - return tempFishingStateMap.get(uuid); - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/FishingPreparationImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/FishingPreparationImpl.java deleted file mode 100644 index c8f079c8..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/FishingPreparationImpl.java +++ /dev/null @@ -1,188 +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.bukkit.fishing; - -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.mechanic.action.Action; -import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -public class FishingPreparationImpl extends FishingPreparation { - - private boolean hasBait = false; - private boolean hasHook = false; - private @Nullable ItemStack baitItemStack; - private final @NotNull ItemStack rodItemStack; - private final List effects; - private boolean canFish = true; - - public FishingPreparationImpl(Player player, BukkitCustomFishingPlugin plugin) { - super(player); - - PlayerInventory playerInventory = player.getInventory(); - ItemStack mainHandItem = playerInventory.getItemInMainHand(); - ItemStack offHandItem = playerInventory.getItemInOffHand(); - - this.effects = new ArrayList<>(); - boolean rodOnMainHand = mainHandItem.getType() == Material.FISHING_ROD; - this.rodItemStack = rodOnMainHand ? mainHandItem : offHandItem; - String rodItemID = plugin.getItemManager().getAnyPluginItemID(this.rodItemStack); - EffectCarrier rodEffect = plugin.getEffectManager().getEffectCarrier("rod", rodItemID); - if (rodEffect != null) effects.add(rodEffect); - super.insertArg("{rod}", rodItemID); - - NBTItem nbtItem = new NBTItem(rodItemStack); - NBTCompound cfCompound = nbtItem.getCompound("CustomFishing"); - if (cfCompound != null && cfCompound.hasTag("hook_id")) { - String hookID = cfCompound.getString("hook_id"); - super.insertArg("{hook}", hookID); - this.hasHook = true; - EffectCarrier carrier = plugin.getEffectManager().getEffectCarrier("hook", hookID); - if (carrier != null) { - this.effects.add(carrier); - } - } - - String baitItemID = plugin.getItemManager().getAnyPluginItemID(rodOnMainHand ? offHandItem : mainHandItem); - EffectCarrier baitEffect = plugin.getEffectManager().getEffectCarrier("bait", baitItemID); - - if (baitEffect != null) { - this.baitItemStack = rodOnMainHand ? offHandItem : mainHandItem; - this.effects.add(baitEffect); - this.hasBait = true; - super.insertArg("{bait}", baitItemID); - } - - if (plugin.getBagManager().isEnabled()) { - Inventory fishingBag = plugin.getBagManager().getOnlineBagInventory(player.getUniqueId()); - HashSet uniqueUtils = new HashSet<>(4); - if (fishingBag != null) { - this.insertArg("{in-bag}", "true"); - for (int i = 0; i < fishingBag.getSize(); i++) { - ItemStack itemInBag = fishingBag.getItem(i); - String bagItemID = plugin.getItemManager().getAnyPluginItemID(itemInBag); - if (!hasBait) { - EffectCarrier effect = plugin.getEffectManager().getEffectCarrier("bait", bagItemID); - if (effect != null) { - this.hasBait = true; - this.baitItemStack = itemInBag; - this.effects.add(effect); - super.insertArg("{bait}", bagItemID); - continue; - } - } - EffectCarrier utilEffect = plugin.getEffectManager().getEffectCarrier("util", bagItemID); - if (utilEffect != null && !uniqueUtils.contains(bagItemID)) { - effects.add(utilEffect); - uniqueUtils.add(bagItemID); - } - } - this.delArg("{in-bag}"); - } - } - - for (String enchant : plugin.getIntegrationManager().getEnchantments(rodItemStack)) { - EffectCarrier enchantEffect = plugin.getEffectManager().getEffectCarrier("enchant", enchant); - if (enchantEffect != null) { - this.effects.add(enchantEffect); - } - } - - for (EffectCarrier effectCarrier : effects) { - if (!effectCarrier.isConditionMet(this)) { - this.canFish = false; - return; - } - } - } - - /** - * Retrieves the ItemStack representing the fishing rod. - * - * @return The ItemStack representing the fishing rod. - */ - @NotNull - public ItemStack getRodItemStack() { - return rodItemStack; - } - - /** - * Retrieves the ItemStack representing the bait (if available). - * - * @return The ItemStack representing the bait, or null if no bait is set. - */ - @Nullable - public ItemStack getBaitItemStack() { - return baitItemStack; - } - - /** - * Checks if player meet the requirements for fishing gears - * - * @return True if can fish, false otherwise. - */ - public boolean canFish() { - return this.canFish; - } - - /** - * Merges a FishingEffect into this fishing rod, applying effect modifiers. - * - * @param effect The FishingEffect to merge into this rod. - */ - public void mergeEffect(FishingEffect effect) { - for (EffectModifier modifier : GlobalSettings.getEffectModifiers()) { - modifier.modify(effect, this); - } - for (EffectCarrier effectCarrier : effects) { - for (EffectModifier modifier : effectCarrier.getEffectModifiers()) { - modifier.modify(effect, this); - } - } - } - - /** - * Triggers actions associated with a specific action trigger. - * - * @param actionTrigger The action trigger that initiates the actions. - */ - public void triggerActions(ActionTrigger actionTrigger) { - GlobalSettings.triggerRodActions(actionTrigger, this); - if (hasBait) GlobalSettings.triggerBaitActions(actionTrigger, this); - if (hasHook) GlobalSettings.triggerHookActions(actionTrigger, this); - for (EffectCarrier effectCarrier : effects) { - Action[] actions = effectCarrier.getActions(actionTrigger); - if (actions != null) - for (Action action : actions) { - action.trigger(this); - } - } - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/HookCheckTimerTask.java b/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/HookCheckTimerTask.java deleted file mode 100644 index 1169e5b7..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/HookCheckTimerTask.java +++ /dev/null @@ -1,353 +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.bukkit.fishing; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.event.FishHookLandEvent; -import net.momirealms.customfishing.api.event.LavaFishingEvent; -import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; -import net.momirealms.customfishing.api.mechanic.effect.Effect; -import net.momirealms.customfishing.api.mechanic.loot.Loot; -import net.momirealms.customfishing.api.scheduler.CancellableTask; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FishHook; -import org.bukkit.persistence.PersistentDataType; -import org.bukkit.util.Vector; - -import java.util.Objects; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; - -/** - * A task responsible for checking the state of a fishing hook and handling lava fishing mechanics. - */ -public class HookCheckTimerTask implements Runnable { - - private final BukkitFishingManager manager; - private final CancellableTask hookMovementTask; - private LavaEffectTask lavaFishingTask; - private final FishHook fishHook; - private final FishingPreparation fishingPreparation; - private final FishingEffect initialEffect; - private Effect tempEffect; - private final int lureLevel; - private boolean firstTime; - private boolean fishHooked; - private boolean reserve; - private int jumpTimer; - private Entity hookedEntity; - private Loot loot; - private boolean inWater; - - /** - * Constructs a new HookCheckTimerTask. - * - * @param manager The FishingManagerImpl instance. - * @param fishHook The FishHook entity being checked. - * @param fishingPreparation The FishingPreparation instance. - * @param initialEffect The initial fishing effect. - */ - public HookCheckTimerTask( - BukkitFishingManager manager, - FishHook fishHook, - FishingPreparation fishingPreparation, - FishingEffect initialEffect - ) { - this.inWater = false; - this.manager = manager; - this.fishHook = fishHook; - this.initialEffect = initialEffect; - this.fishingPreparation = fishingPreparation; - this.hookMovementTask = BukkitCustomFishingPlugin.get().getScheduler().runTaskSyncTimer(this, fishHook.getLocation(), 1, 1); - this.lureLevel = fishingPreparation.getRodItemStack().getEnchantmentLevel(Enchantment.LURE); - this.firstTime = true; - this.tempEffect = new FishingEffect(); - } - - @Override - public void run() { - if ( - !this.fishHook.isValid() - //|| (fishHook.getHookedEntity() != null && fishHook.getHookedEntity().getType() != EntityType.ARMOR_STAND) - ) { - // This task would be cancelled when hook is removed - this.destroy(); - return; - } - if (this.fishHook.isOnGround()) { - this.inWater = false; - return; - } - if (this.fishHook.getLocation().getBlock().getType() == Material.LAVA) { - this.inWater = false; - // if player can fish in lava - if (firstTime) { - this.firstTime = false; - - this.fishingPreparation.setLocation(this.fishHook.getLocation()); - this.fishingPreparation.mergeEffect(this.initialEffect); - if (!initialEffect.allowLavaFishing()) { - this.destroy(); - return; - } - - FishHookLandEvent event = new FishHookLandEvent(this.fishingPreparation.getPlayer(), FishHookLandEvent.Target.LAVA, this.fishHook, true, this.initialEffect); - Bukkit.getPluginManager().callEvent(event); - - this.fishingPreparation.insertArg("{lava}", "true"); - this.fishingPreparation.triggerActions(ActionTrigger.LAND); - } - - // simulate fishing mechanic - if (this.fishHooked) { - this.jumpTimer++; - if (this.jumpTimer < 4) - return; - this.jumpTimer = 0; - this.fishHook.setVelocity(new Vector(0,0.24,0)); - return; - } - - if (!this.reserve) { - // jump - if (this.jumpTimer < 5) { - this.jumpTimer++; - this.fishHook.setVelocity(new Vector(0,0.2 - this.jumpTimer * 0.02,0)); - return; - } - - this.reserve = true; - - this.setNextLoot(); - if (this.loot != null) { - this.tempEffect = this.loot.baseEffect().build(fishingPreparation.getPlayer(), fishingPreparation.getArgs()); - this.tempEffect.merge(this.initialEffect); - this.setTempState(); - this.startLavaFishingMechanic(); - } else { - this.tempEffect = new FishingEffect(); - this.tempEffect.merge(this.initialEffect); - this.manager.removeTempFishingState(fishingPreparation.getPlayer()); - BukkitCustomFishingPlugin.get().debug("No loot available for " + fishingPreparation.getPlayer().getName() + " at " + fishingPreparation.getLocation()); - } - - this.makeHookStatic(this.fishHook.getLocation()); - } - return; - } - if (!this.inWater && this.fishHook.isInWater()) { - this.inWater = true; - - this.fishingPreparation.setLocation(this.fishHook.getLocation()); - this.fishingPreparation.insertArg("{lava}", "false"); - this.fishingPreparation.insertArg("{open-water}", String.valueOf(this.fishHook.isInOpenWater())); - - if (this.firstTime) { - this.firstTime = false; - this.fishingPreparation.mergeEffect(this.initialEffect); - - FishHookLandEvent event = new FishHookLandEvent(this.fishingPreparation.getPlayer(), FishHookLandEvent.Target.WATER, this.fishHook, false, this.initialEffect); - Bukkit.getPluginManager().callEvent(event); - - this.fishingPreparation.triggerActions(ActionTrigger.LAND); - - } else { - FishHookLandEvent event = new FishHookLandEvent(this.fishingPreparation.getPlayer(), FishHookLandEvent.Target.WATER, this.fishHook, true, this.initialEffect); - Bukkit.getPluginManager().callEvent(event); - } - - this.setNextLoot(); - if (this.loot == null) { - // prevent players from getting vanilla loots - this.fishHook.setWaitTime(Integer.MAX_VALUE); - this.tempEffect = new FishingEffect(); - this.tempEffect.merge(this.initialEffect); - this.manager.removeTempFishingState(fishingPreparation.getPlayer()); - BukkitCustomFishingPlugin.get().debug("No loot available for " + fishingPreparation.getPlayer().getName() + " at " + fishingPreparation.getLocation()); - } else { - this.tempEffect = this.loot.baseEffect().build(fishingPreparation.getPlayer(), fishingPreparation.getArgs()); - this.tempEffect.merge(this.initialEffect); - this.setWaitTime(); - this.setTempState(); - } - - return; - } - } - - /** - * Destroys the task and associated entities. - */ - public void destroy() { - this.cancelSubTask(); - this.removeTempEntity(); - this.hookMovementTask.cancel(); - this.manager.removeHookCheckTask(fishingPreparation.getPlayer()); - } - - /** - * Cancels the lava fishing subtask if it's active. - */ - public void cancelSubTask() { - if (lavaFishingTask != null && !lavaFishingTask.isCancelled()) { - lavaFishingTask.cancel(); - lavaFishingTask = null; - } - } - - private void setNextLoot() { - Loot nextLoot = BukkitCustomFishingPlugin.get().getLootManager().getNextLoot(initialEffect, fishingPreparation); - if (nextLoot == null) { - this.loot = null; - return; - } - this.loot = nextLoot; - } - - /** - * Sets temporary state and prepares for the next loot. - */ - private void setTempState() { - fishingPreparation.insertArg("{nick}", loot.getNick()); - fishingPreparation.insertArg("{loot}", loot.getID()); - if (!loot.disableStats()) { - fishingPreparation.insertArg("{statistics_size}", loot.getStatisticKey().sizeKey()); - fishingPreparation.insertArg("{statistics_amount}", loot.getStatisticKey().amountKey()); - } - manager.setTempFishingState(fishingPreparation.getPlayer(), new TempFishingState( - tempEffect, - fishingPreparation, - loot - )); - } - - /** - * Removes the temporary hooked entity. - */ - public void removeTempEntity() { - if (hookedEntity != null && !hookedEntity.isDead()) - hookedEntity.remove(); - } - - /** - * Starts the lava fishing mechanic. - */ - private void startLavaFishingMechanic() { - // get random time - int random; - if (CFConfig.overrideVanilla) { - random = ThreadLocalRandom.current().nextInt(CFConfig.lavaMinTime, CFConfig.lavaMaxTime); - random *= tempEffect.waitTimeMultiplier(); - random += tempEffect.waitTimeAdder(); - random = Math.max(1, random); - } else { - random = ThreadLocalRandom.current().nextInt(CFConfig.lavaMinTime, CFConfig.lavaMaxTime); - random -= lureLevel * 100; - random = Math.max(CFConfig.lavaMinTime, random); - random *= tempEffect.waitTimeMultiplier(); - random += tempEffect.waitTimeAdder(); - random = Math.max(1, random); - } - - // lava effect task (Three seconds in advance) - this.lavaFishingTask = new LavaEffectTask( - this, - fishHook.getLocation(), - random - 3 * 20 - ); - } - - /** - * Handles the hook state of the fish hook. - */ - public void getHooked() { - LavaFishingEvent lavaFishingEvent = new LavaFishingEvent(fishingPreparation.getPlayer(), LavaFishingEvent.State.BITE, fishHook); - Bukkit.getPluginManager().callEvent(lavaFishingEvent); - if (lavaFishingEvent.isCancelled()) { - this.startLavaFishingMechanic(); - return; - } - - this.loot.triggerActions(ActionTrigger.BITE, fishingPreparation); - this.fishingPreparation.triggerActions(ActionTrigger.BITE); - - this.fishHooked = true; - this.removeTempEntity(); - - AdventureHelper.getInstance().sendSound( - fishingPreparation.getPlayer(), - Sound.Source.NEUTRAL, - Key.key("minecraft:block.pointed_dripstone.drip_lava_into_cauldron"), - 1, - 1 - ); - - BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> { - fishHooked = false; - reserve = false; - }, (2 * 20) * 50L, TimeUnit.MILLISECONDS); - } - - private void makeHookStatic(Location armorLoc) { - armorLoc.setY(armorLoc.getBlockY() + 0.2); - if (hookedEntity != null && !hookedEntity.isDead()) - hookedEntity.remove(); - hookedEntity = armorLoc.getWorld().spawn(armorLoc, ArmorStand.class, a -> { - a.setInvisible(true); - a.setCollidable(false); - a.setInvulnerable(true); - a.setVisible(false); - a.setCustomNameVisible(false); - a.setSmall(true); - a.setGravity(false); - a.getPersistentDataContainer().set( - Objects.requireNonNull(NamespacedKey.fromString("lavafishing", BukkitCustomFishingPlugin.get())), - PersistentDataType.STRING, - "temp" - ); - }); - fishHook.setHookedEntity(hookedEntity); - } - - /** - * Checks if the fish hook is currently hooked. - * - * @return True if the fish hook is hooked, false otherwise. - */ - public boolean isFishHooked() { - return fishHooked; - } - - private void setWaitTime() { - if (CFConfig.overrideVanilla) { - double initialTime = ThreadLocalRandom.current().nextInt(CFConfig.waterMaxTime - CFConfig.waterMinTime + 1) + CFConfig.waterMinTime; - fishHook.setWaitTime(Math.max(1, (int) (initialTime * tempEffect.waitTimeMultiplier() + tempEffect.waitTimeAdder()))); - } else { - fishHook.setMinWaitTime(Math.max(1, (int) (fishHook.getMinWaitTime() * tempEffect.waitTimeMultiplier() + tempEffect.waitTimeAdder()))); - fishHook.setMaxWaitTime(Math.max(2, (int) (fishHook.getMaxWaitTime() * tempEffect.waitTimeMultiplier() + tempEffect.waitTimeAdder()))); - } - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/LavaEffectTask.java b/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/LavaEffectTask.java deleted file mode 100644 index cc73ccbb..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/fishing/LavaEffectTask.java +++ /dev/null @@ -1,89 +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.bukkit.fishing; - -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.scheduler.CancellableTask; -import org.bukkit.Location; -import org.bukkit.Particle; - -import java.util.concurrent.TimeUnit; - -/** - * A task responsible for creating a lava effect animation between two points. - */ -public class LavaEffectTask implements Runnable { - - private final Location startLoc; - private final Location endLoc; - private final Location controlLoc; - private int timer; - private final CancellableTask lavaTask; - private final HookCheckTimerTask hookCheckTimerTask; - - /** - * Constructs a new LavaEffectTask. - * - * @param hookCheckTimerTask The HookCheckTimerTask instance. - * @param location The starting location for the lava effect. - * @param delay The delay before starting the task. - */ - public LavaEffectTask(HookCheckTimerTask hookCheckTimerTask, Location location, int delay) { - this.hookCheckTimerTask = hookCheckTimerTask; - this.startLoc = location.clone().add(0,0.3,0); - this.endLoc = this.startLoc.clone().add((Math.random() * 16 - 8), startLoc.getY(), (Math.random() * 16 - 8)); - this.controlLoc = new Location( - startLoc.getWorld(), - (startLoc.getX() + endLoc.getX())/2 + Math.random() * 12 - 6, - startLoc.getY(), - (startLoc.getZ() + endLoc.getZ())/2 + Math.random() * 12 - 6 - ); - this.lavaTask = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, delay * 50L, 50, TimeUnit.MILLISECONDS); - } - - @Override - public void run() { - timer++; - if (timer > 60) { - lavaTask.cancel(); - BukkitCustomFishingPlugin.get().getScheduler().runTaskSync(hookCheckTimerTask::getHooked, startLoc); - } else { - double t = (double) timer / 60; - Location particleLoc = endLoc.clone().multiply(Math.pow((1 - t), 2)).add(controlLoc.clone().multiply(2 * t * (1 - t))).add(startLoc.clone().multiply(Math.pow(t, 2))); - particleLoc.setY(startLoc.getY()); - startLoc.getWorld().spawnParticle(Particle.FLAME, particleLoc,1,0,0,0,0); - } - } - - /** - * Cancels the lava effect task. - */ - public void cancel() { - if (lavaTask != null && !lavaTask.isCancelled()) - lavaTask.cancel(); - } - - /** - * Checks if the lava effect task is cancelled. - * - * @return True if the task is cancelled, false otherwise. - */ - public boolean isCancelled() { - return lavaTask.isCancelled(); - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/game/BukkitGameManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/game/BukkitGameManager.java deleted file mode 100644 index 913df568..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/game/BukkitGameManager.java +++ /dev/null @@ -1,1201 +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.bukkit.game; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.mechanic.game.*; -import net.momirealms.customfishing.common.util.Pair; -import net.momirealms.customfishing.bukkit.util.ConfigUtils; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; - -@SuppressWarnings("DuplicatedCode") -public class BukkitGameManager implements GameManager { - - private final BukkitCustomFishingPlugin plugin; - private final HashMap gameCreatorMap; - private final HashMap> gameInstanceMap; - private final String EXPANSION_FOLDER = "expansions/minigame"; - - public BukkitGameManager(BukkitCustomFishingPlugin plugin) { - this.plugin = plugin; - this.gameCreatorMap = new HashMap<>(); - this.gameInstanceMap = new HashMap<>(); - this.registerInbuiltGames(); - } - - private void registerInbuiltGames() { - this.registerHoldGame(); - this.registerHoldV2Game(); - this.registerTensionGame(); - this.registerClickGame(); - this.registerDanceGame(); - this.registerAccurateClickGame(); - this.registerAccurateClickV2Game(); - this.registerAccurateClickV3Game(); - } - - public void load() { - this.loadExpansions(); - this.loadGamesFromPluginFolder(); - } - - public void unload() { - this.gameInstanceMap.clear(); - } - - public void disable() { - unload(); - this.gameCreatorMap.clear(); - } - - /** - * Registers a new game type with the specified type identifier. - * - * @param type The type identifier for the game. - * @param gameFactory The {@link GameFactory} that creates instances of the game. - * @return {@code true} if the registration was successful, {@code false} if the type identifier is already registered. - */ - @Override - public boolean registerGameType(String type, GameFactory gameFactory) { - if (gameCreatorMap.containsKey(type)) - return false; - else - gameCreatorMap.put(type, gameFactory); - return true; - } - - /** - * Unregisters a game type with the specified type identifier. - * - * @param type The type identifier of the game to unregister. - * @return {@code true} if the game type was successfully unregistered, {@code false} if the type identifier was not found. - */ - @Override - public boolean unregisterGameType(String type) { - return gameCreatorMap.remove(type) != null; - } - - /** - * Retrieves the game factory associated with the specified game type. - * - * @param type The type identifier of the game. - * @return The {@code GameFactory} for the specified game type, or {@code null} if not found. - */ - @Override - @Nullable - public GameFactory getGameFactory(String type) { - return gameCreatorMap.get(type); - } - - /** - * Retrieves a game instance and its basic configuration associated with the specified key. - * - * @param key The key identifying the game instance. - * @return An {@code Optional} containing a {@code Pair} of the basic game configuration and the game instance - * if found, or an empty {@code Optional} if not found. - */ - @Override - public Pair getGameInstance(String key) { - return gameInstanceMap.get(key); - } - - /** - * Retrieves a map of game names and their associated weights based on the specified conditions. - * - * @param playerContext The condition to evaluate game weights. - * @return A {@code HashMap} containing game names as keys and their associated weights as values. - */ - @Override - public HashMap getGameWithWeight(PlayerContext playerContext) { - return ((RequirementManagerImpl) plugin.getRequirementManager()).getGameWithWeight(playerContext); - } - - /** - * Loads minigames from the plugin folder. - * This method searches for minigame configuration files in the plugin's data folder and loads them. - */ - public void loadGamesFromPluginFolder() { - Deque fileDeque = new ArrayDeque<>(); - File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "minigame"); - if (!typeFolder.exists()) { - if (!typeFolder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + "minigame" + File.separator + "default.yml", false); - } - fileDeque.push(typeFolder); - while (!fileDeque.isEmpty()) { - File file = fileDeque.pop(); - File[] files = file.listFiles(); - if (files == null) continue; - for (File subFile : files) { - if (subFile.isDirectory()) { - fileDeque.push(subFile); - } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) { - loadSingleFile(subFile); - } - } - } - } - - /** - * Loads a minigame configuration from a YAML file. - * This method parses the YAML file and extracts minigame configurations to be used in the plugin. - * - * @param file The YAML file to load. - */ - private void loadSingleFile(File file) { - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (Map.Entry entry : config.getValues(false).entrySet()) { - if (entry.getValue() instanceof ConfigurationSection section) { - GameFactory creator = this.getGameFactory(section.getString("game-type")); - if (creator == null) { - LogUtils.warn("Game type:" + section.getString("game-type") + " doesn't exist."); - continue; - } - - BasicGameConfig.Builder basicGameBuilder = new BasicGameConfig.Builder(); - Object time = section.get("time", 15); - if (time instanceof String str) { - String[] split = str.split("~"); - basicGameBuilder.time(Integer.parseInt(split[0]), Integer.parseInt(split[1])); - } else if (time instanceof Integer integer) { - basicGameBuilder.time(integer); - } - Object difficulty = section.get("difficulty", "20~80"); - if (difficulty instanceof String str) { - String[] split = str.split("~"); - basicGameBuilder.difficulty(Integer.parseInt(split[0]), Integer.parseInt(split[1])); - } else if (difficulty instanceof Integer integer) { - basicGameBuilder.difficulty(integer); - } - gameInstanceMap.put(entry.getKey(), Pair.of(basicGameBuilder.build(), creator.setArgs(section))); - } - } - } - - private void registerAccurateClickGame() { - this.registerGameType("accurate_click", (section -> { - - Set chances = Objects.requireNonNull(section.getConfigurationSection("success-rate-sections")).getKeys(false); - var widthPerSection = section.getInt("arguments.width-per-section", 16); - var successRate = new double[chances.size()]; - for(int i = 0; i < chances.size(); i++) - successRate[i] = section.getDouble("success-rate-sections." + (i + 1)); - var totalWidth = chances.size() * widthPerSection - 1; - var pointerOffset = section.getInt("arguments.pointer-offset"); - var pointerWidth = section.getInt("arguments.pointer-width"); - var title = ConfigUtils.stringListArgs(section.get("title")); - var font = section.getString("subtitle.font"); - var barImage = section.getString("subtitle.bar"); - var pointerImage = section.getString("subtitle.pointer"); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - - private int progress = -1; - private boolean face = true; - private final String sendTitle = title.get(ThreadLocalRandom.current().nextInt(title.size())); - - @Override - public void arrangeTask() { - var period = ((double) 10*(200-settings.difficulty()))/((double) (1+4*settings.difficulty())); - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer( - this, - 50, - (long) period, - TimeUnit.MILLISECONDS - ); - } - - @Override - public void onTick() { - if (face) progress++; - else progress--; - if (progress > totalWidth) { - face = !face; - progress = 2 * totalWidth - progress; - } else if (progress < 0) { - face = !face; - progress = -progress; - } - showUI(); - } - - public void showUI() { - String bar = FontUtils.surroundWithFont(barImage, font) - + OffsetUtils.getOffsetChars(pointerOffset + progress) - + FontUtils.surroundWithFont(pointerImage, font) - + OffsetUtils.getOffsetChars(totalWidth - progress - pointerWidth); - AdventureHelper.getInstance().sendTitle(player, sendTitle, bar,0,10,0); - } - - @Override - public boolean isSuccessful() { - if (isTimeOut) return false; - int last = progress / widthPerSection; - return (Math.random() < successRate[last]); - } - }; - })); - } - - private void registerHoldGame() { - this.registerGameType("hold", (section -> { - - var timeRequirements = section.getIntegerList("hold-time-requirements").stream().mapToInt(Integer::intValue).toArray(); - var judgementAreaImage = section.getString("subtitle.judgment-area"); - var pointerImage = section.getString("subtitle.pointer"); - var barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); - var judgementAreaOffset = section.getInt("arguments.judgment-area-offset"); - var judgementAreaWidth = section.getInt("arguments.judgment-area-width"); - var pointerIconWidth = section.getInt("arguments.pointer-icon-width"); - var punishment = section.getDouble("arguments.punishment"); - var progress = section.getStringList("progress").toArray(new String[0]); - var waterResistance = section.getDouble("arguments.water-resistance", 0.15); - var pullingStrength = section.getDouble("arguments.pulling-strength", 0.45); - var looseningLoss = section.getDouble("arguments.loosening-strength-loss", 0.3); - - var title = section.getString("title","{progress}"); - var font = section.getString("subtitle.font"); - var barImage = section.getString("subtitle.bar"); - var tip = section.getString("tip"); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - private double hold_time; - private double judgement_position; - private double fish_position; - private double judgement_velocity; - private double fish_velocity; - private int timer; - private final int time_requirement = timeRequirements[ThreadLocalRandom.current().nextInt(timeRequirements.length)] * 1000; - private boolean played; - - @Override - public void arrangeTask() { - this.judgement_position = (double) (barEffectiveWidth - judgementAreaWidth) / 2; - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer( - this, - 50, - 33, - TimeUnit.MILLISECONDS - ); - } - - @Override - public void onTick() { - if (player.isSneaking()) addV(); - else reduceV(); - if (timer < 40 - (settings.difficulty() / 10)) { - timer++; - } else { - timer = 0; - if (Math.random() > ((double) 25 / (settings.difficulty() + 100))) { - burst(); - } - } - judgement_position += judgement_velocity; - fish_position += fish_velocity; - fraction(); - calibrate(); - if (fish_position >= judgement_position && fish_position + pointerIconWidth <= judgement_position + judgementAreaWidth) { - hold_time += 33; - } else { - hold_time -= punishment * 33; - } - if (hold_time >= time_requirement) { - setGameResult(true); - endGame(); - return; - } - hold_time = Math.max(0, Math.min(hold_time, time_requirement)); - showUI(); - } - - private void burst() { - if (Math.random() < (judgement_position / barEffectiveWidth)) { - judgement_velocity = -1 - 0.8 * Math.random() * ((double) settings.difficulty() / 15); - } else { - judgement_velocity = 1 + 0.8 * Math.random() * ((double) settings.difficulty() / 15); - } - } - - private void fraction() { - if (judgement_velocity > 0) { - judgement_velocity -= waterResistance; - if (judgement_velocity < 0) judgement_velocity = 0; - } else { - judgement_velocity += waterResistance; - if (judgement_velocity > 0) judgement_velocity = 0; - } - } - - private void reduceV() { - fish_velocity -= looseningLoss; - } - - private void addV() { - played = true; - fish_velocity += pullingStrength; - } - - private void calibrate() { - if (fish_position < 0) { - fish_position = 0; - fish_velocity = 0; - } - if (fish_position + pointerIconWidth > barEffectiveWidth) { - fish_position = barEffectiveWidth - pointerIconWidth; - fish_velocity = 0; - } - if (judgement_position < 0) { - judgement_position = 0; - judgement_velocity = 0; - } - if (judgement_position + judgementAreaWidth > barEffectiveWidth) { - judgement_position = barEffectiveWidth - judgementAreaWidth; - judgement_velocity = 0; - } - } - - public void showUI() { - String bar = FontUtils.surroundWithFont(barImage, font) - + OffsetUtils.getOffsetChars((int) (judgementAreaOffset + judgement_position)) - + FontUtils.surroundWithFont(judgementAreaImage, font) - + OffsetUtils.getOffsetChars((int) (barEffectiveWidth - judgement_position - judgementAreaWidth)) - + OffsetUtils.getOffsetChars((int) (-barEffectiveWidth - 1 + fish_position)) - + FontUtils.surroundWithFont(pointerImage, font) - + OffsetUtils.getOffsetChars((int) (barEffectiveWidth - fish_position - pointerIconWidth + 1)); - AdventureHelper.getInstance().sendTitle( - player, - tip != null && !played ? tip : title.replace("{progress}", progress[(int) ((hold_time / time_requirement) * progress.length)]), - bar, - 0, - 10, - 0 - ); - } - }; - })); - } - - private void registerTensionGame() { - this.registerGameType("tension", (section -> { - - var fishIconWidth = section.getInt("arguments.fish-icon-width"); - var fishImage = section.getString("subtitle.fish"); - var tension = section.getStringList("tension").toArray(new String[0]); - var strugglingFishImage = section.getStringList("subtitle.struggling-fish").toArray(new String[0]); - var barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); - var fishOffset = section.getInt("arguments.fish-offset"); - var fishStartPosition = section.getInt("arguments.fish-start-position"); - var successPosition = section.getInt("arguments.success-position"); - var ultimateTension = section.getDouble("arguments.ultimate-tension", 50); - var normalIncrease = section.getDouble("arguments.normal-pull-tension-increase", 1); - var strugglingIncrease = section.getDouble("arguments.struggling-tension-increase", 2); - var tensionLoss = section.getDouble("arguments.loosening-tension-loss", 2); - - var title = section.getString("title","{progress}"); - var font = section.getString("subtitle.font"); - var barImage = section.getString("subtitle.bar"); - var tip = section.getString("tip"); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - - private int fish_position = fishStartPosition; - private double strain; - private int struggling_time; - private boolean played; - - @Override - public void arrangeTask() { - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, 50, 40, TimeUnit.MILLISECONDS); - } - - @Override - public void onTick() { - if (struggling_time <= 0) { - if (Math.random() < ((double) settings.difficulty() / 4000)) { - struggling_time = (int) (10 + Math.random() * (settings.difficulty() / 4)); - } - } else { - struggling_time--; - } - if (player.isSneaking()) pull(); - else loosen(); - if (fish_position < successPosition - fishIconWidth - 1) { - setGameResult(true); - endGame(); - return; - } - if (fish_position + fishIconWidth > barEffectiveWidth || strain >= ultimateTension) { - setGameResult(false); - endGame(); - return; - } - showUI(); - } - - public void pull() { - played = true; - if (struggling_time > 0) { - strain += (strugglingIncrease + ((double) settings.difficulty() / 50)); - fish_position -= 1; - } else { - strain += normalIncrease; - fish_position -= 2; - } - } - - public void loosen() { - fish_position++; - strain -= tensionLoss; - } - - public void showUI() { - String bar = FontUtils.surroundWithFont(barImage, font) - + OffsetUtils.getOffsetChars(fishOffset + fish_position) - + FontUtils.surroundWithFont((struggling_time > 0 ? strugglingFishImage[struggling_time % strugglingFishImage.length] : fishImage), font) - + OffsetUtils.getOffsetChars(barEffectiveWidth - fish_position - fishIconWidth); - strain = Math.max(0, Math.min(strain, ultimateTension)); - AdventureHelper.getInstance().sendTitle( - player, - tip != null && !played ? tip : title.replace("{tension}", tension[(int) ((strain / ultimateTension) * tension.length)]), - bar, - 0, - 10, - 0 - ); - } - }; - })); - } - - private void registerDanceGame() { - this.registerGameType("dance", (section -> { - - var subtitle = section.getString("subtitle", "Dance to win. Time left {time}s"); - var leftNot = section.getString("title.left-button"); - var leftCorrect = section.getString("title.left-button-correct"); - var leftWrong = section.getString("title.left-button-wrong"); - var leftCurrent = section.getString("title.left-button-current"); - var rightNot = section.getString("title.right-button"); - var rightCorrect = section.getString("title.right-button-correct"); - var rightWrong = section.getString("title.right-button-wrong"); - var rightCurrent = section.getString("title.right-button-current"); - - var upNot = section.getString("title.up-button"); - var upCorrect = section.getString("title.up-button-correct"); - var upWrong = section.getString("title.up-button-wrong"); - var upCurrent = section.getString("title.up-button-current"); - var downNot = section.getString("title.down-button"); - var downCorrect = section.getString("title.down-button-correct"); - var downWrong = section.getString("title.down-button-wrong"); - var downCurrent = section.getString("title.down-button-current"); - - var maxShown = section.getInt("title.display-amount", 7); - var tip = section.getString("tip"); - var easy = section.getBoolean("easy", false); - - var correctSound = section.getString("sound.correct", "minecraft:block.amethyst_block.hit"); - var wrongSound = section.getString("sound.wrong", "minecraft:block.anvil.land"); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - - private int clickedTimes; - private int requiredTimes; - private boolean preventFirst = true; - // 0 = left / 1 = right / 2 = up / 3 = down - private int[] order; - boolean fail = false; - - @Override - public void arrangeTask() { - requiredTimes = settings.difficulty() / 4; - order = new int[requiredTimes]; - for (int i = 0; i < requiredTimes; i++) { - order[i] = ThreadLocalRandom.current().nextInt(0, easy ? 2 : 4); - } - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, 50, 50, TimeUnit.MILLISECONDS); - } - - @Override - public void onTick() { - showUI(); - if (tip != null) { - AdventureHelper.getInstance().sendActionbar(player, tip); - } - } - - @Override - public boolean onRightClick() { - preventFirst = true; - if (order[clickedTimes] != 1) { - setGameResult(false); - fail = true; - showUI(); - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(wrongSound), - 1, - 1 - ); - endGame(); - return true; - } - - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(correctSound), - 1, - 1 - ); - clickedTimes++; - if (clickedTimes >= requiredTimes) { - setGameResult(true); - showUI(); - endGame(); - } - return true; - } - - @Override - public boolean onJump() { - if (order[clickedTimes] != 2) { - setGameResult(false); - fail = true; - showUI(); - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(wrongSound), - 1, - 1 - ); - endGame(); - return false; - } - - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(correctSound), - 1, - 1 - ); - clickedTimes++; - if (clickedTimes >= requiredTimes) { - setGameResult(true); - showUI(); - endGame(); - } - return false; - } - - @Override - public boolean onSneak() { - if (order[clickedTimes] != 3) { - setGameResult(false); - fail = true; - showUI(); - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(wrongSound), - 1, - 1 - ); - endGame(); - return false; - } - - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(correctSound), - 1, - 1 - ); - clickedTimes++; - if (clickedTimes >= requiredTimes) { - setGameResult(true); - showUI(); - endGame(); - } - return false; - } - - @Override - public boolean onLeftClick() { - if (preventFirst) { - preventFirst = false; - return false; - } - - if (order[clickedTimes] != 0) { - setGameResult(false); - fail = true; - showUI(); - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(wrongSound), - 1, - 1 - ); - endGame(); - return true; - } - - AdventureHelper.getInstance().sendSound( - player, - Sound.Source.PLAYER, - Key.key(correctSound), - 1, - 1 - ); - clickedTimes++; - if (clickedTimes >= requiredTimes) { - setGameResult(true); - showUI(); - endGame(); - } - return false; - } - - public void showUI() { - try { - if (requiredTimes <= maxShown) { - StringBuilder sb = new StringBuilder(); - for (int x = 0; x < requiredTimes; x++) { - if (x < clickedTimes) { - switch (order[x]) { - case 0 -> sb.append(leftCorrect); - case 1 -> sb.append(rightCorrect); - case 2 -> sb.append(upCorrect); - case 3 -> sb.append(downCorrect); - } - } else if (clickedTimes == x) { - switch (order[x]) { - case 0 -> sb.append(fail ? leftWrong : leftCurrent); - case 1 -> sb.append(fail ? rightWrong : rightCurrent); - case 2 -> sb.append(fail ? upWrong : upCurrent); - case 3 -> sb.append(fail ? downWrong : downCurrent); - } - } else { - switch (order[x]) { - case 0 -> sb.append(leftNot); - case 1 -> sb.append(rightNot); - case 2 -> sb.append(upNot); - case 3 -> sb.append(downNot); - } - } - } - AdventureHelper.getInstance().sendTitle( - player, - sb.toString(), - subtitle.replace("{time}", String.format("%.1f", ((double) deadline - System.currentTimeMillis())/1000)), - 0, - 10, - 0 - ); - } else { - int half = (maxShown - 1) / 2; - int low = clickedTimes - half; - int high = clickedTimes + half; - if (low < 0) { - high += (-low); - low = 0; - } else if (high >= requiredTimes) { - low -= (high - requiredTimes + 1); - high = requiredTimes - 1; - } - StringBuilder sb = new StringBuilder(); - for (int x = low; x < high + 1; x++) { - if (x < clickedTimes) { - switch (order[x]) { - case 0 -> sb.append(leftCorrect); - case 1 -> sb.append(rightCorrect); - case 2 -> sb.append(upCorrect); - case 3 -> sb.append(downCorrect); - } - } else if (clickedTimes == x) { - switch (order[x]) { - case 0 -> sb.append(fail ? leftWrong : leftCurrent); - case 1 -> sb.append(fail ? rightWrong : rightCurrent); - case 2 -> sb.append(fail ? upWrong : upCurrent); - case 3 -> sb.append(fail ? downWrong : downCurrent); - } - } else { - switch (order[x]) { - case 0 -> sb.append(leftNot); - case 1 -> sb.append(rightNot); - case 2 -> sb.append(upNot); - case 3 -> sb.append(downNot); - } - } - } - AdventureHelper.getInstance().sendTitle( - player, - sb.toString(), - subtitle.replace("{time}", String.format("%.1f", ((double) deadline - System.currentTimeMillis())/1000)), - 0, - 10, - 0 - ); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }; - })); - } - - private void registerClickGame() { - this.registerGameType("click", (section -> { - - var title = section.getString("title","{click}"); - var subtitle = section.getString("subtitle", "Click {clicks} times to win. Time left {time}s"); - var left = section.getBoolean("left-click", true); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - - private int clickedTimes; - private final int requiredTimes = settings.difficulty(); - private boolean preventFirst = true; - - @Override - public void arrangeTask() { - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, 50, 50, TimeUnit.MILLISECONDS); - } - - @Override - public void onTick() { - showUI(); - } - - @Override - public boolean onRightClick() { - if (left) { - setGameResult(false); - endGame(); - return true; - } - clickedTimes++; - if (clickedTimes >= requiredTimes) { - showUI(); - setGameResult(true); - endGame(); - } - return true; - } - - @Override - public boolean onLeftClick() { - if (!left) { - return false; - } - if (preventFirst) { - preventFirst = false; - return false; - } - clickedTimes++; - if (clickedTimes >= requiredTimes) { - showUI(); - setGameResult(true); - endGame(); - } - return false; - } - - public void showUI() { - AdventureHelper.getInstance().sendTitle( - player, - title.replace("{click}", String.valueOf(clickedTimes)), - subtitle.replace("{clicks}", String.valueOf(requiredTimes)).replace("{time}", String.format("%.1f", ((double) deadline - System.currentTimeMillis())/1000)), - 0, - 10, - 0 - ); - } - }; - })); - } - - private void registerAccurateClickV2Game() { - - this.registerGameType("accurate_click_v2", (section -> { - - var barWidth = ConfigUtils.getIntegerPair(section.getString("title.total-width", "15~20")); - var barSuccess = ConfigUtils.getIntegerPair(section.getString("title.success-width","3~4")); - var barBody = section.getString("title.body",""); - var barPointer = section.getString("title.pointer", ""); - var barTarget = section.getString("title.target",""); - - var subtitle = section.getString("subtitle", "Reel in at the most critical moment"); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - - private final int totalWidth = ThreadLocalRandom.current().nextInt(barWidth.right() - barWidth.left() + 1) + barWidth.left(); - private final int successWidth = ThreadLocalRandom.current().nextInt(barSuccess.right() - barSuccess.left() + 1) + barSuccess.left(); - private final int successPosition = ThreadLocalRandom.current().nextInt((totalWidth - successWidth + 1)) + 1; - private int currentIndex = 0; - private int timer = 0; - private boolean face = true; - - @Override - public void arrangeTask() { - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, 50, 50, TimeUnit.MILLISECONDS); - } - - @Override - public void onTick() { - timer++; - if (timer % (21 - settings.difficulty() / 5) == 0) { - movePointer(); - } - showUI(); - } - - private void movePointer() { - if (face) { - currentIndex++; - if (currentIndex >= totalWidth - 1) { - face = false; - } - } else { - currentIndex--; - if (currentIndex <= 0) { - face = true; - } - } - } - - public void showUI() { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 1; i <= totalWidth; i++) { - if (i == currentIndex + 1) { - stringBuilder.append(barPointer); - continue; - } - if (i >= successPosition && i <= successPosition + successWidth - 1) { - stringBuilder.append(barTarget); - continue; - } - stringBuilder.append(barBody); - } - - AdventureHelper.getInstance().sendTitle( - player, - stringBuilder.toString(), - subtitle, - 0, - 10, - 0 - ); - } - - @Override - public boolean isSuccessful() { - return currentIndex + 1 <= successPosition + successWidth - 1 && currentIndex + 1 >= successPosition; - } - }; - })); - } - - private void registerAccurateClickV3Game() { - - this.registerGameType("accurate_click_v3", (section -> { - - var font = section.getString("subtitle.font"); - var pointerImage = section.getString("subtitle.pointer"); - var barImage = section.getString("subtitle.bar"); - var judgementAreaImage = section.getString("subtitle.judgment-area"); - var titles = ConfigUtils.stringListArgs(section.get("title")); - - var barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); - var judgementAreaWidth = section.getInt("arguments.judgment-area-width"); - var judgementAreaOffset = section.getInt("arguments.judgment-area-offset"); - var pointerIconWidth = section.getInt("arguments.pointer-icon-width"); - var pointerOffset = section.getInt("arguments.pointer-offset"); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - - private int progress = -1; - private boolean face = true; - private final int judgement_position = ThreadLocalRandom.current().nextInt(barEffectiveWidth - judgementAreaWidth + 1); - private final String title = titles.get(ThreadLocalRandom.current().nextInt(titles.size())); - - @Override - public void arrangeTask() { - var period = ((double) 10*(200-settings.difficulty()))/((double) (1+4*settings.difficulty())); - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer( - this, - 50, - (long) period, - TimeUnit.MILLISECONDS - ); - } - - @Override - public void onTick() { - if (face) { - progress++; - if (progress >= barEffectiveWidth - 1) { - face = false; - } - } else { - progress--; - if (progress <= 0) { - face = true; - } - } - showUI(); - } - - public void showUI() { - String bar = FontUtils.surroundWithFont(barImage, font) - + OffsetUtils.getOffsetChars(judgementAreaOffset + judgement_position) - + FontUtils.surroundWithFont(judgementAreaImage, font) - + OffsetUtils.getOffsetChars(barEffectiveWidth - judgement_position - judgementAreaWidth) - + OffsetUtils.getOffsetChars(progress + pointerOffset) - + FontUtils.surroundWithFont(pointerImage, font) - + OffsetUtils.getOffsetChars(barEffectiveWidth - progress - pointerIconWidth + 1); - AdventureHelper.getInstance().sendTitle( - player, - title, - bar, - 0, - 10, - 0 - ); - } - - @Override - public boolean isSuccessful() { - return progress < judgement_position + judgementAreaWidth && progress >= judgement_position; - } - }; - })); - } - - private void registerHoldV2Game() { - this.registerGameType("hold_v2", (section -> { - - var timeRequirements = section.getIntegerList("hold-time-requirements").stream().mapToInt(Integer::intValue).toArray(); - var judgementAreaImage = section.getString("subtitle.judgment-area"); - var pointerImage = section.getString("subtitle.pointer"); - var barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); - var judgementAreaOffset = section.getInt("arguments.judgment-area-offset"); - var judgementAreaWidth = section.getInt("arguments.judgment-area-width"); - var pointerIconWidth = section.getInt("arguments.pointer-icon-width"); - var punishment = section.getDouble("arguments.punishment"); - var progress = section.getStringList("progress").toArray(new String[0]); - var waterResistance = section.getDouble("arguments.water-resistance", 0.15); - var pullingStrength = section.getDouble("arguments.pulling-strength", 3); - var looseningLoss = section.getDouble("arguments.loosening-strength-loss", 0.5); - - var title = section.getString("title", "{progress}"); - var font = section.getString("subtitle.font"); - var barImage = section.getString("subtitle.bar"); - var tip = section.getString("tip"); - - var left = section.getBoolean("left-click", true); - - return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) { - private double hold_time; - private double judgement_position; - private double fish_position; - private double judgement_velocity; - private double fish_velocity; - private int timer; - private final int time_requirement = timeRequirements[ThreadLocalRandom.current().nextInt(timeRequirements.length)] * 1000; - private boolean played; - private boolean preventFirst = true; - - @Override - public void arrangeTask() { - this.judgement_position = (double) (barEffectiveWidth - judgementAreaWidth) / 2; - this.task = BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer( - this, - 50, - 33, - TimeUnit.MILLISECONDS - ); - } - - @Override - public void onTick() { - if (timer < 40 - (settings.difficulty() / 10)) { - timer++; - } else { - timer = 0; - if (Math.random() > ((double) 25 / (settings.difficulty() + 100))) { - burst(); - } - } - judgement_position += judgement_velocity; - fish_position += fish_velocity; - fraction(); - calibrate(); - if (fish_position >= judgement_position && fish_position + pointerIconWidth <= judgement_position + judgementAreaWidth) { - hold_time += 33; - } else { - hold_time -= punishment * 33; - } - if (hold_time >= time_requirement) { - setGameResult(true); - endGame(); - return; - } - hold_time = Math.max(0, Math.min(hold_time, time_requirement)); - showUI(); - } - - private void burst() { - if (Math.random() < (judgement_position / barEffectiveWidth)) { - judgement_velocity = -1 - 0.8 * Math.random() * ((double) settings.difficulty() / 15); - } else { - judgement_velocity = 1 + 0.8 * Math.random() * ((double) settings.difficulty() / 15); - } - } - - private void fraction() { - if (judgement_velocity > 0) { - judgement_velocity -= waterResistance; - if (judgement_velocity < 0) judgement_velocity = 0; - } else { - judgement_velocity += waterResistance; - if (judgement_velocity > 0) judgement_velocity = 0; - } - fish_velocity -= looseningLoss; - if (fish_velocity < -10 * looseningLoss) { - fish_velocity = -10 * looseningLoss; - } - } - - private void calibrate() { - if (fish_position < 0) { - fish_position = 0; - fish_velocity = 0; - } - if (fish_position + pointerIconWidth > barEffectiveWidth) { - fish_position = barEffectiveWidth - pointerIconWidth; - fish_velocity = 0; - } - if (judgement_position < 0) { - judgement_position = 0; - judgement_velocity = 0; - } - if (judgement_position + judgementAreaWidth > barEffectiveWidth) { - judgement_position = barEffectiveWidth - judgementAreaWidth; - judgement_velocity = 0; - } - } - - @Override - public boolean onRightClick() { - if (left) { - setGameResult(false); - endGame(); - return true; - } - played = true; - fish_velocity = pullingStrength; - return true; - } - - @Override - public boolean onLeftClick() { - if (preventFirst) { - preventFirst = false; - return false; - } - if (left) { - played = true; - fish_velocity = pullingStrength; - } - return false; - } - - public void showUI() { - String bar = FontUtils.surroundWithFont(barImage, font) - + OffsetUtils.getOffsetChars((int) (judgementAreaOffset + judgement_position)) - + FontUtils.surroundWithFont(judgementAreaImage, font) - + OffsetUtils.getOffsetChars((int) (barEffectiveWidth - judgement_position - judgementAreaWidth)) - + OffsetUtils.getOffsetChars((int) (-barEffectiveWidth - 1 + fish_position)) - + FontUtils.surroundWithFont(pointerImage, font) - + OffsetUtils.getOffsetChars((int) (barEffectiveWidth - fish_position - pointerIconWidth + 1)); - AdventureHelper.getInstance().sendTitle( - player, - tip != null && !played ? tip : title.replace("{progress}", progress[(int) ((hold_time / time_requirement) * progress.length)]), - bar, - 0, - 10, - 0 - ); - } - }; - })); - } - - /** - * Loads minigame expansions from the expansion folder. - */ - @SuppressWarnings("ResultOfMethodCallIgnored") - private void loadExpansions() { - File expansionFolder = new File(plugin.getDataFolder(), EXPANSION_FOLDER); - if (!expansionFolder.exists()) - expansionFolder.mkdirs(); - - List> classes = new ArrayList<>(); - File[] expansionJars = expansionFolder.listFiles(); - if (expansionJars == null) return; - for (File expansionJar : expansionJars) { - if (expansionJar.getName().endsWith(".jar")) { - try { - Class expansionClass = ClassUtils.findClass(expansionJar, GameExpansion.class); - classes.add(expansionClass); - } catch (IOException | ClassNotFoundException e) { - LogUtils.warn("Failed to load expansion: " + expansionJar.getName(), e); - } - } - } - try { - for (Class expansionClass : classes) { - GameExpansion expansion = expansionClass.getDeclaredConstructor().newInstance(); - unregisterGameType(expansion.getGameType()); - registerGameType(expansion.getGameType(), expansion.getGameFactory()); - LogUtils.info("Loaded minigame expansion: " + expansion.getGameType() + "[" + expansion.getVersion() + "]" + " by " + expansion.getAuthor() ); - } - } catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) { - LogUtils.warn("Error occurred when creating expansion instance.", e); - } - } -} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/gui/icon/property/item/Head64Item.java b/core/src/main/java/net/momirealms/customfishing/bukkit/gui/icon/property/item/Head64Item.java index cdcb9468..253ae248 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/gui/icon/property/item/Head64Item.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/gui/icon/property/item/Head64Item.java @@ -17,7 +17,6 @@ package net.momirealms.customfishing.bukkit.gui.icon.property.item; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper; import net.momirealms.customfishing.bukkit.gui.SectionPage; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/gui/page/property/MaterialEditor.java b/core/src/main/java/net/momirealms/customfishing/bukkit/gui/page/property/MaterialEditor.java index d1a077db..468a47a8 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/gui/page/property/MaterialEditor.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/gui/page/property/MaterialEditor.java @@ -21,7 +21,6 @@ import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper; import net.momirealms.customfishing.bukkit.gui.SectionPage; import net.momirealms.customfishing.bukkit.gui.icon.BackGroundItem; -import net.momirealms.customfishing.bukkit.item.ItemManagerImpl; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/hook/BukkitHookManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/hook/BukkitHookManager.java deleted file mode 100644 index ca91e814..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/hook/BukkitHookManager.java +++ /dev/null @@ -1,331 +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.bukkit.hook; - -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.mechanic.hook.HookManager; -import net.momirealms.customfishing.api.mechanic.hook.HookSetting; -import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; -import net.momirealms.customfishing.bukkit.item.ItemManagerImpl; -import net.momirealms.customfishing.bukkit.util.ItemUtils; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.*; - -public class BukkitHookManager implements Listener, HookManager { - - private final BukkitCustomFishingPlugin plugin; - private final HashMap hookSettingMap; - - public BukkitHookManager(BukkitCustomFishingPlugin plugin) { - this.plugin = plugin; - this.hookSettingMap = new HashMap<>(); - } - - public void load() { - Bukkit.getPluginManager().registerEvents(this, plugin); - loadConfig(); - } - - public void unload() { - HandlerList.unregisterAll(this); - hookSettingMap.clear(); - } - - public void disable() { - unload(); - } - - /** - * Loads configuration files for the specified types. - */ - @SuppressWarnings("DuplicatedCode") - private void loadConfig() { - Deque fileDeque = new ArrayDeque<>(); - for (String type : List.of("hook")) { - File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type); - if (!typeFolder.exists()) { - if (!typeFolder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false); - } - fileDeque.push(typeFolder); - while (!fileDeque.isEmpty()) { - File file = fileDeque.pop(); - File[] files = file.listFiles(); - if (files == null) continue; - for (File subFile : files) { - if (subFile.isDirectory()) { - fileDeque.push(subFile); - } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) { - this.loadSingleFile(subFile); - } - } - } - } - } - - /** - * Loads data from a single configuration file. - * - * @param file The configuration file to load. - */ - private void loadSingleFile(File file) { - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (Map.Entry entry : config.getValues(false).entrySet()) { - if (entry.getValue() instanceof ConfigurationSection section) { - if (!section.contains("max-durability")) { - LogUtils.warn("Please set max-durability to hook: " + entry.getKey()); - continue; - } - var setting = new HookSetting.Builder(entry.getKey()) - .durability(section.getInt("max-durability", 16)) - .lore(section.getStringList("lore-on-rod").stream().map(it -> "" + it).toList()) - .build(); - hookSettingMap.put(entry.getKey(), setting); - } - } - } - - /** - * Get the hook setting by its ID. - * - * @param id The ID of the hook setting to retrieve. - * @return The hook setting with the given ID, or null if not found. - */ - @Nullable - @Override - public HookSetting getHookSetting(String id) { - return hookSettingMap.get(id); - } - - /** - * Decreases the durability of a fishing hook by a specified amount and optionally updates its lore. - * - * @param rod The fishing rod ItemStack to modify. - * @param amount The amount by which to decrease the durability. - * @param updateLore Whether to update the lore of the fishing rod. - */ - @Override - public void decreaseHookDurability(ItemStack rod, int amount, boolean updateLore) { - ItemUtils.decreaseHookDurability(rod, amount, updateLore); - } - - /** - * Increases the durability of a fishing hook by a specified amount and optionally updates its lore. - * - * @param rod The fishing rod ItemStack to modify. - * @param amount The amount by which to increase the durability. - * @param updateLore Whether to update the lore of the fishing rod. - */ - @Override - public void increaseHookDurability(ItemStack rod, int amount, boolean updateLore) { - ItemUtils.increaseHookDurability(rod, amount, updateLore); - } - - /** - * Sets the durability of a fishing hook to a specific amount and optionally updates its lore. - * - * @param rod The fishing rod ItemStack to modify. - * @param amount The new durability value to set. - * @param updateLore Whether to update the lore of the fishing rod. - */ - @Override - public void setHookDurability(ItemStack rod, int amount, boolean updateLore) { - ItemUtils.setHookDurability(rod, amount, updateLore); - } - - /** - * Equips a fishing hook on a fishing rod. - * - * @param rod The fishing rod ItemStack. - * @param hook The fishing hook ItemStack. - * @return True if the hook was successfully equipped, false otherwise. - */ - @Override - public boolean equipHookOnRod(ItemStack rod, ItemStack hook) { - if (rod == null || hook == null || hook.getType() == Material.AIR || hook.getAmount() != 1) - return false; - if (rod.getType() != Material.FISHING_ROD) - return false; - - String hookID = plugin.getItemManager().getAnyPluginItemID(hook); - HookSetting setting = getHookSetting(hookID); - if (setting == null) - return false; - - var curDurability = ItemUtils.getCustomDurability(hook); - if (curDurability.left() == 0) - return false; - - NBTItem rodNBTItem = new NBTItem(rod); - NBTCompound cfCompound = rodNBTItem.getOrCreateCompound("CustomFishing"); - - cfCompound.setString("hook_id", hookID); - cfCompound.setItemStack("hook_item", hook); - cfCompound.setInteger("hook_dur", curDurability.right()); - - ItemUtils.updateNBTItemLore(rodNBTItem); - rod.setItemMeta(rodNBTItem.getItem().getItemMeta()); - return true; - } - - /** - * Removes the fishing hook from a fishing rod. - * - * @param rod The fishing rod ItemStack. - * @return The removed fishing hook ItemStack, or null if no hook was found. - */ - @Override - public ItemStack removeHookFromRod(ItemStack rod) { - if (rod == null || rod.getType() != Material.FISHING_ROD) - return null; - - NBTItem rodNBTItem = new NBTItem(rod); - NBTCompound cfCompound = rodNBTItem.getCompound("CustomFishing"); - if (cfCompound == null) - return null; - - ItemStack hook = cfCompound.getItemStack("hook_item"); - if (hook != null) { - cfCompound.removeKey("hook_item"); - cfCompound.removeKey("hook_id"); - cfCompound.removeKey("hook_dur"); - ItemUtils.updateNBTItemLore(rodNBTItem); - rod.setItemMeta(rodNBTItem.getItem().getItemMeta()); - } - - return hook; - } - - /** - * Handles the event when a player clicks on a fishing rod in their inventory. - * - * @param event The InventoryClickEvent to handle. - */ - @EventHandler - @SuppressWarnings("deprecation") - public void onDragDrop(InventoryClickEvent event) { - if (event.isCancelled()) - return; - final Player player = (Player) event.getWhoClicked(); - if (event.getClickedInventory() != player.getInventory()) - return; - ItemStack clicked = event.getCurrentItem(); - if (clicked == null || clicked.getType() != Material.FISHING_ROD) - return; - if (player.getGameMode() != GameMode.SURVIVAL) - return; - if (plugin.getFishingManager().hasPlayerCastHook(player.getUniqueId())) - return; - - ItemStack cursor = event.getCursor(); - if (cursor == null || cursor.getType() == Material.AIR) { - if (event.getClick() == ClickType.RIGHT) { - NBTItem nbtItem = new NBTItem(clicked); - NBTCompound cfCompound = nbtItem.getCompound("CustomFishing"); - if (cfCompound == null) - return; - if (cfCompound.hasTag("hook_id")) { - event.setCancelled(true); - ItemStack hook = cfCompound.getItemStack("hook_item"); - ItemUtils.setDurability(hook, cfCompound.getInteger("hook_dur"), true); - cfCompound.removeKey("hook_id"); - cfCompound.removeKey("hook_item"); - cfCompound.removeKey("hook_dur"); - event.setCursor(hook); - ItemUtils.updateNBTItemLore(nbtItem); - clicked.setItemMeta(nbtItem.getItem().getItemMeta()); - } - } - return; - } - - String hookID = plugin.getItemManager().getAnyPluginItemID(cursor); - HookSetting setting = getHookSetting(hookID); - if (setting == null) - return; - - var cursorDurability = ItemUtils.getCustomDurability(cursor); - if (cursorDurability.left() == 0) { - if (plugin.getItemManager().getBuildableItem("hook", hookID) instanceof ItemManagerImpl.CFBuilder cfBuilder) { - ItemStack itemStack = cfBuilder.build(player, new HashMap<>()); - var pair = ItemUtils.getCustomDurability(itemStack); - cursorDurability = pair; - NBTItem nbtItem = new NBTItem(cursor); - NBTCompound compound = nbtItem.getOrCreateCompound("CustomFishing"); - compound.setInteger("max_dur", pair.left()); - compound.setInteger("cur_dur", pair.right()); - compound.setString("type", "hook"); - compound.setString("id", hookID); - cursor.setItemMeta(nbtItem.getItem().getItemMeta()); - } else { - return; - } - } - - PlayerContext playerContext = new PlayerContext(player, new HashMap<>()); - playerContext.insertArg("{rod}", plugin.getItemManager().getAnyPluginItemID(clicked)); - EffectCarrier effectCarrier = plugin.getEffectManager().getEffectCarrier("hook", hookID); - if (effectCarrier != null) { - if (!RequirementManager.isRequirementMet(playerContext, effectCarrier.getRequirements())) { - return; - } - } - - event.setCancelled(true); - - NBTItem rodNBTItem = new NBTItem(clicked); - NBTCompound cfCompound = rodNBTItem.getOrCreateCompound("CustomFishing"); - String previousHookID = cfCompound.getString("hook_id"); - - ItemStack clonedHook = cursor.clone(); - clonedHook.setAmount(1); - cursor.setAmount(cursor.getAmount() - 1); - - if (previousHookID != null && !previousHookID.equals("")) { - int previousHookDurability = cfCompound.getInteger("hook_dur"); - ItemStack previousItemStack = cfCompound.getItemStack("hook_item"); - ItemUtils.setDurability(previousItemStack, previousHookDurability, true); - if (cursor.getAmount() == 0) { - event.setCursor(previousItemStack); - } else { - ItemUtils.giveItem(player, previousItemStack, 1); - } - } - - cfCompound.setString("hook_id", hookID); - cfCompound.setItemStack("hook_item", clonedHook); - cfCompound.setInteger("hook_dur", cursorDurability.right()); - - ItemUtils.updateNBTItemLore(rodNBTItem); - clicked.setItemMeta(rodNBTItem.getItem().getItemMeta()); - } -} 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 new file mode 100644 index 00000000..cb2882b3 --- /dev/null +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/integration/BukkitIntegrationManager.java @@ -0,0 +1,244 @@ +/* + * 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.bukkit.integration; + +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.integration.*; +import net.momirealms.customfishing.bukkit.block.BukkitBlockManager; +import net.momirealms.customfishing.bukkit.entity.BukkitEntityManager; +import net.momirealms.customfishing.bukkit.integration.block.ItemsAdderBlockProvider; +import net.momirealms.customfishing.bukkit.integration.block.OraxenBlockProvider; +import net.momirealms.customfishing.bukkit.integration.enchant.AdvancedEnchantmentsProvider; +import net.momirealms.customfishing.bukkit.integration.entity.ItemsAdderEntityProvider; +import net.momirealms.customfishing.bukkit.integration.entity.MythicEntityProvider; +import net.momirealms.customfishing.bukkit.integration.item.*; +import net.momirealms.customfishing.bukkit.integration.level.*; +import net.momirealms.customfishing.bukkit.integration.quest.BattlePassQuest; +import net.momirealms.customfishing.bukkit.integration.quest.BetonQuestQuest; +import net.momirealms.customfishing.bukkit.integration.quest.ClueScrollsQuest; +import net.momirealms.customfishing.bukkit.integration.season.AdvancedSeasonsProvider; +import net.momirealms.customfishing.bukkit.integration.season.CustomCropsSeasonProvider; +import net.momirealms.customfishing.bukkit.integration.season.RealisticSeasonsProvider; +import net.momirealms.customfishing.bukkit.item.BukkitItemManager; +import net.momirealms.customfishing.common.util.Pair; +import org.bukkit.Bukkit; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class BukkitIntegrationManager implements IntegrationManager { + + private final BukkitCustomFishingPlugin plugin; + private final HashMap levelerProviders; + private final HashMap enchantmentProviders; + private SeasonProvider seasonProvider; + + public BukkitIntegrationManager(BukkitCustomFishingPlugin plugin) { + this.plugin = plugin; + this.levelerProviders = new HashMap<>(); + this.enchantmentProviders = new HashMap<>(); + this.load(); + } + + public void disable() { + this.enchantmentProviders.clear(); + this.levelerProviders.clear(); + } + + public void load() { + if (isHooked("ItemsAdder")) { + registerItemProvider(new ItemsAdderItemProvider()); + registerBlockProvider(new ItemsAdderBlockProvider()); + registerEntityProvider(new ItemsAdderEntityProvider()); + } + if (isHooked("MMOItems")) { + registerItemProvider(new MMOItemsItemProvider()); + } + if (isHooked("Oraxen")) { + registerItemProvider(new OraxenItemProvider()); + registerBlockProvider(new OraxenBlockProvider()); + } + if (isHooked("Zaphkiel")) { + registerItemProvider(new ZaphkielItemProvider()); + } + if (isHooked("NeigeItems")) { + registerItemProvider(new NeigeItemsItemProvider()); + } + if (isHooked("MythicMobs")) { + registerItemProvider(new MythicMobsItemProvider()); + registerEntityProvider(new MythicEntityProvider()); + } + if (isHooked("EcoJobs")) { + registerLevelerProvider(new EcoJobsLevelerProvider()); + } + if (isHooked("EcoSkills")) { + registerLevelerProvider(new EcoSkillsLevelerProvider()); + } + if (isHooked("Jobs")) { + registerLevelerProvider(new JobsRebornLevelerProvider()); + } + if (isHooked("MMOCore")) { + registerLevelerProvider(new MMOCoreLevelerProvider()); + } + if (isHooked("mcMMO")) { + try { + registerItemProvider(new McMMOTreasureProvider()); + } catch (ClassNotFoundException | NoSuchMethodException e) { + plugin.getPluginLogger().warn("Failed to initialize mcMMO Treasure"); + } + registerLevelerProvider(new McMMOLevelerProvider()); + } + if (isHooked("AureliumSkills")) { + registerLevelerProvider(new AureliumSkillsProvider()); + } + if (isHooked("AuraSkills")) { + registerLevelerProvider(new AuraSkillsLevelerProvider()); + } + if (isHooked("AdvancedEnchantments")) { + registerEnchantmentProvider(new AdvancedEnchantmentsProvider()); + } + if (isHooked("RealisticSeasons")) { + registerSeasonProvider(new RealisticSeasonsProvider()); + } else if (isHooked("AdvancedSeasons")) { + registerSeasonProvider(new AdvancedSeasonsProvider()); + } else if (isHooked("CustomCrops")) { + registerSeasonProvider(new CustomCropsSeasonProvider()); + } + if (isHooked("Vault")) { + VaultHook.initialize(); + } + if (isHooked("BattlePass")){ + BattlePassQuest battlePassQuest = new BattlePassQuest(); + battlePassQuest.register(); + } + if (isHooked("ClueScrolls")) { + ClueScrollsQuest clueScrollsQuest = new ClueScrollsQuest(); + clueScrollsQuest.register(); + } + if (isHooked("BetonQuest")) { + BetonQuestQuest.register(); + } + } + + private boolean isHooked(String hooked) { + if (Bukkit.getPluginManager().getPlugin(hooked) != null) { + plugin.getPluginLogger().info(hooked + " hooked!"); + return true; + } + return false; + } + + @Override + public boolean registerLevelerProvider(@NotNull LevelerProvider leveler) { + if (levelerProviders.containsKey(leveler.identifier())) return false; + levelerProviders.put(leveler.identifier(), leveler); + return true; + } + + @Override + public boolean unregisterLevelerProvider(@NotNull String id) { + return levelerProviders.remove(id) != null; + } + + @Override + public boolean registerEnchantmentProvider(@NotNull EnchantmentProvider enchantment) { + if (enchantmentProviders.containsKey(enchantment.identifier())) return false; + enchantmentProviders.put(enchantment.identifier(), enchantment); + return true; + } + + @Override + public boolean unregisterEnchantmentProvider(@NotNull String id) { + return enchantmentProviders.remove(id) != null; + } + + @Override + @Nullable + public LevelerProvider getLevelerProvider(String plugin) { + return levelerProviders.get(plugin); + } + + @Override + @Nullable + public EnchantmentProvider getEnchantmentProvider(String id) { + return enchantmentProviders.get(id); + } + + @Override + public List> getEnchantments(ItemStack itemStack) { + ArrayList> list = new ArrayList<>(); + for (EnchantmentProvider enchantmentProvider : enchantmentProviders.values()) { + list.addAll(enchantmentProvider.getEnchants(itemStack)); + } + return list; + } + + @Nullable + @Override + public SeasonProvider getSeasonProvider() { + return seasonProvider; + } + + @Override + public boolean registerSeasonProvider(@NotNull SeasonProvider season) { + if (this.seasonProvider != null) return false; + this.seasonProvider = season; + return true; + } + + @Override + public boolean unregisterSeasonProvider() { + if (this.seasonProvider == null) return false; + this.seasonProvider = null; + return true; + } + + @Override + public boolean registerEntityProvider(@NotNull EntityProvider entity) { + return ((BukkitEntityManager) plugin.getEntityManager()).registerEntityProvider(entity); + } + + @Override + public boolean unregisterEntityProvider(@NotNull String id) { + return ((BukkitEntityManager) plugin.getEntityManager()).unregisterEntityProvider(id); + } + + @Override + public boolean registerItemProvider(@NotNull ItemProvider item) { + return ((BukkitItemManager) plugin.getItemManager()).registerItemProvider(item); + } + + @Override + public boolean unregisterItemProvider(@NotNull String id) { + return ((BukkitItemManager) plugin.getItemManager()).unregisterItemProvider(id); + } + + @Override + public boolean registerBlockProvider(@NotNull BlockProvider block) { + return ((BukkitBlockManager) plugin.getBlockManager()).registerBlockProvider(block); + } + + @Override + public boolean unregisterBlockProvider(@NotNull String id) { + return ((BukkitBlockManager) plugin.getBlockManager()).unregisterBlockProvider(id); + } +} diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemFactory.java b/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemFactory.java index e8a3877a..1d5d7c30 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemFactory.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/item/BukkitItemFactory.java @@ -48,6 +48,16 @@ public abstract class BukkitItemFactory extends ItemFactory itemProviders = new HashMap<>(); - private final HashMap itemMap = new HashMap<>(); + private final HashMap items = new HashMap<>(); private final BukkitItemFactory factory; + private ItemProvider[] itemDetectArray; public BukkitItemManager(BukkitCustomFishingPlugin plugin) { this.plugin = plugin; this.factory = BukkitItemFactory.create(plugin); - this.registerVanilla(); - } - - private void registerVanilla() { - this.itemProviders.put("vanilla", new ItemProvider() { + this.registerItemProvider(new ItemProvider() { @NotNull @Override public ItemStack buildItem(@NotNull Player player, @NotNull String id) { @@ -51,10 +72,27 @@ public class BukkitItemManager implements ItemManager { }); } + @Override + public void unload() { + HandlerList.unregisterAll(this); + } + + @Override + public void load() { + Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap()); + } + + @Override + public boolean registerItem(@NotNull Key key, @NotNull CustomFishingItem item) { + if (items.containsKey(key)) return false; + items.put(key, item); + return true; + } + @Nullable @Override - public ItemStack buildInternal(Context context, Key key) { - CustomFishingItem item = requireNonNull(itemMap.get(key), () -> "No item found for " + key); + public ItemStack buildInternal(@NotNull Context context, @NotNull Key key) { + CustomFishingItem item = requireNonNull(items.get(key), () -> "No item found for " + key); ItemStack itemStack = getOriginalStack(context.getHolder(), item.material()); Item wrappedItemStack = factory.wrap(itemStack); for (BiConsumer, Context> consumer : item.tagConsumers()) { @@ -63,8 +101,70 @@ public class BukkitItemManager implements ItemManager { return wrappedItemStack.getItem(); } + @Override + public ItemStack buildAny(@NotNull Context context, @NotNull String item) { + return getOriginalStack(context.getHolder(), item); + } + + @NotNull + @Override + public String getItemID(@NotNull ItemStack itemStack) { + if (itemStack.getType() == Material.AIR) + return "AIR"; + for (ItemProvider library : itemDetectArray) { + String id = library.itemID(itemStack); + if (id != null) + return id; + } + // should not reach this because vanilla library would always work + return "AIR"; + } + + @Override + public String getCustomFishingItemID(@NotNull ItemStack itemStack) { + return (String) factory.wrap(itemStack).getTag("CustomFishing", "id").orElse(null); + } + + @Nullable + @Override + @SuppressWarnings("all") + public org.bukkit.entity.Item dropItemLoot(@NotNull Context context) { + String id = requireNonNull(context.arg(ContextKeys.ID)); + ItemStack itemStack = requireNonNull(buildInternal(context, Key.key("item", id))); + 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; + } + + org.bukkit.entity.Item itemEntity = hookLocation.getWorld().dropItem(hookLocation, itemStack); + FishingLootSpawnEvent spawnEvent = new FishingLootSpawnEvent(player, hookLocation, itemEntity); + Bukkit.getPluginManager().callEvent(spawnEvent); + if (spawnEvent.isCancelled()) { + itemEntity.remove(); + return null; + } + + itemEntity.setInvulnerable(true); + // prevent from being killed by lava + plugin.getScheduler().asyncLater(() -> { + if (itemEntity.isValid()) + 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; + } + private ItemStack getOriginalStack(Player player, String material) { - if (material.contains(":")) { + if (!material.contains(":")) { try { return new ItemStack(Material.valueOf(material.toUpperCase(Locale.ENGLISH))); } catch (IllegalArgumentException e) { @@ -73,8 +173,132 @@ public class BukkitItemManager implements ItemManager { } } else { String[] split = material.split(":", 2); - ItemProvider provider = requireNonNull(itemProviders.get(split[0]), "item provider " + split[0] + " not found"); - return requireNonNull(provider.buildItem(player, split[0]), "item " + split[0] + " not found"); + ItemProvider provider = requireNonNull(itemProviders.get(split[0]), "Item provider: " + split[0] + " not found"); + return requireNonNull(provider.buildItem(player, split[0]), "Item: " + split[0] + " not found"); } } + + private void resetItemDetectionOrder() { + ArrayList list = new ArrayList<>(); + for (String plugin : ConfigManager.itemDetectOrder()) { + ItemProvider provider = itemProviders.get(plugin); + if (provider != null) + list.add(provider); + } + this.itemDetectArray = list.toArray(new ItemProvider[0]); + } + + public boolean registerItemProvider(ItemProvider item) { + if (itemProviders.containsKey(item.identifier())) return false; + itemProviders.put(item.identifier(), item); + this.resetItemDetectionOrder(); + return true; + } + + public boolean unregisterItemProvider(String id) { + boolean success = itemProviders.remove(id) != null; + if (success) + this.resetItemDetectionOrder(); + return success; + } + + @EventHandler(ignoreCancelled = true) + public void onInvPickItem(InventoryPickupItemEvent event) { + ItemStack itemStack = event.getItem().getItemStack(); + Item wrapped = factory.wrap(itemStack); + if (wrapped.hasTag("owner")) { + wrapped.removeTag("owner"); + itemStack.setItemMeta(wrapped.getItem().getItemMeta()); + } + } + + @EventHandler (ignoreCancelled = true) + public void onPlaceBlock(BlockPlaceEvent event) { + ItemStack itemStack = event.getItemInHand(); + if (itemStack.getType() == Material.AIR || itemStack.getAmount() == 0 || !itemStack.hasItemMeta()) { + return; + } + + Item wrapped = factory.wrap(itemStack); + if (wrapped.hasTag("CustomFishing")) { + if (!wrapped.hasTag("CustomFishing", "placeable")) { + event.setCancelled(true); + return; + } + Block block = event.getBlock(); + if (block.getState() instanceof Skull) { + PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); + ItemStack cloned = itemStack.clone(); + cloned.setAmount(1); + pdc.set(new NamespacedKey(plugin.getBoostrap(), LocationUtils.toChunkPosString(block.getLocation())), PersistentDataType.STRING, ItemUtils.toBase64(cloned)); + } else { + event.setCancelled(true); + } + } + } + + @EventHandler (ignoreCancelled = true) + public void onBreakBlock(BlockBreakEvent event) { + final Block block = event.getBlock(); + if (block.getState() instanceof Skull) { + PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); + String base64 = pdc.get(new NamespacedKey(plugin.getBoostrap(), LocationUtils.toChunkPosString(block.getLocation())), PersistentDataType.STRING); + if (base64 != null) { + ItemStack itemStack = ItemUtils.fromBase64(base64); + event.setDropItems(false); + block.getLocation().getWorld().dropItemNaturally(block.getLocation(), itemStack); + } + } + } + + @EventHandler (ignoreCancelled = true) + public void onPiston(BlockPistonExtendEvent event) { + handlePiston(event, event.getBlocks()); + } + + @EventHandler (ignoreCancelled = true) + public void onPiston(BlockPistonRetractEvent event) { + handlePiston(event, event.getBlocks()); + } + + private void handlePiston(Cancellable event, List blockList) { + for (Block block : blockList) { + if (block.getState() instanceof Skull) { + PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); + if (pdc.has(new NamespacedKey(plugin.getBoostrap(), LocationUtils.toChunkPosString(block.getLocation())), PersistentDataType.STRING)) { + event.setCancelled(true); + return; + } + } + } + } + + @EventHandler (ignoreCancelled = true) + public void onExplosion(BlockExplodeEvent event) { + handleExplosion(event.blockList()); + } + + @EventHandler (ignoreCancelled = true) + public void onExplosion(EntityExplodeEvent event) { + handleExplosion(event.blockList()); + } + + private void handleExplosion(List blocks) { + ArrayList blockToRemove = new ArrayList<>(); + for (Block block : blocks) { + if (block.getState() instanceof Skull) { + PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); + var nk = new NamespacedKey(plugin.getBoostrap(), LocationUtils.toChunkPosString(block.getLocation())); + String base64 = pdc.get(nk, PersistentDataType.STRING); + if (base64 != null) { + ItemStack itemStack = ItemUtils.fromBase64(base64); + block.getLocation().getWorld().dropItemNaturally(block.getLocation(), itemStack); + blockToRemove.add(block); + block.setType(Material.AIR); + pdc.remove(nk); + } + } + } + blocks.removeAll(blockToRemove); + } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/item/ItemManagerImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/item/ItemManagerImpl.java deleted file mode 100644 index 3b42987b..00000000 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/item/ItemManagerImpl.java +++ /dev/null @@ -1,1110 +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.bukkit.item; - -import com.saicone.rtag.RtagItem; -import com.saicone.rtag.tag.TagCompound; -import com.saicone.rtag.tag.TagList; -import de.tr7zw.changeme.nbtapi.*; -import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; -import net.momirealms.customfishing.api.common.Key; -import net.momirealms.customfishing.api.common.Pair; -import net.momirealms.customfishing.api.common.Tuple; -import net.momirealms.customfishing.api.event.FishingBagPreCollectEvent; -import net.momirealms.customfishing.api.event.FishingLootPreSpawnEvent; -import net.momirealms.customfishing.api.event.FishingLootSpawnEvent; -import net.momirealms.customfishing.api.integration.ItemProvider; -import net.momirealms.customfishing.api.mechanic.action.Action; -import net.momirealms.customfishing.api.mechanic.action.ActionManager; -import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; -import net.momirealms.customfishing.api.mechanic.item.ItemManager; -import net.momirealms.customfishing.api.mechanic.loot.Loot; -import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager; -import net.momirealms.customfishing.api.mechanic.misc.value.MathValue; -import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; -import net.momirealms.customfishing.bukkit.compatibility.item.CustomFishingItemProvider; -import net.momirealms.customfishing.bukkit.util.ConfigUtils; -import net.momirealms.customfishing.bukkit.util.ItemUtils; -import net.momirealms.customfishing.bukkit.util.LocationUtils; -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.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Item; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.block.*; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.inventory.InventoryPickupItemEvent; -import org.bukkit.event.inventory.PrepareAnvilEvent; -import org.bukkit.event.player.PlayerAttemptPickupItemEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; -import org.bukkit.event.player.PlayerItemMendEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; - -public class ItemManagerImpl implements ItemManager, Listener { - - private static ItemManager instance; - private final BukkitCustomFishingPlugin plugin; - private final HashMap buildableItemMap; - private final HashMap itemLibraryMap; - private ItemProvider[] itemDetectionArray; - private NamespacedKey blockKey; - - public ItemManagerImpl(BukkitCustomFishingPlugin plugin) { - instance = this; - this.plugin = plugin; - this.itemLibraryMap = new LinkedHashMap<>(); - this.buildableItemMap = new HashMap<>(); - this.blockKey = NamespacedKey.fromString("block", plugin); - this.registerItemLibrary(new CustomFishingItemProvider()); - this.registerItemLibrary(new VanillaItemImpl()); - } - - public void load() { - this.loadItemsFromPluginFolder(); - Bukkit.getPluginManager().registerEvents(this, plugin); - this.resetItemDetectionOrder(); - } - - public void unload() { - HandlerList.unregisterAll(this); - HashMap tempMap = new HashMap<>(this.buildableItemMap); - this.buildableItemMap.clear(); - for (Map.Entry entry : tempMap.entrySet()) { - if (entry.getValue().persist()) { - tempMap.put(entry.getKey(), entry.getValue()); - } - } - } - - private void resetItemDetectionOrder() { - ArrayList list = new ArrayList<>(); - for (String plugin : CFConfig.itemDetectOrder) { - ItemProvider library = itemLibraryMap.get(plugin); - if (library != null) { - list.add(library); - } - } - this.itemDetectionArray = list.toArray(new ItemProvider[0]); - } - - public Collection getItemLibraries() { - return itemLibraryMap.keySet(); - } - - /** - * Get a set of all item keys in the CustomFishing plugin. - * - * @return A set of item keys. - */ - @Override - public Set getAllItemsKey() { - return buildableItemMap.keySet(); - } - - public void disable() { - HandlerList.unregisterAll(this); - this.buildableItemMap.clear(); - this.itemLibraryMap.clear(); - } - - /** - * Loads items from the plugin folder. - * This method scans various item types (item, bait, rod, util, hook) in the plugin's content folder and loads their configurations. - */ - @SuppressWarnings("DuplicatedCode") - public void loadItemsFromPluginFolder() { - Deque fileDeque = new ArrayDeque<>(); - for (String type : List.of("item", "bait", "rod", "util", "hook")) { - File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type); - if (!typeFolder.exists()) { - if (!typeFolder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false); - } - fileDeque.push(typeFolder); - while (!fileDeque.isEmpty()) { - File file = fileDeque.pop(); - File[] files = file.listFiles(); - if (files == null) continue; - for (File subFile : files) { - if (subFile.isDirectory()) { - fileDeque.push(subFile); - } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) { - this.loadSingleFile(subFile, type); - } - } - } - } - } - - /** - * Loads a single item configuration file. - * - * @param file The YAML configuration file to load. - * @param namespace The namespace of the item type (item, bait, rod, util, hook). - */ - private void loadSingleFile(File file, String namespace) { - YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file); - for (Map.Entry entry : yaml.getValues(false).entrySet()) { - String value = entry.getKey(); - if (entry.getValue() instanceof ConfigurationSection section) { - Key key = Key.of(namespace, value); - if (buildableItemMap.containsKey(key)) { - LogUtils.severe("Duplicated item key found: " + key + "."); - } else { - buildableItemMap.put(key, getItemBuilder(section, namespace, value)); - } - } - } - } - - /** - * Build an ItemStack with a specified namespace and value for a player. - * - * @param player The player for whom the ItemStack is being built. - * @param namespace The namespace of the item. - * @param value The value of the item. - * @return The constructed ItemStack. - */ - - - /** - * Build an ItemStack with a specified namespace and value, replacing placeholders, - * for a player. - * - * @param player The player for whom the ItemStack is being built. - * @param namespace The namespace of the item. - * @param value The value of the item. - * @param placeholders The placeholders to replace in the item's attributes. - * @return The constructed ItemStack, or null if the item doesn't exist. - */ - @Override - public ItemStack build(Player player, String namespace, String value, Map placeholders) { - BuildableItem buildableItem = buildableItemMap.get(Key.of(namespace, value)); - if (buildableItem == null) return null; - return buildableItem.build(player, placeholders); - } - - /** - * Build an ItemStack using an ItemBuilder for a player. - * - * @param player The player for whom the ItemStack is being built. - * @param builder The ItemBuilder used to construct the ItemStack. - * @return The constructed ItemStack. - */ - @NotNull - @Override - public ItemStack build(Player player, ItemBuilder builder) { - return build(player, builder, new HashMap<>()); - } - - /** - * Retrieve a BuildableItem by its namespace and value. - * - * @param namespace The namespace of the BuildableItem. - * @param value The value of the BuildableItem. - * @return The BuildableItem with the specified namespace and value, or null if not found. - */ - @Override - @Nullable - public BuildableItem getBuildableItem(String namespace, String value) { - return buildableItemMap.get(Key.of(namespace, value)); - } - - /** - * Get the item ID associated with the given ItemStack by checking all available item libraries. - * The detection order is determined by the configuration. - * - * @param itemStack The ItemStack to retrieve the item ID from. - * @return The item ID or "AIR" if not found or if the ItemStack is null or empty. - */ - @NotNull - @Override - public String getAnyPluginItemID(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) - return "AIR"; - for (ItemProvider library : itemDetectionArray) { - String id = library.itemID(itemStack); - if (id != null) { - return id; - } - } - // should not reach this because vanilla library would always work - return "AIR"; - } - - /** - * Build an ItemStack for a player based on the provided item ID. - * - * @param player The player for whom the ItemStack is being built. - * @param id The item ID, which may include a namespace (e.g., "namespace:id"). - * @return The constructed ItemStack or null if the ID is not valid. - */ - @Override - public ItemStack buildAnyPluginItemByID(Player player, String id) { - if (id.contains(":")) { - String[] split = id.split(":", 2); - return itemLibraryMap.get(split[0]).buildItem(player, split[1]); - } else { - try { - return new ItemStack(Material.valueOf(id.toUpperCase(Locale.ENGLISH))); - } catch (IllegalArgumentException e) { - return new ItemStack(Material.COD); - } - } - } - - /** - * Checks if the provided ItemStack is a custom fishing item - * - * @param itemStack The ItemStack to check. - * @return True if the ItemStack is a custom fishing item; otherwise, false. - */ - @Override - public boolean isCustomFishingItem(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return false; - NBTItem nbtItem = new NBTItem(itemStack); - return nbtItem.hasTag("CustomFishing") && !nbtItem.getCompound("CustomFishing").getString("id").equals(""); - } - - /** - * Get the item ID associated with the given ItemStack, if available. - * - * @param itemStack The ItemStack to retrieve the item ID from. - * @return The item ID or null if not found or if the ItemStack is null or empty. - */ - @Nullable - @Override - public String getCustomFishingItemID(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return null; - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound cfCompound = nbtItem.getCompound("CustomFishing"); - if (cfCompound == null) return null; - return cfCompound.getString("id"); - } - - /** - * Create a CFBuilder instance for an item configuration section - * - * @param section The configuration section containing item settings. - * @param type The type of the item (e.g., "rod", "bait"). - * @param id The unique identifier for the item. - * @return A CFBuilder instance representing the configured item, or null if the section is null. - */ - @Nullable - @Override - public CFBuilder getItemBuilder(ConfigurationSection section, String type, String id) { - if (section == null) return null; - String material = section.getString("material", type.equals("rod") ? "FISHING_ROD" : "PAPER"); - CFBuilder itemCFBuilder; - if (material.contains(":")) { - String[] split = material.split(":", 2); - itemCFBuilder = CFBuilder.of(split[0], split[1]); - } else { - itemCFBuilder = CFBuilder.of("vanilla", material.toUpperCase(Locale.ENGLISH)); - } - itemCFBuilder - .stackable(section.getBoolean("stackable", true)) - .size(ConfigUtils.getFloatPair(section.getString("size"))) - .price((float) section.getDouble("price.base"), (float) section.getDouble("price.bonus")) - .customModelData(section.getInt("custom-model-data")) - .nbt(section.getConfigurationSection("nbt")) - .maxDurability(section.getInt("max-durability")) - .itemFlag(section.getStringList("item-flags").stream().map(flag -> ItemFlag.valueOf(flag.toUpperCase())).toList()) - .enchantment(ConfigUtils.getEnchantmentPair(section.getConfigurationSection("enchantments")), false) - .enchantment(ConfigUtils.getEnchantmentPair(section.getConfigurationSection("stored-enchantments")), true) - .enchantmentPool(ConfigUtils.getEnchantAmountPair(section.getConfigurationSection("enchantment-pool.amount")), ConfigUtils.getEnchantPoolPair(section.getConfigurationSection("enchantment-pool.pool")), false) - .enchantmentPool(ConfigUtils.getEnchantAmountPair(section.getConfigurationSection("stored-enchantment-pool.amount")), ConfigUtils.getEnchantPoolPair(section.getConfigurationSection("stored-enchantment-pool.pool")), true) - .randomEnchantments(ConfigUtils.getEnchantmentTuple(section.getConfigurationSection("random-enchantments")), false) - .randomEnchantments(ConfigUtils.getEnchantmentTuple(section.getConfigurationSection("random-stored-enchantments")), true) - .tag(section.getBoolean("tag", true), type, id) - .randomDamage(section.getBoolean("random-durability", false)) - .unbreakable(section.getBoolean("unbreakable", false)) - .preventGrabbing(section.getBoolean("prevent-grabbing", true)) - .placeable(section.getBoolean("placeable", false)) - .head(section.getString("head64")) - .name(section.getString("display.name")) - .lore(section.getStringList("display.lore")); - if (section.get("amount") instanceof String s) { - Pair pair = ConfigUtils.getIntegerPair(s); - itemCFBuilder.amount(pair.left(), pair.right()); - } else { - itemCFBuilder.amount(section.getInt("amount", 1)); - } - return itemCFBuilder; - } - - /** - * Build an ItemStack using the provided ItemBuilder, player, and placeholders. - * - * @param player The player for whom the item is being built. - * @param builder The ItemBuilder that defines the item's properties. - * @param placeholders A map of placeholders and their corresponding values to be applied to the item. - * @return The constructed ItemStack. - */ - @Override - @NotNull - public ItemStack build(Player player, ItemBuilder builder, Map placeholders) { - ItemStack temp = itemLibraryMap.get(builder.getLibrary()).buildItem(player, builder.getId()); - if (temp.getType() == Material.AIR) { - return temp; - } - int amount = builder.getAmount(); - temp.setAmount(amount); - RtagItem nbtItem = new RtagItem(temp); - for (ItemBuilder.ItemPropertyEditor editor : builder.getEditors()) { - editor.edit(player, nbtItem, placeholders); - } - // TODO FIX - //ItemUtils.updateNBTItemLore(nbtItem); - return nbtItem.getItem(); - } - - @Override - public ItemStack getItemStackAppearance(Player player, String material) { - if (material != null) { - ItemStack itemStack = buildAnyPluginItemByID(player, material); - if (itemStack != null) { - ItemStack cloned = new ItemStack(itemStack.getType()); - ItemMeta meta = cloned.getItemMeta(); - if (itemStack.getItemMeta().hasCustomModelData()) { - meta.setCustomModelData(itemStack.getItemMeta().getCustomModelData()); - } - cloned.setItemMeta(meta); - return cloned; - } else { - return new ItemStack(Material.BARRIER); - } - } else { - return new ItemStack(Material.STRUCTURE_VOID); - } - } - - /** - * Register an item library. - * - * @param itemProvider The item library to register. - * @return True if the item library was successfully registered, false if it already exists. - */ - @Override - public boolean registerItemLibrary(ItemProvider itemProvider) { - if (itemLibraryMap.containsKey(itemProvider.identification())) return false; - itemLibraryMap.put(itemProvider.identification(), itemProvider); - this.resetItemDetectionOrder(); - return true; - } - - /** - * Unregister an item library. - * - * @param identification The item library to unregister. - * @return True if the item library was successfully unregistered, false if it doesn't exist. - */ - @Override - public boolean unRegisterItemLibrary(String identification) { - boolean success = itemLibraryMap.remove(identification) != null; - if (success) - this.resetItemDetectionOrder(); - return success; - } - - @Override - public void dropItem(Player player, Location hookLocation, Location playerLocation, ItemStack item, PlayerContext playerContext) { - if (item.getType() == Material.AIR) { - return; - } - - if (CFConfig.enableFishingBag && plugin.getBagManager().doesBagStoreLoots() && RequirementManager.isRequirementMet(playerContext, plugin.getBagManager().getCollectRequirements())) { - var bag = plugin.getBagManager().getOnlineBagInventory(player.getUniqueId()); - - FishingBagPreCollectEvent preCollectEvent = new FishingBagPreCollectEvent(player, item, bag); - Bukkit.getPluginManager().callEvent(preCollectEvent); - if (preCollectEvent.isCancelled()) { - return; - } - - int cannotPut = ItemUtils.putLootsToBag(bag, item, item.getAmount()); - // some are put into bag - if (cannotPut != item.getAmount()) { - ActionManager.triggerActions(playerContext, plugin.getBagManager().getCollectLootActions()); - } - // all are put - if (cannotPut == 0) { - return; - } - // bag is full - item.setAmount(cannotPut); - ActionManager.triggerActions(playerContext, plugin.getBagManager().getBagFullActions()); - } - - FishingLootPreSpawnEvent preSpawnEvent = new FishingLootPreSpawnEvent(player, hookLocation, item); - Bukkit.getPluginManager().callEvent(preSpawnEvent); - if (preSpawnEvent.isCancelled()) { - return; - } - - Item itemEntity = hookLocation.getWorld().dropItem(hookLocation, item); - FishingLootSpawnEvent spawnEvent = new FishingLootSpawnEvent(player, hookLocation, itemEntity); - Bukkit.getPluginManager().callEvent(spawnEvent); - if (spawnEvent.isCancelled()) { - itemEntity.remove(); - return; - } - - itemEntity.setInvulnerable(true); - plugin.getScheduler().runTaskAsyncLater(() -> { - if (itemEntity.isValid()) { - 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); - } - - /** - * Decreases the durability of an ItemStack by a specified amount and optionally updates its lore. - * - * @param player Player - * @param itemStack The ItemStack to modify. - * @param amount The amount by which to decrease the durability. - * @param updateLore Whether to update the lore of the ItemStack. - */ - @Override - public void decreaseDurability(Player player, ItemStack itemStack, int amount, boolean updateLore) { - ItemUtils.decreaseDurability(player, itemStack, amount, updateLore); - } - - /** - * Increases the durability of an ItemStack by a specified amount and optionally updates its lore. - * - * @param itemStack The ItemStack to modify. - * @param amount The amount by which to increase the durability. - * @param updateLore Whether to update the lore of the ItemStack. - */ - @Override - public void increaseDurability(ItemStack itemStack, int amount, boolean updateLore) { - ItemUtils.increaseDurability(itemStack, amount, updateLore); - } - - /** - * Sets the durability of an ItemStack to a specific amount and optionally updates its lore. - * - * @param itemStack The ItemStack to modify. - * @param amount The new durability value. - * @param updateLore Whether to update the lore of the ItemStack. - */ - @Override - public void setDurability(ItemStack itemStack, int amount, boolean updateLore) { - ItemUtils.setDurability(itemStack, amount, updateLore); - } - - public static class CFBuilder implements ItemBuilder { - - private final String library; - private final String id; - private int min_amount; - private int max_amount; - private final LinkedHashMap editors; - - public CFBuilder(String library, String id) { - this.id = id; - this.library = library; - this.editors = new LinkedHashMap<>(); - this.min_amount = (max_amount = 1); - } - - public static CFBuilder of(String library, String id) { - return new CFBuilder(library, id); - } - - @Override - public ItemStack build(Player player, Map placeholders) { - return ItemManagerImpl.instance.buildInternal(player, this, placeholders); - } - - @Override - public boolean persist() { - return false; - } - - @Override - public ItemBuilder customModelData(int value) { - if (value == 0) return this; - editors.put("custom-model-data", (player, nbtItem, placeholders) -> nbtItem.set(value, "CustomModelData")); - return this; - } - - @Override - public ItemBuilder name(String name) { - if (name == null) return this; - editors.put("name", (player, nbtItem, placeholders) -> { - nbtItem.set(AdventureHelper.getInstance().componentToJson( - AdventureHelper.getInstance().getComponentFromMiniMessage( - "" + BukkitPlaceholderManager.getInstance().parse(player, name, placeholders) - ) - ), "display", "Name"); - }); - return this; - } - - @Override - public ItemBuilder amount(int amount) { - this.min_amount = amount; - this.max_amount = amount; - return this; - } - - @Override - public ItemBuilder amount(int min_amount, int max_amount) { - this.min_amount = min_amount; - this.max_amount = max_amount; - return this; - } - - @Override - public ItemBuilder tag(boolean tag, String type, String id) { - editors.put("tag", (player, nbtItem, placeholders) -> { - if (!tag) return; - nbtItem.set(type, "CustomFishing", "type"); - nbtItem.set(id, "CustomFishing", "id"); - }); - return this; - } - - @Override - public ItemBuilder unbreakable(boolean unbreakable) { - editors.put("unbreakable", (player, nbtItem, placeholders) -> { - if (!unbreakable) return; - nbtItem.setUnbreakable(true); - }); - return this; - } - - @Override - public ItemBuilder placeable(boolean placeable) { - editors.put("placeable", (player, nbtItem, placeholders) -> { - if (!placeable) return; - nbtItem.set((byte) 1, "CustomFishing", "placeable"); - }); - return this; - } - - @Override - public ItemBuilder lore(List lore) { - if (lore.isEmpty()) return this; - editors.put("lore", (player, nbtItem, placeholders) -> { - List list = new ArrayList<>(lore.stream().map(s -> AdventureHelper.getInstance().componentToJson( - AdventureHelper.getInstance().getComponentFromMiniMessage( - "" + BukkitPlaceholderManager.getInstance().parse(player, s, placeholders) - ) - )).toList()); - nbtItem.set(list, "display", "Lore"); - }); - return this; - } - - @Override - public ItemBuilder nbt(Map nbt) { - if (nbt.isEmpty()) return this; - editors.put("nbt", (player, nbtItem, placeholders) -> NBTUtils.setTagsFromBukkitYAML(player, placeholders, nbtItem, nbt)); - return this; - } - - @Override - public ItemBuilder nbt(ConfigurationSection section) { - if (section == null) return this; - editors.put("nbt", (player, nbtItem, placeholders) -> NBTUtils.setTagsFromBukkitYAML(player, placeholders, nbtItem, section.getValues(false))); - return this; - } - - @Override - public ItemBuilder itemFlag(List itemFlags) { - if (itemFlags.isEmpty()) return this; - editors.put("item-flag", (player, nbtItem, placeholders) -> { - int flag = 0; - for (ItemFlag itemFlag : itemFlags) { - flag = flag | 1 << itemFlag.ordinal(); - } - nbtItem.set(flag, "HideFlags"); - }); - return this; - } - - @Override - public ItemBuilder enchantment(List> enchantments, boolean store) { - if (enchantments.isEmpty()) return this; - editors.put("enchantment", (player, nbtItem, placeholders) -> { - Object nbtList = TagList.newTag(); - for (Pair pair : enchantments) { - Object nbtCompound = TagCompound.newTag(); - TagCompound.set(nbtCompound, "id", pair.left()); - TagCompound.set(nbtCompound, "lvl", pair.right()); - TagList.add(nbtList, nbtCompound); - } - nbtItem.set(nbtList, store ? "StoredEnchantments" : "Enchantments"); - }); - return this; - } - - @Override - public ItemBuilder randomEnchantments(List> enchantments, boolean store) { - if (enchantments.isEmpty()) return this; - editors.put("random-enchantment", (player, nbtItem, placeholders) -> { -// NBTCompoundList list = nbtItem.getCompoundList(store ? "StoredEnchantments" : "Enchantments"); -// HashSet ids = new HashSet<>(); -// for (Tuple pair : enchantments) { -// if (Math.random() < pair.getLeft() && !ids.contains(pair.getMid())) { -// NBTCompound nbtCompound = list.addCompound(); -// nbtCompound.setString("id", pair.getMid()); -// nbtCompound.setShort("lvl", pair.getRight()); -// ids.add(pair.getMid()); -// } -// } - }); - return this; - } - - @Override - public ItemBuilder enchantmentPool(List> amountPairs, List, MathValue>> enchantments, boolean store) { - if (enchantments.size() == 0 || amountPairs.size() == 0) return this; - editors.put("enchantment-pool", (player, nbtItem, placeholders) -> { -// List> parsedAmountPair = new ArrayList<>(amountPairs.size()); -// Map map = new HashMap<>(); -// for (Pair rawValue : amountPairs) { -// parsedAmountPair.add(Pair.of(rawValue.left(), rawValue.right().get(player, map))); -// } -// -// int amount = WeightUtils.getRandom(parsedAmountPair); -// if (amount <= 0) return; -// NBTCompoundList list = nbtItem.getCompoundList(store ? "StoredEnchantments" : "Enchantments"); -// -// HashSet addedEnchantments = new HashSet<>(); -// -// List, Double>> cloned = new ArrayList<>(enchantments.size()); -// for (Pair, Value> rawValue : enchantments) { -// cloned.add(Pair.of(rawValue.left(), rawValue.right().get(player, map))); -// } -// -// int i = 0; -// outer: -// while (i < amount && cloned.size() != 0) { -// Pair enchantPair = WeightUtils.getRandom(cloned); -// Enchantment enchantment = Enchantment.getByKey(NamespacedKey.fromString(enchantPair.left())); -// if (enchantment == null) { -// throw new NullPointerException("Enchantment: " + enchantPair.left() + " doesn't exist on your server."); -// } -// for (Enchantment added : addedEnchantments) { -// if (enchantment.conflictsWith(added)) { -// cloned.removeIf(pair -> pair.left().left().equals(enchantPair.left())); -// continue outer; -// } -// } -// NBTCompound nbtCompound = list.addCompound(); -// nbtCompound.setString("id", enchantPair.left()); -// nbtCompound.setShort("lvl", enchantPair.right()); -// addedEnchantments.add(enchantment); -// cloned.removeIf(pair -> pair.left().left().equals(enchantPair.left())); -// i++; -// } - }); - return this; - } - - @Override - public ItemBuilder maxDurability(int max) { - if (max == 0) return this; - editors.put("durability", (player, nbtItem, placeholders) -> { - nbtItem.set(max, "CustomFishing", "max_dur"); - nbtItem.set(max, "CustomFishing", "cur_dur"); - }); - return this; - } - - @Override - public ItemBuilder price(float base, float bonus) { - if (base == 0 && bonus == 0) return this; - editors.put("price", (player, nbtItem, placeholders) -> { - placeholders.put("{base}", String.format("%.2f", base)); - placeholders.put("{BASE}", String.valueOf(base)); - placeholders.put("{bonus}", String.format("%.2f", bonus)); - placeholders.put("{BONUS}", String.valueOf(bonus)); - double price; - price = BukkitCustomFishingPlugin.get().getMarketManager().getFishPrice( - player, - placeholders - ); - nbtItem.set(price, "Price"); - placeholders.put("{price}", String.format("%.2f", price)); - placeholders.put("{PRICE}", String.valueOf(price)); - }); - return this; - } - - @Override - public ItemBuilder size(Pair size) { - if (size == null) return this; - editors.put("size", (player, nbtItem, placeholders) -> { - float random = size.left() + (size.left() >= size.right() ? 0 : ThreadLocalRandom.current().nextFloat(size.right() - size.left())); - float bonus = Float.parseFloat(placeholders.getOrDefault("{size-multiplier}", "1.0")); - double fixed = Double.parseDouble(placeholders.getOrDefault("{size-fixed}", "0.0")); - random *= bonus; - random += fixed; - if (CFConfig.restrictedSizeRange) { - if (random > size.right()) { - random = size.right(); - } else if (random < size.left()) { - random = size.left(); - } - } - nbtItem.set(random, "CustomFishing", "size"); - placeholders.put("{size}", String.format("%.2f", random)); - placeholders.put("{SIZE}", String.valueOf(random)); - placeholders.put("{min_size}", String.valueOf(size.left())); - placeholders.put("{max_size}", String.valueOf(size.right())); - }); - return this; - } - - @Override - public ItemBuilder stackable(boolean stackable) { - if (stackable) return this; - editors.put("stackable", (player, nbtItem, placeholders) -> { - nbtItem.set(UUID.randomUUID(), "CustomFishing", "stackable"); - }); - return this; - } - - @Override - public ItemBuilder preventGrabbing(boolean prevent) { - if (!prevent) return this; - editors.put("grabbing", (player, nbtItem, placeholders) -> { - nbtItem.set(placeholders.get("player"), "owner"); - }); - return this; - } - - @Override - public ItemBuilder head(String base64) { - if (base64 == null) return this; - editors.put("head", (player, nbtItem, placeholders) -> { - nbtItem.set(UUID.nameUUIDFromBytes(id.getBytes()), "SkullOwner", "Id"); - - NBTListCompound texture = nbtCompound.addCompound("Properties").getCompoundList("textures").addCompound(); - texture.setString("Value", base64); - }); - return this; - } - - @Override - public ItemBuilder randomDamage(boolean damage) { - if (!damage) return this; - editors.put("damage", (player, nbtItem, placeholders) -> { - if (nbtItem.hasTag("CustomFishing")) { - int i = nbtItem.get("CustomFishing", "max_dur"); - if (i != 0) { - int dur = ThreadLocalRandom.current().nextInt(i); - nbtItem.set(dur, "CustomFishing", "max_dur"); - nbtItem.set((int) (nbtItem.getItem().getType().getMaxDurability() * ((double) dur / i)), "Damage"); - } else { - nbtItem.set(ThreadLocalRandom.current().nextInt(nbtItem.getItem().getType().getMaxDurability()), "Damage"); - } - } else { - nbtItem.set(ThreadLocalRandom.current().nextInt(nbtItem.getItem().getType().getMaxDurability()), "Damage"); - } - }); - return this; - } - - @Override - public @NotNull String getId() { - return id; - } - - @Override - public @NotNull String getLibrary() { - return library; - } - - @Override - public int getAmount() { - return ThreadLocalRandom.current().nextInt(min_amount, max_amount + 1); - } - - @Override - public Collection getEditors() { - return editors.values(); - } - - @Override - public ItemBuilder removeEditor(String type) { - editors.remove(type); - return this; - } - - @Override - public ItemBuilder registerCustomEditor(String type, ItemPropertyEditor editor) { - editors.put(type, editor); - return this; - } - } - - /** - * Handles item pickup by players. - * - * @param event The PlayerAttemptPickupItemEvent. - */ - @EventHandler (ignoreCancelled = true) - public void onPickUp(PlayerAttemptPickupItemEvent event) { - ItemStack itemStack = event.getItem().getItemStack(); - RtagItem nbtItem = new RtagItem(itemStack); - if (!nbtItem.hasTag("owner")) return; - if (!Objects.equals(nbtItem.get("owner"), event.getPlayer().getName())) { - event.setCancelled(true); - } else { - nbtItem.remove("owner"); - nbtItem.load(); -// itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - } - } - - /** - * Handles item movement in inventories. - * - * @param event The InventoryPickupItemEvent. - */ - @EventHandler (ignoreCancelled = true) - public void onInvPickItem(InventoryPickupItemEvent event) { - ItemStack itemStack = event.getItem().getItemStack(); - RtagItem nbtItem = new RtagItem(itemStack); - if (!nbtItem.hasTag("owner")) return; - nbtItem.remove("owner"); - nbtItem.load(); -// itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - } - - /** - * Handles item consumption by players. - * - * @param event The PlayerItemConsumeEvent. - */ - @EventHandler (ignoreCancelled = true) - public void onConsumeItem(PlayerItemConsumeEvent event) { - ItemStack itemStack = event.getItem(); - String id = getAnyPluginItemID(itemStack); - Loot loot = plugin.getLootManager().getLoot(id); - if (loot != null) { - PlayerContext playerContext = new PlayerContext(event.getPlayer()); - if (!loot.disableGlobalAction()) - GlobalSettings.triggerLootActions(ActionTrigger.CONSUME, playerContext); - loot.triggerActions(ActionTrigger.CONSUME, playerContext); - } - } - - /** - * Handles the repair of custom items in an anvil. - * - * @param event The PrepareAnvilEvent. - */ - @EventHandler (ignoreCancelled = true) - public void onRepairItem(PrepareAnvilEvent event) { -// ItemStack result = event.getInventory().getResult(); -// if (result == null || result.getType() == Material.AIR) return; -// NBTItem nbtItem = new NBTItem(result); -// NBTCompound compound = nbtItem.getCompound("CustomFishing"); -// if (compound == null || !compound.hasTag("max_dur")) return; -// if (!(result.getItemMeta() instanceof Damageable damageable)) { -// return; -// } -// int max_dur = compound.getInteger("max_dur"); -// compound.setInteger("cur_dur", (int) (max_dur * (1 - (double) damageable.getDamage() / result.getType().getMaxDurability()))); -// event.setResult(nbtItem.getItem()); - } - - /** - * Handles the mending of custom items. - * - * @param event The PlayerItemMendEvent. - */ - @EventHandler (ignoreCancelled = true) - public void onMending(PlayerItemMendEvent event) { - ItemStack itemStack = event.getItem(); - RtagItem nbtItem = new RtagItem(itemStack); - if (!nbtItem.hasTag("CustomFishing")) return; - event.setCancelled(true); - ItemUtils.increaseDurability(itemStack, event.getRepairAmount(), true); - } - - /** - * Handles interactions with custom utility items. - * - * @param event The PlayerInteractEvent. - */ - @EventHandler - public void onInteractWithItems(PlayerInteractEvent event) { - if (event.useItemInHand() == Event.Result.DENY) - return; - if (event.getHand() != EquipmentSlot.HAND) - return; - ItemStack itemStack = event.getPlayer().getInventory().getItemInMainHand(); - if (itemStack.getType() == Material.AIR) - return; - if (event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_AIR && event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK) - return; - String id = getAnyPluginItemID(itemStack); - PlayerContext playerContext = new PlayerContext(event.getPlayer()); - - Loot loot = plugin.getLootManager().getLoot(id); - if (loot != null) { - loot.triggerActions(ActionTrigger.INTERACT, playerContext); - return; - } - - // because the id can be from other plugins, so we can't infer the type of the item - for (String type : List.of("util", "bait", "hook")) { - EffectCarrier carrier = plugin.getEffectManager().getEffectCarrier(type, id); - if (carrier != null) { - Action[] actions = carrier.getActions(ActionTrigger.INTERACT); - if (actions != null) - for (Action action : actions) { - action.trigger(playerContext); - } - break; - } - } - } - - @EventHandler (ignoreCancelled = true) - public void onPlaceBlock(BlockPlaceEvent event) { - ItemStack itemStack = event.getItemInHand(); - if (itemStack.getType() == Material.AIR || itemStack.getAmount() == 0 || !itemStack.hasItemMeta()) { - return; - } - - RtagItem nbtItem = new RtagItem(itemStack); - if (nbtItem.hasTag("CustomFishing")) { - - if (!nbtItem.hasTag("CustomFishing", "placeable") || (byte) nbtItem.get("CustomFishing", "placeable") != 1) { - event.setCancelled(true); - return; - } - - Block block = event.getBlock(); - if (block.getState() instanceof Skull) { - PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); - ItemStack cloned = itemStack.clone(); - cloned.setAmount(1); - pdc.set(new NamespacedKey(plugin, LocationUtils.toChunkPosString(block.getLocation())), PersistentDataType.STRING, ItemUtils.toBase64(cloned)); - } else { - event.setCancelled(true); - } - } - } - - @EventHandler (ignoreCancelled = true) - public void onBreakBlock(BlockBreakEvent event) { - final Block block = event.getBlock(); - if (block.getState() instanceof Skull) { - PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); - String base64 = pdc.get(new NamespacedKey(plugin, LocationUtils.toChunkPosString(block.getLocation())), PersistentDataType.STRING); - if (base64 != null) { - ItemStack itemStack = ItemUtils.fromBase64(base64); - event.setDropItems(false); - block.getLocation().getWorld().dropItemNaturally(block.getLocation(), itemStack); - } - } - } - - @EventHandler (ignoreCancelled = true) - public void onPiston(BlockPistonExtendEvent event) { - for (Block block : event.getBlocks()) { - if (block.getState() instanceof Skull) { - PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); - if (pdc.has(new NamespacedKey(plugin, LocationUtils.toChunkPosString(block.getLocation())), PersistentDataType.STRING)) { - event.setCancelled(true); - return; - } - } - } - } - - @EventHandler (ignoreCancelled = true) - public void onPiston(BlockPistonRetractEvent event) { - for (Block block : event.getBlocks()) { - if (block.getState() instanceof Skull) { - PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); - if (pdc.has(new NamespacedKey(plugin, LocationUtils.toChunkPosString(block.getLocation())), PersistentDataType.STRING)) { - event.setCancelled(true); - return; - } - } - } - } - - @EventHandler (ignoreCancelled = true) - public void onExplosion(BlockExplodeEvent event) { - handleExplode(event.blockList()); - } - - @EventHandler (ignoreCancelled = true) - public void onExplosion(EntityExplodeEvent event) { - handleExplode(event.blockList()); - } - - private void handleExplode(List blocks) { - ArrayList blockToRemove = new ArrayList<>(); - for (Block block : blocks) { - if (block.getState() instanceof Skull) { - PersistentDataContainer pdc = block.getChunk().getPersistentDataContainer(); - var nk = new NamespacedKey(plugin, LocationUtils.toChunkPosString(block.getLocation())); - String base64 = pdc.get(nk, PersistentDataType.STRING); - if (base64 != null) { - ItemStack itemStack = ItemUtils.fromBase64(base64); - block.getLocation().getWorld().dropItemNaturally(block.getLocation(), itemStack); - blockToRemove.add(block); - block.setType(Material.AIR); - pdc.remove(nk); - } - } - } - blocks.removeAll(blockToRemove); - } -} \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/loot/BukkitLootManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/loot/BukkitLootManager.java index d097c7b4..1478fb42 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/loot/BukkitLootManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/loot/BukkitLootManager.java @@ -11,8 +11,6 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -import static java.util.Objects.requireNonNull; - public class BukkitLootManager implements LootManager { private final BukkitCustomFishingPlugin plugin; @@ -23,13 +21,8 @@ public class BukkitLootManager implements LootManager { this.plugin = plugin; } - private void loadConfig() { - - } - @Override - public void registerLoot(@NotNull final Loot loot) { - requireNonNull(loot, "loot cannot be null"); + public void registerLoot(@NotNull Loot loot) { this.lootMap.put(loot.getID(), loot); for (String group : loot.lootGroup()) { addGroupMember(group, loot.getID()); diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/market/BukkitMarketManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/market/BukkitMarketManager.java index c228ba61..19d968db 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/market/BukkitMarketManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/market/BukkitMarketManager.java @@ -20,13 +20,17 @@ package net.momirealms.customfishing.bukkit.market; import de.tr7zw.changeme.nbtapi.NBTItem; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.market.MarketGUIHolder; import net.momirealms.customfishing.api.mechanic.market.MarketManager; import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager; +import net.momirealms.customfishing.api.mechanic.misc.value.TextValue; import net.momirealms.customfishing.api.scheduler.CancellableTask; import net.momirealms.customfishing.api.storage.data.EarningData; import net.momirealms.customfishing.bukkit.util.ConfigUtils; import net.momirealms.customfishing.bukkit.util.NumberUtils; +import net.momirealms.customfishing.common.helper.ExpressionHelper; +import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask; import net.objecthunter.exp4j.ExpressionBuilder; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -76,7 +80,7 @@ public class BukkitMarketManager implements MarketManager, Listener { private boolean sellFishingBag; private final ConcurrentHashMap marketGUIMap; private boolean enable; - private CancellableTask resetEarningsTask; + private SchedulerTask resetEarningsTask; private int date; public BukkitMarketManager(BukkitCustomFishingPlugin plugin) { @@ -91,7 +95,7 @@ public class BukkitMarketManager implements MarketManager, Listener { this.loadConfig(); Bukkit.getPluginManager().registerEvents(this, plugin); if (!enable) return; - this.resetEarningsTask = plugin.getScheduler().runTaskAsyncTimer(() -> { + this.resetEarningsTask = plugin.getScheduler().asyncRepeating(() -> { int now = getRealTimeDate(); if (this.date != now) { this.date = now; @@ -491,18 +495,19 @@ public class BukkitMarketManager implements MarketManager, Listener { } @Override - public String getFormula() { + public TextValue getFormula() { return formula; } @Override - public double getFishPrice(Player player, Map vars) { - String temp = BukkitPlaceholderManager.getInstance().parse(player, formula, vars); + public double getFishPrice(Context context) { + formula. + String temp = plugin.getPlaceholderManager().parse(player, formula, vars); var placeholders = BukkitPlaceholderManager.getInstance().resolvePlaceholders(temp); for (String placeholder : placeholders) { temp = temp.replace(placeholder, "0"); } - return new ExpressionBuilder(temp).build().evaluate(); + return ExpressionHelper.evaluate(temp); } @Override diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/requirement/BukkitRequirementManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/requirement/BukkitRequirementManager.java index 585be069..6ee24094 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/requirement/BukkitRequirementManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/requirement/BukkitRequirementManager.java @@ -15,7 +15,7 @@ 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.*; import net.momirealms.customfishing.api.util.MoonPhase; -import net.momirealms.customfishing.bukkit.compatibility.VaultHook; +import net.momirealms.customfishing.bukkit.integration.VaultHook; import net.momirealms.customfishing.common.util.ClassUtils; import net.momirealms.customfishing.common.util.ListUtils; import net.momirealms.customfishing.common.util.Pair; @@ -599,7 +599,7 @@ public class BukkitRequirementManager implements RequirementManager { registerRequirement("ice-fishing", (args, actions, advanced) -> { boolean iceFishing = (boolean) args; return context -> { - Location location = requireNonNull(context.arg(ContextKeys.LOCATION)); + Location location = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)); int water = 0, ice = 0; for (int i = -2; i <= 2; i++) for (int j = -1; j <= 2; j++) @@ -661,7 +661,7 @@ public class BukkitRequirementManager implements RequirementManager { registerRequirement("biome", (args, actions, advanced) -> { HashSet biomes = new HashSet<>(ListUtils.toList(args)); return context -> { - Location location = requireNonNull(context.arg(ContextKeys.LOCATION)); + Location location = requireNonNull(Optional.ofNullable(context.arg(ContextKeys.HOOK_LOCATION)).orElse(context.arg(ContextKeys.LOCATION))); String currentBiome = SparrowHeart.getInstance().getBiomeResourceLocation(location); if (biomes.contains(currentBiome)) return true; @@ -672,7 +672,7 @@ public class BukkitRequirementManager implements RequirementManager { registerRequirement("!biome", (args, actions, advanced) -> { HashSet biomes = new HashSet<>(ListUtils.toList(args)); return context -> { - Location location = requireNonNull(context.arg(ContextKeys.LOCATION)); + Location location = requireNonNull(Optional.ofNullable(context.arg(ContextKeys.HOOK_LOCATION)).orElse(context.arg(ContextKeys.LOCATION))); String currentBiome = SparrowHeart.getInstance().getBiomeResourceLocation(location); if (!biomes.contains(currentBiome)) return true; @@ -749,7 +749,19 @@ public class BukkitRequirementManager implements RequirementManager { private void registerCoolDownRequirement() { registerRequirement("cooldown", (args, actions, advanced) -> { - return null; + if (args instanceof Section section) { + String key = section.getString("key"); + int time = section.getInt("time"); + return context -> { + if (!plugin.getCoolDownManager().isCoolDown(context.getHolder().getUniqueId(), key, time)) + return true; + if (advanced) ActionManager.trigger(context, actions); + return false; + }; + } else { + plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at cooldown requirement which should be Section"); + return EmptyRequirement.INSTANCE; + } }); } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/statistic/BukkitStatisticsManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/statistic/BukkitStatisticsManager.java index 2a252bf0..826710da 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/statistic/BukkitStatisticsManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/statistic/BukkitStatisticsManager.java @@ -20,6 +20,7 @@ package net.momirealms.customfishing.bukkit.statistic; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.statistic.StatisticsManager; import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -28,39 +29,22 @@ import java.util.*; public class BukkitStatisticsManager implements StatisticsManager { private final BukkitCustomFishingPlugin plugin; - private final HashMap> categoryMap; + private final Map> categoryMap = new HashMap<>(); public BukkitStatisticsManager(BukkitCustomFishingPlugin plugin) { this.plugin = plugin; - this.categoryMap = new HashMap<>(); } + @Override public void load() { this.loadCategoriesFromPluginFolder(); } + @Override public void unload() { this.categoryMap.clear(); } - - public void disable() { - unload(); - } - - /** - * Get the statistics for a player with the given UUID. - * - * @param uuid The UUID of the player for whom statistics are retrieved. - * @return The player's statistics or null if the player is not found. - */ - @Override - @Nullable - public Statistics getStatistics(UUID uuid) { - OnlineUserData onlineUser = plugin.getStorageManager().getOnlineUser(uuid); - if (onlineUser == null) return null; - return onlineUser.getStatistics(); - } - + @SuppressWarnings("DuplicatedCode") public void loadCategoriesFromPluginFolder() { Deque fileDeque = new ArrayDeque<>(); @@ -68,7 +52,7 @@ public class BukkitStatisticsManager implements StatisticsManager { File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type); if (!typeFolder.exists()) { if (!typeFolder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false); + plugin.getBoostrap().saveResource("contents" + File.separator + type + File.separator + "default.yml", false); } fileDeque.push(typeFolder); while (!fileDeque.isEmpty()) { @@ -93,15 +77,9 @@ public class BukkitStatisticsManager implements StatisticsManager { } } - /** - * Get a list of strings associated with a specific key in a category map. - * - * @param key The key to look up in the category map. - * @return A list of strings associated with the key or null if the key is not found. - */ + @NotNull @Override - @Nullable - public List getCategory(String key) { - return categoryMap.get(key); + public List getCategoryMembers(String key) { + return categoryMap.getOrDefault(key, List.of()); } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/BukkitStorageManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/BukkitStorageManager.java index b2805f9a..9d085c33 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/BukkitStorageManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/BukkitStorageManager.java @@ -20,7 +20,6 @@ package net.momirealms.customfishing.bukkit.storage; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.scheduler.CancellableTask; import net.momirealms.customfishing.api.storage.DataStorageProvider; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/H2Impl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/H2Impl.java index 6dcaed9b..19cc0b73 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/H2Impl.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/H2Impl.java @@ -17,7 +17,6 @@ package net.momirealms.customfishing.bukkit.storage.method.database.sql; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.storage.StorageType; import net.momirealms.customfishing.libraries.dependencies.Dependency; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/SQLiteImpl.java b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/SQLiteImpl.java index 9951fb78..ff28f490 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/SQLiteImpl.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/storage/method/database/sql/SQLiteImpl.java @@ -17,7 +17,6 @@ package net.momirealms.customfishing.bukkit.storage.method.database.sql; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.storage.StorageType; import net.momirealms.customfishing.api.storage.data.PlayerData; diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/util/ArmorStandUtils.java b/core/src/main/java/net/momirealms/customfishing/bukkit/util/ArmorStandUtils.java index 0e2cea39..80534a2b 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/util/ArmorStandUtils.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/util/ArmorStandUtils.java @@ -23,7 +23,6 @@ import com.comphenix.protocol.wrappers.*; import com.google.common.collect.Lists; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.momirealms.customfishing.bukkit.BukkitCustomFishingPluginImpl; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import org.bukkit.Location; import org.bukkit.entity.EntityType;