diff --git a/.gitignore b/.gitignore index f9e16241..8dc84b51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,8 @@ -# User-specific stuff +# Folders .idea/ - -*.iml -*.ipr -*.iws - -# IntelliJ -out/ -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml +.gradle/ +build/ +target/ # Compiled class file *.class @@ -22,6 +13,9 @@ atlassian-ide-plugin.xml # BlueJ files *.ctxt +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + # Package Files # *.war *.nar @@ -32,86 +26,4 @@ atlassian-ide-plugin.xml # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* - -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -.gradle -build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Cache of project -.gradletasknamecache - -**/build/ - -# Common working directory -run/ - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar +replay_pid* diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 00000000..b63da455 --- /dev/null +++ b/api/.gitignore @@ -0,0 +1,42 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/api/build.gradle.kts b/api/build.gradle.kts new file mode 100644 index 00000000..bb54151d --- /dev/null +++ b/api/build.gradle.kts @@ -0,0 +1,5 @@ +dependencies { + compileOnly("io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT") + compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0") + implementation("de.tr7zw:item-nbt-api:2.11.3") +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/CustomFishingPlugin.java b/api/src/main/java/net/momirealms/customfishing/api/CustomFishingPlugin.java new file mode 100644 index 00000000..0f0f4209 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/CustomFishingPlugin.java @@ -0,0 +1,125 @@ +package net.momirealms.customfishing.api; + +import net.momirealms.customfishing.api.manager.*; +import net.momirealms.customfishing.api.scheduler.Scheduler; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +public abstract class CustomFishingPlugin extends JavaPlugin { + + protected Scheduler scheduler; + protected CommandManager commandManager; + protected VersionManager versionManager; + protected ItemManager itemManager; + protected RequirementManager requirementManager; + protected ActionManager actionManager; + protected LootManager lootManager; + protected FishingManager fishingManager; + protected EffectManager effectManager; + protected MobManager mobManager; + protected BlockManager blockManager; + protected AdventureManager adventure; + protected BagManager bagManager; + protected GameManager gameManager; + protected MarketManager marketManager; + protected IntegrationManager integrationManager; + protected CompetitionManager competitionManager; + protected StorageManager storageManager; + protected PlaceholderManager placeholderManager; + + private static CustomFishingPlugin instance; + + public CustomFishingPlugin() { + instance = this; + } + + public static CustomFishingPlugin get() { + return instance; + } + + public static CustomFishingPlugin getInstance() { + return instance; + } + + public Scheduler getScheduler() { + return scheduler; + } + + public CommandManager getCommandManager() { + return commandManager; + } + + public VersionManager getVersionManager() { + return versionManager; + } + + public RequirementManager getRequirementManager() { + return requirementManager; + } + + public ActionManager getActionManager() { + return actionManager; + } + + public GameManager getGameManager() { + return gameManager; + } + + public BlockManager getBlockManager() { + return blockManager; + } + + public MobManager getMobManager() { + return mobManager; + } + + public ItemManager getItemManager() { + return itemManager; + } + + public EffectManager getEffectManager() { + return effectManager; + } + + public MarketManager getMarketManager() { + return marketManager; + } + + public FishingManager getFishingManager() { + return fishingManager; + } + + public AdventureManager getAdventure() { + return adventure; + } + + public BagManager getBagManager() { + return bagManager; + } + + public LootManager getLootManager() { + return lootManager; + } + + public StorageManager getStorageManager() { + return storageManager; + } + + public IntegrationManager getIntegrationManager() { + return integrationManager; + } + + public PlaceholderManager getPlaceholderManager() { + return placeholderManager; + } + + public abstract void reload(); + + public abstract YamlConfiguration getConfig(String file); + + public abstract boolean isHookedPluginEnabled(String plugin); + + public CompetitionManager getCompetitionManager() { + return competitionManager; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/common/Key.java b/api/src/main/java/net/momirealms/customfishing/api/common/Key.java new file mode 100644 index 00000000..3c23f965 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/common/Key.java @@ -0,0 +1,29 @@ +package net.momirealms.customfishing.api.common; + +public record Key(String namespace, String value) { + + public static Key of(String namespace, String value) { + return new Key(namespace, value); + } + + @Override + public int hashCode() { + int result = this.namespace.hashCode(); + result = (31 * result) + this.value.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof Key key)) return false; + return this.namespace.equals(key.namespace()) && this.value.equals(key.value()); + } + + @Override + public String toString() { + return namespace + ":" + value; + } +} diff --git a/src/main/java/net/momirealms/customfishing/object/Pair.java b/api/src/main/java/net/momirealms/customfishing/api/common/Pair.java similarity index 94% rename from src/main/java/net/momirealms/customfishing/object/Pair.java rename to api/src/main/java/net/momirealms/customfishing/api/common/Pair.java index ad4a71e6..2491adcd 100644 --- a/src/main/java/net/momirealms/customfishing/object/Pair.java +++ b/api/src/main/java/net/momirealms/customfishing/api/common/Pair.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.object; +package net.momirealms.customfishing.api.common; public record Pair(L left, R right) { diff --git a/api/src/main/java/net/momirealms/customfishing/api/common/Tuple.java b/api/src/main/java/net/momirealms/customfishing/api/common/Tuple.java new file mode 100644 index 00000000..a3e81b45 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/common/Tuple.java @@ -0,0 +1,42 @@ +package net.momirealms.customfishing.api.common; + +public class Tuple { + + private L left; + private M mid; + private R right; + + public Tuple(L left, M mid, R right) { + this.left = left; + this.mid = mid; + this.right = right; + } + + public static Tuple of(final L left, final M mid, final R right) { + return new Tuple<>(left, mid, right); + } + + public L getLeft() { + return left; + } + + public void setLeft(L left) { + this.left = left; + } + + public M getMid() { + return mid; + } + + public void setMid(M mid) { + this.mid = mid; + } + + public R getRight() { + return right; + } + + public void setRight(R right) { + this.right = right; + } +} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/totem/CorePos.java b/api/src/main/java/net/momirealms/customfishing/api/data/DataStorageInterface.java similarity index 61% rename from src/main/java/net/momirealms/customfishing/fishing/totem/CorePos.java rename to api/src/main/java/net/momirealms/customfishing/api/data/DataStorageInterface.java index b6ddccb4..8332bfe8 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/totem/CorePos.java +++ b/api/src/main/java/net/momirealms/customfishing/api/data/DataStorageInterface.java @@ -15,29 +15,20 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing.totem; +package net.momirealms.customfishing.api.data; -public class CorePos { +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; - private final int x; - private final int y; - private final int z; +public interface DataStorageInterface { - public CorePos(int x, int z, int y) { - this.x = x; - this.z = z; - this.y = y; - } + void initialize(); + void disable(); - public int getX() { - return this.x; - } + StorageType getStorageType(); - public int getY() { - return this.y; - } + CompletableFuture> getPlayerData(UUID uuid, boolean force); - public int getZ() { - return this.z; - } + CompletableFuture setPlayData(UUID uuid, PlayerData playerData, boolean unlock); } diff --git a/src/main/java/net/momirealms/customfishing/fishing/VanillaLoot.java b/api/src/main/java/net/momirealms/customfishing/api/data/EarningData.java similarity index 62% rename from src/main/java/net/momirealms/customfishing/fishing/VanillaLoot.java rename to api/src/main/java/net/momirealms/customfishing/api/data/EarningData.java index 89ead047..38b4d3d6 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/VanillaLoot.java +++ b/api/src/main/java/net/momirealms/customfishing/api/data/EarningData.java @@ -15,25 +15,23 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing; +package net.momirealms.customfishing.api.data; -import org.bukkit.inventory.ItemStack; +import com.google.gson.annotations.SerializedName; -public class VanillaLoot { +public class EarningData { - private final ItemStack itemStack; - private final int xp; + @SerializedName("earnings") + public double earnings; + @SerializedName("date") + public int date; - public VanillaLoot(ItemStack itemStack, int xp) { - this.itemStack = itemStack; - this.xp = xp; + public EarningData(double earnings, int date) { + this.earnings = earnings; + this.date = date; } - public ItemStack getItemStack() { - return itemStack; - } - - public int getXp() { - return xp; + public static EarningData empty() { + return new EarningData(0d, 0); } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/data/InventoryData.java b/api/src/main/java/net/momirealms/customfishing/api/data/InventoryData.java new file mode 100644 index 00000000..c5ca476f --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/data/InventoryData.java @@ -0,0 +1,21 @@ +package net.momirealms.customfishing.api.data; + +import com.google.gson.annotations.SerializedName; + +public class InventoryData { + + @SerializedName("inventory") + public String serialized; + + @SerializedName("size") + public int size; + + public static InventoryData empty() { + return new InventoryData("", 9); + } + + public InventoryData(String serialized, int size) { + this.serialized = serialized; + this.size = size; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/data/PlayerData.java b/api/src/main/java/net/momirealms/customfishing/api/data/PlayerData.java new file mode 100644 index 00000000..5e9188dd --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/data/PlayerData.java @@ -0,0 +1,81 @@ +package net.momirealms.customfishing.api.data; + +import com.google.gson.annotations.SerializedName; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PlayerData { + + @SerializedName("name") + protected String name; + @SerializedName("stats") + protected StatisticData statisticsData; + @SerializedName("bag") + protected InventoryData bagData; + @SerializedName("trade") + protected EarningData earningData; + + public static PlayerData NEVER_PLAYED = empty(); + + public static PlayerData empty() { + return new Builder() + .setBagData(InventoryData.empty()) + .setEarningData(EarningData.empty()) + .setStats(StatisticData.empty()) + .build(); + } + + public static class Builder { + + private final PlayerData playerData; + + public Builder() { + this.playerData = new PlayerData(); + } + + @NotNull + public Builder setName(@Nullable String name) { + this.playerData.name = name; + return this; + } + + @NotNull + public Builder setStats(@Nullable StatisticData statisticsData) { + this.playerData.statisticsData = statisticsData; + return this; + } + + @NotNull + public Builder setBagData(@Nullable InventoryData inventoryData) { + this.playerData.bagData = inventoryData; + return this; + } + + @NotNull + public Builder setEarningData(@Nullable EarningData earningData) { + this.playerData.earningData = earningData; + return this; + } + + @NotNull + public PlayerData build() { + return this.playerData; + } + } + + public StatisticData getStatistics() { + return statisticsData; + } + + public InventoryData getBagData() { + return bagData; + } + + public EarningData getEarningData() { + return earningData; + } + + public String getName() { + return name; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/data/StatisticData.java b/api/src/main/java/net/momirealms/customfishing/api/data/StatisticData.java new file mode 100644 index 00000000..c0c8771c --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/data/StatisticData.java @@ -0,0 +1,21 @@ +package net.momirealms.customfishing.api.data; + +import com.google.gson.annotations.SerializedName; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +public class StatisticData { + + @SerializedName("stats") + public Map statisticMap; + + public StatisticData(@NotNull Map data) { + this.statisticMap = data; + } + + public static StatisticData empty() { + return new StatisticData(new HashMap<>()); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/data/StorageType.java b/api/src/main/java/net/momirealms/customfishing/api/data/StorageType.java new file mode 100644 index 00000000..5bff469c --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/data/StorageType.java @@ -0,0 +1,14 @@ +package net.momirealms.customfishing.api.data; + +public enum StorageType { + + JSON, + YAML, + H2, + SQLite, + MySQL, + MariaDB, + MongoDB, + Redis + +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/data/user/OfflineUser.java b/api/src/main/java/net/momirealms/customfishing/api/data/user/OfflineUser.java new file mode 100644 index 00000000..fcf5ce9c --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/data/user/OfflineUser.java @@ -0,0 +1,24 @@ +package net.momirealms.customfishing.api.data.user; + +import net.momirealms.customfishing.api.data.EarningData; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.mechanic.bag.FishingBagHolder; +import net.momirealms.customfishing.api.mechanic.statistic.Statistics; + +import java.util.UUID; + +public interface OfflineUser { + String getName(); + + UUID getUUID(); + + FishingBagHolder getHolder(); + + EarningData getEarningData(); + + Statistics getStatistics(); + + boolean isOnline(); + + PlayerData getPlayerData(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/data/user/OnlineUser.java b/api/src/main/java/net/momirealms/customfishing/api/data/user/OnlineUser.java new file mode 100644 index 00000000..bc49a85d --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/data/user/OnlineUser.java @@ -0,0 +1,27 @@ +package net.momirealms.customfishing.api.data.user; + +import net.momirealms.customfishing.api.data.EarningData; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.mechanic.bag.FishingBagHolder; +import net.momirealms.customfishing.api.mechanic.statistic.Statistics; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public interface OnlineUser { + Player getPlayer(); + + String getName(); + + UUID getUUID(); + + FishingBagHolder getHolder(); + + EarningData getEarningData(); + + Statistics getStatistics(); + + boolean isOnline(); + + PlayerData getPlayerData(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/event/LavaFishingEvent.java b/api/src/main/java/net/momirealms/customfishing/api/event/LavaFishingEvent.java new file mode 100644 index 00000000..c8a56759 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/event/LavaFishingEvent.java @@ -0,0 +1,56 @@ +package net.momirealms.customfishing.api.event; + +import org.bukkit.entity.FishHook; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; + +public class LavaFishingEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlerList = new HandlerList(); + private final State state; + private boolean isCancelled; + private final FishHook hook; + + public LavaFishingEvent(@NotNull Player who, State state, FishHook hook) { + super(who); + this.state = state; + this.isCancelled = false; + this.hook = hook; + } + + public State getState() { + return state; + } + + public FishHook getHook() { + return hook; + } + + public static HandlerList getHandlerList() { + return handlerList; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + + @Override + public boolean isCancelled() { + return isCancelled; + } + + @Override + public void setCancelled(boolean cancel) { + isCancelled = cancel; + } + + public enum State { + REEL_IN, + CAUGHT_FISH, BITE + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java b/api/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java new file mode 100644 index 00000000..eb659677 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java @@ -0,0 +1,50 @@ +package net.momirealms.customfishing.api.event; + +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.jetbrains.annotations.NotNull; + +public class RodCastEvent extends PlayerEvent implements Cancellable { + + private final Effect effect; + private boolean isCancelled; + private final PlayerFishEvent event; + private static final HandlerList handlerList = new HandlerList(); + + public RodCastEvent(PlayerFishEvent event, Effect effect) { + super(event.getPlayer()); + this.effect = effect; + this.event = event; + } + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.isCancelled = cancel; + } + + public static HandlerList getHandlerList() { + return handlerList; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + + public Effect getEffect() { + return effect; + } + + public PlayerFishEvent getBukkitPlayerFishEvent() { + return event; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/event/TotemActivateEvent.java b/api/src/main/java/net/momirealms/customfishing/api/event/TotemActivateEvent.java new file mode 100644 index 00000000..cab74eef --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/event/TotemActivateEvent.java @@ -0,0 +1,4 @@ +package net.momirealms.customfishing.api.event; + +public class TotemActivateEvent { +} diff --git a/src/main/java/net/momirealms/customfishing/integration/EnchantmentInterface.java b/api/src/main/java/net/momirealms/customfishing/api/integration/EnchantmentInterface.java similarity index 74% rename from src/main/java/net/momirealms/customfishing/integration/EnchantmentInterface.java rename to api/src/main/java/net/momirealms/customfishing/api/integration/EnchantmentInterface.java index eb97f2a7..9afea4cf 100644 --- a/src/main/java/net/momirealms/customfishing/integration/EnchantmentInterface.java +++ b/api/src/main/java/net/momirealms/customfishing/api/integration/EnchantmentInterface.java @@ -1,4 +1,4 @@ -package net.momirealms.customfishing.integration; +package net.momirealms.customfishing.api.integration; import org.bukkit.inventory.ItemStack; diff --git a/api/src/main/java/net/momirealms/customfishing/api/integration/LevelInterface.java b/api/src/main/java/net/momirealms/customfishing/api/integration/LevelInterface.java new file mode 100644 index 00000000..cdb41071 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/integration/LevelInterface.java @@ -0,0 +1,9 @@ +package net.momirealms.customfishing.api.integration; + +import org.bukkit.entity.Player; + +public interface LevelInterface { + + void addXp(Player player, String target, double amount); + int getLevel(Player player, String target); +} diff --git a/src/main/java/net/momirealms/customfishing/integration/SeasonInterface.java b/api/src/main/java/net/momirealms/customfishing/api/integration/SeasonInterface.java similarity index 93% rename from src/main/java/net/momirealms/customfishing/integration/SeasonInterface.java rename to api/src/main/java/net/momirealms/customfishing/api/integration/SeasonInterface.java index d784f00b..493ce396 100644 --- a/src/main/java/net/momirealms/customfishing/integration/SeasonInterface.java +++ b/api/src/main/java/net/momirealms/customfishing/api/integration/SeasonInterface.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration; +package net.momirealms.customfishing.api.integration; import org.bukkit.World; diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/ActionManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/ActionManager.java new file mode 100644 index 00000000..7468c3ed --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/ActionManager.java @@ -0,0 +1,18 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionBuilder; +import org.bukkit.configuration.ConfigurationSection; + +public interface ActionManager { + + boolean registerAction(String type, ActionBuilder actionBuilder); + + boolean unregisterAction(String type); + + Action getAction(ConfigurationSection section); + + Action[] getActions(ConfigurationSection section); + + ActionBuilder getActionBuilder(String type); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/AdventureManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/AdventureManager.java new file mode 100644 index 00000000..b2f97e1c --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/AdventureManager.java @@ -0,0 +1,116 @@ +package net.momirealms.customfishing.api.manager; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public interface AdventureManager { + + /** + * Get component from text + * @param text text + * @return component + */ + Component getComponentFromMiniMessage(String text); + + /** + * Send a message to a command sender + * @param sender sender + * @param msg message + */ + void sendMessage(CommandSender sender, String msg); + + void sendMessageWithPrefix(CommandSender sender, String s); + + /** + * Send a message to console + * @param msg message + */ + void sendConsoleMessage(String msg); + + /** + * Send a message to a player + * @param player player + * @param msg message + */ + void sendPlayerMessage(Player player, String msg); + + /** + * Send a title to a player + * @param player player + * @param title title + * @param subtitle subtitle + * @param in in (ms) + * @param duration duration (ms) + * @param out out (ms) + */ + void sendTitle(Player player, String title, String subtitle, int in, int duration, int out); + + /** + * Send a title to a player + * @param player player + * @param title title + * @param subtitle subtitle + * @param in in (ms) + * @param duration duration (ms) + * @param out out (ms) + */ + void sendTitle(Player player, Component title, Component subtitle, int in, int duration, int out); + + /** + * Send actionbar + * @param player player + * @param msg msg + */ + void sendActionbar(Player player, String msg); + + /** + * Play a sound to a player + * @param player player + * @param source sound source + * @param key sound key + * @param volume volume + * @param pitch pitch + */ + void sendSound(Player player, Sound.Source source, Key key, float volume, float pitch); + + void sendSound(Player player, Sound sound); + + /** + * Replace legacy color codes to MiniMessage format + * @param legacy legacy text + * @return MiniMessage format text + */ + String legacyToMiniMessage(String legacy); + + /** + * if a char is legacy color code + * @param c char + * @return is legacy color + */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + boolean isColorCode(char c); + + /** + * Get legacy format text + * @param component component + * @return legacy format text + */ + String componentToLegacy(Component component); + + /** + * Get json + * @param component component + * @return json + */ + String componentToJson(Component component); + + /** + * Get paper component + * @param component shaded component + * @return paper component + */ + Object shadedComponentToPaperComponent(Component component); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/BagManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/BagManager.java new file mode 100644 index 00000000..1a3f8f4e --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/BagManager.java @@ -0,0 +1,11 @@ +package net.momirealms.customfishing.api.manager; + +import org.bukkit.inventory.Inventory; + +import java.util.UUID; + +public interface BagManager { + boolean isBagEnabled(); + + Inventory getOnlineBagInventory(UUID uuid); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/BlockManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/BlockManager.java new file mode 100644 index 00000000..e864d534 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/BlockManager.java @@ -0,0 +1,22 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.block.BlockLibrary; +import net.momirealms.customfishing.api.mechanic.block.BlockDataModifierBuilder; +import net.momirealms.customfishing.api.mechanic.block.BlockStateModifierBuilder; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public interface BlockManager { + boolean registerBlockLibrary(BlockLibrary library); + + boolean unregisterBlockLibrary(BlockLibrary library); + + boolean unregisterBlockLibrary(String library); + + boolean registerBlockDataModifierBuilder(String type, BlockDataModifierBuilder builder); + + boolean registerBlockStateModifierBuilder(String type, BlockStateModifierBuilder builder); + + void summonBlock(Player player, Location hookLocation, Location playerLocation, Loot loot); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/CommandManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/CommandManager.java new file mode 100644 index 00000000..9538f7b1 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/CommandManager.java @@ -0,0 +1,6 @@ +package net.momirealms.customfishing.api.manager; + +public interface CommandManager { + + void loadCommands(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/CompetitionManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/CompetitionManager.java new file mode 100644 index 00000000..2a8a2930 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/CompetitionManager.java @@ -0,0 +1,26 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.competition.CompetitionConfig; +import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public interface CompetitionManager { + Set getAllCompetitions(); + + void startCompetition(String competition, boolean force, boolean allServers); + + @Nullable + FishingCompetition getOnGoingCompetition(); + + void startCompetition(CompetitionConfig config, boolean force, boolean allServers); + + int getNextCompetitionSeconds(); + + CompletableFuture getPlayerCount(); + + @Nullable + CompetitionConfig getConfig(String key); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/EffectManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/EffectManager.java new file mode 100644 index 00000000..734ac8d2 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/EffectManager.java @@ -0,0 +1,15 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.common.Key; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import org.jetbrains.annotations.Nullable; + +public interface EffectManager { + boolean registerEffect(Key key, Effect effect); + + boolean unregisterEffect(Key key); + + @Nullable Effect getEffect(String namespace, String id); + + Effect getInitialEffect(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/FishingManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/FishingManager.java new file mode 100644 index 00000000..0c0b5197 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/FishingManager.java @@ -0,0 +1,27 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.TempFishingState; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.mechanic.game.Game; +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 org.bukkit.entity.Player; + +import java.util.UUID; + +public interface FishingManager { + boolean removeHook(UUID uuid); + + void setTempFishingState(Player player, TempFishingState tempFishingState); + + void removeHookCheckTask(Player player); + + void removeTempFishingState(Player player); + + void processGameResult(GamingPlayer gamingPlayer); + + void startFishingGame(Player player, Loot loot, Effect effect); + + void startFishingGame(Player player, GameSettings settings, Game game); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/GameManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/GameManager.java new file mode 100644 index 00000000..2e52d55f --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/GameManager.java @@ -0,0 +1,29 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.game.Game; +import net.momirealms.customfishing.api.mechanic.game.GameConfig; +import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.Nullable; + +public interface GameManager { + + + boolean registerGameType(String type, GameCreator gameCreator); + + boolean unregisterGameType(String type); + + @Nullable GameCreator getGameCreator(String type); + + @Nullable Game getGame(String key); + + @Nullable GameConfig getGameConfig(String key); + + Game getRandomGame(); + + GameConfig getRandomGameConfig(); + + public interface GameCreator { + + Game setArgs(ConfigurationSection section); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/IntegrationManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/IntegrationManager.java new file mode 100644 index 00000000..7c728843 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/IntegrationManager.java @@ -0,0 +1,27 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.integration.EnchantmentInterface; +import net.momirealms.customfishing.api.integration.LevelInterface; +import net.momirealms.customfishing.api.integration.SeasonInterface; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public interface IntegrationManager { + + boolean registerLevelPlugin(String plugin, LevelInterface level); + + boolean unregisterLevelPlugin(String plugin); + + boolean registerEnchantment(String plugin, EnchantmentInterface enchantment); + + boolean unregisterEnchantment(String plugin); + + LevelInterface getLevelHook(String plugin); + + List getEnchantments(ItemStack rod); + + SeasonInterface getSeasonInterface(); + + void setSeasonInterface(SeasonInterface season); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/ItemManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/ItemManager.java new file mode 100644 index 00000000..013ddb1c --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/ItemManager.java @@ -0,0 +1,59 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.common.Key; +import net.momirealms.customfishing.api.mechanic.item.BuildableItem; +import net.momirealms.customfishing.api.mechanic.item.ItemBuilder; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Set; + +public interface ItemManager { + + @Nullable + ItemStack build(Player player, String namespace, String value); + + @Nullable + ItemStack build(Player player, String namespace, String value, Map placeholders); + + @NotNull + ItemStack build(Player player, ItemBuilder builder); + + ItemStack buildAnyItemByID(Player player, String id); + + @Nullable + String getItemID(ItemStack itemStack); + + String getAnyItemID(ItemStack itemStack); + + @Nullable + ItemBuilder getItemBuilder(ConfigurationSection section, String type, String id); + + ItemStack build(Player player, ItemBuilder builder, Map placeholders); + + Set getAllItemsKey(); + + boolean registerCustomItem(String namespace, String value, BuildableItem buildableItem); + + boolean unregisterCustomItem(String namespace, String value); + + @Nullable + BuildableItem getBuildableItem(String namespace, String value); + + boolean registerItemLibrary(ItemLibrary itemLibrary); + + boolean unRegisterItemLibrary(ItemLibrary itemLibrary); + + boolean unRegisterItemLibrary(String itemLibrary); + + void dropItem(Player player, Location hookLocation, Location playerLocation, Loot loot, Map args); + + void dropItem(Location hookLocation, Location playerLocation, ItemStack itemStack); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/LootManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/LootManager.java new file mode 100644 index 00000000..adcb6e52 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/LootManager.java @@ -0,0 +1,8 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import org.jetbrains.annotations.Nullable; + +public interface LootManager { + @Nullable Loot getLoot(String key); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/MarketManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/MarketManager.java new file mode 100644 index 00000000..6ee01a97 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/MarketManager.java @@ -0,0 +1,13 @@ +package net.momirealms.customfishing.api.manager; + +import org.bukkit.inventory.ItemStack; + +public interface MarketManager { + int getDate(); + + double getItemPrice(ItemStack itemStack); + + String getFormula(); + + double getPrice(float base, float bonus, float size); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/MobManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/MobManager.java new file mode 100644 index 00000000..71329826 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/MobManager.java @@ -0,0 +1,15 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.mob.MobLibrary; +import org.bukkit.Location; + +public interface MobManager { + boolean registerMobLibrary(MobLibrary mobLibrary); + + boolean unregisterMobLibrary(String lib); + + boolean unregisterMobLibrary(MobLibrary mobLibrary); + + void summonMob(Location hookLocation, Location playerLocation, Loot loot); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java new file mode 100644 index 00000000..fecf9aee --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java @@ -0,0 +1,23 @@ +package net.momirealms.customfishing.api.manager; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public interface PlaceholderManager { + + String setPlaceholders(Player player, String text); + + String setPlaceholders(OfflinePlayer player, String text); + + List detectPlaceholders(String text); + + String getSingleValue(@Nullable Player player, String placeholder, Map placeholders); + + String parse(@Nullable OfflinePlayer player, String text, Map placeholders); + + List parse(@Nullable OfflinePlayer player, List list, Map replacements); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/RequirementManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/RequirementManager.java new file mode 100644 index 00000000..447dea72 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/RequirementManager.java @@ -0,0 +1,41 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import net.momirealms.customfishing.api.mechanic.requirement.RequirementBuilder; +import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; + +public interface RequirementManager { + + boolean registerRequirement(String type, RequirementBuilder requirementBuilder); + + boolean unregisterRequirement(String type); + + HashMap getLootWithWeight(Condition condition); + + @Nullable Requirement[] getRequirements(ConfigurationSection section, boolean advanced); + + Requirement getRequirement(ConfigurationSection section, boolean checkAction); + + Requirement getRequirement(String key, Object value); + + RequirementBuilder getRequirementBuilder(String type); + + static boolean isRequirementsMet(Requirement[] requirements, Condition condition) { + if (requirements == null) return true; + for (Requirement requirement : requirements) { + if (!requirement.isConditionMet(condition)) { + return false; + } + } + return true; + } + + static boolean isRequirementMet(Requirement requirement, Condition condition) { + if (requirement == null) return true; + return requirement.isConditionMet(condition); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/StorageManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/StorageManager.java new file mode 100644 index 00000000..3ac1a027 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/StorageManager.java @@ -0,0 +1,58 @@ +package net.momirealms.customfishing.api.manager; + +import net.momirealms.customfishing.api.data.DataStorageInterface; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.user.OfflineUser; +import net.momirealms.customfishing.api.data.user.OnlineUser; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public interface StorageManager { + + /** + * Get server unique id + * @return id + */ + String getUniqueID(); + + /** + * Get online user's data + * @param uuid uuid + * @return online user data + */ + OnlineUser getOnlineUser(UUID uuid); + + /** + * Get an offline user's data + * force reading would ignore the database lock + * Otherwise it would return Optional.empty() if data is locked + * It an offline user never played the server, its name would equal "" (empty string) + * @param uuid uuid + * @param force force + * @return offline user data + */ + CompletableFuture> getOfflineUser(UUID uuid, boolean force); + + /** + * Get all the players in servers that connected to the same redis server + * @return amount + */ + CompletableFuture getRedisPlayerCount(); + + /** + * Get plugin data source + * @return data source + */ + DataStorageInterface getDataSource(); + + boolean isRedisEnabled(); + + byte[] toBytes(@NotNull PlayerData data); + + @NotNull String toJson(@NotNull PlayerData data); + + @NotNull PlayerData fromBytes(byte[] data); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/TotemManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/TotemManager.java new file mode 100644 index 00000000..8cb4c91e --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/TotemManager.java @@ -0,0 +1,4 @@ +package net.momirealms.customfishing.api.manager; + +public interface TotemManager { +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/VersionManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/VersionManager.java new file mode 100644 index 00000000..babcd421 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/VersionManager.java @@ -0,0 +1,18 @@ +package net.momirealms.customfishing.api.manager; + +import java.util.concurrent.CompletableFuture; + +public interface VersionManager { + + boolean isVersionNewerThan1_19_R2(); + + CompletableFuture checkUpdate(); + + boolean isSpigot(); + + public boolean isFolia(); + + String getPluginVersion(); + + String getServerVersion(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/TempFishingState.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/TempFishingState.java new file mode 100644 index 00000000..d76a8ef8 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/TempFishingState.java @@ -0,0 +1,30 @@ +package net.momirealms.customfishing.api.mechanic; + +import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.mechanic.loot.Loot; + +public class TempFishingState { + + private final Effect effect; + private final FishingPreparation preparation; + private final Loot loot; + + public TempFishingState(Effect effect, FishingPreparation preparation, Loot loot) { + this.effect = effect; + this.preparation = preparation; + this.loot = loot; + } + + public Effect getEffect() { + return effect; + } + + public FishingPreparation getPreparation() { + return preparation; + } + + public Loot getLoot() { + return loot; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/Action.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/Action.java new file mode 100644 index 00000000..8295559d --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/Action.java @@ -0,0 +1,9 @@ +package net.momirealms.customfishing.api.mechanic.action; + +import net.momirealms.customfishing.api.mechanic.condition.Condition; + +public interface Action { + + void trigger(Condition condition); + +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionBuilder.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionBuilder.java new file mode 100644 index 00000000..5f79a367 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionBuilder.java @@ -0,0 +1,6 @@ +package net.momirealms.customfishing.api.mechanic.action; + +public interface ActionBuilder { + + Action build(Object args, double chance); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java new file mode 100644 index 00000000..1c3c72aa --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java @@ -0,0 +1,9 @@ +package net.momirealms.customfishing.api.mechanic.action; + +public enum ActionTrigger { + + SUCCESS, + FAILURE, + HOOK, + CONSUME +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/bag/FishingBagHolder.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/bag/FishingBagHolder.java new file mode 100644 index 00000000..5ca2b465 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/bag/FishingBagHolder.java @@ -0,0 +1,35 @@ +package net.momirealms.customfishing.api.mechanic.bag; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class FishingBagHolder implements InventoryHolder { + + private final UUID owner; + private Inventory inventory; + + public FishingBagHolder(UUID owner) { + this.owner = owner; + } + + @Override + public @NotNull Inventory getInventory() { + return inventory; + } + + public void setItems(ItemStack[] itemStacks) { + this.inventory.setContents(itemStacks); + } + + public UUID getOwner() { + return owner; + } + + public void setInventory(Inventory inventory) { + this.inventory = inventory; + } +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockConfig.java new file mode 100644 index 00000000..dddc75cc --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockConfig.java @@ -0,0 +1,86 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import java.util.List; + +public class BlockConfig implements BlockSettings { + + private String blockID; + private List dataModifierList; + private List stateModifierList; + private boolean persist; + private double horizontalVector; + private double verticalVector; + + @Override + public String getBlockID() { + return blockID; + } + + @Override + public List getDataModifier() { + return dataModifierList; + } + + @Override + public List getStateModifierList() { + return stateModifierList; + } + + @Override + public boolean isPersist() { + return persist; + } + + @Override + public double getHorizontalVector() { + return horizontalVector; + } + + @Override + public double getVerticalVector() { + return verticalVector; + } + + public static class Builder { + + private final BlockConfig config; + + public Builder() { + this.config = new BlockConfig(); + } + + public Builder persist(boolean value) { + config.persist = value; + return this; + } + + public Builder horizontalVector(double value) { + config.horizontalVector = value; + return this; + } + + public Builder verticalVector(double value) { + config.verticalVector = value; + return this; + } + + public Builder blockID(String value) { + config.blockID = value; + return this; + } + + public Builder dataModifiers(List value) { + config.dataModifierList = value; + return this; + } + + public Builder stateModifiers(List value) { + config.stateModifierList = value; + return this; + } + + public BlockConfig build() { + return config; + } + } +} 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 new file mode 100644 index 00000000..b77a762e --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifier.java @@ -0,0 +1,8 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; + +public interface BlockDataModifier { + void apply(Player player, BlockData blockData); +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifierBuilder.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifierBuilder.java new file mode 100644 index 00000000..efcfe961 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifierBuilder.java @@ -0,0 +1,8 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import java.util.InvalidPropertiesFormatException; + +public interface BlockDataModifierBuilder { + + BlockDataModifier build(Object args); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockLibrary.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockLibrary.java new file mode 100644 index 00000000..c0f0e10e --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockLibrary.java @@ -0,0 +1,14 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.List; + +public interface BlockLibrary { + + String identification(); + + BlockData getBlockData(Player player, String id, List modifiers); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockSettings.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockSettings.java new file mode 100644 index 00000000..270b6414 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockSettings.java @@ -0,0 +1,17 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import java.util.List; + +public interface BlockSettings { + String getBlockID(); + + List getDataModifier(); + + List getStateModifierList(); + + boolean isPersist(); + + double getHorizontalVector(); + + double getVerticalVector(); +} 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 new file mode 100644 index 00000000..0aa6c511 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java @@ -0,0 +1,9 @@ +package net.momirealms.customfishing.api.mechanic.block; + +import org.bukkit.block.BlockState; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; + +public interface BlockStateModifier { + void apply(Player player, BlockState blockState); +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifierBuilder.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifierBuilder.java new file mode 100644 index 00000000..77ae41fb --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifierBuilder.java @@ -0,0 +1,6 @@ +package net.momirealms.customfishing.api.mechanic.block; + +public interface BlockStateModifierBuilder { + + BlockStateModifier build(Object args); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/AbstractCompetitionInfo.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/AbstractCompetitionInfo.java new file mode 100644 index 00000000..7358f393 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/AbstractCompetitionInfo.java @@ -0,0 +1,25 @@ +package net.momirealms.customfishing.api.mechanic.competition; + +public abstract class AbstractCompetitionInfo { + + protected int refreshRate; + protected int switchInterval; + protected boolean showToAll; + protected String[] texts; + + public int getRefreshRate() { + return refreshRate; + } + + public int getSwitchInterval() { + return switchInterval; + } + + public boolean isShowToAll() { + return showToAll; + } + + public String[] getTexts() { + return texts; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/ActionBarConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/ActionBarConfig.java new file mode 100644 index 00000000..f306aa38 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/ActionBarConfig.java @@ -0,0 +1,37 @@ +package net.momirealms.customfishing.api.mechanic.competition; + +public class ActionBarConfig extends AbstractCompetitionInfo { + + public static class Builder { + + private final ActionBarConfig config; + + public Builder() { + this.config = new ActionBarConfig(); + } + + public Builder showToAll(boolean showToAll) { + this.config.showToAll = showToAll; + return this; + } + + public Builder refreshRate(int rate) { + this.config.refreshRate = rate; + return this; + } + + public Builder switchInterval(int interval) { + this.config.switchInterval = interval; + return this; + } + + public Builder text(String[] texts) { + this.config.texts = texts; + return this; + } + + public ActionBarConfig build() { + return this.config; + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/BossBarConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/BossBarConfig.java new file mode 100644 index 00000000..9306cb66 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/BossBarConfig.java @@ -0,0 +1,68 @@ +package net.momirealms.customfishing.api.mechanic.competition; + +import org.bukkit.boss.BarColor; + +public class BossBarConfig extends AbstractCompetitionInfo { + + private BarColor color; + private Overlay overlay; + + public BarColor getColor() { + return color; + } + + public Overlay getOverlay() { + return overlay; + } + + public static class Builder { + + private final BossBarConfig config; + + public Builder() { + this.config = new BossBarConfig(); + } + + public Builder showToAll(boolean showToAll) { + this.config.showToAll = showToAll; + return this; + } + + public Builder refreshRate(int rate) { + this.config.refreshRate = rate; + return this; + } + + public Builder switchInterval(int interval) { + this.config.switchInterval = interval; + return this; + } + + public Builder text(String[] texts) { + this.config.texts = texts; + return this; + } + + public Builder color(BarColor color) { + this.config.color = color; + return this; + } + + public Builder overlay(Overlay overlay) { + this.config.overlay = overlay; + return this; + } + + public BossBarConfig build() { + return this.config; + } + } + + public enum Overlay { + NOTCHED_6, + NOTCHED_10, + NOTCHED_12, + NOTCHED_20, + PROGRESS + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfig.java new file mode 100644 index 00000000..77119235 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionConfig.java @@ -0,0 +1,131 @@ +package net.momirealms.customfishing.api.mechanic.competition; + +import net.momirealms.customfishing.api.mechanic.action.Action; + +import java.util.HashMap; + +public class CompetitionConfig { + + private final String key; + private int duration; + private int minPlayers; + private BossBarConfig bossBarConfig; + private ActionBarConfig actionBarConfig; + private Action[] skipActions; + private Action[] startActions; + private Action[] endActions; + private Action[] joinActions; + private CompetitionGoal goal; + private HashMap rewards; + + public CompetitionConfig(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public int getDuration() { + return duration; + } + + public int getMinPlayers() { + return minPlayers; + } + + public Action[] getStartActions() { + return startActions; + } + + public Action[] getEndActions() { + return endActions; + } + + public Action[] getJoinActions() { + return joinActions; + } + + public Action[] getSkipActions() { + return skipActions; + } + + public CompetitionGoal getGoal() { + return goal; + } + + public HashMap getRewards() { + return rewards; + } + + public BossBarConfig getBossBarConfig() { + return bossBarConfig; + } + + public ActionBarConfig getActionBarConfig() { + return actionBarConfig; + } + + public static class Builder { + + private final CompetitionConfig config; + + public Builder(String key) { + this.config = new CompetitionConfig(key); + } + + public Builder duration(int duration) { + config.duration = duration; + return this; + } + + public Builder minPlayers(int min) { + config.minPlayers = min; + return this; + } + + public Builder startActions(Action[] startActions) { + config.startActions = startActions; + return this; + } + + public Builder endActions(Action[] endActions) { + config.endActions = endActions; + return this; + } + + public Builder skipActions(Action[] skipActions) { + config.skipActions = skipActions; + return this; + } + + public Builder joinActions(Action[] joinActions) { + config.joinActions = joinActions; + return this; + } + + public Builder actionbar(ActionBarConfig actionBarConfig) { + config.actionBarConfig = actionBarConfig; + return this; + } + + public Builder bossbar(BossBarConfig bossBarConfig) { + config.bossBarConfig = bossBarConfig; + return this; + } + + public Builder goal(CompetitionGoal goal) { + config.goal = goal; + return this; + } + + public Builder rewards(HashMap rewards) { + config.rewards = rewards; + return this; + } + + public CompetitionConfig build() { + return config; + } + } +} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/AbstractAction.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java similarity index 64% rename from src/main/java/net/momirealms/customfishing/fishing/action/AbstractAction.java rename to api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java index 5dc18cf8..306471a9 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/action/AbstractAction.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionGoal.java @@ -15,21 +15,19 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing.action; +package net.momirealms.customfishing.api.mechanic.competition; -public abstract class AbstractAction { +import java.util.concurrent.ThreadLocalRandom; - protected double chance; +public enum CompetitionGoal { - public AbstractAction(double chance) { - this.chance = chance; - } + CATCH_AMOUNT, + TOTAL_SCORE, + MAX_SIZE, + TOTAL_SIZE, + RANDOM; - public double getChance() { - return chance; - } - - public boolean canExecute() { - return Math.random() < chance; + public static CompetitionGoal getRandom() { + return CompetitionGoal.values()[ThreadLocalRandom.current().nextInt(CompetitionGoal.values().length - 1)]; } } diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionPlayer.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionPlayer.java similarity index 73% rename from src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionPlayer.java rename to api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionPlayer.java index 0c07d99d..5a18ef9e 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionPlayer.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/CompetitionPlayer.java @@ -15,35 +15,38 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing.competition; +package net.momirealms.customfishing.api.mechanic.competition; import org.jetbrains.annotations.NotNull; public class CompetitionPlayer implements Comparable{ + public static CompetitionPlayer empty = new CompetitionPlayer("", 0); private long time; private final String player; - private float score; + private double score; - public static CompetitionPlayer emptyPlayer = new CompetitionPlayer(null, 0); - - public CompetitionPlayer(String player, float score) { + public CompetitionPlayer(String player, double score) { this.player = player; this.score = score; this.time = System.currentTimeMillis(); } - public void addScore(float score){ + public void addScore(double score){ this.score += score; this.time = System.currentTimeMillis(); } - public void setScore(float score){ + public void setScore(double score){ this.score = score; this.time = System.currentTimeMillis(); } - public float getScore() { + public long getTime() { + return time; + } + + public double getScore() { return this.score; } @@ -55,17 +58,19 @@ public class CompetitionPlayer implements Comparable{ public int compareTo(@NotNull CompetitionPlayer competitionPlayer) { if (competitionPlayer.getScore() != this.score) { return (competitionPlayer.getScore() > this.score) ? 1 : -1; + } else if (competitionPlayer.getTime() != this.time) { + return (competitionPlayer.getTime() > this.time) ? 1 : -1; } else { - return (competitionPlayer.getScore() > this.time) ? 1 : -1; + return 0; } } @Override public String toString() { - return "CompetitionPlayer{" + + return "CompetitionPlayer[" + "time=" + time + ", player='" + player + '\'' + ", score=" + score + - '}'; + ']'; } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/FishingCompetition.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/FishingCompetition.java new file mode 100644 index 00000000..5c266844 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/FishingCompetition.java @@ -0,0 +1,30 @@ +package net.momirealms.customfishing.api.mechanic.competition; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +public interface FishingCompetition { + void start(); + + void stop(); + + void end(); + + boolean isOnGoing(); + + void refreshData(Player player, double score, boolean doubleScore); + + boolean hasPlayerJoined(OfflinePlayer player); + + float getProgress(); + + long getRemainingTime(); + + long getStartTime(); + + CompetitionConfig getConfig(); + + CompetitionGoal getGoal(); + + Ranking getRanking(); +} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/ranking/RankingInterface.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/Ranking.java similarity index 68% rename from src/main/java/net/momirealms/customfishing/fishing/competition/ranking/RankingInterface.java rename to api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/Ranking.java index 38a215f8..a4cca23d 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/ranking/RankingInterface.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/competition/Ranking.java @@ -15,24 +15,33 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing.competition.ranking; +package net.momirealms.customfishing.api.mechanic.competition; -import net.momirealms.customfishing.fishing.competition.CompetitionPlayer; +import net.momirealms.customfishing.api.common.Pair; import org.jetbrains.annotations.Nullable; import java.util.Iterator; -public interface RankingInterface { +public interface Ranking { void clear(); + CompetitionPlayer getCompetitionPlayer(String player); - Iterator getIterator(); + + Iterator> getIterator(); + int getSize(); - String getPlayerRank(String player); - float getPlayerScore(String player); - void refreshData(String player, float score); - void setData(String player, float score); + + int getPlayerRank(String player); + + double getPlayerScore(String player); + + void refreshData(String player, double score); + + void setData(String player, double score); + @Nullable String getPlayerAt(int rank); - float getScoreAt(int rank); + + double getScoreAt(int rank); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/Condition.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/Condition.java new file mode 100644 index 00000000..170a4383 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/Condition.java @@ -0,0 +1,72 @@ +package net.momirealms.customfishing.api.mechanic.condition; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; + +public class Condition { + + @Nullable + protected final Location location; + @Nullable + protected final Player player; + @NotNull + protected final HashMap args; + + public Condition() { + this(null, null, new HashMap<>()); + } + + public Condition(HashMap args) { + this(null, null, args); + } + + public Condition(Player player) { + this(player.getLocation(), player, new HashMap<>()); + } + + public Condition(Player player, HashMap args) { + this(player.getLocation(), player, args); + } + + public Condition(@Nullable Location location, @Nullable Player player, @NotNull HashMap args) { + this.location = location; + this.player = player; + this.args = args; + if (player != null) + this.args.put("player", player.getName()); + if (location != null) { + this.args.put("x", String.valueOf(location.getX())); + this.args.put("y", String.valueOf(location.getY())); + this.args.put("z", String.valueOf(location.getZ())); + this.args.put("world", location.getWorld().getName()); + } + } + + @Nullable + public Location getLocation() { + return location; + } + + @Nullable + public Player getPlayer() { + return player; + } + + @NotNull + public HashMap getArgs() { + return args; + } + + @Nullable + public String getArg(String key) { + return args.get(key); + } + + public void insertArg(String key, String value) { + args.put(key, value); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/FishingPreparation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/FishingPreparation.java new file mode 100644 index 00000000..d7312947 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/condition/FishingPreparation.java @@ -0,0 +1,143 @@ +package net.momirealms.customfishing.api.mechanic.condition; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +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 FishingPreparation extends Condition { + + private final boolean rodOnMainHand; + private final @NotNull ItemStack rodItemStack; + private final @NotNull String rodItemID; + private final @Nullable Effect rodEffect; + private @Nullable ItemStack baitItemStack; + private @Nullable String baitItemID; + private @Nullable Effect baitEffect; + private final List utilEffects; + private boolean canFish = true; + + public FishingPreparation(Player player, CustomFishingPlugin plugin) { + super(player); + + PlayerInventory playerInventory = player.getInventory(); + ItemStack mainHandItem = playerInventory.getItemInMainHand(); + ItemStack offHandItem = playerInventory.getItemInOffHand(); + + this.utilEffects = new ArrayList<>(); + this.rodOnMainHand = mainHandItem.getType() == Material.FISHING_ROD; + this.rodItemStack = this.rodOnMainHand ? mainHandItem : offHandItem; + this.rodItemID = plugin.getItemManager().getAnyItemID(this.rodItemStack); + this.rodEffect = plugin.getEffectManager().getEffect("rod", this.rodItemID); + super.insertArg("rod", this.rodItemID); + + String baitItemID = plugin.getItemManager().getAnyItemID(this.rodOnMainHand ? offHandItem : mainHandItem); + Effect baitEffect = plugin.getEffectManager().getEffect("bait", baitItemID); + if (baitEffect != null) { + this.baitItemID = baitItemID; + this.baitItemStack = this.rodOnMainHand ? offHandItem : mainHandItem; + this.baitEffect = baitEffect; + } else if (plugin.getBagManager().isBagEnabled()) { + Inventory fishingBag = plugin.getBagManager().getOnlineBagInventory(player.getUniqueId()); + HashSet uniqueUtils = new HashSet<>(4); + if (fishingBag != null) { + for (int i = 0; i < fishingBag.getSize(); i++) { + ItemStack itemInBag = fishingBag.getItem(i); + String bagItemID = plugin.getItemManager().getItemID(itemInBag); + if (bagItemID == null) continue; + if (this.baitEffect == null) { + Effect effect = plugin.getEffectManager().getEffect("bait", bagItemID); + if (effect != null) { + this.baitItemID = bagItemID; + this.baitItemStack = itemInBag; + this.baitEffect = effect; + continue; + } + } + Effect utilEffect = plugin.getEffectManager().getEffect("util", bagItemID); + if (utilEffect != null + && !uniqueUtils.contains(bagItemID) + && utilEffect.canMerge(this)) { + utilEffects.add(utilEffect); + uniqueUtils.add(bagItemID); + } + } + } + } else { + this.baitItemID = null; + this.baitItemStack = null; + this.baitEffect = null; + } + + if (this.baitEffect != null) { + if (!this.baitEffect.canMerge(this)) { + this.canFish = false; + return; + } + super.insertArg("bait", this.baitItemID); + } + + if (this.rodEffect != null) { + if (!this.rodEffect.canMerge(this)) { + this.canFish = false; + } + } + } + + public boolean isRodOnMainHand() { + return rodOnMainHand; + } + + @NotNull + public ItemStack getRodItemStack() { + return rodItemStack; + } + + @NotNull + public String getRodItemID() { + return rodItemID; + } + + @Nullable + public ItemStack getBaitItemStack() { + return baitItemStack; + } + + @Nullable + public String getBaitItemID() { + return baitItemID; + } + + @Nullable + public Effect getRodEffect() { + return rodEffect; + } + + @Nullable + public Effect getBaitEffect() { + return baitEffect; + } + + public boolean canFish() { + return this.canFish; + } + + @Override + public @NotNull Player getPlayer() { + assert super.player != null; + return super.player; + } + + public List getUtilEffects() { + return utilEffects; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/AbstractEffect.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/AbstractEffect.java new file mode 100644 index 00000000..22b12eca --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/AbstractEffect.java @@ -0,0 +1,96 @@ +package net.momirealms.customfishing.api.mechanic.effect; + +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.loot.Modifier; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; + +import java.util.ArrayList; +import java.util.List; + +public class AbstractEffect implements Effect { + + protected boolean lavaFishing = false; + protected double multipleLootChance = 0; + protected double sizeMultiplier = 1; + protected double scoreMultiplier = 1; + protected double timeModifier = 1; + protected double difficultyModifier = 0; + protected double gameTimeModifier = 0; + protected Requirement[] requirements; + protected List> lootWeightModifier = new ArrayList<>(); + + @Override + public boolean persist() { + return false; + } + + @Override + public Requirement[] getRequirements() { + return requirements; + } + + @Override + public boolean canLavaFishing() { + return lavaFishing; + } + + @Override + public double getMultipleLootChance() { + return multipleLootChance; + } + + @Override + public double getSizeMultiplier() { + return sizeMultiplier; + } + + @Override + public double getScoreMultiplier() { + return scoreMultiplier; + } + + @Override + public double getTimeModifier() { + return timeModifier; + } + + @Override + public double getGameTimeModifier() { + return gameTimeModifier; + } + + @Override + public double getDifficultyModifier() { + return difficultyModifier; + } + + @Override + public AbstractEffect merge(Effect another) { + if (another == null) return this; + if (another.canLavaFishing()) this.lavaFishing = true; + this.scoreMultiplier += (another.getScoreMultiplier() -1); + this.sizeMultiplier += (another.getSizeMultiplier() -1); + this.timeModifier += (another.getTimeModifier() -1); + this.multipleLootChance += another.getMultipleLootChance(); + this.difficultyModifier += another.getDifficultyModifier(); + this.gameTimeModifier += another.getGameTimeModifier(); + return this; + } + + @Override + public List> getLootWeightModifier() { + return lootWeightModifier; + } + + @Override + public boolean canMerge(Condition condition) { + if (this.requirements == null) return true; + for (Requirement requirement : requirements) { + if (!requirement.isConditionMet(condition)) { + return false; + } + } + return true; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/Effect.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/Effect.java new file mode 100644 index 00000000..f71be5a1 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/Effect.java @@ -0,0 +1,35 @@ +package net.momirealms.customfishing.api.mechanic.effect; + +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.loot.Modifier; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; + +import java.util.List; + +public interface Effect { + + boolean persist(); + + Requirement[] getRequirements(); + + boolean canLavaFishing(); + + double getMultipleLootChance(); + + double getSizeMultiplier(); + + double getScoreMultiplier(); + + double getTimeModifier(); + + double getGameTimeModifier(); + + double getDifficultyModifier(); + + Effect merge(Effect another); + + List> getLootWeightModifier(); + + boolean canMerge(Condition condition); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/FishingEffect.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/FishingEffect.java new file mode 100644 index 00000000..539f1717 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/effect/FishingEffect.java @@ -0,0 +1,68 @@ +package net.momirealms.customfishing.api.mechanic.effect; + +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.loot.Modifier; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; + +import java.util.List; + +public class FishingEffect extends AbstractEffect { + + public static class Builder { + + private final FishingEffect effect; + + public Builder() { + this.effect = new FishingEffect(); + } + + public Builder lootWeightModifier(List> modifier) { + effect.lootWeightModifier = modifier; + return this; + } + + public Builder multipleLootChance(double multipleLootChance) { + effect.multipleLootChance = multipleLootChance; + return this; + } + + public Builder difficultyModifier(double difficultyModifier) { + effect.difficultyModifier = difficultyModifier; + return this; + } + + public Builder sizeMultiplier(double sizeMultiplier) { + effect.sizeMultiplier = sizeMultiplier; + return this; + } + + public Builder timeModifier(double timeModifier) { + effect.timeModifier = timeModifier; + return this; + } + + public Builder scoreMultiplier(double scoreMultiplier) { + effect.scoreMultiplier = scoreMultiplier; + return this; + } + + public Builder gameTimeModifier(double gameTimeModifier) { + effect.gameTimeModifier = gameTimeModifier; + return this; + } + + public Builder lavaFishing(boolean lavaFishing) { + effect.lavaFishing = lavaFishing; + return this; + } + + public Builder requirements(Requirement[] requirements) { + effect.requirements = requirements; + return this; + } + + public FishingEffect build() { + return effect; + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGame.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGame.java new file mode 100644 index 00000000..cd4c3bc6 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGame.java @@ -0,0 +1,14 @@ +package net.momirealms.customfishing.api.mechanic.game; + +import net.momirealms.customfishing.api.manager.FishingManager; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +public abstract class AbstractGame implements Game { + + public AbstractGame(ConfigurationSection config) { + } + + @Override + public abstract GamingPlayer start(Player player, GameSettings settings, FishingManager manager); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGamingPlayer.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGamingPlayer.java new file mode 100644 index 00000000..cf7dc4e6 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGamingPlayer.java @@ -0,0 +1,101 @@ +package net.momirealms.customfishing.api.mechanic.game; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.FishingManager; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.potion.PotionEffectType; + +import java.util.concurrent.TimeUnit; + +public abstract class AbstractGamingPlayer implements GamingPlayer, Runnable { + + protected boolean succeeded; + protected CancellableTask task; + protected Player player; + protected GameSettings settings; + protected FishingManager manager; + private final long deadline; + + public AbstractGamingPlayer(Player player, GameSettings settings, FishingManager manager) { + this.player = player; + this.settings = settings; + this.manager = manager; + this.deadline = System.currentTimeMillis() + settings.getTime() * 1000L; + this.arrangeTask(); + } + + public void arrangeTask() { + this.task = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, 50, 50, TimeUnit.MILLISECONDS); + } + + @Override + public void cancel() { + if (task != null && !task.isCancelled()) + task.cancel(); + } + + @Override + public boolean isSucceeded() { + return succeeded; + } + + @Override + public boolean onRightClick() { + manager.processGameResult(this); + return true; + } + + @Override + public boolean onLeftClick() { + return false; + } + + @Override + public boolean onSwapHand() { + return false; + } + + @Override + public boolean onJump() { + return false; + } + + @Override + public Player getPlayer() { + return player; + } + + @Override + public Effect getEffectReward() { + return null; + } + + @Override + public void run() { + timeOutCheck(); + switchItemCheck(); + } + + protected void timeOutCheck() { + if (System.currentTimeMillis() > deadline) { + cancel(); + if (manager.removeHook(player.getUniqueId())) { + manager.processGameResult(this); + } + } + } + + protected void switchItemCheck() { + PlayerInventory playerInventory = player.getInventory(); + if (playerInventory.getItemInMainHand().getType() != Material.FISHING_ROD + && playerInventory.getItemInOffHand().getType() != Material.FISHING_ROD) { + cancel(); + manager.processGameResult(this); + player.removePotionEffect(PotionEffectType.SLOW); + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/Game.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/Game.java new file mode 100644 index 00000000..0de14d0f --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/Game.java @@ -0,0 +1,9 @@ +package net.momirealms.customfishing.api.mechanic.game; + +import net.momirealms.customfishing.api.manager.FishingManager; +import org.bukkit.entity.Player; + +public interface Game { + + GamingPlayer start(Player player, GameSettings settings, FishingManager manager); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameConfig.java new file mode 100644 index 00000000..1888526e --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameConfig.java @@ -0,0 +1,11 @@ +package net.momirealms.customfishing.api.mechanic.game; + +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import org.jetbrains.annotations.Nullable; + +public interface GameConfig { + + @Nullable + Pair getRandomGame(Effect effect); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameGroup.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameGroup.java new file mode 100644 index 00000000..7e1c1e4f --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameGroup.java @@ -0,0 +1,61 @@ +package net.momirealms.customfishing.api.mechanic.game; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.util.WeightUtils; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public class GameGroup implements GameConfig { + + private final List> gamePairs; + private int minTime; + private int maxTime; + private int minDifficulty; + private int maxDifficulty; + + public GameGroup(List> gamePairs) { + this.gamePairs = gamePairs; + } + + public GameGroup difficulty(int value) { + minDifficulty = (maxDifficulty = value); + return this; + } + + public GameGroup time(int value) { + minTime = (maxTime = value); + return this; + } + + public GameGroup difficulty(int min, int max) { + minDifficulty = min; + maxDifficulty = max; + return this; + } + + public GameGroup time(int min, int max) { + minTime = min; + maxTime = max; + return this; + } + + @Override + @Nullable + public Pair getRandomGame(Effect effect) { + String key = WeightUtils.getRandom(gamePairs); + Game game = CustomFishingPlugin.get().getGameManager().getGame(key); + if (game == null) { + CustomFishingPlugin.get().getLogger().warning(String.format("Game %s doesn't exist!", key)); + return null; + } + GameSettings settings = new GameSettings( + ThreadLocalRandom.current().nextInt(minTime, maxTime + 1), + (int) (ThreadLocalRandom.current().nextInt(minDifficulty, maxDifficulty + 1) + effect.getDifficultyModifier()) + ); + return Pair.of(game, settings); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameGroups.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameGroups.java new file mode 100644 index 00000000..ec7ab18e --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameGroups.java @@ -0,0 +1,33 @@ +package net.momirealms.customfishing.api.mechanic.game; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.util.WeightUtils; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class GameGroups implements GameConfig { + + private final List> gamesWithWeight; + + public GameGroups(List> gamesWithWeight) { + this.gamesWithWeight = gamesWithWeight; + } + + @Override + public @Nullable Pair getRandomGame(Effect effect) { + String group = WeightUtils.getRandom(gamesWithWeight); + GameConfig gameConfig = CustomFishingPlugin.get().getGameManager().getGameConfig(group); + if (gameConfig == null) { + CustomFishingPlugin.get().getLogger().warning(String.format("Game config %s doesn't exist!", group)); + return null; + } + if (!(gameConfig instanceof GameGroup gameGroup)) { + CustomFishingPlugin.get().getLogger().warning(String.format("%s is not a game group!", group)); + return null; + } + return gameGroup.getRandomGame(effect); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameSettings.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameSettings.java new file mode 100644 index 00000000..05c90ea7 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GameSettings.java @@ -0,0 +1,20 @@ +package net.momirealms.customfishing.api.mechanic.game; + +public class GameSettings { + + private final int time; + private final int difficulty; + + public GameSettings(int time, int difficulty) { + this.time = time; + this.difficulty = difficulty; + } + + public int getTime() { + return time; + } + + public int getDifficulty() { + return difficulty; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GamingPlayer.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GamingPlayer.java new file mode 100644 index 00000000..ec145138 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/GamingPlayer.java @@ -0,0 +1,23 @@ +package net.momirealms.customfishing.api.mechanic.game; + +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import org.bukkit.entity.Player; + +public interface GamingPlayer { + + void cancel(); + + boolean isSucceeded(); + + boolean onRightClick(); + + boolean onLeftClick(); + + boolean onSwapHand(); + + boolean onJump(); + + Player getPlayer(); + + Effect getEffectReward(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/BuildableItem.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/BuildableItem.java new file mode 100644 index 00000000..dd001b92 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/BuildableItem.java @@ -0,0 +1,25 @@ +package net.momirealms.customfishing.api.mechanic.item; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; + +public interface BuildableItem { + + default ItemStack build() { + return build(null, new HashMap<>()); + } + + default ItemStack build(Player player) { + return build(player, new HashMap<>()); + } + + ItemStack build(Player player, Map placeholders); + + /** + * Whether the item would be removed from cache when reloading + */ + boolean persist(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemBuilder.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemBuilder.java new file mode 100644 index 00000000..9d2ace7f --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemBuilder.java @@ -0,0 +1,72 @@ +package net.momirealms.customfishing.api.mechanic.item; + +import de.tr7zw.changeme.nbtapi.NBTItem; +import net.momirealms.customfishing.api.common.Pair; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemFlag; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public interface ItemBuilder { + + ItemBuilder customModelData(int value); + + ItemBuilder name(String name); + + ItemBuilder amount(int amount); + + ItemBuilder tag(boolean tag, String type, String id); + + ItemBuilder unbreakable(boolean unbreakable); + + ItemBuilder lore(List lore); + + ItemBuilder nbt(Map nbt); + + ItemBuilder itemFlag(List itemFlags); + + ItemBuilder nbt(ConfigurationSection section); + + ItemBuilder enchantment(List> enchantments, boolean store); + + ItemBuilder maxDurability(int max); + + ItemBuilder price(float base, float bonus); + + ItemBuilder size(Pair size); + + ItemBuilder stackable(boolean stackable); + + ItemBuilder preventGrabbing(boolean prevent); + + ItemBuilder head(String base64); + + ItemBuilder randomDamage(boolean damage); + + @NotNull + String getId(); + + @NotNull + String getLibrary(); + + int getAmount(); + + Collection getEditors(); + + ItemBuilder removeEditor(String type); + + ItemBuilder registerCustomEditor(String type, ItemPropertyEditor editor); + + interface ItemPropertyEditor { + + void edit(Player player, NBTItem nbtItem, Map placeholders); + + default void edit(Player player, NBTItem nbtItem) { + edit(player, nbtItem, null); + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemLibrary.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemLibrary.java new file mode 100644 index 00000000..d6e07fce --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/item/ItemLibrary.java @@ -0,0 +1,13 @@ +package net.momirealms.customfishing.api.mechanic.item; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public interface ItemLibrary { + + String identification(); + + ItemStack buildItem(Player player, String id); + + String getItemID(ItemStack itemStack); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java new file mode 100644 index 00000000..17e37932 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java @@ -0,0 +1,77 @@ +package net.momirealms.customfishing.api.mechanic.loot; + +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.game.GameConfig; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; + +public interface Loot { + + boolean instanceGame(); + + /** + * get the loot id + * @return id + */ + String getID(); + + /** + * get the loot type + * @return type + */ + LootType getType(); + + /** + * nick would be display.name or key name if not set (MiniMessage format) + * @return nick + */ + @NotNull + String getNick(); + + /** + * if the loot can be seen from the finder + * @return show in finder or not + */ + boolean showInFinder(); + + /** + * get the score in competition + * @return score + */ + double getScore(); + + /** + * if the game is disabled + * @return disabled or not + */ + boolean disableGame(); + + /** + * if the statistics is disabled + * @return disabled or not + */ + boolean disableStats(); + + /** + * Get the game config + * @return game config + */ + GameConfig getGameConfig(); + + /** + * get actions triggered by certain events + * @return actions + */ + Action[] getActions(ActionTrigger actionTrigger); + + /** + * get actions when succeeding in fishing for certain times + * @param times times + * @return actions + */ + Action[] getSuccessTimesActions(int times); + + HashMap getSuccessTimesActionMap(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootType.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootType.java new file mode 100644 index 00000000..42fc6c7b --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/LootType.java @@ -0,0 +1,9 @@ +package net.momirealms.customfishing.api.mechanic.loot; + +public enum LootType { + + LOOT, + MOB, + BLOCK, + GLOBAL +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Modifier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Modifier.java new file mode 100644 index 00000000..305ca553 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Modifier.java @@ -0,0 +1,5 @@ +package net.momirealms.customfishing.api.mechanic.loot; + +public interface Modifier { + double modify(double weight); +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/market/MarketGUI.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/market/MarketGUI.java new file mode 100644 index 00000000..c45a70a2 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/market/MarketGUI.java @@ -0,0 +1,19 @@ +package net.momirealms.customfishing.api.mechanic.market; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.jetbrains.annotations.NotNull; + +public class MarketGUI implements InventoryHolder { + + private Inventory inventory; + + public void setInventory(Inventory inventory) { + this.inventory = inventory; + } + + @Override + public @NotNull Inventory getInventory() { + return inventory; + } +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobConfig.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobConfig.java new file mode 100644 index 00000000..a35b6ada --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobConfig.java @@ -0,0 +1,75 @@ +package net.momirealms.customfishing.api.mechanic.mob; + +import java.util.Map; + +public class MobConfig implements MobSettings { + + private String mob; + private double horizontalVector; + private double verticalVector; + private Map propertyMap; + private boolean persist; + + @Override + public boolean isPersist() { + return persist; + } + + @Override + public double getHorizontalVector() { + return horizontalVector; + } + + @Override + public double getVerticalVector() { + return verticalVector; + } + + @Override + public String getMobID() { + return mob; + } + + @Override + public Map getPropertyMap() { + return propertyMap; + } + + public static class Builder { + + private final MobConfig config; + + public Builder() { + this.config = new MobConfig(); + } + + public Builder mobID(String value) { + this.config.mob = value; + return this; + } + + public Builder persist(boolean value) { + this.config.persist = value; + return this; + } + + public Builder verticalVector(double value) { + this.config.verticalVector = value; + return this; + } + + public Builder horizontalVector(double value) { + this.config.horizontalVector = value; + return this; + } + + public Builder propertyMap(Map value) { + this.config.propertyMap = value; + return this; + } + + public MobConfig build() { + return config; + } + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobLibrary.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobLibrary.java new file mode 100644 index 00000000..b47072f1 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobLibrary.java @@ -0,0 +1,13 @@ +package net.momirealms.customfishing.api.mechanic.mob; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +import java.util.Map; + +public interface MobLibrary { + + String identification(); + + Entity spawn(Location location, String id, Map mobPropertyMap); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobSettings.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobSettings.java new file mode 100644 index 00000000..9d575da5 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/mob/MobSettings.java @@ -0,0 +1,15 @@ +package net.momirealms.customfishing.api.mechanic.mob; + +import java.util.Map; + +public interface MobSettings { + boolean isPersist(); + + double getHorizontalVector(); + + double getVerticalVector(); + + String getMobID(); + + Map getPropertyMap(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/Requirement.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/Requirement.java new file mode 100644 index 00000000..6bcf31a8 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/Requirement.java @@ -0,0 +1,8 @@ +package net.momirealms.customfishing.api.mechanic.requirement; + +import net.momirealms.customfishing.api.mechanic.condition.Condition; + +public interface Requirement { + + boolean isConditionMet(Condition condition); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/RequirementBuilder.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/RequirementBuilder.java new file mode 100644 index 00000000..130f7ea0 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/requirement/RequirementBuilder.java @@ -0,0 +1,14 @@ +package net.momirealms.customfishing.api.mechanic.requirement; + +import net.momirealms.customfishing.api.mechanic.action.Action; + +import java.util.List; + +public interface RequirementBuilder { + + Requirement build(Object args, List notMetActions, boolean checkAction); + + default Requirement build(Object args) { + return build(args, null, false); + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java new file mode 100644 index 00000000..79aff324 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java @@ -0,0 +1,85 @@ +package net.momirealms.customfishing.api.mechanic.statistic; + +import com.google.gson.annotations.SerializedName; +import net.momirealms.customfishing.api.data.StatisticData; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.HashMap; +import java.util.Map; + +public class Statistics { + + @SerializedName("statistic_map") + private final HashMap statisticMap; + private int total; + + public Statistics() { + this.statisticMap = new HashMap<>(); + this.total = 0; + } + + public Statistics(ConfigurationSection section) { + this.statisticMap = new HashMap<>(); + this.total = 0; + for (String key : section.getKeys(false)) { + int amount = section.getInt(key); + total += amount; + statisticMap.put(key, amount); + } + } + + public Statistics(StatisticData statisticData) { + this.statisticMap = new HashMap<>(statisticData.statisticMap); + this.total = statisticMap.values().stream().mapToInt(Integer::intValue).sum(); + } + + public void addLootAmount(Loot loot, FishingPreparation fishingPreparation, int amount) { + Integer previous = statisticMap.get(loot.getID()); + if (previous == null) previous = 0; + int after = previous + amount; + statisticMap.put(loot.getID(), after); + total += amount; + doSuccessTimesAction(previous, after, fishingPreparation, loot); + } + + private void doSuccessTimesAction(Integer previous, int after, FishingPreparation fishingPreparation, Loot loot) { + HashMap actionMap = loot.getSuccessTimesActionMap(); + if (actionMap != null) { + for (Map.Entry entry : actionMap.entrySet()) { + if (entry.getKey() > previous && entry.getKey() <= after) { + for (Action action : entry.getValue()) { + action.trigger(fishingPreparation); + } + } + } + } + } + + public int getFishAmount(String key) { + Integer amount = statisticMap.get(key); + return amount == null ? 0 : amount; + } + + public boolean hasFished(String key) { + return statisticMap.containsKey(key); + } + + public void reset() { + statisticMap.clear(); + } + + public HashMap getStatisticMap() { + return statisticMap; + } + + public void setData(String key, int value) { + statisticMap.put(key, value); + } + + public int getTotalCatchAmount() { + return total; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/scheduler/CancellableTask.java b/api/src/main/java/net/momirealms/customfishing/api/scheduler/CancellableTask.java new file mode 100644 index 00000000..5ec6454f --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/scheduler/CancellableTask.java @@ -0,0 +1,8 @@ +package net.momirealms.customfishing.api.scheduler; + +public interface CancellableTask { + + void cancel(); + + boolean isCancelled(); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/scheduler/Scheduler.java b/api/src/main/java/net/momirealms/customfishing/api/scheduler/Scheduler.java new file mode 100644 index 00000000..f7617495 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/scheduler/Scheduler.java @@ -0,0 +1,22 @@ +package net.momirealms.customfishing.api.scheduler; + +import org.bukkit.Location; + +import java.util.concurrent.TimeUnit; + +public interface Scheduler { + + void runTaskSync(Runnable runnable, Location location); + + CancellableTask runTaskSyncTimer(Runnable runnable, Location location, long delay, long period); + + CancellableTask runTaskAsyncLater(Runnable runnable, long delay, TimeUnit timeUnit); + + void runTaskAsync(Runnable runnable); + + CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay, TimeUnit timeUnit); + + CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay); + + CancellableTask runTaskAsyncTimer(Runnable runnable, long delay, long period, TimeUnit timeUnit); +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/util/FontUtils.java b/api/src/main/java/net/momirealms/customfishing/api/util/FontUtils.java new file mode 100644 index 00000000..bd8e95ba --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/util/FontUtils.java @@ -0,0 +1,8 @@ +package net.momirealms.customfishing.api.util; + +public class FontUtils { + + public static String surroundWithFont(String text, String font) { + return "" + text + ""; + } +} diff --git a/api/src/main/java/net/momirealms/customfishing/api/util/InventoryUtils.java b/api/src/main/java/net/momirealms/customfishing/api/util/InventoryUtils.java new file mode 100644 index 00000000..ab6af613 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/util/InventoryUtils.java @@ -0,0 +1,138 @@ +package net.momirealms.customfishing.api.util; + +import net.kyori.adventure.text.Component; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.io.BukkitObjectInputStream; +import org.bukkit.util.io.BukkitObjectOutputStream; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class InventoryUtils { + + public static Inventory createInventory(InventoryHolder inventoryHolder, int size, Component component) { + try { + boolean isSpigot = CustomFishingPlugin.get().getVersionManager().isSpigot(); + Method createInvMethod = ReflectionUtils.bukkitClass.getMethod( + "createInventory", + InventoryHolder.class, + int.class, + isSpigot ? String.class : ReflectionUtils.componentClass + ); + return (Inventory) createInvMethod.invoke( + null, + inventoryHolder, + size, + isSpigot ? CustomFishingPlugin.get().getAdventure().componentToLegacy(component) : CustomFishingPlugin.get().getAdventure().shadedComponentToPaperComponent(component) + ); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { + exception.printStackTrace(); + return null; + } + } + + public static Inventory createInventory(InventoryHolder inventoryHolder, InventoryType type, Component component) { + try { + boolean isSpigot = CustomFishingPlugin.get().getVersionManager().isSpigot(); + Method createInvMethod = ReflectionUtils.bukkitClass.getMethod( + "createInventory", + InventoryHolder.class, + InventoryType.class, + isSpigot ? String.class : ReflectionUtils.componentClass + ); + return (Inventory) createInvMethod.invoke( + null, + inventoryHolder, + type, + isSpigot ? CustomFishingPlugin.get().getAdventure().componentToLegacy(component) : CustomFishingPlugin.get().getAdventure().shadedComponentToPaperComponent(component) + ); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { + exception.printStackTrace(); + return null; + } + } + + public static @NotNull String stacksToBase64(ItemStack[] contents) { + if (contents.length == 0) { + return ""; + } + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + dataOutput.writeInt(contents.length); + for (ItemStack itemStack : contents) { + dataOutput.writeObject(itemStack); + } + dataOutput.close(); + byte[] byteArr = outputStream.toByteArray(); + outputStream.close(); + return Base64Coder.encodeLines(byteArr); + } catch (IOException e) { + LogUtils.warn("Encoding error", e); + } + return ""; + } + + /** + * Get itemStacks from base64 + * @param base64 base64 + * @return itemStacks + */ + @Nullable + public static ItemStack[] getInventoryItems(String base64) { + ItemStack[] itemStacks = null; + try { + itemStacks = stacksFromBase64(base64); + } catch (IllegalArgumentException exception) { + exception.printStackTrace(); + } + return itemStacks; + } + + private static ItemStack[] stacksFromBase64(String data) { + if (data == null || data.equals("")) return new ItemStack[]{}; + + ByteArrayInputStream inputStream; + try { + inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + } catch (IllegalArgumentException e) { + return new ItemStack[]{}; + } + BukkitObjectInputStream dataInput = null; + ItemStack[] stacks = null; + try { + dataInput = new BukkitObjectInputStream(inputStream); + stacks = new ItemStack[dataInput.readInt()]; + } catch (IOException e) { + e.printStackTrace(); + } + if (stacks == null) return new ItemStack[]{}; + for (int i = 0; i < stacks.length; i++) { + try { + stacks[i] = (ItemStack) dataInput.readObject(); + } catch (IOException | ClassNotFoundException | NullPointerException e) { + try { + dataInput.close(); + } catch (IOException exception) { + LogUtils.severe("Failed to read fishing bag data"); + } + return null; + } + } + try { + dataInput.close(); + } catch (IOException ignored) { + } + return stacks; + } +} diff --git a/src/main/java/net/momirealms/customfishing/helper/Log.java b/api/src/main/java/net/momirealms/customfishing/api/util/LogUtils.java similarity index 78% rename from src/main/java/net/momirealms/customfishing/helper/Log.java rename to api/src/main/java/net/momirealms/customfishing/api/util/LogUtils.java index 81d1efde..239711a5 100644 --- a/src/main/java/net/momirealms/customfishing/helper/Log.java +++ b/api/src/main/java/net/momirealms/customfishing/api/util/LogUtils.java @@ -23,9 +23,9 @@ * SOFTWARE. */ -package net.momirealms.customfishing.helper; +package net.momirealms.customfishing.api.util; -import net.momirealms.customfishing.CustomFishing; +import net.momirealms.customfishing.api.CustomFishingPlugin; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; @@ -34,29 +34,29 @@ import java.util.logging.Level; /** * Utility for quickly accessing a logger instance without using {@link Bukkit#getLogger()} */ -public final class Log { +public final class LogUtils { public static void info(@NotNull String s) { - CustomFishing.getInstance().getLogger().info(s); + CustomFishingPlugin.getInstance().getLogger().info(s); } public static void warn(@NotNull String s) { - CustomFishing.getInstance().getLogger().warning(s); + CustomFishingPlugin.getInstance().getLogger().warning(s); } public static void severe(@NotNull String s) { - CustomFishing.getInstance().getLogger().severe(s); + CustomFishingPlugin.getInstance().getLogger().severe(s); } public static void warn(@NotNull String s, Throwable t) { - CustomFishing.getInstance().getLogger().log(Level.WARNING, s, t); + CustomFishingPlugin.getInstance().getLogger().log(Level.WARNING, s, t); } public static void severe(@NotNull String s, Throwable t) { - CustomFishing.getInstance().getLogger().log(Level.SEVERE, s, t); + CustomFishingPlugin.getInstance().getLogger().log(Level.SEVERE, s, t); } - private Log() { + private LogUtils() { throw new UnsupportedOperationException("This class cannot be instantiated"); } diff --git a/api/src/main/java/net/momirealms/customfishing/api/util/OffsetUtils.java b/api/src/main/java/net/momirealms/customfishing/api/util/OffsetUtils.java new file mode 100644 index 00000000..1aabca3a --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/util/OffsetUtils.java @@ -0,0 +1,126 @@ +package net.momirealms.customfishing.api.util; + +import org.bukkit.configuration.ConfigurationSection; + +public class OffsetUtils { + + private static String font; + private static String negative_1; + private static String negative_2; + private static String negative_4; + private static String negative_8; + private static String negative_16; + private static String negative_32; + private static String negative_64; + private static String negative_128; + private static String positive_1; + private static String positive_2; + private static String positive_4; + private static String positive_8; + private static String positive_16; + private static String positive_32; + private static String positive_64; + private static String positive_128; + + public static void loadConfig(ConfigurationSection section) { + if (section != null) { + font = section.getString("font", "customfishing:offset_chars"); + positive_1 = section.getString("1"); + positive_2 = section.getString("2"); + positive_4 = section.getString("4"); + positive_8 = section.getString("8"); + positive_16 = section.getString("16"); + positive_32 = section.getString("32"); + positive_64 = section.getString("64"); + positive_128 = section.getString("128"); + negative_1 = section.getString("-1"); + negative_2 = section.getString("-2"); + negative_4 = section.getString("-4"); + negative_8 = section.getString("-8"); + negative_16 = section.getString("-16"); + negative_32 = section.getString("-32"); + negative_64 = section.getString("-64"); + negative_128 = section.getString("-128"); + } + } + + public static String getShortestNegChars(int n) { + StringBuilder stringBuilder = new StringBuilder(); + while (n >= 128) { + stringBuilder.append(negative_128); + n -= 128; + } + if (n - 64 >= 0) { + stringBuilder.append(negative_64); + n -= 64; + } + if (n - 32 >= 0) { + stringBuilder.append(negative_32); + n -= 32; + } + if (n - 16 >= 0) { + stringBuilder.append(negative_16); + n -= 16; + } + if (n - 8 >= 0) { + stringBuilder.append(negative_8); + n -= 8; + } + if (n - 4 >= 0) { + stringBuilder.append(negative_4); + n -= 4; + } + if (n - 2 >= 0) { + stringBuilder.append(negative_2); + n -= 2; + } + if (n - 1 >= 0) { + stringBuilder.append(negative_1); + } + return stringBuilder.toString(); + } + + public static String getShortestPosChars(int n) { + StringBuilder stringBuilder = new StringBuilder(); + while (n >= 128) { + stringBuilder.append(positive_128); + n -= 128; + } + if (n - 64 >= 0) { + stringBuilder.append(positive_64); + n -= 64; + } + if (n - 32 >= 0) { + stringBuilder.append(positive_32); + n -= 32; + } + if (n - 16 >= 0) { + stringBuilder.append(positive_16); + n -= 16; + } + if (n - 8 >= 0) { + stringBuilder.append(positive_8); + n -= 8; + } + if (n - 4 >= 0) { + stringBuilder.append(positive_4); + n -= 4; + } + if (n - 2 >= 0) { + stringBuilder.append(positive_2); + n -= 2; + } + if (n - 1 >= 0) { + stringBuilder.append(positive_1); + } + return stringBuilder.toString(); + } + + public static String getOffsetChars(int n) { + if (n > 0) { + return "" + getShortestPosChars(n) + ""; + } else { + return "" + getShortestNegChars(-n) + ""; + } + } +} diff --git a/src/main/java/net/momirealms/customfishing/object/Reflection.java b/api/src/main/java/net/momirealms/customfishing/api/util/ReflectionUtils.java similarity index 56% rename from src/main/java/net/momirealms/customfishing/object/Reflection.java rename to api/src/main/java/net/momirealms/customfishing/api/util/ReflectionUtils.java index 760cab48..4fd1410e 100644 --- a/src/main/java/net/momirealms/customfishing/object/Reflection.java +++ b/api/src/main/java/net/momirealms/customfishing/api/util/ReflectionUtils.java @@ -1,56 +1,58 @@ -package net.momirealms.customfishing.object; +package net.momirealms.customfishing.api.util; import com.comphenix.protocol.utility.MinecraftReflection; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.util.AdventureUtils; +import net.momirealms.customfishing.api.CustomFishingPlugin; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -public class Reflection { +public class ReflectionUtils { - public static Class textComponentClass; - public static Class componentClass; - public static Class bukkitClass; - public static Class textColorClass; - public static Class keyClass; - public static Class textDecorationClass; - public static Class textDecorationStateClass; public static Object removeBossBarPacket; public static Constructor progressConstructor; public static Constructor updateConstructor; public static Method iChatComponentMethod; + public static Method gsonDeserializeMethod; + public static Object gsonInstance; + public static Class componentClass; + public static Class bukkitClass; public static void load() { - if (CustomFishing.getInstance().getVersionHelper().isSpigot()) return; try { - textComponentClass = Class.forName("net;kyori;adventure;text;TextComponent".replace(";", ".")); - componentClass = Class.forName("net;kyori;adventure;text;Component".replace(";", ".")); - bukkitClass = Class.forName("org;bukkit;Bukkit".replace(";", ".")); - textColorClass = Class.forName("net;kyori;adventure;text;format;TextColor".replace(";", ".")); - keyClass = Class.forName("net;kyori;adventure;key;Key".replace(";", ".")); - textDecorationClass = Class.forName("net;kyori;adventure;text;format;TextDecoration".replace(";", ".")); - textDecorationStateClass = Class.forName("net;kyori;adventure;text;format;TextDecoration$State".replace(";", ".")); - Class bar = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutBoss"); Field remove = bar.getDeclaredField("f"); remove.setAccessible(true); removeBossBarPacket = remove.get(null); - Class packetBossClassF = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutBoss$f"); progressConstructor = packetBossClassF.getDeclaredConstructor(float.class); progressConstructor.setAccessible(true); - Class packetBossClassE = Class.forName("net.minecraft.network.protocol.game.PacketPlayOutBoss$e"); updateConstructor = packetBossClassE.getDeclaredConstructor(MinecraftReflection.getIChatBaseComponentClass()); updateConstructor.setAccessible(true); - iChatComponentMethod = MinecraftReflection.getChatSerializerClass().getMethod("a", String.class); iChatComponentMethod.setAccessible(true); } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException exception) { - AdventureUtils.consoleMessage("[CustomFishing] Error occurred when loading reflections"); + LogUtils.severe("Error occurred when loading reflections", exception); exception.printStackTrace(); + return; + } + if (CustomFishingPlugin.get().getVersionManager().isSpigot()) return; + try { + componentClass = Class.forName("net;kyori;adventure;text;Component".replace(";", ".")); + bukkitClass = Class.forName("org;bukkit;Bukkit".replace(";", ".")); + Class gsonComponentSerializerClass = Class.forName("net;kyori;adventure;text;serializer;gson;GsonComponentSerializer".replace(";", ".")); + Class gsonComponentSerializerImplClass = Class.forName("net;kyori;adventure;text;serializer;gson;GsonComponentSerializerImpl".replace(";", ".")); + Method gsonMethod = gsonComponentSerializerClass.getMethod("gson"); + gsonInstance = gsonMethod.invoke(null); + gsonDeserializeMethod = gsonComponentSerializerImplClass.getMethod("deserialize", String.class); + gsonDeserializeMethod.setAccessible(true); + } catch (ClassNotFoundException exception) { + LogUtils.severe("Error occurred when loading reflections", exception); + exception.printStackTrace(); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); } } } \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/util/WeightUtils.java b/api/src/main/java/net/momirealms/customfishing/api/util/WeightUtils.java new file mode 100644 index 00000000..26a316dd --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/util/WeightUtils.java @@ -0,0 +1,60 @@ +package net.momirealms.customfishing.api.util; + +import net.momirealms.customfishing.api.common.Pair; + +import java.util.*; + +public class WeightUtils { + + public static T getRandom(List> pairs) { + List available = new ArrayList<>(); + double[] weights = new double[pairs.size()]; + int index = 0; + for (Pair pair : pairs){ + double weight = pair.right(); + T key = pair.left(); + if (weight <= 0) continue; + available.add(key); + weights[index++] = weight; + } + return getRandom(weights, available, index); + } + + public static T getRandom(HashMap map) { + List available = new ArrayList<>(); + double[] weights = new double[map.size()]; + int index = 0; + for (Map.Entry entry : map.entrySet()){ + double weight = entry.getValue(); + T key = entry.getKey(); + if (weight <= 0) continue; + available.add(key); + weights[index++] = weight; + } + return getRandom(weights, available, index); + } + + private static T getRandom(double[] weights, List available, int effectiveSize) { + double total = Arrays.stream(weights).sum(); + double[] weightRatios = new double[effectiveSize]; + for (int i = 0; i < effectiveSize; i++){ + weightRatios[i] = weights[i]/total; + } + double[] weightRange = new double[effectiveSize]; + double startPos = 0; + for (int i = 0; i < effectiveSize; i++) { + weightRange[i] = startPos + weightRatios[i]; + startPos += weightRatios[i]; + } + double random = Math.random(); + int pos = Arrays.binarySearch(weightRange, random); + + if (pos < 0) { + pos = -pos - 1; + } + if (pos < weightRange.length && random < weightRange[pos]) { + return available.get(pos); + } + return null; + } +} diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 4c5a9b7f..00000000 --- a/build.gradle +++ /dev/null @@ -1,99 +0,0 @@ -plugins { - id 'java' - id 'com.github.johnrengelman.shadow' version '7.1.2' -} - -group = 'net.momirealms' -version = '1.3.2.5' - -repositories { - maven {name = "aliyun-repo"; url = "https://maven.aliyun.com/repository/public/"} - maven {name = 'papermc-repo'; url = 'https://papermc.io/repo/repository/maven-public/'} - maven {name = 'sonatype-repo'; url = 'https://oss.sonatype.org/content/groups/public/'} - maven {name = "dmulloy2-repo"; url = "https://repo.dmulloy2.net/repository/public/"} - maven {name = "clip-repo"; url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/'} - maven {name = "codemc-repo"; url = "https://repo.codemc.org/repository/maven-public/"} - maven {name = "sk89q-repo"; url = "https://maven.enginehub.org/repo/"} - maven {name = "jitpack-repo"; url = "https://jitpack.io"} - maven {name = "Lumine-repo"; url = "https://mvn.lumine.io/repository/maven-public"} - maven {name = 'rapture-repo'; url = 'https://repo.rapture.pw/repository/maven-releases/'} - maven {name = 'mmo-repo'; url = 'https://nexus.phoenixdevt.fr/repository/maven-public/'} - maven {name = 'i-repo'; url = 'https://r.irepo.space/maven/'} - maven {name = 'auxilor-repo'; url = 'https://repo.auxilor.io/repository/maven-public/'} - maven {name = 'betonquest-repo'; url = 'https://betonquest.org/nexus/repository/betonquest/'} - mavenCentral() -} - -dependencies { - compileOnly fileTree(dir:'libs',includes:['*.jar']) - implementation fileTree(dir:'libs',includes:['BiomeAPI.jar']) - compileOnly("io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT") - compileOnly('dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT') - compileOnly('com.zaxxer:HikariCP:5.0.1') - compileOnly('commons-io:commons-io:2.11.0') - compileOnly('com.github.Archy-X:AureliumSkills:Beta1.3.6') - compileOnly('redis.clients:jedis:4.4.3') - compileOnly('me.clip:placeholderapi:2.11.3') - compileOnly("com.github.oraxen:oraxen:1.158.0") - compileOnly('io.lumine:Mythic-Dist:5.2.1') - compileOnly('dev.dejvokep:boosted-yaml:1.3.1') - compileOnly('com.github.LoneDev6:api-itemsadder:3.4.1-r4') - compileOnly('net.objecthunter:exp4j:0.4.8') - compileOnly('org.mariadb.jdbc:mariadb-java-client:3.1.4') - compileOnly('com.google.code.gson:gson:2.10.1') - compileOnly('com.willfp:EcoEnchants:10.13.0') - compileOnly("pers.neige.neigeitems:NeigeItems:1.14.23") - compileOnly('net.Indyuce:MMOItems-API:6.9.2-SNAPSHOT') - compileOnly('io.lumine:MythicLib-dist:1.6-SNAPSHOT') - compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0") - compileOnly('net.Indyuce:MMOCore-API:1.12-SNAPSHOT') - compileOnly('com.github.Zrips:Jobs:4.17.2') - compileOnly("com.willfp:eco:6.65.1") - compileOnly("com.willfp:EcoJobs:3.13.0") - compileOnly("com.willfp:EcoSkills:3.8.1") - compileOnly("pl.betoncraft:betonquest:1.12.10") - compileOnly("com.github.MilkBowl:VaultAPI:1.7") - compileOnly("com.github.Archy-X:AureliumSkills:Beta1.3.21") - implementation('net.kyori:adventure-api:4.14.0') - implementation('net.kyori:adventure-platform-bukkit:4.3.0') - implementation('net.kyori:adventure-text-minimessage:4.14.0') - implementation('net.kyori:adventure-text-serializer-legacy:4.14.0') - implementation('de.tr7zw:item-nbt-api:2.11.3') - implementation('org.bstats:bstats-bukkit:3.0.1') -} - -def targetJavaVersion = 17 -java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - sourceCompatibility = javaVersion - targetCompatibility = javaVersion - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) - } -} - -tasks.withType(JavaCompile).configureEach { - options.release = targetJavaVersion - options.encoding = "UTF-8" -} - -processResources { - def props = [version: version] - inputs.properties props - filteringCharset 'UTF-8' - filesMatching('plugin.yml') { - expand props - } -} - -shadowJar { - relocate 'de.tr7zw', 'net.momirealms.customfishing.libs.de.tr7zw' - relocate 'net.kyori', 'net.momirealms.customfishing.libs.net.kyori' - relocate 'org.bstats', 'net.momirealms.customfishing.libs.org.bstats' - relocate 'net.momirealms.biomeapi', 'net.momirealms.customfishing.libs.net.momirealms.biomeapi' -} - -tasks.register("delete", Delete).get().delete("build/libs/"+project.name+"-"+project.version+".jar") -tasks.named("build").get().dependsOn("shadowJar").finalizedBy("delete").doLast { - println("Deleting: "+ "build/libs/"+project.name+"-"+project.version+".jar") -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..6dcd2a8e --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,73 @@ +plugins { + id("java") + id("application") + id("maven-publish") + id("com.github.johnrengelman.shadow") version "8.1.1" +} + +allprojects { + + version = "2.0-beta" + + apply() + apply(plugin = "java") + apply(plugin = "application") + apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "org.gradle.maven-publish") + + application { + mainClass.set("") + } + + repositories { + maven("https://maven.aliyun.com/repository/public/") + mavenCentral() + maven("https://papermc.io/repo/repository/maven-public/") + maven("https://oss.sonatype.org/content/groups/public/") + maven("https://repo.dmulloy2.net/repository/public/") + maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") + maven("https://repo.codemc.org/repository/maven-public/") + maven("https://maven.enginehub.org/repo/") + maven("https://jitpack.io/") + maven("https://mvn.lumine.io/repository/maven-public/") + maven("https://repo.rapture.pw/repository/maven-releases/") + maven("https://nexus.phoenixdevt.fr/repository/maven-public/") + maven("https://r.irepo.space/maven/") + maven("https://repo.auxilor.io/repository/maven-public/") + maven("https://betonquest.org/nexus/repository/betonquest/") + maven("https://repo.william278.net/releases/") + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") + } +} + +subprojects { + tasks.processResources { + val props = mapOf("version" to version) + inputs.properties(props) + filteringCharset = "UTF-8" + filesMatching("plugin.yml") { + expand(props) + } + } + + tasks.withType { + options.encoding = "UTF-8" + } + + tasks.shadowJar { + destinationDirectory.set(file("$rootDir/target")) + archiveClassifier.set("") + archiveFileName.set("CustomFishing-" + project.name + "-" + project.version + ".jar") + } + +// tasks.javadoc.configure { +// options.quiet() +// } +// +// if ("api" == project.name) { +// java { +// withSourcesJar() +// withJavadocJar() +// } +// } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index e69de29b..7b26f395 100644 --- a/gradle.properties +++ b/gradle.properties @@ -0,0 +1,8 @@ +systemProp.socks.proxyHost=127.0.0.1 +systemProp.socks.proxyPort=7890 + +systemProp.http.proxyHost=127.0.0.1 +systemProp.http.proxyPort=7890 + +systemProp.https.proxyHost=127.0.0.1 +systemProp.https.proxyPort=7890 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a..249e5832 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fae08049..26aca3b0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,3 +1,4 @@ +#Sat Jul 29 00:16:20 SGT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip diff --git a/gradlew b/gradlew index 535fb9f7..1b6c7873 100644 --- a/gradlew +++ b/gradlew @@ -86,7 +86,7 @@ APP_NAME="Gradle" APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx128m" "-Xms128m"' +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/libs/BetonQuest2.0.0-dev-668.jar b/libs/BetonQuest2.0.0-dev-668.jar deleted file mode 100644 index c8de2b85..00000000 Binary files a/libs/BetonQuest2.0.0-dev-668.jar and /dev/null differ diff --git a/libs/ClueScrolls-api.jar b/libs/ClueScrolls-api.jar deleted file mode 100644 index 38234c62..00000000 Binary files a/libs/ClueScrolls-api.jar and /dev/null differ diff --git a/libs/battle-pass-api.jar b/libs/battle-pass-api.jar deleted file mode 100644 index 608df8ca..00000000 Binary files a/libs/battle-pass-api.jar and /dev/null differ diff --git a/plugin/.gitignore b/plugin/.gitignore new file mode 100644 index 00000000..b63da455 --- /dev/null +++ b/plugin/.gitignore @@ -0,0 +1,42 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts new file mode 100644 index 00000000..871b2c18 --- /dev/null +++ b/plugin/build.gradle.kts @@ -0,0 +1,85 @@ +dependencies { + // server + compileOnly("dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT") + + // command + compileOnly("dev.jorel:commandapi-bukkit-core:9.1.0") + + // packet + compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0") + + // papi + compileOnly("me.clip:placeholderapi:2.11.3") + compileOnly("io.github.miniplaceholders:miniplaceholders-api:2.1.0") + + // config + compileOnly("dev.dejvokep:boosted-yaml:1.3.1") + + // mythic + compileOnly("io.lumine:Mythic-Dist:5.3.5") + compileOnly("net.Indyuce:MMOItems-API:6.9.2-SNAPSHOT") + compileOnly("io.lumine:MythicLib-dist:1.6-SNAPSHOT") + compileOnly("net.Indyuce:MMOCore-API:1.12-SNAPSHOT") + + // Gson + compileOnly("com.google.code.gson:gson:2.10.1") + + // eco + compileOnly("com.willfp:eco:6.65.4") + compileOnly("com.willfp:EcoJobs:3.29.1") + compileOnly("com.willfp:EcoSkills:3.17.1") + compileOnly("com.willfp:libreforge:4.29.1") + + // database + compileOnly("org.xerial:sqlite-jdbc:3.42.0.0") + compileOnly("com.h2database:h2:2.2.220") + compileOnly("org.mongodb:mongodb-driver-sync:4.10.2") + compileOnly("com.zaxxer:HikariCP:5.0.1") + compileOnly("redis.clients:jedis:4.4.3") + + // others + compileOnly("com.github.LoneDev6:api-itemsadder:3.5.0b") + compileOnly("com.github.oraxen:oraxen:1.159.0") + compileOnly("pers.neige.neigeitems:NeigeItems:1.15.9") + compileOnly("com.github.Zrips:Jobs:4.17.2") + compileOnly("com.github.Archy-X:AureliumSkills:Beta1.3.21") + + // local jars + compileOnly(files("libs/AdvancedEnchantments-api.jar")) + compileOnly(files("libs/RealisticSeasons-api.jar")) + compileOnly(files("libs/CustomCrops-api.jar")) + compileOnly(files("libs/mcMMO-api.jar")) + + // api module + implementation(project(":api")) + + // adventure + implementation("net.kyori:adventure-api:4.14.0") + implementation("net.kyori:adventure-platform-bukkit:4.3.0") + implementation("net.kyori:adventure-text-minimessage:4.14.0") + implementation("net.kyori:adventure-text-serializer-legacy:4.14.0") + + // nbt + implementation("de.tr7zw:item-nbt-api:2.11.3") + + // bStats + implementation("org.bstats:bstats-bukkit:3.0.1") + + // local lib + implementation(files("libs/BiomeAPI.jar")) + implementation(files("libs/ProtectionLib.jar")) + + // anvil + implementation("net.wesjd:anvilgui:1.7.0-SNAPSHOT") +} + +tasks { + shadowJar { + relocate ("de.tr7zw", "net.momirealms.customfishing.libraries") + relocate ("net.kyori", "net.momirealms.customfishing.libraries") + relocate ("net.wesjd", "net.momirealms.customfishing.libraries") + relocate ("org.bstats", "net.momirealms.customfishing.libraries.bstats") + relocate ("net.momirealms.biomeapi", "net.momirealms.customfishing.libraries.biomeapi") + relocate ("net.momirealms.protectionlib", "net.momirealms.customfishing.libraries.protectionlib") + } +} diff --git a/libs/AdvancedEnchantments-api.jar b/plugin/libs/AdvancedEnchantments-api.jar similarity index 100% rename from libs/AdvancedEnchantments-api.jar rename to plugin/libs/AdvancedEnchantments-api.jar diff --git a/libs/BiomeAPI.jar b/plugin/libs/BiomeAPI.jar similarity index 100% rename from libs/BiomeAPI.jar rename to plugin/libs/BiomeAPI.jar diff --git a/libs/CustomCrops-api-3.3.1.2.jar b/plugin/libs/CustomCrops-api.jar similarity index 100% rename from libs/CustomCrops-api-3.3.1.2.jar rename to plugin/libs/CustomCrops-api.jar diff --git a/libs/RealisticSeasons-api.jar b/plugin/libs/RealisticSeasons-api.jar similarity index 100% rename from libs/RealisticSeasons-api.jar rename to plugin/libs/RealisticSeasons-api.jar diff --git a/libs/mcMMO-api.jar b/plugin/libs/mcMMO-api.jar similarity index 100% rename from libs/mcMMO-api.jar rename to plugin/libs/mcMMO-api.jar diff --git a/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java b/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java new file mode 100644 index 00000000..5f8855b0 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java @@ -0,0 +1,211 @@ +package net.momirealms.customfishing; + +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion; +import de.tr7zw.changeme.nbtapi.utils.VersionChecker; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.api.util.ReflectionUtils; +import net.momirealms.customfishing.command.CommandManagerImpl; +import net.momirealms.customfishing.compatibility.IntegrationManagerImpl; +import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.libraries.libraryloader.LibraryLoader; +import net.momirealms.customfishing.mechanic.action.ActionManagerImpl; +import net.momirealms.customfishing.mechanic.bag.BagManagerImpl; +import net.momirealms.customfishing.mechanic.block.BlockManagerImpl; +import net.momirealms.customfishing.mechanic.competition.CompetitionManagerImpl; +import net.momirealms.customfishing.mechanic.effect.EffectManagerImpl; +import net.momirealms.customfishing.mechanic.fishing.FishingManagerImpl; +import net.momirealms.customfishing.mechanic.game.GameManagerImpl; +import net.momirealms.customfishing.mechanic.item.ItemManagerImpl; +import net.momirealms.customfishing.mechanic.loot.LootManagerImpl; +import net.momirealms.customfishing.mechanic.market.MarketManagerImpl; +import net.momirealms.customfishing.mechanic.mob.MobManagerImpl; +import net.momirealms.customfishing.mechanic.requirement.RequirementManagerImpl; +import net.momirealms.customfishing.scheduler.SchedulerImpl; +import net.momirealms.customfishing.setting.Config; +import net.momirealms.customfishing.setting.Locale; +import net.momirealms.customfishing.storage.StorageManagerImpl; +import net.momirealms.customfishing.version.VersionManagerImpl; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.TimeZone; + +public class CustomFishingPluginImpl extends CustomFishingPlugin { + + private static ProtocolManager protocolManager; + + public CustomFishingPluginImpl() { + super(); + } + + @Override + public void onLoad() { + this.loadDependencies(); + } + + @Override + public void onEnable() { + protocolManager = ProtocolLibrary.getProtocolManager(); + this.versionManager = new VersionManagerImpl(this); + this.disableNBTAPILogs(); + ReflectionUtils.load(); + + this.actionManager = new ActionManagerImpl(this); + this.adventure = new AdventureManagerImpl(this); + this.bagManager = new BagManagerImpl(this); + this.blockManager = new BlockManagerImpl(this); + this.commandManager = new CommandManagerImpl(this); + this.effectManager = new EffectManagerImpl(this); + this.fishingManager = new FishingManagerImpl(this); + this.gameManager = new GameManagerImpl(this); + this.integrationManager = new IntegrationManagerImpl(this); + this.itemManager = new ItemManagerImpl(this); + this.lootManager = new LootManagerImpl(this); + this.marketManager = new MarketManagerImpl(this); + this.mobManager = new MobManagerImpl(this); + this.placeholderManager = new PlaceholderManagerImpl(this); + this.requirementManager = new RequirementManagerImpl(this); + this.scheduler = new SchedulerImpl(this); + this.storageManager = new StorageManagerImpl(this); + this.competitionManager = new CompetitionManagerImpl(this); + this.reload(); + if (Config.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/customfishing.2723"); + }); + } + + @Override + public void onDisable() { + ((AdventureManagerImpl) this.adventure).close(); + ((BagManagerImpl) this.bagManager).disable(); + ((BlockManagerImpl) this.blockManager).disable(); + ((EffectManagerImpl) this.effectManager).disable(); + ((FishingManagerImpl) this.fishingManager).disable(); + ((GameManagerImpl) this.gameManager).disable(); + ((ItemManagerImpl) this.itemManager).disable(); + ((LootManagerImpl) this.lootManager).disable(); + ((MarketManagerImpl) this.marketManager).disable(); + ((MobManagerImpl) this.mobManager).disable(); + ((RequirementManagerImpl) this.requirementManager).disable(); + ((SchedulerImpl) this.scheduler).shutdown(); + ((IntegrationManagerImpl) this.integrationManager).disable(); + ((StorageManagerImpl) this.storageManager).disable(); + ((CompetitionManagerImpl) this.competitionManager).disable(); + ((PlaceholderManagerImpl) this.placeholderManager).disable(); + } + + @Override + public void reload() { + Config.load(); + Locale.load(); + ((SchedulerImpl) this.scheduler).reload(); + ((RequirementManagerImpl) this.requirementManager).unload(); + ((RequirementManagerImpl) this.requirementManager).load(); + ((ItemManagerImpl) this.itemManager).unload(); + ((ItemManagerImpl) this.itemManager).load(); + ((LootManagerImpl) this.lootManager).unload(); + ((LootManagerImpl) this.lootManager).load(); + ((FishingManagerImpl) this.fishingManager).unload(); + ((FishingManagerImpl) this.fishingManager).load(); + ((EffectManagerImpl) this.effectManager).unload(); + ((EffectManagerImpl) this.effectManager).load(); + ((MarketManagerImpl) this.marketManager).unload(); + ((MarketManagerImpl) this.marketManager).load(); + ((BagManagerImpl) this.bagManager).unload(); + ((BagManagerImpl) this.bagManager).load(); + ((BlockManagerImpl) this.blockManager).unload(); + ((BlockManagerImpl) this.blockManager).load(); + ((GameManagerImpl) this.gameManager).unload(); + ((GameManagerImpl) this.gameManager).load(); + ((MobManagerImpl) this.mobManager).unload(); + ((MobManagerImpl) this.mobManager).load(); + ((CompetitionManagerImpl) this.competitionManager).unload(); + ((CompetitionManagerImpl) this.competitionManager).load(); + ((StorageManagerImpl) this.storageManager).reload(); + this.commandManager.loadCommands(); + } + + private void loadDependencies() { + String libRepo = TimeZone.getDefault().getID().startsWith("Asia") ? + "https://maven.aliyun.com/repository/public/" : "https://repo.maven.apache.org/maven2/"; + LibraryLoader.loadDependencies( + "org.apache.commons:commons-pool2:2.11.1", libRepo, + "redis.clients:jedis:4.4.2", libRepo, + "dev.dejvokep:boosted-yaml:1.3.1", libRepo, + "com.zaxxer:HikariCP:5.0.1", libRepo, + "net.objecthunter:exp4j:0.4.8", libRepo, + "org.mariadb.jdbc:mariadb-java-client:3.1.4", libRepo, + "mysql:mysql-connector-java:8.0.30", libRepo, + "commons-io:commons-io:2.13.0", libRepo, + "com.google.code.gson:gson:2.10.1", libRepo, + "com.h2database:h2:2.2.220", libRepo, + "org.mongodb:mongodb-driver-sync:4.10.2", libRepo, + "org.xerial:sqlite-jdbc:3.42.0.0", libRepo, + "dev.jorel:commandapi-bukkit-shade:9.1.0", "https://repo.maven.apache.org/maven2/" + ); + } + + private void disableNBTAPILogs() { + MinecraftVersion.disableBStats(); + MinecraftVersion.disableUpdateCheck(); + VersionChecker.hideOk = true; + try { + Field field = MinecraftVersion.class.getDeclaredField("version"); + field.setAccessible(true); + MinecraftVersion minecraftVersion; + try { + minecraftVersion = MinecraftVersion.valueOf(getVersionManager().getServerVersion().replace("v", "MC")); + } catch (IllegalArgumentException ex) { + minecraftVersion = MinecraftVersion.UNKNOWN; + } + field.set(MinecraftVersion.class, minecraftVersion); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + boolean hasGsonSupport; + try { + Class.forName("com.google.gson.Gson"); + hasGsonSupport = true; + } catch (Exception ex) { + hasGsonSupport = false; + } + try { + Field field= MinecraftVersion.class.getDeclaredField("hasGsonSupport"); + field.setAccessible(true); + field.set(Boolean.class, hasGsonSupport); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @Override + public YamlConfiguration getConfig(String file) { + File config = new File(this.getDataFolder(), file); + if (!config.exists()) this.saveResource(file, false); + return YamlConfiguration.loadConfiguration(config); + } + + @Override + public boolean isHookedPluginEnabled(String plugin) { + return Bukkit.getPluginManager().isPluginEnabled(plugin); + } + + @NotNull + public static ProtocolManager getProtocolManager() { + return protocolManager; + } + + public void debug(String message) { + if (!Config.debug) return; + LogUtils.info(message); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/adventure/AdventureManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/adventure/AdventureManagerImpl.java new file mode 100644 index 00000000..1338b8a1 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/adventure/AdventureManagerImpl.java @@ -0,0 +1,204 @@ +package net.momirealms.customfishing.adventure; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.adventure.title.Title; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.AdventureManager; +import net.momirealms.customfishing.api.util.ReflectionUtils; +import net.momirealms.customfishing.setting.Locale; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +import java.lang.reflect.InvocationTargetException; +import java.time.Duration; + +public class AdventureManagerImpl implements AdventureManager { + + private final BukkitAudiences adventure; + private static AdventureManager instance; + + public AdventureManagerImpl(CustomFishingPlugin plugin) { + this.adventure = BukkitAudiences.create(plugin); + instance = this; + } + + public static AdventureManager getInstance() { + return instance; + } + + public void close() { + if (adventure != null) + adventure.close(); + } + + @Override + public Component getComponentFromMiniMessage(String text) { + return MiniMessage.miniMessage().deserialize(text); + } + + @Override + public void sendMessage(CommandSender sender, String s) { + if (s == null) return; + if (sender instanceof Player player) sendPlayerMessage(player, s); + else if (sender instanceof ConsoleCommandSender) sendConsoleMessage(s); + } + + @Override + public void sendMessageWithPrefix(CommandSender sender, String s) { + if (s == null) return; + if (sender instanceof Player player) sendPlayerMessage(player, Locale.MSG_Prefix + s); + else if (sender instanceof ConsoleCommandSender) sendConsoleMessage(Locale.MSG_Prefix + s); + } + + @Override + public void sendConsoleMessage(String s) { + if (s == null) return; + Audience au = adventure.sender(Bukkit.getConsoleSender()); + au.sendMessage(getComponentFromMiniMessage(s)); + } + + @Override + public void sendPlayerMessage(Player player, String s) { + if (s == null) return; + Audience au = adventure.player(player); + au.sendMessage(getComponentFromMiniMessage(s)); + } + + @Override + public void sendTitle(Player player, String title, String subtitle, int in, int duration, int out) { + Audience au = adventure.player(player); + Title.Times times = Title.Times.times(Duration.ofMillis(in), Duration.ofMillis(duration), Duration.ofMillis(out)); + au.showTitle(Title.title(getComponentFromMiniMessage(title), getComponentFromMiniMessage(subtitle), times)); + } + + @Override + public void sendTitle(Player player, Component title, Component subtitle, int in, int duration, int out) { + Audience au = adventure.player(player); + Title.Times times = Title.Times.times(Duration.ofMillis(in), Duration.ofMillis(duration), Duration.ofMillis(out)); + au.showTitle(Title.title(title, subtitle, times)); + } + + @Override + public void sendActionbar(Player player, String s) { + Audience au = adventure.player(player); + au.sendActionBar(getComponentFromMiniMessage(s)); + } + + @Override + public void sendSound(Player player, Sound.Source source, Key key, float volume, float pitch) { + Sound sound = Sound.sound(key, source, volume, pitch); + Audience au = adventure.player(player); + au.playSound(sound); + } + + @Override + public void sendSound(Player player, Sound sound) { + Audience au = adventure.player(player); + au.playSound(sound); + } + + @Override + public String legacyToMiniMessage(String legacy) { + StringBuilder stringBuilder = new StringBuilder(); + char[] chars = legacy.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (!isColorCode(chars[i])) { + stringBuilder.append(chars[i]); + continue; + } + if (i + 1 >= chars.length) { + stringBuilder.append(chars[i]); + continue; + } + switch (chars[i+1]) { + case '0' -> stringBuilder.append(""); + case '1' -> stringBuilder.append(""); + case '2' -> stringBuilder.append(""); + case '3' -> stringBuilder.append(""); + case '4' -> stringBuilder.append(""); + case '5' -> stringBuilder.append(""); + case '6' -> stringBuilder.append(""); + case '7' -> stringBuilder.append(""); + case '8' -> stringBuilder.append(""); + case '9' -> stringBuilder.append(""); + case 'a' -> stringBuilder.append(""); + case 'b' -> stringBuilder.append(""); + case 'c' -> stringBuilder.append(""); + case 'd' -> stringBuilder.append(""); + case 'e' -> stringBuilder.append(""); + case 'f' -> stringBuilder.append(""); + case 'r' -> stringBuilder.append(""); + case 'l' -> stringBuilder.append(""); + case 'm' -> stringBuilder.append(""); + case 'o' -> stringBuilder.append(""); + case 'n' -> stringBuilder.append(""); + case 'k' -> stringBuilder.append(""); + case 'x' -> { + if (i + 13 >= chars.length + || !isColorCode(chars[i+2]) + || !isColorCode(chars[i+4]) + || !isColorCode(chars[i+6]) + || !isColorCode(chars[i+8]) + || !isColorCode(chars[i+10]) + || !isColorCode(chars[i+12])) { + stringBuilder.append(chars[i]); + continue; + } + stringBuilder + .append("<#") + .append(chars[i+3]) + .append(chars[i+5]) + .append(chars[i+7]) + .append(chars[i+9]) + .append(chars[i+11]) + .append(chars[i+13]) + .append(">"); + i += 13; + } + default -> { + stringBuilder.append(chars[i]); + continue; + } + } + i++; + } + return stringBuilder.toString(); + } + + @Override + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean isColorCode(char c) { + return c == '§' || c == '&'; + } + + @Override + public String componentToLegacy(Component component) { + return LegacyComponentSerializer.legacySection().serialize(component); + } + + @Override + public String componentToJson(Component component) { + return GsonComponentSerializer.gson().serialize(component); + } + + @Override + public Object shadedComponentToPaperComponent(Component component) { + Object cp; + try { + cp = ReflectionUtils.gsonDeserializeMethod.invoke(ReflectionUtils.gsonInstance, GsonComponentSerializer.gson().serialize(component)); + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + return null; + } + return cp; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/command/CommandManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/command/CommandManagerImpl.java new file mode 100644 index 00000000..21c1ccd2 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/command/CommandManagerImpl.java @@ -0,0 +1,51 @@ +package net.momirealms.customfishing.command; + +import dev.jorel.commandapi.CommandAPI; +import dev.jorel.commandapi.CommandAPIBukkitConfig; +import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.CommandPermission; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.CommandManager; +import net.momirealms.customfishing.command.sub.CompetitionCommand; +import net.momirealms.customfishing.command.sub.FishingBagCommand; +import net.momirealms.customfishing.command.sub.ItemCommand; +import net.momirealms.customfishing.setting.Locale; + +public class CommandManagerImpl implements CommandManager { + + private final CustomFishingPlugin plugin; + + public CommandManagerImpl(CustomFishingPluginImpl plugin) { + this.plugin = plugin; + CommandAPI.onLoad(new CommandAPIBukkitConfig(plugin).silentLogs(true)); + } + + @Override + public void loadCommands() { + new CommandAPICommand("customfishing") + .withAliases("cfishing") + .withPermission(CommandPermission.OP) + .withSubcommands( + getReloadCommand(), + CompetitionCommand.INSTANCE.getCompetitionCommand(), + ItemCommand.INSTANCE.getItemCommand() + ) + .register(); + + if (CustomFishingPlugin.get().getBagManager().isBagEnabled()) { + FishingBagCommand.INSTANCE.getBagCommand().register(); + } + } + + private CommandAPICommand getReloadCommand() { + return new CommandAPICommand("reload") + .withPermission("customfishing.command.reload") + .executes((sender, args) -> { + long time = System.currentTimeMillis(); + CustomFishingPlugin.get().reload(); + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_Reload.replace("{time}", String.valueOf(System.currentTimeMillis()-time))); + }); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/command/sub/CompetitionCommand.java b/plugin/src/main/java/net/momirealms/customfishing/command/sub/CompetitionCommand.java new file mode 100644 index 00000000..77907ab9 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/command/sub/CompetitionCommand.java @@ -0,0 +1,90 @@ +package net.momirealms.customfishing.command.sub; + +import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.ArgumentSuggestions; +import dev.jorel.commandapi.arguments.StringArgument; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; +import net.momirealms.customfishing.setting.Config; +import net.momirealms.customfishing.setting.Locale; +import net.momirealms.customfishing.storage.method.database.nosql.RedisManager; + +import java.util.Set; + +public class CompetitionCommand { + + public static CompetitionCommand INSTANCE = new CompetitionCommand(); + + public CommandAPICommand getCompetitionCommand() { + return new CommandAPICommand("competition") + .withPermission("customfishing.command.competition") + .withSubcommands( + getCompetitionStartCommand(), + getCompetitionEndCommand(), + getCompetitionStopCommand() + ); + } + + private CommandAPICommand getCompetitionStartCommand() { + Set allCompetitions = CustomFishingPlugin.get().getCompetitionManager().getAllCompetitions(); + var command = new CommandAPICommand("start") + .withArguments( + new StringArgument("id") + .replaceSuggestions( + ArgumentSuggestions.strings(allCompetitions) + ) + ); + if (Config.redisRanking) command.withOptionalArguments(new StringArgument("-allservers")); + command.executes((sender, args) -> { + String id = (String) args.get(0); + if (!allCompetitions.contains(id)) { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_Competition_Not_Exist.replace("{id}", id)); + return; + } + boolean allServer = args.getOrDefault(1, "").equals("-allservers"); + CustomFishingPlugin.get().getCompetitionManager().startCompetition(id, true, allServer); + }); + return command; + } + + private CommandAPICommand getCompetitionEndCommand() { + var command = new CommandAPICommand("end"); + if (Config.redisRanking) command.withOptionalArguments(new StringArgument("-allservers")); + command.executes((sender, args) -> { + boolean allServer = args.getOrDefault(1, "").equals("-allservers"); + if (allServer) { + RedisManager.getInstance().sendRedisMessage("cf_competition", "end"); + } else { + FishingCompetition competition = CustomFishingPlugin.get().getCompetitionManager().getOnGoingCompetition(); + if (competition != null) { + competition.end(); + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_End_Competition); + } else { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_No_Competition_Ongoing); + } + } + }); + return command; + } + + private CommandAPICommand getCompetitionStopCommand() { + var command = new CommandAPICommand("stop"); + if (Config.redisRanking) command.withOptionalArguments(new StringArgument("-allservers")); + command.executes((sender, args) -> { + boolean allServer = args.getOrDefault(1, "").equals("-allservers"); + if (allServer) { + RedisManager.getInstance().sendRedisMessage("cf_competition", "stop"); + } else { + FishingCompetition competition = CustomFishingPlugin.get().getCompetitionManager().getOnGoingCompetition(); + if (competition != null) { + competition.stop(); + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_Stop_Competition); + } else { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_No_Competition_Ongoing); + } + } + }); + return command; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/command/sub/FishingBagCommand.java b/plugin/src/main/java/net/momirealms/customfishing/command/sub/FishingBagCommand.java new file mode 100644 index 00000000..a7821fc7 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/command/sub/FishingBagCommand.java @@ -0,0 +1,55 @@ +package net.momirealms.customfishing.command.sub; + +import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.OfflinePlayerArgument; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.user.OfflineUser; +import net.momirealms.customfishing.setting.Locale; +import net.momirealms.customfishing.storage.user.OfflineUserImpl; +import org.bukkit.OfflinePlayer; +import org.bukkit.inventory.Inventory; + +import java.util.UUID; + +public class FishingBagCommand { + + public static FishingBagCommand INSTANCE = new FishingBagCommand(); + + public CommandAPICommand getBagCommand() { + return new CommandAPICommand("fishingbag") + .withPermission("fishingbag.user") + .withSubcommand(getAdminCommand()) + .executesPlayer(((player, args) -> { + var inv = CustomFishingPlugin.get().getBagManager().getOnlineBagInventory(player.getUniqueId()); + if (inv != null) player.openInventory(inv); + })); + } + + private CommandAPICommand getAdminCommand() { + return new CommandAPICommand("edit") + .withPermission("fishingbag.admin") + .withArguments(new OfflinePlayerArgument("player")) + .executesPlayer(((player, args) -> { + OfflinePlayer offlinePlayer = (OfflinePlayer) args.get("player"); + UUID uuid = offlinePlayer.getUniqueId(); + Inventory onlineInv = CustomFishingPlugin.get().getBagManager().getOnlineBagInventory(uuid); + if (onlineInv != null) { + player.openInventory(onlineInv); + } else { + CustomFishingPlugin.get().getStorageManager().getOfflineUser(uuid, false).thenAccept(optional -> { + if (optional.isEmpty()) { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, Locale.MSG_Unsafe_Modification); + } else { + OfflineUser offlineUser = optional.get(); + if (offlineUser == OfflineUserImpl.NEVER_PLAYED_USER) { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, Locale.MSG_Never_Played); + } else { + + } + } + }); + } + })); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/command/sub/ItemCommand.java b/plugin/src/main/java/net/momirealms/customfishing/command/sub/ItemCommand.java new file mode 100644 index 00000000..ccafddae --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/command/sub/ItemCommand.java @@ -0,0 +1,150 @@ +package net.momirealms.customfishing.command.sub; + +import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.ArgumentSuggestions; +import dev.jorel.commandapi.arguments.EntitySelectorArgument; +import dev.jorel.commandapi.arguments.IntegerArgument; +import dev.jorel.commandapi.arguments.TextArgument; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Key; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.setting.Locale; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; + +import java.util.Collection; + +public class ItemCommand { + + public static ItemCommand INSTANCE = new ItemCommand(); + + public CommandAPICommand getItemCommand() { + return new CommandAPICommand("items") + .withPermission("customfishing.command.items") + .withSubcommands( + getSubCommand("loot"), + getSubCommand("util"), + getSubCommand("bait"), + getSubCommand("rod") + ); + } + + private CommandAPICommand getSubCommand(String namespace) { + Collection items = CustomFishingPlugin.get() + .getItemManager() + .getAllItemsKey() + .stream() + .filter(it -> it.namespace().equals(namespace)) + .map(Key::value) + .toList(); + return new CommandAPICommand(namespace) + .withSubcommands( + getCommand(namespace, items), + giveCommand(namespace, items) + ); + } + + private CommandAPICommand getCommand(String namespace, Collection items) { + return new CommandAPICommand("get") + .withArguments(new TextArgument("id").replaceSuggestions(ArgumentSuggestions.strings(items))) + .withOptionalArguments(new IntegerArgument("amount", 1)) + .executesPlayer((player, args) -> { + String id = (String) args.get("id"); + int amount = (int) args.getOrDefault("amount", 1); + ItemStack item = CustomFishingPlugin.get().getItemManager().build(player, namespace, id); + if (item != null) { + int actual = giveCertainAmountOfItem(player, item, amount); + AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, Locale.MSG_Get_Item.replace("{item}", id).replace("{amount}", String.valueOf(actual))); + } else { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, Locale.MSG_Item_Not_Exists); + } + }); + } + + private CommandAPICommand giveCommand(String namespace, Collection items) { + return new CommandAPICommand("give") + .withArguments(new EntitySelectorArgument.ManyPlayers("player")) + .withArguments(new TextArgument("id").replaceSuggestions(ArgumentSuggestions.strings(items))) + .withOptionalArguments(new IntegerArgument("amount", 1)) + .executes((sender, args) -> { + Collection players = (Collection) args.get("player"); + String id = (String) args.get("id"); + int amount = (int) args.getOrDefault("amount", 1); + ItemStack item = CustomFishingPlugin.get().getItemManager().build(players.stream().findAny().get(), namespace, id); + if (item != null) { + for (Player player : players) { + int actual = giveCertainAmountOfItem(player, item, amount); + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_Give_Item.replace("{item}", id).replace("{amount}", String.valueOf(actual)).replace("{player}", player.getName())); + } + } else { + AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_Item_Not_Exists); + } + }); + } + + private int giveCertainAmountOfItem(Player player, ItemStack itemStack, int amount) { + PlayerInventory inventory = player.getInventory(); + String metaStr = itemStack.getItemMeta().getAsString(); + int maxStackSize = itemStack.getMaxStackSize(); + + if (amount > maxStackSize * 100) { + LogUtils.warn("Detected too many items spawning. Lowering the amount to " + (maxStackSize * 100)); + amount = maxStackSize * 100; + } + + int actualAmount = amount; + + for (ItemStack other : inventory.getStorageContents()) { + if (other != null) { + if (other.getType() == itemStack.getType() && other.getItemMeta().getAsString().equals(metaStr)) { + if (other.getAmount() < maxStackSize) { + int delta = maxStackSize - other.getAmount(); + if (amount > delta) { + other.setAmount(maxStackSize); + amount -= delta; + } else { + other.setAmount(amount + other.getAmount()); + return actualAmount; + } + } + } + } + } + + if (amount > 0) { + for (ItemStack other : inventory.getStorageContents()) { + if (other == null) { + if (amount > maxStackSize) { + amount -= maxStackSize; + ItemStack cloned = itemStack.clone(); + cloned.setAmount(maxStackSize); + inventory.addItem(cloned); + } else { + ItemStack cloned = itemStack.clone(); + cloned.setAmount(amount); + inventory.addItem(cloned); + return actualAmount; + } + } + } + } + + if (amount > 0) { + for (int i = 0; i < amount / maxStackSize; i++) { + ItemStack cloned = itemStack.clone(); + cloned.setAmount(maxStackSize); + player.getWorld().dropItem(player.getLocation(), cloned); + } + int left = amount % maxStackSize; + if (left != 0) { + ItemStack cloned = itemStack.clone(); + cloned.setAmount(left); + player.getWorld().dropItem(player.getLocation(), cloned); + } + } + + return actualAmount; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java new file mode 100644 index 00000000..06e330fc --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java @@ -0,0 +1,160 @@ +package net.momirealms.customfishing.compatibility; + +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.integration.EnchantmentInterface; +import net.momirealms.customfishing.api.integration.LevelInterface; +import net.momirealms.customfishing.api.integration.SeasonInterface; +import net.momirealms.customfishing.api.manager.IntegrationManager; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.enchant.AdvancedEnchantmentsImpl; +import net.momirealms.customfishing.compatibility.enchant.VanillaEnchantmentsImpl; +import net.momirealms.customfishing.compatibility.item.*; +import net.momirealms.customfishing.compatibility.level.*; +import net.momirealms.customfishing.compatibility.season.CustomCropsSeasonImpl; +import net.momirealms.customfishing.compatibility.season.RealisticSeasonsImpl; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class IntegrationManagerImpl implements IntegrationManager { + + private final CustomFishingPlugin plugin; + private final HashMap levelPluginMap; + private final HashMap enchantments; + private SeasonInterface seasonInterface; + + public IntegrationManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.levelPluginMap = new HashMap<>(); + this.enchantments = new HashMap<>(); + this.init(); + } + + public void disable() { + this.enchantments.clear(); + this.levelPluginMap.clear(); + } + + public void init() { + if (plugin.isHookedPluginEnabled("ItemsAdder")) { + plugin.getItemManager().registerItemLibrary(new ItemsAdderItemImpl()); + hookMessage("ItemsAdder"); + } + if (plugin.isHookedPluginEnabled("MMOItems")) { + plugin.getItemManager().registerItemLibrary(new MMOItemsItemImpl()); + hookMessage("MMOItems"); + } + if (plugin.isHookedPluginEnabled("Oraxen")) { + plugin.getItemManager().registerItemLibrary(new OraxenItemImpl()); + hookMessage("Oraxen"); + } + if (plugin.isHookedPluginEnabled("NeigeItems")) { + plugin.getItemManager().registerItemLibrary(new NeigeItemsItemImpl()); + hookMessage("NeigeItems"); + } + if (plugin.isHookedPluginEnabled("MythicMobs")) { + plugin.getItemManager().registerItemLibrary(new MythicMobsItemImpl()); + hookMessage("MythicMobs"); + } + if (plugin.isHookedPluginEnabled("EcoJobs")) { + registerLevelPlugin("EcoJobs", new EcoJobsImpl()); + hookMessage("EcoJobs"); + } + if (plugin.isHookedPluginEnabled("EcoSkills")) { + registerLevelPlugin("EcoSkills", new EcoSkillsImpl()); + hookMessage("EcoSkills"); + } + if (plugin.isHookedPluginEnabled("Jobs")) { + registerLevelPlugin("JobsReborn", new JobsRebornImpl()); + hookMessage("Jobs"); + } + if (plugin.isHookedPluginEnabled("MMOCore")) { + registerLevelPlugin("MMOCore", new MMOCoreImpl()); + hookMessage("MMOCore"); + } + if (plugin.isHookedPluginEnabled("mcMMO")) { + try { + plugin.getItemManager().registerCustomItem("loot", "mcmmo", new McMMOBuildableItem()); + } catch (ClassNotFoundException | NoSuchMethodException e) { + LogUtils.warn("Failed to initialize mcMMO Treasure"); + } + registerLevelPlugin("mcMMO", new McMMOImpl()); + hookMessage("mcMMO"); + } + if (plugin.isHookedPluginEnabled("AureliumSkills")) { + registerLevelPlugin("AureliumSkills", new AureliumSkillsImpl()); + hookMessage("AureliumSkills"); + } + if (plugin.isHookedPluginEnabled("EcoEnchants")) { + this.enchantments.put("EcoEnchants", new VanillaEnchantmentsImpl()); + hookMessage("EcoEnchants"); + } else { + this.enchantments.put("vanilla", new VanillaEnchantmentsImpl()); + } + if (plugin.isHookedPluginEnabled("AdvancedEnchantments")) { + this.enchantments.put("AdvancedEnchantments", new AdvancedEnchantmentsImpl()); + hookMessage("AdvancedEnchantments"); + } + if (plugin.isHookedPluginEnabled("RealisticSeasons")) { + this.seasonInterface = new RealisticSeasonsImpl(); + } else if (plugin.isHookedPluginEnabled("CustomCrops")) { + this.seasonInterface = new CustomCropsSeasonImpl(); + } + } + + @Override + public boolean registerLevelPlugin(String plugin, LevelInterface level) { + if (levelPluginMap.containsKey(plugin)) return false; + levelPluginMap.put(plugin, level); + return true; + } + + @Override + public boolean unregisterLevelPlugin(String plugin) { + return levelPluginMap.remove(plugin) != null; + } + + @Override + public boolean registerEnchantment(String plugin, EnchantmentInterface enchantment) { + if (enchantments.containsKey(plugin)) return false; + enchantments.put(plugin, enchantment); + return true; + } + + @Override + public boolean unregisterEnchantment(String plugin) { + return enchantments.remove(plugin) != null; + } + + private void hookMessage(String plugin) { + AdventureManagerImpl.getInstance().sendConsoleMessage("[CustomFishing] " + plugin + " hooked!"); + } + + @Override + public LevelInterface getLevelHook(String plugin) { + return levelPluginMap.get(plugin); + } + + @Override + public List getEnchantments(ItemStack itemStack) { + ArrayList list = new ArrayList<>(); + for (EnchantmentInterface enchantmentInterface : enchantments.values()) { + list.addAll(enchantmentInterface.getEnchants(itemStack)); + } + return list; + } + + @Nullable + public SeasonInterface getSeasonInterface() { + return seasonInterface; + } + + @Override + public void setSeasonInterface(SeasonInterface season) { + this.seasonInterface = season; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/ItemsAdderBlockImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/ItemsAdderBlockImpl.java new file mode 100644 index 00000000..04e42fa1 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/ItemsAdderBlockImpl.java @@ -0,0 +1,27 @@ +package net.momirealms.customfishing.compatibility.block; + +import dev.lone.itemsadder.api.CustomBlock; +import net.momirealms.customfishing.api.mechanic.block.BlockDataModifier; +import net.momirealms.customfishing.api.mechanic.block.BlockLibrary; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.List; + +public class ItemsAdderBlockImpl implements BlockLibrary { + + @Override + public String identification() { + return "ItemsAdder"; + } + + @Override + public BlockData getBlockData(Player player, String id, List modifiers) { + BlockData blockData = CustomBlock.getBaseBlockData(id); + for (BlockDataModifier modifier : modifiers) { + modifier.apply(player, blockData); + } + return blockData; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/VanillaBlockImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/VanillaBlockImpl.java new file mode 100644 index 00000000..a0088469 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/VanillaBlockImpl.java @@ -0,0 +1,29 @@ +package net.momirealms.customfishing.compatibility.block; + +import net.momirealms.customfishing.api.mechanic.block.BlockDataModifier; +import net.momirealms.customfishing.api.mechanic.block.BlockLibrary; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class VanillaBlockImpl implements BlockLibrary { + + @Override + public String identification() { + return "vanilla"; + } + + @Override + public BlockData getBlockData(Player player, String id, List modifiers) { + BlockData blockData = Material.valueOf(id.toUpperCase(Locale.ENGLISH)).createBlockData(); + for (BlockDataModifier modifier : modifiers) { + modifier.apply(player, blockData); + } + return blockData; + } +} diff --git a/src/main/java/net/momirealms/customfishing/integration/enchantment/AEImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/enchant/AdvancedEnchantmentsImpl.java similarity index 70% rename from src/main/java/net/momirealms/customfishing/integration/enchantment/AEImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/enchant/AdvancedEnchantmentsImpl.java index f1f0f083..fd5cd1cc 100644 --- a/src/main/java/net/momirealms/customfishing/integration/enchantment/AEImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/enchant/AdvancedEnchantmentsImpl.java @@ -15,18 +15,17 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.enchantment; +package net.momirealms.customfishing.compatibility.enchant; import net.advancedplugins.ae.api.AEAPI; -import net.momirealms.customfishing.integration.EnchantmentInterface; -import org.bukkit.enchantments.Enchantment; +import net.momirealms.customfishing.api.integration.EnchantmentInterface; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.List; import java.util.Map; -public class AEImpl implements EnchantmentInterface { +public class AdvancedEnchantmentsImpl implements EnchantmentInterface { @Override public List getEnchants(ItemStack itemStack) { @@ -34,11 +33,6 @@ public class AEImpl implements EnchantmentInterface { for (Map.Entry entry : AEAPI.getEnchantmentsOnItem(itemStack).entrySet()) { enchants.add("AE:" + entry.getKey() + ":" + entry.getValue()); } - Map enchantments = itemStack.getEnchantments(); - for (Map.Entry en : enchantments.entrySet()) { - String key = en.getKey().getKey() + ":" + en.getValue(); - enchants.add(key); - } return enchants; } } diff --git a/src/main/java/net/momirealms/customfishing/integration/enchantment/VanillaImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/enchant/VanillaEnchantmentsImpl.java similarity index 81% rename from src/main/java/net/momirealms/customfishing/integration/enchantment/VanillaImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/enchant/VanillaEnchantmentsImpl.java index dea92edc..55ad72c8 100644 --- a/src/main/java/net/momirealms/customfishing/integration/enchantment/VanillaImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/enchant/VanillaEnchantmentsImpl.java @@ -15,9 +15,9 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.enchantment; +package net.momirealms.customfishing.compatibility.enchant; -import net.momirealms.customfishing.integration.EnchantmentInterface; +import net.momirealms.customfishing.api.integration.EnchantmentInterface; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; @@ -25,12 +25,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -public class VanillaImpl implements EnchantmentInterface { +public class VanillaEnchantmentsImpl implements EnchantmentInterface { @Override public List getEnchants(ItemStack itemStack) { Map enchantments = itemStack.getEnchantments(); - List enchants = new ArrayList<>(); + List enchants = new ArrayList<>(enchantments.size()); for (Map.Entry en : enchantments.entrySet()) { String key = en.getKey().getKey() + ":" + en.getValue(); enchants.add(key); diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/CustomFishingItemImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/CustomFishingItemImpl.java new file mode 100644 index 00000000..fdfb2ea3 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/CustomFishingItemImpl.java @@ -0,0 +1,42 @@ +/* + * 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.compatibility.item; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class CustomFishingItemImpl implements ItemLibrary { + + @Override + public String identification() { + return "CustomFishing"; + } + + @Override + public ItemStack buildItem(Player player, String id) { + String[] split = id.split(":", 2); + return CustomFishingPlugin.get().getItemManager().build(player, split[0], split[1]); + } + + @Override + public String getItemID(ItemStack itemStack) { + return CustomFishingPlugin.get().getItemManager().getItemID(itemStack); + } +} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/PotionEffectImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/ItemsAdderItemImpl.java similarity index 52% rename from src/main/java/net/momirealms/customfishing/fishing/action/PotionEffectImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/item/ItemsAdderItemImpl.java index 61144a8d..07f5ac71 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/action/PotionEffectImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/ItemsAdderItemImpl.java @@ -15,25 +15,29 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing.action; +package net.momirealms.customfishing.compatibility.item; -import net.momirealms.customfishing.fishing.FishMeta; +import dev.lone.itemsadder.api.CustomStack; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.jetbrains.annotations.Nullable; +import org.bukkit.inventory.ItemStack; -public class PotionEffectImpl extends AbstractAction implements Action { +public class ItemsAdderItemImpl implements ItemLibrary { - private final PotionEffect potionEffect; - - public PotionEffectImpl(PotionEffect potionEffect, double chance) { - super(chance); - this.potionEffect = potionEffect; + @Override + public String identification() { + return "ItemsAdder"; } @Override - public void doOn(Player player, @Nullable Player anotherPlayer, @Nullable FishMeta fishMeta) { - if (!canExecute()) return; - player.addPotionEffect(potionEffect); + public ItemStack buildItem(Player player, String id) { + return CustomStack.getInstance(id).getItemStack(); + } + + @Override + public String getItemID(ItemStack itemStack) { + CustomStack customStack = CustomStack.byItemStack(itemStack); + if (customStack == null) return null; + return customStack.getNamespacedID(); } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/MMOItemsItemImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/MMOItemsItemImpl.java new file mode 100644 index 00000000..1cf8409a --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/MMOItemsItemImpl.java @@ -0,0 +1,51 @@ +/* + * 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.compatibility.item; + +import de.tr7zw.changeme.nbtapi.NBTItem; +import net.Indyuce.mmoitems.MMOItems; +import net.Indyuce.mmoitems.api.Type; +import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Locale; + +public class MMOItemsItemImpl implements ItemLibrary { + + @Override + public String identification() { + return "MMOItems"; + } + + @Override + public ItemStack buildItem(Player player, String id) { + String[] split = id.split(":"); + MMOItem mmoItem = MMOItems.plugin.getMMOItem(Type.get(split[0]), split[1].toUpperCase(Locale.ENGLISH)); + return mmoItem == null ? new ItemStack(Material.AIR) : mmoItem.newBuilder().build(); + } + + @Override + public String getItemID(ItemStack itemStack) { + NBTItem nbtItem = new NBTItem(itemStack); + if (!nbtItem.hasTag("MMOITEMS_ITEM_ID")) return null; + return nbtItem.getString("MMOITEMS_ITEM_ID"); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/McMMOBuildableItem.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/McMMOBuildableItem.java new file mode 100644 index 00000000..a4ccdfc7 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/McMMOBuildableItem.java @@ -0,0 +1,51 @@ +package net.momirealms.customfishing.compatibility.item; + +import net.momirealms.customfishing.api.mechanic.item.BuildableItem; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + +public class McMMOBuildableItem implements BuildableItem { + + private final Method getMcMMOPlayerMethod; + private final Method getFishingManagerMethod; + private final Method getFishingTreasureMethod; + private final Method getItemStackMethod; + + public McMMOBuildableItem() throws ClassNotFoundException, NoSuchMethodException { + Class userClass = Class.forName("com.gmail.nossr50.util.player.UserManager"); + getMcMMOPlayerMethod = userClass.getMethod("getPlayer", Player.class); + Class mcMMOPlayerClass = Class.forName("com.gmail.nossr50.datatypes.player.McMMOPlayer"); + getFishingManagerMethod = mcMMOPlayerClass.getMethod("getFishingManager"); + Class fishingManagerClass = Class.forName("com.gmail.nossr50.skills.fishing.FishingManager"); + getFishingTreasureMethod = fishingManagerClass.getDeclaredMethod("getFishingTreasure"); + Class treasureClass = Class.forName("com.gmail.nossr50.datatypes.treasure.Treasure"); + getItemStackMethod = treasureClass.getMethod("getDrop"); + } + + @Override + public ItemStack build(Player player, Map placeholders) { + ItemStack itemStack = null; + while (itemStack == null) { + try { + Object mcMMOPlayer = getMcMMOPlayerMethod.invoke(null, player); + Object fishingManager = getFishingManagerMethod.invoke(mcMMOPlayer); + Object treasure = getFishingTreasureMethod.invoke(fishingManager); + if (treasure != null) { + itemStack = (ItemStack) getItemStackMethod.invoke(treasure); + } + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + return itemStack; + } + + @Override + public boolean persist() { + return true; + } +} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/MythicMobsItemImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/MythicMobsItemImpl.java similarity index 67% rename from src/main/java/net/momirealms/customfishing/integration/item/MythicMobsItemImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/item/MythicMobsItemImpl.java index ef887b61..28a45b51 100644 --- a/src/main/java/net/momirealms/customfishing/integration/item/MythicMobsItemImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/MythicMobsItemImpl.java @@ -15,16 +15,15 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.item; +package net.momirealms.customfishing.compatibility.item; import de.tr7zw.changeme.nbtapi.NBTItem; import io.lumine.mythic.bukkit.MythicBukkit; -import net.momirealms.customfishing.integration.ItemInterface; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; -public class MythicMobsItemImpl implements ItemInterface { +public class MythicMobsItemImpl implements ItemLibrary { private MythicBukkit mythicBukkit; @@ -33,24 +32,21 @@ public class MythicMobsItemImpl implements ItemInterface { } @Override - @Nullable - public ItemStack build(String material, Player player) { - if (!material.startsWith("MythicMobs:")) return null; - material = material.substring(11); + public String identification() { + return "MythicMobs"; + } + + @Override + public ItemStack buildItem(Player player, String id) { if (mythicBukkit == null || mythicBukkit.isClosed()) { this.mythicBukkit = MythicBukkit.inst(); } - return mythicBukkit.getItemManager().getItemStack(material); + return mythicBukkit.getItemManager().getItemStack(id); } @Override - public boolean loseCustomDurability(ItemStack itemStack, Player player) { - return false; - } - - @Override - public @Nullable String getID(ItemStack itemStack) { + public String getItemID(ItemStack itemStack) { NBTItem nbtItem = new NBTItem(itemStack); return nbtItem.hasTag("MYTHIC_TYPE") ? nbtItem.getString("MYTHIC_TYPE") : null; } -} +} \ No newline at end of file diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/NeigeItemsItemImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/NeigeItemsItemImpl.java new file mode 100644 index 00000000..43047613 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/NeigeItemsItemImpl.java @@ -0,0 +1,47 @@ +/* + * 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.compatibility.item; + +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.neige.neigeitems.item.ItemInfo; +import pers.neige.neigeitems.manager.ItemManager; +import pers.neige.neigeitems.utils.ItemUtils; + +public class NeigeItemsItemImpl implements ItemLibrary { + + @Override + public String identification() { + return "NeigeItems"; + } + + @Override + public ItemStack buildItem(Player player, String id) { + return ItemManager.INSTANCE.getItemStack(id, player); + } + + @Override + public String getItemID(ItemStack itemStack) { + ItemInfo itemInfo = ItemUtils.isNiItem(itemStack); + if (itemInfo != null) { + return itemInfo.getId(); + } + return null; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/OraxenItemImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/OraxenItemImpl.java new file mode 100644 index 00000000..85dd40b5 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/OraxenItemImpl.java @@ -0,0 +1,44 @@ +/* + * 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.compatibility.item; + +import io.th0rgal.oraxen.api.OraxenItems; +import io.th0rgal.oraxen.items.ItemBuilder; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class OraxenItemImpl implements ItemLibrary { + + @Override + public String identification() { + return "Oraxen"; + } + + @Override + public ItemStack buildItem(Player player, String id) { + ItemBuilder itemBuilder = OraxenItems.getItemById(id); + return itemBuilder == null ? new ItemStack(Material.AIR) : itemBuilder.build(); + } + + @Override + public String getItemID(ItemStack itemStack) { + return OraxenItems.getIdByItem(itemStack); + } +} diff --git a/src/main/java/net/momirealms/customfishing/integration/ItemInterface.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/VanillaItemImpl.java similarity index 56% rename from src/main/java/net/momirealms/customfishing/integration/ItemInterface.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/item/VanillaItemImpl.java index c72e7cd7..d502b47a 100644 --- a/src/main/java/net/momirealms/customfishing/integration/ItemInterface.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/item/VanillaItemImpl.java @@ -15,19 +15,29 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration; +package net.momirealms.customfishing.compatibility.item; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; -public interface ItemInterface { +import java.util.Locale; - @Nullable - ItemStack build(String id, Player player); +public class VanillaItemImpl implements ItemLibrary { - boolean loseCustomDurability(ItemStack itemStack, Player player); + @Override + public String identification() { + return "vanilla"; + } - @Nullable - String getID(ItemStack itemStack); + @Override + public ItemStack buildItem(Player player, String id) { + return new ItemStack(Material.valueOf(id.toUpperCase(Locale.ENGLISH))); + } + + @Override + public String getItemID(ItemStack itemStack) { + return itemStack.getType().name(); + } } diff --git a/src/main/java/net/momirealms/customfishing/integration/skill/AureliumsImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/AureliumSkillsImpl.java similarity index 63% rename from src/main/java/net/momirealms/customfishing/integration/skill/AureliumsImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/level/AureliumSkillsImpl.java index 8a8adc28..cb25cee6 100644 --- a/src/main/java/net/momirealms/customfishing/integration/skill/AureliumsImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/AureliumSkillsImpl.java @@ -15,31 +15,28 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.skill; +package net.momirealms.customfishing.compatibility.level; import com.archyx.aureliumskills.api.AureliumAPI; import com.archyx.aureliumskills.leveler.Leveler; -import com.archyx.aureliumskills.skills.Skill; -import net.momirealms.customfishing.integration.SkillInterface; +import net.momirealms.customfishing.api.integration.LevelInterface; import org.bukkit.entity.Player; -public class AureliumsImpl implements SkillInterface { +public class AureliumSkillsImpl implements LevelInterface { private final Leveler leveler; - private final Skill skill; - public AureliumsImpl() { + public AureliumSkillsImpl() { leveler = AureliumAPI.getPlugin().getLeveler(); - skill = AureliumAPI.getPlugin().getSkillRegistry().getSkill("fishing"); } @Override - public void addXp(Player player, double amount) { - leveler.addXp(player, skill, amount); + public void addXp(Player player, String target, double amount) { + leveler.addXp(player, AureliumAPI.getPlugin().getSkillRegistry().getSkill(target), amount); } @Override - public int getLevel(Player player) { - return AureliumAPI.getSkillLevel(player, skill); + public int getLevel(Player player, String target) { + return AureliumAPI.getSkillLevel(player, AureliumAPI.getPlugin().getSkillRegistry().getSkill(target)); } } diff --git a/src/main/java/net/momirealms/customfishing/integration/job/EcoJobsImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/EcoJobsImpl.java similarity index 64% rename from src/main/java/net/momirealms/customfishing/integration/job/EcoJobsImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/level/EcoJobsImpl.java index 4df32605..fb0f8308 100644 --- a/src/main/java/net/momirealms/customfishing/integration/job/EcoJobsImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/EcoJobsImpl.java @@ -15,30 +15,29 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.job; +package net.momirealms.customfishing.compatibility.level; import com.willfp.ecojobs.api.EcoJobsAPI; import com.willfp.ecojobs.jobs.Job; -import net.momirealms.customfishing.integration.JobInterface; +import com.willfp.ecojobs.jobs.Jobs; +import net.momirealms.customfishing.api.integration.LevelInterface; import org.bukkit.entity.Player; -public class EcoJobsImpl implements JobInterface { +public class EcoJobsImpl implements LevelInterface { @Override - public void addXp(Player player, double amount) { + public void addXp(Player player, String target, double amount) { for (Job job : EcoJobsAPI.getActiveJobs(player)) { - if (job.getId().equals("fisherman")) { + if (job.getId().equals(target)) { EcoJobsAPI.giveJobExperience(player, job, amount); } } } @Override - public int getLevel(Player player) { -// Job job = Jobs.getByID("fisherman"); -// if (job == null) return 0; -// return EcoJobsAPI.getJobLevel(player, job); - //TODO com.willfp.libreforge.loader.configs.ConfigCategory - return 0; + public int getLevel(Player player, String target) { + Job job = Jobs.getByID(target); + if (job == null) return 0; + return EcoJobsAPI.getJobLevel(player, job); } } diff --git a/src/main/java/net/momirealms/customfishing/integration/skill/EcoSkillsImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/EcoSkillsImpl.java similarity index 60% rename from src/main/java/net/momirealms/customfishing/integration/skill/EcoSkillsImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/level/EcoSkillsImpl.java index fc9698d9..e74c3bc3 100644 --- a/src/main/java/net/momirealms/customfishing/integration/skill/EcoSkillsImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/EcoSkillsImpl.java @@ -15,22 +15,24 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.skill; +package net.momirealms.customfishing.compatibility.level; import com.willfp.ecoskills.api.EcoSkillsAPI; import com.willfp.ecoskills.skills.Skills; -import net.momirealms.customfishing.integration.SkillInterface; +import net.momirealms.customfishing.api.integration.LevelInterface; import org.bukkit.entity.Player; -public class EcoSkillsImpl implements SkillInterface { +import java.util.Objects; + +public class EcoSkillsImpl implements LevelInterface { @Override - public void addXp(Player player, double amount) { - EcoSkillsAPI.giveSkillXP(player, Skills.INSTANCE.getByID("fishing"), amount); + public void addXp(Player player, String target, double amount) { + EcoSkillsAPI.giveSkillXP(player, Objects.requireNonNull(Skills.INSTANCE.getByID(target)), amount); } @Override - public int getLevel(Player player) { - return EcoSkillsAPI.getSkillLevel(player, Skills.INSTANCE.getByID("fishing")); + public int getLevel(Player player, String target) { + return EcoSkillsAPI.getSkillLevel(player, Objects.requireNonNull(Skills.INSTANCE.getByID(target))); } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/JobsRebornImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/JobsRebornImpl.java new file mode 100644 index 00000000..20f49388 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/JobsRebornImpl.java @@ -0,0 +1,55 @@ +/* + * 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.compatibility.level; + +import com.gamingmesh.jobs.Jobs; +import com.gamingmesh.jobs.container.Job; +import com.gamingmesh.jobs.container.JobProgression; +import com.gamingmesh.jobs.container.JobsPlayer; +import net.momirealms.customfishing.api.integration.LevelInterface; +import org.bukkit.entity.Player; + +import java.util.List; + +public class JobsRebornImpl implements LevelInterface { + + @Override + public void addXp(Player player, String target, double amount) { + JobsPlayer jobsPlayer = Jobs.getPlayerManager().getJobsPlayer(player); + if (jobsPlayer != null) { + List jobs = jobsPlayer.getJobProgression(); + Job job = Jobs.getJob(target); + for (JobProgression progression : jobs) + if (progression.getJob().equals(job)) + progression.addExperience(amount); + } + } + + @Override + public int getLevel(Player player, String target) { + JobsPlayer jobsPlayer = Jobs.getPlayerManager().getJobsPlayer(player); + if (jobsPlayer != null) { + List jobs = jobsPlayer.getJobProgression(); + Job job = Jobs.getJob(target); + for (JobProgression progression : jobs) + if (progression.getJob().equals(job)) + return progression.getLevel(); + } + return 0; + } +} diff --git a/src/main/java/net/momirealms/customfishing/integration/skill/MMOCoreImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/MMOCoreImpl.java similarity index 60% rename from src/main/java/net/momirealms/customfishing/integration/skill/MMOCoreImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/level/MMOCoreImpl.java index 7ddbd728..2c0691c5 100644 --- a/src/main/java/net/momirealms/customfishing/integration/skill/MMOCoreImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/MMOCoreImpl.java @@ -15,32 +15,23 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.skill; +package net.momirealms.customfishing.compatibility.level; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.experience.EXPSource; -import net.Indyuce.mmocore.experience.Profession; -import net.momirealms.customfishing.integration.SkillInterface; +import net.momirealms.customfishing.api.integration.LevelInterface; import org.bukkit.entity.Player; -public class MMOCoreImpl implements SkillInterface { +public class MMOCoreImpl implements LevelInterface { - private final Profession profession; - - public MMOCoreImpl(String name) { - profession = MMOCore.plugin.professionManager.get(name); + @Override + public void addXp(Player player, String target, double amount) { + MMOCore.plugin.professionManager.get(target).giveExperience(PlayerData.get(player), amount, null ,EXPSource.OTHER); } @Override - public void addXp(Player player, double amount) { - if (profession != null) { - profession.giveExperience(PlayerData.get(player), amount, null ,EXPSource.OTHER); - } - } - - @Override - public int getLevel(Player player) { - return PlayerData.get(player).getCollectionSkills().getLevel(profession); + public int getLevel(Player player, String target) { + return PlayerData.get(player).getCollectionSkills().getLevel(MMOCore.plugin.professionManager.get(target)); } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/integration/skill/mcMMOImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/McMMOImpl.java similarity index 65% rename from src/main/java/net/momirealms/customfishing/integration/skill/mcMMOImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/level/McMMOImpl.java index a49e16a7..41ec39f0 100644 --- a/src/main/java/net/momirealms/customfishing/integration/skill/mcMMOImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/level/McMMOImpl.java @@ -15,22 +15,22 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.skill; +package net.momirealms.customfishing.compatibility.level; import com.gmail.nossr50.api.ExperienceAPI; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; -import net.momirealms.customfishing.integration.SkillInterface; +import net.momirealms.customfishing.api.integration.LevelInterface; import org.bukkit.entity.Player; -public class mcMMOImpl implements SkillInterface { +public class McMMOImpl implements LevelInterface { @Override - public void addXp(Player player, double amount) { - ExperienceAPI.addRawXP(player, "FISHING", (float) amount, "UNKNOWN"); + public void addXp(Player player, String target, double amount) { + ExperienceAPI.addRawXP(player, target, (float) amount, "UNKNOWN"); } @Override - public int getLevel(Player player) { - return ExperienceAPI.getLevel(player, PrimarySkillType.FISHING); + public int getLevel(Player player, String target) { + return ExperienceAPI.getLevel(player, PrimarySkillType.valueOf(target)); } } \ No newline at end of file diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/mob/MythicMobsLibraryImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/mob/MythicMobsLibraryImpl.java new file mode 100644 index 00000000..081ae5ed --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/mob/MythicMobsLibraryImpl.java @@ -0,0 +1,43 @@ +package net.momirealms.customfishing.compatibility.mob; + +import io.lumine.mythic.api.adapters.AbstractLocation; +import io.lumine.mythic.api.mobs.MythicMob; +import io.lumine.mythic.bukkit.MythicBukkit; +import io.lumine.mythic.bukkit.utils.serialize.Position; +import io.lumine.mythic.core.mobs.ActiveMob; +import net.momirealms.customfishing.api.mechanic.mob.MobLibrary; +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +import java.util.Map; +import java.util.Optional; + +public class MythicMobsLibraryImpl implements MobLibrary { + + private MythicBukkit mythicBukkit; + + public MythicMobsLibraryImpl() { + this.mythicBukkit = MythicBukkit.inst(); + } + + @Override + public String identification() { + return "MythicMobs"; + } + + @Override + public Entity spawn(Location location, String id, Map mobPropertyMap) { + if (this.mythicBukkit == null || mythicBukkit.isClosed()) { + this.mythicBukkit = MythicBukkit.inst(); + } + Optional mythicMob = mythicBukkit.getMobManager().getMythicMob(id); + if (mythicMob.isPresent()) { + MythicMob theMob = mythicMob.get(); + Position position = Position.of(location); + AbstractLocation abstractLocation = new AbstractLocation(position); + ActiveMob activeMob = theMob.spawn(abstractLocation, (Double) mobPropertyMap.get("{level}")); + return activeMob.getEntity().getBukkitEntity(); + } + throw new NullPointerException("MythicMobs: " + id + " doesn't exist."); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/mob/VanillaMobImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/mob/VanillaMobImpl.java new file mode 100644 index 00000000..75e477c1 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/mob/VanillaMobImpl.java @@ -0,0 +1,22 @@ +package net.momirealms.customfishing.compatibility.mob; + +import net.momirealms.customfishing.api.mechanic.mob.MobLibrary; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; + +import java.util.Locale; +import java.util.Map; + +public class VanillaMobImpl implements MobLibrary { + + @Override + public String identification() { + return "vanilla"; + } + + @Override + public Entity spawn(Location location, String id, Map mobPropertyMap) { + return location.getWorld().spawnEntity(location, EntityType.valueOf(id.toUpperCase(Locale.ENGLISH))); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/MiniPlaceholdersHook.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/MiniPlaceholdersHook.java new file mode 100644 index 00000000..0f2c37d4 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/MiniPlaceholdersHook.java @@ -0,0 +1,4 @@ +package net.momirealms.customfishing.compatibility.papi; + +public class MiniPlaceholdersHook { +} diff --git a/src/main/java/net/momirealms/customfishing/integration/papi/ParseUtil.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/ParseUtils.java similarity index 92% rename from src/main/java/net/momirealms/customfishing/integration/papi/ParseUtil.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/ParseUtils.java index 77c7b369..3791dab0 100644 --- a/src/main/java/net/momirealms/customfishing/integration/papi/ParseUtil.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/ParseUtils.java @@ -15,13 +15,13 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.papi; +package net.momirealms.customfishing.compatibility.papi; import me.clip.placeholderapi.PlaceholderAPI; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -public class ParseUtil { +public class ParseUtils { public static String setPlaceholders(Player player, String text) { return PlaceholderAPI.setPlaceholders(player, text); diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderAPIHook.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderAPIHook.java new file mode 100644 index 00000000..0df4c26f --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderAPIHook.java @@ -0,0 +1,34 @@ +package net.momirealms.customfishing.compatibility.papi; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PlaceholderAPIHook extends PlaceholderExpansion { + + @Override + public @NotNull String getIdentifier() { + return "customfishing"; + } + + @Override + public @NotNull String getAuthor() { + return "XiaoMoMi"; + } + + @Override + public @NotNull String getVersion() { + return "1.4"; + } + + @Override + public boolean persist() { + return true; + } + + @Override + public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) { + return super.onRequest(player, params); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java new file mode 100644 index 00000000..68c51a54 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java @@ -0,0 +1,94 @@ +package net.momirealms.customfishing.compatibility.papi; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.PlaceholderManager; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class PlaceholderManagerImpl implements PlaceholderManager { + + private static PlaceholderManagerImpl instance; + private CustomFishingPlugin plugin; + private final boolean hasPapi; + private final Pattern pattern; + private final HashMap customPlaceholderMap; + + public PlaceholderManagerImpl(CustomFishingPlugin plugin) { + instance = this; + this.plugin = plugin; + this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); + this.pattern = Pattern.compile("\\{[^{}]+}"); + this.customPlaceholderMap = new HashMap<>(); + } + + public void disable() { + this.customPlaceholderMap.clear(); + } + + @Override + public String setPlaceholders(Player player, String text) { + return hasPapi ? ParseUtils.setPlaceholders(player, text) : text; + } + + @Override + public String setPlaceholders(OfflinePlayer player, String text) { + return hasPapi ? ParseUtils.setPlaceholders(player, text) : text; + } + + @Override + public List detectPlaceholders(String text) { + List placeholders = new ArrayList<>(); + Matcher matcher = pattern.matcher(text); + while (matcher.find()) placeholders.add(matcher.group()); + return placeholders; + } + + @Override + public String getSingleValue(@Nullable Player player, String placeholder, Map placeholders) { + String result; + result = placeholders.get(placeholder); + if (result != null) return result; + String custom = customPlaceholderMap.get(placeholder); + if (custom == null) return placeholder; + return setPlaceholders(player, custom); + } + + @Override + public String parse(@Nullable OfflinePlayer player, String text, Map placeholders) { + var list = detectPlaceholders(text); + for (String papi : list) { + String replacer = placeholders.get(papi); + if (replacer == null) { + String custom = customPlaceholderMap.get(papi); + if (custom != null) { + replacer = setPlaceholders(player, custom); + } + } + if (replacer != null) { + text = text.replace(papi, replacer); + } + } + return text; + } + + @Override + public List parse(@Nullable OfflinePlayer player, List list, Map replacements) { + return list.stream() + .map(s -> parse(player, s, replacements)) + .collect(Collectors.toList()); + } + + public static PlaceholderManagerImpl getInstance() { + return instance; + } +} diff --git a/src/main/java/net/momirealms/customfishing/integration/season/CustomCropsSeasonImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/season/CustomCropsSeasonImpl.java similarity index 90% rename from src/main/java/net/momirealms/customfishing/integration/season/CustomCropsSeasonImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/season/CustomCropsSeasonImpl.java index 7ec54c10..557b3d93 100644 --- a/src/main/java/net/momirealms/customfishing/integration/season/CustomCropsSeasonImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/season/CustomCropsSeasonImpl.java @@ -15,10 +15,10 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.season; +package net.momirealms.customfishing.compatibility.season; import net.momirealms.customcrops.api.CustomCropsAPI; -import net.momirealms.customfishing.integration.SeasonInterface; +import net.momirealms.customfishing.api.integration.SeasonInterface; import org.bukkit.World; import java.util.Objects; diff --git a/src/main/java/net/momirealms/customfishing/integration/season/RealisticSeasonsImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/season/RealisticSeasonsImpl.java similarity index 90% rename from src/main/java/net/momirealms/customfishing/integration/season/RealisticSeasonsImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/compatibility/season/RealisticSeasonsImpl.java index bc80dca9..cfe25c8b 100644 --- a/src/main/java/net/momirealms/customfishing/integration/season/RealisticSeasonsImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/season/RealisticSeasonsImpl.java @@ -15,10 +15,10 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.integration.season; +package net.momirealms.customfishing.compatibility.season; import me.casperge.realisticseasons.api.SeasonsAPI; -import net.momirealms.customfishing.integration.SeasonInterface; +import net.momirealms.customfishing.api.integration.SeasonInterface; import org.bukkit.World; public class RealisticSeasonsImpl implements SeasonInterface { diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/DynamicGuiElement.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/DynamicGuiElement.java new file mode 100644 index 00000000..2f2e613a --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/DynamicGuiElement.java @@ -0,0 +1,189 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Represents an element in a gui that will query all it's data when drawn. + */ +public class DynamicGuiElement extends GuiElement { + private Function query; + + private Map cachedElements = new ConcurrentHashMap<>(); + + /** + * Represents an element in a gui that will query all it's data when drawn. + * @param slotChar The character to replace in the gui setup string + * @param query Query the element data, this should return an element with the information + */ + public DynamicGuiElement(char slotChar, Supplier query) { + this(slotChar, (h) -> query.get()); + } + + /** + * Represents an element in a gui that will query all it's data when drawn. + * @param slotChar The character to replace in the gui setup string + * @param query Query the element data, this should return an element with the information and handle null players properly + */ + public DynamicGuiElement(char slotChar, Function query) { + super(slotChar); + this.query = query; + } + + /** + * Query this element's state for every player who had it cached + */ + public void update() { + for (UUID playerId : new ArrayList<>(cachedElements.keySet())) { + Player p = gui.getPlugin().getServer().getPlayer(playerId); + if (p != null && p.isOnline()) { + update(p); + } else { + cachedElements.remove(playerId); + } + } + } + + /** + * Query this element's state for a certain player + * @param player The player for whom to update the element + */ + public CacheEntry update(HumanEntity player) { + CacheEntry cacheEntry = new CacheEntry(queryElement(player)); + if (cacheEntry.element instanceof DynamicGuiElement) { + ((DynamicGuiElement) cacheEntry.element).update(player); + } else if (cacheEntry.element instanceof GuiElementGroup) { + InventoryGui.updateElements(player, ((GuiElementGroup) cacheEntry.element).getElements()); + } + cachedElements.put(player.getUniqueId(), cacheEntry); + return cacheEntry; + } + + @Override + public void setGui(InventoryGui gui) { + super.setGui(gui); + } + + @Override + public ItemStack getItem(HumanEntity who, int slot) { + GuiElement element = getCachedElement(who); + return element != null ? element.getItem(who, slot) : null; + } + + @Override + public Action getAction(HumanEntity who) { + GuiElement element = getCachedElement(who); + return element != null ? element.getAction(who) : null; + } + + /** + * Get the supplier for this element's content + * @return The supplier query + */ + public Function getQuery() { + return query; + } + + /** + * Set the supplier for this element's content + * @param query The supplier query to set + */ + public void setQuery(Function query) { + this.query = query; + } + + /** + * Query the element for a player + * @param who The player + * @return The GuiElement or null + */ + public GuiElement queryElement(HumanEntity who) { + GuiElement element = getQuery().apply(who); + if (element != null) { + element.setGui(gui); + element.setSlots(slots); + } + return element; + } + + /** + * Get the cached element, creates a new one if there is none for that player. + * Use {@link #getLastCached(HumanEntity)} to check if a player has something cached. + * @param who The player to get the element for + * @return The element that is currently cached + */ + public GuiElement getCachedElement(HumanEntity who) { + CacheEntry cached = cachedElements.get(who.getUniqueId()); + if (cached == null) { + cached = update(who); + } + return cached.getElement(); + } + + /** + * Remove the cached element if the player has one. + * @param who The player to remove the cached element for + * @return The element that was cached or null if none was cached + */ + public GuiElement removeCachedElement(HumanEntity who) { + CacheEntry cached = cachedElements.remove(who.getUniqueId()); + return cached != null ? cached.getElement() : null; + } + + /** + * Get the time at which this element was last cached for a certain player + * @param who The player to get the last cache time for + * @return The timestamp from when it was last cached or -1 if it wasn't cached + */ + public long getLastCached(HumanEntity who) { + CacheEntry cached = cachedElements.get(who.getUniqueId()); + return cached != null ? cached.getCreated() : -1; + } + + public class CacheEntry { + private final GuiElement element; + private final long created = System.currentTimeMillis(); + + CacheEntry(GuiElement element) { + this.element = element; + } + + public GuiElement getElement() { + return element; + } + + public long getCreated() { + return created; + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiBackElement.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiBackElement.java new file mode 100644 index 00000000..b73ccb46 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiBackElement.java @@ -0,0 +1,77 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; + +/** + * An element that will not appear if there is no previous history, + * but will go back one step if there is + */ +public class GuiBackElement extends StaticGuiElement { + + private boolean close; + + /** + * An element used to go back in history of the gui if there is something to go back to. + * Will not display when there is nothing to go back to. + * + * @param slotChar The character to replace in the gui setup string + * @param item The {@link ItemStack} representing this element + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public GuiBackElement(char slotChar, ItemStack item, String... text) { + this(slotChar, item, false, text); + } + + /** + * An element used to go back in history of the gui + * + * @param slotChar The character to replace in the gui setup string + * @param item The {@link ItemStack} representing this element + * @param close Whether to close the GUI if there is nothing to go back to. + * Will not display item if set to false and nothing to go back to. + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public GuiBackElement(char slotChar, ItemStack item, boolean close, String... text) { + super(slotChar, item, text); + this.close = close; + + setAction(click -> { + if (canGoBack(click.getWhoClicked())) { + InventoryGui.goBack(click.getWhoClicked()); + } else if (close) { + click.getGui().close(); + } + return true; + }); + } + + @Override + public ItemStack getItem(HumanEntity who, int slot) { + if (!canGoBack(who) && !close) { + return gui.getFiller() != null ? gui.getFiller().getItem(who, slot) : null; + } + + return super.getItem(who, slot); + } + + /** + * Whether this element can close the GUI when nothing to go back to + * @return Close the GUI when nothing to go back + */ + public boolean canClose() { + return close; + } + + private boolean canGoBack(HumanEntity who) { + return InventoryGui.getHistory(who).size() > 1 || (InventoryGui.getHistory(who).size() == 1 && InventoryGui.getHistory(who).peekLast() != gui); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiElement.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiElement.java new file mode 100644 index 00000000..33b50954 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiElement.java @@ -0,0 +1,235 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryInteractEvent; +import org.bukkit.inventory.ItemStack; + +/** + * Represents an element in a gui + */ +public abstract class GuiElement { + private final char slotChar; + private Action action; + protected int[] slots = new int[0]; + protected InventoryGui gui; + + /** + * Represents an element in a gui + * @param slotChar The character to replace in the gui setup string + * @param action The action to run when the player clicks on this element + */ + public GuiElement(char slotChar, Action action) { + this.slotChar = slotChar; + setAction(action); + } + + /** + * Represents an element in a gui that doesn't have any action when clicked + * @param slotChar The character to replace in the gui setup string + */ + public GuiElement(char slotChar) { + this(slotChar, null); + } + + /** + * Get the character in the gui setup that corresponds with this element + * @return The character + */ + public char getSlotChar() { + return slotChar; + } + + /** + * Get the item that is displayed by this element on a certain page + * @param who The player who views the page + * @param slot The slot to get the item for + * @return The ItemStack that is displayed as this element + */ + public abstract ItemStack getItem(HumanEntity who, int slot); + + /** + * Get the action that is executed when clicking on this element + * @param who The player who views the page + * @return The action to run + */ + public Action getAction(HumanEntity who) { + return action; + } + + /** + * Set the action that is executed when clicking on this element + * @param action The action to run. The {@link Action#onClick} method should + * return whether or not the click event should be cancelled + */ + public void setAction(Action action) { + this.action = action; + } + + /** + * Get the indexes of the lots that this element is displayed in + * @return An array of the lost indexes + */ + public int[] getSlots() { + return slots; + } + + /** + * Set the ids of the slots where this element is assigned to + * @param slots An array of the slot ids where this element is displayed + */ + public void setSlots(int[] slots) { + this.slots = slots; + } + + /** + * Get the index that this slot has in the list of slots that this element is displayed in + * @param slot The id of the slot + * @return The index in the list of slots that this id has or -1 if it isn't in that list + */ + public int getSlotIndex(int slot) { + return getSlotIndex(slot, 0); + } + + /** + * Get the index that this slot has in the list of slots that this element is displayed in + * @param slot The id of the slot + * @param pageNumber The number of the page that the gui is on + * @return The index in the list of slots that this id has or -1 if it isn't in that list + */ + public int getSlotIndex(int slot, int pageNumber) { + for (int i = 0; i < slots.length; i++) { + if (slots[i] == slot) { + return i + slots.length * pageNumber; + } + } + return -1; + } + + /** + * Set the gui this element belongs to + * @param gui The GUI that this element is in + */ + public void setGui(InventoryGui gui) { + this.gui = gui; + } + + /** + * Get the gui this element belongs to + * @return The GUI that this element is in + */ + public InventoryGui getGui() { + return gui; + } + + public static interface Action { + + /** + * Executed when a player clicks on an element + * @param click The Click class containing information about the click + * @return Whether or not the click event should be cancelled + */ + boolean onClick(Click click); + + } + + public static class Click { + private final InventoryGui gui; + private final int slot; + private final ClickType clickType; + private ItemStack cursor; + private final GuiElement element; + private final InventoryInteractEvent event; + + public Click(InventoryGui gui, int slot, ClickType clickType, ItemStack cursor, GuiElement element, InventoryInteractEvent event) { + this.gui = gui; + this.slot = slot; + this.clickType = clickType; + this.cursor = cursor; + this.element = element; + this.event = event; + } + + /** + * Get the slot of the GUI that was clicked + * @return The clicked slot + */ + public int getSlot() { + return slot; + } + + /** + * Get the element that was clicked + * @return The clicked GuiElement + */ + public GuiElement getElement() { + return element; + } + + /** + * Get the type of the click + * @return The type of the click + */ + public ClickType getType() { + return clickType; + } + + /** + * Get the item on the cursor + * @return The item on the cursor when this click occurred + */ + public ItemStack getCursor() { + return cursor; + } + + /** + * Set the item on the cursor after the click + * @param cursor The new item on the cursor + */ + public void setCursor(ItemStack cursor) { + this.cursor = cursor; + } + + /** + * Get who clicked the element + * @return The player that clicked + */ + public HumanEntity getWhoClicked() { + return event.getWhoClicked(); + } + + /** + * Get the event of the inventory interaction + * @return The InventoryInteractEvent associated with this Click + */ + public InventoryInteractEvent getRawEvent() { + return event; + } + + public InventoryGui getGui() { + return gui; + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiElementGroup.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiElementGroup.java new file mode 100644 index 00000000..8077b5a7 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiElementGroup.java @@ -0,0 +1,276 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Represents a group of multiple elements. Will be left-aligned by default. + */ +public class GuiElementGroup extends GuiElement { + private List elements = new ArrayList<>(); + private GuiElement filler = null; + private Alignment alignment = Alignment.LEFT; + + /** + * A group of elements + * @param slotChar The character to replace in the gui setup string + * @param elements The elements in this group + */ + public GuiElementGroup(char slotChar, GuiElement... elements) { + super(slotChar, null); + setAction(click -> { + GuiElement element = getElement(click.getSlot(), click.getGui().getPageNumber(click.getWhoClicked())); + if (element != null && element.getAction(click.getRawEvent().getWhoClicked()) != null) { + return element.getAction(click.getWhoClicked()).onClick(click); + } + return true; + }); + Collections.addAll(this.elements, elements); + } + + @Override + public ItemStack getItem(HumanEntity who, int slot) { + GuiElement element = getElement(slot, gui.getPageNumber(who)); + if (element != null) { + return element.getItem(who, slot); + } + return null; + } + + @Override + public void setGui(InventoryGui gui) { + super.setGui(gui); + for (GuiElement element : elements) { + if (element != null) { + element.setGui(gui); + } + } + if (filler != null) { + filler.setGui(gui); + } + } + + @Override + public void setSlots(int[] slots) { + super.setSlots(slots); + for (GuiElement element : elements) { + if (element != null) { + element.setSlots(slots); + } + } + } + + /** + * Add an element to this group + * @param element The element to add + */ + public void addElement(GuiElement element){ + elements.add(element); + if (element != null) { + element.setGui(gui); + element.setSlots(slots); + } + } + + /** + * Add elements to this group + * @param elements The elements to add + */ + public void addElements(GuiElement... elements){ + for (GuiElement element : elements) { + addElement(element); + } + } + + /** + * Add elements to this group + * @param elements The elements to add + */ + public void addElements(Collection elements){ + for (GuiElement element : elements) { + addElement(element); + } + } + + /** + * Get the element in a certain slot + * @param slot The slot to get the element for + * @return The GuiElement in that slot or null + */ + public GuiElement getElement(int slot) { + return getElement(slot, 0); + } + + /** + * Get the element in a certain slot on a certain page + * @param slot The slot to get the element for + * @param pageNumber The number of the page that the gui is on + * @return The GuiElement in that slot or null + */ + public GuiElement getElement(int slot, int pageNumber) { + if (elements.isEmpty()) { + return null; + } + int index = getSlotIndex(slot, slots.length < elements.size() ? pageNumber : 0); + if (index > -1) { + if (alignment == Alignment.LEFT) { + if (index < elements.size()) { + return elements.get(index); + } + } else { + int lineWidth = getLineWidth(slot); + int linePosition = getLinePosition(slot); + if (elements.size() - index > lineWidth - linePosition) { + return elements.get(index); + } + int rest = elements.size() - (index - linePosition); + int blankBefore = alignment == Alignment.CENTER ? (lineWidth - rest) / 2 : lineWidth - rest; + if (linePosition < blankBefore || index - blankBefore >= elements.size()) { + return filler; + } + return elements.get(index - blankBefore); + } + } + return filler; + } + + /** + * Get the width of the line the slot is in + * @param slot The slot + * @return The width of the line in the GUI setup of this group + */ + private int getLineWidth(int slot) { + int width = gui.getWidth(); + int row = slot / width; + + int amount = 0; + for (int s : slots) { + if (s >= row * width && s < (row + 1) * width) { + amount++; + } + } + return amount; + } + + /** + * Get the position of the slot in its line + * @param slot The slot ID + * @return The line position or -1 if not in its line. wat + */ + private int getLinePosition(int slot) { + int width = gui.getWidth(); + int row = slot / width; + + int position = -1; + for (int s : slots) { + if (s >= row * width && s < (row + 1) * width) { + position++; + if (s == slot) { + return position; + } + } + } + return position; + } + + /** + * Get all elements of this group. This list is immutable, use {@link #addElement(GuiElement)} + * and {@link #clearElements()} to modify the elements in this group. + * @return An immutable list of all elements in this group + */ + public List getElements() { + return Collections.unmodifiableList(elements); + } + + /** + * Removes all elements in the group + */ + public void clearElements() { + elements.clear(); + } + + /** + * Set the filler element for empty slots + * @param item The item for the filler element + */ + public void setFiller(ItemStack item) { + filler = new StaticGuiElement(' ', item, " "); + filler.setGui(gui); + } + + /** + * Set the filler element for empty slots + * @param filler The item for the filler element + */ + public void setFiller(GuiElement filler) { + this.filler = filler; + if (filler != null) { + filler.setGui(gui); + } + } + + /** + * Get the filler element + * @return The filler element + */ + public GuiElement getFiller() { + return filler; + } + + /** + * Get the size of this group + * @return The amount of elements that this group has + */ + public int size() { + return elements.size(); + } + + /** + * Set the alignment of the elements in this group + * @param alignment The alignment + */ + public void setAlignment(Alignment alignment) { + this.alignment = alignment; + } + + /** + * Get the alignment of the elements in this group + * @return The alignment + */ + public Alignment getAlignment() { + return alignment; + } + + public enum Alignment { + LEFT, + CENTER, + RIGHT; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiPageElement.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiPageElement.java new file mode 100644 index 00000000..8abf4330 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiPageElement.java @@ -0,0 +1,124 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; + +/** + * This is an element that allows for controlling the pagination of the gui. + * Untested und potentially unfinished. + */ +public class GuiPageElement extends StaticGuiElement { + private PageAction pageAction; + private boolean silent = false; + + /** + * An element that allows for controlling the pagination of the gui. + * @param slotChar The character to replace in the gui setup string + * @param item The {@link ItemStack} representing this element + * @param pageAction What kind of page action you want to happen when interacting with the element. + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public GuiPageElement(char slotChar, ItemStack item, PageAction pageAction, String... text) { + super(slotChar, item, text); + setAction(click -> { + switch (pageAction) { + case NEXT: + if (click.getGui().getPageNumber(click.getWhoClicked()) + 1 < click.getGui().getPageAmount(click.getWhoClicked())) { + if (!isSilent()) { + click.getGui().playClickSound(); + } + click.getGui().setPageNumber(click.getWhoClicked(), click.getGui().getPageNumber(click.getWhoClicked()) + 1); + } + break; + case PREVIOUS: + if (click.getGui().getPageNumber(click.getWhoClicked()) > 0) { + if (!isSilent()) { + click.getGui().playClickSound(); + } + click.getGui().setPageNumber(click.getWhoClicked(), click.getGui().getPageNumber(click.getWhoClicked()) - 1); + } + break; + case FIRST: + if (!isSilent()) { + click.getGui().playClickSound(); + } + click.getGui().setPageNumber(click.getWhoClicked(), 0); + break; + case LAST: + if (!isSilent()) { + click.getGui().playClickSound(); + } + click.getGui().setPageNumber(click.getWhoClicked(), click.getGui().getPageAmount(click.getWhoClicked()) - 1); + break; + } + return true; + }); + this.pageAction = pageAction; + } + + /** + * Get whether or not this element should make a sound when interacted with + * @return Whether or not to make a sound when interacted with + */ + public boolean isSilent() { + return silent; + } + + /** + * Set whether or not this element should make a sound when interacted with + * @param silent Whether or not to make a sound when interacted with + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + @Override + public ItemStack getItem(HumanEntity who, int slot) { + if (((pageAction == PageAction.FIRST || pageAction == PageAction.LAST) && gui.getPageAmount(who) < 3) + || (pageAction == PageAction.NEXT && gui.getPageNumber(who) + 1 >= gui.getPageAmount(who)) + || (pageAction == PageAction.PREVIOUS && gui.getPageNumber(who) == 0)) { + return gui.getFiller() != null ? gui.getFiller().getItem(who, slot) : null; + } + if (pageAction == PageAction.PREVIOUS) { + setNumber(gui.getPageNumber(who)); + } else if (pageAction == PageAction.NEXT) { + setNumber(gui.getPageNumber(who) + 2); + } else if (pageAction == PageAction.LAST) { + setNumber(gui.getPageAmount(who)); + } + return super.getItem(who, slot).clone(); + } + + public enum PageAction { + NEXT, + PREVIOUS, + FIRST, + LAST; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiStateElement.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiStateElement.java new file mode 100644 index 00000000..448c66ae --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiStateElement.java @@ -0,0 +1,280 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; + +import java.util.function.Supplier; + +/** + * An element that can switch between certain states. It automatically handles the switching + * of the item in the slot that corresponds to the state that the element is in. + */ +public class GuiStateElement extends GuiElement { + private Supplier queryState = null; + private boolean silent = false; + private int currentState; + private final State[] states; + + /** + * An element that can switch between certain states. + * @param slotChar The character to replace in the gui setup string. + * @param defaultState The index of the default state. + * @param states The list of different {@link State}s that this element can have. + */ + public GuiStateElement(char slotChar, int defaultState, State... states) { + super(slotChar, null); + if (states.length == 0) { + throw new IllegalArgumentException("You need to add at least one State!"); + } + this.currentState = defaultState; + this.states = states; + + setAction(click -> { + State next = nextState(); + next.change.onChange(click); + if (!isSilent()) { + click.getGui().playClickSound(); + } + gui.draw(click.getWhoClicked(), false); + return true; + }); + } + + /** + * An element that can switch between certain states. + * @param slotChar The character to replace in the gui setup string. + * @param defaultState The key of the default state. + * @param states The list of different {@link State}s that this element can have. + */ + public GuiStateElement(char slotChar, String defaultState, State... states) { + this(slotChar, getStateIndex(defaultState, states), states); + } + + /** + * An element that can switch between certain states. + * @param slotChar The character to replace in the gui setup string. + * @param queryState Supplier for the current state. + * @param states The list of different {@link State}s that this element can have. + */ + public GuiStateElement(char slotChar, Supplier queryState, State... states) { + this(slotChar, queryState.get(), states); + this.queryState = () -> getStateIndex(queryState.get(), states); + } + + /** + * An element that can switch between certain states. The first state will be the default one. + * @param slotChar The character to replace in the gui setup string. + * @param states The list of different {@link State}s that this element can have. + */ + public GuiStateElement(char slotChar, State... states) { + this(slotChar, 0, states); + } + + /** + * Loop through the states of this element + * @return The new state (next one to the old) + */ + public State nextState() { + queryCurrentState(); + currentState = states.length > currentState + 1 ? currentState + 1 : 0; + return states[currentState]; + } + + /** + * Loop through the states of this element backwards + * @return The new state (previous one to the old) + */ + public State previousState() { + queryCurrentState(); + currentState = currentState > 0 ? currentState - 1 : states.length - 1; + return states[currentState]; + } + + @Override + public ItemStack getItem(HumanEntity who, int slot) { + return getState().getItem(who); + } + + @Override + public void setGui(InventoryGui gui) { + super.setGui(gui); + for (State state : states) { + state.setGui(gui); + } + } + + /** + * Get the current state of this element + * @return The current state of this element + */ + public State getState() { + queryCurrentState(); + return states[currentState]; + } + + /** + * Get whether or not this element should make a sound when interacted with + * @return Whether or not to make a sound when interacted with + */ + public boolean isSilent() { + return silent; + } + + /** + * Set whether or not this element should make a sound when interacted with + * @param silent Whether or not to make a sound when interacted with + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** + * Try to query the current state if there is a query + */ + private void queryCurrentState() { + if (queryState != null) { + currentState = queryState.get(); + } + } + + /** + * Set the current state with the state's key. Does not trigger the state's change. + * @param key The key to search for. + * @throws IllegalArgumentException Thrown if there is no state with the provided key. + */ + public void setState(String key) throws IllegalArgumentException { + currentState = getStateIndex(key, states); + } + + /** + * Get the index of a state from a key + * @param key The key to search for. + * @param states The states to search in. + * @return The index of that key in the state array. + * @throws IllegalArgumentException Thrown if there is no state with the provided key. + */ + private static int getStateIndex(String key, State[] states) throws IllegalArgumentException { + for (int i = 0; i < states.length; i++) { + if (states[i].getKey().equals(key)) { + return i; + } + } + throw new IllegalArgumentException("This element does not have the state " + key); + } + + /** + * A state that the {@link GuiStateElement} can have. + */ + public static class State { + private final Change change; + private final String key; + private final ItemStack item; + private String[] text; + private InventoryGui gui; + + /** + * A state that the {@link GuiStateElement} can have. + * @param change What to do when the state changes + * @param key The state's string key + * @param item The {@link ItemStack} to represent this state + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public State(Change change, String key, ItemStack item, String... text) { + this.change = change; + this.key = key; + this.item = item; + this.text = text; + } + + /** + * Set this element's display text. If this is an empty array the item's name will be displayed + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public void setText(String... text) { + this.text = text; + } + + /** + * Get the {@link ItemStack} that represents this state. + * @return The {@link ItemStack} that represents this state + * @deprecated Use {@link #getItem(HumanEntity)} + */ + @Deprecated + public ItemStack getItem() { + return getItem(null); + } + + /** + * Get the {@link ItemStack} that represents this state. + * @param who The player viewing the GUI + * @return The {@link ItemStack} that represents this state + */ + public ItemStack getItem(HumanEntity who) { + ItemStack clone = item.clone(); + gui.setItemText(who, clone, getText()); + return clone; + } + + /** + * Get the string key of the state. + * @return The state's string key + */ + public String getKey() { + return key; + } + + /** + * Get the text lines that describe this state. + * @return The text lines for this state + */ + public String[] getText() { + return text; + } + + private void setGui(InventoryGui gui) { + this.gui = gui; + } + + /** + * Define what should happen when the state of the element' state changes to this state + */ + public interface Change { + + /** + * What should happen when the element's state changes to this state + * @param click The click that triggered this change + */ + void onChange(Click click); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiStorageElement.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiStorageElement.java new file mode 100644 index 00000000..b6204d07 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/GuiStorageElement.java @@ -0,0 +1,368 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.function.Function; + +/** + * This element is used to access an {@link Inventory}. The slots in the inventory are selected + * by searching through the whole gui the element is in and getting the number of the spot + * in the character group that this element is in.
+ * E.g. if you have five characters called "s" in the gui setup and the second element is + * accessed by the player then it will translate to the second slot in the inventory. + */ +public class GuiStorageElement extends GuiElement { + private final Inventory storage; + private final int invSlot; + private Runnable applyStorage; + private Function itemValidator; + + /** + * An element used to access an {@link Inventory}. + * @param slotChar The character to replace in the gui setup string. + * @param storage The {@link Inventory} that this element is linked to. + */ + public GuiStorageElement(char slotChar, Inventory storage) { + this(slotChar, storage, -1); + } + + /** + * An element used to access a specific slot in an {@link Inventory}. + * @param slotChar The character to replace in the gui setup string. + * @param storage The {@link Inventory} that this element is linked to. + * @param invSlot The index of the slot to access in the {@link Inventory}. + */ + public GuiStorageElement(char slotChar, Inventory storage, int invSlot) { + this(slotChar, storage, invSlot, null, null); + } + + /** + * An element used to access a specific slot in an {@link Inventory}. + * @param slotChar The character to replace in the gui setup string. + * @param storage The {@link Inventory} that this element is linked to. + * @param invSlot The index of the slot to access in the {@link Inventory}. + * @param applyStorage Apply the storage that this element represents. + * @param itemValidator Should return false for items that should not work in that slot + * Can be null if the storage is directly linked. + */ + public GuiStorageElement(char slotChar, Inventory storage, int invSlot, Runnable applyStorage, Function itemValidator) { + super(slotChar, null); + this.invSlot = invSlot; + this.applyStorage = applyStorage; + this.itemValidator = itemValidator; + setAction(click -> { + if (getStorageSlot(click.getWhoClicked(), click.getSlot()) < 0) { + return true; + } + ItemStack storageItem = getStorageItem(click.getWhoClicked(), click.getSlot()); + ItemStack slotItem = click.getRawEvent().getView().getTopInventory().getItem(click.getSlot()); + if (slotItem == null && storageItem != null && storageItem.getType() != Material.AIR + || storageItem == null && slotItem != null && slotItem.getType() != Material.AIR + || storageItem != null && !storageItem.equals(slotItem)) { + gui.draw(click.getWhoClicked(), false); + return true; + } + + if (!(click.getRawEvent() instanceof InventoryClickEvent)) { + // Only the click event will be handled here, drag event is handled separately + return true; + } + + InventoryClickEvent event = (InventoryClickEvent) click.getRawEvent(); + + ItemStack movedItem = null; + switch (event.getAction()) { + case NOTHING: + case CLONE_STACK: + return false; + case MOVE_TO_OTHER_INVENTORY: + if (event.getRawSlot() < click.getRawEvent().getView().getTopInventory().getSize()) { + // Moved from storage + + // Check if there is actually space (more advanced checks can unfortunately not be supported right now) + if (click.getRawEvent().getView().getBottomInventory().firstEmpty() == -1) { + // No empty slot, cancel + return true; + } + movedItem = null; + } else { + // Moved to storage + + // Check if there is actually space (more advanced checks can unfortunately not be supported right now) + if (click.getRawEvent().getView().getTopInventory().firstEmpty() == -1) { + // No empty slot, cancel + return true; + } + movedItem = event.getCurrentItem(); + } + // Update GUI to avoid display glitches + gui.runTask(gui::draw); + break; + case HOTBAR_MOVE_AND_READD: + case HOTBAR_SWAP: + int button = event.getHotbarButton(); + if (button < 0) { + return true; + } + ItemStack hotbarItem = click.getRawEvent().getView().getBottomInventory().getItem(button); + if (hotbarItem != null) { + movedItem = hotbarItem.clone(); + } + break; + case PICKUP_ONE: + case DROP_ONE_SLOT: + if (event.getCurrentItem() != null) { + movedItem = event.getCurrentItem().clone(); + movedItem.setAmount(movedItem.getAmount() - 1); + } + break; + case DROP_ALL_SLOT: + movedItem = null; + break; + case PICKUP_HALF: + if (event.getCurrentItem() != null) { + movedItem = event.getCurrentItem().clone(); + movedItem.setAmount(movedItem.getAmount() / 2); + } + break; + case PLACE_SOME: + if (event.getCurrentItem() == null) { + if (event.getCursor() != null) { + movedItem = event.getCursor().clone(); + } + } else { + movedItem = event.getCurrentItem().clone(); + int newAmount = movedItem.getAmount() + (event.getCursor() != null ? event.getCursor().getAmount() : 0); + if (newAmount < movedItem.getMaxStackSize()) { + movedItem.setAmount(newAmount); + } else { + movedItem.setAmount(movedItem.getMaxStackSize()); + } + } + break; + case PLACE_ONE: + if (event.getCursor() != null) { + if (event.getCurrentItem() == null) { + movedItem = event.getCursor().clone(); + movedItem.setAmount(1); + } else { + movedItem = event.getCursor().clone(); + movedItem.setAmount(event.getCurrentItem().getAmount() + 1); + } + } + break; + case PLACE_ALL: + if (event.getCursor() != null) { + movedItem = event.getCursor().clone(); + if (event.getCurrentItem() != null && event.getCurrentItem().getAmount() > 0) { + movedItem.setAmount(event.getCurrentItem().getAmount() + movedItem.getAmount()); + } + } + break; + case PICKUP_ALL: + case SWAP_WITH_CURSOR: + if (event.getCursor() != null) { + movedItem = event.getCursor().clone(); + }; + break; + case COLLECT_TO_CURSOR: + if (event.getCursor() == null + || event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR) { + return true; + } + gui.simulateCollectToCursor(click); + return false; + default: + click.getRawEvent().getWhoClicked().sendMessage(ChatColor.RED + "The action " + event.getAction() + " is not supported! Sorry about that :("); + return true; + } + return !setStorageItem(click.getWhoClicked(), click.getSlot(), movedItem); + }); + this.storage = storage; + } + + @Override + public ItemStack getItem(HumanEntity who, int slot) { + int index = getStorageSlot(who, slot); + if (index > -1 && index < storage.getSize()) { + return storage.getItem(index); + } + return null; + } + + /** + * Get the {@link Inventory} that this element is linked to. + * @return The {@link Inventory} that this element is linked to. + */ + public Inventory getStorage() { + return storage; + } + + /** + * Get the storage slot index that corresponds to the InventoryGui slot + * @param player The player which is using the GUI view + * @param slot The slot in the GUI + * @return The index of the storage slot or -1 if it's outside the storage + */ + private int getStorageSlot(HumanEntity player, int slot) { + int index = invSlot != -1 ? invSlot : getSlotIndex(slot, gui.getPageNumber(player)); + if (index < 0 || index >= storage.getSize()) { + return -1; + } + return index; + } + + /** + * Get the item in the storage that corresponds to the InventoryGui slot + * @param slot The slot in the GUI + * @return The {@link ItemStack} or null if the slot is outside of the item's size + * @deprecated Use {@link #getStorageItem(HumanEntity, int)} + */ + @Deprecated + public ItemStack getStorageItem(int slot) { + return getStorageItem(null, slot); + } + + /** + * Get the item in the storage that corresponds to the InventoryGui slot + * @param player The player which is using the GUI view + * @param slot The slot in the GUI + * @return The {@link ItemStack} or null if the slot is outside of the item's size + */ + public ItemStack getStorageItem(HumanEntity player, int slot) { + int index = getStorageSlot(player, slot); + if (index == -1) { + return null; + } + return storage.getItem(index); + } + + /** + * Set the item in the storage that corresponds to the InventoryGui slot. + * @param slot The slot in the GUI + * @param item The {@link ItemStack} to set + * @return true if the item was set; false if the slot was outside of this storage + * @deprecated Use {@link #setStorageItem(HumanEntity, int, ItemStack)} + */ + @Deprecated + public boolean setStorageItem(int slot, ItemStack item) { + return setStorageItem(null, slot, item); + } + + /** + * Set the item in the storage that corresponds to the InventoryGui slot. + * @param player The player using the GUI view + * @param slot The slot in the GUI + * @param item The {@link ItemStack} to set + * @return true if the item was set; false if the slot was outside of this storage + */ + public boolean setStorageItem(HumanEntity player, int slot, ItemStack item) { + int index = getStorageSlot(player, slot); + if (index == -1) { + return false; + } + if (!validateItem(slot, item)) { + return false; + } + storage.setItem(index, item); + if (applyStorage != null) { + applyStorage.run(); + } + return true; + } + + /** + * Get the runnable that applies the storage + * @return The storage applying runnable; might be null + */ + public Runnable getApplyStorage() { + return applyStorage; + } + + /** + * Set what should be done to apply the storage. + * Not necessary if the storage is directly backed by a real inventory. + * @param applyStorage How to apply the storage; can be null if nothing should be done + */ + public void setApplyStorage(Runnable applyStorage) { + this.applyStorage = applyStorage; + } + + /** + * Get the item validator + * @return The item validator + */ + public Function getItemValidator() { + return itemValidator; + } + + /** + * Set a function that can validate whether or not an item can fit in the slot + * @param itemValidator The item validator that takes a {@link ValidatorInfo} and returns true for items that + * should and false for items that should not work in that slot + */ + public void setItemValidator(Function itemValidator) { + this.itemValidator = itemValidator; + } + + /** + * Validate whether or not an item can be put in a slot with the item validator set in {@link #setItemValidator(Function)} + * @param slot The slot the item should be tested for + * @param item The item to test + * @return true for items that should and false for items that should not work in that slot + */ + public boolean validateItem(int slot, ItemStack item) { + return itemValidator == null || itemValidator.apply(new ValidatorInfo(this, slot, item)); + } + + public static class ValidatorInfo { + private final GuiElement element; + private final int slot; + private final ItemStack item; + + public ValidatorInfo(GuiElement element, int slot, ItemStack item) { + this.item = item; + this.slot = slot; + this.element = element; + } + + public GuiElement getElement() { + return element; + } + + public int getSlot() { + return slot; + } + + public ItemStack getItem() { + return item; + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/InventoryGui.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/InventoryGui.java new file mode 100644 index 00000000..bcc6209d --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/InventoryGui.java @@ -0,0 +1,1690 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import net.kyori.adventure.text.Component; +import net.momirealms.customfishing.api.util.InventoryUtils; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.Nameable; +import org.bukkit.Sound; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +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.BlockBreakEvent; +import org.bukkit.event.block.BlockDispenseEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.inventory.*; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.material.MaterialData; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * The main library class that lets you create and manage your GUIs + */ +public class InventoryGui implements Listener { + + private final static int[] ROW_WIDTHS = {3, 5, 9}; + private final static InventoryType[] INVENTORY_TYPES = { + InventoryType.DISPENSER, // 3*3 + InventoryType.HOPPER, // 5*1 + InventoryType.CHEST // 9*x + }; + + private final static Map GUI_MAP = new ConcurrentHashMap<>(); + private final static Map> GUI_HISTORY = new ConcurrentHashMap<>(); + + private final static Map PATTERN_CACHE = new HashMap<>(); + + private final static boolean FOLIA; + + private static String DEFAULT_CLICK_SOUND; + + private final JavaPlugin plugin; + private final GuiListener listener; + private InventoryCreator creator; + private String title; + private boolean titleUpdated = false; + private final char[] slots; + private int width; + private final GuiElement[] elementSlots; + private final Map elements = new ConcurrentHashMap<>(); + private InventoryType inventoryType; + private final Map inventories = new ConcurrentHashMap<>(); + private InventoryHolder owner; + private final Map pageNumbers = new ConcurrentHashMap<>(); + private final Map pageAmounts = new ConcurrentHashMap<>(); + private GuiElement.Action outsideAction = click -> false; + private CloseAction closeAction = close -> true; + private String clickSound = getDefaultClickSound(); + private boolean silent = false; + + /** + * Added by CustomFishing + */ + public InventoryGui(JavaPlugin plugin, InventoryHolder owner, Component title, String[] rows, GuiElement... elements) { + this(plugin, new InventoryCreator( + (gui, who, type) -> InventoryUtils.createInventory(new Holder(gui), type, title), + (gui, who, size) -> InventoryUtils.createInventory(new Holder(gui), size, title)), + owner, "", rows, elements); + } + + static { + boolean folia; + try { + Class.forName("io.papermc.paper.threadedregions.scheduler.AsyncScheduler"); + folia = true; + } catch (ClassNotFoundException e) { + folia = false; + } + FOLIA = folia; + + // Sound names changed, make it compatible with both versions + String clickSound = null; + Map clickSounds = new LinkedHashMap<>(); + clickSounds.put("UI_BUTTON_CLICK", "ui.button.click"); + clickSounds.put("CLICK", "random.click"); + for (Map.Entry entry : clickSounds.entrySet()) { + try { + // Try to get sound enum to see if it exists + Sound.valueOf(entry.getKey().toUpperCase(Locale.ROOT)); + // If it does use the sound key + clickSound = entry.getValue(); + break; + } catch (IllegalArgumentException ignored) {} + } + if (clickSound == null) { + for (Sound sound : Sound.values()) { + if (sound.name().contains("CLICK")) { + // Convert to sound key under the assumption that the enum name is just using underscores in the place of dots + clickSound = sound.name().toLowerCase(Locale.ROOT).replace('_', '.'); + break; + } + } + } + setDefaultClickSound(clickSound); + } + + /** + * Create a new gui with a certain setup and some elements + * @param plugin Your plugin + * @param creator A creator for the backing inventory + * @param owner The holder that owns this gui to retrieve it with {@link #get(InventoryHolder)}. + * Can be null. + * @param title The name of the GUI. This will be the title of the inventory. + * @param rows How your rows are setup. Each element is getting assigned to a character. + * Empty/missing ones get filled with the Filler. + * @param elements The {@link GuiElement}s that the gui should have. You can also use {@link #addElement(GuiElement)} later. + * @throws IllegalArgumentException Thrown when the provided rows cannot be matched to an InventoryType + */ + public InventoryGui(JavaPlugin plugin, InventoryCreator creator, InventoryHolder owner, String title, String[] rows, GuiElement... elements) { + this.plugin = plugin; + this.creator = creator; + this.owner = owner; + this.title = title; + this.listener = new GuiListener(); + + width = ROW_WIDTHS[0]; + for (String row : rows) { + if (row.length() > width) { + width = row.length(); + } + } + for (int i = 0; i < ROW_WIDTHS.length && i < INVENTORY_TYPES.length; i++) { + if (width < ROW_WIDTHS[i]) { + width = ROW_WIDTHS[i]; + } + if (width == ROW_WIDTHS[i]) { + inventoryType = INVENTORY_TYPES[i]; + break; + } + } + if (inventoryType == null) { + throw new IllegalArgumentException("Could not match row setup to an inventory type!"); + } + + StringBuilder slotsBuilder = new StringBuilder(); + for (String row : rows) { + if (row.length() < width) { + double side = (width - row.length()) / 2.0; + for (int i = 0; i < Math.floor(side); i++) { + slotsBuilder.append(" "); + } + slotsBuilder.append(row); + for (int i = 0; i < Math.ceil(side); i++) { + slotsBuilder.append(" "); + } + } else if (row.length() == width) { + slotsBuilder.append(row); + } else { + slotsBuilder.append(row, 0, width); + } + } + slots = slotsBuilder.toString().toCharArray(); + elementSlots = new GuiElement[slots.length]; + + addElements(elements); + } + + /** + * Create a new gui with a certain setup and some elements + * @param plugin Your plugin + * @param owner The holder that owns this gui to retrieve it with {@link #get(InventoryHolder)}. + * Can be null. + * @param title The name of the GUI. This will be the title of the inventory. + * @param rows How your rows are setup. Each element is getting assigned to a character. + * Empty/missing ones get filled with the Filler. + * @param elements The {@link GuiElement}s that the gui should have. You can also use {@link #addElement(GuiElement)} later. + * @throws IllegalArgumentException Thrown when the provided rows cannot be matched to an InventoryType + */ + @Deprecated + public InventoryGui(JavaPlugin plugin, InventoryHolder owner, String title, String[] rows, GuiElement... elements) { + this(plugin, new InventoryCreator( + (gui, who, type) -> plugin.getServer().createInventory(new Holder(gui), type, gui.replaceVars(who, gui.getTitle())), + (gui, who, size) -> plugin.getServer().createInventory(new Holder(gui), size, gui.replaceVars(who, gui.getTitle()))), + owner, title, rows, elements); + } + + /** + * The simplest way to create a new gui. It has no owner and elements are optional. + * @param plugin Your plugin + * @param title The name of the GUI. This will be the title of the inventory. + * @param rows How your rows are setup. Each element is getting assigned to a character. + * Empty/missing ones get filled with the Filler. + * @param elements The {@link GuiElement}s that the gui should have. You can also use {@link #addElement(GuiElement)} later. + * @throws IllegalArgumentException Thrown when the provided rows cannot be matched to an InventoryType + */ + @Deprecated + public InventoryGui(JavaPlugin plugin, String title, String[] rows, GuiElement... elements) { + this(plugin, null, title, rows, elements); + } + + /** + * Create a new gui that has no owner with a certain setup and some elements + * @param plugin Your plugin + * @param owner The holder that owns this gui to retrieve it with {@link #get(InventoryHolder)}. + * Can be null. + * @param title The name of the GUI. This will be the title of the inventory. + * @param rows How your rows are setup. Each element is getting assigned to a character. + * Empty/missing ones get filled with the Filler. + * @param elements The {@link GuiElement}s that the gui should have. You can also use {@link #addElement(GuiElement)} later. + * @throws IllegalArgumentException Thrown when the provided rows cannot be matched to an InventoryType + */ + @Deprecated + public InventoryGui(JavaPlugin plugin, InventoryHolder owner, String title, String[] rows, Collection elements) { + this(plugin, owner, title, rows); + addElements(elements); + } + + /** + * Directly set the element in a specific slot + * @param element The {@link GuiElement} to add + * @throws IllegalArgumentException Thrown if the provided slot is below 0 or equal/above the available slot count + * @throws IllegalStateException Thrown if the element was already added to a gui + */ + public void setElement(int slot, GuiElement element) { + if (slot < 0 || slot >= elementSlots.length) { + throw new IllegalArgumentException("Provided slots is outside available slots! (" + elementSlots.length + ")"); + } + if (element.getSlots().length > 0 || element.getGui() != null) { + throw new IllegalStateException("Element was already added to a gui!"); + } + element.setSlots(new int[] {slot}); + element.setGui(this); + elementSlots[slot] = element; + } + + /** + * Add an element to the gui with its position directly based on the elements slot char and the gui setup string + * @param element The {@link GuiElement} to add + */ + public void addElement(GuiElement element) { + if (element.getSlots().length > 0 || element.getGui() != null) { + throw new IllegalStateException("Element was already added to a gui!"); + } + elements.put(element.getSlotChar(), element); + element.setGui(this); + int[] slots = getSlots(element.getSlotChar()); + element.setSlots(slots); + for (int slot : slots) { + elementSlots[slot] = element; + } + } + + private int[] getSlots(char slotChar) { + ArrayList slotList = new ArrayList<>(); + for (int i = 0; i < slots.length; i++) { + if (slots[i] == slotChar) { + slotList.add(i); + } + } + return slotList.stream().mapToInt(Integer::intValue).toArray(); + } + + /** + * Create and add a {@link StaticGuiElement} in one quick method. + * @param slotChar The character to specify the elements position based on the gui setup string + * @param item The item that should be displayed + * @param action The {@link net.momirealms.customfishing.libraries.inventorygui.GuiElement.Action} to run when the player clicks on this element + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public void addElement(char slotChar, ItemStack item, GuiElement.Action action, String... text) { + addElement(new StaticGuiElement(slotChar, item, action, text)); + } + + /** + * Create and add a {@link StaticGuiElement} that has no action. + * @param slotChar The character to specify the elements position based on the gui setup string + * @param item The item that should be displayed + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public void addElement(char slotChar, ItemStack item, String... text) { + addElement(new StaticGuiElement(slotChar, item, null, text)); + } + + /** + * Create and add a {@link StaticGuiElement} in one quick method. + * @param slotChar The character to specify the elements position based on the gui setup string + * @param materialData The {@link MaterialData} of the item of tihs element + * @param action The {@link net.momirealms.customfishing.libraries.inventorygui.GuiElement.Action} to run when the player clicks on this element + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public void addElement(char slotChar, MaterialData materialData, GuiElement.Action action, String... text) { + addElement(slotChar, materialData.toItemStack(1), action, text); + } + + /** + * Create and add a {@link StaticGuiElement} + * @param slotChar The character to specify the elements position based on the gui setup string + * @param material The {@link Material} that the item should have + * @param data The byte representation of the material data of this element + * @param action The {@link GuiElement.Action} to run when the player clicks on this element + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public void addElement(char slotChar, Material material, byte data, GuiElement.Action action, String... text) { + addElement(slotChar, new MaterialData(material, data), action, text); + } + + /** + * Create and add a {@link StaticGuiElement} + * @param slotChar The character to specify the elements position based on the gui setup string + * @param material The {@link Material} that the item should have + * @param action The {@link GuiElement.Action} to run when the player clicks on this element + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public void addElement(char slotChar, Material material, GuiElement.Action action, String... text) { + addElement(slotChar, material, (byte) 0, action, text); + } + + /** + * Add multiple elements to the gui with their position based on their slot character + * @param elements The {@link GuiElement}s to add + */ + public void addElements(GuiElement... elements) { + for (GuiElement element : elements) { + addElement(element); + } + } + + /** + * Add multiple elements to the gui with their position based on their slot character + * @param elements The {@link GuiElement}s to add + */ + public void addElements(Collection elements) { + for (GuiElement element : elements) { + addElement(element); + } + } + + /** + * Remove a specific element from this gui. + * @param element The element to remove + * @return Whether or not the gui contained this element and if it was removed + */ + public boolean removeElement(GuiElement element) { + boolean removed = elements.remove(element.getSlotChar(), element); + for (int slot : element.getSlots()) { + if (elementSlots[slot] == element) { + elementSlots[slot] = null; + removed = true; + } + } + return removed; + } + + /** + * Remove the element that is currently assigned to a specific slot char from all slots in the gui + * @param slotChar The char of the slot + * @return The element which was in that slot or null if there was none + */ + public GuiElement removeElement(char slotChar) { + GuiElement element = getElement(slotChar); + if (element != null) { + removeElement(element); + } + return element; + } + + /** + * Remove the element that is currently in a specific slot. Will not remove that element from other slots + * @param slot The slot + * @return The element which was in that slot or null if there was none + */ + public GuiElement removeElement(int slot) { + if (slot < 0 || slot >= elementSlots.length) { + return null; + } + GuiElement element = elementSlots[slot]; + elementSlots[slot] = null; + return element; + } + + /** + * Set the filler element for empty slots + * @param item The item for the filler element + */ + public void setFiller(ItemStack item) { + addElement(new StaticGuiElement(' ', item, " ")); + } + + /** + * Get the filler element + * @return The filler element for empty slots + */ + public GuiElement getFiller() { + return elements.get(' '); + } + + /** + * Get the number of the page that this gui is on. zero indexed. Only affects group elements. + * @param player The Player to query the page number for + * @return The page number + */ + public int getPageNumber(@NotNull HumanEntity player) { + return pageNumbers.getOrDefault(player.getUniqueId(), 0); + } + + /** + * Set the number of the page that this gui is on for all players. zero indexed. Only affects group elements. + * @param pageNumber The page number to set + */ + public void setPageNumber(int pageNumber) { + for (UUID playerId : inventories.keySet()) { + Player player = plugin.getServer().getPlayer(playerId); + if (player != null) { + setPageNumber(player, pageNumber); + } + } + } + + /** + * Set the number of the page that this gui is on for a player. zero indexed. Only affects group elements. + * @param player The player to set the page number for + * @param pageNumber The page number to set + */ + public void setPageNumber(HumanEntity player, int pageNumber) { + setPageNumberInternal(player, pageNumber); + draw(player, false); + } + + private void setPageNumberInternal(HumanEntity player, int pageNumber) { + pageNumbers.put(player.getUniqueId(), Math.max(pageNumber, 0)); + } + + /** + * Get the amount of pages that this GUI has for a certain player + * @param player The Player to query the page amount for + * @return The amount of pages + */ + public int getPageAmount(@NotNull HumanEntity player) { + return pageAmounts.getOrDefault(player.getUniqueId(), 1); + } + + /** + * Set the amount of pages that this GUI has for a certain player + * @param player The Player to query the page amount for + * @param pageAmount The page amount + */ + private void setPageAmount(HumanEntity player, int pageAmount) { + pageAmounts.put(player.getUniqueId(), pageAmount); + } + + private void calculatePageAmount(HumanEntity player) { + int pageAmount = 0; + for (GuiElement element : elements.values()) { + int amount = calculateElementSize(player, element); + if (amount > 0 && (pageAmount - 1) * element.getSlots().length < amount && element.getSlots().length > 0) { + pageAmount = (int) Math.ceil((double) amount / element.getSlots().length); + } + } + setPageAmount(player, pageAmount); + if (getPageNumber(player) >= pageAmount) { + setPageNumberInternal(player, Math.min(0, pageAmount - 1)); + } + } + + private int calculateElementSize(HumanEntity player, GuiElement element) { + if (element instanceof GuiElementGroup) { + return ((GuiElementGroup) element).size(); + } else if (element instanceof GuiStorageElement) { + return ((GuiStorageElement) element).getStorage().getSize(); + } else if (element instanceof DynamicGuiElement) { + return calculateElementSize(player, ((DynamicGuiElement) element).getCachedElement(player)); + } + return 0; + } + + /** + * Show this GUI to a player + * @param player The Player to show the GUI to + */ + public void show(HumanEntity player) { + show(player, true); + } + + /** + * Show this GUI to a player + * @param player The Player to show the GUI to + * @param checkOpen Whether or not it should check if this gui is already open + */ + public void show(HumanEntity player, boolean checkOpen) { + // Draw the elements into an inventory, if the title was updated then also force-recreate the inventory if it exists + draw(player, true, titleUpdated); + if (titleUpdated || !checkOpen || !this.equals(getOpen(player))) { + InventoryType type = player.getOpenInventory().getType(); + if (type != InventoryType.CRAFTING && type != InventoryType.CREATIVE) { + // If the player already has a gui open then we assume that the call was from that gui. + // In order to not close it in a InventoryClickEvent listener (which will lead to errors) + // we delay the opening for one tick to run after it finished processing the event + runTask(player, () -> { + Inventory inventory = getInventory(player); + if (inventory != null) { + addHistory(player, this); + player.openInventory(inventory); + } + }); + } else { + Inventory inventory = getInventory(player); + if (inventory != null) { + clearHistory(player); + addHistory(player, this); + player.openInventory(inventory); + } + } + } + // Reset the field that indicates that the title changed + titleUpdated = false; + } + + /** + * Build the gui + */ + public void build() { + build(owner); + } + + /** + * Set the gui's owner and build it + * @param owner The {@link InventoryHolder} that owns the gui + */ + public void build(InventoryHolder owner) { + setOwner(owner); + listener.registerListeners(); + } + + /** + * Draw the elements in the inventory. This can be used to manually refresh the gui. Updates any dynamic elements. + */ + public void draw() { + for (UUID playerId : inventories.keySet()) { + Player player = plugin.getServer().getPlayer(playerId); + if (player != null) { + runTaskOrNow(player, () -> draw(player)); + } + } + } + + /** + * Draw the elements in the inventory. This can be used to manually refresh the gui. Updates any dynamic elements. + * @param who For who to draw the GUI + */ + public void draw(HumanEntity who) { + draw(who, true); + } + + /** + * Draw the elements in the inventory. This can be used to manually refresh the gui. + * @param who For who to draw the GUI + * @param updateDynamic Update dynamic elements + */ + public void draw(HumanEntity who, boolean updateDynamic) { + draw(who, updateDynamic, false); + } + + /** + * Draw the elements in the inventory. This can be used to manually refresh the gui. + * @param who For who to draw the GUI + * @param updateDynamic Update dynamic elements + * @param recreateInventory Recreate the inventory + */ + public void draw(HumanEntity who, boolean updateDynamic, boolean recreateInventory) { + if (updateDynamic) { + updateElements(who, elements.values()); + } + calculatePageAmount(who); + Inventory inventory = getInventory(who); + if (inventory == null || recreateInventory) { + build(); + if (slots.length != inventoryType.getDefaultSize()) { + inventory = getInventoryCreator().getSizeCreator().create(this, who, slots.length); + } else { + inventory = getInventoryCreator().getTypeCreator().create(this, who, inventoryType); + } + inventories.put(who != null ? who.getUniqueId() : null, inventory); + } else { + inventory.clear(); + } + for (int i = 0; i < inventory.getSize(); i++) { + GuiElement element = getElement(i); + if (element == null) { + element = getFiller(); + } + if (element != null) { + inventory.setItem(i, element.getItem(who, i)); + } + } + } + + /** + * Schedule a task on a {@link HumanEntity}/main thread to run on the next tick + * @param entity the human entity to schedule a task on + * @param task the task to be run + */ + protected void runTask(HumanEntity entity, Runnable task) { + if (FOLIA) { + entity.getScheduler().run(plugin, st -> task.run(), null); + } else { + plugin.getServer().getScheduler().runTask(plugin, task); + } + } + + /** + * Schedule a task on the global region/main thread to run on the next tick + * @param task the task to be run + */ + protected void runTask(Runnable task) { + if (FOLIA) { + plugin.getServer().getGlobalRegionScheduler().run(plugin, st -> task.run()); + } else { + plugin.getServer().getScheduler().runTask(plugin, task); + } + } + + /** + * Schedule a task on a {@link HumanEntity} to run on the next tick + * Alternatively if the current thread is already the right thread, execute immediately + * @param entity the human entity to schedule a task on + * @param task the task to be run + */ + protected void runTaskOrNow(HumanEntity entity, Runnable task) { + if (FOLIA) { + if (plugin.getServer().isOwnedByCurrentRegion(entity)) { + task.run(); + } else { + entity.getScheduler().run(plugin, st -> task.run(), null); + } + } else { + if (plugin.getServer().isPrimaryThread()) { + task.run(); + } else { + plugin.getServer().getScheduler().runTask(plugin, task); + } + } + } + + /** + * Update all dynamic elements in a collection of elements. + * @param who The player to update the elements for + * @param elements The elements to update + */ + public static void updateElements(HumanEntity who, Collection elements) { + for (GuiElement element : elements) { + if (element instanceof DynamicGuiElement) { + ((DynamicGuiElement) element).update(who); + } else if (element instanceof GuiElementGroup) { + updateElements(who, ((GuiElementGroup) element).getElements()); + } + } + } + + /** + * Closes the GUI for everyone viewing it + */ + public void close() { + close(true); + } + + /** + * Close the GUI for everyone viewing it + * @param clearHistory Whether to close the GUI completely (by clearing the history) + */ + public void close(boolean clearHistory) { + for (Inventory inventory : inventories.values()) { + for (HumanEntity viewer : new ArrayList<>(inventory.getViewers())) { + close(viewer, clearHistory); + } + } + } + + /** + * Closes the GUI for a specific viewer it + * @param viewer The player viewing it + */ + public void close(HumanEntity viewer) { + close(viewer, true); + } + + /** + * Closes the GUI for a specific viewer it + * @param viewer The player viewing it + * @param clearHistory Whether to close the GUI completely (by clearing the history) + */ + public void close(HumanEntity viewer, boolean clearHistory) { + if (clearHistory) { + clearHistory(viewer); + } + viewer.closeInventory(); + } + + /** + * Destroy this GUI. This unregisters all listeners and removes it from the GUI_MAP + */ + public void destroy() { + destroy(true); + } + + private void destroy(boolean closeInventories) { + if (closeInventories) { + close(); + } + for (Inventory inventory : inventories.values()) { + inventory.clear(); + } + inventories.clear(); + pageNumbers.clear(); + pageAmounts.clear(); + listener.unregisterListeners(); + removeFromMap(); + } + + /** + * Add a new history entry to the end of the history + * @param player The player to add the history entry for + * @param gui The GUI to add to the history + */ + public static void addHistory(HumanEntity player, InventoryGui gui) { + GUI_HISTORY.putIfAbsent(player.getUniqueId(), new ArrayDeque<>()); + Deque history = getHistory(player); + if (history.peekLast() != gui) { + history.add(gui); + } + } + + /** + * Get the history of a player + * @param player The player to get the history for + * @return The history as a deque of InventoryGuis; + * returns an empty one and not null! + */ + public static Deque getHistory(HumanEntity player) { + return GUI_HISTORY.getOrDefault(player.getUniqueId(), new ArrayDeque<>()); + } + + /** + * Go back one entry in the history + * @param player The player to show the previous gui to + * @return true if there was a gui to show; false if not + */ + public static boolean goBack(HumanEntity player) { + Deque history = getHistory(player); + history.pollLast(); + if (history.isEmpty()) { + return false; + } + InventoryGui previous = history.peekLast(); + if (previous != null) { + previous.show(player, false); + } + return true; + } + + /** + * Clear the history of a player + * @param player The player to clear the history for + * @return The history + */ + public static Deque clearHistory(HumanEntity player) { + Deque previous = GUI_HISTORY.remove(player.getUniqueId()); + return previous != null ? previous : new ArrayDeque<>(); + } + + /** + * Get the plugin which owns this GUI. Should be the one who created it. + * @return The plugin which owns this GUI + */ + public JavaPlugin getPlugin() { + return plugin; + } + + /** + * Get the helper class which will create the custom inventory for this gui. + * Simply uses {@link org.bukkit.Bukkit#createInventory(InventoryHolder, int, String)} by default. + * @return The used inventory creator instance + */ + public InventoryCreator getInventoryCreator() { + return creator; + } + + /** + * Set the helper class which will create the custom inventory for this gui. + * Can be used to create more special inventories. + * Simply uses {@link org.bukkit.Bukkit#createInventory(InventoryHolder, int, String)} by default. + * Should return a container inventory that can hold the size. Special inventories will break stuff. + * @param creator The new inventory creator instance + */ + public void setInventoryCreator(InventoryCreator creator) { + this.creator = creator; + } + + /** + * Get element in a certain slot + * @param slot The slot to get the element from + * @return The GuiElement or null if the slot is empty/there wasn't one + */ + public GuiElement getElement(int slot) { + return slot < 0 || slot >= elementSlots.length ? null : elementSlots[slot]; + } + + /** + * Get an element by its character + * @param c The character to get the element by + * @return The GuiElement or null if there is no element for that character + */ + public GuiElement getElement(char c) { + return elements.get(c); + } + + /** + * Get all elements of this gui. This collection is immutable, use the addElement and removeElement methods + * to modify the elements in this gui. + * @return An immutable collection of all elements in this group + */ + public Collection getElements() { + return Collections.unmodifiableCollection(elements.values()); + } + + /** + * Set the owner of this GUI. Will remove the previous assignment. + * @param owner The owner of the GUI + */ + public void setOwner(InventoryHolder owner) { + removeFromMap(); + this.owner = owner; + if (owner instanceof Entity) { + GUI_MAP.put(((Entity) owner).getUniqueId().toString(), this); + } else if (owner instanceof BlockState) { + GUI_MAP.put(((BlockState) owner).getLocation().toString(), this); + } + } + + /** + * Get the owner of this GUI. Will be null if th GUI doesn't have one + * @return The InventoryHolder of this GUI + */ + public InventoryHolder getOwner() { + return owner; + } + + /** + * Check whether or not the Owner of this GUI is real or fake + * @return true if the owner is a real world InventoryHolder; false if it is null + */ + public boolean hasRealOwner() { + return owner != null; + } + + /** + * Get the Action that is run when clicked outside of the inventory + * @return The Action for when the player clicks outside the inventory; can be null + */ + public GuiElement.Action getOutsideAction() { + return outsideAction; + } + + /** + * Set the Action that is run when clicked outside of the inventory + * @param outsideAction The Action for when the player clicks outside the inventory; can be null + */ + public void setOutsideAction(GuiElement.Action outsideAction) { + this.outsideAction = outsideAction; + } + + /** + * Get the action that is run when this GUI is closed + * @return The action for when the player closes this inventory; can be null + */ + public CloseAction getCloseAction() { + return closeAction; + } + + /** + * Set the action that is run when this GUI is closed; it should return true if the GUI should go back + * @param closeAction The action for when the player closes this inventory; can be null + */ + public void setCloseAction(CloseAction closeAction) { + this.closeAction = closeAction; + } + + /** + * Get the click sound to use for non-silent GUIs that don't have a specific one set + * @return The default click sound, if set null no sound will play + */ + public static String getDefaultClickSound() { + return DEFAULT_CLICK_SOUND; + } + + /** + * Set the click sound to use for non-silent GUIs that don't have a specific one set + * @param defaultClickSound The default click sound, if set to null no sound will play + */ + public static void setDefaultClickSound(String defaultClickSound) { + DEFAULT_CLICK_SOUND = defaultClickSound; + } + + /** + * Set the sound that plays when a button (that isn't preventing the item from being taken) is clicked in the GUI. + * Fillers will not play a click sound + * @return The key of the sound to play + */ + public String getClickSound() { + return clickSound; + } + + /** + * Set the sound that plays when a button (that isn't preventing the item from being taken) is clicked in the GUI. + * Fillers will not play a click sound + * @param soundKey The key of the sound to play, if null then no sound will play (same effect as {@link #setSilent(boolean)}) + */ + public void setClickSound(String soundKey) { + clickSound = soundKey; + } + + /** + * Get whether or not this GUI should make a sound when interacting with elements that make sound + * @return Whether or not to make a sound when interacted with + */ + public boolean isSilent() { + return silent; + } + + /** + * Set whether or not this GUI should make a sound when interacting with elements that make sound + * @param silent Whether or not to make a sound when interacted with + */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + private void removeFromMap() { + if (owner instanceof Entity) { + GUI_MAP.remove(((Entity) owner).getUniqueId().toString(), this); + } else if (owner instanceof BlockState) { + GUI_MAP.remove(((BlockState) owner).getLocation().toString(), this); + } + } + + /** + * Get the GUI registered to an InventoryHolder + * @param holder The InventoryHolder to get the GUI for + * @return The InventoryGui registered to it or null if none was registered to it + */ + public static InventoryGui get(InventoryHolder holder) { + if (holder instanceof Entity) { + return GUI_MAP.get(((Entity) holder).getUniqueId().toString()); + } else if (holder instanceof BlockState) { + return GUI_MAP.get(((BlockState) holder).getLocation().toString()); + } + return null; + } + + /** + * Get the GUI that a player has currently open + * @param player The Player to get the GUI for + * @return The InventoryGui that the player has open + */ + public static InventoryGui getOpen(HumanEntity player) { + return getHistory(player).peekLast(); + } + + /** + * Get the title of the gui + * @return The title of the gui + */ + public String getTitle() { + return title; + } + + /** + * Set the title of the gui + * @param title The {@link String} that should be the title of the gui + */ + public void setTitle(String title) { + this.title = title; + this.titleUpdated = true; + } + + /** + * Play a click sound e.g. when an element acts as a button + */ + public void playClickSound() { + if (isSilent() || clickSound == null) return; + for (Inventory inventory : inventories.values()) { + for (HumanEntity humanEntity : inventory.getViewers()) { + if (humanEntity instanceof Player) { + ((Player) humanEntity).playSound(humanEntity.getEyeLocation(), getClickSound(), 1, 1); + } + } + } + } + + /** + * Get the inventory. Package scope as it should only be used by InventoryGui.Holder + * @return The GUI's generated inventory + */ + Inventory getInventory() { + return getInventory(null); + } + + /** + * Get the inventory of a certain player + * @param who The player, if null it will try to return the inventory created first or null if none was created + * @return The GUI's generated inventory, null if none was found + */ + private Inventory getInventory(HumanEntity who) { + return who != null ? inventories.get(who.getUniqueId()) : (inventories.isEmpty() ? null : inventories.values().iterator().next()); + } + + /** + * Get the width of the GUI in slots + * @return The width of the GUI + */ + int getWidth() { + return width; + } + + /** + * Handle interaction with a slot in this GUI + * @param event The event that triggered it + * @param clickType The type of click + * @param slot The slot + * @param cursor The item on the cursor + * @return The resulting click object + */ + private GuiElement.Click handleInteract(InventoryInteractEvent event, ClickType clickType, int slot, ItemStack cursor) { + GuiElement.Action action = null; + GuiElement element = null; + if (slot >= 0) { + element = getElement(slot); + if (element != null) { + action = element.getAction(event.getWhoClicked()); + } + } else if (slot == -999) { + action = outsideAction; + } else { + if (event instanceof InventoryClickEvent) { + // Click was neither for the top inventory nor outside + // E.g. click is in the bottom inventory + if (((InventoryClickEvent) event).getAction() == InventoryAction.COLLECT_TO_CURSOR) { + GuiElement.Click click = new GuiElement.Click(this, slot, clickType, cursor, null, event); + simulateCollectToCursor(click); + return click; + } else if (((InventoryClickEvent) event).getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) { + // This was an action we can't handle, abort + event.setCancelled(true); + } + } + return null; + } + try { + GuiElement.Click click = new GuiElement.Click(this, slot, clickType, cursor, element, event); + if (action == null || action.onClick(click)) { + event.setCancelled(true); + if (event.getWhoClicked() instanceof Player) { + ((Player) event.getWhoClicked()).updateInventory(); + } + } + if (action != null) { + // Let's assume something changed and re-draw all currently shown inventories + for (UUID playerId : inventories.keySet()) { + if (!event.getWhoClicked().getUniqueId().equals(playerId)) { + Player player = plugin.getServer().getPlayer(playerId); + if (player != null) { + draw(player, false); + } + } + } + return click; + } + } catch (Throwable t) { + event.setCancelled(true); + if (event.getWhoClicked() instanceof Player) { + ((Player) event.getWhoClicked()).updateInventory(); + } + plugin.getLogger().log(Level.SEVERE, "Exception while trying to run action for click on " + + (element != null ? element.getClass().getSimpleName() : "empty element") + + " in slot " + slot + " of " + getTitle() + " GUI!"); + t.printStackTrace(); + } + return null; + } + + private abstract class UnregisterableListener implements Listener { + private final List listeners; + private boolean listenersRegistered = false; + + private UnregisterableListener() { + List listeners = new ArrayList<>(); + for (Class innerClass : getClass().getDeclaredClasses()) { + if (UnregisterableListener.class.isAssignableFrom(innerClass)) { + try { + UnregisterableListener listener = ((Class) innerClass).getDeclaredConstructor(getClass()).newInstance(this); + if (!(listener instanceof OptionalListener) || ((OptionalListener) listener).isCompatible()) { + listeners.add(listener); + } + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + e.printStackTrace(); + } + } + } + this.listeners = Collections.unmodifiableList(listeners); + } + + protected void registerListeners() { + if (listenersRegistered) { + return; + } + plugin.getServer().getPluginManager().registerEvents(this, plugin); + for (UnregisterableListener listener : listeners) { + listener.registerListeners(); + } + listenersRegistered = true; + } + + protected void unregisterListeners() { + HandlerList.unregisterAll(this); + for (UnregisterableListener listener : listeners) { + listener.unregisterListeners(); + } + listenersRegistered = false; + } + } + + private abstract class OptionalListener extends UnregisterableListener { + private boolean isCompatible() { + try { + getClass().getMethods(); + getClass().getDeclaredMethods(); + return true; + } catch (NoClassDefFoundError e) { + return false; + } + } + } + + /** + * All the listeners that InventoryGui needs to work + */ + private class GuiListener extends UnregisterableListener { + + @EventHandler(ignoreCancelled = true) + private void onInventoryClick(InventoryClickEvent event) { + if (event.getInventory().equals(getInventory(event.getWhoClicked()))) { + + int slot = -1; + if (event.getRawSlot() < event.getView().getTopInventory().getSize()) { + slot = event.getRawSlot(); + } else if (event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) { + slot = event.getInventory().firstEmpty(); + } + + // Cache the original cursor + ItemStack originalCursor = event.getCursor() != null ? event.getCursor().clone() : null; + + // Forward the click + GuiElement.Click click = handleInteract(event, event.getClick(), slot, event.getCursor()); + + // Update the cursor if necessary + if (click != null && (originalCursor == null || !originalCursor.equals(click.getCursor()))) { + event.setCursor(click.getCursor()); + } + } else if (hasRealOwner() && owner.equals(event.getInventory().getHolder())) { + // Click into inventory by same owner but not the inventory of the GUI + // Assume that the underlying inventory changed and redraw the GUI + runTask(InventoryGui.this::draw); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onInventoryDrag(InventoryDragEvent event) { + Inventory inventory = getInventory(event.getWhoClicked()); + if (event.getInventory().equals(inventory)) { + // Check if we only drag over one slot if so then handle that as a click with the element + if (event.getRawSlots().size() == 1) { + int slot = event.getRawSlots().iterator().next(); + if (slot < event.getView().getTopInventory().getSize()) { + GuiElement.Click click = handleInteract( + event, + // Map drag type to the button that caused it + event.getType() == DragType.SINGLE ? ClickType.RIGHT : ClickType.LEFT, + slot, + event.getOldCursor() + ); + + // Update the cursor if necessary + if (click != null && !event.getOldCursor().equals(click.getCursor())) { + event.setCursor(click.getCursor()); + } + } + return; + } + + int rest = 0; + Map resetSlots = new HashMap<>(); + for (Map.Entry items : event.getNewItems().entrySet()) { + if (items.getKey() < inventory.getSize()) { + GuiElement element = getElement(items.getKey()); + if (!(element instanceof GuiStorageElement) + || !((GuiStorageElement) element).setStorageItem(event.getWhoClicked(), items.getKey(), items.getValue())) { + ItemStack slotItem = event.getInventory().getItem(items.getKey()); + if (!items.getValue().isSimilar(slotItem)) { + rest += items.getValue().getAmount(); + } else if (slotItem != null) { + rest += items.getValue().getAmount() - slotItem.getAmount(); + } + //items.getValue().setAmount(0); // can't change resulting items :/ + resetSlots.put(items.getKey(), event.getInventory().getItem(items.getKey())); // reset them manually + } + } + } + + runTask(event.getWhoClicked(), () -> { + for (Map.Entry items : resetSlots.entrySet()) { + event.getView().getTopInventory().setItem(items.getKey(), items.getValue()); + } + }); + + if (rest > 0) { + int cursorAmount = event.getCursor() != null ? event.getCursor().getAmount() : 0; + if (!event.getOldCursor().isSimilar(event.getCursor())) { + event.setCursor(event.getOldCursor()); + cursorAmount = 0; + } + int newCursorAmount = cursorAmount + rest; + if (newCursorAmount <= event.getCursor().getMaxStackSize()) { + event.getCursor().setAmount(newCursorAmount); + } else { + event.getCursor().setAmount(event.getCursor().getMaxStackSize()); + ItemStack add = event.getCursor().clone(); + int addAmount = newCursorAmount - event.getCursor().getMaxStackSize(); + if (addAmount > 0) { + add.setAmount(addAmount); + for (ItemStack drop : event.getWhoClicked().getInventory().addItem(add).values()) { + event.getWhoClicked().getLocation().getWorld().dropItem(event.getWhoClicked().getLocation(), drop); + } + } + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onInventoryClose(InventoryCloseEvent event) { + Inventory inventory = getInventory(event.getPlayer()); + if (event.getInventory().equals(inventory)) { + // go back. that checks if the player is in gui and has history + if (InventoryGui.this.equals(getOpen(event.getPlayer()))) { + if (closeAction == null || closeAction.onClose(new Close(event.getPlayer(), InventoryGui.this, event))) { + goBack(event.getPlayer()); + } else { + clearHistory(event.getPlayer()); + } + } + if (inventories.size() <= 1) { + destroy(false); + } else { + inventory.clear(); + for (HumanEntity viewer : inventory.getViewers()) { + if (viewer != event.getPlayer()) { + viewer.closeInventory(); + } + } + inventories.remove(event.getPlayer().getUniqueId()); + pageAmounts.remove(event.getPlayer().getUniqueId()); + pageNumbers.remove(event.getPlayer().getUniqueId()); + for (GuiElement element : getElements()) { + if (element instanceof DynamicGuiElement) { + ((DynamicGuiElement) element).removeCachedElement(event.getPlayer()); + } + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInventoryMoveItem(InventoryMoveItemEvent event) { + if (hasRealOwner() && (owner.equals(event.getDestination().getHolder()) || owner.equals(event.getSource().getHolder()))) { + runTask(InventoryGui.this::draw); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onDispense(BlockDispenseEvent event) { + if (hasRealOwner() && owner.equals(event.getBlock().getState())) { + runTask(InventoryGui.this::draw); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + if (hasRealOwner() && owner.equals(event.getBlock().getState())) { + destroy(); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onEntityDeath(EntityDeathEvent event) { + if (hasRealOwner() && owner.equals(event.getEntity())) { + destroy(); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPluginDisable(PluginDisableEvent event) { + if (event.getPlugin() == plugin) { + destroy(); + } + } + + /** + * Event isn't available on older version so just use a separate listener... + */ + protected class ItemSwapGuiListener extends OptionalListener { + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onInventoryMoveItem(PlayerSwapHandItemsEvent event) { + Inventory inventory = getInventory(event.getPlayer()); + if (event.getPlayer().getOpenInventory().getTopInventory().equals(inventory)) { + event.setCancelled(true); + } + } + } + } + + /** + * Fake InventoryHolder for the GUIs + */ + public static class Holder implements InventoryHolder { + private InventoryGui gui; + + public Holder(InventoryGui gui) { + this.gui = gui; + } + + @Override + public Inventory getInventory() { + return gui.getInventory(); + } + + public InventoryGui getGui() { + return gui; + } + } + + public static interface CloseAction { + + /** + * Executed when a player closes a GUI inventory + * @param close The close object holding information about this close + * @return Whether or not the close should go back or not + */ + boolean onClose(Close close); + + } + + public static class Close { + private final HumanEntity player; + private final InventoryGui gui; + private final InventoryCloseEvent event; + + public Close(HumanEntity player, InventoryGui gui, InventoryCloseEvent event) { + this.player = player; + this.gui = gui; + this.event = event; + } + + public HumanEntity getPlayer() { + return player; + } + + public InventoryGui getGui() { + return gui; + } + + public InventoryCloseEvent getEvent() { + return event; + } + } + + /** + * Set the text of an item using the display name and the lore. + * Also replaces any placeholders in the text and filters out empty lines. + * Use a single space to create an emtpy line. + * @param item The {@link ItemStack} to set the text for + * @param text The text lines to set + * @deprecated Use {@link #setItemText(HumanEntity, ItemStack, String...)} + */ + @Deprecated + public void setItemText(ItemStack item, String... text) { + setItemText(null, item, text); + } + + /** + * Set the text of an item using the display name and the lore. + * Also replaces any placeholders in the text and filters out empty lines. + * Use a single space to create an emtpy line. + * @param player The player viewing the GUI + * @param item The {@link ItemStack} to set the text for + * @param text The text lines to set + */ + public void setItemText(HumanEntity player, ItemStack item, String... text) { + if (item != null && text != null && text.length > 0) { + ItemMeta meta = item.getItemMeta(); + if (meta != null) { + String combined = replaceVars(player, Arrays.stream(text) + .map(s -> s == null ? " " : s) + .filter(s -> !s.isEmpty()) + .collect(Collectors.joining("\n"))); + String[] lines = combined.split("\n"); + if (text[0] != null) { + meta.setDisplayName(lines[0]); + } + if (lines.length > 1) { + meta.setLore(Arrays.asList(Arrays.copyOfRange(lines, 1, lines.length))); + } else { + meta.setLore(null); + } + item.setItemMeta(meta); + } + } + } + + /** + * Replace some placeholders in the with values regarding the gui's state. Replaced color codes.
+ * The placeholders are:
+ * %plugin% - The name of the plugin that this gui is from.
+ * %owner% - The name of the owner of this gui. Will be an empty string when the owner is null.
+ * %title% - The title of this GUI.
+ * %page% - The current page that this gui is on.
+ * %nextpage% - The next page. "none" if there is no next page.
+ * %prevpage% - The previous page. "none" if there is no previous page.
+ * %pages% - The amount of pages that this gui has. + * @param text The text to replace the placeholders in + * @param replacements Additional repplacements. i = placeholder, i+1 = replacements + * @return The text with all placeholders replaced + * @deprecated Use {@link #replaceVars(HumanEntity, String, String...)} + */ + @Deprecated + public String replaceVars(String text, String... replacements) { + return replaceVars(null, text, replacements); + } + + /** + * Replace some placeholders in the with values regarding the gui's state. Replaced color codes.
+ * The placeholders are:
+ * %plugin% - The name of the plugin that this gui is from.
+ * %owner% - The name of the owner of this gui. Will be an empty string when the owner is null.
+ * %title% - The title of this GUI.
+ * %page% - The current page that this gui is on.
+ * %nextpage% - The next page. "none" if there is no next page.
+ * %prevpage% - The previous page. "none" if there is no previous page.
+ * %pages% - The amount of pages that this gui has. + * @param player The player viewing the GUI + * @param text The text to replace the placeholders in + * @param replacements Additional repplacements. i = placeholder, i+1 = replacements + * @return The text with all placeholders replaced + */ + public String replaceVars(HumanEntity player, String text, String... replacements) { + Map map = new LinkedHashMap<>(); + for (int i = 0; i + 1 < replacements.length; i += 2) { + map.putIfAbsent(replacements[i], replacements[i + 1]); + } + + map.putIfAbsent("plugin", plugin.getName()); + try { + map.putIfAbsent("owner", owner instanceof Nameable ? ((Nameable) owner).getCustomName() : ""); + } catch (NoSuchMethodError | NoClassDefFoundError e) { + map.putIfAbsent("owner", owner instanceof Entity ? ((Entity) owner).getCustomName() : ""); + } + map.putIfAbsent("title", title); + map.putIfAbsent("page", String.valueOf(getPageNumber(player) + 1)); + map.putIfAbsent("nextpage", getPageNumber(player) + 1 < getPageAmount(player) ? String.valueOf(getPageNumber(player) + 2) : "none"); + map.putIfAbsent("prevpage", getPageNumber(player) > 0 ? String.valueOf(getPageNumber(player)) : "none"); + map.putIfAbsent("pages", String.valueOf(getPageAmount(player))); + + return ChatColor.translateAlternateColorCodes('&', replace(text, map)); + } + + /** + * Replace placeholders in a string + * @param string The string to replace in + * @param replacements What to replace the placeholders with. The n-th index is the placeholder, the n+1-th the value. + * @return The string with all placeholders replaced (using the configured placeholder prefix and suffix) + */ + private String replace(String string, Map replacements) { + for (Map.Entry entry : replacements.entrySet()) { + if (entry.getKey() == null) { + continue; + } + String placeholder = "%" + entry.getKey() + "%"; + Pattern pattern = PATTERN_CACHE.get(placeholder); + if (pattern == null) { + PATTERN_CACHE.put(placeholder, pattern = Pattern.compile(placeholder, Pattern.LITERAL)); + } + string = pattern.matcher(string).replaceAll(Matcher.quoteReplacement(entry.getValue() != null ? entry.getValue() : "null")); + } + return string; + } + + /** + * Simulate the collecting to the cursor while respecting elements that can't be modified + * @param click The click that startet it all + */ + void simulateCollectToCursor(GuiElement.Click click) { + if (!(click.getRawEvent() instanceof InventoryClickEvent)) { + // Only a click event can trigger the collection to the cursor + return; + } + InventoryClickEvent event = (InventoryClickEvent) click.getRawEvent(); + + ItemStack newCursor = click.getCursor().clone(); + + boolean itemInGui = false; + for (int i = 0; i < click.getRawEvent().getView().getTopInventory().getSize(); i++) { + if (i != event.getRawSlot()) { + ItemStack viewItem = click.getRawEvent().getView().getTopInventory().getItem(i); + if (newCursor.isSimilar(viewItem)) { + itemInGui = true; + } + GuiElement element = getElement(i); + if (element instanceof GuiStorageElement) { + GuiStorageElement storageElement = (GuiStorageElement) element; + ItemStack otherStorageItem = storageElement.getStorageItem(click.getWhoClicked(), i); + if (addToStack(newCursor, otherStorageItem)) { + if (otherStorageItem.getAmount() == 0) { + otherStorageItem = null; + } + storageElement.setStorageItem(i, otherStorageItem); + if (newCursor.getAmount() == newCursor.getMaxStackSize()) { + break; + } + } + } + } + } + + if (itemInGui) { + event.setCurrentItem(null); + click.getRawEvent().setCancelled(true); + if (click.getRawEvent().getWhoClicked() instanceof Player) { + ((Player) click.getRawEvent().getWhoClicked()).updateInventory(); + } + + if (click.getElement() instanceof GuiStorageElement) { + ((GuiStorageElement) click.getElement()).setStorageItem(click.getWhoClicked(), click.getSlot(), null); + } + + if (newCursor.getAmount() < newCursor.getMaxStackSize()) { + Inventory bottomInventory = click.getRawEvent().getView().getBottomInventory(); + for (ItemStack bottomIem : bottomInventory) { + if (addToStack(newCursor, bottomIem)) { + if (newCursor.getAmount() == newCursor.getMaxStackSize()) { + break; + } + } + } + } + event.setCursor(newCursor); + draw(); + } + } + + /** + * Add items to a stack up to the max stack size + * @param item The base item + * @param add The item stack to add + * @return true if the stack is finished; false if these stacks can't be merged + */ + private static boolean addToStack(ItemStack item, ItemStack add) { + if (item.isSimilar(add)) { + int newAmount = item.getAmount() + add.getAmount(); + if (newAmount >= item.getMaxStackSize()) { + item.setAmount(item.getMaxStackSize()); + add.setAmount(newAmount - item.getAmount()); + } else { + item.setAmount(newAmount); + add.setAmount(0); + } + return true; + } + return false; + } + + public static class InventoryCreator { + private final CreatorImplementation typeCreator; + private final CreatorImplementation sizeCreator; + + /** + * A new inventory creator which should be able to create an inventory based on the type and the size. + *

+ * By default the creators are implemented as follows: + *
+         * typeCreator = (gui, who, type) -> plugin.getServer().createInventory(new Holder(gui), type, gui.replaceVars(who, title));
+         * sizeCreator = (gui, who, size) -> plugin.getServer().createInventory(new Holder(gui), size, gui.replaceVars(who, title));
+         * 
+ * @param typeCreator The type creator. + * @param sizeCreator The size creator + */ + public InventoryCreator(CreatorImplementation typeCreator, CreatorImplementation sizeCreator) { + this.typeCreator = typeCreator; + this.sizeCreator = sizeCreator; + } + + public CreatorImplementation getTypeCreator() { + return typeCreator; + } + + public CreatorImplementation getSizeCreator() { + return sizeCreator; + } + + public interface CreatorImplementation { + /** + * Creates a new inventory + * @param gui The InventoryGui instance + * @param who The player to create the inventory for + * @param t The size or type of the inventory + * @return The created inventory + */ + Inventory create(InventoryGui gui, HumanEntity who, T t); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/StaticGuiElement.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/StaticGuiElement.java new file mode 100644 index 00000000..c6a23269 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/inventorygui/StaticGuiElement.java @@ -0,0 +1,159 @@ +package net.momirealms.customfishing.libraries.inventorygui; + +/* + * Copyright 2017 Max Lee (https://github.com/Phoenix616) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; + +/** + * Represents a simple element in a gui to which an action can be assigned. + * If you want the item to change on click you have to do that yourself. + */ +public class StaticGuiElement extends GuiElement { + private ItemStack item; + private int number; + private String[] text; + + /** + * Represents an element in a gui + * @param slotChar The character to replace in the gui setup string + * @param item The item this element displays + * @param number The number, 1 will not display the number + * @param action The action to run when the player clicks on this element + * @param text The text to display on this element, placeholders are automatically + * replaced, see for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + * @throws IllegalArgumentException If the number is below 1 or above the max stack count (currently 64) + */ + public StaticGuiElement(char slotChar, ItemStack item, int number, Action action, String... text) throws IllegalArgumentException { + super(slotChar, action); + this.item = item; + this.text = text; + setNumber(number); + } + + /** + * Represents an element in a gui + * @param slotChar The character to replace in the gui setup string + * @param item The item this element displays + * @param action The action to run when the player clicks on this element + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public StaticGuiElement(char slotChar, ItemStack item, Action action, String... text) { + this(slotChar, item, item != null ? item.getAmount() : 1, action, text); + } + + /** + * Represents an element in a gui that doesn't have any action when clicked + * @param slotChar The character to replace in the gui setup string + * @param item The item this element displays + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public StaticGuiElement(char slotChar, ItemStack item, String... text) { + this(slotChar, item, item != null ? item.getAmount() : 1, null, text); + } + + + /** + * Set the item that is displayed by this element + * @param item The item that should be displayed by this element + */ + public void setItem(ItemStack item) { + this.item = item; + } + + /** + * Get the raw item displayed by this element which was passed to the constructor or set with {@link #setItem(ItemStack)}. + * This item will not have the amount or text applied! Use {@link #getItem(HumanEntity, int)} for that! + * @return The raw item + */ + public ItemStack getRawItem() { + return item; + } + + @Override + public ItemStack getItem(HumanEntity who, int slot) { + if (item == null) { + return null; + } + ItemStack clone = item.clone(); + gui.setItemText(who, clone, getText()); + if (number > 0 && number <= 64) { + clone.setAmount(number); + } + return clone; + } + + /** + * Set this element's display text. If this is an empty array the item's name will be displayed + * @param text The text to display on this element, placeholders are automatically + * replaced, see {@link InventoryGui#replaceVars} for a list of the + * placeholder variables. Empty text strings are also filter out, use + * a single space if you want to add an empty line!
+ * If it's not set/empty the item's default name will be used + */ + public void setText(String... text) { + this.text = text; + } + + /** + * Get the text that this element displays + * @return The text that is displayed on this element + */ + public String[] getText() { + return text; + } + + /** + * Set the number that this element should display (via the Item's amount) + * @param number The number, 1 will not display the number + * @return true if the number was set; false if it was below 1 or above 64 + */ + public boolean setNumber(int number) { + if (number < 1 || number > 64) { + this.number = 1; + return false; + } + this.number = number; + return true; + } + + /** + * Get the number that this element should display + * @return The number (item amount) that this element currently has + */ + public int getNumber() { + return number; + } + +} diff --git a/src/main/java/net/momirealms/customfishing/helper/LibraryLoader.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/LibraryLoader.java similarity index 53% rename from src/main/java/net/momirealms/customfishing/helper/LibraryLoader.java rename to plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/LibraryLoader.java index 434d81b1..3bc61b80 100644 --- a/src/main/java/net/momirealms/customfishing/helper/LibraryLoader.java +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/LibraryLoader.java @@ -23,11 +23,12 @@ * SOFTWARE. */ -package net.momirealms.customfishing.helper; +package net.momirealms.customfishing.libraries.libraryloader; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; -import net.momirealms.customfishing.CustomFishing; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.util.LogUtils; import java.io.File; import java.io.InputStream; @@ -45,7 +46,7 @@ import java.util.StringJoiner; public final class LibraryLoader { @SuppressWarnings("Guava") - private static final Supplier URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) CustomFishing.getInstance().getClass().getClassLoader())); + private static final Supplier URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) CustomFishingPlugin.getInstance().getClass().getClassLoader())); /** * Resolves all {@link MavenLibrary} annotations on the given object. @@ -63,9 +64,6 @@ public final class LibraryLoader { */ public static void loadAll(Class clazz) { MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class); - if (libs == null) { - return; - } for (MavenLibrary lib : libs) { load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url()); } @@ -75,31 +73,38 @@ public final class LibraryLoader { load(new Dependency(groupId, artifactId, version, repoUrl)); } - public static void load(Dependency d) { - //Log.info(String.format("Loading dependency %s:%s:%s from %s", d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getRepoUrl())); - String name = d.getArtifactId() + "-" + d.getVersion(); + public static void loadDependencies(String... libs) { + if (libs == null || libs.length % 2 != 0) + return; + for (int i = 0; i < libs.length; i+=2) { + String[] split = libs[i].split(":"); + load(new Dependency( + split[0], + split[1], + split[2], + libs[i+1] + )); + } + } + public static void load(Dependency d) { + LogUtils.info(String.format("Loading dependency %s:%s:%s from %s", d.groupId, d.artifactId, d.version, d.repoUrl)); + String name = d.artifactId() + "-" + d.version(); File saveLocation = new File(getLibFolder(d), name + ".jar"); if (!saveLocation.exists()) { - try { - Log.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download..."); + LogUtils.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download..."); URL url = d.getUrl(); - try (InputStream is = url.openStream()) { Files.copy(is, saveLocation.toPath()); - Log.info("Dependency '" + name + "' successfully downloaded."); + LogUtils.info("Dependency '" + name + "' successfully downloaded."); } - } catch (Exception e) { e.printStackTrace(); } } - - if (!saveLocation.exists()) { + if (!saveLocation.exists()) throw new RuntimeException("Unable to download dependency: " + d); - } - try { URL_INJECTOR.get().addURL(saveLocation.toURI().toURL()); } catch (Exception e) { @@ -107,12 +112,13 @@ public final class LibraryLoader { } } + @SuppressWarnings("all") private static File getLibFolder(Dependency dependency) { - File pluginDataFolder = CustomFishing.getInstance().getDataFolder(); + File pluginDataFolder = CustomFishingPlugin.getInstance().getDataFolder(); File serverDir = pluginDataFolder.getParentFile().getParentFile(); File helperDir = new File(serverDir, "libraries"); - String[] split = dependency.getGroupId().split("\\."); + String[] split = dependency.groupId().split("\\."); File jarDir; StringJoiner stringJoiner = new StringJoiner(File.separator); for (String str : split) { @@ -123,75 +129,53 @@ public final class LibraryLoader { return jarDir; } - public static final class Dependency { - private final String groupId; - private final String artifactId; - private final String version; - private final String repoUrl; - - public Dependency(String groupId, String artifactId, String version, String repoUrl) { - this.groupId = Objects.requireNonNull(groupId, "groupId"); - this.artifactId = Objects.requireNonNull(artifactId, "artifactId"); - this.version = Objects.requireNonNull(version, "version"); - this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl"); - } - - public String getGroupId() { - return this.groupId; - } - - public String getArtifactId() { - return this.artifactId; - } - - public String getVersion() { - return this.version; - } - - public String getRepoUrl() { - return this.repoUrl; - } - - public URL getUrl() throws MalformedURLException { - String repo = this.repoUrl; - if (!repo.endsWith("/")) { - repo += "/"; + public record Dependency(String groupId, String artifactId, String version, String repoUrl) { + public Dependency(String groupId, String artifactId, String version, String repoUrl) { + this.groupId = Objects.requireNonNull(groupId, "groupId"); + this.artifactId = Objects.requireNonNull(artifactId, "artifactId"); + this.version = Objects.requireNonNull(version, "version"); + this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl"); } - repo += "%s/%s/%s/%s-%s.jar"; - String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version); - return new URL(url); - } + public URL getUrl() throws MalformedURLException { + String repo = this.repoUrl; + if (!repo.endsWith("/")) { + repo += "/"; + } + repo += "%s/%s/%s/%s-%s.jar"; - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof Dependency)) return false; - final Dependency other = (Dependency) o; - return this.getGroupId().equals(other.getGroupId()) && - this.getArtifactId().equals(other.getArtifactId()) && - this.getVersion().equals(other.getVersion()) && - this.getRepoUrl().equals(other.getRepoUrl()); - } + String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version); + return new URL(url); + } - @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - result = result * PRIME + this.getGroupId().hashCode(); - result = result * PRIME + this.getArtifactId().hashCode(); - result = result * PRIME + this.getVersion().hashCode(); - result = result * PRIME + this.getRepoUrl().hashCode(); - return result; - } + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Dependency other)) return false; + return this.groupId().equals(other.groupId()) && + this.artifactId().equals(other.artifactId()) && + this.version().equals(other.version()) && + this.repoUrl().equals(other.repoUrl()); + } - @Override - public String toString() { - return "LibraryLoader.Dependency(" + - "groupId=" + this.getGroupId() + ", " + - "artifactId=" + this.getArtifactId() + ", " + - "version=" + this.getVersion() + ", " + - "repoUrl=" + this.getRepoUrl() + ")"; + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.groupId().hashCode(); + result = result * PRIME + this.artifactId().hashCode(); + result = result * PRIME + this.version().hashCode(); + result = result * PRIME + this.repoUrl().hashCode(); + return result; + } + + @Override + public String toString() { + return "LibraryLoader.Dependency(" + + "groupId=" + this.groupId() + ", " + + "artifactId=" + this.artifactId() + ", " + + "version=" + this.version() + ", " + + "repoUrl=" + this.repoUrl() + ")"; + } } - } } diff --git a/src/main/java/net/momirealms/customfishing/helper/MavenLibraries.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/MavenLibraries.java similarity index 96% rename from src/main/java/net/momirealms/customfishing/helper/MavenLibraries.java rename to plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/MavenLibraries.java index dae6f3cf..7179e34f 100644 --- a/src/main/java/net/momirealms/customfishing/helper/MavenLibraries.java +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/MavenLibraries.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package net.momirealms.customfishing.helper; +package net.momirealms.customfishing.libraries.libraryloader; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/momirealms/customfishing/helper/MavenLibrary.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/MavenLibrary.java similarity index 97% rename from src/main/java/net/momirealms/customfishing/helper/MavenLibrary.java rename to plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/MavenLibrary.java index 7a979775..60ad69c8 100644 --- a/src/main/java/net/momirealms/customfishing/helper/MavenLibrary.java +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/MavenLibrary.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package net.momirealms.customfishing.helper; +package net.momirealms.customfishing.libraries.libraryloader; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/momirealms/customfishing/helper/Repository.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/Repository.java similarity index 96% rename from src/main/java/net/momirealms/customfishing/helper/Repository.java rename to plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/Repository.java index 03c3affc..c0798824 100644 --- a/src/main/java/net/momirealms/customfishing/helper/Repository.java +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/Repository.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package net.momirealms.customfishing.helper; +package net.momirealms.customfishing.libraries.libraryloader; import java.lang.annotation.*; diff --git a/src/main/java/net/momirealms/customfishing/helper/URLClassLoaderAccess.java b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/URLClassLoaderAccess.java similarity index 98% rename from src/main/java/net/momirealms/customfishing/helper/URLClassLoaderAccess.java rename to plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/URLClassLoaderAccess.java index adb705ca..43e6df69 100644 --- a/src/main/java/net/momirealms/customfishing/helper/URLClassLoaderAccess.java +++ b/plugin/src/main/java/net/momirealms/customfishing/libraries/libraryloader/URLClassLoaderAccess.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package net.momirealms.customfishing.helper; +package net.momirealms.customfishing.libraries.libraryloader; import org.jetbrains.annotations.NotNull; diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java new file mode 100644 index 00000000..102c5f20 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java @@ -0,0 +1,317 @@ +package net.momirealms.customfishing.mechanic.action; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.ActionManager; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionBuilder; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.util.ConfigUtils; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ExperienceOrb; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +public class ActionManagerImpl implements ActionManager { + + private final CustomFishingPlugin plugin; + private final HashMap actionBuilderMap; + + public ActionManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.actionBuilderMap = new HashMap<>(); + this.registerInbuiltActions(); + } + + private void registerInbuiltActions() { + this.registerMessageAction(); + this.registerCommandAction(); + this.registerMendingAction(); + this.registerExpAction(); + this.registerChainAction(); + this.registerPotionAction(); + this.registerSoundAction(); + this.registerPluginExpAction(); + this.registerTitleAction(); + this.registerActionBarAction(); + } + + @Override + public boolean registerAction(String type, ActionBuilder actionBuilder) { + if (this.actionBuilderMap.containsKey(type)) return false; + this.actionBuilderMap.put(type, actionBuilder); + return true; + } + + @Override + public boolean unregisterAction(String type) { + return this.actionBuilderMap.remove(type) != null; + } + + @Override + public Action getAction(ConfigurationSection section) { + return getActionBuilder(section.getString("type")).build(section.get("value"), section.getDouble("chance", 1d)); + } + + @Nullable + @Override + public Action[] getActions(ConfigurationSection section) { + if (section == null) return null; + ArrayList actionList = new ArrayList<>(); + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + actionList.add(getAction(innerSection)); + } + } + return actionList.toArray(new Action[0]); + } + + @Override + public ActionBuilder getActionBuilder(String type) { + return actionBuilderMap.get(type); + } + + private void registerMessageAction() { + registerAction("message", (args, chance) -> { + ArrayList msg = ConfigUtils.stringListArgs(args); + return condition -> { + if (Math.random() > chance) return; + List replaced = PlaceholderManagerImpl.getInstance().parse( + condition.getPlayer(), + msg, + condition.getArgs() + ); + for (String text : replaced) { + AdventureManagerImpl.getInstance().sendPlayerMessage(condition.getPlayer(), text); + } + }; + }); + registerAction("broadcast", (args, chance) -> { + ArrayList msg = ConfigUtils.stringListArgs(args); + return condition -> { + if (Math.random() > chance) return; + List replaced = PlaceholderManagerImpl.getInstance().parse( + condition.getPlayer(), + msg, + condition.getArgs() + ); + for (Player player : Bukkit.getOnlinePlayers()) { + for (String text : replaced) { + AdventureManagerImpl.getInstance().sendPlayerMessage(player, text); + } + } + }; + }); + registerAction("random-message", (args, chance) -> { + ArrayList msg = ConfigUtils.stringListArgs(args); + return condition -> { + if (Math.random() > chance) return; + String random = msg.get(ThreadLocalRandom.current().nextInt(msg.size())); + random = PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); + AdventureManagerImpl.getInstance().sendPlayerMessage(condition.getPlayer(), random); + }; + }); + } + + private void registerCommandAction() { + registerAction("command", (args, chance) -> { + ArrayList cmd = ConfigUtils.stringListArgs(args); + return condition -> { + if (Math.random() > chance) return; + List replaced = PlaceholderManagerImpl.getInstance().parse( + condition.getPlayer(), + cmd, + condition.getArgs() + ); + plugin.getScheduler().runTaskSync(() -> { + for (String text : replaced) { + Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), text); + } + }, condition.getLocation()); + }; + }); + registerAction("random-command", (args, chance) -> { + ArrayList cmd = ConfigUtils.stringListArgs(args); + return condition -> { + if (Math.random() > chance) return; + String random = cmd.get(ThreadLocalRandom.current().nextInt(cmd.size())); + random = PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); + String finalRandom = random; + plugin.getScheduler().runTaskSync(() -> { + Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), finalRandom); + }, condition.getLocation()); + }; + }); + } + + private void registerActionBarAction() { + registerAction("actionbar", (args, chance) -> { + String text = (String) args; + return condition -> { + if (Math.random() > chance) return; + String parsed = PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), text, condition.getArgs()); + AdventureManagerImpl.getInstance().sendActionbar(condition.getPlayer(), parsed); + }; + }); + registerAction("random-actionbar", (args, chance) -> { + ArrayList texts = ConfigUtils.stringListArgs(args); + return condition -> { + if (Math.random() > chance) return; + String random = texts.get(ThreadLocalRandom.current().nextInt(texts.size())); + random = PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), random, condition.getArgs()); + AdventureManagerImpl.getInstance().sendActionbar(condition.getPlayer(), random); + }; + }); + } + + private void registerMendingAction() { + registerAction("mending", (args, chance) -> { + int xp = (int) args; + return condition -> { + if (Math.random() > chance) return; + if (CustomFishingPlugin.get().getVersionManager().isSpigot()) { + condition.getPlayer().getLocation().getWorld().spawn(condition.getPlayer().getLocation(), ExperienceOrb.class, e -> e.setExperience(xp)); + } else { + condition.getPlayer().giveExp(xp, true); + AdventureManagerImpl.getInstance().sendSound(condition.getPlayer(), Sound.Source.PLAYER, Key.key("minecraft:entity.experience_orb.pickup"), 1, 1); + } + }; + }); + } + + private void registerExpAction() { + registerAction("exp", (args, chance) -> { + int xp = (int) args; + return condition -> { + if (Math.random() > chance) return; + condition.getPlayer().giveExp(xp); + }; + }); + } + + private void registerChainAction() { + registerAction("chain", (args, chance) -> { + List actions = new ArrayList<>(); + if (args instanceof ConfigurationSection section) { + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + actions.add(getAction(innerSection)); + } + } + } + return condition -> { + if (Math.random() > chance) return; + for (Action action : actions) { + action.trigger(condition); + } + }; + }); + } + + private void registerTitleAction() { + registerAction("title", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + String title = section.getString("title"); + String subtitle = section.getString("subtitle"); + int fadeIn = section.getInt("fade-in", 20); + int stay = section.getInt("stay", 30); + int fadeOut = section.getInt("fade-out", 10); + return condition -> { + if (Math.random() > chance) return; + AdventureManagerImpl.getInstance().sendTitle( + condition.getPlayer(), + PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), title, condition.getArgs()), + PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), subtitle, condition.getArgs()), + fadeIn * 50, + stay * 50, + fadeOut * 50 + ); + }; + } + return null; + }); + registerAction("random-title", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + List titles = section.getStringList("titles"); + List subtitles = section.getStringList("subtitles"); + int fadeIn = section.getInt("fade-in", 20); + int stay = section.getInt("stay", 30); + int fadeOut = section.getInt("fade-out", 10); + return condition -> { + if (Math.random() > chance) return; + AdventureManagerImpl.getInstance().sendTitle( + condition.getPlayer(), + PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), titles.get(ThreadLocalRandom.current().nextInt(titles.size())), condition.getArgs()), + PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), subtitles.get(ThreadLocalRandom.current().nextInt(subtitles.size())), condition.getArgs()), + fadeIn * 50, + stay * 50, + fadeOut * 50 + ); + }; + } + return null; + }); + } + + private void registerPotionAction() { + registerAction("potion-effect", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + PotionEffect potionEffect = new PotionEffect( + Objects.requireNonNull(PotionEffectType.getByName(section.getString("type", "BLINDNESS").toUpperCase(Locale.ENGLISH))), + section.getInt("duration", 20), + section.getInt("amplifier", 0) + ); + return condition -> { + if (Math.random() > chance) return; + condition.getPlayer().addPotionEffect(potionEffect); + }; + } + return null; + }); + } + + @SuppressWarnings("all") + private void registerSoundAction() { + registerAction("sound", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + Sound sound = Sound.sound( + Key.key(section.getString("key")), + Sound.Source.valueOf(section.getString("source", "PLAYER").toUpperCase(Locale.ENGLISH)), + (float) section.getDouble("volume", 1), + (float) section.getDouble("pitch", 1) + ); + return condition -> { + if (Math.random() > chance) return; + AdventureManagerImpl.getInstance().sendSound(condition.getPlayer(), sound); + }; + } + return null; + }); + } + + private void registerPluginExpAction() { + registerAction("plugin-exp", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + String pluginName = section.getString("plugin"); + double exp = section.getDouble("exp", 1); + String target = section.getString("target"); + return condition -> { + if (Math.random() > chance) return; + Optional.ofNullable(plugin.getIntegrationManager().getLevelHook(pluginName)).ifPresentOrElse(it -> { + it.addXp(condition.getPlayer(), target, exp); + }, () -> LogUtils.warn("Plugin (" + pluginName + "'s) level is not compatible. Please double check if it's a problem caused by pronunciation.")); + }; + } + return null; + }); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/bag/BagManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/bag/BagManagerImpl.java new file mode 100644 index 00000000..46ee1919 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/bag/BagManagerImpl.java @@ -0,0 +1,97 @@ +package net.momirealms.customfishing.mechanic.bag; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.WrappedChatComponent; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ScoreComponent; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.BagManager; +import net.momirealms.customfishing.api.mechanic.bag.FishingBagHolder; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.setting.Config; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.inventory.Inventory; + +import java.util.HashMap; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class BagManagerImpl implements BagManager { + + private final CustomFishingPlugin plugin; + private final ConcurrentHashMap bagMap; + private final WindowPacketListener windowPacketListener; + + public BagManagerImpl(CustomFishingPluginImpl plugin) { + this.plugin = plugin; + this.bagMap = new ConcurrentHashMap<>(); + this.windowPacketListener = new WindowPacketListener(); + } + + @Override + public boolean isBagEnabled() { + return Config.enableFishingBag; + } + + public void load() { + CustomFishingPluginImpl.getProtocolManager().addPacketListener(windowPacketListener); + } + + public void unload() { + CustomFishingPluginImpl.getProtocolManager().removePacketListener(windowPacketListener); + } + + public void disable() { + unload(); + } + + @Override + public Inventory getOnlineBagInventory(UUID uuid) { + var onlinePlayer = plugin.getStorageManager().getOnlineUser(uuid); + if (onlinePlayer == null) { + LogUtils.warn("Player " + uuid + "'s bag data is not loaded."); + return null; + } + return onlinePlayer.getHolder().getInventory(); + } + + public static class WindowPacketListener extends PacketAdapter { + + public WindowPacketListener() { + super(CustomFishingPlugin.getInstance(), PacketType.Play.Server.OPEN_WINDOW); + } + + @Override + public void onPacketSending(PacketEvent event) { + final PacketContainer packet = event.getPacket(); + StructureModifier wrappedChatComponentStructureModifier = packet.getChatComponents(); + WrappedChatComponent component = wrappedChatComponentStructureModifier.getValues().get(0); + String windowTitleJson = component.getJson(); + Component titleComponent = GsonComponentSerializer.gson().deserialize(windowTitleJson); + if (titleComponent instanceof ScoreComponent scoreComponent && scoreComponent.name().equals("bag")) { + HashMap placeholders = new HashMap<>(); + String uuidStr = scoreComponent.objective(); + UUID uuid = UUID.fromString(uuidStr); + placeholders.put("{uuid}", uuidStr); + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); + placeholders.put("{player}", Optional.ofNullable(offlinePlayer.getName()).orElse(uuidStr)); + wrappedChatComponentStructureModifier.write(0, + WrappedChatComponent.fromJson( + GsonComponentSerializer.gson().serialize( + AdventureManagerImpl.getInstance().getComponentFromMiniMessage( + PlaceholderManagerImpl.getInstance().parse(offlinePlayer, Config.bagTitle, placeholders) + )))); + } + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/block/BlockManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/block/BlockManagerImpl.java new file mode 100644 index 00000000..0d4ec516 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/block/BlockManagerImpl.java @@ -0,0 +1,288 @@ +package net.momirealms.customfishing.mechanic.block; + +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.common.Tuple; +import net.momirealms.customfishing.api.manager.BlockManager; +import net.momirealms.customfishing.api.mechanic.block.*; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.block.VanillaBlockImpl; +import net.momirealms.customfishing.util.ConfigUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.block.Barrel; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.Chest; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.util.Vector; + +import java.io.File; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +public class BlockManagerImpl implements BlockManager, Listener { + + private final CustomFishingPlugin plugin; + private final HashMap blockLibraryMap; + private final HashMap blockConfigMap; + private final HashMap dataBuilderMap; + private final HashMap stateBuilderMap; + + public BlockManagerImpl(CustomFishingPluginImpl plugin) { + this.plugin = plugin; + this.blockLibraryMap = new HashMap<>(); + this.blockConfigMap = new HashMap<>(); + this.dataBuilderMap = new HashMap<>(); + this.stateBuilderMap = new HashMap<>(); + this.registerBlockLibrary(new VanillaBlockImpl()); + this.registerInbuiltProperties(); + this.registerStorage(); + } + + @Override + public boolean registerBlockLibrary(BlockLibrary library) { + if (this.blockLibraryMap.containsKey(library.identification())) return false; + this.blockLibraryMap.put(library.identification(), library); + return true; + } + + @Override + public boolean unregisterBlockLibrary(BlockLibrary library) { + return unregisterBlockLibrary(library.identification()); + } + + @Override + public boolean unregisterBlockLibrary(String library) { + return blockLibraryMap.remove(library) != null; + } + + @Override + public boolean registerBlockDataModifierBuilder(String type, BlockDataModifierBuilder builder) { + if (dataBuilderMap.containsKey(type)) return false; + dataBuilderMap.put(type, builder); + return true; + } + + @Override + public boolean registerBlockStateModifierBuilder(String type, BlockStateModifierBuilder builder) { + if (stateBuilderMap.containsKey(type)) return false; + stateBuilderMap.put(type, builder); + return true; + } + + public void load() { + this.loadConfig(); + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + private void registerInbuiltProperties() { + this.registerDirectional(); + this.registerStorage(); + } + + 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()); + } + } + } + + public void disable() { + this.blockLibraryMap.clear(); + } + + @SuppressWarnings("DuplicatedCode") + private void loadConfig() { + Deque fileDeque = new ArrayDeque<>(); + for (String type : List.of("blocks")) { + 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()) { + this.loadSingleFile(subFile); + } + } + } + } + } + + 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 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<>(); + ConfigurationSection property = section.getConfigurationSection("properties"); + if (property != null) { + for (Map.Entry innerEntry : property.getValues(false).entrySet()) { + BlockDataModifierBuilder dataBuilder = dataBuilderMap.get(innerEntry.getKey()); + if (dataBuilder != null) { + dataModifiers.add(dataBuilder.build(innerEntry.getValue())); + continue; + } + BlockStateModifierBuilder stateBuilder = stateBuilderMap.get(innerEntry.getKey()); + if (stateBuilder != null) { + stateModifiers.add(stateBuilder.build(innerEntry.getValue())); + } + } + } + BlockConfig blockConfig = new BlockConfig.Builder() + .blockID(blockID) + .persist(false) + .horizontalVector(section.getDouble("vector.horizontal", 1.1)) + .verticalVector(section.getDouble("vector.vertical", 1.2)) + .dataModifiers(dataModifiers) + .stateModifiers(stateModifiers) + .build(); + blockConfigMap.put(entry.getKey(), blockConfig); + } + } + } + + @Override + public void summonBlock(Player player, Location hookLocation, Location playerLocation, Loot loot) { + BlockConfig config = blockConfigMap.get(loot.getID()); + if (config == null) { + LogUtils.warn("Block: " + loot.getID() + " doesn't exist."); + return; + } + String blockID = config.getBlockID(); + BlockData blockData; + if (blockID.contains(":")) { + String[] split = blockID.split(":", 2); + String lib = split[0]; + String id = split[1]; + blockData = blockLibraryMap.get(lib).getBlockData(player, id, config.getDataModifier()); + } else { + blockData = blockLibraryMap.get("vanilla").getBlockData(player, blockID, config.getDataModifier()); + } + FallingBlock fallingBlock = hookLocation.getWorld().spawnFallingBlock(hookLocation, blockData); + fallingBlock.getPersistentDataContainer().set( + Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())), + PersistentDataType.STRING, + loot.getID() + ";" + player.getName() + ); + fallingBlock.setDropItem(false); + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1); + vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector()); + fallingBlock.setVelocity(vector); + } + + private void registerDirectional() { + this.registerBlockDataModifierBuilder("directional", (args) -> { + boolean arg = (boolean) args; + return (player, blockData) -> { + if (arg && blockData instanceof Directional directional) { + directional.setFacing(BlockFace.values()[ThreadLocalRandom.current().nextInt(0,6)]); + } + }; + }); + } + + 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 (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)); + } + } + return (player, blockState) -> { + LinkedList unused = new LinkedList<>(); + for (int i = 0; i < 27; i++) { + unused.add(i); + } + Collections.shuffle(unused); + if (blockState instanceof Chest chest) { + for (Tuple> tuple : tempChanceList) { + ItemStack itemStack = plugin.getItemManager().buildAnyItemByID(player, tuple.getMid()); + itemStack.setAmount(ThreadLocalRandom.current().nextInt(tuple.getRight().left(), tuple.getRight().right() + 1)); + if (tuple.getLeft() > Math.random()) { + chest.getBlockInventory().setItem(unused.pop(), itemStack); + } + } + return; + } + if (blockState instanceof Barrel barrel) { + for (Tuple> tuple : tempChanceList) { + ItemStack itemStack = plugin.getItemManager().buildAnyItemByID(player, tuple.getMid()); + itemStack.setAmount(ThreadLocalRandom.current().nextInt(tuple.getRight().left(), tuple.getRight().right() + 1)); + if (tuple.getLeft() > Math.random()) { + barrel.getInventory().setItem(unused.pop(), itemStack); + } + } + } + }; + } else { + LogUtils.warn("Invalid property format found at block storage."); + return null; + } + }); + } + + @EventHandler + public void onBlockLands(EntityChangeBlockEvent event) { + if (event.isCancelled()) return; + String temp = event.getEntity().getPersistentDataContainer().get( + Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())), + PersistentDataType.STRING + ); + if (temp == null) return; + String[] split = temp.split(";"); + BlockConfig blockConfig = blockConfigMap.get(split[0]); + if (blockConfig == null) return; + Player player = Bukkit.getPlayer(split[1]); + if (player == null) { + event.getEntity().remove(); + event.getBlock().setType(Material.AIR); + return; + } + Location location = event.getBlock().getLocation(); + plugin.getScheduler().runTaskSyncLater(() -> { + BlockState state = location.getBlock().getState(); + for (BlockStateModifier modifier : blockConfig.getStateModifierList()) { + modifier.apply(player, state); + } + }, location, 50, TimeUnit.MILLISECONDS); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java new file mode 100644 index 00000000..d4d8afb4 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java @@ -0,0 +1,265 @@ +package net.momirealms.customfishing.mechanic.competition; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.competition.CompetitionConfig; +import net.momirealms.customfishing.api.mechanic.competition.CompetitionGoal; +import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition; +import net.momirealms.customfishing.api.mechanic.competition.Ranking; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.mechanic.competition.actionbar.ActionBarManager; +import net.momirealms.customfishing.mechanic.competition.bossbar.BossBarManager; +import net.momirealms.customfishing.mechanic.competition.ranking.LocalRankingImpl; +import net.momirealms.customfishing.mechanic.competition.ranking.RedisRankingImpl; +import net.momirealms.customfishing.setting.Config; +import net.momirealms.customfishing.setting.Locale; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.time.Instant; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +public class Competition implements FishingCompetition { + + private final CompetitionConfig config; + private CancellableTask competitionTimerTask; + private final CompetitionGoal goal; + private final ConcurrentHashMap publicPlaceholders; + private final Ranking ranking; + private float progress; + private long remainingTime; + private long startTime; + private BossBarManager bossBarManager; + private ActionBarManager actionBarManager; + + public Competition(CompetitionConfig config) { + this.config = config; + this.goal = config.getGoal() == CompetitionGoal.RANDOM ? CompetitionGoal.getRandom() : config.getGoal(); + if (Config.redisRanking) this.ranking = new RedisRankingImpl(); + else this.ranking = new LocalRankingImpl(); + this.publicPlaceholders = new ConcurrentHashMap<>(); + this.publicPlaceholders.put("{goal}", getCompetitionLocale(goal)); + } + + @Override + public void start() { + this.progress = 1; + this.remainingTime = config.getDuration(); + this.startTime = Instant.now().getEpochSecond(); + this.updatePublicPlaceholders(); + + this.arrangeTimerTask(); + if (config.getBossBarConfig() != null) { + this.bossBarManager = new BossBarManager(config.getBossBarConfig(), this); + this.bossBarManager.load(); + } + if (config.getActionBarConfig() != null) { + this.actionBarManager = new ActionBarManager(config.getActionBarConfig(), this); + this.actionBarManager.load(); + } + + Action[] actions = config.getStartActions(); + if (actions != null) { + Condition condition = new Condition(); + for (Action action : actions) { + action.trigger(condition); + } + } + } + + private void arrangeTimerTask() { + this.competitionTimerTask = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> { + if (decreaseTime()) { + end(); + return; + } + updatePublicPlaceholders(); + }, 1, 1, TimeUnit.SECONDS); + } + + private void updatePublicPlaceholders() { + for (int i = 1; i < Config.placeholderLimit + 1; i++) { + int finalI = i; + Optional.ofNullable(ranking.getPlayerAt(i)).ifPresentOrElse(player -> { + publicPlaceholders.put("{" + finalI + "_player}", player); + publicPlaceholders.put("{" + finalI + "_score}", String.format("%.2f", ranking.getScoreAt(finalI))); + }, () -> { + publicPlaceholders.put("{" + finalI + "_player}", Locale.MSG_No_Player); + publicPlaceholders.put("{" + finalI + "_score}", Locale.MSG_No_Score); + }); + } + publicPlaceholders.put("{hour}", String.valueOf(remainingTime / 3600)); + publicPlaceholders.put("{minute}", String.valueOf((remainingTime % 3600) / 60)); + publicPlaceholders.put("{second}", String.valueOf(remainingTime % 60)); + publicPlaceholders.put("{time}", String.valueOf(remainingTime)); + } + + @Override + public void stop() { + if (!competitionTimerTask.isCancelled()) this.competitionTimerTask.cancel(); + if (this.bossBarManager != null) this.bossBarManager.unload(); + if (this.actionBarManager != null) this.actionBarManager.unload(); + this.ranking.clear(); + this.remainingTime = 0; + } + + @Override + public void end() { + // mark it as ended + this.remainingTime = 0; + + // cancel some sub tasks + if (!competitionTimerTask.isCancelled()) this.competitionTimerTask.cancel(); + if (this.bossBarManager != null) this.bossBarManager.unload(); + if (this.actionBarManager != null) this.actionBarManager.unload(); + + // give prizes + HashMap rewardsMap = config.getRewards(); + if (ranking.getSize() != 0 && rewardsMap != null) { + Iterator> iterator = ranking.getIterator(); + int i = 1; + while (iterator.hasNext()) { + Pair competitionPlayer = iterator.next(); + this.publicPlaceholders.put("{" + i + "_player}", competitionPlayer.left()); + this.publicPlaceholders.put("{" + i + "_score}", String.format("%.2f", competitionPlayer.right())); + if (i < rewardsMap.size()) { + Player player = Bukkit.getPlayer(competitionPlayer.left()); + if (player != null) + for (Action action : rewardsMap.get(String.valueOf(i))) + action.trigger(new Condition(player)); + i++; + } else { + Action[] actions = rewardsMap.get("participation"); + if (actions != null) { + iterator.forEachRemaining(playerName -> { + Player player = Bukkit.getPlayer(competitionPlayer.left()); + if (player != null) + for (Action action : actions) + action.trigger(new Condition(player)); + }); + } else { + break; + } + } + } + } + + // do end actions + Action[] actions = config.getEndActions(); + if (actions != null) { + Condition condition = new Condition(new HashMap<>(publicPlaceholders)); + for (Action action : actions) { + action.trigger(condition); + } + } + + // 1.5 seconds delay for other servers to read the redis data + CustomFishingPlugin.get().getScheduler().runTaskAsyncLater(this.ranking::clear, 1500, TimeUnit.MILLISECONDS); + } + + @Override + public boolean isOnGoing() { + return remainingTime > 0; + } + + private boolean decreaseTime() { + long current = Instant.now().getEpochSecond(); + int duration = config.getDuration(); + remainingTime = duration - (current - startTime); + progress = (float) remainingTime / duration; + return remainingTime <= 0; + } + + @Override + public void refreshData(Player player, double score, boolean doubleScore) { + // if player join for the first time, trigger join actions + if (!hasPlayerJoined(player)) { + Action[] actions = config.getJoinActions(); + if (actions != null) { + Condition condition = new Condition(player); + for (Action action : actions) { + action.trigger(condition); + } + } + } + + // show competition info + if (this.bossBarManager != null) this.bossBarManager.showBossBarTo(player); + if (this.actionBarManager != null) this.actionBarManager.showActionBarTo(player); + + // refresh data + switch (this.goal) { + case CATCH_AMOUNT -> ranking.refreshData(player.getName(), doubleScore ? 2 : 1); + case TOTAL_SIZE, TOTAL_SCORE -> ranking.refreshData(player.getName(), doubleScore ? 2 * score : score); + case MAX_SIZE -> { + if (score > ranking.getPlayerScore(player.getName())) { + ranking.setData(player.getName(), score); + } + } + } + } + + @Override + public boolean hasPlayerJoined(OfflinePlayer player) { + return ranking.getPlayerRank(player.getName()) != -1; + } + + @Override + public float getProgress() { + return progress; + } + + @Override + public long getRemainingTime() { + return remainingTime; + } + + @Override + public long getStartTime() { + return startTime; + } + + @Override + public CompetitionConfig getConfig() { + return config; + } + + @Override + public CompetitionGoal getGoal() { + return goal; + } + + @Override + public Ranking getRanking() { + return ranking; + } + + public ConcurrentHashMap getPublicPlaceholders() { + return publicPlaceholders; + } + + private String getCompetitionLocale(CompetitionGoal goal) { + switch (goal) { + case MAX_SIZE -> { + return Locale.MSG_Max_Size; + } + case CATCH_AMOUNT -> { + return Locale.MSG_Catch_Amount; + } + case TOTAL_SCORE -> { + return Locale.MSG_Total_Score; + } + case TOTAL_SIZE -> { + return Locale.MSG_Total_Size; + } + } + return ""; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionManagerImpl.java new file mode 100644 index 00000000..7ed06e2c --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionManagerImpl.java @@ -0,0 +1,259 @@ +package net.momirealms.customfishing.mechanic.competition; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.manager.CompetitionManager; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.competition.*; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.setting.Config; +import net.momirealms.customfishing.storage.method.database.nosql.RedisManager; +import org.bukkit.Bukkit; +import org.bukkit.boss.BarColor; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +public class CompetitionManagerImpl implements CompetitionManager { + + private final CustomFishingPlugin plugin; + private final HashMap timeConfigMap; + private final HashMap commandConfigMap; + private Competition currentCompetition; + private CancellableTask timerCheckTask; + private int nextCompetitionSeconds; + + public CompetitionManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.timeConfigMap = new HashMap<>(); + this.commandConfigMap = new HashMap<>(); + } + + public void load() { + loadConfig(); + this.timerCheckTask = plugin.getScheduler().runTaskAsyncTimer( + this::timerCheck, + 1, + 1, + TimeUnit.SECONDS + ); + } + + public void unload() { + if (this.timerCheckTask != null && !this.timerCheckTask.isCancelled()) + this.timerCheckTask.cancel(); + this.commandConfigMap.clear(); + this.timeConfigMap.clear(); + if (currentCompetition != null && currentCompetition.isOnGoing()) + currentCompetition.end(); + } + + public void disable() { + if (this.timerCheckTask != null && !this.timerCheckTask.isCancelled()) + this.timerCheckTask.cancel(); + this.commandConfigMap.clear(); + this.timeConfigMap.clear(); + if (currentCompetition != null && currentCompetition.isOnGoing()) + currentCompetition.stop(); + } + + @Override + public Set getAllCompetitions() { + return commandConfigMap.keySet(); + } + + @SuppressWarnings("DuplicatedCode") + private void loadConfig() { + Deque fileDeque = new ArrayDeque<>(); + for (String type : List.of("competitions")) { + 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()) { + this.loadSingleFileCompetition(subFile); + } + } + } + } + } + + private void loadSingleFileCompetition(File file) { + YamlConfiguration config = YamlConfiguration.loadConfiguration(file); + for (Map.Entry entry : config.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection section) { + + CompetitionConfig.Builder builder = new CompetitionConfig.Builder(entry.getKey()) + .goal(CompetitionGoal.valueOf(section.getString("goal", "TOTAL_SCORE").toUpperCase(Locale.ENGLISH))) + .minPlayers(section.getInt("min-players", 0)) + .duration(section.getInt("duration", 300)) + .rewards(getPrizeActions(section.getConfigurationSection("rewards"))) + .startActions(plugin.getActionManager().getActions(section.getConfigurationSection("start-actions"))) + .endActions(plugin.getActionManager().getActions(section.getConfigurationSection("end-actions"))) + .skipActions(plugin.getActionManager().getActions(section.getConfigurationSection("skip-actions"))); + + if (section.getBoolean("bossbar.enable", false)) { + builder.bossbar(new BossBarConfig.Builder() + .color(BarColor.valueOf(section.getString("bossbar.color", "WHITE").toUpperCase(Locale.ENGLISH))) + .overlay(BossBarConfig.Overlay.valueOf(section.getString("bossbar.overlay", "PROGRESS").toUpperCase(Locale.ENGLISH))) + .refreshRate(section.getInt("bossbar.refresh-rate", 20)) + .switchInterval(section.getInt("bossbar.switch-interval", 200)) + .showToAll(!section.getBoolean("bossbar.only-show-to-participants", true)) + .text(section.getStringList("bossbar.text").toArray(new String[0])) + .build()); + } + + if (section.getBoolean("actionbar.enable", false)) { + builder.actionbar(new ActionBarConfig.Builder() + .refreshRate(section.getInt("actionbar.refresh-rate", 5)) + .switchInterval(section.getInt("actionbar.switch-interval", 200)) + .showToAll(!section.getBoolean("actionbar.only-show-to-participants", true)) + .text(section.getStringList("actionbar.text").toArray(new String[0])) + .build()); + } + + CompetitionConfig competitionConfig = builder.build(); + List> timePairs = section.getStringList("start-time") + .stream().map(this::getTimePair).toList(); + List weekdays = section.getIntegerList("start-weekday"); + if (weekdays.size() == 0) { + weekdays.addAll(List.of(1,2,3,4,5,6,7)); + } + for (Integer weekday : weekdays) { + for (Pair timePair : timePairs) { + CompetitionSchedule schedule = new CompetitionSchedule(weekday, timePair.left(), timePair.right(), 0); + timeConfigMap.put(schedule, competitionConfig); + } + } + commandConfigMap.put(entry.getKey(), competitionConfig); + } + } + } + + public HashMap getPrizeActions(ConfigurationSection section) { + HashMap map = new HashMap<>(); + if (section == null) return map; + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + map.put(entry.getKey(), plugin.getActionManager().getActions(innerSection)); + } + } + return map; + } + + public Pair getTimePair(String time) { + String[] split = time.split(":"); + return Pair.of(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + } + + public void timerCheck() { + LocalDateTime now = LocalDateTime.now(); + CompetitionSchedule competitionSchedule = new CompetitionSchedule( + now.getDayOfWeek().getValue(), + now.getHour(), + now.getMinute(), + now.getSecond() + ); + int seconds = competitionSchedule.getTotalSeconds(); + int nextCompetitionTime = 7 * 24 * 60 * 60; + for (CompetitionSchedule schedule : timeConfigMap.keySet()) { + nextCompetitionTime = Math.min(nextCompetitionTime, schedule.getTimeDelta(seconds)); + } + this.nextCompetitionSeconds = nextCompetitionTime; + CompetitionConfig config = timeConfigMap.get(competitionSchedule); + if (config != null) { + startCompetition(config, false, false); + } + } + + @Override + public void startCompetition(String competition, boolean force, boolean allServer) { + CompetitionConfig config = commandConfigMap.get(competition); + if (config == null) { + LogUtils.warn("Competition " + competition + " doesn't exist."); + return; + } + startCompetition(config, force, allServer); + } + + @Override + @Nullable + public FishingCompetition getOnGoingCompetition() { + if (currentCompetition == null) return null; + return currentCompetition.isOnGoing() ? currentCompetition : null; + } + + @Override + public void startCompetition(CompetitionConfig config, boolean force, boolean allServer) { + if (!force) + this.getPlayerCount().thenAccept(count -> { + if (count < config.getMinPlayers()) { + var actions = config.getSkipActions(); + if (actions != null) + for (Player player : Bukkit.getOnlinePlayers()) { + for (Action action : actions) { + action.trigger(new Condition(player)); + } + } + return; + } + start(config); + }); + else if (!allServer) { + start(config); + } else { + RedisManager.getInstance().sendRedisMessage("cf_competition", "start;" + config.getKey()); + } + } + + private void start(CompetitionConfig config) { + if (getOnGoingCompetition() != null) { + currentCompetition.end(); + plugin.getScheduler().runTaskAsyncLater(() -> { + this.currentCompetition = new Competition(config); + this.currentCompetition.start(); + }, 1, TimeUnit.SECONDS); + } else { + this.currentCompetition = new Competition(config); + this.currentCompetition.start(); + } + } + + @Override + public int getNextCompetitionSeconds() { + return nextCompetitionSeconds; + } + + @Override + public CompletableFuture getPlayerCount() { + if (!Config.redisRanking) { + return CompletableFuture.completedFuture(Bukkit.getOnlinePlayers().size()); + } else { + return plugin.getStorageManager().getRedisPlayerCount(); + } + } + + @Nullable + @Override + public CompetitionConfig getConfig(String key) { + return commandConfigMap.get(key); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionSchedule.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionSchedule.java new file mode 100644 index 00000000..f1599dfe --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/CompetitionSchedule.java @@ -0,0 +1,77 @@ +package net.momirealms.customfishing.mechanic.competition; + +public class CompetitionSchedule { + + private final int weekday; + private final int hour; + private final int minute; + private final int second; + + public CompetitionSchedule(int weekday, int hour, int minute, int second) { + this.weekday = weekday; + this.hour = hour; + this.minute = minute; + this.second = second; + } + + public int getWeekday() { + return weekday; + } + + public int getHour() { + return hour; + } + + public int getMinute() { + return minute; + } + + public int getSecond() { + return second; + } + + public int getTotalSeconds() { + return second + + minute * 60 + + hour * 60 * 60 + + weekday * 24 * 60 * 60; + } + + public int getTimeDelta(int totalSeconds) { + int thisSeconds = getTotalSeconds(); + if (thisSeconds >= totalSeconds) { + return thisSeconds - totalSeconds; + } else { + return (7 * 24 * 60 * 60) - (totalSeconds - thisSeconds); + } + } + + @Override + public int hashCode() { + final int prime = 7; + int result = 1; + result = prime * result + weekday; + result = prime * result + hour; + result = prime * result + minute; + result = prime * result + second; + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this == obj) + return true; + if (getClass() != obj.getClass()) + return false; + CompetitionSchedule other = (CompetitionSchedule) obj; + if (weekday != other.weekday) + return false; + if (hour != other.hour) + return false; + if (minute != other.minute) + return false; + return true; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarManager.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarManager.java new file mode 100644 index 00000000..0b4f6a53 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarManager.java @@ -0,0 +1,103 @@ +/* + * 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.mechanic.competition.actionbar; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.competition.ActionBarConfig; +import net.momirealms.customfishing.mechanic.competition.Competition; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +public class ActionBarManager implements Listener { + + private static final ConcurrentHashMap senderMap = new ConcurrentHashMap<>(); + private final ActionBarConfig actionBarConfig; + private final Competition competition; + + public ActionBarManager(ActionBarConfig actionBarConfig, Competition competition) { + this.actionBarConfig = actionBarConfig; + this.competition = competition; + } + + public void load() { + Bukkit.getPluginManager().registerEvents(this, CustomFishingPlugin.getInstance()); + if (actionBarConfig.isShowToAll()) { + for (Player player : Bukkit.getOnlinePlayers()) { + ActionBarSender sender = new ActionBarSender(player, actionBarConfig, competition); + if (!sender.isVisible()) { + sender.show(); + } + senderMap.put(player.getUniqueId(), sender); + } + } + } + + public void unload() { + HandlerList.unregisterAll(this); + for (ActionBarSender ActionBarSender : senderMap.values()) { + ActionBarSender.hide(); + } + senderMap.clear(); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + final Player player = event.getPlayer(); + ActionBarSender sender = senderMap.remove(player.getUniqueId()); + if (sender != null) { + if (sender.isVisible()) + sender.hide(); + } + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + final Player player = event.getPlayer(); + CustomFishingPlugin.getInstance().getScheduler().runTaskAsyncLater(() -> { + boolean hasJoined = competition.hasPlayerJoined(player); + if ((hasJoined || actionBarConfig.isShowToAll()) + && !senderMap.containsKey(player.getUniqueId())) { + ActionBarSender sender = new ActionBarSender(player, actionBarConfig, competition); + if (!sender.isVisible()) { + sender.show(); + } + senderMap.put(player.getUniqueId(), sender); + } + }, 200, TimeUnit.MILLISECONDS); + } + + public void showActionBarTo(Player player) { + ActionBarSender sender = senderMap.get(player.getUniqueId()); + if (sender == null) { + sender = new ActionBarSender(player, actionBarConfig, competition); + senderMap.put(player.getUniqueId(), sender); + } + if (!sender.isVisible()) { + sender.show(); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarSender.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarSender.java new file mode 100644 index 00000000..39556a6f --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/actionbar/ActionBarSender.java @@ -0,0 +1,106 @@ +/* + * 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.mechanic.competition.actionbar; + +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.competition.ActionBarConfig; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.mechanic.competition.Competition; +import net.momirealms.customfishing.setting.Locale; +import net.momirealms.customfishing.util.DynamicText; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.concurrent.TimeUnit; + +public class ActionBarSender { + + private final Player player; + private int refreshTimer; + private int switchTimer; + private int counter; + private final DynamicText[] texts; + private CancellableTask senderTask; + private final ActionBarConfig config; + private boolean isShown; + private final Competition competition; + private final HashMap privatePlaceholders; + + public ActionBarSender(Player player, ActionBarConfig config, Competition competition) { + this.player = player; + this.config = config; + this.isShown = false; + this.competition = competition; + this.privatePlaceholders = new HashMap<>(); + this.privatePlaceholders.put("{player}", player.getName()); + this.updatePrivatePlaceholders(); + + String[] str = config.getTexts(); + texts = new DynamicText[str.length]; + for (int i = 0; i < str.length; i++) { + texts[i] = new DynamicText(player, str[i]); + texts[i].update(privatePlaceholders); + } + } + + @SuppressWarnings("DuplicatedCode") + private void updatePrivatePlaceholders() { + this.privatePlaceholders.put("{score}", String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()))); + int rank = competition.getRanking().getPlayerRank(player.getName()); + this.privatePlaceholders.put("{rank}", rank != -1 ? String.valueOf(rank) : Locale.MSG_No_Rank); + this.privatePlaceholders.putAll(competition.getPublicPlaceholders()); + } + + public void show() { + this.isShown = true; + senderTask = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> { + switchTimer++; + if (switchTimer > config.getSwitchInterval()) { + switchTimer = 0; + counter++; + } + if (refreshTimer < config.getRefreshRate()){ + refreshTimer++; + } else { + refreshTimer = 0; + DynamicText text = texts[counter % (texts.length)]; + updatePrivatePlaceholders(); + text.update(privatePlaceholders); + AdventureManagerImpl.getInstance().sendActionbar( + player, + AdventureManagerImpl.getInstance().legacyToMiniMessage(text.getLatestValue()) + ); + } + }, 50, 50, TimeUnit.MILLISECONDS); + } + + public void hide() { + if (senderTask != null && !senderTask.isCancelled()) + senderTask.cancel(); + this.isShown = false; + } + + public boolean isVisible() { + return this.isShown; + } + + public ActionBarConfig getConfig() { + return config; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarManager.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarManager.java new file mode 100644 index 00000000..3992a815 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarManager.java @@ -0,0 +1,103 @@ +/* + * 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.mechanic.competition.bossbar; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.competition.BossBarConfig; +import net.momirealms.customfishing.mechanic.competition.Competition; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +public class BossBarManager implements Listener { + + private static final ConcurrentHashMap senderMap = new ConcurrentHashMap<>(); + private final BossBarConfig bossBarConfig; + private final Competition competition; + + public BossBarManager(BossBarConfig bossBarConfig, Competition competition) { + this.bossBarConfig = bossBarConfig; + this.competition = competition; + } + + public void load() { + Bukkit.getPluginManager().registerEvents(this, CustomFishingPlugin.getInstance()); + if (bossBarConfig.isShowToAll()) { + for (Player player : Bukkit.getOnlinePlayers()) { + BossBarSender sender = new BossBarSender(player, bossBarConfig, competition); + if (!sender.isVisible()) { + sender.show(); + } + senderMap.put(player.getUniqueId(), sender); + } + } + } + + public void unload() { + HandlerList.unregisterAll(this); + for (BossBarSender bossBarSender : senderMap.values()) { + bossBarSender.hide(); + } + senderMap.clear(); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + final Player player = event.getPlayer(); + BossBarSender sender = senderMap.remove(player.getUniqueId()); + if (sender != null) { + if (sender.isVisible()) + sender.hide(); + } + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + final Player player = event.getPlayer(); + CustomFishingPlugin.getInstance().getScheduler().runTaskAsyncLater(() -> { + boolean hasJoined = competition.hasPlayerJoined(player); + if ((hasJoined || bossBarConfig.isShowToAll()) + && !senderMap.containsKey(player.getUniqueId())) { + BossBarSender sender = new BossBarSender(player, bossBarConfig, competition); + if (!sender.isVisible()) { + sender.show(); + } + senderMap.put(player.getUniqueId(), sender); + } + }, 200, TimeUnit.MILLISECONDS); + } + + public void showBossBarTo(Player player) { + BossBarSender sender = senderMap.get(player.getUniqueId()); + if (sender == null) { + sender = new BossBarSender(player, bossBarConfig, competition); + senderMap.put(player.getUniqueId(), sender); + } + if (!sender.isVisible()) { + sender.show(); + } + } +} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarSender.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarSender.java similarity index 50% rename from src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarSender.java rename to plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarSender.java index 9669c964..2784103b 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarSender.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/bossbar/BossBarSender.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing.competition.bossbar; +package net.momirealms.customfishing.mechanic.competition.bossbar; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.InternalStructure; @@ -23,78 +23,82 @@ import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.wrappers.WrappedChatComponent; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.competition.Competition; -import net.momirealms.customfishing.object.DynamicText; -import net.momirealms.customfishing.object.Reflection; -import net.momirealms.customfishing.util.AdventureUtils; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.competition.BossBarConfig; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.api.util.ReflectionUtils; +import net.momirealms.customfishing.mechanic.competition.Competition; +import net.momirealms.customfishing.setting.Locale; +import net.momirealms.customfishing.util.DynamicText; import org.bukkit.boss.BarColor; import org.bukkit.entity.Player; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.UUID; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public class BossBarSender { private final Player player; - private int timer_1; - private int timer_2; + private int refreshTimer; + private int switchTimer; private int counter; - private final int size; private final DynamicText[] texts; - private DynamicText text; - private ScheduledFuture senderTask; + private CancellableTask senderTask; private final UUID uuid; - private boolean force; private final BossBarConfig config; private boolean isShown; - private boolean hasClaimedJoin; + private final Competition competition; + private final HashMap privatePlaceholders; - public void setText(int position) { - this.text = texts[position]; - this.force = true; - } - - public BossBarSender(Player player, BossBarConfig config) { - String[] str = config.getText(); - this.size = str.length; - texts = new DynamicText[str.length]; - for (int i = 0; i < str.length; i++) { - texts[i] = new DynamicText(player, str[i]); - } - text = texts[0]; + public BossBarSender(Player player, BossBarConfig config, Competition competition) { this.player = player; this.uuid = UUID.randomUUID(); this.config = config; this.isShown = false; + this.competition = competition; + this.privatePlaceholders = new HashMap<>(); + this.privatePlaceholders.put("{player}", player.getName()); + this.updatePrivatePlaceholders(); + + String[] str = config.getTexts(); + texts = new DynamicText[str.length]; + for (int i = 0; i < str.length; i++) { + texts[i] = new DynamicText(player, str[i]); + texts[i].update(privatePlaceholders); + } + } + + @SuppressWarnings("DuplicatedCode") + private void updatePrivatePlaceholders() { + this.privatePlaceholders.put("{score}", String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()))); + int rank = competition.getRanking().getPlayerRank(player.getName()); + this.privatePlaceholders.put("{rank}", rank != -1 ? String.valueOf(rank) : Locale.MSG_No_Rank); + this.privatePlaceholders.putAll(competition.getPublicPlaceholders()); } public void show() { this.isShown = true; - CustomFishing.getProtocolManager().sendServerPacket(player, getCreatePacket()); - senderTask = CustomFishing.getInstance().getScheduler().runTaskTimerAsync(() -> { - if (size != 1) { - timer_2++; - if (timer_2 > config.getInterval()) { - timer_2 = 0; - counter++; - if (counter == size) { - counter = 0; - } - setText(counter); - } + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getCreatePacket()); + senderTask = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> { + switchTimer++; + if (switchTimer > config.getSwitchInterval()) { + switchTimer = 0; + counter++; } - if (timer_1 < config.getRate()){ - timer_1++; + if (refreshTimer < config.getRefreshRate()){ + refreshTimer++; } else { - timer_1 = 0; - if (text.update() || force) { - force = false; - CustomFishing.getProtocolManager().sendServerPacket(player, getUpdatePacket()); - CustomFishing.getProtocolManager().sendServerPacket(player, getProgressPacket()); + refreshTimer = 0; + DynamicText text = texts[counter % (texts.length)]; + updatePrivatePlaceholders(); + if (text.update(privatePlaceholders)) { + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getUpdatePacket(text)); } + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getProgressPacket()); } }, 50, 50, TimeUnit.MILLISECONDS); } @@ -108,17 +112,21 @@ public class BossBarSender { } public void hide() { - sendRemovePacket(); - if (senderTask != null && !senderTask.isCancelled()) senderTask.cancel(false); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getRemovePacket()); + if (senderTask != null && !senderTask.isCancelled()) senderTask.cancel(); this.isShown = false; } - private PacketContainer getUpdatePacket() { + private PacketContainer getUpdatePacket(DynamicText text) { PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS); packet.getModifier().write(0, uuid); try { - Object chatComponent = Reflection.iChatComponentMethod.invoke(null, GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(AdventureUtils.replaceLegacy(text.getLatestValue())))); - Object updatePacket = Reflection.updateConstructor.newInstance(chatComponent); + Object chatComponent = ReflectionUtils.iChatComponentMethod.invoke(null, + GsonComponentSerializer.gson().serialize( + AdventureManagerImpl.getInstance().getComponentFromMiniMessage( + AdventureManagerImpl.getInstance().legacyToMiniMessage(text.getLatestValue()) + ))); + Object updatePacket = ReflectionUtils.updateConstructor.newInstance(chatComponent); packet.getModifier().write(1, updatePacket); } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) { throw new RuntimeException(e); @@ -130,7 +138,7 @@ public class BossBarSender { PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS); packet.getModifier().write(0, uuid); try { - Object updatePacket = Reflection.progressConstructor.newInstance(Competition.currentCompetition.getProgress()); + Object updatePacket = ReflectionUtils.progressConstructor.newInstance(competition.getProgress()); packet.getModifier().write(1, updatePacket); } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) { throw new RuntimeException(e); @@ -142,28 +150,20 @@ public class BossBarSender { PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS); packet.getModifier().write(0, uuid); InternalStructure internalStructure = packet.getStructures().read(1); - internalStructure.getChatComponents().write(0, WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(text.getLatestValue())))); - internalStructure.getFloat().write(0, Competition.currentCompetition.getProgress()); + internalStructure.getChatComponents().write(0, WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(texts[0].getLatestValue())))); + internalStructure.getFloat().write(0, competition.getProgress()); internalStructure.getEnumModifier(BarColor.class, 2).write(0, config.getColor()); - internalStructure.getEnumModifier(BossBarOverlay.class, 3).write(0, config.getOverlay()); + internalStructure.getEnumModifier(BossBarConfig.Overlay.class, 3).write(0, config.getOverlay()); internalStructure.getModifier().write(4, false); internalStructure.getModifier().write(5, false); internalStructure.getModifier().write(6, false); return packet; } - private void sendRemovePacket() { + private PacketContainer getRemovePacket() { PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS); packet.getModifier().write(0, uuid); - packet.getModifier().write(1, Reflection.removeBossBarPacket); - CustomFishing.getProtocolManager().sendServerPacket(player, packet); - } - - public boolean hasClaimedJoin() { - return hasClaimedJoin; - } - - public void setHasClaimedJoinReward(boolean hasClaimedJoin) { - this.hasClaimedJoin = hasClaimedJoin; + packet.getModifier().write(1, ReflectionUtils.removeBossBarPacket); + return packet; } } diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/ranking/LocalRankingImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/LocalRankingImpl.java similarity index 76% rename from src/main/java/net/momirealms/customfishing/fishing/competition/ranking/LocalRankingImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/LocalRankingImpl.java index c48ca828..8b8fd5d7 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/ranking/LocalRankingImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/LocalRankingImpl.java @@ -15,22 +15,28 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing.competition.ranking; +package net.momirealms.customfishing.mechanic.competition.ranking; -import net.momirealms.customfishing.fishing.competition.CompetitionPlayer; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer; +import net.momirealms.customfishing.api.mechanic.competition.Ranking; import java.util.*; -public class LocalRankingImpl implements RankingInterface { +public class LocalRankingImpl implements Ranking { - private final Set competitionPlayers = Collections.synchronizedSet(new TreeSet<>()); + private final Set competitionPlayers; + + public LocalRankingImpl() { + competitionPlayers = Collections.synchronizedSet(new TreeSet<>()); + } public void addPlayer(CompetitionPlayer competitionPlayer) { competitionPlayers.add(competitionPlayer); } public void removePlayer(CompetitionPlayer competitionPlayer) { - competitionPlayers.removeIf(e -> e == competitionPlayer); + competitionPlayers.removeIf(e -> e.equals(competitionPlayer)); } @Override @@ -49,10 +55,10 @@ public class LocalRankingImpl implements RankingInterface { } @Override - public Iterator getIterator() { - List players = new ArrayList<>(); + public Iterator> getIterator() { + List> players = new ArrayList<>(); for (CompetitionPlayer competitionPlayer: competitionPlayers){ - players.add(competitionPlayer.getPlayer()); + players.add(Pair.of(competitionPlayer.getPlayer(), competitionPlayer.getScore())); } return players.iterator(); } @@ -63,20 +69,20 @@ public class LocalRankingImpl implements RankingInterface { } @Override - public String getPlayerRank(String player) { + public int getPlayerRank(String player) { int index = 1; for (CompetitionPlayer competitionPlayer : competitionPlayers) { if (competitionPlayer.getPlayer().equals(player)) { - return String.valueOf(index); + return index; }else { index++; } } - return null; + return -1; } @Override - public float getPlayerScore(String player) { + public double getPlayerScore(String player) { for (CompetitionPlayer competitionPlayer : competitionPlayers) { if (competitionPlayer.getPlayer().equals(player)) { return competitionPlayer.getScore(); @@ -98,7 +104,7 @@ public class LocalRankingImpl implements RankingInterface { } @Override - public float getScoreAt(int i) { + public double getScoreAt(int i) { int index = 1; for (CompetitionPlayer competitionPlayer : competitionPlayers) { if (index == i) { @@ -110,7 +116,7 @@ public class LocalRankingImpl implements RankingInterface { } @Override - public void refreshData(String player, float score) { + public void refreshData(String player, double score) { CompetitionPlayer competitionPlayer = getCompetitionPlayer(player); if (competitionPlayer != null) { removePlayer(competitionPlayer); @@ -123,7 +129,7 @@ public class LocalRankingImpl implements RankingInterface { } @Override - public void setData(String player, float score) { + public void setData(String player, double score) { CompetitionPlayer competitionPlayer = getCompetitionPlayer(player); if (competitionPlayer != null) { removePlayer(competitionPlayer); diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/RedisRankingImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/RedisRankingImpl.java new file mode 100644 index 00000000..b9a8ac46 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/ranking/RedisRankingImpl.java @@ -0,0 +1,115 @@ +/* + * 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.mechanic.competition.ranking; + +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.competition.CompetitionPlayer; +import net.momirealms.customfishing.api.mechanic.competition.Ranking; +import net.momirealms.customfishing.storage.method.database.nosql.RedisManager; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.resps.Tuple; + +import java.util.Iterator; +import java.util.List; + +public class RedisRankingImpl implements Ranking { + + @Override + public void clear() { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + jedis.zremrangeByRank("cf_competition",0,-1); + } + } + + @Override + public CompetitionPlayer getCompetitionPlayer(String player) { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + Double score = jedis.zscore("cf_competition", player); + if (score == null || score == 0) return null; + return new CompetitionPlayer(player, Float.parseFloat(score.toString())); + } + } + + @Override + public Iterator> getIterator() { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + List players = jedis.zrevrangeWithScores("cf_competition", 0, -1); + return players.stream().map(it -> Pair.of(it.getElement(), it.getScore())).toList().iterator(); + } + } + + @Override + public int getSize() { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + long size = jedis.zcard("cf_competition"); + return (int) size; + } + } + + @Override + public int getPlayerRank(String player) { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + Long rank = jedis.zrevrank("cf_competition", player); + if (rank == null) + return -1; + return (int) (rank + 1); + } + } + + @Override + public double getPlayerScore(String player) { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + Double rank = jedis.zscore("cf_competition", player); + if (rank == null) + return 0; + return rank.floatValue(); + } + } + + @Override + public void refreshData(String player, double score) { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + jedis.zincrby("cf_competition", score, player); + } + } + + @Override + public void setData(String player, double score) { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + jedis.zadd("cf_competition", score, player); + } + } + + @Override + public String getPlayerAt(int rank) { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + List player = jedis.zrevrange("cf_competition", rank - 1, rank -1); + if (player == null || player.size() == 0) return null; + return player.get(0); + } + } + + @Override + public double getScoreAt(int rank) { + try (Jedis jedis = RedisManager.getInstance().getJedis()) { + List players = jedis.zrevrangeWithScores("cf_competition", rank - 1, rank -1); + if (players == null || players.size() == 0) return 0; + return players.get(0).getScore(); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java new file mode 100644 index 00000000..dc46dc15 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/effect/EffectManagerImpl.java @@ -0,0 +1,114 @@ +package net.momirealms.customfishing.mechanic.effect; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Key; +import net.momirealms.customfishing.api.manager.EffectManager; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.mechanic.effect.FishingEffect; +import net.momirealms.customfishing.util.ConfigUtils; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.*; + +public class EffectManagerImpl implements EffectManager { + + private final CustomFishingPlugin plugin; + + private final HashMap effectMap; + + public EffectManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.effectMap = new HashMap<>(); + } + + @Override + public boolean registerEffect(Key key, Effect effect) { + if (effectMap.containsKey(key)) return false; + this.effectMap.put(key, effect); + return true; + } + + @Override + public boolean unregisterEffect(Key key) { + return this.effectMap.remove(key) != null; + } + + @Nullable + @Override + public Effect getEffect(String namespace, String id) { + return effectMap.get(Key.of(namespace, id)); + } + + @SuppressWarnings("DuplicatedCode") + public void load() { + Deque fileDeque = new ArrayDeque<>(); + for (String type : List.of("rods", "baits", "enchants", "utils", "totems")) { + 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()) { + this.loadSingleFile(subFile, StringUtils.chop(type)); + } + } + } + } + } + + 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) { + effectMap.put(Key.of(namespace, value), getFishingEffectFromSection(section)); + } + } + } + + private Effect getFishingEffectFromSection(ConfigurationSection section) { + if (section == null) return getInitialEffect(); + return new FishingEffect.Builder() + .lootWeightModifier(ConfigUtils.getModifiers(section.getStringList("weight"))) + .timeModifier(section.getDouble("hook-time", 1)) + .difficultyModifier(section.getDouble("difficulty", 0)) + .multipleLootChance(section.getDouble("multiple-loot")) + .lavaFishing(section.getBoolean("lava-fishing", false)) + .scoreMultiplier(section.getDouble("score-bonus", 1)) + .sizeMultiplier(section.getDouble("size-bonus", 1)) + .gameTimeModifier(section.getDouble("game-time", 0)) + .requirements(plugin.getRequirementManager().getRequirements(section.getConfigurationSection("requirements"), true)) + .build(); + } + + public void unload() { + HashMap temp = new HashMap<>(effectMap); + effectMap.clear(); + for (Map.Entry entry : temp.entrySet()) { + if (entry.getValue().persist()) { + effectMap.put(entry.getKey(), entry.getValue()); + } + } + } + + @Override + public Effect getInitialEffect() { + return new FishingEffect.Builder().build(); + } + + public void disable() { + this.effectMap.clear(); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/BaitAnimationTask.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/BaitAnimationTask.java new file mode 100644 index 00000000..5678419d --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/BaitAnimationTask.java @@ -0,0 +1,49 @@ +package net.momirealms.customfishing.mechanic.fishing; + +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.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; + +public class BaitAnimationTask implements Runnable { + + private final CancellableTask cancellableTask; + private final int entityID; + private final Player player; + private final FishHook fishHook; + + public BaitAnimationTask(CustomFishingPlugin plugin, Player player, FishHook fishHook, ItemStack baitItem) { + this.player = player; + this.fishHook = fishHook; + entityID = ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getSpawnPacket(entityID, fishHook.getLocation())); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(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 { + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getVelocity(entityID, fishHook.getVelocity())); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getTpPacket(entityID, fishHook.getLocation())); + } + } + + private void cancelAnimation() { + cancellableTask.cancel(); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, FakeItemUtils.getDestroyPacket(entityID)); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java new file mode 100644 index 00000000..8a1c48d2 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java @@ -0,0 +1,570 @@ +package net.momirealms.customfishing.mechanic.fishing; + +import com.destroystokyo.paper.event.player.PlayerJumpEvent; +import de.tr7zw.changeme.nbtapi.NBTItem; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.event.LavaFishingEvent; +import net.momirealms.customfishing.api.event.RodCastEvent; +import net.momirealms.customfishing.api.manager.FishingManager; +import net.momirealms.customfishing.api.manager.RequirementManager; +import net.momirealms.customfishing.api.mechanic.TempFishingState; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.mechanic.game.Game; +import net.momirealms.customfishing.api.mechanic.game.GameConfig; +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.Modifier; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.api.util.WeightUtils; +import net.momirealms.customfishing.mechanic.loot.LootManagerImpl; +import net.momirealms.customfishing.mechanic.requirement.RequirementManagerImpl; +import net.momirealms.customfishing.setting.Config; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.Statistic; +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.inventory.InventoryPickupItemEvent; +import org.bukkit.event.player.PlayerAttemptPickupItemEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class FishingManagerImpl implements Listener, FishingManager { + + private final CustomFishingPluginImpl plugin; + private final ConcurrentHashMap hookCacheMap; + private final ConcurrentHashMap hookCheckMap; + private final ConcurrentHashMap tempFishingStateMap; + private final ConcurrentHashMap gamingPlayerMap; + private final ConcurrentHashMap vanillaLootMap; + + public FishingManagerImpl(CustomFishingPluginImpl 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 (Config.eventPriority != EventPriority.MONITOR) return; + this.selectState(event); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onFishHIGHEST(PlayerFishEvent event) { + if (Config.eventPriority != EventPriority.HIGHEST) return; + this.selectState(event); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onFishHIGH(PlayerFishEvent event) { + if (Config.eventPriority != EventPriority.HIGH) return; + this.selectState(event); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onFishNORMAL(PlayerFishEvent event) { + if (Config.eventPriority != EventPriority.NORMAL) return; + this.selectState(event); + } + + @EventHandler(priority = EventPriority.LOW) + public void onFishLOW(PlayerFishEvent event) { + if (Config.eventPriority != EventPriority.LOW) return; + this.selectState(event); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onFishLOWEST(PlayerFishEvent event) { + if (Config.eventPriority != EventPriority.LOWEST) return; + this.selectState(event); + } + + @EventHandler + public void onPickUp(PlayerAttemptPickupItemEvent event) { + if (event.isCancelled()) return; + ItemStack itemStack = event.getItem().getItemStack(); + NBTItem nbtItem = new NBTItem(itemStack); + if (!nbtItem.hasTag("owner")) return; + if (!Objects.equals(nbtItem.getString("owner"), event.getPlayer().getName())) { + event.setCancelled(true); + } else { + nbtItem.removeKey("owner"); + itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); + } + } + + @EventHandler + public void onMove(InventoryPickupItemEvent event) { + if (event.isCancelled()) return; + ItemStack itemStack = event.getItem().getItemStack(); + NBTItem nbtItem = new NBTItem(itemStack); + if (!nbtItem.hasTag("owner")) return; + nbtItem.removeKey("owner"); + itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + this.removeHook(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onSwapHand(PlayerSwapHandItemsEvent event) { + if (event.isCancelled()) return; + 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); + } + } + + @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; + } + } + + 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); + } + } + + public void onCastRod(PlayerFishEvent event) { + var player = event.getPlayer(); + var fishingPreparation = new FishingPreparation(player, plugin); + if (!fishingPreparation.canFish()) { + event.setCancelled(true); + return; + } + // Check mechanic requirements + if (!RequirementManager.isRequirementsMet( + RequirementManagerImpl.mechanicRequirements, + fishingPreparation + )) { + return; + } + // Merge rod/bait/util effects + Effect initialEffect = plugin.getEffectManager().getInitialEffect(); + initialEffect + .merge(fishingPreparation.getRodEffect()) + .merge(fishingPreparation.getBaitEffect()); + + for (Effect utilEffect : fishingPreparation.getUtilEffects()) { + initialEffect.merge(utilEffect); + } + + // Apply enchants + for (String enchant : plugin.getIntegrationManager().getEnchantments(fishingPreparation.getRodItemStack())) { + Effect enchantEffect = plugin.getEffectManager().getEffect("enchant", enchant); + if (enchantEffect != null && enchantEffect.canMerge(fishingPreparation)) { + initialEffect.merge(enchantEffect); + } + } + //TODO Apply totem effects + + // Call custom event + RodCastEvent rodCastEvent = new RodCastEvent(event, 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); + fishHook.setMaxWaitTime((int) (fishHook.getMaxWaitTime() * initialEffect.getTimeModifier())); + fishHook.setMinWaitTime((int) (fishHook.getMinWaitTime() * initialEffect.getTimeModifier())); + // Reduce amount & Send animation + var baitItem = fishingPreparation.getBaitItemStack(); + if (baitItem != null) { + if (Config.enableBaitAnimation) { + ItemStack cloned = baitItem.clone(); + cloned.setAmount(1); + new BaitAnimationTask(plugin, player, fishHook, cloned); + } + baitItem.setAmount(baitItem.getAmount() - 1); + } + // Arrange hook check task + this.hookCheckMap.put(player.getUniqueId(), new HookCheckTimerTask(this, fishHook, fishingPreparation, initialEffect)); + } + + 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.BOOLEAN + ) != 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(); + } + } + + // TODO It's unsure if the hook would hook into other entities when playing a game + // TODO But it should not affect the game result + } + + 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.tempFishingStateMap.get(uuid); + if (temp != null ) { + var loot = temp.getLoot(); + if (loot.getID().equals("vanilla")) { + // put vanilla loot in map + this.vanillaLootMap.put(uuid, item.getItemStack()); + } + if (!loot.disableGame()) { + // start the game if the loot has a game + event.setCancelled(true); + startFishingGame(player, temp.getLoot(), temp.getEffect()); + } else { + // If the game is disabled, then do success actions + success(temp, event.getHook()); + // Cancel the event because loots can be multiple and unique + event.setCancelled(true); + event.getHook().remove(); + } + return; + } + + if (!Config.vanillaMechanicIfNoLoot) { + event.setCancelled(true); + event.getHook().remove(); + } + } + + 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 = gamingPlayerMap.get(uuid); + if (gamingPlayer != null) { + return; + } + + // If the loot's game is instant + TempFishingState temp = tempFishingStateMap.get(uuid); + if (temp != null) { + var loot = temp.getLoot(); + + Action[] actions = loot.getActions(ActionTrigger.HOOK); + if (actions != null) + for (Action action : actions) + action.trigger(temp.getPreparation()); + + if (loot.instanceGame() && !loot.disableGame()) { + startFishingGame(player, loot, temp.getEffect()); + } + } + } + + private void onReelIn(PlayerFishEvent event) { + final Player player = event.getPlayer(); + final UUID uuid = player.getUniqueId(); + + // If player is in game + GamingPlayer gamingPlayer = gamingPlayerMap.get(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 = this.tempFishingStateMap.get(uuid); + if (temp != null ) { + if (!temp.getLoot().disableGame()) { + event.setCancelled(true); + startFishingGame(player, temp.getLoot(), temp.getEffect()); + } else { + success(temp, event.getHook()); + } + } + } + } + + @Override + public void removeTempFishingState(Player player) { + this.tempFishingStateMap.remove(player.getUniqueId()); + } + + @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 = tempFishingStateMap.remove(uuid); + 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); + + if (gamingPlayer.isSucceeded()) + success(tempFishingState, fishHook); + else + fail(tempFishingState); + + // remove hook because some games don't depend on right clicks + fishHook.remove(); + gamingPlayer.cancel(); + gamingPlayerMap.remove(uuid); + } + + public void fail(TempFishingState state) { + var loot = state.getLoot(); + var fishingPreparation = state.getPreparation(); + + if (loot.getID().equals("vanilla")) { + ItemStack itemStack = this.vanillaLootMap.remove(fishingPreparation.getPlayer().getUniqueId()); + if (itemStack != null) { + fishingPreparation.insertArg("loot", ""); + } + } + + Action[] globalActions = LootManagerImpl.globalLootProperties.getActions(ActionTrigger.FAILURE); + if (globalActions != null) + for (Action action : globalActions) + action.trigger(fishingPreparation); + + Action[] actions = loot.getActions(ActionTrigger.FAILURE); + if (actions != null) + for (Action action : actions) + action.trigger(fishingPreparation); + } + + public void success(TempFishingState state, FishHook hook) { + var loot = state.getLoot(); + var effect = state.getEffect(); + var fishingPreparation = state.getPreparation(); + var player = fishingPreparation.getPlayer(); + + int amount = (int) effect.getMultipleLootChance(); + amount += Math.random() < (effect.getMultipleLootChance() - amount) ? 2 : 1; + + fishingPreparation.insertArg("{amount}", String.valueOf(amount)); + fishingPreparation.insertArg("{score}", String.format("%.2f", loot.getScore() * effect.getScoreMultiplier())); + fishingPreparation.insertArg("{size-multiplier}", String.format("%.2f", effect.getSizeMultiplier())); + fishingPreparation.insertArg("{x}", String.valueOf(hook.getLocation().getBlockX())); + fishingPreparation.insertArg("{y}", String.valueOf(hook.getLocation().getBlockY())); + fishingPreparation.insertArg("{z}", String.valueOf(hook.getLocation().getBlockZ())); + fishingPreparation.insertArg("{loot}", loot.getID()); + fishingPreparation.insertArg("{nick}", loot.getNick()); + fishingPreparation.insertArg("{score}", String.format("%.2f", loot.getScore())); + + switch (loot.getType()) { + case LOOT -> { + // build the items for multiple times instead of using setAmount() to make sure that each item is unique + if (loot.getID().equals("vanilla")) { + ItemStack itemStack = vanillaLootMap.remove(player.getUniqueId()); + if (itemStack != null) { + fishingPreparation.insertArg("{loot}", ""); + for (int i = 0; i < amount; i++) { + plugin.getItemManager().dropItem(hook.getLocation(), player.getLocation(), itemStack.clone()); + doActions(loot, fishingPreparation, player); + } + } + } else { + for (int i = 0; i < amount; i++) { + plugin.getItemManager().dropItem(player, hook.getLocation(), player.getLocation(), loot, fishingPreparation.getArgs()); + doActions(loot, fishingPreparation, player); + } + } + return; + } + case MOB -> plugin.getMobManager().summonMob(hook.getLocation(), player.getLocation(), loot); + case BLOCK -> plugin.getBlockManager().summonBlock(player, hook.getLocation(), player.getLocation(), loot); + } + doActions(loot, fishingPreparation, player); + } + + private void doActions(Loot loot, FishingPreparation fishingPreparation, Player player) { + Action[] globalActions = LootManagerImpl.globalLootProperties.getActions(ActionTrigger.SUCCESS); + if (globalActions != null) + for (Action action : globalActions) + action.trigger(fishingPreparation); + + Action[] actions = loot.getActions(ActionTrigger.SUCCESS); + if (actions != null) + for (Action action : actions) + action.trigger(fishingPreparation); + + player.setStatistic( + Statistic.FISH_CAUGHT, + player.getStatistic(Statistic.FISH_CAUGHT) + 1 + ); + } + + @Nullable + public Loot getNextLoot(Effect initialEffect, FishingPreparation fishingPreparation) { + HashMap lootWithWeight = plugin.getRequirementManager().getLootWithWeight(fishingPreparation); + if (lootWithWeight.size() == 0) { + LogUtils.warn(String.format("No Loot found at %s for Player %s!", fishingPreparation.getPlayer().getLocation(), fishingPreparation.getPlayer().getName())); + return null; + } + + for (Pair pair : initialEffect.getLootWeightModifier()) { + double previous = lootWithWeight.getOrDefault(pair.left(), 0d); + lootWithWeight.put(pair.left(), pair.right().modify(previous)); + } + + String key = WeightUtils.getRandom(lootWithWeight); + Loot loot = plugin.getLootManager().getLoot(key); + if (loot == null) { + LogUtils.warn(String.format("Loot %s doesn't exist!", key)); + return null; + } + return loot; + } + + @Override + public void startFishingGame(Player player, Loot loot, Effect effect) { + GameConfig gameConfig = loot.getGameConfig(); + if (gameConfig == null) { + gameConfig = plugin.getGameManager().getRandomGameConfig(); + } + var gamePair = gameConfig.getRandomGame(effect); + if (gamePair == null) { + return; + } + startFishingGame(player, gamePair.right(), gamePair.left()); + } + + @Override + public void startFishingGame(Player player, GameSettings settings, Game game) { + this.gamingPlayerMap.put(player.getUniqueId(), game.start(player, settings, this)); + } + + @Override + public void setTempFishingState(Player player, TempFishingState tempFishingState) { + tempFishingStateMap.put(player.getUniqueId(), tempFishingState); + } + + @Override + public void removeHookCheckTask(Player player) { + hookCheckMap.remove(player.getUniqueId()); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java new file mode 100644 index 00000000..4480beac --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java @@ -0,0 +1,225 @@ +package net.momirealms.customfishing.mechanic.fishing; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.event.LavaFishingEvent; +import net.momirealms.customfishing.api.mechanic.TempFishingState; +import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation; +import net.momirealms.customfishing.api.mechanic.effect.Effect; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.setting.Config; +import net.momirealms.customfishing.util.ArmorStandUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +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; + +public class HookCheckTimerTask implements Runnable { + + private final FishingManagerImpl manager; + private final CancellableTask hookMovementTask; + private LavaEffectTask lavaFishingTask; + private final FishHook fishHook; + private final FishingPreparation fishingPreparation; + private final Effect initialEffect; + private final int lureLevel; + private boolean firstTime; + private boolean fishHooked; + private boolean reserve; + private int jumpTimer; + private Entity hookedEntity; + + public HookCheckTimerTask( + FishingManagerImpl manager, + FishHook fishHook, + FishingPreparation fishingPreparation, + Effect initialEffect + ) { + this.manager = manager; + this.fishHook = fishHook; + this.initialEffect = initialEffect; + this.fishingPreparation = fishingPreparation; + this.hookMovementTask = CustomFishingPlugin.get().getScheduler().runTaskSyncTimer(this, fishHook.getLocation(), 1, 1); + this.lureLevel = fishingPreparation.getRodItemStack().getEnchantmentLevel(Enchantment.LURE); + this.firstTime = true; + } + + @Override + public void run() { + if ( + !fishHook.isValid() + || fishHook.isOnGround() + || (fishHook.getHookedEntity() != null && fishHook.getHookedEntity().getType() != EntityType.ARMOR_STAND) + ) { + // This task would be cancelled when hook is not at a proper place + // or player reels in before it goes into water or lava + this.destroy(); + return; + } + if (fishHook.getLocation().getBlock().getType() == Material.LAVA) { + // if player can fish in lava + if (!initialEffect.canLavaFishing()) { + this.destroy(); + return; + } + if (firstTime) { + this.fishingPreparation.insertArg("in-lava", "true"); + if (Config.enableSplashAnimation) + ArmorStandUtils.sendAnimationToPlayer( + fishingPreparation.getPlayer(), + fishHook.getLocation(), + CustomFishingPlugin.get().getItemManager().build(null, "util", Config.lavaSplashItem), + Config.splashAnimationTime + ); + firstTime = false; + this.setTempState(); + } + // simulate fishing mechanic + if (fishHooked) { + jumpTimer++; + if (jumpTimer < 4) + return; + jumpTimer = 0; + fishHook.setVelocity(new Vector(0,0.24,0)); + return; + } + if (!reserve) { + if (jumpTimer < 5) { + jumpTimer++; + fishHook.setVelocity(new Vector(0,0.2 - jumpTimer * 0.02,0)); + return; + } + reserve = true; + this.startLavaFishingMechanic(); + this.makeHookStatic(fishHook.getLocation()); + } + return; + } + if (fishHook.isInWater()) { + // if the hook is in water + // then cancel the task + this.fishingPreparation.insertArg("in-lava", "false"); + if (Config.enableSplashAnimation) + ArmorStandUtils.sendAnimationToPlayer( + fishingPreparation.getPlayer(), + fishHook.getLocation(), + CustomFishingPlugin.get().getItemManager().build(null, "util", Config.waterSplashItem), + Config.splashAnimationTime + ); + this.destroy(); + this.setTempState(); + return; + } + } + + public void destroy() { + this.cancelSubTask(); + this.removeTempEntity(); + this.hookMovementTask.cancel(); + this.manager.removeHookCheckTask(fishingPreparation.getPlayer()); + } + + public void cancelSubTask() { + if (lavaFishingTask != null && !lavaFishingTask.isCancelled()) { + lavaFishingTask.cancel(); + lavaFishingTask = null; + } + } + + private void setTempState() { + Loot nextLoot = manager.getNextLoot(initialEffect, fishingPreparation); + if (nextLoot == null) + return; + fishingPreparation.insertArg("loot", nextLoot.getNick()); + fishingPreparation.insertArg("id", nextLoot.getID()); + CustomFishingPlugin.get().getScheduler().runTaskAsync(() -> manager.setTempFishingState(fishingPreparation.getPlayer(), new TempFishingState( + initialEffect, + fishingPreparation, + nextLoot + ))); + } + + public void removeTempEntity() { + if (hookedEntity != null && !hookedEntity.isDead()) + hookedEntity.remove(); + } + + private void startLavaFishingMechanic() { + // get random time + int random = ThreadLocalRandom.current().nextInt(Config.lavaMinTime, Config.lavaMaxTime); + random -= lureLevel * 100; + random *= initialEffect.getTimeModifier(); + random = Math.max(Config.lavaMinTime, random); + + // lava effect task (Three seconds in advance) + this.lavaFishingTask = new LavaEffectTask( + this, + fishHook.getLocation(), + random - 3 * 20 + ); + } + + public void getHooked() { + LavaFishingEvent lavaFishingEvent = new LavaFishingEvent(fishingPreparation.getPlayer(), LavaFishingEvent.State.BITE, fishHook); + Bukkit.getPluginManager().callEvent(lavaFishingEvent); + if (lavaFishingEvent.isCancelled()) { + this.startLavaFishingMechanic(); + return; + } + + this.fishHooked = true; + this.removeTempEntity(); + + AdventureManagerImpl.getInstance().sendSound( + fishingPreparation.getPlayer(), + Sound.Source.NEUTRAL, + Key.key("minecraft:block.pointed_dripstone.drip_lava_into_cauldron"), + 1, + 1 + ); + + CustomFishingPlugin.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", CustomFishingPlugin.get())), + PersistentDataType.BOOLEAN, + true + ); + }); + fishHook.setHookedEntity(hookedEntity); + } + + public boolean isFishHooked() { + return fishHooked; + } +} diff --git a/src/main/java/net/momirealms/customfishing/fishing/LavaEffect.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/LavaEffectTask.java similarity index 60% rename from src/main/java/net/momirealms/customfishing/fishing/LavaEffect.java rename to plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/LavaEffectTask.java index 7f6f05b7..ec4b4592 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/LavaEffect.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/LavaEffectTask.java @@ -15,35 +15,43 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.fishing; +package net.momirealms.customfishing.mechanic.fishing; -import net.momirealms.customfishing.CustomFishing; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.scheduler.CancellableTask; import org.bukkit.Location; import org.bukkit.Particle; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -public class LavaEffect implements Runnable { +public class LavaEffectTask implements Runnable { private final Location startLoc; private final Location endLoc; private final Location controlLoc; private int timer; - private final ScheduledFuture lavaTask; + private final CancellableTask lavaTask; + private final HookCheckTimerTask hookCheckTimerTask; - public LavaEffect(Location loc, int delay) { + public LavaEffectTask(HookCheckTimerTask hookCheckTimerTask, Location loc, int delay) { + this.hookCheckTimerTask = hookCheckTimerTask; this.startLoc = loc.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 = CustomFishing.getInstance().getScheduler().runTaskTimerAsync(this, delay * 50L, 50, TimeUnit.MILLISECONDS); + 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 = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, delay * 50L, 50, TimeUnit.MILLISECONDS); } @Override public void run() { timer++; if (timer > 60) { - lavaTask.cancel(false); + lavaTask.cancel(); + CustomFishingPlugin.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))); @@ -53,7 +61,8 @@ public class LavaEffect implements Runnable { } public void cancel() { - lavaTask.cancel(false); + if (lavaTask != null && !lavaTask.isCancelled()) + lavaTask.cancel(); } public boolean isCancelled() { diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java new file mode 100644 index 00000000..b80bc134 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java @@ -0,0 +1,213 @@ +package net.momirealms.customfishing.mechanic.game; + +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.GameManager; +import net.momirealms.customfishing.api.mechanic.game.*; +import net.momirealms.customfishing.api.util.FontUtils; +import net.momirealms.customfishing.api.util.OffsetUtils; +import net.momirealms.customfishing.util.ConfigUtils; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +public class GameManagerImpl implements GameManager { + + private final CustomFishingPlugin plugin; + private final HashMap gameCreatorMap; + private final HashMap gameMap; + private final HashMap gameConfigMap; + + public GameManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.gameCreatorMap = new HashMap<>(); + this.gameMap = new HashMap<>(); + this.gameConfigMap = new HashMap<>(); + this.registerInbuiltGames(); + } + + private void registerInbuiltGames() { + this.registerAccurateClickGame(); + } + + public void load() { + this.loadGamesFromPluginFolder(); + this.loadGameConfigs(); + } + + public void unload() { + this.gameMap.clear(); + this.gameConfigMap.clear(); + } + + public void disable() { + unload(); + this.gameCreatorMap.clear(); + } + + @Override + public boolean registerGameType(String type, GameCreator gameCreator) { + if (gameCreatorMap.containsKey(type)) + return false; + else + gameCreatorMap.put(type, gameCreator); + return true; + } + + @Override + public boolean unregisterGameType(String type) { + return gameCreatorMap.remove(type) != null; + } + + @Override + @Nullable + public GameCreator getGameCreator(String type) { + return gameCreatorMap.get(type); + } + + @Override + @Nullable + public Game getGame(String key) { + return gameMap.get(key); + } + + @Override + @Nullable + public GameConfig getGameConfig(String key) { + return gameConfigMap.get(key); + } + + @Override + public Game getRandomGame() { + Collection collection = gameMap.values(); + return (Game) collection.toArray()[ThreadLocalRandom.current().nextInt(collection.size())]; + } + + @Override + public GameConfig getRandomGameConfig() { + Collection collection = gameConfigMap.values(); + return (GameConfig) collection.toArray()[ThreadLocalRandom.current().nextInt(collection.size())]; + } + + public void loadGameConfigs() { + YamlConfiguration config = plugin.getConfig("game-groups.yml"); + for (Map.Entry entry : config.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection section) { + if (section.contains("groups")) { + gameConfigMap.put(entry.getKey(), new GameGroups(ConfigUtils.getWeights(section.getStringList("groups")))); + } else if (section.contains("games")) { + var pair1 = ConfigUtils.splitStringIntegerArgs(section.getString("difficulty", "1~100")); + var pair2 = ConfigUtils.splitStringIntegerArgs(section.getString("time", "10~20")); + gameConfigMap.put(entry.getKey(), + new GameGroup(ConfigUtils.getWeights(section.getStringList("games"))) + .difficulty(pair1.left(), pair1.right()) + .time(pair2.left(), pair2.right()) + ); + } + } + } + } + + public void loadGamesFromPluginFolder() { + Deque fileDeque = new ArrayDeque<>(); + File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "minigames"); + if (!typeFolder.exists()) { + if (!typeFolder.mkdirs()) return; + plugin.saveResource("contents" + File.separator + "minigames" + 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()) { + loadSingleFile(subFile); + } + } + } + } + + private void loadSingleFile(File file) { + YamlConfiguration config = YamlConfiguration.loadConfiguration(file); + for (Map.Entry entry : config.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection section) { + GameCreator creator = this.getGameCreator(section.getString("game-type")); + if (creator != null) { + gameMap.put(entry.getKey(), 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 = section.getString("title"); + var font = section.getString("subtitle.font"); + var barImage = section.getString("subtitle.bar"); + var pointerImage = section.getString("subtitle.pointer"); + + return (player, settings, manager) -> new AbstractGamingPlayer(player, settings, manager) { + + private int progress; + private boolean face; + + @Override + public void arrangeTask() { + var period = ((double) 10*(200-settings.getDifficulty()))/((double) (1+4*settings.getDifficulty())); + this.task = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer( + this, + 50, + (long) period, + TimeUnit.MILLISECONDS + ); + } + + @Override + public void run() { + super.run(); + 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); + AdventureManagerImpl.getInstance().sendTitle(player, title, bar,0,500,0); + } + + @Override + public boolean isSucceeded() { + int last = progress / widthPerSection; + return (Math.random() < successRate[last]); + } + }; + })); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java new file mode 100644 index 00000000..baf0f00f --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java @@ -0,0 +1,554 @@ +package net.momirealms.customfishing.mechanic.item; + +import de.tr7zw.changeme.nbtapi.*; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.common.Key; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.manager.ItemManager; +import net.momirealms.customfishing.api.mechanic.item.BuildableItem; +import net.momirealms.customfishing.api.mechanic.item.ItemBuilder; +import net.momirealms.customfishing.api.mechanic.item.ItemLibrary; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.item.CustomFishingItemImpl; +import net.momirealms.customfishing.compatibility.item.VanillaItemImpl; +import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.setting.Config; +import net.momirealms.customfishing.util.NBTUtils; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +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; + +public class ItemManagerImpl implements ItemManager { + + private static ItemManager instance; + private final CustomFishingPlugin plugin; + private final HashMap buildableItemMap; + private final HashMap itemLibraryMap; + + public ItemManagerImpl(CustomFishingPlugin plugin) { + instance = this; + this.plugin = plugin; + this.itemLibraryMap = new LinkedHashMap<>(); + this.buildableItemMap = new HashMap<>(); + this.registerItemLibrary(new CustomFishingItemImpl()); + this.registerItemLibrary(new VanillaItemImpl()); + } + + public void load() { + this.loadItemsFromPluginFolder(); + AdventureManagerImpl.getInstance().sendMessageWithPrefix(Bukkit.getConsoleSender(), "Loaded " + buildableItemMap.size() + " items."); + } + + public void unload() { + 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()); + } + } + } + + @Override + public Set getAllItemsKey() { + return buildableItemMap.keySet(); + } + + public void disable() { + this.buildableItemMap.clear(); + this.itemLibraryMap.clear(); + } + + @SuppressWarnings("DuplicatedCode") + public void loadItemsFromPluginFolder() { + Deque fileDeque = new ArrayDeque<>(); + for (String type : List.of("loots", "baits", "rods", "utils")) { + 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()) { + this.loadSingleFile(subFile, StringUtils.chop(type)); + } + } + } + } + } + + 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)); + } + } + } + } + + @Override + public boolean registerCustomItem(String namespace, String value, BuildableItem buildableItem) { + Key key = Key.of(namespace, value); + if (buildableItemMap.containsKey(key)) return false; + buildableItemMap.put(key, buildableItem); + return true; + } + + @Override + public boolean unregisterCustomItem(String namespace, String value) { + return buildableItemMap.remove(Key.of(namespace, value)) != null; + } + + @Override + public ItemStack build(Player player, String namespace, String value) { + return build(player, namespace, value, new HashMap<>()); + } + + @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); + } + + @NotNull + @Override + public ItemStack build(Player player, ItemBuilder builder) { + return build(player, builder, new HashMap<>()); + } + + @Override + @Nullable + public BuildableItem getBuildableItem(String namespace, String value) { + return buildableItemMap.get(Key.of(namespace, value)); + } + + @Override + public String getAnyItemID(ItemStack itemStack) { + for (String plugin : Config.itemDetectOrder) { + ItemLibrary itemLibrary = itemLibraryMap.get(plugin); + if (itemLibrary != null) { + String id = itemLibrary.getItemID(itemStack); + if (id != null) { + return id; + } + } + } + // should not reach this because vanilla library would always work + return null; + } + + @Override + public ItemStack buildAnyItemByID(Player player, String id) { + if (id.contains(":")) { + String[] split = id.split(":", 2); + return itemLibraryMap.get(split[0]).buildItem(player, split[1]); + } else { + return new ItemStack(Material.valueOf(id.toUpperCase(Locale.ENGLISH))); + } + } + + @Nullable + @Override + public String getItemID(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"); + } + + @Nullable + @Override + public CFBuilder getItemBuilder(ConfigurationSection section, String type, String id) { + if (section == null) return null; + String material = section.getString("material", "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 + .amount(section.getInt("amount", 1)) + .stackable(section.getBoolean("stackable", true)) + .size(getSizePair(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(getEnchantmentPair(section.getConfigurationSection("enchantments")), false) + .enchantment(getEnchantmentPair(section.getConfigurationSection("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", false)) + .head(section.getString("head64")) + .name(section.getString("display.name")) + .lore(section.getStringList("display.lore")); + return itemCFBuilder; + } + + @Override + public ItemStack build(Player player, ItemBuilder builder, Map placeholders) { + ItemStack temp = itemLibraryMap.get(builder.getLibrary()).buildItem(player, builder.getId()); + temp.setAmount(builder.getAmount()); + NBTItem nbtItem = new NBTItem(temp); + for (ItemBuilder.ItemPropertyEditor editor : builder.getEditors()) { + editor.edit(player, nbtItem, placeholders); + } + return nbtItem.getItem(); + } + + @Override + public boolean registerItemLibrary(ItemLibrary itemLibrary) { + if (itemLibraryMap.containsKey(itemLibrary.identification())) return false; + itemLibraryMap.put(itemLibrary.identification(), itemLibrary); + return true; + } + + @Override + public boolean unRegisterItemLibrary(ItemLibrary itemLibrary) { + return itemLibraryMap.remove(itemLibrary.identification(), itemLibrary); + } + + @Override + public boolean unRegisterItemLibrary(String itemLibrary) { + return itemLibraryMap.remove(itemLibrary) != null; + } + + @Override + public void dropItem(Player player, Location hookLocation, Location playerLocation, Loot loot, Map args) { + ItemStack item = build(player, "loot", loot.getID(), args); + if (item == null) { + LogUtils.warn(String.format("Item %s not exists", loot.getID())); + return; + } + if (item.getType() == Material.AIR) { + return; + } + Entity itemEntity = hookLocation.getWorld().dropItem(hookLocation, item); + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(0.105); + vector = vector.setY((vector.getY() + 0.2) * 1.18); + itemEntity.setVelocity(vector); + } + + @Override + public void dropItem(Location hookLocation, Location playerLocation, ItemStack itemStack) { + Entity itemEntity = hookLocation.getWorld().dropItem(hookLocation, itemStack); + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(0.105); + vector = vector.setY((vector.getY() + 0.2) * 1.18); + itemEntity.setVelocity(vector); + } + + @NotNull + private List> getEnchantmentPair(ConfigurationSection section) { + List> list = new ArrayList<>(); + if (section == null) return list; + for (Map.Entry entry : section.getValues(false).entrySet()) { + list.add(Pair.of(entry.getKey(), (short) entry.getValue())); + } + return list; + } + + @Nullable + private Pair getSizePair(String size) { + if (size == null) return null; + String[] split = size.split("~", 2); + return Pair.of(Float.parseFloat(split[0]), Float.parseFloat(split[1])); + } + + public static class CFBuilder implements ItemBuilder, BuildableItem { + + private final String library; + private final String id; + private int amount; + private final LinkedHashMap editors; + + public CFBuilder(String library, String id) { + this.id = id; + this.library = library; + this.editors = new LinkedHashMap<>(); + this.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.build(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.setInteger("CustomModelData", value)); + return this; + } + + @Override + public ItemBuilder name(String name) { + if (name == null) return this; + String replacedName = AdventureManagerImpl.getInstance().legacyToMiniMessage(name); + editors.put("name", (player, nbtItem, placeholders) -> { + NBTCompound displayCompound = nbtItem.getOrCreateCompound("display"); + displayCompound.setString("Name", AdventureManagerImpl.getInstance().componentToJson( + AdventureManagerImpl.getInstance().getComponentFromMiniMessage( + "" + PlaceholderManagerImpl.getInstance().parse(player, replacedName, placeholders) + ) + )); + }); + return this; + } + + @Override + public ItemBuilder amount(int amount) { + this.amount = amount; + return this; + } + + @Override + public ItemBuilder tag(boolean tag, String type, String id) { + editors.put("tag", (player, nbtItem, placeholders) -> { + if (!tag) return; + NBTCompound cfCompound = nbtItem.getOrCreateCompound("CustomFishing"); + cfCompound.setString("type", type); + cfCompound.setString("id", id); + }); + return this; + } + + @Override + public ItemBuilder unbreakable(boolean unbreakable) { + editors.put("unbreakable", (player, nbtItem, placeholders) -> { + if (!unbreakable) return; + nbtItem.setByte("Unbreakable", (byte) 1); + }); + return this; + } + + @Override + public ItemBuilder lore(List lore) { + if (lore.size() == 0) return this; + List replacedList = lore.stream().map(s -> AdventureManagerImpl.getInstance().legacyToMiniMessage(s)).toList(); + editors.put("lore", (player, nbtItem, placeholders) -> { + NBTCompound displayCompound = nbtItem.getOrCreateCompound("display"); + NBTList list = displayCompound.getStringList("Lore"); + list.clear(); + list.addAll(replacedList.stream().map(s -> AdventureManagerImpl.getInstance().componentToJson( + AdventureManagerImpl.getInstance().getComponentFromMiniMessage( + "" + PlaceholderManagerImpl.getInstance().parse(player, s, placeholders) + ) + )).toList()); + }); + return this; + } + + @Override + public ItemBuilder nbt(Map nbt) { + if (nbt.size() == 0) return this; + editors.put("nbt", (player, nbtItem, placeholders) -> NBTUtils.setTagsFromBukkitYAML(nbtItem, nbt)); + return this; + } + + @Override + public ItemBuilder nbt(ConfigurationSection section) { + if (section == null) return this; + editors.put("nbt", (player, nbtItem, placeholders) -> NBTUtils.setTagsFromBukkitYAML(nbtItem, section.getValues(false))); + return this; + } + + @Override + public ItemBuilder itemFlag(List itemFlags) { + if (itemFlags.size() == 0) return this; + editors.put("item-flag", (player, nbtItem, placeholders) -> { + int flag = 0; + for (ItemFlag itemFlag : itemFlags) { + flag = flag | 1 << itemFlag.ordinal(); + } + nbtItem.setInteger("HideFlags", flag); + }); + return this; + } + + @Override + public ItemBuilder enchantment(List> enchantments, boolean store) { + if (enchantments.size() == 0) return this; + editors.put("enchantment", (player, nbtItem, placeholders) -> { + NBTCompoundList list = nbtItem.getCompoundList(store ? "StoredEnchantments" : "Enchantments"); + for (Pair pair : enchantments) { + NBTCompound nbtCompound = list.addCompound(); + nbtCompound.setString("id", pair.left()); + nbtCompound.setShort("lvl", pair.right()); + } + }); + return this; + } + + @Override + public ItemBuilder maxDurability(int max) { + if (max == 0) return this; + editors.put("durability", (player, nbtItem, placeholders) -> { + NBTCompound cfCompound = nbtItem.getOrCreateCompound("CustomFishing"); + cfCompound.setInteger("max_dur", max); + cfCompound.setInteger("cur_dur", max); + }); + return this; + } + + @Override + public ItemBuilder price(float base, float bonus) { + editors.put("price", (player, nbtItem, placeholders) -> { + if (base != 0) { + placeholders.put("{base}", String.format("%.2f", base)); + } + if (bonus != 0) { + placeholders.put("{bonus}", String.format("%.2f", bonus)); + } + float size = Float.parseFloat(placeholders.getOrDefault("{size}", "0")); + double price = CustomFishingPlugin.get().getMarketManager().getPrice( + base, + bonus, + size + ); + nbtItem.setDouble("Price", price); + placeholders.put("{price}", String.format("%.2f", price)); + }); + return this; + } + + @Override + public ItemBuilder size(Pair size) { + if (size == null) return this; + editors.put("size", (player, nbtItem, placeholders) -> { + NBTCompound cfCompound = nbtItem.getOrCreateCompound("CustomFishing"); + float random = size.left() + ThreadLocalRandom.current().nextFloat(size.right() - size.left()); + float bonus = Float.parseFloat(placeholders.getOrDefault("size-multiplier", "1.0")); + random *= bonus; + cfCompound.setFloat("size", random); + placeholders.put("{size}", String.format("%.2f", random)); + }); + return this; + } + + @Override + public ItemBuilder stackable(boolean stackable) { + if (stackable) return this; + editors.put("stackable", (player, nbtItem, placeholders) -> { + NBTCompound cfCompound = nbtItem.getOrCreateCompound("CustomFishing"); + cfCompound.setUUID("uuid", UUID.randomUUID()); + }); + return this; + } + + @Override + public ItemBuilder preventGrabbing(boolean prevent) { + if (!prevent) return this; + editors.put("grabbing", (player, nbtItem, placeholders) -> { + nbtItem.setString("owner", placeholders.get("player")); + }); + return this; + } + + @Override + public ItemBuilder head(String base64) { + if (base64 == null) return this; + editors.put("head", (player, nbtItem, placeholders) -> { + NBTCompound nbtCompound = nbtItem.addCompound("SkullOwner"); + nbtCompound.setUUID("Id", UUID.nameUUIDFromBytes(base64.substring(0,8).getBytes())); + 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) -> { + NBTCompound cfCompound = nbtItem.getCompound("CustomFishing"); + if (cfCompound != null) { + int i = cfCompound.getInteger("max_dur"); + if (i != 0) { + int dur = ThreadLocalRandom.current().nextInt(i); + cfCompound.setInteger("cur_dur", dur); + nbtItem.setInteger("Damage", (int) (nbtItem.getItem().getType().getMaxDurability() * ((double) dur / i))); + } + } else { + nbtItem.setInteger("Damage", ThreadLocalRandom.current().nextInt(nbtItem.getItem().getType().getMaxDurability())); + } + }); + return this; + } + + @Override + public @NotNull String getId() { + return id; + } + + @Override + public @NotNull String getLibrary() { + return library; + } + + @Override + public int getAmount() { + return amount; + } + + @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; + } + } +} \ No newline at end of file diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java new file mode 100644 index 00000000..7d61535f --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java @@ -0,0 +1,304 @@ +package net.momirealms.customfishing.mechanic.loot; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.LootManager; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.game.GameConfig; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.loot.LootType; +import net.momirealms.customfishing.api.util.LogUtils; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.*; + +public class LootManagerImpl implements LootManager { + + private final CustomFishingPlugin plugin; + private final HashMap lootMap; + public static CFLoot globalLootProperties; + private boolean disableStats; + private boolean disableGames; + private boolean instantGame; + private boolean showInFinder; + private String gameGroup; + + public LootManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.lootMap = new HashMap<>(); + } + + public void load() { + this.loadGlobalLootProperties(); + this.loadLootsFromPluginFolder(); + } + + public void unload() { + this.lootMap.clear(); + } + + public void disable() { + unload(); + } + + @SuppressWarnings("DuplicatedCode") + public void loadLootsFromPluginFolder() { + Deque fileDeque = new ArrayDeque<>(); + for (String type : List.of("loots", "mobs", "blocks")) { + 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()) { + loadSingleFile(subFile, StringUtils.chop(type)); + } + } + } + } + } + + @Nullable + @Override + public Loot getLoot(String key) { + return lootMap.get(key); + } + + private void loadGlobalLootProperties() { + YamlConfiguration config = plugin.getConfig("config.yml"); + globalLootProperties = getSingleSectionItem( + Objects.requireNonNull(config.getConfigurationSection("mechanics.global-loot-properties")), + "GLOBAL", + "global" + ); + disableStats = globalLootProperties.disableStats(); + disableGames = globalLootProperties.disableGame(); + instantGame = globalLootProperties.instanceGame(); + showInFinder = globalLootProperties.showInFinder(); + gameGroup = globalLootProperties.gameConfig; + } + + private void loadSingleFile(File file, String namespace) { + YamlConfiguration yaml = YamlConfiguration.loadConfiguration(file); + for (Map.Entry entry : yaml.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection section) { + var loot = getSingleSectionItem( + section, + namespace, + entry.getKey() + ); + if (lootMap.containsKey(entry.getKey())) { + LogUtils.severe("Duplicated loot found: " + entry.getKey() + "."); + } else { + lootMap.put(entry.getKey(), loot); + } + } + } + } + + private CFLoot getSingleSectionItem(ConfigurationSection section, String namespace, String key) { + return new CFLoot.Builder(key, LootType.valueOf(namespace.toUpperCase(Locale.ENGLISH))) + .disableStats(section.getBoolean("disable-stat", disableStats)) + .disableGames(section.getBoolean("disable-game", disableGames)) + .instantGame(section.getBoolean("instant-game", instantGame)) + .showInFinder(section.getBoolean("show-in-fishfinder", showInFinder)) + .gameConfig(section.getString("game-group", gameGroup)) + .nick(section.getString("nick", section.getString("display.name", key))) + .addActions(getActionMap(section.getConfigurationSection("action"))) + .addTimesActions(getTimesActionMap(section.getConfigurationSection("action.success-times"))) + .build(); + } + + private HashMap getActionMap(ConfigurationSection section) { + HashMap actionMap = new HashMap<>(); + if (section == null) return actionMap; + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + actionMap.put( + ActionTrigger.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)), + plugin.getActionManager().getActions(innerSection) + ); + } + } + return actionMap; + } + + private HashMap getTimesActionMap(ConfigurationSection section) { + HashMap actionMap = new HashMap<>(); + if (section == null) return actionMap; + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + actionMap.put(Integer.parseInt(entry.getKey()), plugin.getActionManager().getActions(innerSection)); + } + } + return actionMap; + } + + public static class CFLoot implements Loot { + + private final String id; + private final LootType type; + private String gameConfig; + private final HashMap actionMap; + private final HashMap successTimesActionMap; + private String nick; + private boolean showInFinder; + private boolean disableGame; + private boolean disableStats; + private boolean instanceGame; + private double score; + + public CFLoot(String id, LootType type) { + this.id = id; + this.type = type; + this.actionMap = new HashMap<>(); + this.successTimesActionMap = new HashMap<>(); + } + + public static CFLoot of(String id, LootType type) { + return new CFLoot(id, type); + } + + public static class Builder { + + private final CFLoot loot; + + public Builder(String id, LootType type) { + this.loot = new CFLoot(id, type); + } + + public Builder nick(String nick) { + this.loot.nick = nick; + return this; + } + + public Builder showInFinder(boolean show) { + this.loot.showInFinder = show; + return this; + } + + public Builder instantGame(boolean instant) { + this.loot.instanceGame = instant; + return this; + } + + public Builder gameConfig(String gameConfig) { + this.loot.gameConfig = gameConfig; + return this; + } + + public Builder disableGames(boolean disable) { + this.loot.disableGame = disable; + return this; + } + + public Builder disableStats(boolean disable) { + this.loot.disableStats = disable; + return this; + } + + public Builder score(double score) { + this.loot.score = score; + return this; + } + + public Builder addActions(ActionTrigger trigger, Action[] actions) { + this.loot.actionMap.put(trigger, actions); + return this; + } + + public Builder addActions(HashMap actionMap) { + this.loot.actionMap.putAll(actionMap); + return this; + } + + public Builder addTimesActions(int times, Action[] actions) { + this.loot.successTimesActionMap.put(times, actions); + return this; + } + + public Builder addTimesActions(HashMap actionMap) { + this.loot.successTimesActionMap.putAll(actionMap); + return this; + } + + public CFLoot build() { + return loot; + } + } + + @Override + public boolean instanceGame() { + return this.instanceGame; + } + + @Override + public String getID() { + return this.id; + } + + @Override + public LootType getType() { + return this.type; + } + + @Override + public @NotNull String getNick() { + return this.nick; + } + + @Override + public boolean showInFinder() { + return this.showInFinder; + } + + @Override + public double getScore() { + return this.score; + } + + @Override + public boolean disableGame() { + return this.disableGame; + } + + @Override + public boolean disableStats() { + return this.disableStats; + } + + @Override + public GameConfig getGameConfig() { + return CustomFishingPlugin.get().getGameManager().getGameConfig(this.gameConfig); + } + + @Override + public Action[] getActions(ActionTrigger actionTrigger) { + return actionMap.get(actionTrigger); + } + + @Override + public Action[] getSuccessTimesActions(int times) { + return successTimesActionMap.get(times); + } + + @Override + public HashMap getSuccessTimesActionMap() { + return successTimesActionMap; + } + } + +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java new file mode 100644 index 00000000..36df2e26 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java @@ -0,0 +1,136 @@ +package net.momirealms.customfishing.mechanic.market; + +import de.tr7zw.changeme.nbtapi.NBTItem; +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.MarketManager; +import net.momirealms.customfishing.api.mechanic.item.ItemBuilder; +import net.momirealms.customfishing.api.mechanic.market.MarketGUI; +import net.momirealms.customfishing.libraries.inventorygui.InventoryGui; +import net.momirealms.customfishing.libraries.inventorygui.StaticGuiElement; +import net.momirealms.customfishing.mechanic.item.ItemManagerImpl; +import net.momirealms.customfishing.util.ConfigUtils; +import net.objecthunter.exp4j.Expression; +import net.objecthunter.exp4j.ExpressionBuilder; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class MarketManagerImpl implements MarketManager { + + private final CustomFishingPlugin plugin; + private final HashMap priceMap; + private String[] layout; + private String title; + private String formula; + private final HashMap decorativeIcons; + private char itemSlot; + + public MarketManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.priceMap = new HashMap<>(); + this.decorativeIcons = new HashMap<>(); + } + + public void load() { + YamlConfiguration config = plugin.getConfig("market.yml"); + this.layout = config.getStringList("layout").toArray(new String[0]); + this.title = config.getString("title", "market.title"); + this.formula = config.getString("price-formula", "{base} + {bonus} * {size}"); + ConfigurationSection priceSection = config.getConfigurationSection("item-price"); + if (priceSection != null) { + for (Map.Entry entry : priceSection.getValues(false).entrySet()) { + this.priceMap.put(entry.getKey(), ConfigUtils.getDoubleValue(entry.getValue())); + } + } + ConfigurationSection decorativeSection = config.getConfigurationSection("decorative-icons"); + if (decorativeSection != null) { + for (Map.Entry entry : decorativeSection.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + char symbol = Objects.requireNonNull(innerSection.getString("symbol")).charAt(0); + var builder = plugin.getItemManager().getItemBuilder(innerSection, "gui", entry.getKey()); + decorativeIcons.put(symbol, builder); + } + } + } + } + + public void unload() { + this.priceMap.clear(); + this.decorativeIcons.clear(); + } + + public void disable() { + unload(); + } + + public void openMarketGUI(Player player) { + player.closeInventory(); + + InventoryGui gui = new InventoryGui( + plugin, + new MarketGUI(), + AdventureManagerImpl.getInstance().getComponentFromMiniMessage(title), + layout + ); + + gui.setCloseAction(close -> { + var elements = gui.getElement(itemSlot); + + + return false; + }); + + for (Map.Entry entry : decorativeIcons.entrySet()) { + gui.addElement(new StaticGuiElement( + entry.getKey(), + ((ItemManagerImpl.CFBuilder) entry.getValue()).build() + )); + } + } + + @Override + public int getDate() { + Calendar calendar = Calendar.getInstance(); + return (calendar.get(Calendar.MONTH) +1) * 100 + calendar.get(Calendar.DATE); + } + + @Override + public double getItemPrice(ItemStack itemStack) { + if (itemStack == null || itemStack.getType() == Material.AIR) + return 0; + NBTItem nbtItem = new NBTItem(itemStack); + Double price = nbtItem.getDouble("Price"); + if (price != null && price != 0) { + return price; + } + String itemID = itemStack.getType().name(); + if (nbtItem.hasTag("CustomModelData")) { + itemID = itemID + ":" + nbtItem.getInteger("CustomModelData"); + } + return priceMap.getOrDefault(itemID, 0d); + } + + @Override + public String getFormula() { + return formula; + } + + @Override + public double getPrice(float base, float bonus, float size) { + Expression expression = new ExpressionBuilder(getFormula()) + .variables("base", "bonus", "size") + .build() + .setVariable("base", base) + .setVariable("bonus", bonus) + .setVariable("size", size); + return expression.evaluate(); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/mob/MobManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/mob/MobManagerImpl.java new file mode 100644 index 00000000..c6e2000e --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/mob/MobManagerImpl.java @@ -0,0 +1,142 @@ +package net.momirealms.customfishing.mechanic.mob; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.MobManager; +import net.momirealms.customfishing.api.mechanic.loot.Loot; +import net.momirealms.customfishing.api.mechanic.mob.MobConfig; +import net.momirealms.customfishing.api.mechanic.mob.MobLibrary; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.mob.VanillaMobImpl; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Entity; +import org.bukkit.util.Vector; + +import java.io.File; +import java.util.*; + +public class MobManagerImpl implements MobManager { + + private final CustomFishingPlugin plugin; + private final HashMap mobLibraryMap; + private final HashMap mobConfigMap; + + public MobManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.mobLibraryMap = new HashMap<>(); + this.mobConfigMap = new HashMap<>(); + this.registerMobLibrary(new VanillaMobImpl()); + } + + public void load() { + this.loadConfig(); + } + + public void unload() { + HashMap tempMap = new HashMap<>(this.mobConfigMap); + this.mobConfigMap.clear(); + for (Map.Entry entry : tempMap.entrySet()) { + if (entry.getValue().isPersist()) { + tempMap.put(entry.getKey(), entry.getValue()); + } + } + } + + @Override + public boolean registerMobLibrary(MobLibrary mobLibrary) { + if (mobLibraryMap.containsKey(mobLibrary.identification())) return false; + else mobLibraryMap.put(mobLibrary.identification(), mobLibrary); + return true; + } + + @Override + public boolean unregisterMobLibrary(String lib) { + return mobLibraryMap.remove(lib) != null; + } + + @Override + public boolean unregisterMobLibrary(MobLibrary mobLibrary) { + return unregisterMobLibrary(mobLibrary.identification()); + } + + @SuppressWarnings("DuplicatedCode") + private void loadConfig() { + Deque fileDeque = new ArrayDeque<>(); + for (String type : List.of("mobs")) { + 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()) { + this.loadSingleFile(subFile); + } + } + } + } + } + + 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 mobID = section.getString("mob"); + if (mobID == null) { + LogUtils.warn("Mob 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)); + } + MobConfig mobConfig = new MobConfig.Builder() + .mobID(mobID) + .persist(false) + .horizontalVector(section.getDouble("vector.horizontal", 1.1)) + .verticalVector(section.getDouble("vector.vertical", 1.2)) + .propertyMap(propertyMap) + .build(); + mobConfigMap.put(entry.getKey(), mobConfig); + } + } + } + + public void disable() { + unload(); + this.mobConfigMap.clear(); + this.mobLibraryMap.clear(); + } + + @Override + public void summonMob(Location hookLocation, Location playerLocation, Loot loot) { + MobConfig config = mobConfigMap.get(loot.getID()); + if (config == null) { + LogUtils.warn("Mob: " + loot.getID() + " doesn't exist."); + return; + } + String mobID = config.getMobID(); + Entity entity; + if (mobID.contains(":")) { + String[] split = mobID.split(":", 2); + String identification = split[0]; + String id = split[1]; + MobLibrary library = mobLibraryMap.get(identification); + entity = library.spawn(hookLocation, id, config.getPropertyMap()); + } else { + entity = mobLibraryMap.get("vanilla").spawn(hookLocation, mobID, config.getPropertyMap()); + } + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1); + vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector()); + entity.setVelocity(vector); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/AbstractRequirement.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/AbstractRequirement.java new file mode 100644 index 00000000..611cd344 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/AbstractRequirement.java @@ -0,0 +1,24 @@ +package net.momirealms.customfishing.mechanic.requirement; + +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; + +import java.util.List; + +public abstract class AbstractRequirement implements Requirement { + + private final List actions; + + public AbstractRequirement(List actions) { + this.actions = actions; + } + + protected void triggerActions(Condition condition) { + if (actions != null) { + for (Action action : actions) { + action.trigger(condition); + } + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/ConditionalLoots.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/ConditionalLoots.java new file mode 100644 index 00000000..2eb5b472 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/ConditionalLoots.java @@ -0,0 +1,46 @@ +package net.momirealms.customfishing.mechanic.requirement; + +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.loot.Modifier; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; + +import java.util.HashMap; +import java.util.List; + +public class ConditionalLoots { + + private final List> modifierList; + private final HashMap subLoots; + private final Requirement[] requirements; + + public ConditionalLoots( + Requirement[] requirements, + List> modifierList, + HashMap subLoots + ) { + this.modifierList = modifierList; + this.requirements = requirements; + this.subLoots = subLoots; + } + + synchronized public void combine(HashMap weightMap) { + for (Pair modifierPair : this.modifierList) { + double previous = weightMap.getOrDefault(modifierPair.left(), 0d); + weightMap.put(modifierPair.left(), modifierPair.right().modify(previous)); + } + } + + public boolean isConditionsMet(Condition condition) { + for (Requirement requirement : requirements) { + if (!requirement.isConditionMet(condition)) { + return false; + } + } + return true; + } + + public HashMap getSubLoots() { + return subLoots; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java new file mode 100644 index 00000000..071599a9 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java @@ -0,0 +1,475 @@ +package net.momirealms.customfishing.mechanic.requirement; + +import net.momirealms.biomeapi.BiomeAPI; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.integration.LevelInterface; +import net.momirealms.customfishing.api.integration.SeasonInterface; +import net.momirealms.customfishing.api.manager.RequirementManager; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import net.momirealms.customfishing.api.mechanic.requirement.RequirementBuilder; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.mechanic.requirement.inbuilt.LogicRequirement; +import net.momirealms.customfishing.util.ConfigUtils; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.MemorySection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RequirementManagerImpl implements RequirementManager { + + public static Requirement[] mechanicRequirements; + private final CustomFishingPluginImpl plugin; + private final HashMap requirementBuilderMap; + private final LinkedHashMap conditionalLootsMap; + + public RequirementManagerImpl(CustomFishingPluginImpl plugin) { + this.plugin = plugin; + this.requirementBuilderMap = new HashMap<>(); + this.conditionalLootsMap = new LinkedHashMap<>(); + this.registerInbuiltRequirements(); + } + + public void load() { + this.loadRequirementGroupFileConfig(); + } + + public void unload() { + this.conditionalLootsMap.clear(); + } + + public void disable() { + this.requirementBuilderMap.clear(); + this.conditionalLootsMap.clear(); + } + + public void loadRequirementGroupFileConfig() { + YamlConfiguration main = plugin.getConfig("config.yml"); + mechanicRequirements = getRequirements(main.getConfigurationSection("mechanics.mechanic-requirements"), true); + + YamlConfiguration config = plugin.getConfig("loot-conditions.yml"); + for (Map.Entry entry : config.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection section) { + conditionalLootsMap.put(entry.getKey(), getConditionalLoots(section)); + } + } + } + + @Override + public boolean registerRequirement(String type, RequirementBuilder requirementBuilder) { + if (this.requirementBuilderMap.containsKey(type)) return false; + this.requirementBuilderMap.put(type, requirementBuilder); + return true; + } + + @Override + public boolean unregisterRequirement(String type) { + return this.requirementBuilderMap.remove(type) != null; + } + + private void registerInbuiltRequirements() { + this.registerTimeRequirement(); + this.registerYRequirement(); + this.registerLogicRequirement(); + this.registerCompare(); + this.registerBiomeRequirement(); + this.registerDateRequirement(); + this.registerPluginLevelRequirement(); + this.registerPermissionRequirement(); + this.registerWorldRequirement(); + this.registerWeatherRequirement(); + this.registerSeasonRequirement(); + this.registerInLavaRequirement(); + this.registerRodRequirement(); + this.registerBaitRequirement(); + } + + public ConditionalLoots getConditionalLoots(ConfigurationSection section) { + var sub = section.getConfigurationSection("sub-groups"); + if (sub == null) { + return new ConditionalLoots( + getRequirements(section.getConfigurationSection("conditions"), false), + ConfigUtils.getModifiers(section.getStringList("list")), + null + ); + } else { + HashMap subLoots = new HashMap<>(); + for (Map.Entry entry : sub.getValues(false).entrySet()) { + if (entry.getValue() instanceof ConfigurationSection innerSection) { + subLoots.put(entry.getKey(), getConditionalLoots(innerSection)); + } + } + return new ConditionalLoots( + getRequirements(section.getConfigurationSection("conditions"), false), + ConfigUtils.getModifiers(section.getStringList("list")), + subLoots + ); + } + } + + @Override + public HashMap getLootWithWeight(Condition condition) { + HashMap lootWeightMap = new HashMap<>(); + Queue> lootQueue = new LinkedList<>(); + lootQueue.add(conditionalLootsMap); + while (!lootQueue.isEmpty()) { + HashMap currentLootMap = lootQueue.poll(); + for (ConditionalLoots loots : currentLootMap.values()) { + if (loots.isConditionsMet(condition)) { + loots.combine(lootWeightMap); + if (loots.getSubLoots() != null) { + lootQueue.add(loots.getSubLoots()); + } + } + } + } + return lootWeightMap; + } + + @Nullable + @Override + public Requirement[] getRequirements(ConfigurationSection section, boolean advanced) { + if (section == null) return null; + List requirements = new ArrayList<>(); + for (Map.Entry entry : section.getValues(false).entrySet()) { + String typeOrName = entry.getKey(); + if (hasRequirement(typeOrName)) { + requirements.add(getRequirementBuilder(typeOrName).build(entry.getValue(), null, advanced)); + } else { + requirements.add(getRequirement(section.getConfigurationSection(typeOrName), advanced)); + } + } + return requirements.toArray(new Requirement[0]); + } + + public boolean hasRequirement(String type) { + return requirementBuilderMap.containsKey(type); + } + + @NotNull + @Override + public Requirement getRequirement(ConfigurationSection section, boolean advanced) { + List actionList = null; + if (advanced) { + actionList = new ArrayList<>(); + if (section.contains("actions")) { + for (Map.Entry entry : Objects.requireNonNull(section.getConfigurationSection("actions")).getValues(false).entrySet()) { + if (entry.getValue() instanceof MemorySection inner) { + actionList.add(plugin.getActionManager().getAction(inner)); + } + } + } + if (actionList.size() == 0) + actionList = null; + } + String type = section.getString("type"); + if (type == null) { + throw new NullPointerException(section.getCurrentPath() + ".type" + " doesn't exist"); + } + var builder = getRequirementBuilder(type); + if (builder == null) { + throw new NullPointerException("Requirement type: " + type + " doesn't exist"); + } + return builder.build(section.get("value"), actionList, advanced); + } + + @Override + public Requirement getRequirement(String key, Object value) { + return getRequirementBuilder(key).build(value); + } + + private Pair getIntegerPair(String range) { + String[] split = range.split("~"); + return Pair.of(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + } + + @Override + public RequirementBuilder getRequirementBuilder(String type) { + return requirementBuilderMap.get(type); + } + + private void registerLogicRequirement() { + registerRequirement("logic", (args, actions, advanced) -> + new LogicRequirement(this, args, actions, advanced) + ); + } + + private void registerTimeRequirement() { + registerRequirement("time", (args, actions, advanced) -> { + List> timePairs = ConfigUtils.stringListArgs(args).stream().map(this::getIntegerPair).toList(); + return condition -> { + long time = condition.getLocation().getWorld().getTime(); + for (Pair pair : timePairs) + if (time >= pair.left() && time <= pair.right()) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerYRequirement() { + registerRequirement("ypos", (args, actions, advanced) -> { + List> timePairs = ConfigUtils.stringListArgs(args).stream().map(this::getIntegerPair).toList(); + return condition -> { + int y = condition.getLocation().getBlockY(); + for (Pair pair : timePairs) + if (y >= pair.left() && y <= pair.right()) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerInLavaRequirement() { + registerRequirement("in-lava", (args, actions, advanced) -> { + boolean inLava = (boolean) args; + return condition -> { + String current = condition.getArgs().get("in-lava"); + if (current.equals(String.valueOf(inLava))) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerBiomeRequirement() { + registerRequirement("biome", (args, actions, advanced) -> { + HashSet biomes = new HashSet<>(ConfigUtils.stringListArgs(args)); + return condition -> { + String currentBiome = BiomeAPI.getBiome(condition.getLocation()); + if (biomes.contains(currentBiome)) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + registerRequirement("!biome", (args, actions, advanced) -> { + HashSet biomes = new HashSet<>(ConfigUtils.stringListArgs(args)); + return condition -> { + String currentBiome = BiomeAPI.getBiome(condition.getLocation()); + if (!biomes.contains(currentBiome)) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerWorldRequirement() { + registerRequirement("world", (args, actions, advanced) -> { + HashSet worlds = new HashSet<>(ConfigUtils.stringListArgs(args)); + return condition -> { + if (worlds.contains(condition.getLocation().getWorld().getName())) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + registerRequirement("!world", (args, actions, advanced) -> { + HashSet worlds = new HashSet<>(ConfigUtils.stringListArgs(args)); + return condition -> { + if (!worlds.contains(condition.getLocation().getWorld().getName())) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerWeatherRequirement() { + registerRequirement("weather", (args, actions, advanced) -> { + List weathers = ConfigUtils.stringListArgs(args); + return condition -> { + String currentWeather; + World world = condition.getLocation().getWorld(); + if (world.isThundering()) currentWeather = "thunder"; + else if (world.isClearWeather()) currentWeather = "clear"; + else currentWeather = "rain"; + for (String weather : weathers) + if (weather.equalsIgnoreCase(currentWeather)) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerDateRequirement() { + registerRequirement("date", (args, actions, advanced) -> { + HashSet dates = new HashSet<>(ConfigUtils.stringListArgs(args)); + return condition -> { + Calendar calendar = Calendar.getInstance(); + String current = (calendar.get(Calendar.MONTH) + 1) + "/" + calendar.get(Calendar.DATE); + if (dates.contains(current)) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerPermissionRequirement() { + registerRequirement("permission", (args, actions, advanced) -> { + List perms = ConfigUtils.stringListArgs(args); + return condition -> { + for (String perm : perms) + if (condition.getPlayer().hasPermission(perm)) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + registerRequirement("!permission", (args, actions, advanced) -> { + List perms = ConfigUtils.stringListArgs(args); + return condition -> { + for (String perm : perms) + if (condition.getPlayer().hasPermission(perm)) { + if (advanced) triggerActions(actions, condition); + return false; + } + return true; + }; + }); + } + + private void registerSeasonRequirement() { + registerRequirement("season", (args, actions, advanced) -> { + List seasons = ConfigUtils.stringListArgs(args); + return condition -> { + SeasonInterface seasonInterface = plugin.getIntegrationManager().getSeasonInterface(); + if (seasonInterface == null) return true; + String season = seasonInterface.getSeason(condition.getLocation().getWorld()); + if (seasons.contains(season)) return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerRodRequirement() { + registerRequirement("rod", (args, actions, advanced) -> { + List rods = ConfigUtils.stringListArgs(args); + return condition -> { + String id = condition.getArg("rod"); + if (rods.contains(id)) return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + registerRequirement("!rod", (args, actions, advanced) -> { + List rods = ConfigUtils.stringListArgs(args); + return condition -> { + String id = condition.getArg("rod"); + if (!rods.contains(id)) return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerBaitRequirement() { + registerRequirement("bait", (args, actions, advanced) -> { + List baits = ConfigUtils.stringListArgs(args); + return condition -> { + String id = condition.getArg("bait"); + if (baits.contains(id)) return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + registerRequirement("!bait", (args, actions, advanced) -> { + List baits = ConfigUtils.stringListArgs(args); + return condition -> { + String id = condition.getArg("bait"); + if (!baits.contains(id)) return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerPluginLevelRequirement() { + registerRequirement("plugin-level", (args, actions, advanced) -> { + if (args instanceof ConfigurationSection section) { + String pluginName = section.getString("plugin"); + int level = section.getInt("level"); + String target = section.getString("target"); + return condition -> { + LevelInterface levelInterface = plugin.getIntegrationManager().getLevelHook(pluginName); + if (levelInterface == null) { + LogUtils.warn("Plugin (" + pluginName + "'s) level is not compatible. Please double check if it's a problem caused by pronunciation."); + return true; + } + if (levelInterface.getLevel(condition.getPlayer(), target) >= level) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + } + return null; + }); + } + + private void registerCompare() { + registerRequirement("compare", (args, actions, advanced) -> condition -> { + if (evaluateExpression((String) args, condition.getPlayer())) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }); + } + + private void triggerActions(List actions, Condition condition) { + if (actions != null) + for (Action action : actions) + action.trigger(condition); + } + + private double doubleArg(String s, Player player) { + double arg = 0; + try { + arg = Double.parseDouble(s); + } catch (NumberFormatException e1) { + try { + arg = Double.parseDouble(plugin.getPlaceholderManager().setPlaceholders(player, s)); + } catch (NumberFormatException e2) { + LogUtils.severe(String.format("Invalid placeholder %s", s), e2); + } + } + return arg; + } + + public boolean evaluateExpression(String input, Player player) { + input = input.replace("\\s", ""); + Pattern pattern = Pattern.compile("(-?\\d+\\.?\\d*)(==|!=|<=?|>=?)(-?\\d+\\.?\\d*)"); + Matcher matcher = pattern.matcher(input); + if (matcher.matches()) { + double num1 = doubleArg(matcher.group(1), player); + String operator = matcher.group(2); + double num2 = doubleArg(matcher.group(3), player); + return switch (operator) { + case ">" -> num1 > num2; + case "<" -> num1 < num2; + case ">=" -> num1 >= num2; + case "<=" -> num1 <= num2; + case "==" -> num1 == num2; + case "!=" -> num1 != num2; + default -> throw new IllegalArgumentException("Unsupported operator: " + operator); + }; + } else { + throw new IllegalArgumentException("Invalid input format: " + input); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/inbuilt/LogicRequirement.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/inbuilt/LogicRequirement.java new file mode 100644 index 00000000..9b89567c --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/inbuilt/LogicRequirement.java @@ -0,0 +1,117 @@ +package net.momirealms.customfishing.mechanic.requirement.inbuilt; + +import net.momirealms.customfishing.api.manager.RequirementManager; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.requirement.Requirement; +import net.momirealms.customfishing.mechanic.requirement.AbstractRequirement; +import org.bukkit.configuration.MemorySection; + +import java.util.*; + +public class LogicRequirement extends AbstractRequirement { + + private List requirementList; + private boolean checkAction; + + public LogicRequirement(RequirementManager requirementManager, Object args, List actions, boolean checkAction) { + super(actions); + if (!(args instanceof MemorySection section1)) + return; + this.requirementList = new ArrayList<>(); + this.checkAction = checkAction; + Deque stack = new ArrayDeque<>(); + stack.push(new StackElement(section1.getValues(false), requirementList)); + while (!stack.isEmpty()) { + StackElement stackElement = stack.pop(); + Map currentMap = stackElement.getMap(); + List currentResult = stackElement.getRequirements(); + for (Map.Entry entry : currentMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof MemorySection section2) { + Map sectionMap = section2.getValues(false); + if (key.startsWith("&&")) { + List andReqList = new ArrayList<>(); + currentResult.add(new AndRequirement(andReqList)); + stack.push(new StackElement(sectionMap, andReqList)); + } else if (key.startsWith("||")) { + List orReqList = new ArrayList<>(); + currentResult.add(new OrRequirement(orReqList)); + stack.push(new StackElement(sectionMap, orReqList)); + } else { + currentResult.add(requirementManager.getRequirement(section2, checkAction)); + } + } + } + } + } + + public static class StackElement { + + private final Map map; + private final List requirements; + + public StackElement(Map map, List requirements) { + this.map = map; + this.requirements = requirements; + } + + public Map getMap() { + return map; + } + + public List getRequirements() { + return requirements; + } + } + + @Override + public boolean isConditionMet(Condition condition) { + for (Requirement requirement : requirementList) { + if (!requirement.isConditionMet(condition)) { + if (checkAction) super.triggerActions(condition); + return false; + } + } + return true; + } + + public static class AndRequirement implements Requirement { + + private final List requirementList; + + public AndRequirement(List requirementList) { + this.requirementList = requirementList; + } + + @Override + public boolean isConditionMet(Condition condition) { + for (Requirement requirement : requirementList) { + if (!requirement.isConditionMet(condition)) { + return false; + } + } + return true; + } + } + + public static class OrRequirement implements Requirement { + + private final List requirementList; + + public OrRequirement(List requirementList) { + this.requirementList = requirementList; + } + + @Override + public boolean isConditionMet(Condition condition) { + for (Requirement requirement : requirementList) { + if (requirement.isConditionMet(condition)) { + return true; + } + } + return false; + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java new file mode 100644 index 00000000..f0346047 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java @@ -0,0 +1,4 @@ +package net.momirealms.customfishing.mechanic.totem; + +public class TotemManagerImpl { +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java new file mode 100644 index 00000000..2caeef3b --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java @@ -0,0 +1,70 @@ +/* + * 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.scheduler; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.scheduler.BukkitTask; + +public class BukkitSchedulerImpl implements SyncScheduler { + + private final CustomFishingPlugin plugin; + + public BukkitSchedulerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + } + + @Override + public void runSyncTask(Runnable runnable, Location location) { + if (Bukkit.isPrimaryThread()) + runnable.run(); + else + Bukkit.getScheduler().runTask(plugin, runnable); + } + + @Override + public CancellableTask runTaskSyncTimer(Runnable runnable, Location location, long delay, long period) { + return new BukkitCancellableTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period)); + } + + @Override + public CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay) { + return new BukkitCancellableTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay)); + } + + public static class BukkitCancellableTask implements CancellableTask { + + private final BukkitTask bukkitTask; + + public BukkitCancellableTask(BukkitTask bukkitTask) { + this.bukkitTask = bukkitTask; + } + + @Override + public void cancel() { + this.bukkitTask.cancel(); + } + + @Override + public boolean isCancelled() { + return this.bukkitTask.isCancelled(); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/scheduler/FoliaSchedulerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/scheduler/FoliaSchedulerImpl.java new file mode 100644 index 00000000..9f361a88 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/scheduler/FoliaSchedulerImpl.java @@ -0,0 +1,67 @@ +/* + * 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.scheduler; + +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import org.bukkit.Bukkit; +import org.bukkit.Location; + +public class FoliaSchedulerImpl implements SyncScheduler { + + private final CustomFishingPlugin plugin; + + public FoliaSchedulerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + } + + @Override + public void runSyncTask(Runnable runnable, Location location) { + Bukkit.getRegionScheduler().execute(plugin, location, runnable); + } + + @Override + public CancellableTask runTaskSyncTimer(Runnable runnable, Location location, long delay, long period) { + return new FoliaCancellableTask(Bukkit.getRegionScheduler().runAtFixedRate(plugin, location, (scheduledTask -> runnable.run()), delay, period)); + } + + @Override + public CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay) { + return new FoliaCancellableTask(Bukkit.getRegionScheduler().runDelayed(plugin, location, (scheduledTask -> runnable.run()), delay)); + } + + public static class FoliaCancellableTask implements CancellableTask { + + private final ScheduledTask scheduledTask; + + public FoliaCancellableTask(ScheduledTask scheduledTask) { + this.scheduledTask = scheduledTask; + } + + @Override + public void cancel() { + this.scheduledTask.cancel(); + } + + @Override + public boolean isCancelled() { + return this.scheduledTask.isCancelled(); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/scheduler/SchedulerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/scheduler/SchedulerImpl.java new file mode 100644 index 00000000..9e36c5f4 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/scheduler/SchedulerImpl.java @@ -0,0 +1,113 @@ +/* + * 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.scheduler; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.api.scheduler.Scheduler; +import net.momirealms.customfishing.setting.Config; +import org.bukkit.Location; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class SchedulerImpl implements Scheduler { + + private final SyncScheduler syncScheduler; + private final ScheduledThreadPoolExecutor schedule; + private final CustomFishingPlugin plugin; + + public SchedulerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.syncScheduler = plugin.getVersionManager().isFolia() ? + new FoliaSchedulerImpl(plugin) : new BukkitSchedulerImpl(plugin); + this.schedule = new ScheduledThreadPoolExecutor(4); + this.schedule.setMaximumPoolSize(4); + this.schedule.setKeepAliveTime(10, TimeUnit.SECONDS); + this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + } + + public void reload() { + this.schedule.setCorePoolSize(Config.corePoolSize); + this.schedule.setKeepAliveTime(Config.keepAliveTime, TimeUnit.SECONDS); + this.schedule.setMaximumPoolSize(Config.maximumPoolSize); + } + + public void shutdown() { + if (this.schedule != null && !this.schedule.isShutdown()) + this.schedule.shutdown(); + } + + @Override + public void runTaskSync(Runnable runnable, Location location) { + this.syncScheduler.runSyncTask(runnable, location); + } + + @Override + public void runTaskAsync(Runnable runnable) { + this.schedule.execute(runnable); + } + + @Override + public CancellableTask runTaskSyncTimer(Runnable runnable, Location location, long delay, long period) { + return this.syncScheduler.runTaskSyncTimer(runnable, location, delay, period); + } + + @Override + public CancellableTask runTaskAsyncLater(Runnable runnable, long delay, TimeUnit timeUnit) { + return new ScheduledTask(schedule.schedule(runnable, delay, timeUnit)); + } + + @Override + public CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay, TimeUnit timeUnit) { + return new ScheduledTask(schedule.schedule(() -> { + runTaskSync(runnable, location); + }, delay, timeUnit)); + } + + @Override + public CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay) { + return this.syncScheduler.runTaskSyncLater(runnable, location, delay); + } + + @Override + public CancellableTask runTaskAsyncTimer(Runnable runnable, long delay, long period, TimeUnit timeUnit) { + return new ScheduledTask(schedule.scheduleAtFixedRate(runnable, delay, period, timeUnit)); + } + + public static class ScheduledTask implements CancellableTask { + + private final ScheduledFuture scheduledFuture; + + public ScheduledTask(ScheduledFuture scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + @Override + public void cancel() { + this.scheduledFuture.cancel(false); + } + + @Override + public boolean isCancelled() { + return this.scheduledFuture.isCancelled(); + } + } +} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/SchedulerPlatform.java b/plugin/src/main/java/net/momirealms/customfishing/scheduler/SyncScheduler.java similarity index 68% rename from src/main/java/net/momirealms/customfishing/scheduler/SchedulerPlatform.java rename to plugin/src/main/java/net/momirealms/customfishing/scheduler/SyncScheduler.java index 8f675901..4392fbef 100644 --- a/src/main/java/net/momirealms/customfishing/scheduler/SchedulerPlatform.java +++ b/plugin/src/main/java/net/momirealms/customfishing/scheduler/SyncScheduler.java @@ -17,17 +17,14 @@ package net.momirealms.customfishing.scheduler; +import net.momirealms.customfishing.api.scheduler.CancellableTask; import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; +public interface SyncScheduler { -public interface SchedulerPlatform { + void runSyncTask(Runnable runnable, Location location); - Future callSyncMethod(@NotNull Callable task); + CancellableTask runTaskSyncTimer(Runnable runnable, Location location, long delay, long period); - void runTask(Runnable runnable); - - void runTask(Runnable runnable, Location location); + CancellableTask runTaskSyncLater(Runnable runnable, Location location, long delay); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/setting/Config.java b/plugin/src/main/java/net/momirealms/customfishing/setting/Config.java new file mode 100644 index 00000000..4a389b55 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/setting/Config.java @@ -0,0 +1,139 @@ +package net.momirealms.customfishing.setting; + +import dev.dejvokep.boostedyaml.YamlDocument; +import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning; +import dev.dejvokep.boostedyaml.settings.dumper.DumperSettings; +import dev.dejvokep.boostedyaml.settings.general.GeneralSettings; +import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings; +import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.api.util.OffsetUtils; +import org.bukkit.Material; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.event.EventPriority; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +public class Config { + + // config version + public static String configVersion = "26"; + + // language + public static String language; + + // update checker + public static boolean updateChecker; + + // BStats + public static boolean metrics; + + // fishing event priority + public static EventPriority eventPriority; + + // thread pool settings + public static int corePoolSize; + public static int maximumPoolSize; + public static int keepAliveTime; + + // detection order for item id + public static List itemDetectOrder; + + // fishing bag + public static boolean enableFishingBag; + public static boolean bagStoreLoots; + public static String bagTitle; + public static List bagWhiteListItems; + + // Animation + public static boolean enableBaitAnimation; + public static boolean enableSplashAnimation; + public static int splashAnimationTime; + public static String lavaSplashItem; + public static String waterSplashItem; + + // Lava fishing + public static int lavaMinTime; + public static int lavaMaxTime; + + // Exception + public static boolean vanillaMechanicIfNoLoot; + public static Action[] noLootActions; + public static boolean debug; + + // Competition + public static boolean redisRanking; + public static int placeholderLimit; + + // + public static int dataSaveInterval; + + public static void load() { + try { + YamlDocument.create( + new File(CustomFishingPlugin.getInstance().getDataFolder(), "config.yml"), + Objects.requireNonNull(CustomFishingPlugin.getInstance().getResource("config.yml")), + GeneralSettings.DEFAULT, + LoaderSettings + .builder() + .setAutoUpdate(true) + .build(), + DumperSettings.DEFAULT, + UpdaterSettings + .builder() + .setVersioning(new BasicVersioning("config-version")) + .addIgnoredRoute(configVersion, "mechanics.mechanic-requirements", '.') + .addIgnoredRoute(configVersion, "mechanics.global-loot-properties", '.') + .build() + ); + loadSettings(CustomFishingPlugin.getInstance().getConfig("config.yml")); + } catch (IOException e) { + LogUtils.warn(e.getMessage()); + } + } + + private static void loadSettings(YamlConfiguration config) { + debug = config.getBoolean("debug", false); + + language = config.getString("lang", "english"); + updateChecker = config.getBoolean("update-checker"); + metrics = config.getBoolean("metrics"); + eventPriority = EventPriority.valueOf(config.getString("other-settings.event-priority", "NORMAL").toUpperCase(Locale.ENGLISH)); + + corePoolSize = config.getInt("other-settings.thread-pool-settings.corePoolSize", 4); + maximumPoolSize = config.getInt("other-settings.thread-pool-settings.maximumPoolSize", 8); + keepAliveTime = config.getInt("other-settings.thread-pool-settings.keepAliveTime", 10); + + itemDetectOrder = config.getStringList("other-settings.item-detection-order"); + + enableFishingBag = config.getBoolean("mechanics.fishing-bag.enable", true); + bagTitle = config.getString("mechanics.fishing-bag.bag-title"); + bagStoreLoots = config.getBoolean("mechanics.fishing-bag.can-store-loot", false); + bagWhiteListItems = config.getStringList("mechanics.fishing-bag.whitelist-items").stream().map(it -> Material.valueOf(it.toUpperCase(Locale.ENGLISH))).toList(); + + lavaMinTime = config.getInt("mechanics.lava-fishing.min-wait-time", 100); + lavaMaxTime = config.getInt("mechanics.lava-fishing.max-wait-time", 600); + + enableSplashAnimation = config.getBoolean("mechanics.animation.splash.enable", true); + enableBaitAnimation = config.getBoolean("mechanics.animation.bait.enable", true); + waterSplashItem = config.getString("mechanics.animation.splash.water"); + lavaSplashItem = config.getString("mechanics.animation.splash.lava"); + splashAnimationTime = config.getInt("mechanics.animation.splash.duration"); + + vanillaMechanicIfNoLoot = config.getBoolean("mechanics.vanilla-mechanic-if-no-loot.enable", false); + noLootActions = CustomFishingPlugin.get().getActionManager().getActions(config.getConfigurationSection("mechanics.vanilla-mechanic-if-no-loot.actions")); + + redisRanking = config.getBoolean("mechanics.competition.redis-ranking", false); + placeholderLimit = config.getInt("mechanics.competition.placeholder-limit", 3); + + dataSaveInterval = config.getInt("other-settings.data-saving-interval", 600); + + OffsetUtils.loadConfig(config.getConfigurationSection("other-settings.offset-characters")); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/setting/Locale.java b/plugin/src/main/java/net/momirealms/customfishing/setting/Locale.java new file mode 100644 index 00000000..a56a35bf --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/setting/Locale.java @@ -0,0 +1,83 @@ +package net.momirealms.customfishing.setting; + +import dev.dejvokep.boostedyaml.YamlDocument; +import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning; +import dev.dejvokep.boostedyaml.settings.dumper.DumperSettings; +import dev.dejvokep.boostedyaml.settings.general.GeneralSettings; +import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings; +import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.util.LogUtils; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.Objects; + +public class Locale { + public static String MSG_Total_Size; + public static String MSG_Catch_Amount; + public static String MSG_Total_Score; + public static String MSG_Max_Size; + public static String MSG_No_Player; + public static String MSG_No_Score; + public static String MSG_Prefix; + public static String MSG_Reload; + public static String MSG_Competition_Not_Exist; + public static String MSG_No_Competition_Ongoing; + public static String MSG_End_Competition; + public static String MSG_Stop_Competition; + public static String MSG_No_Rank; + public static String MSG_Item_Not_Exists; + public static String MSG_Get_Item; + public static String MSG_Give_Item; + public static String MSG_Never_Played; + public static String MSG_Unsafe_Modification; + + public static void load() { + try { + YamlDocument.create( + new File(CustomFishingPlugin.getInstance().getDataFolder(), "messages/" + Config.language + ".yml"), + Objects.requireNonNull(CustomFishingPlugin.getInstance().getResource("messages/" + Config.language + ".yml")), + GeneralSettings.DEFAULT, + LoaderSettings + .builder() + .setAutoUpdate(true) + .build(), + DumperSettings.DEFAULT, + UpdaterSettings + .builder() + .setVersioning(new BasicVersioning("config-version")) + .build() + ); + } catch (IOException e) { + LogUtils.warn(e.getMessage()); + } + loadSettings(CustomFishingPlugin.get().getConfig("messages/" + Config.language + ".yml")); + } + + private static void loadSettings(YamlConfiguration locale) { + ConfigurationSection msgSection = locale.getConfigurationSection("messages"); + if (msgSection != null) { + MSG_Prefix = msgSection.getString("prefix"); + MSG_Reload = msgSection.getString("reload"); + MSG_Competition_Not_Exist = msgSection.getString("competition-not-exist"); + MSG_No_Competition_Ongoing = msgSection.getString("no-competition-ongoing"); + MSG_Stop_Competition = msgSection.getString("stop-competition"); + MSG_End_Competition = msgSection.getString("end-competition"); + MSG_No_Player = msgSection.getString("no-player"); + MSG_No_Score = msgSection.getString("no-score"); + MSG_No_Rank = msgSection.getString("no-rank"); + MSG_Catch_Amount = msgSection.getString("goal-catch-amount"); + MSG_Max_Size = msgSection.getString("goal-max-size"); + MSG_Total_Score = msgSection.getString("goal-total-score"); + MSG_Total_Size = msgSection.getString("goal-total-size"); + MSG_Item_Not_Exists = msgSection.getString("item-not-exist"); + MSG_Get_Item = msgSection.getString("get-item"); + MSG_Give_Item = msgSection.getString("give-item"); + MSG_Never_Played = msgSection.getString("never-played"); + MSG_Unsafe_Modification = msgSection.getString("unsafe-modification"); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/StorageManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/StorageManagerImpl.java new file mode 100644 index 00000000..d6ddc295 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/StorageManagerImpl.java @@ -0,0 +1,278 @@ +package net.momirealms.customfishing.storage; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.DataStorageInterface; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.StorageType; +import net.momirealms.customfishing.api.data.user.OfflineUser; +import net.momirealms.customfishing.api.manager.StorageManager; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.storage.method.database.nosql.MongoDBImpl; +import net.momirealms.customfishing.storage.method.database.nosql.RedisManager; +import net.momirealms.customfishing.storage.method.database.sql.H2Impl; +import net.momirealms.customfishing.storage.method.database.sql.MariaDBImpl; +import net.momirealms.customfishing.storage.method.database.sql.MySQLImpl; +import net.momirealms.customfishing.storage.method.database.sql.SQLiteImpl; +import net.momirealms.customfishing.storage.method.file.JsonImpl; +import net.momirealms.customfishing.storage.method.file.YAMLImpl; +import net.momirealms.customfishing.storage.user.OfflineUserImpl; +import net.momirealms.customfishing.storage.user.OnlineUserImpl; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.nio.charset.StandardCharsets; +import java.util.HashSet; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +public class StorageManagerImpl implements StorageManager, Listener { + + private final CustomFishingPlugin plugin; + private DataStorageInterface dataSource; + private StorageType previousType; + private final ConcurrentHashMap onlineUserMap; + private final HashSet locked; + private boolean hasRedis; + private RedisManager redisManager; + private String uniqueID; + + public StorageManagerImpl(CustomFishingPluginImpl plugin) { + this.plugin = plugin; + this.locked = new HashSet<>(); + this.onlineUserMap = new ConcurrentHashMap<>(); + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + public void reload() { + YamlConfiguration config = plugin.getConfig("database.yml"); + uniqueID = config.getString("unique-server-id", "default"); + StorageType storageType = StorageType.valueOf(config.getString("data-storage-method", "H2")); + if (storageType != previousType) { + if (this.dataSource != null) this.dataSource.disable(); + this.previousType = storageType; + switch (storageType) { + case H2 -> this.dataSource = new H2Impl(plugin); + case JSON -> this.dataSource = new JsonImpl(plugin); + case YAML -> this.dataSource = new YAMLImpl(plugin); + case SQLite -> this.dataSource = new SQLiteImpl(plugin); + case MySQL -> this.dataSource = new MySQLImpl(plugin); + case MariaDB -> this.dataSource = new MariaDBImpl(plugin); + case MongoDB -> this.dataSource = new MongoDBImpl(plugin); + } + if (dataSource != null) this.dataSource.initialize(); + else LogUtils.severe("No storage type is set."); + } + if (!hasRedis && config.getBoolean("Redis.enable", false)) { + hasRedis = true; + this.redisManager = new RedisManager(plugin); + this.redisManager.initialize(); + } + if (hasRedis && !config.getBoolean("Redis.enable", false) && redisManager != null) { + redisManager.disable(); + redisManager = null; + } + } + + public void disable() { + HandlerList.unregisterAll(this); + if (this.dataSource != null) + dataSource.disable(); + if (this.redisManager != null) + redisManager.disable(); + } + + @Override + public String getUniqueID() { + return uniqueID; + } + + @Override + public OnlineUserImpl getOnlineUser(UUID uuid) { + return onlineUserMap.get(uuid); + } + + @Override + public CompletableFuture> getOfflineUser(UUID uuid, boolean force) { + var optionalDataFuture = dataSource.getPlayerData(uuid, force); + return optionalDataFuture.thenCompose(optionalUser -> { + if (optionalUser.isEmpty()) { + // locked + return CompletableFuture.completedFuture(Optional.empty()); + } + PlayerData data = optionalUser.get(); + if (data == PlayerData.NEVER_PLAYED) { + return CompletableFuture.completedFuture(Optional.of(OfflineUserImpl.NEVER_PLAYED_USER)); + } else { + OfflineUserImpl offlineUser = new OfflineUserImpl(uuid, data.getName(), data); + return CompletableFuture.completedFuture(Optional.of(offlineUser)); + } + }); + } + + @Override + public CompletableFuture getRedisPlayerCount() { + return redisManager.getPlayerCount(); + } + + @Override + public DataStorageInterface getDataSource() { + return dataSource; + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + locked.add(uuid); + if (!hasRedis) { + waitForDataLockRelease(uuid, 1); + } else { + redisReadingData(uuid); + } + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + if (locked.contains(uuid)) + return; + + OnlineUserImpl onlineUser = onlineUserMap.remove(uuid); + if (onlineUser == null) return; + PlayerData data = onlineUser.getPlayerData(); + + if (hasRedis) { + redisManager.setChangeServer(uuid).thenRun( + () -> redisManager.setPlayData(uuid, data, true).thenRun( + () -> dataSource.setPlayData(uuid, data, true).thenAccept( + result -> { + if (result) locked.remove(uuid); + }))); + } else { + dataSource.setPlayData(uuid, data, true).thenAccept( + result -> { + if (result) locked.remove(uuid); + }); + } + } + + public void redisReadingData(UUID uuid) { + // delay 0.5s for another server to insert the key + plugin.getScheduler().runTaskAsyncLater(() -> redisManager.getChangeServer(uuid).thenAccept(result -> { + if (!result) { + waitForDataLockRelease(uuid, 3); + } else { + new RedisGetDataTask(uuid); + } + }), 500, TimeUnit.MILLISECONDS); + } + + public class RedisGetDataTask implements Runnable { + + private final UUID uuid; + private int triedTimes; + private final CancellableTask task; + + public RedisGetDataTask(UUID uuid) { + this.uuid = uuid; + this.task = plugin.getScheduler().runTaskAsyncTimer(this, 200, 200, TimeUnit.MILLISECONDS); + } + + @Override + public void run() { + triedTimes++; + Player player = Bukkit.getPlayer(uuid); + if (player == null || !player.isOnline()) { + // offline + task.cancel(); + return; + } + if (triedTimes >= 10) { + waitForDataLockRelease(uuid, 3); + return; + } + redisManager.getPlayerData(uuid, false).thenAccept(optionalData -> { + if (optionalData.isPresent()) { + putDataInCache(player, optionalData.get()); + task.cancel(); + } + }); + } + } + + // wait 1 second for the lock to release + // try three times at most + public void waitForDataLockRelease(UUID uuid, int times) { + plugin.getScheduler().runTaskAsyncLater(() -> { + var player = Bukkit.getPlayer(uuid); + if (player == null || !player.isOnline() || times > 3) + return; + this.dataSource.getPlayerData(uuid, false).thenAccept(optionalData -> { + if (optionalData.isEmpty()) { + waitForDataLockRelease(uuid, times + 1); + } else { + putDataInCache(player, optionalData.get()); + } + }); + }, 1, TimeUnit.SECONDS); + } + + public void putDataInCache(Player player, PlayerData playerData) { + locked.remove(player.getUniqueId()); + OnlineUserImpl bukkitUser = new OnlineUserImpl(player, playerData); + onlineUserMap.put(player.getUniqueId(), bukkitUser); + } + + @Override + public boolean isRedisEnabled() { + return hasRedis; + } + + @Nullable + public RedisManager getRedisManager() { + return redisManager; + } + + @Override + public byte[] toBytes(@NotNull PlayerData data) { + return toJson(data).getBytes(StandardCharsets.UTF_8); + } + + @Override + @NotNull + public String toJson(@NotNull PlayerData data) { + return new GsonBuilder().create().toJson(data); + } + + @Override + @NotNull + public PlayerData fromBytes(byte[] data) { + try { + return new GsonBuilder().create().fromJson(new String(data, StandardCharsets.UTF_8), PlayerData.class); + } catch (JsonSyntaxException e) { + throw new DataSerializationException("Failed to get PlayerData from bytes", e); + } + } + + public static class DataSerializationException extends RuntimeException { + protected DataSerializationException(String message, Throwable cause) { + super(message, cause); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/AbstractStorage.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/AbstractStorage.java new file mode 100644 index 00000000..18317ddb --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/AbstractStorage.java @@ -0,0 +1,29 @@ +package net.momirealms.customfishing.storage.method; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.DataStorageInterface; + +import java.time.Instant; + +public abstract class AbstractStorage implements DataStorageInterface { + + protected CustomFishingPlugin plugin; + + public AbstractStorage(CustomFishingPlugin plugin) { + this.plugin = plugin; + } + + @Override + public void initialize() { + + } + + @Override + public void disable() { + + } + + public int getCurrentSeconds() { + return (int) Instant.now().getEpochSecond(); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/nosql/MongoDBImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/nosql/MongoDBImpl.java new file mode 100644 index 00000000..0c3b4287 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/nosql/MongoDBImpl.java @@ -0,0 +1,134 @@ +package net.momirealms.customfishing.storage.method.database.nosql; + +import com.mongodb.*; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.result.InsertOneResult; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.StorageType; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.storage.method.AbstractStorage; +import org.bson.Document; +import org.bson.UuidRepresentation; +import org.bson.types.Binary; +import org.bson.types.ObjectId; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.util.Collections; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class MongoDBImpl extends AbstractStorage { + + private MongoClient mongoClient; + private MongoDatabase database; + private String collectionPrefix; + + public MongoDBImpl(CustomFishingPlugin plugin) { + super(plugin); + } + + @Override + public void initialize() { + YamlConfiguration config = plugin.getConfig("database.yml"); + ConfigurationSection section = config.getConfigurationSection("MongoDB"); + if (section == null) { + LogUtils.warn("Failed to load database config. It seems that your config is broken. Please regenerate a new one."); + return; + } + + collectionPrefix = section.getString("collection-prefix", "customfishing"); + var settings = MongoClientSettings.builder().uuidRepresentation(UuidRepresentation.STANDARD); + if (!section.getString("connection-uri", "").equals("")) { + settings.applyConnectionString(new ConnectionString(section.getString("connection-uri", ""))); + mongoClient = MongoClients.create(settings.build()); + return; + } + + if (section.contains("user")) { + MongoCredential credential = MongoCredential.createCredential( + section.getString("user", "root"), + section.getString("database", "minecraft"), + section.getString("password", "password").toCharArray() + ); + settings.credential(credential); + } + + settings.applyToClusterSettings(builder -> builder.hosts(Collections.singletonList(new ServerAddress( + section.getString("host", "localhost"), + section.getInt("port", 27017) + )))); + this.mongoClient = MongoClients.create(settings.build()); + this.database = mongoClient.getDatabase(section.getString("database", "minecraft")); + } + + @Override + public void disable() { + if (this.mongoClient != null) { + this.mongoClient.close(); + } + } + + public String getCollectionName(String sub) { + return getCollectionPrefix() + "_" + sub; + } + + public String getCollectionPrefix() { + return collectionPrefix; + } + + @Override + public StorageType getStorageType() { + return StorageType.MongoDB; + } + + @Override + public CompletableFuture> getPlayerData(UUID uuid, boolean force) { + var future = new CompletableFuture>(); + plugin.getScheduler().runTaskAsync(() -> { + MongoCollection collection = database.getCollection("movies"); + Document doc = collection.find(Filters.eq("uuid", uuid)).first(); + if (doc == null) { + if (Bukkit.getPlayer(uuid) != null) { + future.complete(Optional.of(PlayerData.empty())); + } else { + future.complete(Optional.of(PlayerData.NEVER_PLAYED)); + } + } else { + if (!force && doc.getInteger("lock") != 0) { + future.complete(Optional.empty()); + return; + } + Binary binary = (Binary) doc.get("data"); + future.complete(Optional.of(plugin.getStorageManager().fromBytes(binary.getData()))); + } + }); + return future; + } + + @Override + public CompletableFuture setPlayData(UUID uuid, PlayerData playerData, boolean unlock) { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + MongoCollection collection = database.getCollection(getCollectionName("data")); + try { + InsertOneResult result = collection.insertOne(new Document() + .append("_id", new ObjectId()) + .append("uuid", uuid) + .append("lock", unlock ? 0 : getCurrentSeconds()) + .append("data", new Binary(plugin.getStorageManager().toBytes(playerData)))); + future.complete(result.wasAcknowledged()); + } catch (MongoException e) { + future.completeExceptionally(e); + } + }); + return future; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/nosql/RedisManager.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/nosql/RedisManager.java new file mode 100644 index 00000000..87249dfd --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/nosql/RedisManager.java @@ -0,0 +1,259 @@ +package net.momirealms.customfishing.storage.method.database.nosql; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.StorageType; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.storage.method.AbstractStorage; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; +import redis.clients.jedis.*; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisException; +import redis.clients.jedis.resps.Tuple; + +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +public class RedisManager extends AbstractStorage { + + private static RedisManager instance; + private JedisPool jedisPool; + private String password; + private int port; + private String host; + private JedisPoolConfig jedisPoolConfig; + private boolean useSSL; + private Jedis subscriber; + private JedisPubSub pubSub; + private CancellableTask checkConnectionTask; + + public RedisManager(CustomFishingPlugin plugin) { + super(plugin); + instance = this; + } + + public static RedisManager getInstance() { + return instance; + } + + public Jedis getJedis() { + return jedisPool.getResource(); + } + + @Override + public void initialize() { + YamlConfiguration config = plugin.getConfig("database.yml"); + ConfigurationSection section = config.getConfigurationSection("Redis"); + if (section == null) { + LogUtils.warn("Failed to load database config. It seems that your config is broken. Please regenerate a new one."); + return; + } + + jedisPoolConfig = new JedisPoolConfig(); + jedisPoolConfig.setTestWhileIdle(true); + jedisPoolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(30000)); + jedisPoolConfig.setNumTestsPerEvictionRun(-1); + jedisPoolConfig.setMinEvictableIdleTime(Duration.ofMillis(section.getInt("MinEvictableIdleTimeMillis",1800000))); + jedisPoolConfig.setMaxTotal(section.getInt("MaxTotal",8)); + jedisPoolConfig.setMaxIdle(section.getInt("MaxIdle",8)); + jedisPoolConfig.setMinIdle(section.getInt("MinIdle",1)); + jedisPoolConfig.setMaxWait(Duration.ofMillis(section.getInt("MaxWaitMillis"))); + + password = section.getString("password", ""); + port = section.getInt("port", 6379); + host = section.getString("host", "localhost"); + useSSL = section.getBoolean("use-ssl", false); + + if (password.isBlank()) { + jedisPool = new JedisPool(jedisPoolConfig, host, port, 0, useSSL); + } else { + jedisPool = new JedisPool(jedisPoolConfig, host, port, 0, password, useSSL); + } + try (Jedis jedis = jedisPool.getResource()) { + jedis.ping(); + } catch (JedisException e) { + LogUtils.warn("Failed to connect redis.", e); + } + + this.checkConnectionTask = plugin.getScheduler().runTaskAsyncTimer(() -> { + try { + pubSub.ping(); + } catch (JedisConnectionException e) { + subscribe(); + } + }, 30, 30, TimeUnit.SECONDS); + } + + @Override + public void disable() { + this.removeServerPlayers(plugin.getStorageManager().getUniqueID()); + if (checkConnectionTask != null && !checkConnectionTask.isCancelled()) + checkConnectionTask.cancel(); + if (jedisPool != null && !jedisPool.isClosed()) + jedisPool.close(); + if (pubSub != null && !pubSub.isSubscribed()) + pubSub.unsubscribe(); + if (subscriber != null) + subscriber.close(); + } + + public void sendRedisMessage(@NotNull String channel, @NotNull String message) { + try (Jedis jedis = jedisPool.getResource()) { + jedis.publish(channel, message); + } + } + + private void subscribe() { + new Thread(() -> { + try (final Jedis jedis = password.isBlank() ? + new Jedis(host, port, 0, useSSL) : + new Jedis(host, port, DefaultJedisClientConfig + .builder() + .password(password) + .timeoutMillis(0) + .ssl(useSSL) + .build()) + ) { + subscriber = jedis; + subscriber.connect(); + pubSub = new JedisPubSub() { + @Override + public void onMessage(String channel, String message) { + if (!channel.equals("cf_competition")) { + return; + } + String[] split = message.split(";"); + String action = split[0]; + switch (action) { + case "start" -> { + // start competition for all the servers that connected to redis + plugin.getCompetitionManager().startCompetition(split[1], true, false); + } + case "end" -> { + if (plugin.getCompetitionManager().getOnGoingCompetition() != null) + plugin.getCompetitionManager().getOnGoingCompetition().end(); + } + case "stop" -> { + if (plugin.getCompetitionManager().getOnGoingCompetition() != null) + plugin.getCompetitionManager().getOnGoingCompetition().stop(); + } + } + } + }; + subscriber.subscribe(pubSub, "cf_competition"); + } + }).start(); + } + + @Override + public StorageType getStorageType() { + return StorageType.Redis; + } + + public CompletableFuture getPlayerCount() { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + int players = 0; + try (Jedis jedis = jedisPool.getResource()) { + var list = jedis.zrangeWithScores("cf_players",0, -1); + for (Tuple tuple : list) { + players += (int) tuple.getScore(); + } + } + future.complete(players); + }); + return future; + } + + public CompletableFuture setServerPlayers(int amount, String unique) { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + try (Jedis jedis = jedisPool.getResource()) { + jedis.zadd("cf_players", amount, unique); + } + future.complete(null); + }); + return future; + } + + public void removeServerPlayers(String unique) { + try (Jedis jedis = jedisPool.getResource()) { + jedis.zrem("cf_players", unique); + } + } + + public CompletableFuture setChangeServer(UUID uuid) { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + try (Jedis jedis = jedisPool.getResource()) { + jedis.setex( + getRedisKey("cf_server", uuid), + 10, + new byte[0] + ); + } + future.complete(null); + }); + return future; + } + + public CompletableFuture getChangeServer(UUID uuid) { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + try (Jedis jedis = jedisPool.getResource()) { + byte[] key = getRedisKey("cf_server", uuid); + if (jedis.get(key) != null) { + jedis.del(key); + future.complete(true); + } else { + future.complete(false); + } + } + }); + return future; + } + + @Override + public CompletableFuture> getPlayerData(UUID uuid, boolean ignore) { + var future = new CompletableFuture>(); + plugin.getScheduler().runTaskAsync(() -> { + try (Jedis jedis = jedisPool.getResource()) { + byte[] key = getRedisKey("cf_data", uuid); + byte[] data = jedis.get(key); + jedis.del(key); + if (data != null) { + future.complete(Optional.of(plugin.getStorageManager().fromBytes(data))); + } else { + future.complete(Optional.empty()); + } + } + }); + return future; + } + + @Override + public CompletableFuture setPlayData(UUID uuid, PlayerData playerData, boolean ignore) { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + try (Jedis jedis = jedisPool.getResource()) { + jedis.setex( + getRedisKey("cf_data", uuid), + 10, + plugin.getStorageManager().toBytes(playerData) + ); + } + }); + return future; + } + + private byte[] getRedisKey(String key, @NotNull UUID uuid) { + return (key + ":" + uuid).getBytes(StandardCharsets.UTF_8); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/AbstractHikariDatabase.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/AbstractHikariDatabase.java new file mode 100644 index 00000000..49801641 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/AbstractHikariDatabase.java @@ -0,0 +1,103 @@ +package net.momirealms.customfishing.storage.method.database.sql; + +import com.zaxxer.hikari.HikariDataSource; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.StorageType; +import net.momirealms.customfishing.api.util.LogUtils; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; + +public abstract class AbstractHikariDatabase extends AbstractSQLDatabase { + + private HikariDataSource dataSource; + private final String driverClass; + private final String sqlBrand; + + public AbstractHikariDatabase(CustomFishingPlugin plugin) { + super(plugin); + this.driverClass = getStorageType() == StorageType.MariaDB ? "org.mariadb.jdbc.Driver" : "com.mysql.cj.jdbc.Driver"; + this.sqlBrand = getStorageType() == StorageType.MariaDB ? "MariaDB" : "MySQL"; + try { + Class.forName(this.driverClass); + } catch (ClassNotFoundException e1) { + if (getStorageType() == StorageType.MariaDB) { + LogUtils.warn("No MariaDB driver is found"); + } else if (getStorageType() == StorageType.MySQL) { + try { + Class.forName("com.mysql.jdbc.Driver"); + LogUtils.warn("It seems that you are not using MySQL 8.0+. It's recommended to update."); + } catch (ClassNotFoundException e2) { + LogUtils.warn("No MySQL driver is found"); + } + } + } + } + + @Override + public void initialize() { + YamlConfiguration config = plugin.getConfig("database.yml"); + ConfigurationSection section = config.getConfigurationSection(sqlBrand); + if (section == null) { + LogUtils.warn("Failed to load database config. It seems that your config is broken. Please regenerate a new one."); + return; + } + + super.tablePrefix = section.getString("table-prefix", "customfishing"); + dataSource = new HikariDataSource(); + dataSource.setDriverClassName(driverClass); + dataSource.setJdbcUrl(String.format("jdbc:%s://%s:%s/%s%s", + sqlBrand.toLowerCase(Locale.ENGLISH), + section.getString("host", "localhost"), + section.getString("port", "3306"), + section.getString("database", "minecraft"), + section.getString("connection-parameters") + )); + + dataSource.setUsername(section.getString("user", "root")); + dataSource.setPassword(section.getString("password", "pa55w0rd")); + + dataSource.setMaximumPoolSize(section.getInt("Pool-Settings.max-pool-size", 10)); + dataSource.setMinimumIdle(section.getInt("Pool-Settings.min-idle", 10)); + dataSource.setMaxLifetime(section.getLong("Pool-Settings.max-lifetime", 180000L)); + dataSource.setKeepaliveTime(section.getLong("Pool-Settings.keep-alive-time", 60000L)); + dataSource.setConnectionTimeout(section.getLong("Pool-Settings.time-out", 20000L)); + dataSource.setPoolName("CustomFishingHikariPool"); + + final Properties properties = new Properties(); + properties.putAll( + Map.of("cachePrepStmts", "true", + "prepStmtCacheSize", "250", + "prepStmtCacheSqlLimit", "2048", + "useServerPrepStmts", "true", + "useLocalSessionState", "true", + "useLocalTransactionState", "true" + )); + properties.putAll( + Map.of( + "rewriteBatchedStatements", "true", + "cacheResultSetMetadata", "true", + "cacheServerConfiguration", "true", + "elideSetAutoCommits", "true", + "maintainTimeStats", "false") + ); + dataSource.setDataSourceProperties(properties); + super.createTableIfNotExist(); + } + + @Override + public void disable() { + if (dataSource != null && !dataSource.isClosed()) + dataSource.close(); + } + + @Override + public Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/AbstractSQLDatabase.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/AbstractSQLDatabase.java new file mode 100644 index 00000000..0034e167 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/AbstractSQLDatabase.java @@ -0,0 +1,143 @@ +package net.momirealms.customfishing.storage.method.database.sql; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.setting.Config; +import net.momirealms.customfishing.storage.method.AbstractStorage; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.sql.*; +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public abstract class AbstractSQLDatabase extends AbstractStorage { + + protected String tablePrefix; + + public AbstractSQLDatabase(CustomFishingPlugin plugin) { + super(plugin); + } + + public abstract Connection getConnection() throws SQLException; + + public void createTableIfNotExist() { + try (Connection connection = getConnection()) { + final String[] databaseSchema = getSchema(getStorageType().name().toLowerCase(Locale.ENGLISH)); + try (Statement statement = connection.createStatement()) { + for (String tableCreationStatement : databaseSchema) { + statement.execute(tableCreationStatement); + } + } catch (SQLException e) { + LogUtils.warn("Failed to create tables", e); + } + } catch (SQLException e) { + LogUtils.warn("Failed to get sql connection", e); + } catch (IOException e) { + LogUtils.warn("Failed to get schema resource", e); + } + } + + private String[] getSchema(@NotNull String fileName) throws IOException { + return replaceSchemaPlaceholder(new String(Objects.requireNonNull(plugin.getResource("schema/" + fileName + ".sql")) + .readAllBytes(), StandardCharsets.UTF_8)).split(";"); + } + + private String replaceSchemaPlaceholder(@NotNull String sql) { + return sql.replace("{prefix}", tablePrefix); + } + + public String getTableName(String sub) { + return getTablePrefix() + "_" + sub; + } + + public String getTablePrefix() { + return tablePrefix; + } + + @Override + public CompletableFuture> getPlayerData(UUID uuid, boolean force) { + var future = new CompletableFuture>(); + plugin.getScheduler().runTaskAsync(() -> { + try ( + Connection connection = getConnection(); + PreparedStatement statement = connection.prepareStatement(String.format(SqlConstants.SQL_SELECT_BY_UUID, getTableName("data"))) + ) { + statement.setString(1, uuid.toString()); + ResultSet rs = statement.executeQuery(); + if (rs.next()) { + int lock = rs.getInt(2); + if (!force && (lock != 0 && getCurrentSeconds() - Config.dataSaveInterval <= lock)) { + statement.close(); + rs.close(); + connection.close(); + future.complete(Optional.empty()); + return; + } + final Blob blob = rs.getBlob("data"); + final byte[] dataByteArray = blob.getBytes(1, (int) blob.length()); + blob.free(); + future.complete(Optional.of(plugin.getStorageManager().fromBytes(dataByteArray))); + } else if (Bukkit.getPlayer(uuid) != null) { + var data = PlayerData.empty(); + insertPlayerData(uuid, data); + future.complete(Optional.of(data)); + } else { + future.complete(Optional.of(PlayerData.NEVER_PLAYED)); + } + } catch (SQLException e) { + LogUtils.warn("Failed to get " + uuid + "'s data.", e); + future.completeExceptionally(e); + } + }); + return future; + } + + @Override + public CompletableFuture setPlayData(UUID uuid, PlayerData playerData, boolean unlock) { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + try ( + Connection connection = getConnection(); + PreparedStatement statement = connection.prepareStatement(String.format(SqlConstants.SQL_UPDATE_BY_UUID, getTableName("data"))) + ) { + statement.setInt(1, unlock ? 0 : getCurrentSeconds()); + statement.setBlob(2, new ByteArrayInputStream(plugin.getStorageManager().toBytes(playerData))); + statement.setString(3, uuid.toString()); + statement.executeUpdate(); + future.complete(true); + } catch (SQLException e) { + LogUtils.warn("Failed to update " + uuid + "'s data.", e); + future.completeExceptionally(e); + } + }); + return future; + } + + public void insertPlayerData(UUID uuid, PlayerData playerData) { + try ( + Connection connection = getConnection(); + PreparedStatement statement = connection.prepareStatement(String.format(SqlConstants.SQL_INSERT_DATA_BY_UUID, getTableName("data"))) + ) { + statement.setString(1, uuid.toString()); + statement.setInt(2, getCurrentSeconds()); + statement.setBlob(3, new ByteArrayInputStream(plugin.getStorageManager().toBytes(playerData))); + statement.execute(); + } catch (SQLException e) { + LogUtils.warn("Failed to insert " + uuid + "'s data.", e); + } + } + + public static class SqlConstants { + public static final String SQL_SELECT_BY_UUID = "SELECT * FROM `%s` WHERE `uuid` = ?"; + public static final String SQL_UPDATE_BY_UUID = "UPDATE `%s` SET `lock` = ?, `data` = ? WHERE `uuid` = ?"; + public static final String SQL_INSERT_DATA_BY_UUID = "INSERT INTO `%s`(`uuid`, `lock`, `data`) VALUES(?, ?, ?)"; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/H2Impl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/H2Impl.java new file mode 100644 index 00000000..1f62a965 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/H2Impl.java @@ -0,0 +1,47 @@ +package net.momirealms.customfishing.storage.method.database.sql; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.StorageType; +import org.bukkit.configuration.file.YamlConfiguration; +import org.h2.jdbcx.JdbcConnectionPool; + +import java.io.File; +import java.sql.Connection; +import java.sql.SQLException; + +public class H2Impl extends AbstractSQLDatabase { + + private JdbcConnectionPool connectionPool; + + public H2Impl(CustomFishingPlugin plugin) { + super(plugin); + } + + @Override + public void initialize() { + YamlConfiguration config = plugin.getConfig("database.yml"); + File databaseFile = new File(plugin.getDataFolder(), config.getString("H2.file", "data.db")); + super.tablePrefix = config.getString("H2.table-prefix", "customfishing"); + + final String url = String.format("jdbc:h2:%s", databaseFile.getAbsolutePath()); + this.connectionPool = JdbcConnectionPool.create(url, "sa", ""); + super.createTableIfNotExist(); + } + + @Override + public void disable() { + if (connectionPool != null) { + connectionPool.dispose(); + } + } + + @Override + public StorageType getStorageType() { + return StorageType.H2; + } + + @Override + public Connection getConnection() throws SQLException { + return connectionPool.getConnection(); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/MariaDBImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/MariaDBImpl.java new file mode 100644 index 00000000..1607d8c9 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/MariaDBImpl.java @@ -0,0 +1,16 @@ +package net.momirealms.customfishing.storage.method.database.sql; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.StorageType; + +public class MariaDBImpl extends AbstractHikariDatabase { + + public MariaDBImpl(CustomFishingPlugin plugin) { + super(plugin); + } + + @Override + public StorageType getStorageType() { + return StorageType.MariaDB; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/MySQLImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/MySQLImpl.java new file mode 100644 index 00000000..c791e8e8 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/MySQLImpl.java @@ -0,0 +1,16 @@ +package net.momirealms.customfishing.storage.method.database.sql; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.StorageType; + +public class MySQLImpl extends AbstractHikariDatabase { + + public MySQLImpl(CustomFishingPlugin plugin) { + super(plugin); + } + + @Override + public StorageType getStorageType() { + return StorageType.MySQL; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/SQLiteImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/SQLiteImpl.java new file mode 100644 index 00000000..2bbf5119 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/database/sql/SQLiteImpl.java @@ -0,0 +1,151 @@ +package net.momirealms.customfishing.storage.method.database.sql; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.StorageType; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.setting.Config; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.sqlite.SQLiteConfig; + +import java.io.File; +import java.io.IOException; +import java.sql.*; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class SQLiteImpl extends AbstractSQLDatabase { + + private Connection connection; + private File databaseFile; + + public SQLiteImpl(CustomFishingPlugin plugin) { + super(plugin); + } + + @Override + public void initialize() { + YamlConfiguration config = plugin.getConfig("database.yml"); + this.databaseFile = new File(plugin.getDataFolder(), config.getString("SQLite.file", "data") + ".db"); + super.tablePrefix = config.getString("SQLite.table-prefix", "customfishing"); + super.createTableIfNotExist(); + } + + @Override + public void disable() { + try { + if (connection != null && !connection.isClosed()) + connection.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public StorageType getStorageType() { + return StorageType.SQLite; + } + + @Override + public Connection getConnection() throws SQLException { + if (connection == null || connection.isClosed()) { + setConnection(); + } + return connection; + } + + @Override + public CompletableFuture> getPlayerData(UUID uuid, boolean force) { + var future = new CompletableFuture>(); + plugin.getScheduler().runTaskAsync(() -> { + try ( + Connection connection = getConnection(); + PreparedStatement statement = connection.prepareStatement(String.format(SqlConstants.SQL_SELECT_BY_UUID, getTableName("data"))) + ) { + statement.setString(1, uuid.toString()); + ResultSet rs = statement.executeQuery(); + if (rs.next()) { + int lock = rs.getInt(2); + if (!force && (lock != 0 && getCurrentSeconds() - Config.dataSaveInterval <= lock)) { + statement.close(); + rs.close(); + connection.close(); + future.complete(Optional.empty()); + return; + } + final byte[] dataByteArray = rs.getBytes("data"); + future.complete(Optional.of(plugin.getStorageManager().fromBytes(dataByteArray))); + } else if (Bukkit.getPlayer(uuid) != null) { + var data = PlayerData.empty(); + insertPlayerData(uuid, data); + future.complete(Optional.of(data)); + } else { + future.complete(Optional.of(PlayerData.NEVER_PLAYED)); + } + } catch (SQLException e) { + LogUtils.warn("Failed to get " + uuid + "'s data.", e); + future.completeExceptionally(e); + } + }); + return future; + } + + @Override + public CompletableFuture setPlayData(UUID uuid, PlayerData playerData, boolean unlock) { + var future = new CompletableFuture(); + plugin.getScheduler().runTaskAsync(() -> { + try ( + Connection connection = getConnection(); + PreparedStatement statement = connection.prepareStatement(String.format(SqlConstants.SQL_UPDATE_BY_UUID, getTableName("data"))) + ) { + statement.setInt(1, unlock ? 0 : getCurrentSeconds()); + statement.setBytes(2, plugin.getStorageManager().toBytes(playerData)); + statement.setString(3, uuid.toString()); + statement.executeUpdate(); + future.complete(true); + } catch (SQLException e) { + LogUtils.warn("Failed to update " + uuid + "'s data.", e); + future.completeExceptionally(e); + } + }); + return future; + } + + @Override + public void insertPlayerData(UUID uuid, PlayerData playerData) { + try ( + Connection connection = getConnection(); + PreparedStatement statement = connection.prepareStatement(String.format(SqlConstants.SQL_INSERT_DATA_BY_UUID, getTableName("data"))) + ) { + statement.setString(1, uuid.toString()); + statement.setInt(2, getCurrentSeconds()); + statement.setBytes(3, plugin.getStorageManager().toBytes(playerData)); + statement.execute(); + } catch (SQLException e) { + LogUtils.warn("Failed to insert " + uuid + "'s data.", e); + } + } + + private void setConnection() { + try { + if (!databaseFile.exists()) databaseFile.createNewFile(); + Class.forName("org.sqlite.JDBC"); + SQLiteConfig config = new SQLiteConfig(); + config.enforceForeignKeys(true); + config.setEncoding(SQLiteConfig.Encoding.UTF8); + config.setSynchronous(SQLiteConfig.SynchronousMode.FULL); + connection = DriverManager.getConnection( + String.format("jdbc:sqlite:%s", databaseFile.getAbsolutePath()), + config.toProperties() + ); + } catch (IOException e) { + LogUtils.warn("Failed to create the SQLite database.", e); + } catch (SQLException e) { + LogUtils.warn("Failed to initialize SQLite database.", e); + } catch (ClassNotFoundException e) { + LogUtils.warn("Failed to find SQLite driver.", e); + } + } +} \ No newline at end of file diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/file/JsonImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/file/JsonImpl.java new file mode 100644 index 00000000..480119f2 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/file/JsonImpl.java @@ -0,0 +1,97 @@ +/* + * 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.storage.method.file; + +import com.google.gson.Gson; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.StorageType; +import net.momirealms.customfishing.storage.method.AbstractStorage; +import org.bukkit.Bukkit; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class JsonImpl extends AbstractStorage { + + public JsonImpl(CustomFishingPlugin plugin) { + super(plugin); + File folder = new File(plugin.getDataFolder(), "data"); + if (!folder.exists()) folder.mkdirs(); + } + + @Override + public StorageType getStorageType() { + return StorageType.JSON; + } + + @Override + public CompletableFuture> getPlayerData(UUID uuid, boolean ignore) { + File file = getPlayerDataFile(uuid); + PlayerData playerData; + if (file.exists()) { + playerData = readFromJsonFile(file, PlayerData.class); + } else if (Bukkit.getPlayer(uuid) != null) { + playerData = PlayerData.empty(); + } else { + playerData = PlayerData.NEVER_PLAYED; + } + return CompletableFuture.completedFuture(Optional.of(playerData)); + } + + @Override + public CompletableFuture setPlayData(UUID uuid, PlayerData playerData, boolean ignore) { + this.saveToJsonFile(playerData, getPlayerDataFile(uuid)); + return CompletableFuture.completedFuture(true); + } + + public File getPlayerDataFile(UUID uuid) { + return new File(plugin.getDataFolder(), "data" + File.separator + uuid + ".json"); + } + + public void saveToJsonFile(Object obj, File filepath) { + Gson gson = new Gson(); + try (FileWriter file = new FileWriter(filepath)) { + gson.toJson(obj, file); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public T readFromJsonFile(File file, Class classOfT) { + Gson gson = new Gson(); + String jsonContent = new String(readFileToByteArray(file), StandardCharsets.UTF_8); + return gson.fromJson(jsonContent, classOfT); + } + + public byte[] readFileToByteArray(File file) { + byte[] fileBytes = new byte[(int) file.length()]; + try (FileInputStream fis = new FileInputStream(file)) { + fis.read(fileBytes); + } catch (IOException e) { + e.printStackTrace(); + } + return fileBytes; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/method/file/YAMLImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/method/file/YAMLImpl.java new file mode 100644 index 00000000..e5cf8335 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/method/file/YAMLImpl.java @@ -0,0 +1,88 @@ +package net.momirealms.customfishing.storage.method.file; + +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.data.*; +import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.storage.method.AbstractStorage; +import net.momirealms.customfishing.util.ConfigUtils; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class YAMLImpl extends AbstractStorage { + + public YAMLImpl(CustomFishingPlugin plugin) { + super(plugin); + File folder = new File(plugin.getDataFolder(), "data"); + if (!folder.exists()) folder.mkdirs(); + } + + @Override + public StorageType getStorageType() { + return StorageType.YAML; + } + + public File getPlayerDataFile(UUID uuid) { + return new File(plugin.getDataFolder(), "data" + File.separator + uuid + ".yml"); + } + + @Override + public CompletableFuture> getPlayerData(UUID uuid, boolean ignore) { + File dataFile = getPlayerDataFile(uuid); + if (!dataFile.exists()) { + if (Bukkit.getPlayer(uuid) != null) { + return CompletableFuture.completedFuture(Optional.of(PlayerData.empty())); + } else { + return CompletableFuture.completedFuture(Optional.of(PlayerData.NEVER_PLAYED)); + } + } + YamlConfiguration data = ConfigUtils.readData(dataFile); + PlayerData playerData = new PlayerData.Builder() + .setBagData(new InventoryData(data.getString("bag", ""), data.getInt("size", 9))) + .setEarningData(new EarningData(data.getDouble("earnings"), data.getInt("date"))) + .setStats(getStatistics(data.getConfigurationSection("stats"))) + .setName(data.getString("name")) + .build(); + return CompletableFuture.completedFuture(Optional.of(playerData)); + } + + @Override + public CompletableFuture setPlayData(UUID uuid, PlayerData playerData, boolean ignore) { + YamlConfiguration data = new YamlConfiguration(); + data.set("name", playerData.getName()); + data.set("bag", playerData.getBagData().serialized); + data.set("size", playerData.getBagData().size); + data.set("date", playerData.getEarningData().date); + data.set("earnings", playerData.getEarningData().earnings); + ConfigurationSection section = data.createSection("stats"); + for (Map.Entry entry : playerData.getStatistics().statisticMap.entrySet()) { + section.set(entry.getKey(), entry.getValue()); + } + try { + data.save(getPlayerDataFile(uuid)); + } catch (IOException e) { + LogUtils.warn("Failed to save player data", e); + } + return CompletableFuture.completedFuture(true); + } + + public StatisticData getStatistics(ConfigurationSection section) { + if (section == null) + return StatisticData.empty(); + else { + HashMap map = new HashMap<>(); + for (Map.Entry entry : section.getValues(false).entrySet()) { + map.put(entry.getKey(), (Integer) entry.getValue()); + } + return new StatisticData(map); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/user/OfflineUserImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/user/OfflineUserImpl.java new file mode 100644 index 00000000..a4765fdb --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/user/OfflineUserImpl.java @@ -0,0 +1,87 @@ +package net.momirealms.customfishing.storage.user; + +import net.momirealms.customfishing.adventure.AdventureManagerImpl; +import net.momirealms.customfishing.api.data.EarningData; +import net.momirealms.customfishing.api.data.InventoryData; +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.StatisticData; +import net.momirealms.customfishing.api.data.user.OfflineUser; +import net.momirealms.customfishing.api.mechanic.bag.FishingBagHolder; +import net.momirealms.customfishing.api.mechanic.statistic.Statistics; +import net.momirealms.customfishing.api.util.InventoryUtils; +import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; +import net.momirealms.customfishing.setting.Config; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class OfflineUserImpl implements OfflineUser { + + private final UUID uuid; + private final String name; + private final FishingBagHolder holder; + private final EarningData earningData; + private final Statistics statistics; + public static OfflineUserImpl NEVER_PLAYED_USER = new OfflineUserImpl(UUID.randomUUID(), "", PlayerData.empty()); + + public OfflineUserImpl(UUID uuid, String name, PlayerData playerData) { + this.name = name; + this.uuid = uuid; + this.holder = new FishingBagHolder(uuid); + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); + this.holder.setInventory(InventoryUtils.createInventory(this.holder, playerData.getBagData().size, + AdventureManagerImpl.getInstance().getComponentFromMiniMessage( + PlaceholderManagerImpl.getInstance().parse( + offlinePlayer, Config.bagTitle, Map.of("{player}", Optional.ofNullable(offlinePlayer.getName()).orElse(String.valueOf(uuid))) + ) + ))); + this.holder.setItems(InventoryUtils.getInventoryItems(playerData.getBagData().serialized)); + this.earningData = playerData.getEarningData(); + this.statistics = new Statistics(playerData.getStatistics()); + } + + @Override + public String getName() { + return name; + } + + @Override + public UUID getUUID() { + return uuid; + } + + @Override + public FishingBagHolder getHolder() { + return holder; + } + + @Override + public EarningData getEarningData() { + return earningData; + } + + @Override + public Statistics getStatistics() { + return statistics; + } + + @Override + public boolean isOnline() { + Player player = Bukkit.getPlayer(uuid); + return player != null && player.isOnline(); + } + + @Override + public PlayerData getPlayerData() { + return new PlayerData.Builder() + .setBagData(new InventoryData(InventoryUtils.stacksToBase64(holder.getInventory().getStorageContents()), holder.getInventory().getSize())) + .setEarningData(earningData) + .setStats(new StatisticData(statistics.getStatisticMap())) + .setName(name) + .build(); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/user/OnlineUserImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/user/OnlineUserImpl.java new file mode 100644 index 00000000..4ba36962 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/user/OnlineUserImpl.java @@ -0,0 +1,20 @@ +package net.momirealms.customfishing.storage.user; + +import net.momirealms.customfishing.api.data.PlayerData; +import net.momirealms.customfishing.api.data.user.OnlineUser; +import org.bukkit.entity.Player; + +public class OnlineUserImpl extends OfflineUserImpl implements OnlineUser { + + private final Player player; + + public OnlineUserImpl(Player player, PlayerData playerData) { + super(player.getUniqueId(), player.getName(), playerData); + this.player = player; + } + + @Override + public Player getPlayer() { + return player; + } +} diff --git a/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java similarity index 82% rename from src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java rename to plugin/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java index 2b5f789a..d9288c8f 100644 --- a/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java +++ b/plugin/src/main/java/net/momirealms/customfishing/util/ArmorStandUtils.java @@ -23,8 +23,8 @@ import com.comphenix.protocol.wrappers.*; import com.google.common.collect.Lists; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.loot.Item; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.api.CustomFishingPlugin; import org.bukkit.Location; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -55,7 +55,7 @@ public class ArmorStandUtils { public static PacketContainer getMetaPacket(int id) { PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); metaPacket.getIntegers().write(0, id); - if (CustomFishing.getInstance().getVersionHelper().isVersionNewerThan1_19_R2()) { + if (CustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_R2()) { WrappedDataWatcher wrappedDataWatcher = createDataWatcher(); setValueList(metaPacket, wrappedDataWatcher); } else { @@ -64,7 +64,7 @@ public class ArmorStandUtils { return metaPacket; } - static void setValueList(PacketContainer metaPacket, WrappedDataWatcher wrappedDataWatcher) { + private static void setValueList(PacketContainer metaPacket, WrappedDataWatcher wrappedDataWatcher) { List wrappedDataValueList = Lists.newArrayList(); wrappedDataWatcher.getWatchableObjects().stream().filter(Objects::nonNull).forEach(entry -> { final WrappedDataWatcher.WrappedDataWatcherObject dataWatcherObject = entry.getWatcherObject(); @@ -76,7 +76,7 @@ public class ArmorStandUtils { public static PacketContainer getMetaPacket(int id, String text) { PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); metaPacket.getIntegers().write(0, id); - if (CustomFishing.getInstance().getVersionHelper().isVersionNewerThan1_19_R2()) { + if (CustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_R2()) { WrappedDataWatcher wrappedDataWatcher = createDataWatcher(text); setValueList(metaPacket, wrappedDataWatcher); } else { @@ -104,7 +104,6 @@ public class ArmorStandUtils { wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, serializer2), (byte) 0x01); byte flag = 0x20; wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, serializer2), flag); - wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), true); return wrappedDataWatcher; } @@ -117,15 +116,11 @@ public class ArmorStandUtils { return equipPacket; } - public static void sendAnimationToPlayer(Location location, Player player, String key, int time) { + public static void sendAnimationToPlayer(Player player, Location location, ItemStack itemStack, int time) { int id = new Random().nextInt(Integer.MAX_VALUE); - Item item = CustomFishing.getInstance().getEffectManager().getUtilItem(key); - if (item == null) return; - CustomFishing.getProtocolManager().sendServerPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0))); - CustomFishing.getProtocolManager().sendServerPacket(player, getMetaPacket(id)); - CustomFishing.getProtocolManager().sendServerPacket(player, getEquipPacket(id, ItemStackUtils.getFromItem(item))); - CustomFishing.getInstance().getScheduler().runTaskAsyncLater(() -> { - CustomFishing.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)); - }, time * 50L, TimeUnit.MILLISECONDS); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0))); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getMetaPacket(id)); + CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getEquipPacket(id, itemStack)); + CustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> CustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), time * 50L, TimeUnit.MILLISECONDS); } } \ No newline at end of file diff --git a/plugin/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java new file mode 100644 index 00000000..fd1fbd49 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java @@ -0,0 +1,108 @@ +package net.momirealms.customfishing.util; + +import net.momirealms.customfishing.api.common.Pair; +import net.momirealms.customfishing.api.mechanic.loot.Modifier; +import net.momirealms.customfishing.api.util.LogUtils; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class ConfigUtils { + + @SuppressWarnings("unchecked") + public static ArrayList stringListArgs(Object object) { + ArrayList list = new ArrayList<>(); + if (object instanceof String member) { + list.add(member); + } else if (object instanceof List members) { + list.addAll((Collection) members); + } + return list; + } + + public static Pair splitStringIntegerArgs(String value) { + String[] split = value.split("~"); + return Pair.of(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + } + + public static List> getWeights(List list) { + List> result = new ArrayList<>(list.size()); + for (String member : list) { + String[] split = member.split(":",2); + String key = split[0]; + result.add(Pair.of(key, Double.parseDouble(split[1]))); + } + return result; + } + + public static double getDoubleValue(Object arg) { + if (arg instanceof Double d) { + return d; + } else if (arg instanceof Integer i) { + return Double.valueOf(i); + } + return 0; + } + + public static List> getModifiers(List modList) { + List> result = new ArrayList<>(modList.size()); + for (String member : modList) { + String[] split = member.split(":",2); + String key = split[0]; + result.add(Pair.of(key, getModifier(split[1]))); + } + return result; + } + + /** + * Create a data file if not exists + * @param file file path + * @return yaml data + */ + @SuppressWarnings("ResultOfMethodCallIgnored") + public static YamlConfiguration readData(File file) { + if (!file.exists()) { + try { + file.getParentFile().mkdirs(); + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + LogUtils.warn("Failed to generate data files!
"); + } + } + return YamlConfiguration.loadConfiguration(file); + } + + public static Modifier getModifier(String text) { + if (text.length() == 0) { + throw new IllegalArgumentException("Weight format is invalid."); + } + switch (text.charAt(0)) { + case '/' -> { + double arg = Double.parseDouble(text.substring(1)); + return weight -> weight / arg; + } + case '*' -> { + double arg = Double.parseDouble(text.substring(1)); + return weight -> weight * arg; + } + case '-' -> { + double arg = Double.parseDouble(text.substring(1)); + return weight -> weight - arg; + } + case '%' -> { + double arg = Double.parseDouble(text.substring(1)); + return weight -> weight % arg; + } + case '+' -> { + double arg = Double.parseDouble(text.substring(1)); + return weight -> weight + arg; + } + default -> throw new IllegalArgumentException("Invalid weight: " + text); + } + } +} diff --git a/src/main/java/net/momirealms/customfishing/object/DynamicText.java b/plugin/src/main/java/net/momirealms/customfishing/util/DynamicText.java similarity index 63% rename from src/main/java/net/momirealms/customfishing/object/DynamicText.java rename to plugin/src/main/java/net/momirealms/customfishing/util/DynamicText.java index e7ba94a1..af0ebf8d 100644 --- a/src/main/java/net/momirealms/customfishing/object/DynamicText.java +++ b/plugin/src/main/java/net/momirealms/customfishing/util/DynamicText.java @@ -15,21 +15,22 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.object; +package net.momirealms.customfishing.util; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.integration.papi.PlaceholderManager; +import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.List; +import java.util.Map; public class DynamicText { private final Player owner; private String originalValue; private String latestValue; - private String[] ownerPlaceholders; + private String[] placeholders; + private String[] previousParsedValues; public DynamicText(Player owner, String rawValue) { this.owner = owner; @@ -37,31 +38,30 @@ public class DynamicText { } private void analyze(String value) { - List placeholdersOwner = new ArrayList<>(CustomFishing.getInstance().getIntegrationManager().getPlaceholderManager().detectPlaceholders(value)); + List placeholdersOwner = new ArrayList<>(PlaceholderManagerImpl.getInstance().detectPlaceholders(value)); String origin = value; for (String placeholder : placeholdersOwner) { origin = origin.replace(placeholder, "%s"); } originalValue = origin; - ownerPlaceholders = placeholdersOwner.toArray(new String[0]); + placeholders = placeholdersOwner.toArray(new String[0]); latestValue = originalValue; - update(); } public String getLatestValue() { return latestValue; } - public boolean update() { + public boolean update(Map placeholders) { String string = originalValue; - if (ownerPlaceholders.length != 0) { - PlaceholderManager placeholderManager = CustomFishing.getInstance().getIntegrationManager().getPlaceholderManager(); + if (this.placeholders.length != 0) { + PlaceholderManagerImpl placeholderManagerImpl = PlaceholderManagerImpl.getInstance(); if ("%s".equals(originalValue)) { - string = placeholderManager.parseSinglePlaceholder(owner, ownerPlaceholders[0]); + string = placeholderManagerImpl.getSingleValue(owner, this.placeholders[0], placeholders); } else { - Object[] values = new String[ownerPlaceholders.length]; - for (int i = 0; i < ownerPlaceholders.length; i++) { - values[i] = placeholderManager.parseSinglePlaceholder(owner, ownerPlaceholders[i]); + Object[] values = new String[this.placeholders.length]; + for (int i = 0; i < this.placeholders.length; i++) { + values[i] = placeholderManagerImpl.getSingleValue(owner, this.placeholders[i], placeholders); } string = String.format(originalValue, values); } diff --git a/src/main/java/net/momirealms/customfishing/util/FakeItemUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/FakeItemUtils.java similarity index 76% rename from src/main/java/net/momirealms/customfishing/util/FakeItemUtils.java rename to plugin/src/main/java/net/momirealms/customfishing/util/FakeItemUtils.java index faa07533..01f268e9 100644 --- a/src/main/java/net/momirealms/customfishing/util/FakeItemUtils.java +++ b/plugin/src/main/java/net/momirealms/customfishing/util/FakeItemUtils.java @@ -2,14 +2,17 @@ package net.momirealms.customfishing.util; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.WrappedDataValue; import com.comphenix.protocol.wrappers.WrappedDataWatcher; -import net.momirealms.customfishing.CustomFishing; +import com.google.common.collect.Lists; +import net.momirealms.customfishing.api.CustomFishingPlugin; import org.bukkit.Location; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; import java.util.List; +import java.util.Objects; import java.util.UUID; public class FakeItemUtils { @@ -34,9 +37,9 @@ public class FakeItemUtils { public static PacketContainer getMetaPacket(int id, ItemStack itemStack) { PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); metaPacket.getIntegers().write(0, id); - if (CustomFishing.getInstance().getVersionHelper().isVersionNewerThan1_19_R2()) { + if (CustomFishingPlugin.getInstance().getVersionManager().isVersionNewerThan1_19_R2()) { WrappedDataWatcher wrappedDataWatcher = createDataWatcher(itemStack); - ArmorStandUtils.setValueList(metaPacket, wrappedDataWatcher); + setValueList(metaPacket, wrappedDataWatcher); } else { metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(itemStack).getWatchableObjects()); } @@ -67,4 +70,13 @@ public class FakeItemUtils { wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(5, WrappedDataWatcher.Registry.get(Boolean.class)), true); return wrappedDataWatcher; } + + private static void setValueList(PacketContainer metaPacket, WrappedDataWatcher wrappedDataWatcher) { + List wrappedDataValueList = Lists.newArrayList(); + wrappedDataWatcher.getWatchableObjects().stream().filter(Objects::nonNull).forEach(entry -> { + final WrappedDataWatcher.WrappedDataWatcherObject dataWatcherObject = entry.getWatcherObject(); + wrappedDataValueList.add(new WrappedDataValue(dataWatcherObject.getIndex(), dataWatcherObject.getSerializer(), entry.getRawValue())); + }); + metaPacket.getDataValueCollectionModifier().write(0, wrappedDataValueList); + } } diff --git a/src/main/java/net/momirealms/customfishing/util/NBTUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/NBTUtils.java similarity index 79% rename from src/main/java/net/momirealms/customfishing/util/NBTUtils.java rename to plugin/src/main/java/net/momirealms/customfishing/util/NBTUtils.java index 841fe9a9..925ef2ab 100644 --- a/src/main/java/net/momirealms/customfishing/util/NBTUtils.java +++ b/plugin/src/main/java/net/momirealms/customfishing/util/NBTUtils.java @@ -18,40 +18,53 @@ package net.momirealms.customfishing.util; import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; import de.tr7zw.changeme.nbtapi.NBTListCompound; import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT; import org.bukkit.configuration.MemorySection; -import org.bukkit.inventory.ItemStack; import java.util.*; public class NBTUtils { - public static NBTItem setNBTToItemStack(Map nbt, ItemStack itemStack){ - NBTItem nbtItem = new NBTItem(itemStack); - setTags(nbt, nbtItem); - return nbtItem; + public static class StackElement { + final Map currentMap; + final NBTCompound currentNbtCompound; + + StackElement(Map map, NBTCompound nbtCompound) { + this.currentMap = map; + this.currentNbtCompound = nbtCompound; + } } @SuppressWarnings("unchecked") - public static void setTags(Map map, NBTCompound nbtCompound) { - for (Map.Entry entry : map.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - if (value instanceof MemorySection memorySection) { - setTags(memorySection.getValues(false), nbtCompound.addCompound(key)); - } else if (value instanceof List list) { - for (Object o : list) { - if (o instanceof String stringValue) { - setListValue(key, stringValue, nbtCompound); - } else if (o instanceof Map mapValue) { - NBTListCompound nbtListCompound = nbtCompound.getCompoundList(key).addCompound(); - setTags((Map) mapValue, nbtListCompound); + public static void setTagsFromBukkitYAML(NBTCompound nbtCompound, Map map) { + + Deque stack = new ArrayDeque<>(); + stack.push(new StackElement(map, nbtCompound)); + + while (!stack.isEmpty()) { + StackElement currentElement = stack.pop(); + Map currentMap = currentElement.currentMap; + NBTCompound currentNbtCompound = currentElement.currentNbtCompound; + + for (Map.Entry entry : currentMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof MemorySection memorySection) { + stack.push(new StackElement(memorySection.getValues(false), currentNbtCompound.addCompound(key))); + } else if (value instanceof List list) { + for (Object o : list) { + if (o instanceof String stringValue) { + setListValue(key, stringValue, currentNbtCompound); + } else if (o instanceof Map mapValue) { + NBTListCompound nbtListCompound = currentNbtCompound.getCompoundList(key).addCompound(); + stack.push(new StackElement((Map) mapValue, nbtListCompound)); + } } + } else if (value instanceof String stringValue) { + setSingleValue(key, stringValue, currentNbtCompound); } - } else if (value instanceof String stringValue) { - setSingleValue(key, stringValue, nbtCompound); } } } diff --git a/src/main/java/net/momirealms/customfishing/helper/VersionHelper.java b/plugin/src/main/java/net/momirealms/customfishing/version/VersionManagerImpl.java similarity index 51% rename from src/main/java/net/momirealms/customfishing/helper/VersionHelper.java rename to plugin/src/main/java/net/momirealms/customfishing/version/VersionManagerImpl.java index 97d542d4..b005525a 100644 --- a/src/main/java/net/momirealms/customfishing/helper/VersionHelper.java +++ b/plugin/src/main/java/net/momirealms/customfishing/version/VersionManagerImpl.java @@ -15,86 +15,75 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.helper; +package net.momirealms.customfishing.version; -import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion; -import de.tr7zw.changeme.nbtapi.utils.VersionChecker; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.util.AdventureUtils; +import io.papermc.paper.threadedregions.scheduler.AsyncScheduler; +import net.momirealms.customfishing.CustomFishingPluginImpl; +import net.momirealms.customfishing.api.manager.VersionManager; +import net.momirealms.customfishing.api.util.LogUtils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.reflect.Field; import java.net.URL; import java.net.URLConnection; +import java.util.concurrent.CompletableFuture; -public class VersionHelper { +public class VersionManagerImpl implements VersionManager { - private boolean isNewerThan1_19_R2; - private String serverVersion; - private final CustomFishing plugin; + private final boolean isNewerThan1_19_R2; + private final String serverVersion; + private final CustomFishingPluginImpl plugin; private final boolean isSpigot; - private final boolean isFolia; + private boolean isFolia; private final String pluginVersion; - public VersionHelper(CustomFishing plugin) { + @SuppressWarnings("deprecation") + public VersionManagerImpl(CustomFishingPluginImpl plugin) { this.plugin = plugin; - isVersionNewerThan1_19_R2(); - disableUseLessInfo(); + serverVersion = plugin.getServer().getClass().getPackage().getName().split("\\.")[3]; + String[] split = serverVersion.split("_"); + int main_ver = Integer.parseInt(split[1]); + if (main_ver >= 20) isNewerThan1_19_R2 = true; + else if (main_ver == 19) isNewerThan1_19_R2 = Integer.parseInt(split[2].substring(1)) >= 2; + else isNewerThan1_19_R2 = false; String server_name = plugin.getServer().getName(); - isSpigot = server_name.equals("CraftBukkit"); - isFolia = server_name.equals("DirtyFolia"); - pluginVersion = plugin.getDescription().getVersion(); + this.isSpigot = server_name.equals("CraftBukkit"); + try { + Class.forName(String.valueOf(AsyncScheduler.class)); + this.isFolia = true; + } catch (ClassNotFoundException ignored) {} + this.pluginVersion = plugin.getDescription().getVersion(); } + @Override public boolean isVersionNewerThan1_19_R2() { - if (serverVersion == null) { - serverVersion = plugin.getServer().getClass().getPackage().getName().split("\\.")[3]; - String[] split = serverVersion.split("_"); - int main_ver = Integer.parseInt(split[1]); - if (main_ver >= 20) isNewerThan1_19_R2 = true; - else if (main_ver == 19) isNewerThan1_19_R2 = Integer.parseInt(split[2].substring(1)) >= 2; - else isNewerThan1_19_R2 = false; - } return isNewerThan1_19_R2; } - private void disableUseLessInfo() { - MinecraftVersion.disableBStats(); - MinecraftVersion.disableUpdateCheck(); - VersionChecker.hideOk = true; - try { - Field field = MinecraftVersion.class.getDeclaredField("version"); - field.setAccessible(true); - MinecraftVersion minecraftVersion; - try { - minecraftVersion = MinecraftVersion.valueOf(serverVersion.replace("v", "MC")); - } catch (IllegalArgumentException ex) { - minecraftVersion = MinecraftVersion.UNKNOWN; - } - field.set(MinecraftVersion.class, minecraftVersion); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } - boolean hasGsonSupport; - try { - Class.forName("com.google.gson.Gson"); - hasGsonSupport = true; - } catch (Exception ex) { - hasGsonSupport = false; - } - try { - Field field= MinecraftVersion.class.getDeclaredField("hasGsonSupport"); - field.setAccessible(true); - field.set(Boolean.class, hasGsonSupport); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } + @Override + public boolean isSpigot() { + return isSpigot; } - public void checkUpdate() { + @Override + public String getPluginVersion() { + return pluginVersion; + } + + @Override + public boolean isFolia() { + return isFolia; + } + + @Override + public String getServerVersion() { + return serverVersion; + } + + @Override + public CompletableFuture checkUpdate() { + CompletableFuture updateFuture = new CompletableFuture<>(); plugin.getScheduler().runTaskAsync(() -> { try { URL url = new URL("https://api.polymart.org/v1/getResourceInfoSimple/?resource_id=2723&key=version"); @@ -103,28 +92,19 @@ public class VersionHelper { conn.setReadTimeout(60000); InputStream inputStream = conn.getInputStream(); String newest = new BufferedReader(new InputStreamReader(inputStream)).readLine(); - String current = plugin.getDescription().getVersion(); + String current = plugin.getVersionManager().getPluginVersion(); inputStream.close(); - if (!compareVer(newest, current)) { - AdventureUtils.consoleMessage(ConfigManager.lang.equalsIgnoreCase("chinese") ? "[CustomFishing] 当前已是最新版本" : "[CustomFishing] You are using the latest version."); + updateFuture.complete(false); return; } - - if (ConfigManager.lang.equalsIgnoreCase("chinese")) { - AdventureUtils.consoleMessage("[CustomFishing] 当前版本: " + current); - AdventureUtils.consoleMessage("[CustomFishing] 最新版本: " + newest); - AdventureUtils.consoleMessage("[CustomFishing] 请到 售后群https://polymart.org/resource/customfishing.2723 获取最新版本."); - } - else { - AdventureUtils.consoleMessage("[CustomFishing] Current version: " + current); - AdventureUtils.consoleMessage("[CustomFishing] Latest version: " + newest); - AdventureUtils.consoleMessage("[CustomFishing] Update is available: https://polymart.org/resource/customfishing.2723"); - } + updateFuture.complete(true); } catch (Exception exception) { - Log.warn("Error occurred when checking update"); + LogUtils.warn("Error occurred when checking update.", exception); + updateFuture.complete(false); } }); + return updateFuture; } private boolean compareVer(String newV, String currentV) { @@ -147,9 +127,7 @@ public class VersionHelper { } else if (newPart.length > 1 && currentPart.length > 1) { String[] newHotfix = newPart[1].split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"); String[] currentHotfix = currentPart[1].split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"); - // hotfix2 & hotfix if (newHotfix.length == 2 && currentHotfix.length == 1) return true; - // hotfix3 & hotfix2 else if (newHotfix.length > 1 && currentHotfix.length > 1) { int newHotfixNum = Integer.parseInt(newHotfix[1]); int currentHotfixNum = Integer.parseInt(currentHotfix[1]); @@ -171,19 +149,6 @@ public class VersionHelper { return false; } } - // if common parts are the same, the longer is newer return newVS.length > currentVS.length; } - - public boolean isSpigot() { - return isSpigot; - } - - public String getPluginVersion() { - return pluginVersion; - } - - public boolean isFolia() { - return isFolia; - } } \ No newline at end of file diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml new file mode 100644 index 00000000..eec225fc --- /dev/null +++ b/plugin/src/main/resources/config.yml @@ -0,0 +1,160 @@ +# Developer: @Xiao-MoMi +# Wiki: https://mo-mi.gitbook.io/xiaomomi-plugins/ +config-version: '26' + +# BStats +metrics: true + +# Check updates +update-checker: true + +# Available locales: chinese/english/spanish/turkish +lang: english + +# Mechanic settings +mechanics: + + # The requirements for the plugin to work + mechanic-requirements: + world_requirement: + type: '!world' + value: + - blacklist_world + + # Global loot properties + global-loot-properties: + show-in-fishfinder: true + disable-stat: false + disable-game: false + instant-game: false + prevent-grabbing: false + action: + success: + title_action: + type: random-title + value: + titles: + - 'GG!' + - 'Good Job!' + subtitles: + - 'You caught a {loot}' + - 'Whoa! Nice catch!' + - 'Oh {loot} here we go!' + - 'Let''s see what it is!' + fade-in: 20 + stay: 30 + fade-out: 10 + chance: 1.0 + failure: + title_action: + type: random-title + value: + titles: + - 'Be concentrated!' + - 'What a pity!' + - 'Try next time!' + - 'Bad luck' + subtitles: + - 'The fish escaped...' + fade-in: 20 + stay: 30 + fade-out: 10 + chance: 1.0 + + # Fishing bag is where players can store their baits, utils and rods (Fish optional) + fishing-bag: + # Enable + enable: true + # Fishing bag container title + bag-title: '{player}''s Fishing Bag' + # Can fishing bag store fishing loots? + can-store-loot: false + # Other whitelist-items + whitelist-items: + - fishing_rod + + # Lava fishing settings + lava-fishing: + # ticks + min-wait-time: 100 + max-wait-time: 600 + + # Animation settings + animation: + splash: + enable: true + water: water_effect + lava: lava_effect + duration: 25 + bait: + enable: true + + # Competition settings + competition: + # Use redis for cross server data synchronization + redis-ranking: false + # Increase this value would increase cpu load + # But would allow you to use more placeholders like {4_player} {5_score} + placeholder-limit: 3 + + # Enable vanilla fishing mechanic if there's no loot available + vanilla-mechanic-if-no-loot: + enable: false + # actions to trigger if vanilla mechanic not allowed + actions: + message_action: + type: message + value: + - 'There''s no loot here. Try to find another place for fishing.' + +# Other settings +other-settings: + + # Thread pool settings + thread-pool-settings: + # The size of the core Thread pool, that is, the size of the Thread pool when there is no task to execute + # Increase the size of corePoolSize when you are running a large server with many players fishing at the same time + corePoolSize: 4 + # The maximum number of threads allowed to be created in the Thread pool. The current number of threads in the Thread pool will not exceed this value + maximumPoolSize: 8 + # If a thread is idle for more than this attribute value, it will exit due to timeout + keepAliveTime: 10 + + # Event priority: MONITOR HIGHEST HIGH NORMAL LOW LOWEST + event-priority: NORMAL + + # Save the data from cache to file periodically to minimize the data loss if server crashes + data-saving-interval: 600 + + # Requires PlaceholderAPI to work + placeholder-register: + '{date}': '%server_date%' + + # CustomFishing supports using items from other plugins + # If items share the same id, they would inherit the effects + item-detection-order: + # - Oraxen + # - ItemsAdder + - CustomFishing + - vanilla + + # Offset characters' unicodes + # Never edit this unless you know what you are doing + offset-characters: + font: customfishing:offset_chars + '1':  + '2':  + '4':  + '8':  + '16':  + '32':  + '64':  + '128':  + '-1':  + '-2':  + '-4':  + '-8':  + '-16':  + '-32':  + '-64':  + '-128':  \ No newline at end of file diff --git a/src/main/resources/contents/baits/default.yml b/plugin/src/main/resources/contents/baits/default.yml similarity index 100% rename from src/main/resources/contents/baits/default.yml rename to plugin/src/main/resources/contents/baits/default.yml diff --git a/plugin/src/main/resources/contents/blocks/default.yml b/plugin/src/main/resources/contents/blocks/default.yml new file mode 100644 index 00000000..3dfe2ac4 --- /dev/null +++ b/plugin/src/main/resources/contents/blocks/default.yml @@ -0,0 +1,42 @@ +wooden_crate: + show-in-fishfinder: false + nick: Apple Crate + block: barrel + vector: + horizontal: 1.07 + vertical: 1.5 + properties: + directional: true + storage: + apple_1: + item: APPLE + amount: 1~2 + chance: 0.8 + apple_2: + item: APPLE + amount: 1~2 + chance: 0.8 + apple_3: + item: APPLE + amount: 1~2 + chance: 0.8 + apple_4: + item: APPLE + amount: 1~2 + chance: 0.8 + apple_5: + item: APPLE + amount: 1~2 + chance: 0.8 + apple_6: + item: APPLE + amount: 1~2 + chance: 0.8 + apple_7: + item: APPLE + amount: 1~2 + chance: 0.8 + apple_8: + item: APPLE + amount: 1~2 + chance: 0.8 \ No newline at end of file diff --git a/plugin/src/main/resources/contents/competitions/default.yml b/plugin/src/main/resources/contents/competitions/default.yml new file mode 100644 index 00000000..a3f182ed --- /dev/null +++ b/plugin/src/main/resources/contents/competitions/default.yml @@ -0,0 +1,123 @@ +example: + # TOTAL_SCORE + # CATCH_AMOUNT + # MAX_SIZE + # TOTAL_SIZE + # RANDOM + goal: CATCH_AMOUNT + + # Optional + # 1-7 + start-weekday: + - 1 + - 7 + + # Optional + start-time: + - '9:30' + - '14:30' + - '20:00' + + # Seconds + duration: 300 + + # Min players to start the competition + min-players: 2 + skip-actions: + broadcast: + type: broadcast + value: + - 'The number of players is not enough for the fishing competition to be started as scheduled.' + + bossbar: + enable: true + color: WHITE + overlay: PROGRESS + text: + - '[<#87CEFA>🎣] Time Left: <#E6E6FA>{time}s | Your Rank: <#E6E6FA>{rank} | No.1 Player: <#E6E6FA>{1_player}' + - '[<#87CEFA>🎣] Time Left: <#E6E6FA>{minute}m{second}s | Your Score: <#E6E6FA>{score} | No.1 Score: <#E6E6FA>{1_score}' + - '[<#87CEFA>🎣] Time Left: <#E6E6FA>{minute}m{second}s | Winning condition: <#E6E6FA>{goal}' + refresh-rate: 20 + switch-interval: 200 + only-show-to-participants: true + + actionbar: + enable: false + text: + - 'Time Left: <#E6E6FA>{time}s | Your Rank: <#E6E6FA>{rank} | No.1 Player: <#E6E6FA>{1_player}' + - 'Time Left: <#E6E6FA>{minute}m{second}s | Your Score: <#E6E6FA>{score} | No.1 Score: <#E6E6FA>{1_score}' + - 'Time Left: <#E6E6FA>{minute}m{second}s | Winning condition: <#E6E6FA>{goal}' + refresh-rate: 5 + switch-interval: 200 + only-show-to-participants: true + + start-actions: + broadcast: + type: broadcast + value: + - '<#D4F2E7>◤─────────────────────────◥' + - '' + - ' [<#87CEFA>🎣] Fishing Competition' + - '' + - ' <#E1FFFF>Objectives:' + - ' <#B0C4DE>Catch as many fish as possible' + - ' <#B0C4DE>Start fishing to participate!' + - '' + - '<#D4F2E7>◣─────────────────────────◢' + end-actions: + broadcast: + type: broadcast + value: + - '<#D4F2E7>◤─────────────────────────◥' + - '' + - ' [<#87CEFA>🎣] Fishing Competition' + - '' + - ' <#E1FFFF>Results:' + - ' No.①: {1_player} - {1_score}' + - ' No.②: {2_player} - {2_score}' + - ' No.③: {3_player} - {3_score}' + - '' + - '<#D4F2E7>◣─────────────────────────◢' + participate-actions: + message: + type: message + value: + - 'You have joined the competition. Good luck!' + + rewards: + 1: + command_action: + type: command + value: + - 'money give {player} 200' + messages_action: + type: message + value: + - '<#FF4500>[1st] Congratulations! You got the first prize!' + 2: + command_action: + type: command + value: + - 'money give {player} 100' + messages_action: + type: message + value: + - '<#FF4500>[2nd] Just miss the opportunity, try next time!' + 3: + command_action: + type: command + value: + - 'money give {player} 100' + messages_action: + type: message + value: + - '<#FF4500>[3rd] Just miss the opportunity, try next time!' + participation: + command_action: + type: command + value: + - 'money give {player} 10' + messages_action: + type: message + value: + - '<#FF4500>Thanks for participation!' \ No newline at end of file diff --git a/plugin/src/main/resources/contents/enchants/default.yml b/plugin/src/main/resources/contents/enchants/default.yml new file mode 100644 index 00000000..e69de29b diff --git a/src/main/resources/contents/loots/default.yml b/plugin/src/main/resources/contents/loots/default.yml similarity index 75% rename from src/main/resources/contents/loots/default.yml rename to plugin/src/main/resources/contents/loots/default.yml index f02cff5b..06af7e95 100644 --- a/src/main/resources/contents/loots/default.yml +++ b/plugin/src/main/resources/contents/loots/default.yml @@ -1,49 +1,23 @@ -# https://mo-mi.gitbook.io/xiaomomi-plugins/plugin-wiki/customfishing/item-library -vanilla: - disable-stats: false - disable-bar-mechanic: true rubbish: - material: cod - show-in-fishfinder: false - disable-stats: true - disable-bar-mechanic: true + material: paper + nick: Rubbish display: - name: Garbage + name: Rubbish lore: - - Maybe we need to protect the environment... - weight: 130 + - We need to protect the environment... custom-model-data: 50000 + show-in-fishfinder: false + disable-stat: true + disable-game: true + instant-game: false + prevent-grabbing: false action: success: - action_mending: + mending: type: mending value: 3 chance: 1.0 -obsidian: - nick: <#4B0082>Obsidian - material: obsidian - show-in-fishfinder: false - in-lava: true - disable-stats: true - action: - success: - action_mending: - type: mending - value: 15 - chance: 1.0 -wither_skeleton_skull: - nick: Wither Skeleton Skull - material: wither_skeleton_skull - show-in-fishfinder: false - in-lava: true - disable-stats: true - weight: 1 - action: - success: - action_mending: - type: mending - value: 80 - chance: 1.0 +#################################### tuna_fish: material: cod nick: Tuna Fish @@ -52,7 +26,6 @@ tuna_fish: lore: - Tuna is a kind of healthy food. - 'size: {size}cm' - weight: 50 custom-model-data: 50001 action: success: @@ -64,16 +37,6 @@ tuna_fish: price: base: 30 bonus: 0.6 - requirements: - biome: - - minecraft:ocean - - minecraft:cold_ocean - - minecraft:deep_cold_ocean - - minecraft:deep_frozen_ocean - - minecraft:deep_lukewarm_ocean - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean tuna_fish_silver_star: show-in-fishfinder: false material: cod @@ -83,8 +46,6 @@ tuna_fish_silver_star: lore: - Tuna is a kind of healthy food. - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50002 action: success: @@ -96,16 +57,6 @@ tuna_fish_silver_star: price: base: 50 bonus: 0.6 - requirements: - biome: - - minecraft:ocean - - minecraft:cold_ocean - - minecraft:deep_cold_ocean - - minecraft:deep_frozen_ocean - - minecraft:deep_lukewarm_ocean - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean tuna_fish_golden_star: show-in-fishfinder: false material: cod @@ -115,8 +66,6 @@ tuna_fish_golden_star: lore: - Tuna is a kind of healthy food. - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50003 action: success: @@ -128,16 +77,7 @@ tuna_fish_golden_star: price: base: 80 bonus: 0.7 - requirements: - biome: - - minecraft:ocean - - minecraft:cold_ocean - - minecraft:deep_cold_ocean - - minecraft:deep_frozen_ocean - - minecraft:deep_lukewarm_ocean - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean +#################################### pike_fish: material: cod nick: Pike Fish @@ -149,7 +89,6 @@ pike_fish: - survive in seawater, brackish fresh - water and inland freshwater lakes - 'size: {size}cm' - weight: 70 custom-model-data: 50004 action: success: @@ -161,14 +100,6 @@ pike_fish: price: base: 30 bonus: 1.5 - requirements: - biome: - - minecraft:ocean - - minecraft:river - - minecraft:frozen_river - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean pike_fish_silver_star: show-in-fishfinder: false material: cod @@ -181,8 +112,7 @@ pike_fish_silver_star: - survive in seawater, brackish fresh - water and inland freshwater lakes - 'size: {size}cm' - weight: 30 - group: silver + custom-model-data: 50005 action: success: action_mending: @@ -193,15 +123,6 @@ pike_fish_silver_star: price: base: 40 bonus: 1.5 - custom-model-data: 50005 - requirements: - biome: - - minecraft:ocean - - minecraft:river - - minecraft:frozen_river - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean pike_fish_golden_star: show-in-fishfinder: false material: cod @@ -214,8 +135,7 @@ pike_fish_golden_star: - survive in seawater, brackish fresh - water and inland freshwater lakes - 'size: {size}cm' - weight: 10 - group: gold + custom-model-data: 50006 action: success: action_mending: @@ -226,15 +146,7 @@ pike_fish_golden_star: price: base: 50 bonus: 1.5 - custom-model-data: 50006 - requirements: - biome: - - minecraft:ocean - - minecraft:river - - minecraft:frozen_river - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean +#################################### gold_fish: material: cod display: @@ -243,7 +155,6 @@ gold_fish: - Goldfish is one of most famous ornamental - fishes in the world. It originated in China - and has a history of more than 1700 years - weight: 50 price: base: 70 custom-model-data: 50007 @@ -263,10 +174,8 @@ gold_fish_silver_star: - Goldfish is one of most famous ornamental - fishes in the world. It originated in China - and has a history of more than 1700 years - weight: 20 price: base: 80 - group: silver custom-model-data: 50008 action: success: @@ -284,10 +193,8 @@ gold_fish_golden_star: - Goldfish is one of most famous ornamental - fishes in the world. It originated in China - and has a history of more than 1700 years - weight: 10 price: base: 100 - group: gold custom-model-data: 50009 action: success: @@ -295,6 +202,7 @@ gold_fish_golden_star: type: mending value: 9 chance: 1.0 +#################################### perch_fish: material: cod display: @@ -303,7 +211,6 @@ perch_fish: - Living in various habitats and - foraging at dusk and early morning - 'size: {size}cm' - weight: 100 custom-model-data: 50010 action: success: @@ -315,10 +222,6 @@ perch_fish: price: base: 10 bonus: 3 - requirements: - time: - - 0~3000 - - 17000~19000 perch_fish_silver_star: show-in-fishfinder: false material: cod @@ -329,8 +232,6 @@ perch_fish_silver_star: - Living in various habitats and - foraging at dusk and early morning - 'size: {size}cm' - weight: 30 - group: silver custom-model-data: 50011 action: success: @@ -342,10 +243,6 @@ perch_fish_silver_star: price: base: 10 bonus: 3 - requirements: - time: - - 0~3000 - - 17000~19000 perch_fish_golden_star: show-in-fishfinder: false material: cod @@ -356,8 +253,6 @@ perch_fish_golden_star: - Living in various habitats and - foraging at dusk and early morning - 'size: {size}cm' - weight: 15 - group: gold custom-model-data: 50012 action: success: @@ -369,10 +264,7 @@ perch_fish_golden_star: price: base: 10 bonus: 3 - requirements: - time: - - 0~3000 - - 17000~19000 +#################################### mullet_fish: material: cod nick: Mullet Fish @@ -382,7 +274,6 @@ mullet_fish: - Used in traditional Chinese medicine - to treat spleen and stomach weakness - 'size: {size}cm' - weight: 50 custom-model-data: 50013 action: success: @@ -404,8 +295,6 @@ mullet_fish_silver_star: - Used in traditional Chinese medicine - to treat spleen and stomach weakness - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50014 action: success: @@ -427,8 +316,6 @@ mullet_fish_golden_star: - Used in traditional Chinese medicine - to treat spleen and stomach weakness - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50015 action: success: @@ -440,6 +327,7 @@ mullet_fish_golden_star: price: base: 50 bonus: 1.5 +#################################### sardine_fish: material: cod nick: Sardine Fish @@ -449,7 +337,6 @@ sardine_fish: - Sardine fish is rich in DHA which improves memory - Therefore, sardine are also called "smart food" - 'size: {size}cm' - weight: 50 custom-model-data: 50016 action: success: @@ -470,8 +357,6 @@ sardine_fish_silver_star: - Sardine fish is rich in DHA which improves memory - Therefore, sardine are also called "smart food" - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50017 action: success: @@ -492,8 +377,6 @@ sardine_fish_golden_star: - Sardine fish is rich in DHA which improves memory - Therefore, sardine are also called "smart food" - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50018 action: success: @@ -505,6 +388,7 @@ sardine_fish_golden_star: price: base: 15 bonus: 3.4 +#################################### carp_fish: material: cod nick: Carp Fish @@ -513,7 +397,6 @@ carp_fish: lore: - One of the most common edible fish - 'size: {size}cm' - weight: 100 custom-model-data: 50019 action: success: @@ -525,17 +408,6 @@ carp_fish: price: base: 10 bonus: 2 - requirements: - biome: - - minecraft:river - - minecraft:plains - - minecraft:forest - - minecraft:swamp - - minecraft:dark_forest - - minecraft:flower_forest - - minecraft:birch_forest - - minecraft:old_growth_birch_forest - - minecraft:sunflower_plains carp_fish_silver_star: show-in-fishfinder: false material: cod @@ -544,8 +416,6 @@ carp_fish_silver_star: lore: - One of the most common edible fish - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50020 action: success: @@ -557,17 +427,6 @@ carp_fish_silver_star: price: base: 11 bonus: 2.1 - requirements: - biome: - - minecraft:river - - minecraft:plains - - minecraft:forest - - minecraft:swamp - - minecraft:dark_forest - - minecraft:flower_forest - - minecraft:birch_forest - - minecraft:old_growth_birch_forest - - minecraft:sunflower_plains carp_fish_golden_star: show-in-fishfinder: false material: cod @@ -576,8 +435,6 @@ carp_fish_golden_star: lore: - One of the most common edible fish - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50021 action: success: @@ -589,17 +446,7 @@ carp_fish_golden_star: price: base: 12 bonus: 2.2 - requirements: - biome: - - minecraft:river - - minecraft:plains - - minecraft:forest - - minecraft:swamp - - minecraft:dark_forest - - minecraft:flower_forest - - minecraft:birch_forest - - minecraft:old_growth_birch_forest - - minecraft:sunflower_plains +#################################### cat_fish: material: cod display: @@ -608,7 +455,6 @@ cat_fish: - Catfish is a fierce carnivorous fish with - sharp jaw teeth, short intestine and stomach - 'size: {size}cm' - weight: 50 custom-model-data: 50022 action: success: @@ -620,17 +466,6 @@ cat_fish: price: base: 27 bonus: 1.8 - requirements: - biome: - - minecraft:river - - minecraft:plains - - minecraft:forest - - minecraft:swamp - - minecraft:dark_forest - - minecraft:flower_forest - - minecraft:birch_forest - - minecraft:old_growth_birch_forest - - minecraft:sunflower_plains cat_fish_silver_star: show-in-fishfinder: false material: cod @@ -640,8 +475,6 @@ cat_fish_silver_star: - Catfish is a fierce carnivorous fish with - sharp jaw teeth, short intestine and stomach - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50023 action: success: @@ -653,17 +486,6 @@ cat_fish_silver_star: price: base: 14 bonus: 2.2 - requirements: - biome: - - minecraft:river - - minecraft:plains - - minecraft:forest - - minecraft:swamp - - minecraft:dark_forest - - minecraft:flower_forest - - minecraft:birch_forest - - minecraft:old_growth_birch_forest - - minecraft:sunflower_plains cat_fish_golden_star: show-in-fishfinder: false material: cod @@ -673,8 +495,6 @@ cat_fish_golden_star: - Catfish is a fierce carnivorous fish with - sharp jaw teeth, short intestine and stomach - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50024 action: success: @@ -686,17 +506,7 @@ cat_fish_golden_star: price: base: 16 bonus: 2.2 - requirements: - biome: - - minecraft:river - - minecraft:plains - - minecraft:forest - - minecraft:swamp - - minecraft:dark_forest - - minecraft:flower_forest - - minecraft:birch_forest - - minecraft:old_growth_birch_forest - - minecraft:sunflower_plains +#################################### octopus: material: cod nick: Octopus @@ -706,7 +516,6 @@ octopus: - Octopus is crazy about all kinds of utensils - People often use pots to catch octopus - 'size: {size}cm' - weight: 50 custom-model-data: 50025 action: success: @@ -718,14 +527,6 @@ octopus: price: base: 50 bonus: 2.2 - requirements: - biome: - - minecraft:ocean - - minecraft:deep_lukewarm_ocean - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean - - minecraft:jungle octopus_silver_star: show-in-fishfinder: false material: cod @@ -735,8 +536,6 @@ octopus_silver_star: - Octopus is crazy about all kinds of utensils - People often use pots to catch octopus - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50026 action: success: @@ -748,16 +547,6 @@ octopus_silver_star: price: base: 50 bonus: 2.2 - requirements: - biome: - - minecraft:ocean - - minecraft:cold_ocean - - minecraft:deep_cold_ocean - - minecraft:deep_frozen_ocean - - minecraft:deep_lukewarm_ocean - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean octopus_golden_star: show-in-fishfinder: false material: cod @@ -767,8 +556,6 @@ octopus_golden_star: - Octopus is crazy about all kinds of utensils - People often use pots to catch octopus - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50027 action: success: @@ -780,16 +567,7 @@ octopus_golden_star: price: base: 10 bonus: 1.5 - requirements: - biome: - - minecraft:ocean - - minecraft:cold_ocean - - minecraft:deep_cold_ocean - - minecraft:deep_frozen_ocean - - minecraft:deep_lukewarm_ocean - - minecraft:frozen_ocean - - minecraft:lukewarm_ocean - - minecraft:warm_ocean +#################################### sunfish: material: cod nick: <#F5DEB3>Sunfish @@ -798,7 +576,6 @@ sunfish: lore: - It only has one huge head - 'size: {size}cm' - weight: 50 custom-model-data: 50028 action: success: @@ -818,8 +595,6 @@ sunfish_silver_star: lore: - It only has one huge head - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50029 action: success: @@ -839,8 +614,6 @@ sunfish_golden_star: lore: - It only has one huge head - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50030 action: success: @@ -852,6 +625,7 @@ sunfish_golden_star: price: base: 26 bonus: 1.5 +#################################### red_snapper_fish: material: cod display: @@ -860,7 +634,6 @@ red_snapper_fish: - They usually have a large family of ten or twenty - with a male as the "head of the family" - 'size: {size}cm' - weight: 100 custom-model-data: 50031 action: success: @@ -882,8 +655,6 @@ red_snapper_fish_silver_star: - They usually have a large family of ten or twenty - with a male as the "head of the family" - 'size: {size}cm' - weight: 40 - group: silver custom-model-data: 50032 action: success: @@ -905,8 +676,6 @@ red_snapper_fish_golden_star: - They usually have a large family of ten or twenty - with a male as the "head of the family" - 'size: {size}cm' - weight: 20 - group: gold custom-model-data: 50033 action: success: @@ -918,6 +687,7 @@ red_snapper_fish_golden_star: price: base: 10 bonus: 2.3 +#################################### salmon_void_fish: material: cod in-lava: true @@ -926,7 +696,6 @@ salmon_void_fish: name: Void Salmon lore: - A fish from the hell - weight: 50 custom-model-data: 50034 action: success: @@ -936,9 +705,6 @@ salmon_void_fish: chance: 1.0 price: base: 20 - requirements: - world: - - world_nether salmon_void_fish_silver_star: show-in-fishfinder: false in-lava: true @@ -947,8 +713,6 @@ salmon_void_fish_silver_star: name: Void Salmon<#F5F5F5>(Silver Star) lore: - A fish from the hell - weight: 20 - group: silver custom-model-data: 50035 action: success: @@ -958,9 +722,6 @@ salmon_void_fish_silver_star: chance: 1.0 price: base: 50 - requirements: - world: - - world_nether salmon_void_fish_golden_star: show-in-fishfinder: false in-lava: true @@ -969,7 +730,6 @@ salmon_void_fish_golden_star: name: Void Salmon <#FFD700>(Golden Star) lore: - A fish from the hell - weight: 10 group: gold custom-model-data: 50036 action: @@ -980,9 +740,7 @@ salmon_void_fish_golden_star: chance: 1.0 price: base: 100 - requirements: - world: - - world_nether +#################################### woodskip_fish: material: cod nick: <#CD5C5C>Woodskip Fish @@ -992,7 +750,6 @@ woodskip_fish: - A very sensitive fish that can only - live in pools deep in the forest - 'size: {size}cm' - weight: 50 custom-model-data: 50037 action: success: @@ -1004,12 +761,6 @@ woodskip_fish: price: base: 10 bonus: 2.3 - requirements: - biome: - - minecraft:dark_forest - - minecraft:forest - - minecraft:flower_forest - - minecraft:birch_forest woodskip_fish_silver_star: show-in-fishfinder: false material: cod @@ -1019,8 +770,6 @@ woodskip_fish_silver_star: - A very sensitive fish that can only - live in pools deep in the forest - 'size: {size}cm' - weight: 20 - group: silver custom-model-data: 50038 action: success: @@ -1032,12 +781,6 @@ woodskip_fish_silver_star: price: base: 17 bonus: 2.5 - requirements: - biome: - - minecraft:dark_forest - - minecraft:forest - - minecraft:flower_forest - - minecraft:birch_forest woodskip_fish_golden_star: show-in-fishfinder: false material: cod @@ -1047,8 +790,6 @@ woodskip_fish_golden_star: - A very sensitive fish that can only - live in pools deep in the forest - 'size: {size}cm' - weight: 10 - group: gold custom-model-data: 50039 action: success: @@ -1060,12 +801,7 @@ woodskip_fish_golden_star: price: base: 25 bonus: 2.8 - requirements: - biome: - - minecraft:dark_forest - - minecraft:forest - - minecraft:flower_forest - - minecraft:birch_forest +#################################### sturgeon_fish: material: cod nick: <#48D1CC>Sturgeon Fish @@ -1075,7 +811,6 @@ sturgeon_fish: - An ancient bottom-feeder with a dwindling - population. Females can live up to 150 years - 'size: {size}cm' - weight: 5 custom-model-data: 50040 action: success: @@ -1087,9 +822,6 @@ sturgeon_fish: price: base: 200 bonus: 10 - requirements: - ypos: - - -64~0 sturgeon_fish_silver_star: show-in-fishfinder: false material: cod @@ -1099,8 +831,6 @@ sturgeon_fish_silver_star: - An ancient bottom-feeder with a dwindling - population. Females can live up to 150 years - 'size: {size}cm' - weight: 2 - group: silver custom-model-data: 50041 action: success: @@ -1112,9 +842,6 @@ sturgeon_fish_silver_star: price: base: 250 bonus: 10 - requirements: - ypos: - - -64~0 sturgeon_fish_golden_star: show-in-fishfinder: false material: cod @@ -1124,8 +851,6 @@ sturgeon_fish_golden_star: - An ancient bottom-feeder with a dwindling - population. Females can live up to 150 years - 'size: {size}cm' - weight: 1 - group: gold custom-model-data: 50042 action: success: @@ -1136,7 +861,4 @@ sturgeon_fish_golden_star: size: 15~30 price: base: 300 - bonus: 10 - requirements: - ypos: - - -64~0 + bonus: 10 \ No newline at end of file diff --git a/src/main/resources/contents/bars/default.yml b/plugin/src/main/resources/contents/minigames/default.yml similarity index 84% rename from src/main/resources/contents/bars/default.yml rename to plugin/src/main/resources/contents/minigames/default.yml index 9434b3fb..a49a9b29 100644 --- a/src/main/resources/contents/bars/default.yml +++ b/plugin/src/main/resources/contents/minigames/default.yml @@ -1,8 +1,10 @@ -############### -# Game Type 1 # -############### +###################################### +# Accurate Click # +# You need to concentrate and reel # +# in at the most critical time # +###################################### rainbow_1: - game-type: 1 + game-type: accurate_click title: '<#B22222>RED!' subtitle: font: 'customfishing:default' @@ -21,7 +23,7 @@ rainbow_1: 6: 0 7: 0 rainbow_2: - game-type: 1 + game-type: accurate_click title: '<#FFA500>ORANGE!' subtitle: font: 'customfishing:default' @@ -40,7 +42,7 @@ rainbow_2: 6: 0 7: 0 rainbow_3: - game-type: 1 + game-type: accurate_click title: '<#FFFF00>YELLOW!' subtitle: font: 'customfishing:default' @@ -59,7 +61,7 @@ rainbow_3: 6: 0 7: 0 rainbow_4: - game-type: 1 + game-type: accurate_click title: 'GREEN!' subtitle: font: 'customfishing:default' @@ -78,7 +80,7 @@ rainbow_4: 6: 0 7: 0 rainbow_5: - game-type: 1 + game-type: accurate_click title: '<#00FFFF>AQUA!' subtitle: font: 'customfishing:default' @@ -97,7 +99,7 @@ rainbow_5: 6: 0 7: 0 rainbow_6: - game-type: 1 + game-type: accurate_click title: '<#1E90FF>BLUE!' subtitle: font: 'customfishing:default' @@ -116,7 +118,7 @@ rainbow_6: 6: 1 7: 0 rainbow_7: - game-type: 1 + game-type: accurate_click title: '<#9400D3>PURPLE!' subtitle: font: 'customfishing:default' @@ -134,8 +136,8 @@ rainbow_7: 5: 0 6: 0 7: 1 -bar_1: - game-type: 1 +accurate_click_bar_1: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -160,8 +162,8 @@ bar_1: 9: 0 10: 0 11: 0 -bar_2: - game-type: 1 +accurate_click_bar_2: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -186,8 +188,8 @@ bar_2: 9: 0 10: 0 11: 0 -bar_3: - game-type: 1 +accurate_click_bar_3: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -212,8 +214,8 @@ bar_3: 9: 0.6 10: 0.2 11: 0 -bar_4: - game-type: 1 +accurate_click_bar_4: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -249,8 +251,8 @@ bar_4: 20: 0.1 21: 0 22: 0 -bar_5: - game-type: 1 +accurate_click_bar_5: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -286,8 +288,8 @@ bar_5: 20: 0.1 21: 0 22: 0 -bar_6: - game-type: 1 +accurate_click_bar_6: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -323,8 +325,8 @@ bar_6: 20: 0.1 21: 0.1 22: 0.1 -bar_7: - game-type: 1 +accurate_click_bar_7: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -382,8 +384,8 @@ bar_7: 42: 0.3 43: 0.3 44: 0.3 -bar_8: - game-type: 1 +accurate_click_bar_8: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -441,8 +443,8 @@ bar_8: 42: 0 43: 0 44: 0 -bar_9: - game-type: 1 +accurate_click_bar_9: + game-type: accurate_click title: - 'So close, stay cool!' - 'The fish is hooked, focus on it!' @@ -501,11 +503,13 @@ bar_9: 43: 0 44: 1 -############### -# Game Type 2 # -############### -bar_10: - game-type: 2 +###################################### +# Hold # +# You need to control the fish in # +# a certain area for some time # +###################################### +hold_game: + game-type: hold title: '{progress}' # Tip would show on the title to guide the player how to play tip: 'Press to start' @@ -540,11 +544,14 @@ bar_10: - '뀈' - '뀉' -############### -# Game Type 3 # -############### -bar_11: - game-type: 3 +########################################################## +# Tension # +# The fish will struggle. During the # +# struggling, the tension would increase sharply. # +# Fishing will fail if the tension reaches its peak # +########################################################## +tension_game: + game-type: tension title: '{strain}' # Tip would show on the title to guide the player how to play tip: 'Press to start' @@ -576,4 +583,10 @@ bar_11: - '뀖' - '뀗' - '뀘' - - '뀙' \ No newline at end of file + - '뀙' + +###################################### +# Burst # +# When the fish is hooked, you need # +# to click quickly in limited time # +###################################### diff --git a/plugin/src/main/resources/contents/mobs/default.yml b/plugin/src/main/resources/contents/mobs/default.yml new file mode 100644 index 00000000..fc8c0a2a --- /dev/null +++ b/plugin/src/main/resources/contents/mobs/default.yml @@ -0,0 +1,17 @@ +drowned: + show-in-fishfinder: false + mob: Drowned + nick: drowned + vector: + horizontal: 1.1 + vertical: 1.2 + +skeletalknight: + show-in-fishfinder: false + mob: MythicMobs:SkeletalKnight + nick: Skeletal Knight + vector: + horizontal: 1.1 + vertical: 1.2 + properties: + level: 0 \ No newline at end of file diff --git a/src/main/resources/contents/rods/default.yml b/plugin/src/main/resources/contents/rods/default.yml similarity index 88% rename from src/main/resources/contents/rods/default.yml rename to plugin/src/main/resources/contents/rods/default.yml index ddd924aa..83b1e797 100644 --- a/src/main/resources/contents/rods/default.yml +++ b/plugin/src/main/resources/contents/rods/default.yml @@ -1,4 +1,5 @@ wooden_rod: + material: fishing_rod display: name: 'Ordinary wooden fishing rod' lore: @@ -8,6 +9,7 @@ wooden_rod: difficulty: -1 nature_fishing_cane: + material: fishing_rod display: name: 'Nature Fishing Cane' lore: @@ -15,10 +17,12 @@ nature_fishing_cane: - 'But also increase the difficulty' custom-model-data: 50001 effect: - time: 0.9 + hook-time: 0.9 difficulty: 1 + game-time: 3 silver_fishing_rod: + material: fishing_rod display: name: 'Silver Fishing Rod' lore: @@ -30,6 +34,7 @@ silver_fishing_rod: gold: -10 golden_fishing_rod: + material: fishing_rod display: name: 'Golden Fishing Rod' lore: @@ -41,6 +46,7 @@ golden_fishing_rod: gold: 20 star_fishing_rod: + material: fishing_rod effect: weight-add: silver: 20 @@ -50,10 +56,8 @@ star_fishing_rod: requirements: requirement_1: type: permission - message: 'You don''t have permission to use this rod!' value: star_fishing_rod.use requirement_2: type: world - message: 'You can only use this rod in Nether.' value: - world_nether \ No newline at end of file diff --git a/src/main/resources/contents/totems/default.yml b/plugin/src/main/resources/contents/totems/default.yml similarity index 100% rename from src/main/resources/contents/totems/default.yml rename to plugin/src/main/resources/contents/totems/default.yml diff --git a/src/main/resources/contents/totem_blocks/default.yml b/plugin/src/main/resources/contents/totems/totem_blocks/default.yml similarity index 100% rename from src/main/resources/contents/totem_blocks/default.yml rename to plugin/src/main/resources/contents/totems/totem_blocks/default.yml diff --git a/src/main/resources/contents/utils/fisherman_talismans.yml b/plugin/src/main/resources/contents/utils/default.yml similarity index 62% rename from src/main/resources/contents/utils/fisherman_talismans.yml rename to plugin/src/main/resources/contents/utils/default.yml index 79319009..e2dae3f9 100644 --- a/src/main/resources/contents/utils/fisherman_talismans.yml +++ b/plugin/src/main/resources/contents/utils/default.yml @@ -1,3 +1,16 @@ +fishfinder: + material: PAPER + display: + name: 'Fish Finder' + lore: + - 'Right click to see what fish can be caught in this place!' + custom-model-data: 50000 +water_effect: + material: PAPER + custom-model-data: 49998 +lava_effect: + material: PAPER + custom-model-data: 49999 fisherman_talismans: material: player_head display: diff --git a/plugin/src/main/resources/database.yml b/plugin/src/main/resources/database.yml new file mode 100644 index 00000000..7bc7a071 --- /dev/null +++ b/plugin/src/main/resources/database.yml @@ -0,0 +1,80 @@ +# file: +# JSON +# YAML +# +# local database +# SQLite +# H2 (preferred over SQLite) +# +# remote database +# MySQL +# MariaDB (preferred over MySQL) +# MongoDB +# +data-storage-method: H2 + +# Server unique id, make sure that all the servers are using different ids +server-unique-id: "plz_edit_this" + +SQLite: + file: 'sqlite' + table-prefix: customfishing + +H2: + file: 'h2' + table-prefix: customfishing + +MySQL: + host: 'localhost' + port: '3306' + user: 'root' + password: 'password' + database: 'minecraft' + connection-parameters: '?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8' + Pool-Settings: + max-pool-size: 10 + min-idle: 10 + max-lifetime: 180000 + keep-alive-time: 60000 + time-out: 20000 + table-prefix: customfishing + +MariaDB: + host: 'localhost' + port: '3306' + user: 'root' + password: 'password' + database: 'minecraft' + connection-parameters: '?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8' + Pool-Settings: + max-pool-size: 10 + min-idle: 10 + max-lifetime: 180000 + keep-alive-time: 60000 + time-out: 20000 + table-prefix: customfishing + +MongoDB: + host: 'localhost' + port: '27017' + #user: 'root' + #password: 'password' + database: 'minecraft' + # If this section is not empty, it would override the configs above + # https://www.mongodb.com/docs/manual/reference/connection-string/ + connection-uri: '' + collection-prefix: customfishing + +# Redis is optional if you are using remote database +# If you do not know how to use Redis, please do not enable it +Redis: + enable: false + host: localhost + #password: 123456 + port: 6379 + use-ssl: false + MaxTotal: 10 + MaxIdle: 10 + MinIdle: 1 + MaxWaitMillis: 30000 + MinEvictableIdleTimeMillis: 1800000 \ No newline at end of file diff --git a/plugin/src/main/resources/game-groups.yml b/plugin/src/main/resources/game-groups.yml new file mode 100644 index 00000000..678a523b --- /dev/null +++ b/plugin/src/main/resources/game-groups.yml @@ -0,0 +1,28 @@ +mixed_accurate_click_group: + groups: + - accurate_click_group:6 + - rainbow_group:1 +accurate_click_group: + difficulty: 10~60 + time: 10~15 + games: + - accurate_click_bar_1:3 + - accurate_click_bar_2:3 + - accurate_click_bar_3:3 + - accurate_click_bar_4:3 + - accurate_click_bar_5:3 + - accurate_click_bar_6:3 + - accurate_click_bar_7:3 + - accurate_click_bar_8:3 + - accurate_click_bar_9:3 +rainbow_group: + difficulty: 10~60 + time: 10~15 + games: + - rainbow_1:1 + - rainbow_2:1 + - rainbow_3:1 + - rainbow_4:1 + - rainbow_5:1 + - rainbow_6:1 + - rainbow_7:1 \ No newline at end of file diff --git a/plugin/src/main/resources/loot-conditions.yml b/plugin/src/main/resources/loot-conditions.yml new file mode 100644 index 00000000..a84eed7a --- /dev/null +++ b/plugin/src/main/resources/loot-conditions.yml @@ -0,0 +1,83 @@ +# global 条件组 +global-group: + list: [] + conditions: {} + sub-groups: + loots_in_water: + conditions: + in-lava: false + list: + - rubbish:+15 + sub-groups: + ocean_fish: + conditions: + biome: + - minecraft:ocean + - minecraft:deep_ocean + - minecraft:cold_ocean + - minecraft:deep_cold_ocean + - minecraft:frozen_ocean + - minecraft:deep_frozen_ocean + - minecraft:lukewarm_ocean + - minecraft:deep_lukewarm_ocean + - minecraft:warm_ocean + list: + - rubbish:-10 + - tuna_fish:+15 + - tuna_fish_silver_star:+3 + - tuna_fish_golden_star:+1 + - pike_fish:+15 + - pike_fish_silver_star:+3 + - pike_fish_golden_star:+1 + - sardine_fish:+15 + - sardine_fish_silver_star:+3 + - sardine_fish_golden_star:+1 + sub-groups: + warm_ocean_fish: + conditions: + biome: + - minecraft:lukewarm_ocean + - minecraft:deep_lukewarm_ocean + - minecraft:warm_ocean + list: + - blue_jellyfish:+15 + - blue_jellyfish_silver_star:+3 + - blue_jellyfish_golden_star:+1 + - pink_jellyfish:+15 + - pink_jellyfish_silver_star:+3 + - pink_jellyfish_golden_star:+1 + river_fish: + conditions: + '!biome': + - minecraft:ocean + - minecraft:river + - minecraft:frozen_river + - minecraft:frozen_ocean + - minecraft:lukewarm_ocean + - minecraft:warm_ocean + list: + - rubbish:+5 + - gold_fish:+15 + - gold_fish_silver_star:+3 + - gold_fish_golden_star:+1 + - perch_fish:+15 + - perch_fish_silver_star:+3 + - perch_fish_golden_star:+1 + - mullet_fish:+15 + - mullet_fish_silver_star:+3 + - mullet_fish_golden_star:+1 + - carp_fish:+25 + - carp_fish_silver_star:+5 + - carp_fish_golden_star:+2 + sub-groups: + swamp_fish: + list: [] + conditions: + biome: + - minecraft:swamp + - minecraft:mangrove_swamp + loots_in_lava: + conditions: + in-lava: true + list: + - obsidian:+10 \ No newline at end of file diff --git a/plugin/src/main/resources/market.yml b/plugin/src/main/resources/market.yml new file mode 100644 index 00000000..091d1540 --- /dev/null +++ b/plugin/src/main/resources/market.yml @@ -0,0 +1,54 @@ +# Container title +title: 'Fish Market' + +# Market menu layout +layout: + - 'AAAAAAAAA' + - 'AIIIIIIIA' + - 'AIIIIIIIA' + - 'AIIIIIIIA' + - 'AAAABAAAA' + +# Price formula (For customfishing loots) +price-formula: '{base} + {bonus} * {size}' + +# Item price (For vanilla items & other plugin items) +item-price: + # Vanilla Items + COD: 10 + PUFFERFISH: 10 + SALMON: 10 + TROPICAL_FISH: 10 + # PAPER (CustomModelData: 999) + PAPER:999: 5 + +# Functional icons +functional-icons: + sell-icon: + symbol: 'B' + material: IRON_BLOCK + display: + name: '<#00CED1>Sell the fish' + lore: + - 'You will gain {money}$' + action: + message: + type: message + text: 'You earned {money}$ from selling the fish! You can still gain {remains}$ from selling fish today' + chance: 1.0 + deny-icon: + symbol: 'B' + material: REDSTONE_BLOCK + display: + name: 'Denied' + lore: + - 'Nothing to sell!' + item-slot: + symbol: 'I' + +decorative-icons: + glass-pane: + symbol: 'A' + material: BLACK_STAINED_GLASS_PANE + display: + name: ' ' \ No newline at end of file diff --git a/src/main/resources/messages/messages_chinese.yml b/plugin/src/main/resources/messages/chinese.yml similarity index 100% rename from src/main/resources/messages/messages_chinese.yml rename to plugin/src/main/resources/messages/chinese.yml diff --git a/plugin/src/main/resources/messages/english.yml b/plugin/src/main/resources/messages/english.yml new file mode 100644 index 00000000..b656cfc3 --- /dev/null +++ b/plugin/src/main/resources/messages/english.yml @@ -0,0 +1,26 @@ +#MiniMessage Format +#https://docs.adventure.kyori.net/minimessage/format.html +config-version: '26' + +messages: + prefix: '[CustomFishing] ' + reload: 'Reloaded. Took {time}ms.' + item-not-exist: 'That item does not exist.' + escape: 'It has been too long since the fish is hooked. Oh my god, it escaped.' + give-item: 'Successfully given player {player} {amount}x {item}.' + get-item: 'Successfully got {amount}x {item}.' + possible-loots: 'Possible loots here: ' + split-char: ', ' + competition-not-exist: 'Competition {id} does not exist.' + no-competition-ongoing: 'There''s no competition ongoing.' + stop-competition: 'Successfully stopped the current competition.' + end-competition: 'Successfully ended the current competition.' + no-score: 'No Score' + no-player: 'No Player' + no-rank: 'No Rank' + goal-catch-amount: 'Amount of fish caught' + goal-max-size: 'Max size of the fish caught' + goal-total-size: 'Total size of the fish caught' + goal-total-score: 'Total score of the fish caught' + unsafe-modification: 'You can''t edit a player''s fishing bag when the player is playing on another server that connected to the database' + never-played: 'Player {player} has never played the server. You can''t edit a non existent player''s fishing bag.' \ No newline at end of file diff --git a/src/main/resources/messages/messages_spanish.yml b/plugin/src/main/resources/messages/spanish.yml similarity index 100% rename from src/main/resources/messages/messages_spanish.yml rename to plugin/src/main/resources/messages/spanish.yml diff --git a/src/main/resources/messages/messages_turkish.yml b/plugin/src/main/resources/messages/turkish.yml similarity index 100% rename from src/main/resources/messages/messages_turkish.yml rename to plugin/src/main/resources/messages/turkish.yml diff --git a/plugin/src/main/resources/plugin.yml b/plugin/src/main/resources/plugin.yml new file mode 100644 index 00000000..13968d76 --- /dev/null +++ b/plugin/src/main/resources/plugin.yml @@ -0,0 +1,39 @@ +name: CustomFishing +version: '${version}' +main: net.momirealms.customfishing.CustomFishingPluginImpl +api-version: 1.17 +authors: [ XiaoMoMi ] +folia-supported: true +depend: + - ProtocolLib +softdepend: + - Vault + - PlaceholderAPI + + - RealisticSeasons + + - ItemsAdder + - MythicMobs + - Oraxen + - eco + - MMOItems + + - mcMMO + - AureliumSkills + - CustomCrops + - MMOCore + - EcoSkills + + - BattlePass + - ClueScrolls + - BetonQuest + + - AdvancedEnchantments + - EcoEnchants + + - Jobs + - EcoJobs + +permissions: + fishingbag.user: + default: true \ No newline at end of file diff --git a/plugin/src/main/resources/schema/h2.sql b/plugin/src/main/resources/schema/h2.sql new file mode 100644 index 00000000..9eac1c22 --- /dev/null +++ b/plugin/src/main/resources/schema/h2.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS `{prefix}_data` +( + `uuid` char(36) NOT NULL UNIQUE, + `lock` INT NOT NULL, + `data` longblob NOT NULL, + PRIMARY KEY (`uuid`) +); \ No newline at end of file diff --git a/plugin/src/main/resources/schema/mariadb.sql b/plugin/src/main/resources/schema/mariadb.sql new file mode 100644 index 00000000..4fbd068e --- /dev/null +++ b/plugin/src/main/resources/schema/mariadb.sql @@ -0,0 +1,11 @@ +SET DEFAULT_STORAGE_ENGINE = INNODB; + +CREATE TABLE IF NOT EXISTS `{prefix}_data` +( + `uuid` char(36) NOT NULL UNIQUE, + `lock` INT NOT NULL, + `data` longblob NOT NULL, + PRIMARY KEY (`uuid`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; \ No newline at end of file diff --git a/plugin/src/main/resources/schema/mysql.sql b/plugin/src/main/resources/schema/mysql.sql new file mode 100644 index 00000000..531c6a17 --- /dev/null +++ b/plugin/src/main/resources/schema/mysql.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS `{prefix}_data` +( + `uuid` char(36) NOT NULL UNIQUE, + `lock` INT NOT NULL, + `data` longblob NOT NULL, + PRIMARY KEY (`uuid`) +); \ No newline at end of file diff --git a/plugin/src/main/resources/schema/sqlite.sql b/plugin/src/main/resources/schema/sqlite.sql new file mode 100644 index 00000000..9eac1c22 --- /dev/null +++ b/plugin/src/main/resources/schema/sqlite.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS `{prefix}_data` +( + `uuid` char(36) NOT NULL UNIQUE, + `lock` INT NOT NULL, + `data` longblob NOT NULL, + PRIMARY KEY (`uuid`) +); \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 0c50946b..00000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'CustomFishing' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..d2bc3642 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,3 @@ +rootProject.name = "CustomFishing" +include("api") +include("plugin") diff --git a/src/main/java/net/momirealms/customfishing/CustomFishing.java b/src/main/java/net/momirealms/customfishing/CustomFishing.java deleted file mode 100644 index 74319c6e..00000000 --- a/src/main/java/net/momirealms/customfishing/CustomFishing.java +++ /dev/null @@ -1,284 +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; - -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; -import net.momirealms.customfishing.commands.FishingBagCommand; -import net.momirealms.customfishing.commands.MainCommand; -import net.momirealms.customfishing.commands.SellFishCommand; -import net.momirealms.customfishing.helper.LibraryLoader; -import net.momirealms.customfishing.helper.Log; -import net.momirealms.customfishing.helper.VersionHelper; -import net.momirealms.customfishing.manager.*; -import net.momirealms.customfishing.object.Reflection; -import net.momirealms.customfishing.scheduler.Scheduler; -import net.momirealms.customfishing.util.AdventureUtils; -import org.apache.commons.io.FileUtils; -import org.bstats.bukkit.Metrics; -import org.bukkit.Bukkit; -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.TimeZone; - -public final class CustomFishing extends JavaPlugin { - - private static CustomFishing plugin; - private static BukkitAudiences adventure; - private static ProtocolManager protocolManager; - private IntegrationManager integrationManager; - private FishingManager fishingManager; - private CompetitionManager competitionManager; - private EffectManager effectManager; - private LootManager lootManager; - private BarMechanicManager barMechanicManager; - private BagDataManager bagDataManager; - private TotemManager totemManager; - private DataManager dataManager; - private SellManager sellManager; - private OffsetManager offsetManager; - private StatisticsManager statisticsManager; - private VersionHelper versionHelper; - private Scheduler scheduler; - - @Override - public void onLoad() { - plugin = this; - loadLibs(); - } - - @Override - public void onEnable() { - adventure = BukkitAudiences.create(this); - protocolManager = ProtocolLibrary.getProtocolManager(); - this.updateLegacyFormatContents(); - this.versionHelper = new VersionHelper(this); - this.fishingManager = new FishingManager(this); - this.dataManager = new DataManager(this); - this.statisticsManager = new StatisticsManager(this); - this.integrationManager = new IntegrationManager(this); - this.competitionManager = new CompetitionManager(this); - this.effectManager = new EffectManager(this); - this.lootManager = new LootManager(this); - this.barMechanicManager = new BarMechanicManager(this); - this.totemManager = new TotemManager(this); - this.sellManager = new SellManager(this); - this.bagDataManager = new BagDataManager(this); - this.offsetManager = new OffsetManager(this); - this.scheduler = new Scheduler(this); - this.reload(); - this.registerCommands(); - this.registerQuests(); - Reflection.load(); - AdventureUtils.consoleMessage("[CustomFishing] Plugin Enabled!"); - if (ConfigManager.bStats) new Metrics(this, 16648); - if (ConfigManager.updateChecker) this.versionHelper.checkUpdate(); - } - - @Override - public void onDisable() { - if (this.fishingManager != null) this.fishingManager.unload(); - if (this.integrationManager != null) this.integrationManager.unload(); - if (this.competitionManager != null) this.competitionManager.unload(); - if (this.effectManager != null) this.effectManager.unload(); - if (this.lootManager != null) this.lootManager.unload(); - if (this.barMechanicManager != null) this.barMechanicManager.unload(); - if (this.totemManager != null) this.totemManager.unload(); - if (this.bagDataManager != null) this.bagDataManager.disable(); - if (this.sellManager != null) this.sellManager.disable(); - if (this.statisticsManager != null) this.statisticsManager.disable(); - if (this.dataManager != null) this.dataManager.disable(); - if (this.scheduler != null) scheduler.disable(); - if (adventure != null) adventure.close(); - } - - private void registerCommands() { - MainCommand mainCommand = new MainCommand(); - PluginCommand cfCommand = Bukkit.getPluginCommand("customfishing"); - if (cfCommand != null) { - cfCommand.setExecutor(mainCommand); - cfCommand.setTabCompleter(mainCommand); - } - FishingBagCommand fishingBagCommand = new FishingBagCommand(); - PluginCommand fbCommand = Bukkit.getPluginCommand("fishingbag"); - if (fbCommand != null) { - fbCommand.setExecutor(fishingBagCommand); - fbCommand.setTabCompleter(fishingBagCommand); - } - SellFishCommand sellFishCommand = new SellFishCommand(); - PluginCommand sfCommand = Bukkit.getPluginCommand("sellfish"); - if (sfCommand != null) { - sfCommand.setExecutor(sellFishCommand); - sfCommand.setTabCompleter(sellFishCommand); - } - } - - private void loadLibs() { - TimeZone timeZone = TimeZone.getDefault(); - String libRepo = timeZone.getID().startsWith("Asia") ? "https://maven.aliyun.com/repository/public/" : "https://repo.maven.apache.org/maven2/"; - LibraryLoader.load("org.apache.commons","commons-pool2","2.11.1", libRepo); - LibraryLoader.load("redis.clients","jedis","4.4.2", libRepo); - LibraryLoader.load("dev.dejvokep","boosted-yaml","1.3.1", libRepo); - LibraryLoader.load("com.zaxxer","HikariCP","5.0.1", libRepo); - LibraryLoader.load("net.objecthunter","exp4j","0.4.8", libRepo); - LibraryLoader.load("org.mariadb.jdbc","mariadb-java-client","3.1.4", libRepo); - LibraryLoader.load("mysql","mysql-connector-java","8.0.30", libRepo); - LibraryLoader.load("commons-io","commons-io","2.11.0", libRepo); - } - - private void registerQuests() { - this.integrationManager.registerQuests(); - } - - public IntegrationManager getIntegrationManager() { - return integrationManager; - } - - public FishingManager getFishingManager() { - return fishingManager; - } - - public CompetitionManager getCompetitionManager() { - return competitionManager; - } - - public EffectManager getEffectManager() { - return effectManager; - } - - public LootManager getLootManager() { - return lootManager; - } - - public TotemManager getTotemManager() { - return totemManager; - } - - public SellManager getSellManager() { - return sellManager; - } - - public BagDataManager getBagDataManager() { - return bagDataManager; - } - - public DataManager getDataManager() { - return dataManager; - } - - public VersionHelper getVersionHelper() { - return versionHelper; - } - - public BarMechanicManager getBarMechanicManager() { - return barMechanicManager; - } - - public StatisticsManager getStatisticsManager() { - return statisticsManager; - } - - public OffsetManager getOffsetManager() { - return offsetManager; - } - - public Scheduler getScheduler() { - return scheduler; - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - public void reload() { - File contentFolder = new File(plugin.getDataFolder(), "contents"); - if (!contentFolder.exists()) { - contentFolder.mkdirs(); - } - ConfigManager.load(); - MessageManager.load(); - getScheduler().reload(); - getDataManager().unload(); - getDataManager().load(); - getEffectManager().unload(); - getEffectManager().load(); - getIntegrationManager().unload(); - getIntegrationManager().load(); - getBarMechanicManager().unload(); - getBarMechanicManager().load(); - getOffsetManager().unload(); - getOffsetManager().load(); - getLootManager().unload(); - getLootManager().load(); - getTotemManager().unload(); - getTotemManager().load(); - getFishingManager().unload(); - getFishingManager().load(); - getSellManager().unload(); - getSellManager().load(); - getCompetitionManager().unload(); - getCompetitionManager().load(); - getBagDataManager().unload(); - getBagDataManager().load(); - getStatisticsManager().unload(); - getStatisticsManager().load(); - } - - public static BukkitAudiences getAdventure() { - return adventure; - } - - public static ProtocolManager getProtocolManager() { - return protocolManager; - } - - public static CustomFishing getInstance() { - return plugin; - } - - private void updateLegacyFormatContents() { - List folders = List.of( - "baits", "bars", "categories", "competitions", - "enchants", "loots", "minigames", "mobs", - "rods", "totems", "totem_blocks", "utils" - ); - for (String folderName : folders) { - File legacyFolder = new File(plugin.getDataFolder(), folderName); - if (legacyFolder.exists()) { - try { - FileUtils.moveDirectory(legacyFolder, new File(plugin.getDataFolder(), "contents" + File.separator + folderName)); - } catch (IOException e) { - Log.severe("Failed to convert old files into new folders"); - } - } - } - List dataFolders = List.of("fishingbag", "sell", "statistics"); - for (String folderName : dataFolders) { - File legacyFolder = new File(plugin.getDataFolder(), folderName + "_data"); - if (legacyFolder.exists()) { - try { - FileUtils.moveDirectory(legacyFolder, new File(plugin.getDataFolder(), "data" + File.separator + folderName)); - } catch (IOException e) { - Log.severe("Failed to convert old files into new folders"); - } - } - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/api/CustomFishingAPI.java b/src/main/java/net/momirealms/customfishing/api/CustomFishingAPI.java deleted file mode 100644 index d9855e74..00000000 --- a/src/main/java/net/momirealms/customfishing/api/CustomFishingAPI.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api; - -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.fishing.competition.Competition; -import net.momirealms.customfishing.fishing.loot.DroppedItem; -import net.momirealms.customfishing.fishing.loot.Item; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.util.ItemStackUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.UUID; - -public class CustomFishingAPI { - - /** - * get plugin instance - * @return plugin instance - */ - public static CustomFishing getPluginInstance() { - return CustomFishing.getInstance(); - } - - /** - * Is there a competition ongoing - * @return is or not - */ - public static boolean isCompetitionGoingOn() { - return Competition.getCurrentCompetition() != null; - } - - /** - * Get the current competition - * return null if there's no competition - * @return competition - */ - @Nullable - public static Competition getCurrentCompetition() { - return Competition.getCurrentCompetition(); - } - - /** - * get a fish's size - * @return size - */ - public static float getFishSize(ItemStack fish) { - return CustomFishing.getInstance().getFishingManager().getSize(fish); - } - - /** - * get an item's price - * @param itemStack item to sell - * @return price - */ - public static double getItemPrice(ItemStack itemStack) { - return CustomFishing.getInstance().getSellManager().getSingleItemPrice(itemStack); - } - - /** - * If an item exists in item library - * @param type type - * @param key key - * @return exist - */ - public static boolean doesItemExist(String type, String key) { - return switch (type) { - case "loot" -> CustomFishing.getInstance().getLootManager().hasLoot(key); - case "rod" -> CustomFishing.getInstance().getEffectManager().getRodItem(key) != null; - case "bait" -> CustomFishing.getInstance().getEffectManager().getBaitItem(key) != null; - case "util" -> CustomFishing.getInstance().getEffectManager().getUtilItem(key) != null; - default -> false; - }; - } - - /** - * If a world allow new fishing - * @param world world - * @return allow or not - */ - public static boolean isFishingWorld(World world) { - return ConfigManager.getWorldsList().contains(world.getName()); - } - - /** - * Get all the possible loots for a certain player at a certain location - * @param location location - * @param player player - * @return loots - */ - public static List getLootsAt(Location location, Player player) { - return CustomFishing.getInstance().getFishingManager().getPossibleLootList(new FishingCondition(location, player, null, null), false, CustomFishing.getInstance().getLootManager().getAllLoots()); - } - - /** - * Get all the possible loots at a certain location - * @param location location - * @return loots - */ - public static List getLootsAt(Location location) { - return CustomFishing.getInstance().getFishingManager().getPossibleLootList(new FishingCondition(location, null, null, null), false, CustomFishing.getInstance().getLootManager().getAllLoots()); - } - - /** - * Get a loot from Loot Manager - * @param id id - * @return loot - */ - public static LootImpl getLootByID(String id) { - return CustomFishing.getInstance().getLootManager().getLoot(id); - } - - /** - * get items directly from item library - * return AIR if the loot does not exist - * @param id item_id - * @return itemStack - */ - @NotNull - public static ItemStack getLootItemByID(String id) { - return CustomFishing.getInstance().getIntegrationManager().build(id, null); - } - - /** - * get items obtained by fishing - * return AIR if the loot does not exist - * @param id item_id - * @param player player - * @return itemStack - */ - @NotNull - public static ItemStack getLootItemByID(String id, @Nullable Player player) { - LootImpl loot = CustomFishing.getInstance().getLootManager().getLoot(id); - if (!(loot instanceof DroppedItem droppedItem)) return new ItemStack(Material.AIR); - return CustomFishing.getInstance().getFishingManager().getCustomFishingLootItemStack(droppedItem, player); - } - - /** - * get rods directly from item library - * return null if the rod does not exist - * @param id rod_id - * @return itemStack - */ - public static ItemStack getRodItemByID(String id) { - Item item = CustomFishing.getInstance().getEffectManager().getRodItem(id); - return item == null ? null : ItemStackUtils.getFromItem(item); - } - - /** - * get baits directly from item library - * return null if the bait does not exist - * @param id bait_id - * @return itemStack - */ - public static ItemStack getBaitItemByID(String id) { - Item item = CustomFishing.getInstance().getEffectManager().getBaitItem(id); - return item == null ? null : ItemStackUtils.getFromItem(item); - } - - /** - * get utils directly from item library - * return null if the util does not exist - * @param id util_id - * @return itemStack - */ - public static ItemStack getUtilItemByID(String id) { - Item item = CustomFishing.getInstance().getEffectManager().getUtilItem(id); - return item == null ? null : ItemStackUtils.getFromItem(item); - } - - /** - * get the catch amount of a certain loot - * return -1 if player's data is not loaded - * @param id loot id - * @param uuid uuid - * @return amount - */ - public static int getCertainLootCatchAmount(String id, UUID uuid) { - return CustomFishing.getInstance().getStatisticsManager().getFishAmount(uuid, id); - } - - /** - * If the item is CustomFishing item - * @param itemStack itemStack - * @return is or not - */ - public static boolean isCustomFishingItem(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return false; - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - return nbtCompound != null; - } - - /** - * Add CustomFishing tag to an item - * @param itemStack itemStack - * @param type type - * @param id id - */ - public static void addCustomFishingTagToItem(ItemStack itemStack, String type, String id) { - if (itemStack == null || itemStack.getType() == Material.AIR) return; - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.addCompound("CustomFishing"); - nbtCompound.setString("type", type); - nbtCompound.setString("id", id); - itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - } - - /** - * Get a player's earnings - * @param player player - * @return earnings - */ - public static double getTodayEarning(Player player) { - return CustomFishing.getInstance().getSellManager().getTodayEarning(player); - } - - /** - * return null if the itemStack is not a CustomFishing rod - * @param itemStack itemStack - * @return rod id - */ - public static String getRodID(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return null; - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound == null) return null; - String type = nbtCompound.getString("type"); - if (!type.equals("rod")) return null; - return nbtCompound.getString("id"); - } - - /** - * return null if the itemStack is not a CustomFishing util - * @param itemStack itemStack - * @return util id - */ - public static String getUtilID(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return null; - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound == null) return null; - String type = nbtCompound.getString("type"); - if (!type.equals("util")) return null; - return nbtCompound.getString("id"); - } - - /** - * return null if the itemStack is not a CustomFishing bait - * @param itemStack itemStack - * @return bait id - */ - public static String getBaitID(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return null; - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound == null) return null; - String type = nbtCompound.getString("type"); - if (!type.equals("bait")) return null; - return nbtCompound.getString("id"); - } - - /** - * return null if the itemStack is not a CustomFishing loot - * @param itemStack itemStack - * @return loot id - */ - public static String getLootID(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return null; - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound == null) return null; - String type = nbtCompound.getString("type"); - if (!type.equals("loot")) return null; - return nbtCompound.getString("id"); - } -} diff --git a/src/main/java/net/momirealms/customfishing/api/event/FishFinderEvent.java b/src/main/java/net/momirealms/customfishing/api/event/FishFinderEvent.java deleted file mode 100644 index edeec827..00000000 --- a/src/main/java/net/momirealms/customfishing/api/event/FishFinderEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import net.momirealms.customfishing.fishing.loot.LootImpl; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public class FishFinderEvent extends PlayerEvent implements Cancellable { - - private static final HandlerList handlerList = new HandlerList(); - - private boolean cancelled; - private final List loots; - - public FishFinderEvent(@NotNull Player who, List loots) { - super(who); - this.cancelled = false; - this.loots = loots; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - cancelled = cancel; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - public List getLoots() { - return loots; - } -} diff --git a/src/main/java/net/momirealms/customfishing/api/event/FishResultEvent.java b/src/main/java/net/momirealms/customfishing/api/event/FishResultEvent.java deleted file mode 100644 index d1b0aaa3..00000000 --- a/src/main/java/net/momirealms/customfishing/api/event/FishResultEvent.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import net.momirealms.customfishing.fishing.FishResult; -import net.momirealms.customfishing.fishing.loot.Loot; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class FishResultEvent extends PlayerEvent implements Cancellable { - - private boolean cancelled; - private boolean isDouble; - private final FishResult result; - private final ItemStack itemStack; - private final String loot_id; - private final Loot loot; - private static final HandlerList handlerList = new HandlerList(); - - public FishResultEvent(@NotNull Player who, FishResult result, boolean isDouble, @Nullable ItemStack itemStack, @Nullable String loot_id, @Nullable Loot loot) { - super(who); - this.cancelled = false; - this.result = result; - this.isDouble = isDouble; - this.itemStack = itemStack; - this.loot_id = loot_id; - this.loot = loot; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - cancelled = cancel; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - public boolean isDouble() { - return isDouble; - } - - @NotNull - public FishResult getResult() { - return result; - } - - /** - * Would be null if failed or caught a mob - * @return loot id - */ - @Nullable - public ItemStack getItemStack() { - return itemStack; - } - - public void setDouble(boolean willDouble) { - isDouble = willDouble; - } - - @Nullable - @Deprecated - public String getLoot_id() { - return loot_id; - } - - /** - * Would be null if failed - * @return loot id (Vanilla loots would be "vanilla") - */ - @Nullable - public String getLootID() { - return loot_id; - } - - public Loot getLoot() { - return loot; - } -} diff --git a/src/main/java/net/momirealms/customfishing/api/event/MiniGameStartEvent.java b/src/main/java/net/momirealms/customfishing/api/event/MiniGameStartEvent.java deleted file mode 100644 index 46f14257..00000000 --- a/src/main/java/net/momirealms/customfishing/api/event/MiniGameStartEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -public class MiniGameStartEvent extends PlayerEvent implements Cancellable { - - private boolean cancelled; - private int difficulty; - private static final HandlerList handlerList = new HandlerList(); - - public MiniGameStartEvent(@NotNull Player who, int difficulty) { - super(who); - this.cancelled = false; - this.difficulty = difficulty; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - cancelled = cancel; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - public int getDifficulty() { - return difficulty; - } - - public void setDifficulty(int difficulty) { - this.difficulty = difficulty; - } -} diff --git a/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java b/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java deleted file mode 100644 index 4a8395e9..00000000 --- a/src/main/java/net/momirealms/customfishing/api/event/RodCastEvent.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import net.momirealms.customfishing.fishing.Effect; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -public class RodCastEvent extends PlayerEvent implements Cancellable { - - private final Effect effect; - private boolean isCancelled; - private static final HandlerList handlerList = new HandlerList(); - - public RodCastEvent(@NotNull Player who, @NotNull Effect effect) { - super(who); - this.isCancelled = false; - this.effect = effect; - } - - @Override - public boolean isCancelled() { - return this.isCancelled; - } - - /** - * If cancelled, PlayerFishEvent would also be cancelled - * @param cancel true if you wish to cancel this event - */ - @Override - public void setCancelled(boolean cancel) { - this.isCancelled = cancel; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - public Effect getEffect() { - return effect; - } -} diff --git a/src/main/java/net/momirealms/customfishing/api/event/SellFishEvent.java b/src/main/java/net/momirealms/customfishing/api/event/SellFishEvent.java deleted file mode 100644 index 02a8b432..00000000 --- a/src/main/java/net/momirealms/customfishing/api/event/SellFishEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -public class SellFishEvent extends PlayerEvent implements Cancellable { - - private boolean cancelled; - private float money; - private static final HandlerList handlerList = new HandlerList(); - - public SellFishEvent(@NotNull Player who, float money) { - super(who); - this.money = money; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - cancelled = cancel; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - public float getMoney() { - return money; - } - - public void setMoney(float money) { - this.money = money; - } -} diff --git a/src/main/java/net/momirealms/customfishing/api/event/TotemActivationEvent.java b/src/main/java/net/momirealms/customfishing/api/event/TotemActivationEvent.java deleted file mode 100644 index 428c0e25..00000000 --- a/src/main/java/net/momirealms/customfishing/api/event/TotemActivationEvent.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) <2022> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.momirealms.customfishing.api.event; - -import net.momirealms.customfishing.fishing.totem.TotemConfig; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; -import org.jetbrains.annotations.NotNull; - -public class TotemActivationEvent extends PlayerEvent implements Cancellable { - - private boolean cancelled; - private final TotemConfig totem; - private final Location location; - private static final HandlerList handlerList = new HandlerList(); - - public TotemActivationEvent(@NotNull Player who, Location location, TotemConfig totem) { - super(who); - this.cancelled = false; - this.totem = totem; - this.location = location; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancel) { - cancelled = cancel; - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return getHandlerList(); - } - - public TotemConfig getTotem() { - return totem; - } - - public Location getLocation() { - return location; - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/AbstractMainCommand.java b/src/main/java/net/momirealms/customfishing/commands/AbstractMainCommand.java deleted file mode 100644 index 0eada606..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/AbstractMainCommand.java +++ /dev/null @@ -1,75 +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.commands; - -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabExecutor; -import org.jetbrains.annotations.NotNull; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -public abstract class AbstractMainCommand implements TabExecutor { - - protected final Map subCommandMap; - - public AbstractMainCommand() { - this.subCommandMap = new ConcurrentHashMap<>(); - } - - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { - List argList = Arrays.asList(args); - if (argList.size() < 1) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.nonArgs); - return true; - } - AbstractSubCommand subCommand = subCommandMap.get(argList.get(0)); - if (subCommand != null) - return subCommand.onCommand(sender, argList.subList(1, argList.size())); - else { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.unavailableArgs); - return true; - } - } - - @Override - public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) { - List argList = Arrays.asList(args); - if (argList.size() <= 1) { - List returnList = new ArrayList<>(subCommandMap.keySet()); - returnList.removeIf(str -> !str.startsWith(args[0])); - return returnList; - } - AbstractSubCommand subCommand = subCommandMap.get(argList.get(0)); - if (subCommand != null) - return subCommand.onTabComplete(sender, argList.subList(1, argList.size())); - else - return Collections.singletonList(""); - } - - public void regSubCommand(AbstractSubCommand executor) { - subCommandMap.put(executor.getSubCommand(), executor); - } - - public Map getSubCommandMap() { - return subCommandMap; - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/AbstractSubCommand.java b/src/main/java/net/momirealms/customfishing/commands/AbstractSubCommand.java deleted file mode 100644 index ddb2371f..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/AbstractSubCommand.java +++ /dev/null @@ -1,134 +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.commands; - -import net.momirealms.customfishing.api.CustomFishingAPI; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -public abstract class AbstractSubCommand { - - private final String command; - private Map subCommandMap; - - public AbstractSubCommand(String command) { - this.command = command; - } - - public boolean onCommand(CommandSender sender, List args) { - if (subCommandMap == null || args.size() < 1) { - return true; - } - AbstractSubCommand subCommand = subCommandMap.get(args.get(0)); - if (subCommand == null) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.unavailableArgs); - } else { - subCommand.onCommand(sender, args.subList(1, args.size())); - } - return true; - } - - public List onTabComplete(CommandSender sender, List args) { - if (subCommandMap == null) - return Collections.singletonList(""); - if (args.size() <= 1) { - List returnList = new ArrayList<>(subCommandMap.keySet()); - returnList.removeIf(str -> !str.startsWith(args.get(0))); - return returnList; - } - AbstractSubCommand subCmd = subCommandMap.get(args.get(0)); - if (subCmd != null) - return subCommandMap.get(args.get(0)).onTabComplete(sender, args.subList(1, args.size())); - return Collections.singletonList(""); - } - - public String getSubCommand() { - return command; - } - - public Map getSubCommands() { - return Collections.unmodifiableMap(subCommandMap); - } - - public void regSubCommand(AbstractSubCommand command) { - if (subCommandMap == null) { - subCommandMap = new ConcurrentHashMap<>(); - } - subCommandMap.put(command.getSubCommand(), command); - } - - protected boolean noConsoleExecute(CommandSender commandSender) { - if (!(commandSender instanceof Player)) { - AdventureUtils.consoleMessage(MessageManager.prefix + MessageManager.noConsole); - return true; - } - return false; - } - - protected boolean itemNotExist(CommandSender commandSender, String type, String key) { - if (!CustomFishingAPI.doesItemExist(type, key)) { - AdventureUtils.sendMessage(commandSender, MessageManager.prefix + MessageManager.itemNotExist); - return true; - } - return false; - } - - protected boolean playerNotOnline(CommandSender commandSender, String player) { - if (Bukkit.getPlayer(player) == null) { - AdventureUtils.sendMessage(commandSender, MessageManager.prefix + MessageManager.notOnline.replace("{Player}", player)); - return true; - } - return false; - } - - protected boolean lackArgs(CommandSender commandSender, int required, int current) { - if (required > current) { - AdventureUtils.sendMessage(commandSender, MessageManager.prefix + MessageManager.lackArgs); - return true; - } - return false; - } - - protected void giveItemMsg(CommandSender sender, String name, String item, int amount) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.giveItem.replace("{Amount}", String.valueOf(amount)).replace("{Player}",name).replace("{Item}",item)); - } - - protected void getItemMsg(CommandSender sender, String item, int amount) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.getItem.replace("{Amount}", String.valueOf(amount)).replace("{Item}", item)); - } - - protected List online_players() { - List online = new ArrayList<>(); - Bukkit.getOnlinePlayers().forEach((player -> online.add(player.getName()))); - return online; - } - - protected List filterStartingWith(List list, String prefix) { - return list.stream().filter(s -> s.startsWith(prefix)).collect(Collectors.toList()); - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/FishingBagCommand.java b/src/main/java/net/momirealms/customfishing/commands/FishingBagCommand.java deleted file mode 100644 index 1b490e9c..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/FishingBagCommand.java +++ /dev/null @@ -1,81 +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.commands; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.List; - -public class FishingBagCommand extends AbstractMainCommand { - - public FishingBagCommand() { - regSubCommand(OpenCommand.INSTANCE); - } - - public static class OpenCommand extends AbstractSubCommand { - - public static final OpenCommand INSTANCE = new OpenCommand(); - - private OpenCommand() { - super("open"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.noConsoleExecute(sender)) return true; - Player player = (Player) sender; - if (args.size() == 0) { - if (!sender.hasPermission("fishingbag.open")) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.noPerm); - return true; - } - player.closeInventory(); - CustomFishing.getInstance().getBagDataManager().openFishingBag(player, player, false); - } - if (args.size() >= 1) { - if (!sender.hasPermission("customfishing.admin")) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.noPerm); - return true; - } - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayerIfCached(args.get(0)); - if (offlinePlayer == null) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.playerNotExist); - return true; - } - player.closeInventory(); - CustomFishing.getInstance().getBagDataManager().openFishingBag(player, offlinePlayer, args.size() >= 2 && args.get(1).equals("--force")); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (ConfigManager.enableFishingBag && sender.hasPermission("customfishing.admin") && args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } - return null; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/MainCommand.java b/src/main/java/net/momirealms/customfishing/commands/MainCommand.java deleted file mode 100644 index 16cf06f2..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/MainCommand.java +++ /dev/null @@ -1,38 +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.commands; - - -import net.momirealms.customfishing.commands.subcmd.*; -import net.momirealms.customfishing.commands.subcmd.item.ItemsCommand; - -public class MainCommand extends AbstractMainCommand { - - public MainCommand() { - regSubCommand(ReloadCommand.INSTANCE); - regSubCommand(ItemsCommand.INSTANCE); - regSubCommand(CompetitionCommand.INSTANCE); - regSubCommand(SellShopCommand.INSTANCE); - regSubCommand(OpenBagCommand.INSTANCE); - regSubCommand(StatisticsCommand.INSTANCE); - regSubCommand(HelpCommand.INSTANCE); - regSubCommand(AboutCommand.INSTANCE); - regSubCommand(DebugCommand.INSTANCE); - regSubCommand(ConvertCommand.INSTANCE); - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/SellFishCommand.java b/src/main/java/net/momirealms/customfishing/commands/SellFishCommand.java deleted file mode 100644 index 7158c7ef..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/SellFishCommand.java +++ /dev/null @@ -1,49 +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.commands; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabExecutor; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class SellFishCommand implements TabExecutor { - - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - if (!(sender instanceof Player player)) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.noConsole); - return true; - } - player.closeInventory(); - CustomFishing.getInstance().getSellManager().openGuiForPlayer(player); - return true; - } - - @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { - return null; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/AboutCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/AboutCommand.java deleted file mode 100644 index a433b83b..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/AboutCommand.java +++ /dev/null @@ -1,44 +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.commands.subcmd; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.CommandSender; - -import java.util.List; - -public class AboutCommand extends AbstractSubCommand { - - public static final AboutCommand INSTANCE = new AboutCommand(); - - public AboutCommand() { - super("about"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - AdventureUtils.sendMessage(sender, "<#00BFFF>\uD83C\uDFA3 CustomFishing - <#87CEEB>" + CustomFishing.getInstance().getVersionHelper().getPluginVersion()); - AdventureUtils.sendMessage(sender, "<#B0C4DE>A fishing plugin that provides innovative mechanics and powerful loot system"); - AdventureUtils.sendMessage(sender, "<#DA70D6>\uD83E\uDDEA Author: <#FFC0CB>XiaoMoMi"); - AdventureUtils.sendMessage(sender, "<#FF7F50>\uD83D\uDD25 Contributors: <#FFA07A>0ft3n, <#FFA07A>Peng_Lx, <#FFA07A>Masaki"); - AdventureUtils.sendMessage(sender, "<#FFD700>⭐ Document <#A9A9A9>| <#FAFAD2>⛏ Github <#A9A9A9>| <#48D1CC>\uD83D\uDD14 Polymart"); - return true; - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/CompetitionCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/CompetitionCommand.java deleted file mode 100644 index 83c731e9..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/CompetitionCommand.java +++ /dev/null @@ -1,88 +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.commands.subcmd; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.fishing.competition.CompetitionSchedule; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.CommandSender; - -import java.util.ArrayList; -import java.util.List; - -public class CompetitionCommand extends AbstractSubCommand { - - public static final CompetitionCommand INSTANCE = new CompetitionCommand(); - - public CompetitionCommand() { - super("competition"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (!ConfigManager.enableCompetition || super.lackArgs(sender, 1, args.size())) return true; - switch (args.get(0)) { - case "start" -> { - if (args.size() < 2) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.lackArgs); - return true; - } - if (CompetitionSchedule.startCompetition(args.get(1))) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.forceSuccess); - } else { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.forceFailure); - } - } - case "end" -> { - CompetitionSchedule.endCompetition(); - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.forceEnd); - } - case "cancel" -> { - CompetitionSchedule.cancelCompetition(); - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.forceCancel); - } - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - List completions = new ArrayList<>(); - if (args.size() == 1) { - for (String cmd : List.of("start", "end", "cancel")) { - if (cmd.startsWith(args.get(0))) { - completions.add(cmd); - } - } - } else if (args.size() == 2 && args.get(0).equals("start")) { - for (String cmd : competitions()) { - if (cmd.startsWith(args.get(1))) { - completions.add(cmd); - } - } - } - return completions.isEmpty() ? null : completions; - } - - private List competitions() { - return new ArrayList<>(CustomFishing.getInstance().getCompetitionManager().getCompetitionsC().keySet()); - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/ConvertCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/ConvertCommand.java deleted file mode 100644 index fb7f70ee..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/ConvertCommand.java +++ /dev/null @@ -1,110 +0,0 @@ -package net.momirealms.customfishing.commands.subcmd; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -public class ConvertCommand extends AbstractSubCommand { - - public static final ConvertCommand INSTANCE = new ConvertCommand(); - - public ConvertCommand() { - super("convert"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - convertItems("loots"); - convertItems("mobs"); - AdventureUtils.sendMessage(sender, "Done! Files are saved to your /loots & /mobs folder"); - AdventureUtils.sendMessage(sender, "Converted files are named by converted-xxx.yml."); - AdventureUtils.sendMessage(sender, "Do a quick check and delete your old files to make them work"); - return true; - } - - private void convertItems(String folder) { - File loot_file = new File(CustomFishing.getInstance().getDataFolder() + File.separator + "contents" + File.separator + folder); - if (!loot_file.exists()) return; - File[] files = loot_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (file.getName().startsWith("converted-")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (String key : config.getKeys(false)) { - ConfigurationSection section = config.getConfigurationSection(key); - if (section == null || !section.contains("action")) continue; - ConfigurationSection actionSec = section.getConfigurationSection("action"); - if (actionSec == null) continue; - for (String event : new String[]{"success", "fail", "failure", "hook", "consume"}) { - convertSec(actionSec, event); - } - ConfigurationSection successTimesSection = actionSec.getConfigurationSection("success-times"); - if (successTimesSection != null) { - for (String times : successTimesSection.getKeys(false)) { - convertSec(successTimesSection, times); - } - } - } - try { - config.save(new File(file.getParentFile(), "converted-"+file.getName())); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - private void convertSec(ConfigurationSection actionSec, String event) { - ConfigurationSection eventSec = actionSec.getConfigurationSection(event); - if (eventSec == null) return; - for (String actionType : eventSec.getKeys(false)) { - switch (actionType) { - case "message", "command" -> { - ConfigurationSection newSec = eventSec.createSection("action" + "_" + actionType); - newSec.set("type", actionType); - newSec.set("value", eventSec.getStringList(actionType)); - newSec.set("chance", eventSec.getDouble(actionType + "-chance",1)); - } - case "exp", "mending" -> { - ConfigurationSection newSec = eventSec.createSection("action" + "_" + actionType); - newSec.set("type", actionType); - newSec.set("value", eventSec.getInt(actionType)); - newSec.set("chance", eventSec.getDouble(actionType + "-chance",1)); - } - case "skill-xp", "job-xp" -> { - ConfigurationSection newSec = eventSec.createSection("action" + "_" + actionType); - newSec.set("type", actionType); - newSec.set("value", eventSec.getDouble(actionType)); - newSec.set("chance", eventSec.getDouble(actionType + "-chance",1)); - } - case "sound" -> { - ConfigurationSection newSec = eventSec.createSection("action" + "_" + actionType); - newSec.set("type", actionType); - newSec.set("value.source", eventSec.getString(actionType + ".source")); - newSec.set("value.key", eventSec.getString(actionType + ".key")); - newSec.set("value.volume", eventSec.getDouble(actionType + ".volume")); - newSec.set("value.pitch", eventSec.getDouble(actionType + ".pitch")); - } - case "potion-effect" -> { - ConfigurationSection potionSec = eventSec.getConfigurationSection(actionType); - if (potionSec != null) { - for (String potion : potionSec.getKeys(false)) { - ConfigurationSection newSec = eventSec.createSection("potion" + "_" + potion); - newSec.set("type", actionType); - newSec.set("value.type", potionSec.getString(potion + ".type")); - newSec.set("value.amplifier", potionSec.getInt(potion + ".amplifier")); - newSec.set("value.duration", potionSec.getInt(potion + ".duration")); - } - } - } - } - eventSec.set(actionType, null); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/DebugCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/DebugCommand.java deleted file mode 100644 index 361c6415..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/DebugCommand.java +++ /dev/null @@ -1,94 +0,0 @@ -package net.momirealms.customfishing.commands.subcmd; - -import net.momirealms.biomeapi.BiomeAPI; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.api.CustomFishingAPI; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.fishing.Effect; -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import net.momirealms.customfishing.integration.SeasonInterface; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -public class DebugCommand extends AbstractSubCommand { - - public static final DebugCommand INSTANCE = new DebugCommand(); - - public DebugCommand() { - super("debug"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (lackArgs(sender, 1, args.size()) || noConsoleExecute(sender)) return true; - Player player = (Player) sender; - switch (args.get(0)) { - case "biome" -> { - AdventureUtils.playerMessage(player, BiomeAPI.getBiome(player.getLocation())); - } - case "time" -> { - AdventureUtils.playerMessage(player, String.valueOf(player.getWorld().getTime())); - } - case "world" -> { - AdventureUtils.playerMessage(player, player.getWorld().getName()); - } - case "season" -> { - SeasonInterface seasonInterface = CustomFishing.getInstance().getIntegrationManager().getSeasonInterface(); - if (seasonInterface == null) return true; - AdventureUtils.playerMessage(player, seasonInterface.getSeason(player.getLocation().getWorld())); - } - case "loot-chance" -> { - Effect initial = CustomFishing.getInstance().getFishingManager().getInitialEffect(player); - List lootProbability = getLootProbability(initial, CustomFishing.getInstance().getFishingManager().getPossibleLootList(new FishingCondition(player.getLocation(), player, "fish_finder", "fish_finder"), false, CustomFishing.getInstance().getLootManager().getAllLoots())); - for (String msg : lootProbability) { - AdventureUtils.playerMessage(player, msg); - } - } - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(List.of("biome", "time", "world", "season", "loot-chance"), args.get(0)); - } - return null; - } - - public ArrayList getLootProbability(Effect initialEffect, List possibleLoots) { - List availableLoots = new ArrayList<>(); - HashMap as = initialEffect.getWeightAS(); - HashMap md = initialEffect.getWeightMD(); - double[] weights = new double[possibleLoots.size()]; - int index = 0; - for (LootImpl loot : possibleLoots){ - double weight = loot.getWeight(); - String group = loot.getGroup(); - if (group != null){ - if (as.get(group) != null){ - weight += as.get(group); - } - if (md.get(group) != null){ - weight *= md.get(group); - } - } - if (weight <= 0) continue; - availableLoots.add(loot); - weights[index++] = weight; - } - ArrayList lootWithChance = new ArrayList<>(availableLoots.size()); - double total = Arrays.stream(weights).sum(); - for (int i = 0; i < index; i++){ - lootWithChance.add(availableLoots.get(i).getKey() + ": " + String.format("%.2f", weights[i]*100/total) + "%"); - } - return lootWithChance; - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/HelpCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/HelpCommand.java deleted file mode 100644 index 4e341ddb..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/HelpCommand.java +++ /dev/null @@ -1,71 +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.commands.subcmd; - -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.CommandSender; - -import java.util.List; - -public class HelpCommand extends AbstractSubCommand { - - public static final HelpCommand INSTANCE = new HelpCommand(); - - public HelpCommand() { - super("help"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - AdventureUtils.sendMessage(sender, "<#4169E1>Command usage:"); - AdventureUtils.sendMessage(sender, " ├─<#FFFACD> "); - AdventureUtils.sendMessage(sender, " └─<#FFFACD><#E1FFFF>[Optional Augument]"); - AdventureUtils.sendMessage(sender, "<#4169E1>/customfishing"); - AdventureUtils.sendMessage(sender, " ├─help"); - AdventureUtils.sendMessage(sender, " ├─about"); - AdventureUtils.sendMessage(sender, " ├─reload <#87CEFA>Reload the plugin"); - AdventureUtils.sendMessage(sender, " ├─forceopenbag <#FFFACD> <#87CEFA>Force a player to open his fishing bag"); - AdventureUtils.sendMessage(sender, " ├─sellshop <#FFFACD> <#87CEFA>Force a player to open sell shop"); - AdventureUtils.sendMessage(sender, " ├─competition"); - AdventureUtils.sendMessage(sender, " │ ├─start <#FFFACD> <#87CEFA>Start a competition"); - AdventureUtils.sendMessage(sender, " │ ├─end <#87CEFA>End the ongoing competition"); - AdventureUtils.sendMessage(sender, " │ └─cancel <#87CEFA>Cancel the ongoing competition"); - AdventureUtils.sendMessage(sender, " ├─items"); - AdventureUtils.sendMessage(sender, " │ ├─loot"); - AdventureUtils.sendMessage(sender, " │ │ ├─get <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " │ │ ├─give <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " │ │ └─import <#FFFACD> <#87CEFA>Import the item in hand"); - AdventureUtils.sendMessage(sender, " │ ├─rod"); - AdventureUtils.sendMessage(sender, " │ │ ├─get <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " │ │ └─give <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " │ ├─bait"); - AdventureUtils.sendMessage(sender, " │ │ ├─get <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " │ │ └─give <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " │ └─util"); - AdventureUtils.sendMessage(sender, " │ ├─get <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " │ └─give <#FFFACD> <#E1FFFF>[amount]"); - AdventureUtils.sendMessage(sender, " └─statistics"); - AdventureUtils.sendMessage(sender, " ├─reset <#FFFACD> <#87CEFA>Reset a player's statistics"); - AdventureUtils.sendMessage(sender, " └─set <#FFFACD> <#87CEFA>Set certain statistics' value"); - AdventureUtils.sendMessage(sender, "<#4169E1>/fishingbag"); - AdventureUtils.sendMessage(sender, " └─open <#E1FFFF>[player] <#87CEFA>Open the fishing bag"); - AdventureUtils.sendMessage(sender, "<#4169E1>/sellshop <#87CEFA>Open the sell shop"); - return true; - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/OpenBagCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/OpenBagCommand.java deleted file mode 100644 index 5c2be29a..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/OpenBagCommand.java +++ /dev/null @@ -1,57 +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.commands.subcmd; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.manager.ConfigManager; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.List; - -public class OpenBagCommand extends AbstractSubCommand { - - public static final OpenBagCommand INSTANCE = new OpenBagCommand(); - - private OpenBagCommand() { - super("forceopenbag"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (!ConfigManager.enableFishingBag - || super.lackArgs(sender, 1, args.size()) - || playerNotOnline(sender, args.get(0)) - ) return true; - Player viewer = Bukkit.getPlayer(args.get(0)); - assert viewer != null; - viewer.closeInventory(); - CustomFishing.getInstance().getBagDataManager().openFishingBag(viewer, viewer, false); - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (ConfigManager.enableFishingBag && args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } - return null; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/ReloadCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/ReloadCommand.java deleted file mode 100644 index 1c77876a..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/ReloadCommand.java +++ /dev/null @@ -1,44 +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.commands.subcmd; - - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.command.CommandSender; - -import java.util.List; - -public final class ReloadCommand extends AbstractSubCommand { - - public static final ReloadCommand INSTANCE = new ReloadCommand(); - - private ReloadCommand() { - super("reload"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - long time1 = System.currentTimeMillis(); - CustomFishing.getInstance().reload(); - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.reload.replace("{time}", String.valueOf(System.currentTimeMillis() - time1))); - return true; - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/SellShopCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/SellShopCommand.java deleted file mode 100644 index de3f1f2b..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/SellShopCommand.java +++ /dev/null @@ -1,55 +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.commands.subcmd; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.List; - -public class SellShopCommand extends AbstractSubCommand { - - public static final SellShopCommand INSTANCE = new SellShopCommand(); - - public SellShopCommand() { - super("sellshop"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 1, args.size()) - || playerNotOnline(sender, args.get(0)) - ) return true; - Player player = Bukkit.getPlayer(args.get(0)); - assert player != null; - player.closeInventory(); - CustomFishing.getInstance().getSellManager().openGuiForPlayer(player); - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } - return null; - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/StatisticsCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/StatisticsCommand.java deleted file mode 100644 index ac1d2b83..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/StatisticsCommand.java +++ /dev/null @@ -1,121 +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.commands.subcmd; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.List; -import java.util.stream.Collectors; - -public class StatisticsCommand extends AbstractSubCommand { - - public static final StatisticsCommand INSTANCE = new StatisticsCommand(); - - public StatisticsCommand() { - super("statistics"); - regSubCommand(SetCommand.INSTANCE); - regSubCommand(ResetCommand.INSTANCE); - } - - public static class SetCommand extends AbstractSubCommand { - - public static final SetCommand INSTANCE = new SetCommand(); - - public SetCommand() { - super("set"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (!ConfigManager.enableStatistics - || super.lackArgs(sender, 3, args.size()) - || super.playerNotOnline(sender, args.get(0)) - ) return true; - int amount = Integer.parseInt(args.get(2)); - if (amount < 0) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.negativeStatistics); - return true; - } - LootImpl loot = CustomFishing.getInstance().getLootManager().getLoot(args.get(1)); - if (loot == null || loot.isDisableStats()) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.statisticsNotExists); - return true; - } - Player player = Bukkit.getPlayer(args.get(0)); - assert player != null; - CustomFishing.getInstance().getStatisticsManager().setData(player.getUniqueId(), args.get(1), amount); - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.setStatistics.replace("{Player}", args.get(0)).replace("{Amount}", args.get(2)).replace("{Loot}", args.get(1))); - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } - if (args.size() == 2) { - return CustomFishing.getInstance().getLootManager().getAllLoots().stream() - .filter(loot -> loot.getKey().startsWith(args.get(1)) && !loot.isDisableStats()) - .map(LootImpl::getKey) - .collect(Collectors.toList()); - } - if (args.size() == 3) { - return filterStartingWith(List.of("0","1","2","4","8","16","32","64"), args.get(2)); - } - return null; - } - } - - public static class ResetCommand extends AbstractSubCommand { - - public static final ResetCommand INSTANCE = new ResetCommand(); - - public ResetCommand() { - super("reset"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (!ConfigManager.enableStatistics - || super.lackArgs(sender, 1, args.size()) - || super.playerNotOnline(sender, args.get(0)) - ) return true; - Player player = Bukkit.getPlayer(args.get(0)); - assert player != null; - if (CustomFishing.getInstance().getStatisticsManager().reset(player.getUniqueId())) AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.resetStatistics.replace("{Player}", args.get(0))); - else AdventureUtils.sendMessage(sender, MessageManager.prefix + "Internal Error, player's data is not loaded"); - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } - return null; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/BaitCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/item/BaitCommand.java deleted file mode 100644 index bd1e6771..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/BaitCommand.java +++ /dev/null @@ -1,122 +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.commands.subcmd.item; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ItemStackUtils; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.List; - -public class BaitCommand extends AbstractSubCommand { - - public static final BaitCommand INSTANCE = new BaitCommand(); - - public BaitCommand() { - super("bait"); - regSubCommand(GetCommand.INSTANCE); - regSubCommand(GiveCommand.INSTANCE); - } - - public static class GetCommand extends AbstractSubCommand { - - public static final GetCommand INSTANCE = new GetCommand(); - - public GetCommand() { - super("get"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 1, args.size()) - || super.noConsoleExecute(sender) - || super.itemNotExist(sender, "bait", args.get(0)) - ) return true; - if (args.size() == 1){ - ItemStackUtils.givePlayerBait((Player) sender, args.get(0), 0); - super.getItemMsg(sender, args.get(0), 1); - } else { - if (Integer.parseInt(args.get(1)) < 1){ - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerBait((Player) sender, args.get(0), Integer.parseInt(args.get(1))); - super.getItemMsg(sender, args.get(0), Integer.parseInt(args.get(1))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(new ArrayList<>(CustomFishing.getInstance().getEffectManager().getBaitItems().keySet()), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(1)); - } - return null; - } - } - - public static class GiveCommand extends AbstractSubCommand { - - public static final GiveCommand INSTANCE = new GiveCommand(); - - public GiveCommand() { - super("give"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 2, args.size()) - || playerNotOnline(sender, args.get(0)) - || itemNotExist(sender, "bait", args.get(1)) - ) return true; - if (args.size() == 2){ - ItemStackUtils.givePlayerBait(Bukkit.getPlayer(args.get(0)), args.get(1), 0); - super.giveItemMsg(sender, args.get(0), args.get(1), 1); - } - else if (args.size() == 3) { - if (Integer.parseInt(args.get(2)) < 1) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerBait(Bukkit.getPlayer(args.get(0)), args.get(1), Integer.parseInt(args.get(2))); - super.giveItemMsg(sender, args.get(0), args.get(1), Integer.parseInt(args.get(2))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(new ArrayList<>(CustomFishing.getInstance().getEffectManager().getBaitItems().keySet()), args.get(1)); - } else if (args.size() == 3) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(2)); - } - return null; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/ItemsCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/item/ItemsCommand.java deleted file mode 100644 index 9715b00c..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/ItemsCommand.java +++ /dev/null @@ -1,33 +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.commands.subcmd.item; - -import net.momirealms.customfishing.commands.AbstractSubCommand; - -public class ItemsCommand extends AbstractSubCommand { - - public static final ItemsCommand INSTANCE = new ItemsCommand(); - - public ItemsCommand() { - super("items"); - regSubCommand(UtilCommand.INSTANCE); - regSubCommand(RodCommand.INSTANCE); - regSubCommand(BaitCommand.INSTANCE); - regSubCommand(LootCommand.INSTANCE); - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/LootCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/item/LootCommand.java deleted file mode 100644 index f6a072e2..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/LootCommand.java +++ /dev/null @@ -1,153 +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.commands.subcmd.item; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ItemStackUtils; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class LootCommand extends AbstractSubCommand { - - public static final LootCommand INSTANCE = new LootCommand(); - - public LootCommand() { - super("loot"); - regSubCommand(GiveCommand.INSTANCE); - regSubCommand(GetCommand.INSTANCE); - regSubCommand(ImportCommand.INSTANCE); - } - - public static class GiveCommand extends AbstractSubCommand { - - public static final GiveCommand INSTANCE = new GiveCommand(); - - public GiveCommand() { - super("give"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 2, args.size()) - || playerNotOnline(sender, args.get(0)) - || itemNotExist(sender, "loot", args.get(1)) - ) return true; - if (args.size() == 2){ - int amount = ItemStackUtils.givePlayerLoot(Bukkit.getPlayer(args.get(0)), args.get(1), 0); - if (amount > 0) - super.giveItemMsg(sender, args.get(0), args.get(1), amount); - } else if (args.size() == 3) { - if (Integer.parseInt(args.get(2)) < 1) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerLoot(Bukkit.getPlayer(args.get(0)), args.get(1), Integer.parseInt(args.get(2))); - super.giveItemMsg(sender, args.get(0), args.get(1), Integer.parseInt(args.get(2))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(new ArrayList<>(CustomFishing.getInstance().getLootManager().getAllKeys()), args.get(1)); - } else if (args.size() == 3) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(2)); - } - return null; - } - } - - public static class GetCommand extends AbstractSubCommand { - - public static final GetCommand INSTANCE = new GetCommand(); - - public GetCommand() { - super("get"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 1, args.size()) - || super.noConsoleExecute(sender) - || super.itemNotExist(sender, "loot", args.get(0)) - ) return true; - if (args.size() == 1){ - int amount = ItemStackUtils.givePlayerLoot((Player) sender, args.get(0), 0); - if (amount > 0) - super.getItemMsg(sender, args.get(0), amount); - } else { - if (Integer.parseInt(args.get(1)) < 1){ - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerLoot((Player) sender, args.get(0), Integer.parseInt(args.get(1))); - super.getItemMsg(sender, args.get(0), Integer.parseInt(args.get(1))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(CustomFishing.getInstance().getLootManager().getAllKeys(), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(1)); - } - return null; - } - } - - public static class ImportCommand extends AbstractSubCommand { - - public static final ImportCommand INSTANCE = new ImportCommand(); - - public ImportCommand() { - super("import"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.noConsoleExecute(sender) - || lackArgs(sender, 1, args.size()) - ) return true; - Player player = (Player) sender; - if (ItemStackUtils.saveToFile(player.getInventory().getItemInMainHand(), args.get(0))) AdventureUtils.playerMessage(player, MessageManager.prefix + "Done! File is saved to /CustomFishing/loots/imported.yml"); - else AdventureUtils.playerMessage(player, MessageManager.prefix + "Error. The item can't be null or there already exists loot with that key name"); - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return Collections.singletonList(""); - } - return super.onTabComplete(sender, args); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/RodCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/item/RodCommand.java deleted file mode 100644 index 8f502a63..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/RodCommand.java +++ /dev/null @@ -1,122 +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.commands.subcmd.item; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ItemStackUtils; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.List; - -public class RodCommand extends AbstractSubCommand { - - public static final RodCommand INSTANCE = new RodCommand(); - - public RodCommand() { - super("rod"); - regSubCommand(GetCommand.INSTANCE); - regSubCommand(GiveCommand.INSTANCE); - } - - public static class GiveCommand extends AbstractSubCommand { - - public static final GiveCommand INSTANCE = new GiveCommand(); - - public GiveCommand() { - super("give"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 2, args.size()) - || playerNotOnline(sender, args.get(0)) - || itemNotExist(sender, "rod", args.get(1)) - ) return true; - if (args.size() == 2){ - ItemStackUtils.givePlayerRod(Bukkit.getPlayer(args.get(0)), args.get(1), 0); - super.giveItemMsg(sender, args.get(0), args.get(1), 1); - } - else if (args.size() == 3) { - if (Integer.parseInt(args.get(2)) < 1) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerRod(Bukkit.getPlayer(args.get(0)), args.get(1), Integer.parseInt(args.get(2))); - super.giveItemMsg(sender, args.get(0), args.get(1), Integer.parseInt(args.get(2))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(new ArrayList<>(CustomFishing.getInstance().getEffectManager().getRodItems().keySet()), args.get(1)); - } else if (args.size() == 3) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(2)); - } - return null; - } - } - - public static class GetCommand extends AbstractSubCommand { - - public static final GetCommand INSTANCE = new GetCommand(); - - public GetCommand() { - super("get"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 1, args.size()) - || super.noConsoleExecute(sender) - || super.itemNotExist(sender, "rod", args.get(0)) - ) return true; - if (args.size() == 1){ - ItemStackUtils.givePlayerRod((Player) sender, args.get(0), 0); - super.getItemMsg(sender, args.get(0), 1); - } else { - if (Integer.parseInt(args.get(1)) < 1){ - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerRod((Player) sender, args.get(0), Integer.parseInt(args.get(1))); - super.getItemMsg(sender, args.get(0), Integer.parseInt(args.get(1))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(new ArrayList<>(CustomFishing.getInstance().getEffectManager().getRodItems().keySet()), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(1)); - } - return null; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/UtilCommand.java b/src/main/java/net/momirealms/customfishing/commands/subcmd/item/UtilCommand.java deleted file mode 100644 index 13444c90..00000000 --- a/src/main/java/net/momirealms/customfishing/commands/subcmd/item/UtilCommand.java +++ /dev/null @@ -1,122 +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.commands.subcmd.item; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.commands.AbstractSubCommand; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ItemStackUtils; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.List; - -public class UtilCommand extends AbstractSubCommand { - - public static final UtilCommand INSTANCE = new UtilCommand(); - - public UtilCommand() { - super("util"); - regSubCommand(GetCommand.INSTANCE); - regSubCommand(GiveCommand.INSTANCE); - } - - public static class GetCommand extends AbstractSubCommand { - - public static final GetCommand INSTANCE = new GetCommand(); - - public GetCommand() { - super("get"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 1, args.size()) - || super.noConsoleExecute(sender) - || super.itemNotExist(sender, "util", args.get(0)) - ) return true; - if (args.size() == 1){ - ItemStackUtils.givePlayerUtil((Player) sender, args.get(0), 0); - super.getItemMsg(sender, args.get(0), 1); - } else { - if (Integer.parseInt(args.get(1)) < 1){ - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerUtil((Player) sender, args.get(0), Integer.parseInt(args.get(1))); - super.getItemMsg(sender, args.get(0), Integer.parseInt(args.get(1))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(new ArrayList<>(CustomFishing.getInstance().getEffectManager().getUtilItems().keySet()), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(1)); - } - return null; - } - } - - public static class GiveCommand extends AbstractSubCommand { - - public static final GiveCommand INSTANCE = new GiveCommand(); - - public GiveCommand() { - super("give"); - } - - @Override - public boolean onCommand(CommandSender sender, List args) { - if (super.lackArgs(sender, 2, args.size()) - || playerNotOnline(sender, args.get(0)) - || itemNotExist(sender, "util", args.get(1)) - ) return true; - if (args.size() == 2){ - ItemStackUtils.givePlayerUtil(Bukkit.getPlayer(args.get(0)), args.get(1), 0); - super.giveItemMsg(sender, args.get(0), args.get(1), 1); - } - else if (args.size() == 3) { - if (Integer.parseInt(args.get(2)) < 1) { - AdventureUtils.sendMessage(sender, MessageManager.prefix + MessageManager.wrongAmount); - return true; - } - ItemStackUtils.givePlayerUtil(Bukkit.getPlayer(args.get(0)), args.get(1), Integer.parseInt(args.get(2))); - super.giveItemMsg(sender, args.get(0), args.get(1), Integer.parseInt(args.get(2))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, List args) { - if (args.size() == 1) { - return filterStartingWith(online_players(), args.get(0)); - } else if (args.size() == 2) { - return filterStartingWith(new ArrayList<>(CustomFishing.getInstance().getEffectManager().getUtilItems().keySet()), args.get(1)); - } else if (args.size() == 3) { - return filterStartingWith(List.of("1", "2", "4", "8", "16", "32", "64"), args.get(2)); - } - return null; - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/data/PlayerSellData.java b/src/main/java/net/momirealms/customfishing/data/PlayerSellData.java deleted file mode 100644 index 33aed72d..00000000 --- a/src/main/java/net/momirealms/customfishing/data/PlayerSellData.java +++ /dev/null @@ -1,45 +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.data; - -public class PlayerSellData { - - private double money; - private int date; - - public PlayerSellData(double money, int date) { - this.money = money; - this.date = date; - } - - public double getMoney() { - return money; - } - - public void setMoney(double money) { - this.money = money; - } - - public int getDate() { - return date; - } - - public void setDate(int date) { - this.date = date; - } -} diff --git a/src/main/java/net/momirealms/customfishing/data/PlayerStatisticsData.java b/src/main/java/net/momirealms/customfishing/data/PlayerStatisticsData.java deleted file mode 100644 index 4b10d7f9..00000000 --- a/src/main/java/net/momirealms/customfishing/data/PlayerStatisticsData.java +++ /dev/null @@ -1,147 +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.data; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import org.bukkit.Bukkit; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -public class PlayerStatisticsData { - - private final ConcurrentHashMap amountMap; - private int total_catch_amount; - - public PlayerStatisticsData() { - this.amountMap = new ConcurrentHashMap<>(); - this.total_catch_amount = 0; - } - - public PlayerStatisticsData(ConfigurationSection section) { - this.amountMap = new ConcurrentHashMap<>(); - this.total_catch_amount = 0; - for (String key : section.getKeys(false)) { - int amount = section.getInt(key); - total_catch_amount += amount; - amountMap.put(key, amount); - } - } - - public PlayerStatisticsData(String longText) { - this.total_catch_amount = 0; - this.amountMap = (ConcurrentHashMap) Arrays.stream(longText.split(";")) - .map(element -> element.split(":")) - .filter(pair -> pair.length == 2) - .collect(Collectors.toConcurrentMap(pair -> pair[0], pair -> { - int amount = Integer.parseInt(pair[1]); - total_catch_amount += amount; - return amount; - })); - } - - public String getLongText() { - StringJoiner joiner = new StringJoiner(";"); - for (Map.Entry entry : amountMap.entrySet()) { - joiner.add(entry.getKey() + ":" + entry.getValue()); - } - return joiner.toString(); - } - - public void addFishAmount(LootImpl loot, UUID uuid, int amount) { - Integer previous = amountMap.get(loot.getKey()); - if (previous == null) previous = 0; - int after = previous + amount; - amountMap.put(loot.getKey(), after); - total_catch_amount += amount; - Player player = Bukkit.getPlayer(uuid); - if (player == null) return; - doSuccessTimesAction(previous, after, player, loot); - } - - private void doSuccessTimesAction(Integer previous, int after, Player player, LootImpl vanilla) { - HashMap actionMap = vanilla.getSuccessTimesActions(); - if (actionMap != null) { - for (Map.Entry entry : actionMap.entrySet()) { - if (entry.getKey() > previous && entry.getKey() <= after) { - for (Action action : entry.getValue()) { - action.doOn(player); - } - } - } - } - } - - public int getFishAmount(String key) { - Integer amount = amountMap.get(key); - return amount == null ? 0 : amount; - } - - public boolean hasFished(String key) { - return amountMap.containsKey(key); - } - - /** - * Get a category's unlock progress - * @param category category name - * @return percent - */ - public double getCategoryUnlockProgress(String category) { - List categories = CustomFishing.getInstance().getLootManager().getCategories(category); - if (categories == null) return -1d; - double total = categories.size(); - double unlocked = 0; - for (String value : categories) { - if (hasFished(value)) { - unlocked++; - } - } - return (unlocked / total) * 100d; - } - - public int getCategoryTotalFishAmount(String category) { - List categories = CustomFishing.getInstance().getLootManager().getCategories(category); - if (categories == null) return -1; - int total = 0; - for (String value : categories) { - total += getFishAmount(value); - } - return total; - } - - public void reset() { - amountMap.clear(); - } - - public ConcurrentHashMap getAmountMap() { - return amountMap; - } - - public void setData(String key, int value) { - amountMap.put(key, value); - } - - public int getTotalCatchAmount() { - return total_catch_amount; - } -} diff --git a/src/main/java/net/momirealms/customfishing/data/storage/DataStorageInterface.java b/src/main/java/net/momirealms/customfishing/data/storage/DataStorageInterface.java deleted file mode 100644 index b6564f7e..00000000 --- a/src/main/java/net/momirealms/customfishing/data/storage/DataStorageInterface.java +++ /dev/null @@ -1,42 +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.data.storage; - -import net.momirealms.customfishing.data.PlayerSellData; -import net.momirealms.customfishing.data.PlayerStatisticsData; -import org.bukkit.inventory.Inventory; - -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -public interface DataStorageInterface { - - void initialize(); - void disable(); - Inventory loadBagData(UUID uuid, boolean force); - void saveBagData(UUID uuid, Inventory inventory, boolean unlock); - void saveBagData(Set> set, boolean unlock); - PlayerSellData loadSellData(UUID uuid, boolean force); - void saveSellData(UUID uuid, PlayerSellData playerSellData, boolean unlock); - void saveSellData(Set> set, boolean unlock); - StorageType getStorageType(); - void saveStatistics(UUID uuid, PlayerStatisticsData statisticsData, boolean unlock); - void saveStatistics(Set> set, boolean unlock); - PlayerStatisticsData loadStatistics(UUID uuid, boolean force); -} diff --git a/src/main/java/net/momirealms/customfishing/data/storage/FileStorageImpl.java b/src/main/java/net/momirealms/customfishing/data/storage/FileStorageImpl.java deleted file mode 100644 index f68ba898..00000000 --- a/src/main/java/net/momirealms/customfishing/data/storage/FileStorageImpl.java +++ /dev/null @@ -1,149 +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.data.storage; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.data.PlayerSellData; -import net.momirealms.customfishing.data.PlayerStatisticsData; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.util.ConfigUtils; -import net.momirealms.customfishing.util.InventoryUtils; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -public class FileStorageImpl implements DataStorageInterface { - - private final CustomFishing plugin; - - public FileStorageImpl(CustomFishing plugin) { - this.plugin = plugin; - } - - @Override - public void initialize() { - - } - - @Override - public void disable() { - - } - - @Override - public Inventory loadBagData(UUID uuid, boolean force) { - YamlConfiguration config = ConfigUtils.readData(new File(plugin.getDataFolder(), "data" + File.separator + "fishingbag" + File.separator + uuid + ".yml")); - String contents = config.getString("contents"); - int size = config.getInt("size", 9); - ItemStack[] itemStacks = InventoryUtils.getInventoryItems(contents); - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); - Inventory inventory = InventoryUtils.createInventory(null, size, plugin.getIntegrationManager().getPlaceholderManager().parse(offlinePlayer, ConfigManager.fishingBagTitle)); - if (itemStacks != null) inventory.setContents(itemStacks); - return inventory; - } - - @Override - public void saveBagData(UUID uuid, Inventory inventory, boolean unlock) { - YamlConfiguration data = new YamlConfiguration(); - String contents = InventoryUtils.toBase64(inventory.getContents()); - data.set("contents", contents); - data.set("size", inventory.getSize()); - try { - data.save(new File(plugin.getDataFolder(), "data" + File.separator + "fishingbag" + File.separator + uuid + ".yml")); - } - catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void saveBagData(Set> set, boolean unlock) { - for (Map.Entry entry : set) { - saveBagData(entry.getKey(), entry.getValue(), unlock); - } - } - - - @Override - public PlayerSellData loadSellData(UUID uuid, boolean force) { - YamlConfiguration data = ConfigUtils.readData(new File(plugin.getDataFolder(), "data" + File.separator + "sell" + File.separator + uuid + ".yml")); - int date = data.getInt("date"); - double money = data.getDouble("earnings"); - return new PlayerSellData(money, date); - } - - @Override - public void saveSellData(UUID uuid, PlayerSellData playerSellData, boolean unlock) { - YamlConfiguration data = new YamlConfiguration(); - data.set("date", playerSellData.getDate()); - data.set("earnings", playerSellData.getMoney()); - try { - data.save(new File(plugin.getDataFolder(), "data" + File.separator + "sell" + File.separator + uuid + ".yml")); - } - catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void saveSellData(Set> set, boolean unlock) { - for (Map.Entry entry : set) { - saveSellData(entry.getKey(), entry.getValue(), unlock); - } - } - - @Override - public StorageType getStorageType() { - return StorageType.YAML; - } - - @Override - public void saveStatistics(UUID uuid, PlayerStatisticsData statisticsData, boolean unlock) { - YamlConfiguration data = new YamlConfiguration(); - for (Map.Entry entry : statisticsData.getAmountMap().entrySet()) { - data.set(entry.getKey(), entry.getValue()); - } - try { - data.save(new File(plugin.getDataFolder(), "data" + File.separator + "statistics" + File.separator + uuid + ".yml")); - } - catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void saveStatistics(Set> set, boolean unlock) { - for (Map.Entry entry : set) { - saveStatistics(entry.getKey(), entry.getValue(), unlock); - } - } - - @Override - public PlayerStatisticsData loadStatistics(UUID uuid, boolean force) { - YamlConfiguration data = ConfigUtils.readData(new File(plugin.getDataFolder(), "data" + File.separator + "statistics" + File.separator + uuid + ".yml")); - return new PlayerStatisticsData(data); - } -} diff --git a/src/main/java/net/momirealms/customfishing/data/storage/MySQLStorageImpl.java b/src/main/java/net/momirealms/customfishing/data/storage/MySQLStorageImpl.java deleted file mode 100644 index cf1e021c..00000000 --- a/src/main/java/net/momirealms/customfishing/data/storage/MySQLStorageImpl.java +++ /dev/null @@ -1,360 +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.data.storage; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.data.PlayerSellData; -import net.momirealms.customfishing.data.PlayerStatisticsData; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.InventoryUtils; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Calendar; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -public class MySQLStorageImpl implements DataStorageInterface { - - private final SqlConnection sqlConnection; - private final CustomFishing plugin; - - public MySQLStorageImpl(CustomFishing plugin) { - this.plugin = plugin; - this.sqlConnection = new SqlConnection(this); - } - - @Override - public void initialize() { - sqlConnection.createNewHikariConfiguration(); - createTableIfNotExist(sqlConnection.getTablePrefix() + "_fishingbag", SqlConstants.SQL_CREATE_BAG_TABLE); - createTableIfNotExist(sqlConnection.getTablePrefix() + "_selldata", SqlConstants.SQL_CREATE_SELL_TABLE); - createTableIfNotExist(sqlConnection.getTablePrefix() + "_statistics", SqlConstants.SQL_CREATE_STATS_TABLE); - } - - @Override - public void disable() { - sqlConnection.close(); - } - - @Override - public StorageType getStorageType() { - return StorageType.SQL; - } - - @Override - public Inventory loadBagData(UUID uuid, boolean force) { - Inventory inventory = null; - String sql = String.format(SqlConstants.SQL_SELECT_BY_UUID, sqlConnection.getTablePrefix() + "_" + "fishingbag"); - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, uuid.toString()); - ResultSet rs = statement.executeQuery(); - if (rs.next()) { - int version = rs.getInt(2); - if (!force && version != 0) { - statement.close(); - connection.close(); - return null; - } - int size = rs.getInt(3); - String contents = rs.getString(4); - ItemStack[] itemStacks = InventoryUtils.getInventoryItems(contents); - inventory = InventoryUtils.createInventory(null, size, plugin.getIntegrationManager().getPlaceholderManager().parse(offlinePlayer, ConfigManager.fishingBagTitle)); - if (itemStacks != null) inventory.setContents(itemStacks); - lockData(uuid, "fishingbag"); - } - else { - inventory = InventoryUtils.createInventory(null, 9, plugin.getIntegrationManager().getPlaceholderManager().parse(offlinePlayer, ConfigManager.fishingBagTitle)); - insertBagData(uuid, InventoryUtils.toBase64(inventory.getContents())); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return inventory; - } - - @Override - public void saveBagData(UUID uuid, Inventory inventory, boolean unlock) { - updateBagData(uuid, inventory.getSize(), InventoryUtils.toBase64(inventory.getContents()), unlock); - } - - @Override - public void saveBagData(Set> set, boolean unlock) { - String sql = String.format(SqlConstants.SQL_UPDATE_BAG_BY_UUID, sqlConnection.getTablePrefix() + "_" + "fishingbag"); - try (Connection connection = sqlConnection.getConnectionAndCheck()) { - connection.setAutoCommit(false); - try (PreparedStatement statement = connection.prepareStatement(sql)) { - for (Map.Entry entry : set) { - statement.setInt(1, unlock ? 0 : 1); - statement.setInt(2, entry.getValue().getSize()); - statement.setString(3, InventoryUtils.toBase64(entry.getValue().getContents())); - statement.setString(4, entry.getKey().toString()); - statement.addBatch(); - } - statement.executeBatch(); - connection.commit(); - } - catch (SQLException ex) { - connection.rollback(); - AdventureUtils.consoleMessage("[CustomFishing] Failed to update bag data for online players"); - } - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to get connection"); - } - } - - @Override - public PlayerSellData loadSellData(UUID uuid, boolean force) { - PlayerSellData playerSellData = null; - String sql = String.format(SqlConstants.SQL_SELECT_BY_UUID, sqlConnection.getTablePrefix() + "_" + "selldata"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, uuid.toString()); - ResultSet rs = statement.executeQuery(); - if (rs.next()) { - int version = rs.getInt(2); - if (!force && version != 0) { - statement.close(); - connection.close(); - return null; - } - int date = rs.getInt(3); - int money = rs.getInt(4); - playerSellData = new PlayerSellData(money, date); - lockData(uuid, "selldata"); - } - else { - Calendar calendar = Calendar.getInstance(); - playerSellData = new PlayerSellData(0, (calendar.get(Calendar.MONTH) +1)* 100 + calendar.get(Calendar.DATE)); - insertSellData(uuid, playerSellData.getDate()); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return playerSellData; - } - - @Override - public void saveSellData(UUID uuid, PlayerSellData playerSellData, boolean unlock) { - updateSellData(uuid, playerSellData.getDate(), (int) playerSellData.getMoney(), unlock); - } - - @Override - public void saveSellData(Set> set, boolean unlock) { - String sql = String.format(SqlConstants.SQL_UPDATE_SELL_BY_UUID, sqlConnection.getTablePrefix() + "_" + "selldata"); - try (Connection connection = sqlConnection.getConnectionAndCheck()) { - connection.setAutoCommit(false); - try (PreparedStatement statement = connection.prepareStatement(sql)) { - for (Map.Entry entry : set) { - statement.setInt(1, unlock ? 0 : 1); - statement.setInt(2, entry.getValue().getDate()); - statement.setInt(3, (int) entry.getValue().getMoney()); - statement.setString(4, entry.getKey().toString()); - statement.addBatch(); - } - statement.executeBatch(); - connection.commit(); - } - catch (SQLException ex) { - connection.rollback(); - AdventureUtils.consoleMessage("[CustomFishing] Failed to update sell data for all the players"); - } - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to get connection"); - } - } - - @Override - public PlayerStatisticsData loadStatistics(UUID uuid, boolean force) { - PlayerStatisticsData playerStatisticsData = null; - String sql = String.format(SqlConstants.SQL_SELECT_BY_UUID, sqlConnection.getTablePrefix() + "_" + "statistics"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, uuid.toString()); - ResultSet rs = statement.executeQuery(); - if (rs.next()) { - int version = rs.getInt(2); - if (!force && version != 0) { - statement.close(); - connection.close(); - return null; - } - String longText = rs.getString(3); - playerStatisticsData = new PlayerStatisticsData(longText); - lockData(uuid, "statistics"); - } - else { - playerStatisticsData = new PlayerStatisticsData(); - insertStatisticsData(uuid); - } - } catch (SQLException e) { - e.printStackTrace(); - } - return playerStatisticsData; - } - - @Override - public void saveStatistics(UUID uuid, PlayerStatisticsData statisticsData, boolean unlock) { - updateStatisticsData(uuid, statisticsData.getLongText(), unlock); - } - - @Override - public void saveStatistics(Set> set, boolean unlock) { - String sql = String.format(SqlConstants.SQL_UPDATE_STATS_BY_UUID, sqlConnection.getTablePrefix() + "_" + "statistics"); - try (Connection connection = sqlConnection.getConnectionAndCheck()) { - connection.setAutoCommit(false); - try (PreparedStatement statement = connection.prepareStatement(sql)) { - for (Map.Entry entry : set) { - statement.setInt(1, unlock ? 0 : 1); - statement.setString(2, entry.getValue().getLongText()); - statement.setString(3, entry.getKey().toString()); - statement.addBatch(); - } - statement.executeBatch(); - connection.commit(); - } - catch (SQLException ex) { - connection.rollback(); - AdventureUtils.consoleMessage("[CustomFishing] Failed to update statistics data for online players"); - } - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to get connection"); - } - } - - private void createTableIfNotExist(String table, String sqlStat) { - String sql = String.format(sqlStat, table); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to create table"); - } - } - - private void insertBagData(UUID uuid, String contents) { - String sql = String.format(SqlConstants.SQL_INSERT_BAG, sqlConnection.getTablePrefix() + "_" + "fishingbag"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, uuid.toString()); - statement.setInt(2, 1); - statement.setInt(3, 9); - statement.setString(4, contents); - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to insert data for " + uuid); - } - } - - private void insertSellData(UUID uuid, int date) { - String sql = String.format(SqlConstants.SQL_INSERT_SELL, sqlConnection.getTablePrefix() + "_" + "selldata"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, uuid.toString()); - statement.setInt(2, 1); - statement.setInt(3, date); - statement.setInt(4, 0); - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to insert data for " + uuid); - } - } - - private void insertStatisticsData(UUID uuid) { - String sql = String.format(SqlConstants.SQL_INSERT_STATS, sqlConnection.getTablePrefix() + "_" + "statistics"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, uuid.toString()); - statement.setInt(2, 1); - statement.setString(3, ""); - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to insert data for " + uuid); - } - } - - private void updateBagData(UUID uuid, int size, String contents, boolean unlock) { - String sql = String.format(SqlConstants.SQL_UPDATE_BAG_BY_UUID, sqlConnection.getTablePrefix() + "_" + "fishingbag"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setInt(1, unlock ? 0 : 1); - statement.setInt(2, size); - statement.setString(3, contents); - statement.setString(4, uuid.toString()); - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to update data for " + uuid); - } - } - - private void updateSellData(UUID uuid, int date, int money, boolean unlock) { - String sql = String.format(SqlConstants.SQL_UPDATE_SELL_BY_UUID, sqlConnection.getTablePrefix() + "_" + "selldata"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setInt(1, unlock ? 0 : 1); - statement.setInt(2, date); - statement.setInt(3, money); - statement.setString(4, uuid.toString()); - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to update data for " + uuid); - } - } - - private void updateStatisticsData(UUID uuid, String longText, boolean unlock) { - String sql = String.format(SqlConstants.SQL_UPDATE_STATS_BY_UUID, sqlConnection.getTablePrefix() + "_" + "statistics"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setInt(1, unlock ? 0 : 1); - statement.setString(2, longText); - statement.setString(3, uuid.toString()); - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to update data for " + uuid); - } - } - - public void migrate() { - String sql_1 = String.format(SqlConstants.SQL_ALTER_TABLE, sqlConnection.getTablePrefix() + "_" + "fishingbag"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql_1)) { - statement.executeUpdate(); - AdventureUtils.consoleMessage("[CustomFishing] Tables updated"); - } catch (SQLException ex) { - AdventureUtils.consoleMessage(ex.getSQLState()); - AdventureUtils.consoleMessage("[CustomFishing] Failed to migrate data"); - } - String sql_2 = String.format(SqlConstants.SQL_DROP_TABLE, sqlConnection.getTablePrefix() + "_" + "sellcache"); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql_2)) { - statement.executeUpdate(); - AdventureUtils.consoleMessage("[CustomFishing] Outdated table deleted"); - } catch (SQLException ex) { - AdventureUtils.consoleMessage(ex.getSQLState()); - AdventureUtils.consoleMessage("[CustomFishing] Failed to migrate data"); - } - } - - public void lockData(UUID uuid, String table_suffix) { - String sql = String.format(SqlConstants.SQL_LOCK_BY_UUID, sqlConnection.getTablePrefix() + "_" + table_suffix); - try (Connection connection = sqlConnection.getConnectionAndCheck(); PreparedStatement statement = connection.prepareStatement(sql);) { - statement.setString(1, uuid.toString()); - statement.executeUpdate(); - } catch (SQLException ex) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to lock data for " + uuid); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/data/storage/SqlConnection.java b/src/main/java/net/momirealms/customfishing/data/storage/SqlConnection.java deleted file mode 100644 index 9c67b76a..00000000 --- a/src/main/java/net/momirealms/customfishing/data/storage/SqlConnection.java +++ /dev/null @@ -1,169 +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.data.storage; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import com.zaxxer.hikari.pool.HikariPool; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ConfigUtils; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.io.IOException; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.ArrayList; - -public class SqlConnection { - - private boolean secondTry = false; - private boolean firstTry = false; - private HikariDataSource hikariDataSource; - private String tablePrefix; - private final MySQLStorageImpl mySQLStorage; - - public SqlConnection(MySQLStorageImpl mySQLStorage) { - this.mySQLStorage = mySQLStorage; - } - - public void createNewHikariConfiguration() { - ConfigUtils.update("database.yml", new ArrayList<>()); - YamlConfiguration config = ConfigUtils.getConfig("database.yml"); - String storageMode = config.getString("data-storage-method", "MySQL"); - HikariConfig hikariConfig = new HikariConfig(); - String sql = "mysql"; - if (storageMode.equalsIgnoreCase("MariaDB")) { - try { - Class.forName("org.mariadb.jdbc.Driver"); - } catch (ClassNotFoundException e1) { - AdventureUtils.consoleMessage("[CustomFishing] No sql driver is found."); - } - hikariConfig.setDriverClassName("org.mariadb.jdbc.Driver"); - sql = "mariadb"; - } else { - try { - Class.forName("com.mysql.jdbc.Driver"); - } catch (ClassNotFoundException e1) { - try { - Class.forName("com.mysql.cj.jdbc.Driver"); - } catch (ClassNotFoundException e2) { - AdventureUtils.consoleMessage("[CustomFishing] No sql driver is found."); - } - } - } - tablePrefix = config.getString(storageMode + ".table-prefix"); - hikariConfig.setPoolName("[CustomFishing]"); - hikariConfig.setJdbcUrl("jdbc:" + sql + "://" + config.getString(storageMode + ".host") + ":" + config.getString(storageMode + ".port") + "/" + config.getString(storageMode + ".database")); - hikariConfig.setUsername(config.getString(storageMode + ".user")); - hikariConfig.setPassword(config.getString(storageMode + ".password")); - hikariConfig.setMaximumPoolSize(config.getInt(storageMode + ".Pool-Settings.maximum-pool-size")); - hikariConfig.setMinimumIdle(config.getInt(storageMode + ".Pool-Settings.minimum-idle")); - hikariConfig.setMaxLifetime(config.getInt(storageMode + ".Pool-Settings.maximum-lifetime")); - hikariConfig.setConnectionTimeout(3000); - hikariConfig.setIdleTimeout(hikariConfig.getMinimumIdle() < hikariConfig.getMaximumPoolSize() ? config.getInt(storageMode + ".Pool-Settings.idle-timeout") : 0); - ConfigurationSection section = config.getConfigurationSection(storageMode + ".properties"); - if (section != null) { - for (String property : section.getKeys(false)) { - hikariConfig.addDataSourceProperty(property, config.getString(storageMode + ".properties." + property)); - } - } - try { - hikariDataSource = new HikariDataSource(hikariConfig); - } catch (HikariPool.PoolInitializationException e) { - AdventureUtils.consoleMessage("[CustomFishing] Failed to create sql connection"); - } - - if (config.getBoolean("migration", false)) { - mySQLStorage.migrate(); - config.set("migration", false); - try { - config.save(new File(CustomFishing.getInstance().getDataFolder(), "database.yml")); - } - catch (IOException e) { - AdventureUtils.consoleMessage("[CustomFishing] Error occurred when saving database config"); - } - } - } - - public boolean setGlobalConnection() { - try { - createNewHikariConfiguration(); - Connection connection = getConnection(); - connection.close(); - if (secondTry) { - AdventureUtils.consoleMessage("[CustomFishing] Successfully reconnect to SQL!"); - } else { - secondTry = true; - } - return true; - } catch (SQLException e) { - AdventureUtils.consoleMessage("[CustomFishing] Error! Failed to connect to SQL!"); - e.printStackTrace(); - close(); - return false; - } - } - - public Connection getConnection() throws SQLException { - return hikariDataSource.getConnection(); - } - - public boolean canConnect() { - if (hikariDataSource == null) { - return setGlobalConnection(); - } - if (hikariDataSource.isClosed()) { - return setGlobalConnection(); - } - return true; - } - - public void close() { - if (hikariDataSource != null && hikariDataSource.isRunning()) { - hikariDataSource.close(); - } - } - - public String getTablePrefix() { - return tablePrefix; - } - - public Connection getConnectionAndCheck() { - if (!canConnect()) { - return null; - } - try { - return getConnection(); - } catch (SQLException e) { - if (firstTry) { - firstTry = false; - close(); - return getConnectionAndCheck(); - } else { - firstTry = true; - AdventureUtils.consoleMessage("[CustomFishing] Error! Failed to connect to SQL!"); - close(); - e.printStackTrace(); - return null; - } - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/data/storage/SqlConstants.java b/src/main/java/net/momirealms/customfishing/data/storage/SqlConstants.java deleted file mode 100644 index c6ac6c29..00000000 --- a/src/main/java/net/momirealms/customfishing/data/storage/SqlConstants.java +++ /dev/null @@ -1,35 +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.data.storage; - -public class SqlConstants { - - public static final String SQL_CREATE_BAG_TABLE = "CREATE TABLE IF NOT EXISTS `%s` ( `uuid` VARCHAR(36) NOT NULL, `version` INT NOT NULL, `size` INT NOT NULL, `contents` LONGTEXT NOT NULL, PRIMARY KEY (`uuid`) )"; - public static final String SQL_CREATE_SELL_TABLE = "CREATE TABLE IF NOT EXISTS `%s` ( `uuid` VARCHAR(36) NOT NULL, `version` INT NOT NULL, `date` INT NOT NULL, `money` INT NOT NULL, PRIMARY KEY (`uuid`) )"; - public static final String SQL_CREATE_STATS_TABLE = "CREATE TABLE IF NOT EXISTS `%s` ( `uuid` VARCHAR(36) NOT NULL, `version` INT NOT NULL, `stats` LONGTEXT NOT NULL, PRIMARY KEY (`uuid`) )"; - public static final String SQL_INSERT_BAG = "INSERT INTO `%s`(`uuid`, `version`, `size`, `contents`) VALUES (?, ?, ?, ?)"; - public static final String SQL_INSERT_SELL = "INSERT INTO `%s`(`uuid`, `version`, `date`, `money`) VALUES (?, ?, ?, ?)"; - public static final String SQL_INSERT_STATS = "INSERT INTO `%s`(`uuid`, `version`, `stats`) VALUES (?, ?, ?)"; - public static final String SQL_UPDATE_BAG_BY_UUID = "UPDATE `%s` SET `version` = ?, `size` = ?, `contents` = ? WHERE `uuid` = ?"; - public static final String SQL_UPDATE_SELL_BY_UUID = "UPDATE `%s` SET `version` = ?, `date` = ?, `money` = ? WHERE `uuid` = ?"; - public static final String SQL_UPDATE_STATS_BY_UUID = "UPDATE `%s` SET `version` = ?, `stats` = ? WHERE `uuid` = ?"; - public static final String SQL_SELECT_BY_UUID = "SELECT * FROM `%s` WHERE `uuid` = ?"; - public static final String SQL_LOCK_BY_UUID = "UPDATE `%s` SET `version` = 1 WHERE `uuid` = ?"; - public static final String SQL_ALTER_TABLE = "ALTER TABLE `%s` ADD COLUMN `version` INT NOT NULL AFTER `uuid`"; - public static final String SQL_DROP_TABLE = "DROP TABLE `%s`"; -} diff --git a/src/main/java/net/momirealms/customfishing/data/storage/StorageType.java b/src/main/java/net/momirealms/customfishing/data/storage/StorageType.java deleted file mode 100644 index 26ccd7e6..00000000 --- a/src/main/java/net/momirealms/customfishing/data/storage/StorageType.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.momirealms.customfishing.data.storage; - -public enum StorageType { - SQL, - YAML -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/BobberCheckTask.java b/src/main/java/net/momirealms/customfishing/fishing/BobberCheckTask.java deleted file mode 100644 index 74d6d07c..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/BobberCheckTask.java +++ /dev/null @@ -1,246 +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.fishing; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.manager.FishingManager; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ArmorStandUtils; -import net.momirealms.customfishing.util.FakeItemUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class BobberCheckTask implements Runnable { - - private final CustomFishing plugin; - - private final ScheduledFuture bobberTask; - private ScheduledFuture getHookedTask; - private ScheduledFuture resetTask; - private final FishHook fishHook; - private final Player player; - private final Effect effect; - private final String rod; - private final String bait; - private final FishingManager fishingManager; - private boolean hooked; - private boolean reserve; - private boolean land; - private boolean first; - private int timer; - private int jump_timer; - private final int entityID; - private final int lureLevel; - private LavaEffect lavaEffect; - private ArmorStand hookedEntity; - - public BobberCheckTask(CustomFishing plugin, Player player, Effect effect, FishHook fishHook, FishingManager fishingManager, int lureLevel, int entityID, String rod, String bait) { - this.fishHook = fishHook; - this.plugin = plugin; - this.fishingManager = fishingManager; - this.player = player; - this.timer = 0; - this.effect = effect; - this.reserve = true; - this.jump_timer = 0; - this.lureLevel = lureLevel; - this.entityID = entityID; - this.land = false; - this.first = true; - this.rod = rod; - this.bait = bait; - this.bobberTask = plugin.getScheduler().runTaskTimer(this, 50, 50, TimeUnit.MILLISECONDS); - } - - @Override - public void run() { - timer ++; - if (!land && entityID != 0) { - CustomFishing.getProtocolManager().sendServerPacket(player, FakeItemUtils.getVelocity(entityID, fishHook.getVelocity())); - CustomFishing.getProtocolManager().sendServerPacket(player, FakeItemUtils.getTpPacket(entityID, fishHook.getLocation())); - } - if (timer > 3600) { - stop(); - return; - } - if (fishHook.getHookedEntity() != null && fishHook.getHookedEntity().getType() != EntityType.ARMOR_STAND) { - stop(); - return; - } - if (!fishHook.isValid()) { - stop(); - return; - } - if (fishHook.getLocation().getBlock().getType() == Material.LAVA) { - land = true; - if (!effect.canLavaFishing()) { - stop(); - return; - } - if (first) { - sendRemovePacket(); - ArmorStandUtils.sendAnimationToPlayer(fishHook.getLocation(), player, ConfigManager.lava_item, ConfigManager.lava_time); - first = false; - } - if (hooked) { - jump_timer++; - if (jump_timer < 4) { - return; - } - jump_timer = 0; - fishHook.setVelocity(new Vector(0,0.24,0)); - return; - } - if (reserve) { - if (jump_timer < 5) { - jump_timer++; - fishHook.setVelocity(new Vector(0,0.2 - jump_timer * 0.02,0)); - return; - } - reserve = false; - randomTime(); - if (plugin.getVersionHelper().isFolia()) { - plugin.getScheduler().runTask(() -> spawnArmorStand(fishHook.getLocation()), fishHook.getLocation()); - } else { - spawnArmorStand(fishHook.getLocation()); - } - } - return; - } - if (fishHook.isInWater()) { - stop(); - plugin.getScheduler().runTaskAsync(() -> { - List possibleLoots = new ArrayList<>(); - if (!(ConfigManager.needRodForLoot && !effect.hasSpecialRod())) { - possibleLoots = fishingManager.getPossibleLootList(new FishingCondition(fishHook.getLocation(), player, rod, bait), false, plugin.getLootManager().getWaterLoots().values()); - } - fishingManager.getNextLoot(player, effect, possibleLoots); - if (ConfigManager.enableWaterAnimation) { - ArmorStandUtils.sendAnimationToPlayer(fishHook.getLocation(), player, ConfigManager.water_item, ConfigManager.water_time); - } - }); - return; - } - if (fishHook.isOnGround()) { - stop(); - } - } - - public void stop() { - bobberTask.cancel(false); - cancelSubTask(); - fishingManager.removePlayerFromLavaFishing(player); - if (hookedEntity != null && !hookedEntity.isDead()) { - if (plugin.getVersionHelper().isFolia()) { - plugin.getScheduler().runTask(() -> { - hookedEntity.remove(); hookedEntity = null; - }, hookedEntity.getLocation()); - } else { - hookedEntity.remove(); - hookedEntity = null; - } - } - sendRemovePacket(); - } - - private void sendRemovePacket() { - if (entityID == 0) return; - CustomFishing.getProtocolManager().sendServerPacket(player, FakeItemUtils.getDestroyPacket(entityID)); - } - - public void cancelSubTask() { - if (getHookedTask != null && !lavaEffect.isCancelled()) { - getHookedTask.cancel(false); - getHookedTask = null; - } - if (resetTask != null && !lavaEffect.isCancelled()) { - resetTask.cancel(false); - resetTask = null; - } - if (lavaEffect != null && !lavaEffect.isCancelled()) { - lavaEffect.cancel(); - lavaEffect = null; - } - } - - private void randomTime() { - plugin.getScheduler().runTaskAsync(() -> { - List possibleLoots = new ArrayList<>(); - if (!(ConfigManager.needRodForLoot && !effect.hasSpecialRod())) { - possibleLoots = fishingManager.getPossibleLootList(new FishingCondition(fishHook.getLocation(), player, rod, bait), false, plugin.getLootManager().getLavaLoots().values()); - } - fishingManager.getNextLoot(player, effect, possibleLoots); - }); - cancelSubTask(); - int random = new Random().nextInt(ConfigManager.lavaMaxTime) + ConfigManager.lavaMinTime; - random -= lureLevel * 100; - random *= effect.getTimeModifier(); - if (random < ConfigManager.lavaMinTime) random = ConfigManager.lavaMinTime; - getHookedTask = plugin.getScheduler().runTaskLater(() -> { - hooked = true; - if (hookedEntity != null && !hookedEntity.isDead()) { - if (plugin.getVersionHelper().isFolia()) { - plugin.getScheduler().runTask(() -> hookedEntity.remove(), hookedEntity.getLocation()); - } else { - hookedEntity.remove(); - } - } - AdventureUtils.playerSound(player, Sound.Source.NEUTRAL, Key.key("minecraft:block.pointed_dripstone.drip_lava_into_cauldron"), 1, 1); - if (ConfigManager.instantBar) fishingManager.showBar(player); - }, random * 50L, TimeUnit.MILLISECONDS); - resetTask = plugin.getScheduler().runTaskAsyncLater(() -> { - hooked = false; - reserve = true; - }, (random + 40) * 50L, TimeUnit.MILLISECONDS); - lavaEffect = new LavaEffect(fishHook.getLocation(), random - 60); - } - - private void spawnArmorStand(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); - }); - fishHook.setHookedEntity(hookedEntity); - } - - public boolean isHooked() { - return hooked; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/Effect.java b/src/main/java/net/momirealms/customfishing/fishing/Effect.java deleted file mode 100644 index f6a9369b..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/Effect.java +++ /dev/null @@ -1,163 +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.fishing; - -import net.momirealms.customfishing.fishing.requirements.RequirementInterface; -import net.momirealms.customfishing.manager.ConfigManager; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -public class Effect { - - private HashMap weightMD; - private HashMap weightAS; - private double timeModifier; - private double sizeMultiplier; - private double scoreMultiplier; - private int difficulty; - private double doubleLootChance; - private boolean canLavaFishing; - private String specialRodID; - private RequirementInterface[] requirements; - - public Effect() { - this.sizeMultiplier = 1; - this.scoreMultiplier = 1; - this.timeModifier = 1; - } - - public void setSizeMultiplier(double sizeMultiplier) { - this.sizeMultiplier = sizeMultiplier; - } - - public HashMap getWeightMD() { - return weightMD; - } - - public void setWeightMD(HashMap weightMD) { - this.weightMD = weightMD; - } - - public HashMap getWeightAS() { - return weightAS; - } - - public void setWeightAS(HashMap weightAS) { - this.weightAS = weightAS; - } - - public double getTimeModifier() { - return timeModifier; - } - - public void setTimeModifier(double timeModifier) { - this.timeModifier = timeModifier; - } - - public void setScoreMultiplier(double scoreMultiplier) { - this.scoreMultiplier = scoreMultiplier; - } - - public int getDifficulty() { - return difficulty; - } - - public void setDifficulty(int difficulty) { - this.difficulty = difficulty; - } - - public double getDoubleLootChance() { - return doubleLootChance; - } - - public void setDoubleLootChance(double doubleLootChance) { - this.doubleLootChance = doubleLootChance; - } - - public boolean canLavaFishing() { - return canLavaFishing || ConfigManager.allRodsFishInLava; - } - - public void setCanLavaFishing(boolean canLavaFishing) { - this.canLavaFishing = canLavaFishing; - } - - public RequirementInterface[] getRequirements() { - return requirements; - } - - public void setRequirements(RequirementInterface[] requirements) { - this.requirements = requirements; - } - - public void addEffect(Effect anotherEffect) { - HashMap weightAS = anotherEffect.getWeightAS(); - if (weightAS != null) { - for (Map.Entry en : weightAS.entrySet()) { - String group = en.getKey(); - this.weightAS.put(group, Optional.ofNullable(this.weightAS.get(group)).orElse(0) + en.getValue()); - } - } - HashMap weightMD = anotherEffect.getWeightMD(); - if (weightMD != null){ - for (Map.Entry en : weightMD.entrySet()) { - String group = en.getKey(); - this.weightMD.put(group, Optional.ofNullable(this.weightMD.get(group)).orElse(1d) + en.getValue()); - } - } - this.timeModifier += (anotherEffect.getTimeModifier() - 1); - this.scoreMultiplier += (anotherEffect.getScoreMultiplier() - 1); - this.sizeMultiplier += (anotherEffect.getSizeMultiplier() - 1); - this.doubleLootChance += anotherEffect.getDoubleLootChance(); - this.difficulty += anotherEffect.getDifficulty(); - if (anotherEffect.canLavaFishing()) this.canLavaFishing = true; - } - - public boolean canAddEffect(Effect anotherEffect, FishingCondition fishingCondition) { - if (anotherEffect.getRequirements() != null) { - for (RequirementInterface requirement : anotherEffect.getRequirements()) { - if (!requirement.isConditionMet(fishingCondition)) { - return false; - } - } - } - return true; - } - - public double getScoreMultiplier() { - return scoreMultiplier; - } - - public double getSizeMultiplier() { - return sizeMultiplier; - } - - public boolean hasSpecialRod() { - return specialRodID != null; - } - - public void setSpecialRodID(String specialRodID) { - this.specialRodID = specialRodID; - } - - public String getSpecialRodID() { - return specialRodID; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/FishMeta.java b/src/main/java/net/momirealms/customfishing/fishing/FishMeta.java deleted file mode 100644 index a728e591..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/FishMeta.java +++ /dev/null @@ -1,4 +0,0 @@ -package net.momirealms.customfishing.fishing; - -public record FishMeta(float size, float base, float bonus) { -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/FishResult.java b/src/main/java/net/momirealms/customfishing/fishing/FishResult.java deleted file mode 100644 index c2d55265..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/FishResult.java +++ /dev/null @@ -1,26 +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.fishing; - -public enum FishResult { - - FAILURE, - CATCH_MOB, - CATCH_SPECIAL_ITEM, - CATCH_VANILLA_ITEM -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/FishingCondition.java b/src/main/java/net/momirealms/customfishing/fishing/FishingCondition.java deleted file mode 100644 index c7dd729d..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/FishingCondition.java +++ /dev/null @@ -1,93 +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.fishing; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.requirements.CustomPapi; -import net.momirealms.customfishing.integration.papi.PlaceholderManager; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; - -public class FishingCondition{ - - private final Location location; - private final Player player; - private final String rodID; - private final String baitID; - private final HashMap papiMap; - - public FishingCondition(Location location, Player player, @Nullable String rodID, @Nullable String baitID) { - this.location = location; - this.player = player; - this.rodID = rodID; - this.baitID = baitID; - this.papiMap = new HashMap<>(); - if (player != null) { - PlaceholderManager placeholderManager = CustomFishing.getInstance().getIntegrationManager().getPlaceholderManager(); - for (String papi : CustomPapi.allPapi) { - this.papiMap.put(papi, placeholderManager.parse(player, papi)); - } - } - } - - public FishingCondition(Location location, Player player) { - this.location = location; - this.player = player; - this.rodID = null; - this.baitID = null; - this.papiMap = new HashMap<>(); - if (player != null) { - PlaceholderManager placeholderManager = CustomFishing.getInstance().getIntegrationManager().getPlaceholderManager(); - for (String papi : CustomPapi.allPapi) { - this.papiMap.put(papi, placeholderManager.parse(player, papi)); - } - } - } - - public HashMap getPapiMap() { - return papiMap; - } - - public Location getLocation() { - return location; - } - - public Player getPlayer() { - return player; - } - - public String getRodID() { - return rodID; - } - - public String getBaitID() { - return baitID; - } - - @Override - public String toString() { - return "FishingCondition{" + - "location=" + location + - ", player=" + player + - ", papiMap=" + papiMap + - '}'; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/MiniGameConfig.java b/src/main/java/net/momirealms/customfishing/fishing/MiniGameConfig.java deleted file mode 100644 index 9f2a5cf7..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/MiniGameConfig.java +++ /dev/null @@ -1,47 +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.fishing; - -import net.momirealms.customfishing.fishing.bar.FishingBar; - -import java.util.Random; - -public class MiniGameConfig { - - private final int time; - private final FishingBar[] bars; - private final int[] difficulties; - - public MiniGameConfig(int time, FishingBar[] bars, int[] difficulties) { - this.time = time; - this.bars = bars; - this.difficulties = difficulties; - } - - public FishingBar getRandomBar() { - return bars[new Random().nextInt(bars.length)]; - } - - public int getRandomDifficulty() { - return difficulties[new Random().nextInt(difficulties.length)]; - } - - public int getTime() { - return this.time; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/Action.java b/src/main/java/net/momirealms/customfishing/fishing/action/Action.java deleted file mode 100644 index 58f7e2f5..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/Action.java +++ /dev/null @@ -1,35 +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.fishing.action; - -import net.momirealms.customfishing.fishing.FishMeta; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public interface Action { - - void doOn(Player player, @Nullable Player anotherPlayer, @Nullable FishMeta fishMeta); - - default void doOn(Player player) { - doOn(player, null, null); - } - - default void doOn(Player player, Player anotherPlayer) { - doOn(player, anotherPlayer, null); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/ChainImpl.java b/src/main/java/net/momirealms/customfishing/fishing/action/ChainImpl.java deleted file mode 100644 index 8d417c9b..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/ChainImpl.java +++ /dev/null @@ -1,40 +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.fishing.action; - -import net.momirealms.customfishing.fishing.FishMeta; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public class ChainImpl extends AbstractAction implements Action { - - private final Action[] actions; - - public ChainImpl(Action[] actions, double chance) { - super(chance); - this.actions = actions; - } - - @Override - public void doOn(Player player, @Nullable Player anotherPlayer, @Nullable FishMeta fishMeta) { - if (!canExecute()) return; - for (Action action : actions) { - action.doOn(player, anotherPlayer, fishMeta); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/CommandActionImpl.java b/src/main/java/net/momirealms/customfishing/fishing/action/CommandActionImpl.java deleted file mode 100644 index 087b800d..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/CommandActionImpl.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.fishing.action; - -import net.momirealms.customfishing.fishing.FishMeta; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public class CommandActionImpl extends AbstractAction implements Action { - - private final String[] commands; - private final String nick; - - public CommandActionImpl(String[] commands, @Nullable String nick, double chance) { - super(chance); - this.commands = commands; - this.nick = nick == null ? "" : nick; - } - - @Override - public void doOn(Player player, @Nullable Player anotherPlayer, @Nullable FishMeta fishMeta) { - if (!canExecute()) return; - for (String command : commands) { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), - command.replace("{player}", player.getName()) - .replace("{x}", String.valueOf(player.getLocation().getBlockX())) - .replace("{y}", String.valueOf(player.getLocation().getBlockY())) - .replace("{z}", String.valueOf(player.getLocation().getBlockZ())) - .replace("{loot}", nick) - .replace("{world}", player.getWorld().getName()) - .replace("{activator}", anotherPlayer == null ? "" : anotherPlayer.getName()) - .replace("{size}", fishMeta == null ? "" : String.format("%.2f", fishMeta.size())) - ); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/JobXPImpl.java b/src/main/java/net/momirealms/customfishing/fishing/action/JobXPImpl.java deleted file mode 100644 index 5b201fe9..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/JobXPImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.momirealms.customfishing.fishing.action; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishMeta; -import net.momirealms.customfishing.integration.JobInterface; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public class JobXPImpl extends AbstractAction implements Action { - - private final double amount; - - public JobXPImpl(double amount, double chance) { - super(chance); - this.amount = amount; - } - - @Override - public void doOn(Player player, @Nullable Player anotherPlayer, @Nullable FishMeta fishMeta) { - if (!canExecute()) return; - JobInterface jobInterface = CustomFishing.getInstance().getIntegrationManager().getJobInterface(); - if (jobInterface == null) return; - jobInterface.addXp(player, amount); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/MessageActionImpl.java b/src/main/java/net/momirealms/customfishing/fishing/action/MessageActionImpl.java deleted file mode 100644 index 990ea943..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/MessageActionImpl.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.fishing.action; - -import net.momirealms.customfishing.fishing.FishMeta; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public class MessageActionImpl extends AbstractAction implements Action { - - private final String[] messages; - private final String nick; - - public MessageActionImpl(String[] messages, String nick, double chance) { - super(chance); - this.messages = messages; - this.nick = nick == null ? "" : nick; - } - - @Override - public void doOn(Player player, @Nullable Player anotherPlayer, @Nullable FishMeta fishMeta) { - if (!canExecute()) return; - for (String message : messages) { - AdventureUtils.playerMessage(player, - message.replace("{player}", player.getName()) - .replace("{world}", player.getWorld().getName()) - .replace("{x}", String.valueOf(player.getLocation().getBlockX())) - .replace("{y}", String.valueOf(player.getLocation().getBlockY())) - .replace("{z}", String.valueOf(player.getLocation().getBlockZ())) - .replace("{loot}", nick) - .replace("{activator}", anotherPlayer == null ? "" : anotherPlayer.getName()) - .replace("{size}", fishMeta == null ? "" : String.format("%.2f", fishMeta.size())) - ); - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/SkillXPImpl.java b/src/main/java/net/momirealms/customfishing/fishing/action/SkillXPImpl.java deleted file mode 100644 index fbe3e82a..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/SkillXPImpl.java +++ /dev/null @@ -1,42 +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.fishing.action; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishMeta; -import net.momirealms.customfishing.integration.SkillInterface; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public class SkillXPImpl extends AbstractAction implements Action { - - private final double amount; - - public SkillXPImpl(double amount, double chance) { - super(chance); - this.amount = amount; - } - - @Override - public void doOn(Player player, Player another, @Nullable FishMeta fishMeta) { - if (!canExecute()) return; - SkillInterface skillInterface = CustomFishing.getInstance().getIntegrationManager().getSkillInterface(); - if (skillInterface == null) return; - skillInterface.addXp(player, amount); - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/SoundActionImpl.java b/src/main/java/net/momirealms/customfishing/fishing/action/SoundActionImpl.java deleted file mode 100644 index 0e9bfe42..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/SoundActionImpl.java +++ /dev/null @@ -1,46 +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.fishing.action; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.momirealms.customfishing.fishing.FishMeta; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public class SoundActionImpl extends AbstractAction implements Action { - - private final Sound.Source source; - private final Key key; - private final float volume; - private final float pitch; - - public SoundActionImpl(Sound.Source source, Key sound, float volume, float pitch, double chance) { - super(chance); - this.pitch = pitch; - this.source = source; - this.key = sound; - this.volume = volume; - } - - @Override - public void doOn(Player player, Player another, @Nullable FishMeta fishMeta) { - AdventureUtils.playerSound(player, source, key, volume, pitch); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/action/VanillaXPImpl.java b/src/main/java/net/momirealms/customfishing/fishing/action/VanillaXPImpl.java deleted file mode 100644 index afa8c6b4..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/action/VanillaXPImpl.java +++ /dev/null @@ -1,54 +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.fishing.action; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishMeta; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.entity.ExperienceOrb; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public class VanillaXPImpl extends AbstractAction implements Action { - - private final int amount; - private final boolean mending; - - public VanillaXPImpl(int amount, boolean mending, double chance) { - super(chance); - this.amount = amount; - this.mending = mending; - } - - @Override - public void doOn(Player player, Player another, @Nullable FishMeta fishMeta) { - if (CustomFishing.getInstance().getVersionHelper().isSpigot()) { - if (mending) { - player.getLocation().getWorld().spawn(player.getLocation(), ExperienceOrb.class, e -> e.setExperience(amount)); - } else { - player.giveExp(amount); - AdventureUtils.playerSound(player, Sound.Source.PLAYER, Key.key("minecraft:entity.experience_orb.pickup"), 1, 1); - } - } else { - player.giveExp(amount, mending); - AdventureUtils.playerSound(player, Sound.Source.PLAYER, Key.key("minecraft:entity.experience_orb.pickup"), 1, 1); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/bar/FishingBar.java b/src/main/java/net/momirealms/customfishing/fishing/bar/FishingBar.java deleted file mode 100644 index 429eb7af..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/bar/FishingBar.java +++ /dev/null @@ -1,53 +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.fishing.bar; - -import org.bukkit.configuration.ConfigurationSection; - -import java.util.Random; - -public abstract class FishingBar { - - protected String[] titles; - protected String font; - protected String barImage; - protected String tip; - - public FishingBar(ConfigurationSection section) { - this.tip = section.getString("tip"); - this.titles = section.getStringList("title").size() == 0 ? new String[]{section.getString("title")} : section.getStringList("title").toArray(new String[0]); - this.font = section.getString("subtitle.font", "customfishing:bar"); - this.barImage = section.getString("subtitle.bar","뀃"); - } - - public String getRandomTitle() { - return titles[new Random().nextInt(titles.length)]; - } - - public String getBarImage() { - return barImage; - } - - public String getFont() { - return font; - } - - public String getTip() { - return tip; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/bar/ModeOneBar.java b/src/main/java/net/momirealms/customfishing/fishing/bar/ModeOneBar.java deleted file mode 100644 index 66bd2d1c..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/bar/ModeOneBar.java +++ /dev/null @@ -1,70 +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.fishing.bar; - -import org.bukkit.configuration.ConfigurationSection; - -import java.util.Objects; -import java.util.Set; - -public class ModeOneBar extends FishingBar { - - private final int widthPerSection; - private final double[] successRate; - private final int totalWidth; - private final int pointerWidth; - private final String pointerImage; - private final int pointerOffset; - - public ModeOneBar(ConfigurationSection section) { - super(section); - Set chances = Objects.requireNonNull(section.getConfigurationSection("success-rate-sections")).getKeys(false); - this.widthPerSection = section.getInt("arguments.width-per-section", 16); - this.successRate = new double[chances.size()]; - for(int i = 0; i < chances.size(); i++) - successRate[i] = section.getDouble("success-rate-sections." + (i + 1)); - this.totalWidth = chances.size() * widthPerSection - 1; - this.pointerImage = section.getString("subtitle.pointer","뀄"); - this.pointerOffset = section.getInt("arguments.pointer-offset"); - this.pointerWidth = section.getInt("arguments.pointer-width"); - } - - public int getWidthPerSection() { - return widthPerSection; - } - - public double[] getSuccessRate() { - return successRate; - } - - public int getTotalWidth() { - return totalWidth; - } - - public String getPointerImage() { - return pointerImage; - } - - public int getPointerWidth() { - return pointerWidth; - } - - public int getPointerOffset() { - return pointerOffset; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/bar/ModeThreeBar.java b/src/main/java/net/momirealms/customfishing/fishing/bar/ModeThreeBar.java deleted file mode 100644 index ebba9f9d..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/bar/ModeThreeBar.java +++ /dev/null @@ -1,100 +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.fishing.bar; - -import org.bukkit.configuration.ConfigurationSection; - -public class ModeThreeBar extends FishingBar { - - private final String fishImage; - private final int fishIconWidth; - private final String[] strain; - private final String[] strugglingFishImage; - private final int barEffectiveWidth; - private final int fishOffset; - private final int fishStartPosition; - private final int successPosition; - private final double ultimateStrain; - private final double normalIncrease; - private final double strugglingIncrease; - private final double strainLoss; - - public ModeThreeBar(ConfigurationSection section) { - super(section); - this.fishIconWidth = section.getInt("arguments.fish-icon-width"); - this.fishImage = section.getString("subtitle.fish"); - this.strain = section.getStringList("strain").toArray(new String[0]); - this.strugglingFishImage = section.getStringList("subtitle.struggling-fish").toArray(new String[0]); - this.barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); - this.fishOffset = section.getInt("arguments.fish-offset"); - this.fishStartPosition = section.getInt("arguments.fish-start-position"); - this.successPosition = section.getInt("arguments.success-position"); - this.ultimateStrain = section.getDouble("arguments.ultimate-strain", 50); - this.normalIncrease = section.getDouble("arguments.normal-pull-strain-increase", 1); - this.strugglingIncrease = section.getDouble("arguments.struggling-strain-increase", 2); - this.strainLoss = section.getDouble("arguments.loosening-strain-loss", 2); - } - - public String getFishImage() { - return fishImage; - } - - public int getFishIconWidth() { - return fishIconWidth; - } - - public String[] getStrain() { - return strain; - } - - public int getBarEffectiveWidth() { - return barEffectiveWidth; - } - - public int getFishOffset() { - return fishOffset; - } - - public int getFishStartPosition() { - return fishStartPosition; - } - - public int getSuccessPosition() { - return successPosition; - } - - public String[] getStrugglingFishImage() { - return strugglingFishImage; - } - - public double getUltimateStrain() { - return ultimateStrain; - } - - public double getNormalIncrease() { - return normalIncrease; - } - - public double getStrugglingIncrease() { - return strugglingIncrease; - } - - public double getStrainLoss() { - return strainLoss; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/bar/ModeTwoBar.java b/src/main/java/net/momirealms/customfishing/fishing/bar/ModeTwoBar.java deleted file mode 100644 index 352942ea..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/bar/ModeTwoBar.java +++ /dev/null @@ -1,102 +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.fishing.bar; - -import org.bukkit.configuration.ConfigurationSection; - -import java.util.Random; - -public class ModeTwoBar extends FishingBar { - - private final int[] timeRequirements; - private final String judgementAreaImage; - private final String fishImage; - private final int barEffectiveWidth; - private final int judgementAreaOffset; - private final int judgementAreaWidth; - private final int fishIconWidth; - private final String[] progress; - private final double punishment; - private final double waterResistance; - private final double pullingStrength; - private final double looseningLoss; - - public ModeTwoBar(ConfigurationSection section) { - super(section); - this.timeRequirements = section.getIntegerList("hold-time-requirements").stream().mapToInt(Integer::intValue).toArray(); - this.judgementAreaImage = section.getString("subtitle.judgment-area"); - this.fishImage = section.getString("subtitle.fish"); - this.barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); - this.judgementAreaOffset = section.getInt("arguments.judgment-area-offset"); - this.judgementAreaWidth = section.getInt("arguments.judgment-area-width"); - this.fishIconWidth = section.getInt("arguments.fish-icon-width"); - this.punishment = section.getDouble("arguments.punishment"); - this.progress = section.getStringList("progress").toArray(new String[0]); - this.waterResistance = section.getDouble("arguments.water-resistance", 0.15); - this.pullingStrength = section.getDouble("arguments.pulling-strength", 0.45); - this.looseningLoss = section.getDouble("arguments.loosening-strength-loss", 0.3); - } - - public int getRandomTimeRequirement() { - return timeRequirements[new Random().nextInt(timeRequirements.length)] * 20; - } - - public String getJudgementAreaImage() { - return judgementAreaImage; - } - - public String getFishImage() { - return fishImage; - } - - public int getBarEffectiveWidth() { - return barEffectiveWidth; - } - - public int getJudgementAreaOffset() { - return judgementAreaOffset; - } - - public int getJudgementAreaWidth() { - return judgementAreaWidth; - } - - public int getFishIconWidth() { - return fishIconWidth; - } - - public String[] getProgress() { - return progress; - } - - public double getPunishment() { - return punishment; - } - - public double getWaterResistance() { - return waterResistance; - } - - public double getPullingStrength() { - return pullingStrength; - } - - public double getLooseningLoss() { - return looseningLoss; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/Competition.java b/src/main/java/net/momirealms/customfishing/fishing/competition/Competition.java deleted file mode 100644 index d4146ad4..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/Competition.java +++ /dev/null @@ -1,283 +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.fishing.competition; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.competition.bossbar.BossBarConfig; -import net.momirealms.customfishing.fishing.competition.bossbar.BossBarManager; -import net.momirealms.customfishing.fishing.competition.ranking.LocalRankingImpl; -import net.momirealms.customfishing.fishing.competition.ranking.RankingInterface; -import net.momirealms.customfishing.fishing.competition.ranking.RedisRankingImpl; -import net.momirealms.customfishing.integration.papi.PlaceholderManager; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.JedisUtils; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.time.Instant; -import java.util.*; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class Competition { - - public static Competition currentCompetition; - private final CompetitionConfig competitionConfig; - private CompetitionGoal goal; - private ScheduledFuture timerTask; - private RankingInterface ranking; - private long startTime; - private long remainingTime; - private float progress; - private BossBarManager bossBarManager; - - public Competition(CompetitionConfig competitionConfig) { - this.competitionConfig = competitionConfig; - } - - public void begin(boolean forceStart) { - Collection playerCollections = Bukkit.getOnlinePlayers(); - if (playerCollections.size() >= competitionConfig.getMinPlayers() || forceStart) { - this.goal = competitionConfig.getGoal() == CompetitionGoal.RANDOM ? getRandomGoal() : competitionConfig.getGoal(); - this.remainingTime = this.competitionConfig.getDuration(); - this.startTime = Instant.now().getEpochSecond(); - if (ConfigManager.useRedis) { - this.ranking = new RedisRankingImpl(); - } else { - this.ranking = new LocalRankingImpl(); - } - this.ranking.clear(); - - startTimer(); - PlaceholderManager placeholderManager = CustomFishing.getInstance().getIntegrationManager().getPlaceholderManager(); - for (String startMsg : competitionConfig.getStartMessage()) - for (Player player : playerCollections) - AdventureUtils.playerMessage(player, placeholderManager.parse(player, startMsg)); - - for (String startCmd : competitionConfig.getStartCommand()) { - CustomFishing.getInstance().getScheduler().runTask(() -> { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), startCmd); - }); - } - - if (competitionConfig.isBossBarEnabled()) { - BossBarConfig bossBarConfig = competitionConfig.getBossBarConfig(); - if (bossBarConfig != null) { - this.bossBarManager = new BossBarManager(bossBarConfig); - this.bossBarManager.load(); - if (bossBarConfig.isShowToAll()) { - for (Player player : Bukkit.getOnlinePlayers()) { - this.bossBarManager.tryJoin(player, false); - } - } - } - } - } else { - for (Player player : playerCollections) { - AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.notEnoughPlayers); - } - currentCompetition = null; - } - } - - private void startTimer() { - this.timerTask = CustomFishing.getInstance().getScheduler().runTaskTimer(() -> { - if (decreaseTime()) { - end(); - } - }, 1, 1, TimeUnit.SECONDS); - } - - public void cancel() { - if (this.bossBarManager != null) { - bossBarManager.unload(); - } - if (this.timerTask != null && !this.timerTask.isCancelled()) { - this.timerTask.cancel(false); - } - this.ranking.clear(); - currentCompetition = null; - } - - public void end() { - if (this.bossBarManager != null) { - bossBarManager.unload(); - } - if (this.timerTask != null && !this.timerTask.isCancelled()) { - this.timerTask.cancel(false); - } - - this.givePrize(); - - List newMessage = new ArrayList<>(); - PlaceholderManager placeholderManager = CustomFishing.getInstance().getIntegrationManager().getPlaceholderManager(); - for (String endMsg : competitionConfig.getEndMessage()) { - List placeholders = new ArrayList<>(placeholderManager.detectBetterPlaceholders(endMsg)); - for (String placeholder : placeholders) { - if (placeholder.endsWith("_player}")) { - int rank = Integer.parseInt(placeholder.substring(1, placeholder.length() - 8)); - endMsg = endMsg.replace(placeholder, Optional.ofNullable(ranking.getPlayerAt(rank)).orElse(MessageManager.noPlayer)); - } else if (placeholder.endsWith("_score}")) { - int rank = Integer.parseInt(placeholder.substring(1, placeholder.length() - 7)); - float score = ranking.getScoreAt(rank); - endMsg = endMsg.replace(placeholder, score == 0 ? MessageManager.noScore : String.format("%.1f", score)); - } - } - newMessage.add(endMsg); - } - - for (Player player : Bukkit.getOnlinePlayers()) { - for (String msg : newMessage) { - AdventureUtils.playerMessage(player, placeholderManager.parse(player, msg)); - } - } - - for (String endCmd : competitionConfig.getEndCommand()) { - CustomFishing.getInstance().getScheduler().runTask(() -> { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), endCmd); - }); - } - - currentCompetition = null; - CustomFishing.getInstance().getScheduler().runTaskAsyncLater(() -> ranking.clear(), 3, TimeUnit.SECONDS); - } - - public void givePrize(){ - HashMap rewardsMap = competitionConfig.getRewards(); - if (ranking.getSize() != 0 && rewardsMap != null) { - Iterator iterator = ranking.getIterator(); - int i = 1; - while (iterator.hasNext()) { - if (i < rewardsMap.size()) { - String playerName = iterator.next(); - Player player = Bukkit.getPlayer(playerName); - if (player != null){ - for (Action action : rewardsMap.get(String.valueOf(i))) { - action.doOn(player); - } - } - i++; - } else { - Action[] actions = rewardsMap.get("participation"); - if (actions != null) { - iterator.forEachRemaining(playerName -> { - Player player = Bukkit.getPlayer(playerName); - if (player != null){ - for (Action action : actions) { - action.doOn(player); - } - } - }); - } else { - break; - } - } - } - } - } - - private boolean decreaseTime() { - long tVac; - long current = Instant.now().getEpochSecond(); - int duration = competitionConfig.getDuration(); - progress = (float) remainingTime / duration; - remainingTime = duration - (current - startTime); - if ((tVac = (current - startTime) + 1) != duration - remainingTime) { - for (long i = duration - remainingTime; i < tVac; i++) { - if (remainingTime <= 0) return true; - remainingTime--; - } - } - return false; - } - - private CompetitionGoal getRandomGoal() { - return CompetitionGoal.values()[new Random().nextInt(CompetitionGoal.values().length - 1)]; - } - - public static boolean hasCompetitionOn() { - return currentCompetition != null; - } - - public float getProgress() { - return progress; - } - - public CompetitionConfig getCompetitionConfig() { - return competitionConfig; - } - - public String getPlayerRank(OfflinePlayer player) { - return Optional.ofNullable(ranking.getPlayerRank(player.getName())).orElse(MessageManager.noRank); - } - - public long getRemainingTime() { - return remainingTime; - } - - public double getScore(OfflinePlayer player) { - return Optional.ofNullable(ranking.getCompetitionPlayer(player.getName())).orElse(CompetitionPlayer.emptyPlayer).getScore(); - } - - public boolean isJoined(Player player) { - return ranking.getCompetitionPlayer(player.getName()) != null; - } - - public BossBarManager getBossBarManager() { - return bossBarManager; - } - - public void tryJoinCompetition(Player player) { - if (bossBarManager != null) { - bossBarManager.tryJoin(player, true); - } - } - - public void refreshData(Player player, float score, boolean doubleScore) { - if (this.goal == CompetitionGoal.CATCH_AMOUNT) { - score = 1f; - } - if (this.goal == CompetitionGoal.MAX_SIZE) { - if (score > ranking.getPlayerScore(player.getName())) { - ranking.setData(player.getName(), score); - } - return; - } - ranking.refreshData(player.getName(), doubleScore ? 2 * score : score); - } - - public CompetitionGoal getGoal() { - return goal; - } - - public RankingInterface getRanking() { - return ranking; - } - - public static Competition getCurrentCompetition() { - return currentCompetition; - } - - public long getStartTime() { - return startTime; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionConfig.java b/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionConfig.java deleted file mode 100644 index de7fb78e..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionConfig.java +++ /dev/null @@ -1,143 +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.fishing.competition; - -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.competition.bossbar.BossBarConfig; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; - -public class CompetitionConfig { - - private String key; - private final int duration; - private final int minPlayers; - private final List startMessage; - private final List endMessage; - private final List startCommand; - private final List endCommand; - private final List joinCommand; - private List date; - private List weekday; - private final CompetitionGoal goal; - private final BossBarConfig bossBarConfig; - private final boolean enableBossBar; - private final HashMap rewards; - - public CompetitionConfig( - String key, - int duration, - int minPlayers, - List startMessage, - List endMessage, - List startCommand, - List endCommand, - List joinCommand, - CompetitionGoal goal, - BossBarConfig bossBarConfig, - boolean enableBossBar, - HashMap rewards - ) { - this.key = key; - this.duration = duration; - this.minPlayers = minPlayers; - this.startMessage = startMessage; - this.endMessage = endMessage; - this.startCommand = startCommand; - this.endCommand = endCommand; - this.joinCommand = joinCommand; - this.goal = goal; - this.bossBarConfig = bossBarConfig; - this.enableBossBar = enableBossBar; - this.rewards = rewards; - } - - public int getDuration() { - return duration; - } - - public int getMinPlayers() { - return minPlayers; - } - - public List getStartMessage() { - return startMessage; - } - - public List getEndMessage() { - return endMessage; - } - - public List getStartCommand() { - return startCommand; - } - - public List getEndCommand() { - return endCommand; - } - - public List getJoinCommand() { - return joinCommand; - } - - public CompetitionGoal getGoal() { - return goal; - } - - public BossBarConfig getBossBarConfig() { - return bossBarConfig; - } - - public boolean isBossBarEnabled() { - return enableBossBar; - } - - public HashMap getRewards() { - return rewards; - } - - public void setDate(List date) { - this.date = date; - } - - public void setWeekday(List weekday) { - this.weekday = weekday; - } - - public String getKey() { - return key; - } - - public boolean canStart() { - if (date != null && date.size() != 0) { - Calendar calendar = Calendar.getInstance(); - int dateDay = calendar.get(Calendar.DATE); - if (!date.contains(dateDay)) { - return false; - } - } - if (weekday != null && weekday.size() != 0) { - Calendar calendar = Calendar.getInstance(); - int dateDay = calendar.get(Calendar.DAY_OF_WEEK); - return weekday.contains(dateDay); - } - return true; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionGoal.java b/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionGoal.java deleted file mode 100644 index e1d672d1..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionGoal.java +++ /dev/null @@ -1,39 +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.fishing.competition; - -import net.momirealms.customfishing.manager.MessageManager; - -public enum CompetitionGoal { - - CATCH_AMOUNT(MessageManager.CATCH_AMOUNT), - TOTAL_SCORE(MessageManager.TOTAL_SCORE), - MAX_SIZE(MessageManager.MAX_SIZE), - TOTAL_SIZE(MessageManager.TOTAL_SIZE), - RANDOM("Random"); - - private final String display; - CompetitionGoal(String display) { - this.display = display; - } - - public String getDisplay() { - return display; - } - -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionSchedule.java b/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionSchedule.java deleted file mode 100644 index 2024afd2..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/CompetitionSchedule.java +++ /dev/null @@ -1,119 +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.fishing.competition; - -import com.google.common.io.ByteArrayDataInput; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.messaging.PluginMessageListener; -import org.jetbrains.annotations.NotNull; - -import java.io.*; -import java.time.LocalTime; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class CompetitionSchedule extends Function { - - private static CompetitionSchedule instance; - private ScheduledFuture checkTimeTask; - private int doubleCheckTime; - - @Override - public void unload() { - stopCheck(); - cancelCompetition(); - } - - public void load() { - instance = this; - checkTime(); - } - - public static boolean startCompetition(String competitionName) { - CompetitionConfig competitionConfig = CustomFishing.getInstance().getCompetitionManager().getCompetitionsC().get(competitionName); - if (competitionConfig == null) return false; - if (Competition.currentCompetition != null) { - Competition.currentCompetition.end(); - } - Competition.currentCompetition = new Competition(competitionConfig); - Competition.currentCompetition.begin(true); - return true; - } - - public static void cancelCompetition() { - if (Competition.currentCompetition != null) { - Competition.currentCompetition.cancel(); - } - } - - public static void endCompetition() { - if (Competition.currentCompetition != null) { - Competition.currentCompetition.end(); - } - } - - - public void startCompetition(CompetitionConfig competitionConfig) { - if (Competition.currentCompetition != null) { - Competition.currentCompetition.end(); - } - Competition.currentCompetition = new Competition(competitionConfig); - Competition.currentCompetition.begin(false); - } - - public void checkTime() { - this.checkTimeTask = CustomFishing.getInstance().getScheduler().runTaskTimerAsync(() -> { - if (isANewMinute()) { - CompetitionConfig competitionConfig = CustomFishing.getInstance().getCompetitionManager().getCompetitionsT().get(getCurrentTime()); - if (competitionConfig != null && competitionConfig.canStart()) { - startCompetition(competitionConfig); - } - } - }, 1, 1, TimeUnit.SECONDS); - } - - public void stopCheck() { - if (this.checkTimeTask != null && !checkTimeTask.isCancelled()) { - checkTimeTask.cancel(false); - } - } - - public String getCurrentTime() { - return LocalTime.now().getHour() + ":" + String.format("%02d", LocalTime.now().getMinute()); - } - - private boolean isANewMinute() { - int minute = LocalTime.now().getMinute(); - if (doubleCheckTime != minute) { - doubleCheckTime = minute; - return true; - } else { - return false; - } - } - - public static CompetitionSchedule getInstance() { - return instance; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarConfig.java b/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarConfig.java deleted file mode 100644 index 3b329c31..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarConfig.java +++ /dev/null @@ -1,63 +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.fishing.competition.bossbar; - -import org.bukkit.boss.BarColor; - -public class BossBarConfig { - - private final String[] text; - private final int interval; - private final BossBarOverlay overlay; - private final BarColor color; - private final int rate; - private boolean showToAll; - - public BossBarConfig(String[] text, BossBarOverlay overlay, BarColor color, int rate, int interval, boolean showToAll) { - this.text = text; - this.overlay = overlay; - this.color = color; - this.rate = rate; - this.interval = interval; - this.showToAll = showToAll; - } - - public String[] getText() { - return text; - } - - public int getInterval() { - return interval; - } - - public BossBarOverlay getOverlay() { - return overlay; - } - - public BarColor getColor() { - return color; - } - - public int getRate() { - return rate; - } - - public boolean isShowToAll() { - return showToAll; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarManager.java b/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarManager.java deleted file mode 100644 index 5d0b59eb..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarManager.java +++ /dev/null @@ -1,101 +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.fishing.competition.bossbar; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.competition.Competition; -import net.momirealms.customfishing.listener.JoinQuitListener; -import net.momirealms.customfishing.object.Function; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; - -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -public class BossBarManager extends Function { - - private static final ConcurrentHashMap senderMap = new ConcurrentHashMap<>(); - private final JoinQuitListener joinQuitListener; - private final BossBarConfig bossBarConfig; - - public BossBarManager(BossBarConfig bossBarConfig) { - this.joinQuitListener = new JoinQuitListener(this); - this.bossBarConfig = bossBarConfig; - } - - @Override - public void load() { - Bukkit.getPluginManager().registerEvents(this.joinQuitListener, CustomFishing.getInstance()); - } - - @Override - public void unload() { - if (this.joinQuitListener != null) HandlerList.unregisterAll(this.joinQuitListener); - for (BossBarSender bossBarSender : senderMap.values()) { - bossBarSender.hide(); - } - senderMap.clear(); - } - - @Override - public void onQuit(Player player) { - BossBarSender sender = senderMap.get(player.getUniqueId()); - if (sender != null) { - if (sender.isVisible()) { - sender.hide(); - } - senderMap.remove(player.getUniqueId()); - } - } - - @Override - public void onJoin(Player player) { - CustomFishing.getInstance().getScheduler().runTaskAsyncLater(() -> { - if (Competition.currentCompetition != null){ - boolean hasJoined = Competition.currentCompetition.isJoined(player); - if ((hasJoined || bossBarConfig.isShowToAll()) && senderMap.get(player.getUniqueId()) == null) { - BossBarSender sender = new BossBarSender(player, bossBarConfig); - sender.setHasClaimedJoinReward(hasJoined); - if (!sender.isVisible()) { - sender.show(); - } - senderMap.put(player.getUniqueId(), sender); - } - } - }, 200, TimeUnit.MILLISECONDS); - } - - public void tryJoin(Player player, boolean hasJoinReward) { - BossBarSender sender = senderMap.get(player.getUniqueId()); - if (sender == null) { - sender = new BossBarSender(player, Competition.currentCompetition.getCompetitionConfig().getBossBarConfig()); - senderMap.put(player.getUniqueId(), sender); - } - if (!sender.isVisible()) { - sender.show(); - } - if (hasJoinReward && !sender.hasClaimedJoin()) { - sender.setHasClaimedJoinReward(true); - for (String joinCmd : Competition.currentCompetition.getCompetitionConfig().getJoinCommand()){ - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), joinCmd.replace("{player}", player.getName())); - } - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarOverlay.java b/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarOverlay.java deleted file mode 100644 index 941d83c8..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/bossbar/BossBarOverlay.java +++ /dev/null @@ -1,26 +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.fishing.competition.bossbar; - -public enum BossBarOverlay { - NOTCHED_6, - NOTCHED_10, - NOTCHED_12, - NOTCHED_20, - PROGRESS -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/ranking/RedisRankingImpl.java b/src/main/java/net/momirealms/customfishing/fishing/competition/ranking/RedisRankingImpl.java deleted file mode 100644 index c2ed82bd..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/ranking/RedisRankingImpl.java +++ /dev/null @@ -1,117 +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.fishing.competition.ranking; - -import net.momirealms.customfishing.fishing.competition.CompetitionPlayer; -import net.momirealms.customfishing.util.JedisUtils; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.resps.Tuple; - -import java.util.Iterator; -import java.util.List; - -public class RedisRankingImpl implements RankingInterface { - - @Override - public void clear() { - Jedis jedis = JedisUtils.getJedis(); - jedis.zremrangeByRank("cf_competition",0,-1); - jedis.close(); - } - - @Override - public CompetitionPlayer getCompetitionPlayer(String player) { - Jedis jedis = JedisUtils.getJedis(); - Double score = jedis.zscore("cf_competition", player); - jedis.close(); - if (score == null || score == 0) return null; - return new CompetitionPlayer(player, Float.parseFloat(score.toString())); - } - - @Override - public Iterator getIterator() { - Jedis jedis = JedisUtils.getJedis(); - List players = jedis.zrevrange("cf_competition", 0, -1); - jedis.close(); - return players.iterator(); - } - - @Override - public int getSize() { - Jedis jedis = JedisUtils.getJedis(); - long size = jedis.zcard("cf_competition"); - jedis.close(); - return (int) size; - } - - @Override - public String getPlayerRank(String player) { - Jedis jedis = JedisUtils.getJedis(); - Long rank = jedis.zrevrank("cf_competition", player); - jedis.close(); - if(rank == null){ - return null; - } - return String.valueOf(rank + 1); - } - - @Override - public float getPlayerScore(String player) { - Jedis jedis = JedisUtils.getJedis(); - Double rank = jedis.zscore("cf_competition", player); - jedis.close(); - if(rank == null) { - return 0; - } - return rank.floatValue(); - } - - @Override - public void refreshData(String player, float score) { - Jedis jedis = JedisUtils.getJedis(); - jedis.zincrby("cf_competition", score, player); - jedis.close(); - } - - @Override - public void setData(String player, float score) { - Jedis jedis = JedisUtils.getJedis(); - jedis.zadd("cf_competition", score, player); - jedis.close(); - } - - @Override - public String getPlayerAt(int rank) { - Jedis jedis = JedisUtils.getJedis(); - List player = jedis.zrevrange("cf_competition", rank - 1, rank -1); - jedis.close(); - if (player == null) return null; - if (player.size() == 0) return null; - return player.get(0); - } - - @Override - public float getScoreAt(int rank) { - Jedis jedis = JedisUtils.getJedis(); - List players = jedis.zrevrangeWithScores("cf_competition", rank - 1, rank -1); - jedis.close(); - if (players == null) return 0; - if (players.size() == 0) return 0; - return (float) players.get(0).getScore(); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/loot/DroppedItem.java b/src/main/java/net/momirealms/customfishing/fishing/loot/DroppedItem.java deleted file mode 100644 index 37825282..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/loot/DroppedItem.java +++ /dev/null @@ -1,79 +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.fishing.loot; - -import net.momirealms.customfishing.fishing.MiniGameConfig; -import net.momirealms.customfishing.object.LeveledEnchantment; -import org.jetbrains.annotations.Nullable; - -public class DroppedItem extends LootImpl { - - private final boolean randomDurability; - private LeveledEnchantment[] randomEnchants; - private final String material; - private String[] size; - private float basicPrice; - private float sizeBonus; - - public DroppedItem(String key, String nick, String material, MiniGameConfig[] fishingGames, int weight, boolean showInFinder, double score, boolean randomDurability, boolean disableBar, boolean disableStats) { - super(key, nick, fishingGames, weight, showInFinder, score, disableBar, disableStats); - this.material = material; - this.randomDurability = randomDurability; - } - - public boolean isRandomDurability() { - return randomDurability; - } - - @Nullable - public LeveledEnchantment[] getRandomEnchants() { - return randomEnchants; - } - - public void setRandomEnchants(LeveledEnchantment[] randomEnchants) { - this.randomEnchants = randomEnchants; - } - - public String getMaterial() { - return material; - } - - public String[] getSize() { - return size; - } - - public void setSize(String[] size) { - this.size = size; - } - - public float getBasicPrice() { - return basicPrice; - } - - public void setBasicPrice(float basicPrice) { - this.basicPrice = basicPrice; - } - - public float getSizeBonus() { - return sizeBonus; - } - - public void setSizeBonus(float sizeBonus) { - this.sizeBonus = sizeBonus; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/loot/Item.java b/src/main/java/net/momirealms/customfishing/fishing/loot/Item.java deleted file mode 100644 index d3c7c2cf..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/loot/Item.java +++ /dev/null @@ -1,205 +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.fishing.loot; - -import net.momirealms.customfishing.object.LeveledEnchantment; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.inventory.ItemFlag; - -import java.util.*; - -public class Item { - - private final String key; - private final int amount; - private final Material material; - private String name; - private List lore; - private List itemFlags; - private int customModelData; - private boolean unbreakable; - private String head64; - private List enchantment; - private Map nbt; - private String totem; - private boolean headStackable; - private String[] cfTag; - - public Item(Material material, String key) { - this.material = material; - this.key = key; - this.amount = 1; - } - - public Item(ConfigurationSection section, String key) { - this.key = key; - this.material = Material.valueOf(section.getString("material", "cod").toUpperCase(Locale.ENGLISH)); - this.amount = section.getInt("amount", 1); - this.setUnbreakable(section.getBoolean("unbreakable", false)); - if (section.contains("display.lore")) this.setLore(section.getStringList("display.lore")); - if (section.contains("display.name")) this.setName(section.getString("display.name")); - if (section.contains("custom-model-data")) this.setCustomModelData(section.getInt("custom-model-data")); - if (section.contains("enchantments")) { - List enchantmentList = new ArrayList<>(); - Objects.requireNonNull(section.getConfigurationSection("enchantments")).getKeys(false).forEach(enchant -> { - LeveledEnchantment leveledEnchantment = new LeveledEnchantment( - NamespacedKey.fromString(enchant), - section.getInt("enchantments." + enchant), - 1 - ); - enchantmentList.add(leveledEnchantment); - }); - this.setEnchantment(enchantmentList); - } - if (section.contains("item_flags")) { - ArrayList itemFlags = new ArrayList<>(); - section.getStringList("item_flags").forEach(flag -> itemFlags.add(ItemFlag.valueOf(flag))); - this.setItemFlags(itemFlags); - } - if (section.contains("nbt")) { - ConfigurationSection nbtSection = section.getConfigurationSection(".nbt"); - if (nbtSection == null) return; - this.setNbt(nbtSection.getValues(false)); - } - if (section.contains("head64")) { - this.setHead64(section.getString("head64")); - this.setHeadStackable(section.getBoolean("head-stackable", false)); - } - if (section.contains("totem")) { - this.setTotem(section.getString("totem")); - } - } - - public Material getMaterial() { - return material; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getLore() { - return lore; - } - - public void setLore(List lore) { - this.lore = lore; - } - - public List getItemFlags() { - return itemFlags; - } - - public void setItemFlags(List itemFlags) { - this.itemFlags = itemFlags; - } - - public int getCustomModelData() { - return customModelData; - } - - public void setCustomModelData(int customModelData) { - this.customModelData = customModelData; - } - - public boolean isUnbreakable() { - return unbreakable; - } - - public void setUnbreakable(boolean unbreakable) { - this.unbreakable = unbreakable; - } - - public List getEnchantment() { - return enchantment; - } - - public void setEnchantment(List enchantment) { - this.enchantment = enchantment; - } - - public Map getNbt() { - return nbt; - } - - public void setNbt(Map nbt) { - this.nbt = nbt; - } - - public String getHead64() { - return head64; - } - - public void setHead64(String head64) { - this.head64 = head64; - } - - public String getKey() { - return key; - } - - public int getAmount() { - return amount; - } - - public String getTotem() { - return totem; - } - - public void setTotem(String totem) { - this.totem = totem; - } - - public boolean isHeadStackable() { - return headStackable; - } - - public void setHeadStackable(boolean headStackable) { - this.headStackable = headStackable; - } - - public String[] getCfTag() { - return cfTag; - } - - public void setCfTag(String[] cfTag) { - this.cfTag = cfTag; - } - - public Item cloneWithPrice(double price){ - Item newItem = new Item(this.material, this.key); - if (this.lore != null){ - List lore = new ArrayList<>(); - for (String text : this.lore) { - lore.add(text.replace("{money}", String.format("%.2f", price))); - } - newItem.setLore(lore); - } - if (this.name != null){ - newItem.setName(this.name.replace("{money}", String.format("%.2f", price))); - } - newItem.setCustomModelData(this.customModelData); - return newItem; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/loot/Loot.java b/src/main/java/net/momirealms/customfishing/fishing/loot/Loot.java deleted file mode 100644 index 4ce0a3b2..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/loot/Loot.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.momirealms.customfishing.fishing.loot; - -import net.momirealms.customfishing.fishing.MiniGameConfig; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.requirements.RequirementInterface; - -import java.util.HashMap; - -public interface Loot { - - MiniGameConfig[] getFishingGames(); - - String getKey(); - - String getNick(); - - String getGroup(); - - boolean isShowInFinder(); - - Action[] getSuccessActions(); - - public Action[] getFailureActions(); - - public Action[] getConsumeActions(); - - public Action[] getHookActions(); - - public int getWeight(); - - public double getScore(); - - public RequirementInterface[] getRequirements(); - - public boolean isDisableBar(); - - HashMap getSuccessTimesActions(); - - boolean isDisableStats(); -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/loot/LootImpl.java b/src/main/java/net/momirealms/customfishing/fishing/loot/LootImpl.java deleted file mode 100644 index 2c864ae9..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/loot/LootImpl.java +++ /dev/null @@ -1,144 +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.fishing.loot; - -import net.momirealms.customfishing.fishing.MiniGameConfig; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.requirements.RequirementInterface; - -import java.util.HashMap; - -public class LootImpl implements Loot { - - public static LootImpl EMPTY = new LootImpl("null", "null", new MiniGameConfig[0], 0, false, 0d, false, true); - - protected final String key; - protected final String nick; - protected String group; - protected boolean disableStats; - protected boolean disableBar; - protected final boolean showInFinder; - protected Action[] successActions; - protected Action[] failureActions; - protected Action[] hookActions; - protected Action[] consumeActions; - protected HashMap successTimesActions; - protected RequirementInterface[] requirements; - protected final MiniGameConfig[] fishingGames; - protected final int weight; - protected final double score; - - public LootImpl(String key, String nick, MiniGameConfig[] fishingGames, int weight, boolean showInFinder, double score, boolean disableBar, boolean disableStats) { - this.key = key; - this.nick = nick; - this.weight = weight; - this.showInFinder = showInFinder; - this.score = score; - this.fishingGames = fishingGames; - this.disableBar = disableBar; - this.disableStats = disableStats; - } - - public MiniGameConfig[] getFishingGames() { - return fishingGames; - } - - public String getKey() { - return key; - } - - public String getNick() { - return nick; - } - - public String getGroup() { - return group; - } - - public void setGroup(String group) { - this.group = group; - } - - public boolean isShowInFinder() { - return showInFinder; - } - - public Action[] getSuccessActions() { - return successActions; - } - - public void setSuccessActions(Action[] successActions) { - this.successActions = successActions; - } - - public Action[] getFailureActions() { - return failureActions; - } - - public Action[] getConsumeActions() { - return consumeActions; - } - - public void setConsumeActions(Action[] consumeActions) { - this.consumeActions = consumeActions; - } - - public void setFailureActions(Action[] failureActions) { - this.failureActions = failureActions; - } - - public Action[] getHookActions() { - return hookActions; - } - - public void setHookActions(Action[] hookActions) { - this.hookActions = hookActions; - } - - public int getWeight() { - return weight; - } - - public double getScore() { - return score; - } - - public RequirementInterface[] getRequirements() { - return requirements; - } - - public void setRequirements(RequirementInterface[] requirements) { - this.requirements = requirements; - } - - public boolean isDisableBar() { - return disableBar; - } - - public HashMap getSuccessTimesActions() { - return successTimesActions; - } - - public void setSuccessTimesActions(HashMap successTimesActions) { - this.successTimesActions = successTimesActions; - } - - public boolean isDisableStats() { - return disableStats; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/loot/Mob.java b/src/main/java/net/momirealms/customfishing/fishing/loot/Mob.java deleted file mode 100644 index 8e8098d8..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/loot/Mob.java +++ /dev/null @@ -1,48 +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.fishing.loot; - -import net.momirealms.customfishing.fishing.MiniGameConfig; -import org.jetbrains.annotations.NotNull; - -public class Mob extends LootImpl { - - private final String mobID; - private final int mobLevel; - private final MobVector mobVector; - - public Mob(String key, String nick, MiniGameConfig[] fishingGames, int weight, boolean showInFinder, double score, String mobID, int mobLevel, MobVector mobVector, boolean disableBar, boolean disableStats) { - super(key, nick, fishingGames, weight, showInFinder, score, disableBar, disableStats); - this.mobID = mobID; - this.mobLevel = mobLevel; - this.mobVector = mobVector; - } - - public String getMobID() { - return mobID; - } - - public int getMobLevel() { - return mobLevel; - } - - @NotNull - public MobVector getMobVector() { - return mobVector; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/loot/MobVector.java b/src/main/java/net/momirealms/customfishing/fishing/loot/MobVector.java deleted file mode 100644 index e2af7b4d..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/loot/MobVector.java +++ /dev/null @@ -1,31 +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.fishing.loot; - -public record MobVector(double horizontal, double vertical) { - - @Override - public double horizontal() { - return horizontal; - } - - @Override - public double vertical() { - return vertical; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/mode/FishingGame.java b/src/main/java/net/momirealms/customfishing/fishing/mode/FishingGame.java deleted file mode 100644 index aaaa2fbd..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/mode/FishingGame.java +++ /dev/null @@ -1,149 +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.fishing.mode; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.bar.FishingBar; -import net.momirealms.customfishing.manager.FishingManager; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.manager.OffsetManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Material; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Player; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.potion.PotionEffectType; - -import java.time.LocalTime; -import java.util.concurrent.ScheduledFuture; - -public abstract class FishingGame implements Runnable { - - protected OffsetManager offsetManager; - protected long deadline; - protected FishingManager fishingManager; - protected CustomFishing plugin; - protected Player player; - protected int difficulty; - protected String title; - protected FishHook fishHook; - protected ScheduledFuture gameTask; - protected boolean success; - private int doubleCheckTime; - - public FishingGame( - CustomFishing plugin, - FishingManager fishingManager, - long deadline, - Player player, - int difficulty, - FishingBar fishingBar - ) { - this.plugin = plugin; - this.offsetManager = plugin.getOffsetManager(); - this.fishingManager = fishingManager; - this.player = player; - this.deadline = deadline; - this.difficulty = difficulty; - this.title = fishingBar.getRandomTitle(); - this.fishHook = fishingManager.getHook(player.getUniqueId()); - this.success = false; - } - - @Override - public void run() { - timeOutCheck(); - switchItemCheck(); - invalidHookCheck(); - } - - public void showBar() { - - } - - public boolean isSuccess() { - return false; - } - - protected void timeOutCheck() { - if (System.currentTimeMillis() > deadline) { - AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.escape); - cancel(); - fishingManager.removeFishingPlayer(player); - fishingManager.removeHook(player.getUniqueId()); - fishingManager.fail(player, null, true); - } - } - - protected void switchItemCheck() { - if (!isANewSecond()) return; - PlayerInventory playerInventory = player.getInventory(); - if (playerInventory.getItemInMainHand().getType() != Material.FISHING_ROD && playerInventory.getItemInOffHand().getType() != Material.FISHING_ROD) { - cancel(); - fishingManager.removeFishingPlayer(player); - player.removePotionEffect(PotionEffectType.SLOW); - } - } - - protected void invalidHookCheck() { - if (fishHook == null || !fishHook.isValid()) { - cancel(); - fishingManager.removeFishingPlayer(player); - player.removePotionEffect(PotionEffectType.SLOW); - } - } - - public void cancel() { - if (!this.gameTask.isCancelled()) { - this.gameTask.cancel(false); - } - } - - public void success() { - success = true; - proceedTheResult(); - cancel(); - } - - public void fail() { - success = false; - proceedTheResult(); - cancel(); - } - - public void proceedTheResult() { - plugin.getScheduler().runTask(() -> { - FishHook fishHook = fishingManager.getHook(player.getUniqueId()); - if (fishHook != null) { - fishingManager.proceedReelIn(fishHook.getLocation(), player, this); - fishingManager.removeHook(player.getUniqueId()); - fishingManager.removeFishingPlayer(player); - } - }, fishHook.getLocation()); - } - - private boolean isANewSecond() { - int minute = LocalTime.now().getSecond(); - if (doubleCheckTime != minute) { - doubleCheckTime = minute; - return true; - } else { - return false; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/mode/ModeOneGame.java b/src/main/java/net/momirealms/customfishing/fishing/mode/ModeOneGame.java deleted file mode 100644 index 6445b5cc..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/mode/ModeOneGame.java +++ /dev/null @@ -1,78 +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.fishing.mode; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.bar.ModeOneBar; -import net.momirealms.customfishing.manager.FishingManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.entity.Player; - -import java.util.concurrent.TimeUnit; - -public class ModeOneGame extends FishingGame { - - private int progress; - private boolean face; - private final ModeOneBar modeOneBar; - - public ModeOneGame( - CustomFishing plugin, - FishingManager fishingManager, - long deadline, - Player player, - int difficulty, - ModeOneBar modeOneBar - ) { - super(plugin, fishingManager, deadline, player, difficulty, modeOneBar); - this.face = true; - this.modeOneBar = modeOneBar; - this.gameTask = plugin.getScheduler().runTaskTimerAsync(this, 50, Math.max(55 - difficulty * 5L, 5), TimeUnit.MILLISECONDS); - this.progress = -1; - } - - @Override - public void run() { - super.run(); - if (face) progress++; - else progress--; - if (progress > modeOneBar.getTotalWidth()) { - face = !face; - progress = 2 * modeOneBar.getTotalWidth() - progress; - } else if (progress < 0) { - face = !face; - progress = -progress; - } - showBar(); - } - - @Override - public void showBar() { - String bar = "" + modeOneBar.getBarImage() - + "" + offsetManager.getOffsetChars(modeOneBar.getPointerOffset() + progress) + "" - + modeOneBar.getPointerImage() - + "" + offsetManager.getOffsetChars(modeOneBar.getTotalWidth() - progress - modeOneBar.getPointerWidth()) + ""; - AdventureUtils.playerTitle(player, title, bar,0,500,0); - } - - @Override - public boolean isSuccess() { - int last = progress / modeOneBar.getWidthPerSection(); - return (Math.random() < modeOneBar.getSuccessRate()[last]); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/mode/ModeThreeGame.java b/src/main/java/net/momirealms/customfishing/fishing/mode/ModeThreeGame.java deleted file mode 100644 index 7ed424a2..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/mode/ModeThreeGame.java +++ /dev/null @@ -1,121 +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.fishing.mode; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.bar.ModeThreeBar; -import net.momirealms.customfishing.manager.FishingManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.entity.Player; - -import java.util.concurrent.TimeUnit; - -public class ModeThreeGame extends FishingGame { - - private final ModeThreeBar modeThreeBar; - private int fish_position; - private int timer; - private final int timer_max; - private double strain; - private int struggling_time; - private boolean played; - - public ModeThreeGame( - CustomFishing plugin, - FishingManager fishingManager, - long deadline, - Player player, - int difficulty, - ModeThreeBar modeThreeBar - ) { - super(plugin, fishingManager, deadline, player, difficulty, modeThreeBar); - this.fish_position = modeThreeBar.getFishStartPosition(); - this.success = false; - this.modeThreeBar = modeThreeBar; - this.timer_max = modeThreeBar.getStrugglingFishImage().length; - this.gameTask = plugin.getScheduler().runTaskTimerAsync(this, 50, 40, TimeUnit.MILLISECONDS); - this.played = false; - } - - @Override - public void run() { - super.run(); - timer++; - if (timer >= timer_max) { - timer = 0; - } - if (struggling_time <= 0) { - if (Math.random() < ((double) difficulty / 300)) { - struggling_time = (int) (15 + Math.random() * difficulty * 3); - } - } else { - struggling_time--; - } - if (player.isSneaking()) pull(); - else loosen(); - if (fish_position < modeThreeBar.getSuccessPosition() - modeThreeBar.getFishIconWidth() - 1) { - success(); - return; - } - if (fish_position + modeThreeBar.getFishIconWidth() > modeThreeBar.getBarEffectiveWidth() || strain >= modeThreeBar.getUltimateStrain()) { - fail(); - return; - } - showBar(); - } - - public void pull() { - played = true; - if (struggling_time > 0) { - strain += (modeThreeBar.getStrugglingIncrease() + ((double) difficulty / 5)); - fish_position -= 1; - } else { - strain += modeThreeBar.getNormalIncrease(); - fish_position -= 2; - } - } - - public void loosen() { - fish_position++; - strain -= modeThreeBar.getStrainLoss(); - } - - @Override - public void showBar() { - String bar = "" + modeThreeBar.getBarImage() - + "" + offsetManager.getOffsetChars(modeThreeBar.getFishOffset() + fish_position) + "" - + (struggling_time > 0 ? modeThreeBar.getStrugglingFishImage()[timer] : modeThreeBar.getFishImage()) - + "" + offsetManager.getOffsetChars(modeThreeBar.getBarEffectiveWidth() - fish_position - modeThreeBar.getFishIconWidth()) + "" - + ""; - strain = Math.max(0, Math.min(strain, modeThreeBar.getUltimateStrain())); - AdventureUtils.playerTitle( - player, - modeThreeBar.getTip() != null && !played ? modeThreeBar.getTip() : - title.replace("{strain}", modeThreeBar.getStrain()[(int) ((strain / modeThreeBar.getUltimateStrain()) * modeThreeBar.getStrain().length)]), - bar, - 0, - 500, - 0 - ); - } - - @Override - public boolean isSuccess() { - return success; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/mode/ModeTwoGame.java b/src/main/java/net/momirealms/customfishing/fishing/mode/ModeTwoGame.java deleted file mode 100644 index 0c1e0512..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/mode/ModeTwoGame.java +++ /dev/null @@ -1,163 +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.fishing.mode; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.bar.ModeTwoBar; -import net.momirealms.customfishing.manager.FishingManager; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Location; -import org.bukkit.entity.Player; - -import java.util.concurrent.TimeUnit; - -public class ModeTwoGame extends FishingGame { - - private double hold_time; - private final ModeTwoBar modeTwoBar; - private double judgement_position; - private double fish_position; - private double judgement_velocity; - private double fish_velocity; - private int timer; - private final int time_requirement; - private boolean played; - - public ModeTwoGame( - CustomFishing plugin, - FishingManager fishingManager, - long deadline, - Player player, - int difficulty, - ModeTwoBar modeTwoBar, - Location hookLoc - ) { - super(plugin, fishingManager, deadline, player, difficulty, modeTwoBar); - this.success = false; - this.judgement_position = (double) (modeTwoBar.getBarEffectiveWidth() - modeTwoBar.getJudgementAreaWidth()) / 2; - this.fish_position = 0; - this.timer = 0; - this.modeTwoBar = modeTwoBar; - this.time_requirement = modeTwoBar.getRandomTimeRequirement(); - this.played = false; - this.gameTask = plugin.getScheduler().runTaskTimerAsync(this, 50, 40, TimeUnit.MILLISECONDS); - } - - @Override - public void run() { - super.run(); - if (player.isSneaking()) addV(); - else reduceV(); - if (timer < 40 - difficulty) { - timer++; - } else { - timer = 0; - if (Math.random() > ((double) 1 / (difficulty + 1))) { - burst(); - } - } - judgement_position += judgement_velocity; - fish_position += fish_velocity; - fraction(); - calibrate(); - if (fish_position >= judgement_position - 2 && fish_position + modeTwoBar.getFishIconWidth() <= judgement_position + modeTwoBar.getJudgementAreaWidth() + 2) { - hold_time += 0.66; - } else { - hold_time -= modeTwoBar.getPunishment() * 0.66; - } - if (hold_time >= time_requirement) { - success(); - return; - } - showBar(); - } - - @Override - public void showBar() { - String bar = "" + modeTwoBar.getBarImage() - + "" + offsetManager.getOffsetChars((int) (modeTwoBar.getJudgementAreaOffset() + judgement_position)) + "" - + modeTwoBar.getJudgementAreaImage() - + "" + offsetManager.getOffsetChars((int) (modeTwoBar.getBarEffectiveWidth() - judgement_position - modeTwoBar.getJudgementAreaWidth())) + "" - + "" + offsetManager.getOffsetChars((int) (-modeTwoBar.getBarEffectiveWidth() - 1 + fish_position)) + "" - + modeTwoBar.getFishImage() - + "" + offsetManager.getOffsetChars((int) (modeTwoBar.getBarEffectiveWidth() - fish_position - modeTwoBar.getFishIconWidth() + 1)) + "" - + ""; - hold_time = Math.max(0, Math.min(hold_time, time_requirement)); - AdventureUtils.playerTitle( - player, - modeTwoBar.getTip() != null && !played ? modeTwoBar.getTip() : - title.replace("{progress}", modeTwoBar.getProgress()[(int) ((hold_time / time_requirement) * modeTwoBar.getProgress().length)]) - , - bar, - 0, - 500, - 0 - ); - } - - private void burst() { - if (Math.random() < (judgement_position / modeTwoBar.getBarEffectiveWidth())) { - judgement_velocity = -1 - 0.8 * Math.random() * difficulty; - } else { - judgement_velocity = 1 + 0.8 * Math.random() * difficulty; - } - } - - private void fraction() { - if (judgement_velocity > 0) { - judgement_velocity -= modeTwoBar.getWaterResistance(); - if (judgement_velocity < 0) judgement_velocity = 0; - } else { - judgement_velocity += modeTwoBar.getWaterResistance(); - if (judgement_velocity > 0) judgement_velocity = 0; - } - } - - private void reduceV() { - fish_velocity -= modeTwoBar.getLooseningLoss(); - } - - private void addV() { - played = true; - fish_velocity += modeTwoBar.getPullingStrength(); - } - - private void calibrate() { - if (fish_position < 0) { - fish_position = 0; - fish_velocity = 0; - } - if (fish_position + modeTwoBar.getFishIconWidth() > modeTwoBar.getBarEffectiveWidth()) { - fish_position = modeTwoBar.getBarEffectiveWidth() - modeTwoBar.getFishIconWidth(); - fish_velocity = 0; - } - if (judgement_position < 0) { - judgement_position = 0; - judgement_velocity = 0; - } - if (judgement_position + modeTwoBar.getJudgementAreaWidth() > modeTwoBar.getBarEffectiveWidth()) { - judgement_position = modeTwoBar.getBarEffectiveWidth() - modeTwoBar.getJudgementAreaWidth(); - judgement_velocity = 0; - } - } - - @Override - public boolean isSuccess() { - return success; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/BaitImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/BaitImpl.java deleted file mode 100644 index 886ebe72..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/BaitImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.momirealms.customfishing.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; - -public class BaitImpl extends Requirement implements RequirementInterface { - - private final HashSet baits; - - public BaitImpl(@Nullable String[] msg, HashSet baits) { - super(msg); - this.baits = baits; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - Player player = fishingCondition.getPlayer(); - String bait = fishingCondition.getBaitID(); - if (bait != null && (baits.contains(bait) || bait.equals("fish_finder"))) { - return true; - } - notMetMessage(player); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/BiomeImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/BiomeImpl.java deleted file mode 100644 index 3d24eaa7..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/BiomeImpl.java +++ /dev/null @@ -1,44 +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.fishing.requirements; - -import net.momirealms.biomeapi.BiomeAPI; -import net.momirealms.customfishing.fishing.FishingCondition; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; - -public class BiomeImpl extends Requirement implements RequirementInterface { - - private final HashSet biomes; - - public BiomeImpl(@Nullable String[] msg, HashSet biomes) { - super(msg); - this.biomes = biomes; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - String currentBiome = BiomeAPI.getBiome(fishingCondition.getLocation()); - if (biomes.contains(currentBiome)) { - return true; - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/CompetitionImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/CompetitionImpl.java deleted file mode 100644 index 9016b95e..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/CompetitionImpl.java +++ /dev/null @@ -1,39 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.fishing.competition.Competition; -import org.jetbrains.annotations.Nullable; - -public class CompetitionImpl extends Requirement implements RequirementInterface { - - private final boolean state; - - public CompetitionImpl(@Nullable String[] msg, boolean state) { - super(msg); - this.state = state; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - if (Competition.hasCompetitionOn() == state) return true; - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/CustomPapi.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/CustomPapi.java deleted file mode 100644 index c72a9dd6..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/CustomPapi.java +++ /dev/null @@ -1,82 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.fishing.requirements.papi.*; -import org.bukkit.configuration.MemorySection; -import org.bukkit.entity.Player; - -import java.util.*; - -public class CustomPapi extends Requirement implements RequirementInterface { - - public static HashSet allPapi = new HashSet<>(); - private final List papiRequirement; - - public CustomPapi(String[] msg, Map expressions){ - super(msg); - papiRequirement = getRequirements(expressions); - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - Player player = fishingCondition.getPlayer(); - if (fishingCondition.getPlayer() == null) return true; - HashMap papiMap = fishingCondition.getPapiMap(); - for (PapiRequirement requirement : papiRequirement) { - if (!requirement.isMet(papiMap, player)) { - notMetMessage(player); - return false; - } - } - return true; - } - - private List getRequirements(Map map) { - List papiRequirements = new ArrayList<>(); - map.keySet().forEach(key -> { - if (key.startsWith("&&")) { - if (map.get(key) instanceof MemorySection map2) { - papiRequirements.add(new ExpressionAnd(getRequirements(map2.getValues(false)))); - } - } else if (key.startsWith("||")) { - if (map.get(key) instanceof MemorySection map2) { - papiRequirements.add(new ExpressionOr(getRequirements(map2.getValues(false)))); - } - } else { - if (map.get(key) instanceof MemorySection map2) { - String type = map2.getString("type"); - String papi = map2.getString("papi"); - String value = map2.getString("value"); - if (value == null || papi == null || type == null) return; - allPapi.add(papi); - switch (type){ - case "==" -> papiRequirements.add(new PapiEquals(papi, value)); - case "!=" -> papiRequirements.add(new PapiNotEquals(papi, value)); - case ">=" -> papiRequirements.add(new PapiNoLess(papi, value)); - case "<=" -> papiRequirements.add(new PapiNoLarger(papi, value)); - case "<" -> papiRequirements.add(new PapiSmaller(papi, value)); - case ">" -> papiRequirements.add(new PapiGreater(papi, value)); - } - } - } - }); - return papiRequirements; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/DateImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/DateImpl.java deleted file mode 100644 index 69321413..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/DateImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.momirealms.customfishing.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; - -import java.util.Calendar; -import java.util.HashSet; - -public class DateImpl extends Requirement implements RequirementInterface { - - private final HashSet dates; - - public DateImpl(String[] msg, HashSet dates) { - super(msg); - this.dates = dates; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - Calendar calendar = Calendar.getInstance(); - String current = (calendar.get(Calendar.MONTH) + 1) + "/" + calendar.get(Calendar.DATE); - if (dates.contains(current)) { - return true; - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/JobLevelImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/JobLevelImpl.java deleted file mode 100644 index 1e948b99..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/JobLevelImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.momirealms.customfishing.fishing.requirements; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.integration.JobInterface; -import org.jetbrains.annotations.Nullable; - -public class JobLevelImpl extends Requirement implements RequirementInterface { - - private final int level; - - public JobLevelImpl(@Nullable String[] msg, int level) { - super(msg); - this.level = level; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - JobInterface jobInterface = CustomFishing.getInstance().getIntegrationManager().getJobInterface(); - if (jobInterface == null || fishingCondition.getPlayer() == null) return true; - if (jobInterface.getLevel(fishingCondition.getPlayer()) >= level) { - return true; - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/PermissionImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/PermissionImpl.java deleted file mode 100644 index 620ed990..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/PermissionImpl.java +++ /dev/null @@ -1,44 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import org.jetbrains.annotations.Nullable; - -public class PermissionImpl extends Requirement implements RequirementInterface { - - private final String permission; - - public PermissionImpl(@Nullable String[] msg, String permission) { - super(msg); - this.permission = permission; - } - - public String getPermission() { - return this.permission; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - if (fishingCondition.getPlayer() == null || fishingCondition.getPlayer().hasPermission(permission)) { - return true; - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/Requirement.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/Requirement.java deleted file mode 100644 index 8cbfec66..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/Requirement.java +++ /dev/null @@ -1,39 +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.fishing.requirements; - -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -public abstract class Requirement { - - protected String[] msg; - - protected Requirement(@Nullable String[] msg) { - this.msg = msg; - } - - public void notMetMessage(Player player) { - if (msg != null && player != null) { - for (String str : msg) { - AdventureUtils.playerMessage(player, str); - } - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/RequirementInterface.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/RequirementInterface.java deleted file mode 100644 index b439ca50..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/RequirementInterface.java +++ /dev/null @@ -1,25 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; - -public interface RequirementInterface { - - boolean isConditionMet(FishingCondition fishingCondition); -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/RodImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/RodImpl.java deleted file mode 100644 index b1db28cb..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/RodImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.momirealms.customfishing.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; - -public class RodImpl extends Requirement implements RequirementInterface { - - private final HashSet rods; - - public RodImpl(@Nullable String[] msg, HashSet rods) { - super(msg); - this.rods = rods; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - Player player = fishingCondition.getPlayer(); - String rod = fishingCondition.getRodID(); - if (rod != null && (rods.contains(rod) || rod.equals("fish_finder"))) { - return true; - } - notMetMessage(player); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/SeasonImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/SeasonImpl.java deleted file mode 100644 index 66cb9a45..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/SeasonImpl.java +++ /dev/null @@ -1,49 +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.fishing.requirements; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.integration.SeasonInterface; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class SeasonImpl extends Requirement implements RequirementInterface { - - private final List seasons; - - public SeasonImpl(@Nullable String[] msg, List seasons) { - super(msg); - this.seasons = seasons; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - SeasonInterface seasonInterface = CustomFishing.getInstance().getIntegrationManager().getSeasonInterface(); - if (seasonInterface == null) return true; - String currentSeason = seasonInterface.getSeason(fishingCondition.getLocation().getWorld()); - for (String season : seasons) { - if (season.equalsIgnoreCase(currentSeason)) { - return true; - } - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/SkillLevelImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/SkillLevelImpl.java deleted file mode 100644 index 4db23cdc..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/SkillLevelImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.momirealms.customfishing.fishing.requirements; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.integration.SkillInterface; -import org.jetbrains.annotations.Nullable; - -public class SkillLevelImpl extends Requirement implements RequirementInterface { - - private final int level; - - public SkillLevelImpl(@Nullable String[] msg, int level) { - super(msg); - this.level = level; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - SkillInterface skillInterface = CustomFishing.getInstance().getIntegrationManager().getSkillInterface(); - if (skillInterface == null || fishingCondition.getPlayer() == null) return true; - if (skillInterface.getLevel(fishingCondition.getPlayer()) >= level) { - return true; - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/TimeImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/TimeImpl.java deleted file mode 100644 index 2d5a47dc..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/TimeImpl.java +++ /dev/null @@ -1,46 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class TimeImpl extends Requirement implements RequirementInterface { - - private final List times; - - public TimeImpl(@Nullable String[] msg, List times) { - super(msg); - this.times = times; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - long time = fishingCondition.getLocation().getWorld().getTime(); - for (String range : times) { - String[] timeMinMax = range.split("~"); - if (time > Long.parseLong(timeMinMax[0]) && time < Long.parseLong(timeMinMax[1])) { - return true; - } - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/WeatherImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/WeatherImpl.java deleted file mode 100644 index bd7327e9..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/WeatherImpl.java +++ /dev/null @@ -1,50 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import org.bukkit.World; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class WeatherImpl extends Requirement implements RequirementInterface { - - private final List weathers; - - public WeatherImpl(@Nullable String[] msg, List weathers) { - super(msg); - this.weathers = weathers; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - World world = fishingCondition.getLocation().getWorld(); - String currentWeather; - if (world.isThundering()) currentWeather = "thunder"; - else if (world.isClearWeather()) currentWeather = "clear"; - else currentWeather = "rain"; - for (String weather : weathers) { - if (weather.equalsIgnoreCase(currentWeather)) { - return true; - } - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/WorldImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/WorldImpl.java deleted file mode 100644 index 28836fa2..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/WorldImpl.java +++ /dev/null @@ -1,44 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import org.bukkit.World; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class WorldImpl extends Requirement implements RequirementInterface { - - private final List worlds; - - public WorldImpl(@Nullable String[] msg, List worlds) { - super(msg); - this.worlds = worlds; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - World world = fishingCondition.getLocation().getWorld(); - if (worlds.contains(world.getName())) { - return true; - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/YPosImpl.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/YPosImpl.java deleted file mode 100644 index 5d69937f..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/YPosImpl.java +++ /dev/null @@ -1,46 +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.fishing.requirements; - -import net.momirealms.customfishing.fishing.FishingCondition; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class YPosImpl extends Requirement implements RequirementInterface { - - private final List yPos; - - public YPosImpl(@Nullable String[] msg, List yPos) { - super(msg); - this.yPos = yPos; - } - - @Override - public boolean isConditionMet(FishingCondition fishingCondition) { - int y = (int) fishingCondition.getLocation().getY(); - for (String range : yPos) { - String[] yMinMax = range.split("~"); - if (y > Integer.parseInt(yMinMax[0]) && y < Integer.parseInt(yMinMax[1])) { - return true; - } - } - notMetMessage(fishingCondition.getPlayer()); - return false; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/ExpressionAnd.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/ExpressionAnd.java deleted file mode 100644 index b3df5bae..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/ExpressionAnd.java +++ /dev/null @@ -1,34 +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.fishing.requirements.papi; - -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.List; - -public record ExpressionAnd(List requirements) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - for (PapiRequirement requirement : requirements) { - if (!requirement.isMet(papiMap, player)) return false; - } - return true; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/ExpressionOr.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/ExpressionOr.java deleted file mode 100644 index dd43d52a..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/ExpressionOr.java +++ /dev/null @@ -1,34 +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.fishing.requirements.papi; - -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.List; - -public record ExpressionOr(List requirements) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - for (PapiRequirement requirement : requirements) { - if (requirement.isMet(papiMap, player)) return true; - } - return false; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiEquals.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiEquals.java deleted file mode 100644 index 605e5736..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiEquals.java +++ /dev/null @@ -1,33 +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.fishing.requirements.papi; - -import me.clip.placeholderapi.PlaceholderAPI; -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.Objects; - -public record PapiEquals(String papi, String requirement) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - String value = papiMap.get(papi); - return Objects.equals(value, PlaceholderAPI.setPlaceholders(player, requirement)); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiGreater.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiGreater.java deleted file mode 100644 index e5e16a25..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiGreater.java +++ /dev/null @@ -1,32 +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.fishing.requirements.papi; - -import me.clip.placeholderapi.PlaceholderAPI; -import org.bukkit.entity.Player; - -import java.util.HashMap; - -public record PapiGreater(String papi, String requirement) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - double value = Double.parseDouble(papiMap.get(papi)); - return value > Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement)); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNoLarger.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNoLarger.java deleted file mode 100644 index 5791e460..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNoLarger.java +++ /dev/null @@ -1,32 +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.fishing.requirements.papi; - -import me.clip.placeholderapi.PlaceholderAPI; -import org.bukkit.entity.Player; - -import java.util.HashMap; - -public record PapiNoLarger(String papi, String requirement) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - double value = Double.parseDouble(papiMap.get(papi)); - return value <= Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement)); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNoLess.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNoLess.java deleted file mode 100644 index 973a8611..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNoLess.java +++ /dev/null @@ -1,32 +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.fishing.requirements.papi; - -import me.clip.placeholderapi.PlaceholderAPI; -import org.bukkit.entity.Player; - -import java.util.HashMap; - -public record PapiNoLess(String papi, String requirement) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - double value = Double.parseDouble(papiMap.get(papi)); - return value >= Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement)); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNotEquals.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNotEquals.java deleted file mode 100644 index 37a7e85c..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiNotEquals.java +++ /dev/null @@ -1,33 +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.fishing.requirements.papi; - -import me.clip.placeholderapi.PlaceholderAPI; -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.Objects; - -public record PapiNotEquals(String papi, String requirement) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - String value = papiMap.get(papi); - return !Objects.equals(value, PlaceholderAPI.setPlaceholders(player, requirement)); - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiRequirement.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiRequirement.java deleted file mode 100644 index 2d5a5441..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiRequirement.java +++ /dev/null @@ -1,26 +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.fishing.requirements.papi; - -import org.bukkit.entity.Player; - -import java.util.HashMap; - -public interface PapiRequirement { - boolean isMet(HashMap papiMap, Player player); -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiSmaller.java b/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiSmaller.java deleted file mode 100644 index 3dc21789..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/requirements/papi/PapiSmaller.java +++ /dev/null @@ -1,32 +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.fishing.requirements.papi; - -import me.clip.placeholderapi.PlaceholderAPI; -import org.bukkit.entity.Player; - -import java.util.HashMap; - -public record PapiSmaller(String papi, String requirement) implements PapiRequirement{ - - @Override - public boolean isMet(HashMap papiMap, Player player) { - double value = Double.parseDouble(papiMap.get(papi)); - return value < Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement)); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/totem/ActivatedTotem.java b/src/main/java/net/momirealms/customfishing/fishing/totem/ActivatedTotem.java deleted file mode 100644 index aca49740..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/totem/ActivatedTotem.java +++ /dev/null @@ -1,155 +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.fishing.totem; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.manager.FishingManager; -import net.momirealms.customfishing.util.ArmorStandUtils; -import net.momirealms.customfishing.util.LocationUtils; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class ActivatedTotem implements Runnable { - - public static int id = 121616121; - private int timer; - private final TotemConfig totem; - private final Location bottomLoc; - private final Location coreLoc; - private final Set nearbyPlayerSet; - private final int[] entityID; - private final boolean hasHolo; - private final TotemParticle particleTimerTask; - private final FishingManager fishingManager; - private final int direction; - private final String activator; - private final ScheduledFuture totemTask; - - public ActivatedTotem(Location coreLoc, TotemConfig totem, FishingManager fishingManager, int direction, String activator) { - this.fishingManager = fishingManager; - this.totem = totem; - this.coreLoc = coreLoc; - this.bottomLoc = coreLoc.clone().subtract(0, totem.getOriginalModel().getCorePos().getY(), 0); - this.entityID = new int[totem.getHoloText().length]; - for (int i = 0; i < totem.getHoloText().length; i++) { - this.entityID[i] = id++; - } - this.hasHolo = totem.getHoloText() != null; - this.nearbyPlayerSet = Collections.synchronizedSet(new HashSet<>()); - this.particleTimerTask = new TotemParticle(bottomLoc, totem.getRadius(), totem.getParticle()); - this.direction = direction; - this.activator = activator; - this.totemTask = CustomFishing.getInstance().getScheduler().runTaskTimer(this, 1, 1, TimeUnit.SECONDS, coreLoc); - } - - @Override - public void run() { - - timer++; - if (timer > totem.getDuration()) { - stop(); - return; - } - - HashSet temp = new HashSet<>(nearbyPlayerSet); - Collection nearbyPlayers = LocationUtils.getNearbyPlayers(bottomLoc, totem.getRadius()); - - for (Player player : temp) { - if (nearbyPlayers.remove(player)) { - if (hasHolo) { - for (int i = 0; i < entityID.length; i++) { - CustomFishing.getProtocolManager().sendServerPacket(player, ArmorStandUtils.getMetaPacket(entityID[i], - totem.getHoloText()[entityID.length - 1 - i] - .replace("{time}", String.valueOf(totem.getDuration() - timer)) - .replace("{max_time}", String.valueOf(totem.getDuration())) - .replace("{player}", activator) - )); - } - addPotionEffect(player); - } - } - else { - if (hasHolo) { - for (int j : entityID) { - CustomFishing.getProtocolManager().sendServerPacket(player, ArmorStandUtils.getDestroyPacket(j)); - } - } - nearbyPlayerSet.remove(player); - } - } - - for (Player newComer : nearbyPlayers) { - if (hasHolo) { - for (int i = 0; i < entityID.length; i++) { - CustomFishing.getProtocolManager().sendServerPacket(newComer, ArmorStandUtils.getSpawnPacket(entityID[i], bottomLoc.clone().add(0.5, totem.getHoloOffset() + i * 0.4, 0.5))); - CustomFishing.getProtocolManager().sendServerPacket(newComer, ArmorStandUtils.getMetaPacket(entityID[i], - totem.getHoloText()[entityID.length - 1 - i] - .replace("{time}", String.valueOf(totem.getDuration() - timer)) - .replace("{max_time}", String.valueOf(totem.getDuration())) - .replace("{player}", activator) - )); - } - addPotionEffect(newComer); - } - nearbyPlayerSet.add(newComer); - } - } - - public Set getNearbyPlayerSet() { - return nearbyPlayerSet; - } - - public TotemConfig getTotem() { - return totem; - } - - public void stop() { - this.particleTimerTask.cancel(); - cancel(); - fishingManager.removeTotem(coreLoc); - CustomFishing.getInstance().getTotemManager().clearBreakDetectCache(totem.getFinalModel(), bottomLoc, direction); - if (hasHolo) { - for (Player player : nearbyPlayerSet) { - for (int j : entityID) { - CustomFishing.getProtocolManager().sendServerPacket(player, ArmorStandUtils.getDestroyPacket(j)); - } - } - } - nearbyPlayerSet.clear(); - } - - private void addPotionEffect(Player player) { - if (totem.getPotionEffects() != null) { - for (PotionEffect potionEffect : totem.getPotionEffects()) { - player.addPotionEffect(potionEffect); - } - } - } - - public void cancel() { - this.totemTask.cancel(false); - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/totem/FinalModel.java b/src/main/java/net/momirealms/customfishing/fishing/totem/FinalModel.java deleted file mode 100644 index 3329f738..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/totem/FinalModel.java +++ /dev/null @@ -1,77 +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.fishing.totem; - -public class FinalModel { - - private final int length; - private final int width; - private final int height; - private final String[][][] model; - private CorePos corePos; - - public FinalModel(int length, int width, int height) { - this.length = length; - this.width = width; - this.height = height; - this.model = new String[length][width][height]; - } - - @Override - public String toString() { - StringBuilder stringBuilder = new StringBuilder("FinalModel:"); - for (int i = 0; i < height; i++) { - stringBuilder.append("\nlayer: ").append(i + 1); - for (int j = 0; j < width; j++) { - stringBuilder.append("\n"); - for (int k = 0; k < height; k++) { - stringBuilder.append(model[k][j][i]).append("\t"); - } - } - } - return stringBuilder.toString(); - } - - public CorePos getCorePos() { - return corePos; - } - - public void setCorePos(CorePos corePos) { - this.corePos = corePos; - } - - public int getLength() { - return length; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public void setElement(String element, int length, int width, int height) { - this.model[length][width][height] = element; - } - - public String getElement(int length, int width, int height) { - return this.model[length][width][height]; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/fishing/totem/OriginalModel.java b/src/main/java/net/momirealms/customfishing/fishing/totem/OriginalModel.java deleted file mode 100644 index 15a3b0a6..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/totem/OriginalModel.java +++ /dev/null @@ -1,80 +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.fishing.totem; - -import java.util.Arrays; - -public class OriginalModel { - - private final int length; - private final int width; - private final int height; - private final String[][][][] model; - private CorePos corePos; - - public OriginalModel(int length, int width, int height) { - this.length = length; - this.width = width; - this.height = height; - this.model = new String[length][width][height][]; - } - - @Override - public String toString() { - StringBuilder stringBuilder = new StringBuilder("TotemModel:"); - for (int i = 0; i < height; i++) { - stringBuilder.append("\nlayer: ").append(i + 1); - for (int j = 0; j < width; j++) { - stringBuilder.append("\n"); - for (int k = 0; k < height; k++) { - stringBuilder.append(Arrays.toString(model[k][j][i])).append("\t"); - } - } - } - return stringBuilder.toString(); - } - - public CorePos getCorePos() { - return corePos; - } - - public void setCorePos(CorePos corePos) { - this.corePos = corePos; - } - - public int getLength() { - return length; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public void setElement(String[] element, int length, int width, int height) { - this.model[length][width][height] = element; - } - - public String[] getElement(int length, int width, int height) { - return this.model[length][width][height]; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/totem/TotemConfig.java b/src/main/java/net/momirealms/customfishing/fishing/totem/TotemConfig.java deleted file mode 100644 index 156afa91..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/totem/TotemConfig.java +++ /dev/null @@ -1,125 +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.fishing.totem; - -import net.momirealms.customfishing.fishing.Effect; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.requirements.RequirementInterface; -import org.bukkit.Particle; -import org.bukkit.potion.PotionEffect; - -public class TotemConfig { - - private final OriginalModel originalModel; - private FinalModel finalModel; - private RequirementInterface[] requirements; - private final int radius; - private final Particle particle; - private final int duration; - private final Effect effect; - private Action[] activatorActions; - private Action[] nearbyActions; - private double holoOffset; - private String[] holoText; - private PotionEffect[] potionEffects; - - public TotemConfig(OriginalModel originalModel, FinalModel finalModel, int radius, int duration, Particle particle, Effect effect) { - this.originalModel = originalModel; - this.finalModel = finalModel; - this.radius = radius; - this.duration = duration; - this.particle = particle; - this.effect = effect; - } - - public RequirementInterface[] getRequirements() { - return requirements; - } - - public void setRequirements(RequirementInterface[] requirements) { - this.requirements = requirements; - } - - public OriginalModel getOriginalModel() { - return originalModel; - } - - public FinalModel getFinalModel() { - return finalModel; - } - - public void setFinalModel(FinalModel finalModel) { - this.finalModel = finalModel; - } - - public int getRadius() { - return radius; - } - - public Particle getParticle() { - return particle; - } - - public int getDuration() { - return duration; - } - - public Effect getEffect() { - return effect; - } - - public Action[] getActivatorActions() { - return activatorActions; - } - - public void setActivatorActions(Action[] activatorActions) { - this.activatorActions = activatorActions; - } - - public Action[] getNearbyActions() { - return nearbyActions; - } - - public void setNearbyActions(Action[] nearbyActions) { - this.nearbyActions = nearbyActions; - } - - public double getHoloOffset() { - return holoOffset; - } - - public void setHoloOffset(double holoOffset) { - this.holoOffset = holoOffset; - } - - public String[] getHoloText() { - return holoText; - } - - public void setHoloText(String[] holoText) { - this.holoText = holoText; - } - - public PotionEffect[] getPotionEffects() { - return potionEffects; - } - - public void setPotionEffects(PotionEffect[] potionEffects) { - this.potionEffects = potionEffects; - } -} diff --git a/src/main/java/net/momirealms/customfishing/fishing/totem/TotemParticle.java b/src/main/java/net/momirealms/customfishing/fishing/totem/TotemParticle.java deleted file mode 100644 index 4a62cdc0..00000000 --- a/src/main/java/net/momirealms/customfishing/fishing/totem/TotemParticle.java +++ /dev/null @@ -1,69 +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.fishing.totem; - -import net.momirealms.customfishing.CustomFishing; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.World; - -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class TotemParticle implements Runnable { - - private final Location bottomLoc; - private final int radius; - private final double angle_1; - private final double angle_2; - private int timer; - private final Particle particle; - private final World world; - private final ScheduledFuture task; - - public TotemParticle(Location bottomLoc, int radius, Particle particle) { - this.bottomLoc = bottomLoc.clone().add(0.5,0,0.5); - this.radius = radius; - this.particle = particle; - this.angle_1 = 360 / (double) radius; - this.angle_2 = 72 / (double) radius; - this.world = bottomLoc.getWorld(); - this.task = CustomFishing.getInstance().getScheduler().runTaskTimerAsync(this, 200, 200, TimeUnit.MILLISECONDS); - } - - @Override - public void run() { - timer++; - if (timer > 4) { - timer = 0; - } - for (int i = 0; i < radius; i++) { - double temp_angle = angle_1 * i + angle_2 * timer; - double angle = temp_angle * Math.PI / 180; - world.spawnParticle(particle, bottomLoc.clone().add(Math.cos(angle) * radius, 0.5, Math.sin(angle) * radius), 1 ,0, 0,0, 0); - } - } - - public void cancel() { - this.task.cancel(false); - } - - public boolean isCancelled() { - return this.task.isCancelled(); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/BlockInterface.java b/src/main/java/net/momirealms/customfishing/integration/BlockInterface.java deleted file mode 100644 index c7f81d3f..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/BlockInterface.java +++ /dev/null @@ -1,50 +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.integration; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.jetbrains.annotations.Nullable; - -public interface BlockInterface { - - void removeBlock(Block block); - void placeBlock(String id, Location location); - @Nullable - String getID(Block block); - - default void replaceBlock(Location location, String id) { - removeBlock(location.getBlock()); - placeBlock(id, location); - } - - static boolean isVanillaItem(String item) { - char[] chars = item.toCharArray(); - for (char character : chars) { - if ((character < 65 || character > 90) && character != 95) { - return false; - } - } - return true; - } - - static void placeVanillaBlock(String id, Location location) { - location.getBlock().setType(Material.valueOf(id)); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/JobInterface.java b/src/main/java/net/momirealms/customfishing/integration/JobInterface.java deleted file mode 100644 index ab0ee684..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/JobInterface.java +++ /dev/null @@ -1,8 +0,0 @@ -package net.momirealms.customfishing.integration; - -import org.bukkit.entity.Player; - -public interface JobInterface { - void addXp(Player player, double amount); - int getLevel(Player player); -} diff --git a/src/main/java/net/momirealms/customfishing/integration/MobInterface.java b/src/main/java/net/momirealms/customfishing/integration/MobInterface.java deleted file mode 100644 index 8a89e5d6..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/MobInterface.java +++ /dev/null @@ -1,25 +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.integration; - -import net.momirealms.customfishing.fishing.loot.Mob; -import org.bukkit.Location; - -public interface MobInterface { - void summon(Location playerLoc, Location summonLoc, Mob mob); -} diff --git a/src/main/java/net/momirealms/customfishing/integration/SkillInterface.java b/src/main/java/net/momirealms/customfishing/integration/SkillInterface.java deleted file mode 100644 index bcc094f3..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/SkillInterface.java +++ /dev/null @@ -1,26 +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.integration; - -import org.bukkit.entity.Player; - -public interface SkillInterface { - - void addXp(Player player, double amount); - int getLevel(Player player); -} diff --git a/src/main/java/net/momirealms/customfishing/integration/VaultHook.java b/src/main/java/net/momirealms/customfishing/integration/VaultHook.java deleted file mode 100644 index cd3a3113..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/VaultHook.java +++ /dev/null @@ -1,40 +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.integration; - -import net.milkbowl.vault.economy.Economy; -import net.momirealms.customfishing.CustomFishing; -import org.bukkit.plugin.RegisteredServiceProvider; - -public class VaultHook { - - private Economy economy; - - public boolean initialize() { - RegisteredServiceProvider rsp = CustomFishing.getInstance().getServer().getServicesManager().getRegistration(Economy.class); - if (rsp == null) { - return false; - } - this.economy = rsp.getProvider(); - return true; - } - - public Economy getEconomy() { - return economy; - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/block/ItemsAdderBlockImpl.java b/src/main/java/net/momirealms/customfishing/integration/block/ItemsAdderBlockImpl.java deleted file mode 100644 index 1fbfbbb5..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/block/ItemsAdderBlockImpl.java +++ /dev/null @@ -1,69 +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.integration.block; - -import dev.lone.itemsadder.api.CustomBlock; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.integration.BlockInterface; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.jetbrains.annotations.Nullable; - -public class ItemsAdderBlockImpl implements BlockInterface { - - @Override - public void removeBlock(Block block) { - if (CustomBlock.byAlreadyPlaced(block) != null) { - CustomBlock.remove(block.getLocation()); - } - else { - block.setType(Material.AIR); - } - } - - @Override - public void placeBlock(String id, Location location) { - String blockID = CustomFishing.getInstance().getTotemManager().getInvertedBlock(id); - if (blockID == null) { - AdventureUtils.consoleMessage(id + " does not exist in default.yml"); - return; - } - if (BlockInterface.isVanillaItem(blockID)) { - BlockInterface.placeVanillaBlock(blockID, location); - } - else { - CustomBlock.place(blockID, location); - } - } - - @Override - @Nullable - public String getID(Block block) { - CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block); - String id; - if (customBlock == null) { - id = block.getType().name(); - } - else { - id = customBlock.getNamespacedID(); - } - return CustomFishing.getInstance().getTotemManager().getBlockID(id); - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/integration/block/OraxenBlockImpl.java b/src/main/java/net/momirealms/customfishing/integration/block/OraxenBlockImpl.java deleted file mode 100644 index 5bba954e..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/block/OraxenBlockImpl.java +++ /dev/null @@ -1,71 +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.integration.block; - -import io.th0rgal.oraxen.api.OraxenBlocks; -import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanic; -import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanicFactory; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.integration.BlockInterface; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.jetbrains.annotations.Nullable; - -public class OraxenBlockImpl implements BlockInterface { - - @Override - public void removeBlock(Block block) { - block.setType(Material.AIR); - } - - @Override - public void placeBlock(String id, Location location) { - String blockID = CustomFishing.getInstance().getTotemManager().getInvertedBlock(id); - if (blockID == null) { - AdventureUtils.consoleMessage(id + " does not exist in default.yml"); - return; - } - if (BlockInterface.isVanillaItem(blockID)) { - BlockInterface.placeVanillaBlock(blockID, location); - } - else { - NoteBlockMechanicFactory.setBlockModel(location.getBlock(), blockID); - } - } - - @Override - public void replaceBlock(Location location, String id) { - placeBlock(id, location); - } - - @Nullable - @Override - public String getID(Block block) { - NoteBlockMechanic mechanic = OraxenBlocks.getNoteBlockMechanic(block); - String id; - if (mechanic == null) { - id = block.getType().name(); - } - else { - id = mechanic.getItemID(); - } - return CustomFishing.getInstance().getTotemManager().getBlockID(id); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/block/VanillaBlockImpl.java b/src/main/java/net/momirealms/customfishing/integration/block/VanillaBlockImpl.java deleted file mode 100644 index 6a1686dd..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/block/VanillaBlockImpl.java +++ /dev/null @@ -1,54 +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.integration.block; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.integration.BlockInterface; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.jetbrains.annotations.Nullable; - -public class VanillaBlockImpl implements BlockInterface { - @Override - public void removeBlock(Block block) { - block.setType(Material.AIR); - } - - @Override - public void placeBlock(String id, Location location) { - String blockID = CustomFishing.getInstance().getTotemManager().getInvertedBlock(id); - if (blockID == null) { - AdventureUtils.consoleMessage(id + " does not exist in default.yml"); - return; - } - BlockInterface.placeVanillaBlock(blockID, location); - } - - @Nullable - @Override - public String getID(Block block) { - return CustomFishing.getInstance().getTotemManager().getBlockID(block.getType().name()); - } - - @Override - public void replaceBlock(Location location, String id) { - placeBlock(id, location); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/CustomFishingItemImpl.java b/src/main/java/net/momirealms/customfishing/integration/item/CustomFishingItemImpl.java deleted file mode 100644 index e27af9e7..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/item/CustomFishingItemImpl.java +++ /dev/null @@ -1,62 +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.integration.item; - -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.integration.ItemInterface; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.Damageable; -import org.jetbrains.annotations.Nullable; - -public class CustomFishingItemImpl implements ItemInterface { - - private final CustomFishing plugin; - - public CustomFishingItemImpl(CustomFishing plugin) { - this.plugin = plugin; - } - - @Override - @Nullable - public ItemStack build(String material, Player player) { - if (material.contains(":")) return null; - return plugin.getLootManager().build(material); - } - - @Override - public boolean loseCustomDurability(ItemStack itemStack, Player player) { - Damageable damageable = (Damageable) itemStack.getItemMeta(); - if (Math.random() < (1 / (double) (damageable.getEnchantLevel(Enchantment.DURABILITY) + 1))) { - damageable.setDamage(damageable.getDamage() + 1); - itemStack.setItemMeta(damageable); - } - return true; - } - - @Override - public @Nullable String getID(ItemStack itemStack) { - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound == null) return null; - return nbtCompound.getString("id"); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/EcoItemRegister.java b/src/main/java/net/momirealms/customfishing/integration/item/EcoItemRegister.java deleted file mode 100644 index e142966e..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/item/EcoItemRegister.java +++ /dev/null @@ -1,88 +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.integration.item; - -import com.willfp.eco.core.items.CustomItem; -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.loot.Item; -import net.momirealms.customfishing.util.ItemStackUtils; -import org.bukkit.NamespacedKey; - -import java.util.Map; - -public class EcoItemRegister { - - public static void registerItems() { - // Rods - for (Map.Entry entry : CustomFishing.getInstance().getEffectManager().getRodItems().entrySet()) { - new CustomItem( - new NamespacedKey(CustomFishing.getInstance(), "rod_" + entry.getKey()), - itemStack -> { - try { - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - return nbtCompound != null - && nbtCompound.getString("type").equalsIgnoreCase("rod") - && nbtCompound.getString("id").equalsIgnoreCase(entry.getKey()); - } catch (Exception e) { - return false; - } - }, - ItemStackUtils.getFromItem(entry.getValue()) - ).register(); - } - // Baits - for (Map.Entry entry : CustomFishing.getInstance().getEffectManager().getBaitItems().entrySet()) { - new CustomItem( - new NamespacedKey(CustomFishing.getInstance(), "bait_" + entry.getKey()), - itemStack -> { - try { - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - return nbtCompound != null - && nbtCompound.getString("type").equalsIgnoreCase("bait") - && nbtCompound.getString("id").equalsIgnoreCase(entry.getKey()); - } catch (Exception e) { - return false; - } - }, - ItemStackUtils.getFromItem(entry.getValue()) - ).register(); - } - // Utils - for (Map.Entry entry : CustomFishing.getInstance().getEffectManager().getUtilItems().entrySet()) { - new CustomItem( - new NamespacedKey(CustomFishing.getInstance(), "util_" + entry.getKey()), - itemStack -> { - try { - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - return nbtCompound != null - && nbtCompound.getString("type").equalsIgnoreCase("util") - && nbtCompound.getString("id").equalsIgnoreCase(entry.getKey()); - } catch (Exception e) { - return false; - } - }, - ItemStackUtils.getFromItem(entry.getValue()) - ).register(); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/ItemsAdderItemImpl.java b/src/main/java/net/momirealms/customfishing/integration/item/ItemsAdderItemImpl.java deleted file mode 100644 index 03b091c9..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/item/ItemsAdderItemImpl.java +++ /dev/null @@ -1,57 +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.integration.item; - -import dev.lone.itemsadder.api.CustomStack; -import net.momirealms.customfishing.integration.ItemInterface; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -public class ItemsAdderItemImpl implements ItemInterface { - - @Override - @Nullable - public ItemStack build(String material, Player player) { - if (!material.startsWith("ItemsAdder:")) return null; - material = material.substring(11); - CustomStack customStack = CustomStack.getInstance(material); - return customStack == null ? null : customStack.getItemStack(); - } - - @Override - public boolean loseCustomDurability(ItemStack itemStack, Player player) { - CustomStack customStack = CustomStack.byItemStack(itemStack); - if (customStack == null) return false; - if (customStack.hasCustomDurability()) { - if (Math.random() < (1 / (double) (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1))) { - customStack.setDurability(customStack.getDurability() - 1); - } - return true; - } - return false; - } - - @Override - public @Nullable String getID(ItemStack itemStack) { - CustomStack customStack = CustomStack.byItemStack(itemStack); - if (customStack == null) return null; - return customStack.getNamespacedID(); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/MMOItemsItemImpl.java b/src/main/java/net/momirealms/customfishing/integration/item/MMOItemsItemImpl.java deleted file mode 100644 index 0009699f..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/item/MMOItemsItemImpl.java +++ /dev/null @@ -1,65 +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.integration.item; - -import de.tr7zw.changeme.nbtapi.NBTItem; -import net.Indyuce.mmoitems.MMOItems; -import net.Indyuce.mmoitems.api.Type; -import net.Indyuce.mmoitems.api.interaction.util.DurabilityItem; -import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; -import net.momirealms.customfishing.integration.ItemInterface; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -import java.util.Locale; - -public class MMOItemsItemImpl implements ItemInterface { - - @Nullable - @Override - public ItemStack build(String material, Player player) { - if (!material.startsWith("MMOItems:")) return null; - material = material.substring(9); - String[] split = material.split(":"); - MMOItem mmoItem = MMOItems.plugin.getMMOItem(Type.get(split[0]), split[1].toUpperCase(Locale.ENGLISH)); - return mmoItem == null ? null : mmoItem.newBuilder().build(); - } - - @Override - public boolean loseCustomDurability(ItemStack itemStack, Player player) { - NBTItem nbtItem = new NBTItem(itemStack); - if (!nbtItem.hasTag("MMOITEMS_MAX_DURABILITY")) return false; - DurabilityItem durabilityItem = new DurabilityItem(player, itemStack); - if (Math.random() < (1 / (double) (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1))) { - durabilityItem.decreaseDurability(1); - final ItemStack newVersion = durabilityItem.toItem(); - if (newVersion == null) return false; - itemStack.setItemMeta(newVersion.getItemMeta()); - } - return true; - } - - @Override - public @Nullable String getID(ItemStack itemStack) { - NBTItem nbtItem = new NBTItem(itemStack); - if (nbtItem.getCompound("CustomFishing") != null || !nbtItem.hasTag("MMOITEMS_ITEM_ID")) return null; - return nbtItem.getString("MMOITEMS_ITEM_ID"); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/McMMOTreasure.java b/src/main/java/net/momirealms/customfishing/integration/item/McMMOTreasure.java deleted file mode 100644 index bf9274c2..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/item/McMMOTreasure.java +++ /dev/null @@ -1,147 +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.integration.item; - -import com.gmail.nossr50.config.treasure.FishingTreasureConfig; -import com.gmail.nossr50.datatypes.skills.SubSkillType; -import com.gmail.nossr50.datatypes.treasure.EnchantmentTreasure; -import com.gmail.nossr50.datatypes.treasure.FishingTreasure; -import com.gmail.nossr50.datatypes.treasure.FishingTreasureBook; -import com.gmail.nossr50.datatypes.treasure.Rarity; -import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.skills.fishing.FishingManager; -import com.gmail.nossr50.util.ItemUtils; -import com.gmail.nossr50.util.Misc; -import com.gmail.nossr50.util.Permissions; -import com.gmail.nossr50.util.player.UserManager; -import com.gmail.nossr50.util.skills.RankUtils; -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class McMMOTreasure { - - public static ItemStack getTreasure(Player player){ - FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager(); - FishingTreasure treasure = getFishingTreasure(player, fishingManager.getLootTier()); - ItemStack treasureDrop; - if (treasure != null) { - if (treasure instanceof FishingTreasureBook) { - treasureDrop = ItemUtils.createEnchantBook((FishingTreasureBook) treasure); - } else { - treasureDrop = treasure.getDrop().clone(); - } - Map enchants = new HashMap<>(); - if(treasure instanceof FishingTreasureBook) { - if(treasureDrop.getItemMeta() != null) { - enchants = new HashMap<>(treasureDrop.getItemMeta().getEnchants()); - } - } else { - if (isMagicHunterEnabled(player) && ItemUtils.isEnchantable(treasureDrop)) { - enchants = processMagicHunter(treasureDrop, fishingManager.getLootTier()); - } - } - if (!enchants.isEmpty()) { - treasureDrop.addUnsafeEnchantments(enchants); - } - return treasureDrop; - } - return null; - } - - public static boolean isMagicHunterEnabled(Player player) { - return RankUtils.hasUnlockedSubskill(player, SubSkillType.FISHING_MAGIC_HUNTER) - && RankUtils.hasUnlockedSubskill(player, SubSkillType.FISHING_TREASURE_HUNTER) - && Permissions.isSubSkillEnabled(player, SubSkillType.FISHING_TREASURE_HUNTER); - } - - private static Map processMagicHunter(@NotNull ItemStack treasureDrop, int tier) { - Map enchants = new HashMap<>(); - List fishingEnchantments = null; - double diceRoll = Misc.getRandom().nextDouble() * 100; - for (Rarity rarity : Rarity.values()) { - double dropRate = FishingTreasureConfig.getInstance().getEnchantmentDropRate(tier, rarity); - if (diceRoll <= dropRate) { - if (treasureDrop.getType() == Material.ENCHANTED_BOOK) { - diceRoll = dropRate + 1; - continue; - } - fishingEnchantments = FishingTreasureConfig.getInstance().fishingEnchantments.get(rarity); - break; - } - diceRoll -= dropRate; - } - if (fishingEnchantments == null) { - return enchants; - } - Collections.shuffle(fishingEnchantments, Misc.getRandom()); - int specificChance = 1; - for (EnchantmentTreasure enchantmentTreasure : fishingEnchantments) { - Enchantment possibleEnchantment = enchantmentTreasure.getEnchantment(); - if (treasureDrop.getItemMeta().hasConflictingEnchant(possibleEnchantment) || Misc.getRandom().nextInt(specificChance) != 0) { - continue; - } - enchants.put(possibleEnchantment, enchantmentTreasure.getLevel()); - specificChance *= 2; - } - return enchants; - } - - private static @Nullable FishingTreasure getFishingTreasure(Player player, int tier) { - double diceRoll = Misc.getRandom().nextDouble() * 100; - int luck; - if (player.getInventory().getItemInMainHand().getType() == Material.FISHING_ROD) { - luck = player.getInventory().getItemInMainHand().getEnchantmentLevel(Enchantment.LUCK); - } - else { - luck = player.getInventory().getItemInOffHand().getEnchantmentLevel(Enchantment.LUCK); - } - diceRoll *= (1.0 - luck * mcMMO.p.getGeneralConfig().getFishingLureModifier() / 100); - FishingTreasure treasure = null; - for (Rarity rarity : Rarity.values()) { - double dropRate = FishingTreasureConfig.getInstance().getItemDropRate(tier, rarity); - if (diceRoll <= dropRate) { - List fishingTreasures = FishingTreasureConfig.getInstance().fishingRewards.get(rarity); - if (fishingTreasures.isEmpty()) { - return null; - } - treasure = fishingTreasures.get(Misc.getRandom().nextInt(fishingTreasures.size())); - break; - } - diceRoll -= dropRate; - } - if (treasure == null) { - return null; - } - ItemStack treasureDrop = treasure.getDrop().clone(); - short maxDurability = treasureDrop.getType().getMaxDurability(); - if (maxDurability > 0) { - treasureDrop.setDurability((short) (Misc.getRandom().nextInt(maxDurability))); - } - treasure.setDrop(treasureDrop); - return treasure; - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/NeigeItemsImpl.java b/src/main/java/net/momirealms/customfishing/integration/item/NeigeItemsImpl.java deleted file mode 100644 index 1ecc8098..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/item/NeigeItemsImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.momirealms.customfishing.integration.item; - -import net.momirealms.customfishing.integration.ItemInterface; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; -import pers.neige.neigeitems.item.ItemDurability; -import pers.neige.neigeitems.item.ItemInfo; -import pers.neige.neigeitems.manager.ItemManager; -import pers.neige.neigeitems.utils.ItemUtils; - -public class NeigeItemsImpl implements ItemInterface { - - @Override - public @Nullable ItemStack build(String material, Player player) { - if (!material.startsWith("NeigeItems:")) return null; - material = material.substring(11); - return ItemManager.INSTANCE.getItemStack(material, player); - } - - @Override - public boolean loseCustomDurability(ItemStack itemStack, Player player) { - ItemInfo itemInfo = ItemUtils.isNiItem(itemStack); - if (itemInfo == null) return false; - ItemDurability.INSTANCE.damage(player, itemStack, 1, true, null); - return true; - } - - @Override - public @Nullable String getID(ItemStack itemStack) { - ItemInfo itemInfo = ItemUtils.isNiItem(itemStack); - if (itemInfo != null) { - return itemInfo.getId(); - } - return null; - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/item/OraxenItemImpl.java b/src/main/java/net/momirealms/customfishing/integration/item/OraxenItemImpl.java deleted file mode 100644 index a7c1247e..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/item/OraxenItemImpl.java +++ /dev/null @@ -1,57 +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.integration.item; - -import io.th0rgal.oraxen.api.OraxenItems; -import io.th0rgal.oraxen.items.ItemBuilder; -import io.th0rgal.oraxen.mechanics.provided.gameplay.durability.DurabilityMechanic; -import io.th0rgal.oraxen.mechanics.provided.gameplay.durability.DurabilityMechanicFactory; -import net.momirealms.customfishing.integration.ItemInterface; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -public class OraxenItemImpl implements ItemInterface { - - @Override - @Nullable - public ItemStack build(String material, Player player) { - if (!material.startsWith("Oraxen:")) return null; - material = material.substring(7); - ItemBuilder itemBuilder = OraxenItems.getItemById(material); - return itemBuilder == null ? null : itemBuilder.build(); - } - - @Override - public boolean loseCustomDurability(ItemStack itemStack, Player player) { - DurabilityMechanic mechanic = (DurabilityMechanic) DurabilityMechanicFactory.get().getMechanic(OraxenItems.getIdByItem(itemStack)); - if (mechanic == null) { - return false; - } - if (Math.random() < (1 / (double) (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1))) { - mechanic.changeDurability(itemStack, -1); - } - return true; - } - - @Override - public @Nullable String getID(ItemStack itemStack) { - return OraxenItems.getIdByItem(itemStack); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/job/JobsRebornImpl.java b/src/main/java/net/momirealms/customfishing/integration/job/JobsRebornImpl.java deleted file mode 100644 index 94f89434..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/job/JobsRebornImpl.java +++ /dev/null @@ -1,92 +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.integration.job; - -import com.gamingmesh.jobs.Jobs; -import com.gamingmesh.jobs.container.*; -import com.gamingmesh.jobs.listeners.JobsPaymentListener; -import net.momirealms.customfishing.api.event.FishResultEvent; -import net.momirealms.customfishing.fishing.FishResult; -import net.momirealms.customfishing.integration.JobInterface; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -import java.util.List; - -public class JobsRebornImpl implements JobInterface, Listener { - - @Override - public void addXp(Player player, double amount) { - JobsPlayer jobsPlayer = Jobs.getPlayerManager().getJobsPlayer(player); - if (jobsPlayer != null) { - List jobs = jobsPlayer.getJobProgression(); - Job job = Jobs.getJob("Fisherman"); - for (JobProgression progression : jobs) - if (progression.getJob().equals(job)) - progression.addExperience(amount); - } - } - - @Override - public int getLevel(Player player) { - JobsPlayer jobsPlayer = Jobs.getPlayerManager().getJobsPlayer(player); - if (jobsPlayer != null) { - List jobs = jobsPlayer.getJobProgression(); - Job job = Jobs.getJob("Fisherman"); - for (JobProgression progression : jobs) - if (progression.getJob().equals(job)) - return progression.getLevel(); - } - return 0; - } - - @EventHandler - public void onFish(FishResultEvent event) { - if (event.isCancelled() || event.getResult() == FishResult.FAILURE) return; - Player player = event.getPlayer(); - if (!Jobs.getGCManager().canPerformActionInWorld(player.getWorld())) return; - if (!JobsPaymentListener.payIfCreative(player)) - return; - - if (!Jobs.getPermissionHandler().hasWorldPermission(player, player.getLocation().getWorld().getName())) - return; - - JobsPlayer jobsPlayer = Jobs.getPlayerManager().getJobsPlayer(player); - if (jobsPlayer == null) return; - - Jobs.action(jobsPlayer, new CustomFishingInfo(event.getLootID(), ActionType.MMKILL)); - } - - public static class CustomFishingInfo extends BaseActionInfo { - private final String name; - - public CustomFishingInfo(String name, ActionType type) { - super(type); - this.name = name; - } - - public String getName() { - return this.name; - } - - public String getNameWithSub() { - return this.name; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/mob/MythicMobsMobImpl.java b/src/main/java/net/momirealms/customfishing/integration/mob/MythicMobsMobImpl.java deleted file mode 100644 index 5ec555df..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/mob/MythicMobsMobImpl.java +++ /dev/null @@ -1,59 +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.integration.mob; - -import io.lumine.mythic.api.adapters.AbstractLocation; -import io.lumine.mythic.api.adapters.AbstractVector; -import io.lumine.mythic.api.mobs.MythicMob; -import io.lumine.mythic.bukkit.MythicBukkit; -import io.lumine.mythic.bukkit.utils.serialize.Position; -import io.lumine.mythic.core.mobs.ActiveMob; -import net.momirealms.customfishing.fishing.loot.Mob; -import net.momirealms.customfishing.fishing.loot.MobVector; -import net.momirealms.customfishing.integration.MobInterface; -import org.bukkit.Location; -import org.bukkit.util.Vector; - -import java.util.Optional; - -public class MythicMobsMobImpl implements MobInterface { - - private MythicBukkit mythicBukkit; - - public MythicMobsMobImpl() { - this.mythicBukkit = MythicBukkit.inst(); - } - - @Override - public void summon(Location playerLoc, Location summonLoc, Mob mob){ - if (this.mythicBukkit == null || mythicBukkit.isClosed()) { - this.mythicBukkit = MythicBukkit.inst(); - } - Optional mythicMob = mythicBukkit.getMobManager().getMythicMob(mob.getMobID()); - if (mythicMob.isPresent()) { - MythicMob theMob = mythicMob.get(); - Position position = Position.of(summonLoc); - AbstractLocation abstractLocation = new AbstractLocation(position); - ActiveMob activeMob = theMob.spawn(abstractLocation, mob.getMobLevel()); - MobVector mobVector = mob.getMobVector(); - Vector vector = playerLoc.subtract(summonLoc).toVector().multiply((mobVector.horizontal()) - 1); - vector = vector.setY((vector.getY() + 0.2) * mobVector.vertical()); - activeMob.getEntity().setVelocity(new AbstractVector(vector.getX(), vector.getY(), vector.getZ())); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/papi/CompetitionPapi.java b/src/main/java/net/momirealms/customfishing/integration/papi/CompetitionPapi.java deleted file mode 100644 index 49ff9972..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/papi/CompetitionPapi.java +++ /dev/null @@ -1,96 +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.integration.papi; - -import me.clip.placeholderapi.expansion.PlaceholderExpansion; -import net.momirealms.customfishing.fishing.competition.Competition; -import net.momirealms.customfishing.fishing.competition.ranking.RankingInterface; -import net.momirealms.customfishing.manager.MessageManager; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; - -public class CompetitionPapi extends PlaceholderExpansion { - - @Override - public @NotNull String getIdentifier() { - return "competition"; - } - - @Override - public @NotNull String getAuthor() { - return "XiaoMoMi"; - } - - @Override - public @NotNull String getVersion() { - return "1.3"; - } - - @Override - public boolean persist() { - return true; - } - - @Override - public @Nullable String onPlaceholderRequest(Player player, @NotNull String params) { - if (Competition.currentCompetition == null) return ""; - RankingInterface ranking = Competition.currentCompetition.getRanking(); - switch (params) { - case "rank" -> { - return Competition.currentCompetition.getPlayerRank(player); - } - case "score" -> { - return String.format("%.1f", Competition.currentCompetition.getScore(player)); - } - case "time" -> { - return String.valueOf(Competition.currentCompetition.getRemainingTime()); - } - case "minute" -> { - return String.format("%02d", Competition.currentCompetition.getRemainingTime() / 60); - } - case "second" -> { - return String.format("%02d", Competition.currentCompetition.getRemainingTime() % 60); - } - case "goal" -> { - return Competition.currentCompetition.getGoal().getDisplay(); - } - case "1st_score" -> { - return ranking.getScoreAt(1) <= 0 ? MessageManager.noScore : String.format("%.1f", ranking.getScoreAt(1)); - } - case "1st_player" -> { - return Optional.ofNullable(ranking.getPlayerAt(1)).orElse(MessageManager.noPlayer); - } - case "2nd_score" -> { - return ranking.getScoreAt(2) <= 0 ? MessageManager.noScore : String.format("%.1f", ranking.getScoreAt(2)); - } - case "2nd_player" -> { - return Optional.ofNullable(ranking.getPlayerAt(2)).orElse(MessageManager.noPlayer); - } - case "3rd_score" -> { - return ranking.getScoreAt(3) <= 0 ? MessageManager.noScore : String.format("%.1f", ranking.getScoreAt(3)); - } - case "3rd_player" -> { - return Optional.ofNullable(ranking.getPlayerAt(3)).orElse(MessageManager.noPlayer); - } - } - return "null"; - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/papi/PlaceholderManager.java b/src/main/java/net/momirealms/customfishing/integration/papi/PlaceholderManager.java deleted file mode 100644 index ca36a01c..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/papi/PlaceholderManager.java +++ /dev/null @@ -1,166 +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.integration.papi; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.competition.Competition; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.manager.MessageManager; -import net.momirealms.customfishing.object.Function; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class PlaceholderManager extends Function { - - private CustomFishing plugin; - private final Pattern basicPattern = Pattern.compile("%([^%]*)%"); - private final Pattern betterPattern = Pattern.compile("\\{(.+?)\\}"); - private final Pattern allPattern = Pattern.compile("%([^%]*)%|\\{(.+?)\\}"); - private CompetitionPapi competitionPapi; - private StatisticsPapi statisticsPapi; - private boolean hasPlaceholderAPI = false; - - public PlaceholderManager(CustomFishing plugin) { - this.plugin = plugin; - if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { - hasPlaceholderAPI = true; - this.competitionPapi = new CompetitionPapi(); - this.statisticsPapi = new StatisticsPapi(plugin); - } - } - - @Override - public void load() { - if (competitionPapi != null) competitionPapi.register(); - if (statisticsPapi != null) statisticsPapi.register(); - } - - @Override - public void unload() { - if (this.competitionPapi != null) competitionPapi.unregister(); - if (this.statisticsPapi != null) statisticsPapi.unregister(); - } - - public String parse(OfflinePlayer player, String text) { - if (hasPlaceholderAPI) { - return ParseUtil.setPlaceholders(player, parseInner(player, text)); - } else { - return parseInner(player, text); - } - } - - public String parseInner(OfflinePlayer player, String text) { - List papis = detectBetterPlaceholders(text); - for (String papi : papis) { - text = text.replace(papi, parseSingleInner(player, papi)); - } - return text; - } - - public String parseSinglePlaceholder(OfflinePlayer player, String placeholder) { - if (placeholder.startsWith("{")) { - return parseSingleInner(player, placeholder); - } else if (hasPlaceholderAPI) { - return ParseUtil.setPlaceholders(player, placeholder); - } - return placeholder; - } - - public List detectBasicPlaceholders(String text) { - List placeholders = new ArrayList<>(); - Matcher matcher = basicPattern.matcher(text); - while (matcher.find()) placeholders.add(matcher.group()); - return placeholders; - } - - public List detectBetterPlaceholders(String text) { - List placeholders = new ArrayList<>(); - Matcher matcher = betterPattern.matcher(text); - while (matcher.find()) placeholders.add(matcher.group()); - return placeholders; - } - - public List detectAllPlaceholders(String text) { - List placeholders = new ArrayList<>(); - Matcher matcher = allPattern.matcher(text); - while (matcher.find()) placeholders.add(matcher.group()); - return placeholders; - } - - public List detectPlaceholders(String text) { - return hasPlaceholderAPI ? detectAllPlaceholders(text) : detectBetterPlaceholders(text); - } - - public String parseSingleInner(OfflinePlayer player, String placeholder) { - switch (placeholder) { - case "{player}" -> { - return player == null ? placeholder : player.getName(); - } - case "{date}" -> { - return LocalDateTime.now().format(DateTimeFormatter.ofPattern(ConfigManager.dateFormat)); - } - case "{time}" -> { - return String.valueOf(Competition.currentCompetition.getRemainingTime()); - } - case "{goal}" -> { - return Competition.currentCompetition.getGoal().getDisplay(); - } - case "{minute}" -> { - return String.format("%02d", Competition.currentCompetition.getRemainingTime() / 60); - } - case "{second}" -> { - return String.format("%02d", Competition.currentCompetition.getRemainingTime() % 60); - } - case "{rank}" -> { - return player == null ? placeholder : Competition.currentCompetition.getPlayerRank(player); - } - case "{score}" -> { - return player == null ? placeholder : String.format("%.1f", Competition.currentCompetition.getScore(player)); - } - case "{1st_player}" -> { - return Optional.ofNullable(Competition.currentCompetition.getRanking().getPlayerAt(1)).orElse(MessageManager.noPlayer); - } - case "{1st_score}" -> { - return Competition.currentCompetition.getRanking().getScoreAt(1) <= 0 ? MessageManager.noScore : String.format("%.1f", Competition.currentCompetition.getRanking().getScoreAt(1)); - } - case "{2nd_player}" -> { - return Optional.ofNullable(Competition.currentCompetition.getRanking().getPlayerAt(2)).orElse(MessageManager.noPlayer); - } - case "{2nd_score}" -> { - return Competition.currentCompetition.getRanking().getScoreAt(2) <= 0 ? MessageManager.noScore : String.format("%.1f", Competition.currentCompetition.getRanking().getScoreAt(2)); - } - case "{3rd_player}" -> { - return Optional.ofNullable(Competition.currentCompetition.getRanking().getPlayerAt(3)).orElse(MessageManager.noPlayer); - } - case "{3rd_score}" -> { - return Competition.currentCompetition.getRanking().getScoreAt(3) <= 0 ? MessageManager.noScore : String.format("%.1f", Competition.currentCompetition.getRanking().getScoreAt(3)); - } - default -> { - return placeholder; - } - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/papi/StatisticsPapi.java b/src/main/java/net/momirealms/customfishing/integration/papi/StatisticsPapi.java deleted file mode 100644 index 46612930..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/papi/StatisticsPapi.java +++ /dev/null @@ -1,69 +0,0 @@ -package net.momirealms.customfishing.integration.papi; - -import me.clip.placeholderapi.expansion.PlaceholderExpansion; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.manager.StatisticsManager; -import org.bukkit.OfflinePlayer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class StatisticsPapi extends PlaceholderExpansion { - - private final StatisticsManager statisticsManager; - - public StatisticsPapi(CustomFishing plugin) { - this.statisticsManager = plugin.getStatisticsManager(); - } - - @Override - public @NotNull String getIdentifier() { - return "fishingstats"; - } - - @Override - public @NotNull String getAuthor() { - return "XiaoMoMi"; - } - - @Override - public @NotNull String getVersion() { - return "1.3"; - } - - @Override - public boolean persist() { - return true; - } - - @Override - public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) { - String[] args = params.split("_", 2); - switch (args[0]) { - case "total" -> { - return String.valueOf(statisticsManager.getTotalFishAmount(player.getUniqueId())); - } - case "amount" -> { - if (args[1].equals("")) return "lack args"; - return String.valueOf(statisticsManager.getFishAmount(player.getUniqueId(), args[1])); - } - case "hascaught" -> { - if (args[1].equals("")) return "lack args"; - return String.valueOf(statisticsManager.hasFished(player.getUniqueId(), args[1])); - } - case "category" -> { - String[] moreArgs = args[1].split("_", 2); - if (moreArgs[1].equals("")) return "lack args"; - switch (moreArgs[0]) { - case "total" -> { - return String.valueOf(statisticsManager.getCategoryTotalFishAmount(player.getUniqueId(), moreArgs[1])); - } - case "progress" -> { - String progress = String.format("%.1f", statisticsManager.getCategoryUnlockProgress(player.getUniqueId(), moreArgs[1])); - return progress.equals("100.0") ? "100" : progress; - } - } - } - } - return "null"; - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/quest/BattlePassCFQuest.java b/src/main/java/net/momirealms/customfishing/integration/quest/BattlePassCFQuest.java deleted file mode 100644 index dd3ae57a..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/quest/BattlePassCFQuest.java +++ /dev/null @@ -1,67 +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.integration.quest; - -import io.github.battlepass.BattlePlugin; -import io.github.battlepass.api.events.server.PluginReloadEvent; -import io.github.battlepass.quests.service.base.ExternalQuestContainer; -import io.github.battlepass.registry.quest.QuestRegistry; -import net.momirealms.customfishing.api.event.FishResultEvent; -import net.momirealms.customfishing.fishing.FishResult; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -public class BattlePassCFQuest implements Listener { - - public static void register() { - QuestRegistry questRegistry = BattlePlugin.getApi().getQuestRegistry(); - questRegistry.hook("customfishing", FishQuest::new); - } - - @EventHandler(ignoreCancelled = true) - public void onBattlePassReload(PluginReloadEvent event) { - register(); - } - - private static class FishQuest extends ExternalQuestContainer { - - public FishQuest(BattlePlugin battlePlugin) { - super(battlePlugin, "customfishing"); - } - - @EventHandler - public void onFishCaught(FishResultEvent event) { - if (event.isCancelled() || event.getResult() == FishResult.FAILURE) - return; - Player player = event.getPlayer(); - if (event.getLootID() != null) - this.executionBuilder("fish") - .player(player) - .root(event.getLootID()) - .progress(event.isDouble() ? 2 : 1) - .buildAndExecute(); - if (event.getLoot() != null && event.getLoot().getGroup() != null) - this.executionBuilder("group") - .player(player) - .root(event.getLoot().getGroup()) - .progress(event.isDouble() ? 2 : 1) - .buildAndExecute(); - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/integration/quest/ClueScrollCFQuest.java b/src/main/java/net/momirealms/customfishing/integration/quest/ClueScrollCFQuest.java deleted file mode 100644 index 48fd7c54..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/quest/ClueScrollCFQuest.java +++ /dev/null @@ -1,47 +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.integration.quest; - -import com.electro2560.dev.cluescrolls.api.*; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.api.event.FishResultEvent; -import net.momirealms.customfishing.fishing.FishResult; -import net.momirealms.customfishing.fishing.loot.Loot; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -public class ClueScrollCFQuest implements Listener { - - private final CustomClue idClue; - private final CustomClue groupClue; - - public ClueScrollCFQuest() { - idClue = ClueScrollsAPI.getInstance().registerCustomClue(CustomFishing.getInstance(), "fish", new ClueConfigData("fish_id", DataType.STRING)); - groupClue = ClueScrollsAPI.getInstance().registerCustomClue(CustomFishing.getInstance(), "group", new ClueConfigData("fish_group", DataType.STRING)); - } - - @EventHandler - public void onFish(FishResultEvent event) { - if (event.isCancelled() || event.getResult() == FishResult.FAILURE) - return; - if (event.getLootID() != null) - idClue.handle(event.getPlayer(), event.isDouble() ? 2 : 1, new ClueDataPair("fish_id", event.getLootID())); - if (event.getLoot() != null && event.getLoot().getGroup() != null) - groupClue.handle(event.getPlayer(), event.isDouble() ? 2 : 1, new ClueDataPair("fish_group", event.getLoot().getGroup())); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/quest/NewBetonQuestCFQuest.java b/src/main/java/net/momirealms/customfishing/integration/quest/NewBetonQuestCFQuest.java deleted file mode 100644 index 22846bd7..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/quest/NewBetonQuestCFQuest.java +++ /dev/null @@ -1,112 +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.integration.quest; - -import net.momirealms.customfishing.api.event.FishResultEvent; -import net.momirealms.customfishing.fishing.FishResult; -import net.momirealms.customfishing.util.AdventureUtils; -import org.betonquest.betonquest.BetonQuest; -import org.betonquest.betonquest.Instruction; -import org.betonquest.betonquest.VariableNumber; -import org.betonquest.betonquest.api.CountingObjective; -import org.betonquest.betonquest.api.profiles.OnlineProfile; -import org.betonquest.betonquest.api.profiles.Profile; -import org.betonquest.betonquest.exceptions.InstructionParseException; -import org.betonquest.betonquest.utils.PlayerConverter; -import org.betonquest.betonquest.utils.location.CompoundLocation; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; - -import java.util.Collections; -import java.util.HashSet; - -public class NewBetonQuestCFQuest extends CountingObjective implements Listener { - - private final CompoundLocation playerLocation; - private final VariableNumber rangeVar; - private final HashSet loot_ids; - - public NewBetonQuestCFQuest(Instruction instruction) throws InstructionParseException { - super(instruction, "loot_to_fish"); - loot_ids = new HashSet<>(); - Collections.addAll(loot_ids, instruction.getArray()); - targetAmount = instruction.getVarNum(); - preCheckAmountNotLessThanOne(targetAmount); - final String pack = instruction.getPackage().getQuestPath(); - final String loc = instruction.getOptional("playerLocation"); - final String range = instruction.getOptional("range"); - if (loc != null && range != null) { - playerLocation = new CompoundLocation(pack, loc); - rangeVar = new VariableNumber(pack, range); - } else { - playerLocation = null; - rangeVar = null; - } - } - - public static void register() { - BetonQuest.getInstance().registerObjectives("customfishing", NewBetonQuestCFQuest.class); - } - - @EventHandler - public void onFish(FishResultEvent event) { - if (event.getResult() != FishResult.FAILURE) { - OnlineProfile onlineProfile = PlayerConverter.getID(event.getPlayer()); - if (!containsPlayer(onlineProfile)) { - return; - } - if (isInvalidLocation(event, onlineProfile)) { - return; - } - if (this.loot_ids.contains(event.getLootID()) && this.checkConditions(onlineProfile)) { - getCountingData(onlineProfile).progress(event.isDouble() ? 1 : 2); - completeIfDoneOrNotify(onlineProfile); - } - } - } - - private boolean isInvalidLocation(FishResultEvent event, final Profile profile) { - if (playerLocation == null || rangeVar == null) { - return false; - } - - final Location targetLocation; - try { - targetLocation = playerLocation.getLocation(profile); - } catch (final org.betonquest.betonquest.exceptions.QuestRuntimeException e) { - AdventureUtils.consoleMessage(e.getMessage()); - return true; - } - final int range = rangeVar.getInt(profile); - final Location playerLoc = event.getPlayer().getLocation(); - return !playerLoc.getWorld().equals(targetLocation.getWorld()) || targetLocation.distanceSquared(playerLoc) > range * range; - } - - @Override - public void start() { - Bukkit.getPluginManager().registerEvents(this, BetonQuest.getInstance()); - } - - @Override - public void stop() { - HandlerList.unregisterAll(this); - } -} diff --git a/src/main/java/net/momirealms/customfishing/integration/quest/OldBetonQuestCFQuest.java b/src/main/java/net/momirealms/customfishing/integration/quest/OldBetonQuestCFQuest.java deleted file mode 100644 index 3552c488..00000000 --- a/src/main/java/net/momirealms/customfishing/integration/quest/OldBetonQuestCFQuest.java +++ /dev/null @@ -1,159 +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.integration.quest; - -import net.momirealms.customfishing.api.event.FishResultEvent; -import net.momirealms.customfishing.fishing.FishResult; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import pl.betoncraft.betonquest.BetonQuest; -import pl.betoncraft.betonquest.Instruction; -import pl.betoncraft.betonquest.api.Objective; -import pl.betoncraft.betonquest.config.Config; -import pl.betoncraft.betonquest.exceptions.InstructionParseException; -import pl.betoncraft.betonquest.exceptions.QuestRuntimeException; -import pl.betoncraft.betonquest.utils.LogUtils; -import pl.betoncraft.betonquest.utils.PlayerConverter; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Locale; -import java.util.logging.Level; - -public class OldBetonQuestCFQuest extends Objective implements Listener { - - private final HashSet loot_ids = new HashSet<>(); - private final int amount; - private final boolean notify; - private final int notifyInterval; - - public OldBetonQuestCFQuest(Instruction instruction) throws InstructionParseException { - super(instruction); - this.template = FishData.class; - this.notifyInterval = instruction.getInt(instruction.getOptional("notify"), 1); - this.notify = instruction.hasArgument("notify") || this.notifyInterval > 1; - this.amount = instruction.getInt(instruction.getOptional("amount"), 1); - Collections.addAll(this.loot_ids, instruction.getArray()); - } - - public static void register() { - BetonQuest.getInstance().registerObjectives("customfishing", OldBetonQuestCFQuest.class); - } - - @Override - public void start() { - Bukkit.getPluginManager().registerEvents(this, BetonQuest.getInstance()); - } - - @Override - public void stop() { - HandlerList.unregisterAll(this); - } - - @Override - public String getDefaultDataInstruction() { - return Integer.toString(this.amount); - } - - @Override - public String getProperty(String name, String playerID) { - return switch (name.toLowerCase(Locale.ROOT)) { - case "amount" -> - Integer.toString(this.amount - ((OldBetonQuestCFQuest.FishData) this.dataMap.get(playerID)).getAmount()); - case "left" -> Integer.toString(((OldBetonQuestCFQuest.FishData) this.dataMap.get(playerID)).getAmount()); - case "total" -> Integer.toString(this.amount); - default -> ""; - }; - } - - private boolean isValidPlayer(Player player) { - if (player == null) { - return false; - } else { - return player.isOnline() && player.isValid(); - } - } - - @EventHandler - public void onFish(FishResultEvent event) { - if (event.getResult() != FishResult.FAILURE) { - String playerID = PlayerConverter.getID(event.getPlayer()); - if (this.containsPlayer(playerID)) { - if (this.loot_ids.contains(event.getLootID())) { - if (this.checkConditions(playerID)) { - if (!isValidPlayer(event.getPlayer())) { - return; - } - FishData fishData = (FishData) this.dataMap.get(playerID); - fishData.catchFish(event.isDouble() ? 1 : 2); - if (fishData.finished()) { - this.completeObjective(playerID); - } - else if (this.notify && fishData.getAmount() % this.notifyInterval == 0) { - try { - Config.sendNotify(this.instruction.getPackage().getName(), playerID, "loot_to_fish", new String[]{String.valueOf(fishData.getAmount())}, "loot_to_fish,info"); - } catch (QuestRuntimeException e1) { - try { - LogUtils.getLogger().log(Level.WARNING, "The notify system was unable to play a sound for the 'loot_to_fish' category in '" + this.instruction.getObjective().getFullID() + "'. Error was: '" + e1.getMessage() + "'"); - } catch (InstructionParseException e2) { - LogUtils.logThrowableReport(e2); - } - } - } - } - } - } - } - } - - public static class FishData extends Objective.ObjectiveData { - private int amount; - - public FishData(String instruction, String playerID, String objID) { - super(instruction, playerID, objID); - try { - this.amount = Integer.parseInt(instruction); - } - catch (NumberFormatException e) { - AdventureUtils.consoleMessage("[CustomFishing] NumberFormatException"); - this.amount = 1; - } - } - - public void catchFish(int caughtAmount) { - this.amount -= caughtAmount; - this.update(); - } - - public int getAmount() { - return this.amount; - } - - public String toString() { - return String.valueOf(this.amount); - } - - public boolean finished() { - return this.amount <= 0; - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/listener/BreakBlockListener.java b/src/main/java/net/momirealms/customfishing/listener/BreakBlockListener.java deleted file mode 100644 index 07b4f8d4..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/BreakBlockListener.java +++ /dev/null @@ -1,38 +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.listener; - -import net.momirealms.customfishing.object.Function; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; - -public class BreakBlockListener implements Listener { - - private final Function function; - - public BreakBlockListener(Function function) { - this.function = function; - } - - @EventHandler - public void onBreak(BlockBreakEvent event) { - if (event.isCancelled()) return; - function.onBreakBlock(event); - } -} diff --git a/src/main/java/net/momirealms/customfishing/listener/ConsumeItemListener.java b/src/main/java/net/momirealms/customfishing/listener/ConsumeItemListener.java deleted file mode 100644 index dc33f33d..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/ConsumeItemListener.java +++ /dev/null @@ -1,38 +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.listener; - -import net.momirealms.customfishing.object.Function; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerItemConsumeEvent; - -public class ConsumeItemListener implements Listener { - - private final Function function; - - public ConsumeItemListener(Function function) { - this.function = function; - } - - @EventHandler - public void onConsumeItem(PlayerItemConsumeEvent event) { - if (event.isCancelled()) return; - function.onConsumeItem(event); - } -} diff --git a/src/main/java/net/momirealms/customfishing/listener/InteractListener.java b/src/main/java/net/momirealms/customfishing/listener/InteractListener.java deleted file mode 100644 index 7a77b749..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/InteractListener.java +++ /dev/null @@ -1,37 +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.listener; - -import net.momirealms.customfishing.object.Function; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerInteractEvent; - -public class InteractListener implements Listener { - - private final Function function; - - public InteractListener(Function function) { - this.function = function; - } - - @EventHandler - public void onInteract(PlayerInteractEvent event) { - function.onInteract(event); - } -} diff --git a/src/main/java/net/momirealms/customfishing/listener/InventoryListener.java b/src/main/java/net/momirealms/customfishing/listener/InventoryListener.java deleted file mode 100644 index 16c2c6d8..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/InventoryListener.java +++ /dev/null @@ -1,49 +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.listener; - -import net.momirealms.customfishing.object.InventoryFunction; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryDragEvent; - -public class InventoryListener implements Listener { - - private final InventoryFunction function; - - public InventoryListener(InventoryFunction function) { - this.function = function; - } - - @EventHandler - public void onClick(InventoryClickEvent event) { - function.onClickInventory(event); - } - - @EventHandler - public void onClose(InventoryCloseEvent event){ - function.onCloseInventory(event); - } - - @EventHandler - public void onDrag(InventoryDragEvent event) { - function.onDragInventory(event); - } -} diff --git a/src/main/java/net/momirealms/customfishing/listener/JobsRebornXPListener.java b/src/main/java/net/momirealms/customfishing/listener/JobsRebornXPListener.java deleted file mode 100644 index 00b3b965..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/JobsRebornXPListener.java +++ /dev/null @@ -1,35 +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.listener; - -import com.gamingmesh.jobs.Jobs; -import com.gamingmesh.jobs.api.JobsExpGainEvent; -import com.gamingmesh.jobs.container.Job; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -public class JobsRebornXPListener implements Listener { - - @EventHandler - public void onXpGain(JobsExpGainEvent event) { - Job job = Jobs.getJob("Fisherman"); - if (event.getJob().equals(job)){ - event.setExp(0); - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/listener/JoinQuitListener.java b/src/main/java/net/momirealms/customfishing/listener/JoinQuitListener.java deleted file mode 100644 index 948faeb3..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/JoinQuitListener.java +++ /dev/null @@ -1,37 +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.listener; - -import net.momirealms.customfishing.object.Function; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; - -public record JoinQuitListener(Function function) implements Listener { - - @EventHandler - public void onJoin(PlayerJoinEvent event) { - function.onJoin(event.getPlayer()); - } - - @EventHandler - public void onQuit(PlayerQuitEvent event) { - function.onQuit(event.getPlayer()); - } -} diff --git a/src/main/java/net/momirealms/customfishing/listener/PickUpListener.java b/src/main/java/net/momirealms/customfishing/listener/PickUpListener.java deleted file mode 100644 index 60b807d0..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/PickUpListener.java +++ /dev/null @@ -1,53 +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.listener; - -import de.tr7zw.changeme.nbtapi.NBTItem; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryPickupItemEvent; -import org.bukkit.event.player.PlayerAttemptPickupItemEvent; -import org.bukkit.inventory.ItemStack; - -import java.util.Objects; - -public class PickUpListener implements Listener { - - @EventHandler - public void onPickUp(PlayerAttemptPickupItemEvent event) { - ItemStack itemStack = event.getItem().getItemStack(); - NBTItem nbtItem = new NBTItem(itemStack); - if (!nbtItem.hasTag("TempOwner")) return; - if (!Objects.equals(nbtItem.getString("TempOwner"), event.getPlayer().getName())) { - event.setCancelled(true); - } - else { - nbtItem.removeKey("TempOwner"); - itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - } - } - - @EventHandler - public void onMove(InventoryPickupItemEvent event) { - ItemStack itemStack = event.getItem().getItemStack(); - NBTItem nbtItem = new NBTItem(itemStack); - if (!nbtItem.hasTag("TempOwner")) return; - nbtItem.removeKey("TempOwner"); - itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/listener/PlayerFishListener.java b/src/main/java/net/momirealms/customfishing/listener/PlayerFishListener.java deleted file mode 100644 index 716a8e8c..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/PlayerFishListener.java +++ /dev/null @@ -1,86 +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.listener; - -import net.momirealms.customfishing.fishing.FishingCondition; -import net.momirealms.customfishing.fishing.requirements.RequirementInterface; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.manager.FishingManager; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerFishEvent; - -public record PlayerFishListener(FishingManager manager) implements Listener { - - @EventHandler(priority = EventPriority.MONITOR) - public void onFishMONITOR(PlayerFishEvent event) { - if (!ConfigManager.priority.equals("MONITOR")) return; - selectState(event); - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onFishHIGHEST(PlayerFishEvent event) { - if (!ConfigManager.priority.equals("HIGHEST")) return; - selectState(event); - } - - @EventHandler(priority = EventPriority.HIGH) - public void onFishHIGH(PlayerFishEvent event) { - if (!ConfigManager.priority.equals("HIGH")) return; - selectState(event); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onFishNORMAL(PlayerFishEvent event) { - if (!ConfigManager.priority.equals("NORMAL")) return; - selectState(event); - } - - @EventHandler(priority = EventPriority.LOW) - public void onFishLOW(PlayerFishEvent event) { - if (!ConfigManager.priority.equals("LOW")) return; - selectState(event); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onFishLOWEST(PlayerFishEvent event) { - if (!ConfigManager.priority.equals("LOWEST")) return; - selectState(event); - } - - public void selectState(PlayerFishEvent event) { - if (event.isCancelled()) return; - if (!ConfigManager.getWorldsList().contains(event.getHook().getLocation().getWorld().getName())) return; - FishingCondition fishingCondition = new FishingCondition(event.getPlayer().getLocation(), event.getPlayer(), null, null); - if (ConfigManager.mechanicRequirements != null) { - for (RequirementInterface requirement : ConfigManager.mechanicRequirements) { - if (!requirement.isConditionMet(fishingCondition)) { - return; - } - } - } - switch (event.getState()) { - case FISHING -> manager.onFishing(event); - case REEL_IN -> manager.onReelIn(event); - case CAUGHT_ENTITY -> manager.onCaughtEntity(event); - case CAUGHT_FISH -> manager.onCaughtFish(event); - case BITE -> manager.onBite(event); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/listener/WindowPacketListener.java b/src/main/java/net/momirealms/customfishing/listener/WindowPacketListener.java deleted file mode 100644 index b2bebe29..00000000 --- a/src/main/java/net/momirealms/customfishing/listener/WindowPacketListener.java +++ /dev/null @@ -1,39 +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.listener; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketEvent; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.object.InventoryFunction; - -public class WindowPacketListener extends PacketAdapter { - - private final InventoryFunction function; - - public WindowPacketListener(InventoryFunction function) { - super(CustomFishing.getInstance(), PacketType.Play.Server.OPEN_WINDOW); - this.function = function; - } - - @Override - public void onPacketSending(PacketEvent event) { - function.onWindowTitlePacketSend(event.getPacket(), event.getPlayer()); - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/BagDataManager.java b/src/main/java/net/momirealms/customfishing/manager/BagDataManager.java deleted file mode 100644 index 7db1ab62..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/BagDataManager.java +++ /dev/null @@ -1,215 +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.manager; - -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.listener.InventoryListener; -import net.momirealms.customfishing.listener.JoinQuitListener; -import net.momirealms.customfishing.listener.WindowPacketListener; -import net.momirealms.customfishing.object.InventoryFunction; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.InventoryUtils; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -public class BagDataManager extends InventoryFunction { - - private final ConcurrentHashMap dataMap; - private final HashMap tempData; - private final InventoryListener inventoryListener; - private final WindowPacketListener windowPacketListener; - private final JoinQuitListener joinQuitListener; - private final CustomFishing plugin; - - public BagDataManager(CustomFishing plugin) { - super(); - this.plugin = plugin; - this.dataMap = new ConcurrentHashMap<>(); - this.tempData = new HashMap<>(); - this.inventoryListener = new InventoryListener(this); - this.windowPacketListener = new WindowPacketListener(this); - this.joinQuitListener = new JoinQuitListener(this); - } - - public void saveBagDataForOnlinePlayers(boolean unlock) { - plugin.getDataManager().getDataStorageInterface().saveBagData(dataMap.entrySet(), unlock); - } - - @Override - public void load() { - if (!ConfigManager.enableFishingBag) return; - Bukkit.getPluginManager().registerEvents(inventoryListener, plugin); - Bukkit.getPluginManager().registerEvents(joinQuitListener, plugin); - CustomFishing.getProtocolManager().addPacketListener(windowPacketListener); - } - - @Override - public void unload() { - HandlerList.unregisterAll(inventoryListener); - HandlerList.unregisterAll(joinQuitListener); - CustomFishing.getProtocolManager().removePacketListener(windowPacketListener); - } - - @Override - public void disable() { - unload(); - saveBagDataForOnlinePlayers(true); - dataMap.clear(); - tempData.clear(); - } - - public Inventory getPlayerBagData(UUID uuid) { - return dataMap.get(uuid); - } - - public void openFishingBag(Player viewer, OfflinePlayer ownerOffline, boolean force) { - Player owner = ownerOffline.getPlayer(); - //not online - if (owner == null || !owner.isOnline()) { - Inventory inventory = plugin.getDataManager().getDataStorageInterface().loadBagData(ownerOffline.getUniqueId(), force); - if (inventory == null) { - AdventureUtils.playerMessage(viewer, "[CustomFishing] Failed to load bag data for player " + ownerOffline.getName()); - AdventureUtils.playerMessage(viewer, "This might be caused by the target player is online but on another server"); - AdventureUtils.playerMessage(viewer, "Use /fishingbag open [Player] --force to ignore this warning"); - return; - } - tempData.put(ownerOffline.getUniqueId(), inventory); - viewer.openInventory(inventory); - } else { - Inventory inventory = dataMap.get(owner.getUniqueId()); - if (inventory == null) { - AdventureUtils.consoleMessage("[CustomFishing] Bag data is not loaded for player " + owner.getName()); - } else { - openBagGUI(owner, viewer, inventory); - } - } - } - - @Override - public void onQuit(Player player) { - UUID uuid = player.getUniqueId(); - Inventory inventory = dataMap.remove(uuid); - triedTimes.remove(player.getUniqueId()); - if (inventory != null) { - plugin.getScheduler().runTaskAsync(() -> plugin.getDataManager().getDataStorageInterface().saveBagData(uuid, inventory, true)); - } - } - - @Override - public void onJoin(Player player) { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, false), 750, TimeUnit.MILLISECONDS); - } - - public void joinReadData(Player player, boolean force) { - if (player == null || !player.isOnline()) return; - Inventory inventory = plugin.getDataManager().getDataStorageInterface().loadBagData(player.getUniqueId(), force); - if (inventory != null) { - dataMap.put(player.getUniqueId(), inventory); - } else if (!force) { - if (checkTriedTimes(player.getUniqueId())) { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, false), 2500, TimeUnit.MILLISECONDS); - } else { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, true), 2500, TimeUnit.MILLISECONDS); - } - } - } - - @Override - public void onClickInventory(InventoryClickEvent event) { - final Player player = (Player) event.getWhoClicked(); - Inventory fishingBagInv = dataMap.get(player.getUniqueId()); - if (fishingBagInv == event.getInventory()) { - ItemStack currentItem = event.getCurrentItem(); - if (currentItem == null || currentItem.getType() == Material.AIR) return; - NBTItem nbtItem = new NBTItem(currentItem); - NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound == null && !ConfigManager.bagWhiteListItems.contains(currentItem.getType())) { - event.setCancelled(true); - return; - } - if (nbtCompound != null) { - String type = nbtCompound.getString("type"); - if (!ConfigManager.canStoreLoot && type.equals("loot")) { - event.setCancelled(true); - } - } - } - } - - @Override - public void onCloseInventory(InventoryCloseEvent event) { - final Player player = (Player) event.getPlayer(); - Inventory inventory = event.getInventory(); - Inventory fishingBagInv = dataMap.get(player.getUniqueId()); - if (fishingBagInv != null) { - if (inventory == fishingBagInv) { - for (ItemStack itemStack : event.getInventory().getContents()) { - if (itemStack == null || itemStack.getType() == Material.AIR) continue; - NBTItem nbtItem = new NBTItem(itemStack); - if (nbtItem.hasTag("CustomFishing") || ConfigManager.bagWhiteListItems.contains(itemStack.getType())) continue; - player.getInventory().addItem(itemStack.clone()); - itemStack.setAmount(0); - } - return; - } - for (Map.Entry entry : tempData.entrySet()) { - if (entry.getValue() == inventory) { - tempData.remove(entry.getKey()); - plugin.getScheduler().runTaskAsync(() -> { - plugin.getDataManager().getDataStorageInterface().saveBagData(entry.getKey(), entry.getValue(), true); - }); - } - } - } - } - - public void openBagGUI(Player owner, Player viewer, Inventory inventory) { - int size = 1; - for (int i = 6; i > 1; i--) { - if (owner.hasPermission("fishingbag.rows." + i)) { - size = i; - break; - } - } - if (size * 9 != inventory.getSize()) { - ItemStack[] itemStacks = inventory.getContents(); - Inventory newInv = InventoryUtils.createInventory(null, size * 9, plugin.getIntegrationManager().getPlaceholderManager().parse(owner, ConfigManager.fishingBagTitle)); - newInv.setContents(itemStacks); - dataMap.put(owner.getUniqueId(), newInv); - viewer.openInventory(newInv); - } - else { - viewer.openInventory(inventory); - } - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/manager/BarMechanicManager.java b/src/main/java/net/momirealms/customfishing/manager/BarMechanicManager.java deleted file mode 100644 index f8f9a0b8..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/BarMechanicManager.java +++ /dev/null @@ -1,135 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.MiniGameConfig; -import net.momirealms.customfishing.fishing.bar.FishingBar; -import net.momirealms.customfishing.fishing.bar.ModeOneBar; -import net.momirealms.customfishing.fishing.bar.ModeThreeBar; -import net.momirealms.customfishing.fishing.bar.ModeTwoBar; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.util.*; - -public class BarMechanicManager extends Function { - - private final CustomFishing plugin; - private final HashMap bars; - private final HashMap miniGames; - - public BarMechanicManager(CustomFishing plugin) { - this.plugin = plugin; - this.bars = new HashMap<>(); - this.miniGames = new HashMap<>(); - } - - @Override - public void load() { - loadBars(); - loadGames(); - } - - @Override - public void unload() { - bars.clear(); - miniGames.clear(); - } - - private void loadGames() { - File game_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "minigames"); - if (!game_file.exists()) { - if (!game_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "minigames" + File.separator + "default.yml", false); - } - File[] files = game_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (String key : config.getKeys(false)) { - ConfigurationSection section = config.getConfigurationSection(key); - if (section == null) continue; - List fishingBarList = new ArrayList<>(); - for (String bar : section.getStringList("bars")) { - if (bars.containsKey(bar)) { - fishingBarList.add(bars.get(bar)); - } - else { - AdventureUtils.consoleMessage("[CustomFishing] Bar " + bar + " doesn't exist"); - } - } - int[] difficulties = section.getIntegerList("difficulty").stream().mapToInt(Integer::intValue).toArray(); - if (difficulties.length == 0) { - AdventureUtils.consoleMessage("[CustomFishing] Game " + key + " doesn't have difficulties"); - continue; - } - MiniGameConfig miniGameConfig = new MiniGameConfig( - section.getInt("time", 10), - fishingBarList.toArray(new FishingBar[0]), - difficulties - ); - miniGames.put(key, miniGameConfig); - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + miniGames.size() + " game(s)"); - } - - private void loadBars() { - File bar_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "bars"); - if (!bar_file.exists()) { - if (!bar_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "bars" + File.separator + "default.yml", false); - } - File[] files = bar_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (String key : config.getKeys(false)) { - ConfigurationSection section = config.getConfigurationSection(key); - if (section == null) continue; - int type = section.getInt("game-type"); - if (type == 1) { - ModeOneBar modeOneBar = new ModeOneBar(section); - bars.put(key, modeOneBar); - } else if (type == 2) { - ModeTwoBar modeTwoBar = new ModeTwoBar(section); - bars.put(key, modeTwoBar); - } else if (type == 3) { - ModeThreeBar modeThreeBar = new ModeThreeBar(section); - bars.put(key, modeThreeBar); - } - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + bars.size() + " bar(s)"); - } - - public MiniGameConfig getGameConfig(String game) { - return miniGames.get(game); - } - - public MiniGameConfig getRandomGame() { - Collection miniGameConfigs = miniGames.values(); - return (MiniGameConfig) miniGameConfigs.toArray()[new Random().nextInt(miniGameConfigs.size())]; - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/CompetitionManager.java b/src/main/java/net/momirealms/customfishing/manager/CompetitionManager.java deleted file mode 100644 index 10a07145..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/CompetitionManager.java +++ /dev/null @@ -1,161 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.action.CommandActionImpl; -import net.momirealms.customfishing.fishing.action.MessageActionImpl; -import net.momirealms.customfishing.fishing.competition.CompetitionConfig; -import net.momirealms.customfishing.fishing.competition.CompetitionGoal; -import net.momirealms.customfishing.fishing.competition.CompetitionSchedule; -import net.momirealms.customfishing.fishing.competition.bossbar.BossBarConfig; -import net.momirealms.customfishing.fishing.competition.bossbar.BossBarOverlay; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.AdventureUtils; -import org.bukkit.boss.BarColor; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.util.*; - -public class CompetitionManager extends Function { - - private final CustomFishing plugin; - // Competitions that can be triggered at a specified time - private final HashMap competitionsT; - // Competitions that can be triggered with a command - private final HashMap competitionsC; - private CompetitionSchedule competitionSchedule; - - public CompetitionManager(CustomFishing plugin) { - this.plugin = plugin; - this.competitionsC = new HashMap<>(); - this.competitionsT = new HashMap<>(); - } - - @Override - public void load() { - if (ConfigManager.enableCompetition) { - loadCompetitions(); - this.competitionSchedule = new CompetitionSchedule(); - this.competitionSchedule.load(); - } - } - - @Override - public void unload() { - this.competitionsC.clear(); - this.competitionsT.clear(); - if (this.competitionSchedule != null) { - this.competitionSchedule.unload(); - } - } - - private void loadCompetitions() { - File competition_file = new File(plugin.getDataFolder(), "contents" + File.separator + "competitions"); - if (!competition_file.exists()) { - if (!competition_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "competitions" + File.separator + "default.yml", false); - } - File[] files = competition_file.listFiles(); - if (files == null) return; - int amount = 0; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - Set keys = config.getKeys(false); - for (String key : keys) { - ConfigurationSection competitionSection = config.getConfigurationSection(key); - if (competitionSection == null) continue; - boolean enableBsb = competitionSection.getBoolean("bossbar.enable", false); - BossBarConfig bossBarConfig = new BossBarConfig( - competitionSection.getStringList("bossbar.text").toArray(new String[0]), - BossBarOverlay.valueOf(competitionSection.getString("bossbar.overlay","SOLID").toUpperCase(Locale.ENGLISH)), - BarColor.valueOf(competitionSection.getString("bossbar.color","WHITE").toUpperCase(Locale.ENGLISH)), - competitionSection.getInt("bossbar.refresh-rate",10), - competitionSection.getInt("bossbar.switch-interval", 200), - !competitionSection.getBoolean("bossbar.only-show-to-participants", true) - ); - - HashMap rewardsMap = new HashMap<>(); - Objects.requireNonNull(competitionSection.getConfigurationSection("prize")).getKeys(false).forEach(rank -> { - List rewards = new ArrayList<>(); - if (competitionSection.contains("prize." + rank + ".messages")) - rewards.add(new MessageActionImpl(competitionSection.getStringList("prize." + rank + ".messages").toArray(new String[0]), null, 1)); - if (competitionSection.contains("prize." + rank + ".commands")) - rewards.add(new CommandActionImpl(competitionSection.getStringList("prize." + rank + ".commands").toArray(new String[0]), null, 1)); - rewardsMap.put(rank, rewards.toArray(new Action[0])); - }); - - CompetitionConfig competitionConfig = new CompetitionConfig( - key, - competitionSection.getInt("duration",600), - competitionSection.getInt("min-players",1), - competitionSection.getStringList("broadcast.start"), - competitionSection.getStringList("broadcast.end"), - competitionSection.getStringList("command.start"), - competitionSection.getStringList("command.end"), - competitionSection.getStringList("command.join"), - CompetitionGoal.valueOf(competitionSection.getString("goal", "RANDOM")), - bossBarConfig, - enableBsb, - rewardsMap - ); - - if (competitionSection.contains("start-weekday")) { - List days = new ArrayList<>(); - for (String weekDay : competitionSection.getStringList("start-weekday").stream().map(String::toLowerCase).toList()) { - switch (weekDay) { - case "sunday" -> days.add(1); - case "monday" -> days.add(2); - case "tuesday" -> days.add(3); - case "wednesday" -> days.add(4); - case "thursday" -> days.add(5); - case "friday" -> days.add(6); - case "saturday" -> days.add(7); - default -> AdventureUtils.consoleMessage("[CustomFishing] Unknown weekday: " + weekDay); - } - } - competitionConfig.setWeekday(days); - } - - if (competitionSection.contains("start-date")) { - List days = new ArrayList<>(); - for (String weekDay : competitionSection.getStringList("start-date")) { - days.add(Integer.parseInt(weekDay)); - } - competitionConfig.setDate(days); - } - competitionSection.getStringList("start-time").forEach(time -> competitionsT.put(time, competitionConfig)); - competitionsC.put(key, competitionConfig); - amount++; - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + amount + " competition(s)"); - } - - public HashMap getCompetitionsT() { - return competitionsT; - } - - public HashMap getCompetitionsC() { - return competitionsC; - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/ConfigManager.java b/src/main/java/net/momirealms/customfishing/manager/ConfigManager.java deleted file mode 100644 index 5f7f86b6..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/ConfigManager.java +++ /dev/null @@ -1,193 +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.manager; - -import net.momirealms.customfishing.fishing.requirements.RequirementInterface; -import net.momirealms.customfishing.util.ConfigUtils; -import net.momirealms.customfishing.util.JedisUtils; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.util.*; - -public class ConfigManager { - - public static List worldList; - public static boolean whiteOrBlack; - public static String priority; - public static String lang; - public static boolean enableVanillaLoot; - public static boolean enableMcMMOLoot; - public static double vanillaLootRatio; - public static double mcMMOLootChance; - public static boolean needRodToFish; - public static boolean needRodForLoot; - public static boolean rodLoseDurability; - public static boolean enableCompetition; - public static boolean disableJobsXp; - public static boolean preventPickUp; - public static boolean enableFishingBag; - public static boolean allRodsFishInLava; - public static boolean enableSuccessTitle; - public static String[] successTitle; - public static String[] successSubTitle; - public static int successFadeIn; - public static int successFadeStay; - public static int successFadeOut; - public static boolean enableFailureTitle; - public static String[] failureTitle; - public static String[] failureSubTitle; - public static int failureFadeIn; - public static int failureFadeStay; - public static int failureFadeOut; - public static boolean useRedis; - public static boolean canStoreLoot; - public static int lavaMaxTime; - public static int lavaMinTime; - public static boolean enableWaterAnimation; - public static boolean enableLavaAnimation; - public static String water_item; - public static String lava_item; - public static int water_time; - public static int lava_time; - public static boolean addTagToFish; - public static boolean logEarning; - public static boolean disableBar; - public static boolean instantBar; - public static String fishingBagTitle; - public static boolean bStats; - public static HashSet bagWhiteListItems; - public static boolean enableStatistics; - public static boolean updateChecker; - public static boolean hideSaveInfo; - public static boolean baitAnimation; - public static int corePoolSize; - public static int maximumPoolSize; - public static int keepAliveTime; - public static String dateFormat; - public static RequirementInterface[] mechanicRequirements; - - public static void load() { - ConfigUtils.update("config.yml", new ArrayList<>()); - YamlConfiguration config = ConfigUtils.getConfig("config.yml"); - lang = config.getString("lang","english"); - bStats = config.getBoolean("metrics", true); - updateChecker = config.getBoolean("update-checker", true); - loadMechanics(Objects.requireNonNull(config.getConfigurationSection("mechanics"))); - loadTitle(Objects.requireNonNull(config.getConfigurationSection("titles"))); - loadFishingWorlds(Objects.requireNonNull(config.getConfigurationSection("worlds"))); - loadOtherSettings(Objects.requireNonNull(config.getConfigurationSection("other-settings"))); - } - - private static void loadOtherSettings(ConfigurationSection config) { - priority = config.getString("event-priority", "NORMAL").toUpperCase(Locale.ENGLISH); - disableJobsXp = config.getBoolean("disable-JobsReborn-fishing-exp", false); - preventPickUp = config.getBoolean("prevent-other-players-pick-up-loot", false); - logEarning = config.getBoolean("log-earnings", true); - hideSaveInfo = config.getBoolean("hide-data-saving-info", false); - corePoolSize = config.getInt("thread-pool-settings.corePoolSize", 1); - maximumPoolSize = config.getInt("thread-pool-settings.maximumPoolSize", 4); - keepAliveTime = config.getInt("thread-pool-settings.keepAliveTime", 10); - dateFormat = config.getString("date-format", "yyyy-MM-dd"); - } - - private static void loadMechanics(ConfigurationSection config) { - disableBar = config.getBoolean("disable-bar-mechanic", false); - instantBar = config.getBoolean("instant-bar", false); - enableVanillaLoot = config.getBoolean("other-loots.vanilla.enable", true); - vanillaLootRatio = config.getDouble("other-loots.vanilla.ratio", 0.4); - enableMcMMOLoot = config.getBoolean("other-loots.mcMMO.enable", false); - mcMMOLootChance = config.getDouble("other-loots.mcMMO.chance", 0.5); - needRodToFish = config.getBoolean("need-special-rod-to-fish", false); - needRodForLoot = config.getBoolean("need-special-rod-for-loots", false); - rodLoseDurability = config.getBoolean("rod-lose-durability", true); - enableCompetition = config.getBoolean("fishing-competition.enable", true); - enableWaterAnimation = config.getBoolean("splash-animation.water.enable", false); - enableLavaAnimation = config.getBoolean("splash-animation.lava.enable", false); - allRodsFishInLava = config.getBoolean("all-rods-fish-in-lava", false); - water_item = config.getString("splash-animation.water.item"); - lava_item = config.getString("splash-animation.lava.item"); - water_time = config.getInt("splash-animation.water.time"); - lava_time = config.getInt("splash-animation.lava.time"); - lavaMinTime = config.getInt("lava-fishing.min-wait-time", 100); - lavaMaxTime = config.getInt("lava-fishing.max-wait-time", 600) - lavaMinTime; - enableFishingBag = config.getBoolean("fishing-bag.enable", true); - canStoreLoot = config.getBoolean("fishing-bag.can-store-loot", false); - addTagToFish = config.getBoolean("add-custom-fishing-tags-to-loots", true); - fishingBagTitle = config.getString("fishing-bag.bag-title", "Fishing Bag"); - enableStatistics = config.getBoolean("fishing-statistics.enable", true); - baitAnimation = config.getBoolean("bait-animation", true); - mechanicRequirements = ConfigUtils.getRequirementsWithMsg(config.getConfigurationSection("mechanic-requirements")); - bagWhiteListItems = new HashSet<>(); - for (String material : config.getStringList("fishing-bag.whitelist-items")) bagWhiteListItems.add(Material.valueOf(material.toUpperCase(Locale.ENGLISH))); - redisSettings(config); - } - - private static void loadTitle(ConfigurationSection config) { - enableSuccessTitle = config.getBoolean("success.enable", true); - enableFailureTitle = config.getBoolean("failure.enable", true); - successTitle = config.getStringList("success.title").toArray(new String[0]); - successSubTitle = config.getStringList("success.subtitle").toArray(new String[0]); - successFadeIn = config.getInt("success.fade.in", 10) * 50; - successFadeStay = config.getInt("success.fade.stay", 30) * 50; - successFadeOut = config.getInt("success.fade.out", 10) * 50; - failureTitle = config.getStringList("failure.title").toArray(new String[0]); - failureSubTitle = config.getStringList("failure.subtitle").toArray(new String[0]); - failureFadeIn = config.getInt("failure.fade.in", 10) * 50; - failureFadeStay = config.getInt("failure.fade.stay", 30) * 50; - failureFadeOut = config.getInt("failure.fade.out", 10) * 50; - if (successTitle.length == 0) successTitle = new String[]{""}; - if (successSubTitle.length == 0) successSubTitle = new String[]{""}; - if (failureTitle.length == 0) failureTitle = new String[]{""}; - if (failureSubTitle.length == 0) failureSubTitle = new String[]{""}; - } - - private static void loadFishingWorlds(ConfigurationSection config) { - whiteOrBlack = config.getString("mode","whitelist").equals("whitelist"); - worldList = config.getStringList("list"); - } - - public static List getWorldsList() { - if (whiteOrBlack) { - return worldList; - } - else { - List worldList = new ArrayList<>(); - for (World world : Bukkit.getWorlds()) { - worldList.add(world.getName()); - } - worldList.removeAll(ConfigManager.worldList); - return worldList; - } - } - - private static void redisSettings(ConfigurationSection config) { - if (enableCompetition && config.getBoolean("fishing-competition.redis", false)) { - if (!JedisUtils.isPoolEnabled()) { - JedisUtils.initializeRedis(ConfigUtils.getConfig("database.yml")); - } - useRedis = true; - } else if (useRedis && JedisUtils.isPoolEnabled()) { - JedisUtils.closePool(); - useRedis = false; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/DataManager.java b/src/main/java/net/momirealms/customfishing/manager/DataManager.java deleted file mode 100644 index ecba73a6..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/DataManager.java +++ /dev/null @@ -1,103 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.data.storage.DataStorageInterface; -import net.momirealms.customfishing.data.storage.FileStorageImpl; -import net.momirealms.customfishing.data.storage.MySQLStorageImpl; -import net.momirealms.customfishing.data.storage.StorageType; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ConfigUtils; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -public class DataManager extends Function { - - private DataStorageInterface dataStorageInterface; - private final CustomFishing plugin; - private StorageType storageType; - private ScheduledFuture timerSave; - - public DataManager(CustomFishing plugin) { - this.plugin = plugin; - } - - public DataStorageInterface getDataStorageInterface() { - return dataStorageInterface; - } - - private boolean loadStorageMode() { - YamlConfiguration config = ConfigUtils.getConfig("database.yml"); - if (config.getString("data-storage-method","YAML").equalsIgnoreCase("YAML")) { - if (storageType != StorageType.YAML) { - this.dataStorageInterface = new FileStorageImpl(plugin); - this.storageType = StorageType.YAML; - return true; - } - } else { - if (storageType != StorageType.SQL) { - this.dataStorageInterface = new MySQLStorageImpl(plugin); - this.storageType = StorageType.SQL; - return true; - } - } - return false; - } - - @Override - public void load() { - if (loadStorageMode()) this.dataStorageInterface.initialize(); - this.timerSave = plugin.getScheduler().runTaskTimerAsync(() -> { - //long time1 = System.currentTimeMillis(); - if (ConfigManager.enableFishingBag) { - if (!ConfigManager.hideSaveInfo) AdventureUtils.consoleMessage("[CustomFishing] Saving fishing bag data..."); - plugin.getBagDataManager().saveBagDataForOnlinePlayers(false); - } - if (ConfigManager.enableStatistics) { - if (!ConfigManager.hideSaveInfo) AdventureUtils.consoleMessage("[CustomFishing] Saving statistics data..."); - plugin.getStatisticsManager().saveStatisticsDataForOnlinePlayers(false); - } - //AdventureUtil.consoleMessage("[CustomFishing] Data saved for all online players. Took " + (System.currentTimeMillis() - time1) + " ms."); - if (!ConfigManager.hideSaveInfo) AdventureUtils.consoleMessage("[CustomFishing] Data saved for all online players."); - }, 20, 20, TimeUnit.MINUTES); - } - - @Override - public void unload() { - if (timerSave != null && !timerSave.isCancelled()) { - timerSave.cancel(false); - } - YamlConfiguration config = ConfigUtils.getConfig("database.yml"); - StorageType st = config.getString("data-storage-method","YAML").equalsIgnoreCase("YAML") ? StorageType.YAML : StorageType.SQL; - if (this.dataStorageInterface != null && dataStorageInterface.getStorageType() != st) this.dataStorageInterface.disable(); - } - - @Override - public void disable() { - if (this.dataStorageInterface != null) { - this.dataStorageInterface.disable(); - } - if (timerSave != null && !timerSave.isCancelled()) { - timerSave.cancel(false); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/EffectManager.java b/src/main/java/net/momirealms/customfishing/manager/EffectManager.java deleted file mode 100644 index 922d5f99..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/EffectManager.java +++ /dev/null @@ -1,278 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.Effect; -import net.momirealms.customfishing.fishing.loot.Item; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ConfigUtils; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class EffectManager extends Function { - - private final CustomFishing plugin; - private final HashMap baitItems; - private final HashMap baitEffects; - private final HashMap rodItems; - private final HashMap rodEffects; - private final HashMap utilItems; - private final HashMap utilEffects; - private final HashMap effectMap; - private final HashMap enchantEffects; - - public EffectManager(CustomFishing plugin) { - this.plugin = plugin; - this.baitEffects = new HashMap<>(); - this.baitItems = new HashMap<>(); - this.rodEffects = new HashMap<>(); - this.rodItems = new HashMap<>(); - this.utilItems = new HashMap<>(); - this.enchantEffects = new HashMap<>(); - this.utilEffects = new HashMap<>(); - this.effectMap = new HashMap<>(); - } - - @Override - public void load() { - loadRod(); - loadBait(); - loadEnchant(); - loadUtil(); - toEffectMap("bait", baitEffects); - toEffectMap("rod", rodEffects); - toEffectMap("util", utilEffects); - } - - @Override - public void unload() { - this.baitEffects.clear(); - this.baitItems.clear(); - this.rodEffects.clear(); - this.rodItems.clear(); - this.utilItems.clear(); - this.enchantEffects.clear(); - this.utilEffects.clear(); - this.effectMap.clear(); - } - - private void toEffectMap(String type, Map map) { - for (Map.Entry entry : map.entrySet()) { - effectMap.put(type + "_" + entry.getKey(), entry.getValue()); - } - } - - private void loadUtil() { - File util_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "utils"); - if (!util_file.exists()) { - if (!util_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "utils" + File.separator + "fish_finder.yml", false); - plugin.saveResource("contents" + File.separator + "utils" + File.separator + "totem_items.yml", false); - plugin.saveResource("contents" + File.separator + "utils" + File.separator + "splash_items.yml", false); - plugin.saveResource("contents" + File.separator + "utils" + File.separator + "fisherman_talismans.yml", false); - } - File[] files = util_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - Set keys = config.getKeys(false); - for (String key : keys) { - ConfigurationSection utilSection = config.getConfigurationSection(key); - if (utilSection == null) continue; - Item item = new Item(utilSection, key); - item.setCfTag(new String[] {"util", key}); - utilItems.put(key, item); - Effect effect = ConfigUtils.getEffect(utilSection.getConfigurationSection("effect")); - if (utilSection.contains("requirements")) { - effect.setRequirements(ConfigUtils.getRequirementsWithMsg(utilSection.getConfigurationSection("requirements"))); - } - utilEffects.put(key, effect); - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + utilItems.size() + " util(s)"); - } - - private void loadEnchant() { - File enchant_file = new File(plugin.getDataFolder(), "contents" + File.separator + "enchants"); - if (!enchant_file.exists()) { - if (!enchant_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "enchants" + File.separator + "default.yml", false); - } - File[] files = enchant_file.listFiles(); - if (files == null) return; - int amount = 0; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (String key : config.getKeys(false)) { - ConfigurationSection levelSection = config.getConfigurationSection(key); - if (levelSection == null) continue; - for (String level : levelSection.getKeys(false)) { - Effect effect = ConfigUtils.getEffect(levelSection.getConfigurationSection(level + ".effect")); - if (levelSection.contains(level + ".requirements")) { - effect.setRequirements(ConfigUtils.getRequirementsWithMsg(levelSection.getConfigurationSection(level + ".requirements"))); - } - enchantEffects.put((key.startsWith("eco") ? "minecraft" + key.substring(3) : key) + ":" + level, effect); - } - amount++; - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + amount + " enchantment(s)"); - } - - private void loadBait() { - File bait_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "baits"); - if (!bait_file.exists()) { - if (!bait_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "baits" + File.separator + "default.yml", false); - } - File[] files = bait_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - Set keys = config.getKeys(false); - for (String key : keys) { - ConfigurationSection baitSection = config.getConfigurationSection(key); - if (baitSection == null) continue; - Item item = new Item(baitSection, key); - item.setCfTag(new String[] {"bait", key}); - baitItems.put(key, item); - Effect effect = ConfigUtils.getEffect(baitSection.getConfigurationSection("effect")); - if (baitSection.contains("requirements")) { - effect.setRequirements(ConfigUtils.getRequirementsWithMsg(baitSection.getConfigurationSection("requirements"))); - } - baitEffects.put(key, effect); - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + baitItems.size() + " bait(s)"); - } - - private void loadRod() { - File rod_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "rods"); - if (!rod_file.exists()) { - if (!rod_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "rods" + File.separator + "default.yml", false); - } - File[] files = rod_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - Set keys = config.getKeys(false); - for (String key : keys) { - ConfigurationSection rodSection = config.getConfigurationSection(key); - if (rodSection == null) continue; - rodSection.set("material", "fishing_rod"); - Item item = new Item(rodSection, key); - item.setCfTag(new String[] {"rod", key}); - rodItems.put(key, item); - Effect effect = ConfigUtils.getEffect(rodSection.getConfigurationSection("effect")); - if (rodSection.contains("requirements")) { - effect.setRequirements(ConfigUtils.getRequirementsWithMsg(rodSection.getConfigurationSection("requirements"))); - } - rodEffects.put(key, effect); - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + rodItems.size() + " rod(s)"); - } - - @Nullable - public Item getBaitItem(String key) { - return baitItems.get(key); - } - - @NotNull - public HashMap getBaitItems() { - return baitItems; - } - - @Nullable - public Effect getBaitEffect(String key) { - return baitEffects.get(key); - } - - @NotNull - public HashMap getBaitEffects() { - return baitEffects; - } - - @Nullable - public Item getRodItem(String key) { - return rodItems.get(key); - } - - @NotNull - public HashMap getRodItems() { - return rodItems; - } - - @Nullable - public Effect getRodEffect(String key) { - return rodEffects.get(key); - } - - @NotNull - public HashMap getRodEffects() { - return rodEffects; - } - - @Nullable - public Effect getEnchantEffect(String key) { - return enchantEffects.get(key); - } - - @NotNull - public HashMap getEnchantEffects() { - return enchantEffects; - } - - @Nullable - public Item getUtilItem(String key) { - return utilItems.get(key); - } - - @NotNull - public HashMap getUtilItems() { - return utilItems; - } - - @NotNull - public HashMap getUtilEffects() { - return utilEffects; - } - - @Nullable - public Effect getUtilEffect(String key) { - return utilEffects.get(key); - } - - public Effect getEffect(String type, String id) { - return effectMap.get(type + "_" + id); - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/FishingManager.java b/src/main/java/net/momirealms/customfishing/manager/FishingManager.java deleted file mode 100644 index 65a6f79c..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/FishingManager.java +++ /dev/null @@ -1,1106 +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.manager; - -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.kyori.adventure.text.Component; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.api.CustomFishingAPI; -import net.momirealms.customfishing.api.event.*; -import net.momirealms.customfishing.fishing.Effect; -import net.momirealms.customfishing.fishing.*; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.action.VanillaXPImpl; -import net.momirealms.customfishing.fishing.bar.FishingBar; -import net.momirealms.customfishing.fishing.bar.ModeOneBar; -import net.momirealms.customfishing.fishing.bar.ModeThreeBar; -import net.momirealms.customfishing.fishing.bar.ModeTwoBar; -import net.momirealms.customfishing.fishing.competition.Competition; -import net.momirealms.customfishing.fishing.competition.CompetitionGoal; -import net.momirealms.customfishing.fishing.loot.DroppedItem; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import net.momirealms.customfishing.fishing.loot.Mob; -import net.momirealms.customfishing.fishing.mode.FishingGame; -import net.momirealms.customfishing.fishing.mode.ModeOneGame; -import net.momirealms.customfishing.fishing.mode.ModeThreeGame; -import net.momirealms.customfishing.fishing.mode.ModeTwoGame; -import net.momirealms.customfishing.fishing.requirements.RequirementInterface; -import net.momirealms.customfishing.fishing.totem.ActivatedTotem; -import net.momirealms.customfishing.fishing.totem.TotemConfig; -import net.momirealms.customfishing.integration.MobInterface; -import net.momirealms.customfishing.integration.item.McMMOTreasure; -import net.momirealms.customfishing.listener.*; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.object.Pair; -import net.momirealms.customfishing.object.SimpleLocation; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.FakeItemUtils; -import net.momirealms.customfishing.util.ItemStackUtils; -import net.momirealms.customfishing.util.LocationUtils; -import org.bukkit.*; -import org.bukkit.block.Block; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.*; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class FishingManager extends Function { - - private final CustomFishing plugin; - private final PlayerFishListener playerFishListener; - private final InteractListener interactListener; - private final ConsumeItemListener consumeItemListener; - private PickUpListener pickUpListener; - private JobsRebornXPListener jobsRebornXPListener; - private final JoinQuitListener joinQuitListener; - private final BreakBlockListener breakBlockListener; - private final HashMap coolDown; - private final HashMap hooks; - private final HashMap nextLoot; - private final HashMap nextEffect; - private final HashMap vanillaLoot; - private final ConcurrentHashMap fishingPlayerMap; - private final ConcurrentHashMap activeTotemMap; - private final ConcurrentHashMap breakDetectionMap; - private final ConcurrentHashMap hookCheckTaskMap; - - public FishingManager(CustomFishing plugin) { - this.plugin = plugin; - this.playerFishListener = new PlayerFishListener(this); - this.interactListener = new InteractListener(this); - this.breakBlockListener = new BreakBlockListener(this); - this.consumeItemListener = new ConsumeItemListener(this); - this.joinQuitListener = new JoinQuitListener(this); - this.coolDown = new HashMap<>(); - this.hooks = new HashMap<>(); - this.nextLoot = new HashMap<>(); - this.nextEffect = new HashMap<>(); - this.vanillaLoot = new HashMap<>(); - this.fishingPlayerMap = new ConcurrentHashMap<>(); - this.activeTotemMap = new ConcurrentHashMap<>(); - this.hookCheckTaskMap = new ConcurrentHashMap<>(); - this.breakDetectionMap = new ConcurrentHashMap<>(); - load(); - } - - @Override - public void load() { - Bukkit.getPluginManager().registerEvents(this.playerFishListener, plugin); - Bukkit.getPluginManager().registerEvents(this.interactListener, plugin); - Bukkit.getPluginManager().registerEvents(this.breakBlockListener, plugin); - Bukkit.getPluginManager().registerEvents(this.consumeItemListener, plugin); - Bukkit.getPluginManager().registerEvents(this.joinQuitListener, plugin); - if (ConfigManager.preventPickUp) { - this.pickUpListener = new PickUpListener(); - Bukkit.getPluginManager().registerEvents(this.pickUpListener, plugin); - } - if (ConfigManager.disableJobsXp) { - this.jobsRebornXPListener = new JobsRebornXPListener(); - Bukkit.getPluginManager().registerEvents(this.jobsRebornXPListener, plugin); - } - } - - @Override - public void unload() { - HandlerList.unregisterAll(this.playerFishListener); - HandlerList.unregisterAll(this.interactListener); - HandlerList.unregisterAll(this.breakBlockListener); - HandlerList.unregisterAll(this.consumeItemListener); - HandlerList.unregisterAll(this.joinQuitListener); - if (this.pickUpListener != null) HandlerList.unregisterAll(this.pickUpListener); - if (this.jobsRebornXPListener != null) HandlerList.unregisterAll(this.jobsRebornXPListener); - for (BobberCheckTask bobberCheckTask : hookCheckTaskMap.values()) { - bobberCheckTask.stop(); - } - } - - public void onFishing(PlayerFishEvent event) { - final Player player = event.getPlayer(); - final FishHook fishHook = event.getHook(); - hooks.put(player.getUniqueId(), fishHook); - - boolean noBait = true; - boolean rodOnMainHand = false; - ItemStack baitAnimationItem = null; - ItemStack baitRealItem = null; - - Effect initialEffect = new Effect(); - initialEffect.setWeightMD(new HashMap<>(8)); - initialEffect.setWeightAS(new HashMap<>(8)); - - final PlayerInventory inventory = player.getInventory(); - final ItemStack mainHandItem = inventory.getItemInMainHand(); - final ItemStack offHandItem = inventory.getItemInOffHand(); - - if (mainHandItem.getType() == Material.FISHING_ROD) { - rodOnMainHand = true; - } - String rod_id = Optional.ofNullable(plugin.getIntegrationManager().getItemID(rodOnMainHand ? mainHandItem : offHandItem)).orElse("vanilla"); - final FishingCondition fishingCondition = new FishingCondition(player.getLocation(), player, rod_id, null); - String bait_id = plugin.getIntegrationManager().getItemID(rodOnMainHand ? offHandItem: mainHandItem); - if (bait_id != null) { - Effect baitEffect = plugin.getEffectManager().getBaitEffect(bait_id); - if (baitEffect != null && initialEffect.canAddEffect(baitEffect, fishingCondition)) { - initialEffect.addEffect(baitEffect); - baitAnimationItem = rodOnMainHand ? offHandItem.clone() : mainHandItem.clone(); - baitRealItem = rodOnMainHand ? offHandItem : mainHandItem; - noBait = false; - } - } - - for (ActivatedTotem activatedTotem : activeTotemMap.values()) { - if (activatedTotem.getNearbyPlayerSet().contains(player)) { - initialEffect.addEffect(activatedTotem.getTotem().getEffect()); - break; - } - } - - if (ConfigManager.enableFishingBag) { - Inventory fishingBag = plugin.getBagDataManager().getPlayerBagData(player.getUniqueId()); - HashSet uniqueUtils = new HashSet<>(4); - if (fishingBag != null) { - for (int i = 0; i < fishingBag.getSize(); i++) { - ItemStack itemStack = fishingBag.getItem(i); - String bagItemID = plugin.getIntegrationManager().getItemID(itemStack); - if (bagItemID == null) continue; - if (noBait) { - Effect effect = plugin.getEffectManager().getBaitEffect(bagItemID); - if (effect != null) { - if (initialEffect.canAddEffect(effect, fishingCondition)) { - initialEffect.addEffect(effect); - noBait = false; - bait_id = bagItemID; - baitAnimationItem = itemStack.clone(); - baitRealItem = itemStack; - } - continue; - } - } - Effect utilEffect = plugin.getEffectManager().getUtilEffect(bagItemID); - if (utilEffect != null && !uniqueUtils.contains(bagItemID) && initialEffect.canAddEffect(utilEffect, fishingCondition)) { - initialEffect.addEffect(utilEffect); - uniqueUtils.add(bagItemID); - } - } - } - } - - Effect rod_effect = plugin.getEffectManager().getRodEffect(rod_id); - if (rod_effect != null) { - if (initialEffect.canAddEffect(rod_effect, new FishingCondition(player.getLocation(), player, rod_id, bait_id))) { - initialEffect.addEffect(rod_effect); - } else { - event.setCancelled(true); - return; - } - initialEffect.setSpecialRodID(rod_id); - } - this.addEnchantEffect(initialEffect, rodOnMainHand ? mainHandItem : offHandItem, fishingCondition); - - RodCastEvent rodCastEvent = new RodCastEvent(player, initialEffect); - Bukkit.getPluginManager().callEvent(rodCastEvent); - if (rodCastEvent.isCancelled()) { - event.setCancelled(true); - return; - } - - if (baitRealItem != null) baitRealItem.setAmount(baitRealItem.getAmount() - 1); - int lureLevel = rodOnMainHand ? mainHandItem.getEnchantmentLevel(Enchantment.LURE) : offHandItem.getEnchantmentLevel(Enchantment.LURE); - - fishHook.setMaxWaitTime((int) (fishHook.getMaxWaitTime() * initialEffect.getTimeModifier())); - fishHook.setMinWaitTime((int) (fishHook.getMinWaitTime() * initialEffect.getTimeModifier())); - - this.nextEffect.put(player.getUniqueId(), initialEffect); - if (ConfigManager.needRodToFish && !initialEffect.hasSpecialRod()) { - this.nextLoot.put(player.getUniqueId(), LootImpl.EMPTY); - return; - } - - int entityID = 0; - if (baitAnimationItem != null && ConfigManager.baitAnimation) { - baitAnimationItem.setAmount(1); - entityID = new Random().nextInt(Integer.MAX_VALUE); - CustomFishing.getProtocolManager().sendServerPacket(player, FakeItemUtils.getSpawnPacket(entityID, fishHook.getLocation())); - CustomFishing.getProtocolManager().sendServerPacket(player, FakeItemUtils.getMetaPacket(entityID, baitAnimationItem)); - } - - BobberCheckTask bobberCheckTask = new BobberCheckTask(plugin, player, initialEffect, fishHook, this, lureLevel, entityID, rod_id, bait_id); - this.hookCheckTaskMap.put(player.getUniqueId(), bobberCheckTask); - } - - public void onBite(PlayerFishEvent event) { - if (ConfigManager.disableBar || !ConfigManager.instantBar) return; - showBar(event.getPlayer()); - } - - public void getNextLoot(Player player, Effect initialEffect, List possibleLoots) { - List availableLoots = new ArrayList<>(); - if (possibleLoots.size() == 0){ - nextLoot.put(player.getUniqueId(), null); - return; - } - - HashMap as = initialEffect.getWeightAS(); - HashMap md = initialEffect.getWeightMD(); - - double[] weights = new double[possibleLoots.size()]; - int index = 0; - for (LootImpl loot : possibleLoots){ - double weight = loot.getWeight(); - String group = loot.getGroup(); - if (group != null){ - if (as.get(group) != null){ - weight += as.get(group); - } - if (md.get(group) != null){ - weight *= md.get(group); - } - } - if (weight <= 0) continue; - availableLoots.add(loot); - weights[index++] = weight; - } - - double total = Arrays.stream(weights).sum(); - double[] weightRatios = new double[index]; - for (int i = 0; i < index; i++){ - weightRatios[i] = weights[i]/total; - } - - double[] weightRange = new double[index]; - double startPos = 0; - for (int i = 0; i < index; i++) { - weightRange[i] = startPos + weightRatios[i]; - startPos += weightRatios[i]; - } - - double random = Math.random(); - int pos = Arrays.binarySearch(weightRange, random); - - if (pos < 0) { - pos = -pos - 1; - } - if (pos < weightRange.length && random < weightRange[pos]) { - nextLoot.put(player.getUniqueId(), availableLoots.get(pos)); - return; - } - nextLoot.put(player.getUniqueId(), null); - } - - public void onCaughtFish(PlayerFishEvent event) { - final Player player = event.getPlayer(); - if (!(event.getCaught() instanceof Item item)) return; - UUID uuid = player.getUniqueId(); - FishingGame fishingGame = fishingPlayerMap.remove(uuid); - // if the player is noy playing the game - if (fishingGame == null) { - // get his next loot - LootImpl loot = nextLoot.get(uuid); - if (loot == LootImpl.EMPTY) return; - - if (ConfigManager.enableVanillaLoot) { - // Not a vanilla loot - if (ConfigManager.vanillaLootRatio < Math.random()) { - if (loot != null) { - vanillaLoot.remove(uuid); - if (loot.isDisableBar() || ConfigManager.disableBar) { - noBarWaterReelIn(event); - return; - } - showFishingBar(player, loot); - } - else { - vanillaLoot.put(uuid, new VanillaLoot(item.getItemStack(), event.getExpToDrop())); - if (ConfigManager.disableBar) { - noBarWaterReelIn(event); - return; - } - showFishingBar(player, plugin.getLootManager().getVanilla_loot()); - } - event.setCancelled(true); - } - // Is vanilla loot - else { - if (!plugin.getLootManager().getVanilla_loot().isDisableBar() && !ConfigManager.disableBar) { - event.setCancelled(true); - vanillaLoot.put(uuid, new VanillaLoot(item.getItemStack(), event.getExpToDrop())); - showFishingBar(player, plugin.getLootManager().getVanilla_loot()); - } - //else vanilla fishing mechanic - } - } else { - // No custom loot - if (loot == null) { - event.setCancelled(true); - removeHook(uuid); - AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.noLoot); - } - else { - if (loot.isDisableBar() || ConfigManager.disableBar) { - noBarWaterReelIn(event); - return; - } - event.setCancelled(true); - showFishingBar(player, loot); - } - } - } else { - event.setCancelled(true); - removeHook(uuid); - proceedReelIn(event.getHook().getLocation(), player, fishingGame); - } - } - - public void onReelIn(PlayerFishEvent event) { - final Player player = event.getPlayer(); - - if (ConfigManager.disableBar) { - noBarLavaReelIn(event); - return; - } - - UUID uuid = player.getUniqueId(); - //in fishing game - FishingGame fishingGame = fishingPlayerMap.remove(uuid); - if (fishingGame != null) { - proceedReelIn(event.getHook().getLocation(), player, fishingGame); - hookCheckTaskMap.remove(uuid); - return; - } - //not in fishing game - BobberCheckTask bobberCheckTask = hookCheckTaskMap.get(uuid); - if (bobberCheckTask != null && bobberCheckTask.isHooked()) { - LootImpl loot = nextLoot.get(uuid); - if (loot == LootImpl.EMPTY || loot == null) return; - if (loot.isDisableBar()) { - noBarLavaReelIn(event); - return; - } - showFishingBar(player, loot); - event.setCancelled(true); - } - } - - public void onCaughtEntity(PlayerFishEvent event) { - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - FishingGame fishingGame = fishingPlayerMap.remove(uuid); - if (fishingGame != null) { - Entity entity = event.getCaught(); - if (entity != null && entity.getType() == EntityType.ARMOR_STAND) { - proceedReelIn(event.getHook().getLocation(), player, fishingGame); - } - else { - fishingGame.cancel(); - nextEffect.remove(uuid); - nextLoot.remove(uuid); - AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.hookOther); - } - } - } - - private void noBarWaterReelIn(PlayerFishEvent event) { - Entity entity = event.getCaught(); - if (!(entity instanceof Item item)) { - return; - } - entity.remove(); - event.setExpToDrop(0); - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - LootImpl loot = nextLoot.remove(uuid); - VanillaLoot vanilla = vanillaLoot.remove(uuid); - Effect effect = nextEffect.remove(uuid); - if (vanilla != null) { - dropVanillaLoot(player, vanilla, item.getLocation(), effect.getDoubleLootChance() > Math.random()); - } else if (loot instanceof Mob mob) { - summonMob(player, loot, item.getLocation(), mob, effect.getScoreMultiplier()); - } else if (loot instanceof DroppedItem droppedItem){ - if (ConfigManager.enableMcMMOLoot && Math.random() < ConfigManager.mcMMOLootChance){ - if (dropMcMMOLoot(player, item.getLocation(), effect.getDoubleLootChance() > Math.random())){ - return; - } - } - dropCustomFishingLoot(player, item.getLocation(), droppedItem, effect.getDoubleLootChance() > Math.random(), effect.getScoreMultiplier(), effect.getSizeMultiplier()); - } - } - - private void noBarLavaReelIn(PlayerFishEvent event) { - final Player player = event.getPlayer(); - final UUID uuid = player.getUniqueId(); - BobberCheckTask bobberCheckTask = hookCheckTaskMap.remove(uuid); - if (bobberCheckTask != null && bobberCheckTask.isHooked()) { - LootImpl loot = nextLoot.remove(uuid); - VanillaLoot vanilla = vanillaLoot.remove(uuid); - Effect effect = nextEffect.remove(uuid); - if (vanilla != null) { - dropVanillaLoot(player, vanilla, event.getHook().getLocation(), effect.getDoubleLootChance() > Math.random()); - } else if (loot instanceof Mob mob) { - summonMob(player, loot, event.getHook().getLocation(), mob, effect.getScoreMultiplier()); - } else if (loot instanceof DroppedItem droppedItem) { - if (ConfigManager.enableMcMMOLoot && Math.random() < ConfigManager.mcMMOLootChance) { - if (dropMcMMOLoot(player, event.getHook().getLocation(), effect.getDoubleLootChance() > Math.random())){ - return; - } - } - dropCustomFishingLoot(player, event.getHook().getLocation(), droppedItem, effect.getDoubleLootChance() > Math.random(), effect.getScoreMultiplier(), effect.getSizeMultiplier()); - } - } - } - - public void proceedReelIn(Location hookLoc, Player player, FishingGame fishingGame) { - fishingGame.cancel(); - final UUID uuid = player.getUniqueId(); - LootImpl loot = nextLoot.remove(uuid); - VanillaLoot vanilla = vanillaLoot.remove(uuid); - Effect effect = nextEffect.remove(uuid); - player.removePotionEffect(PotionEffectType.SLOW); - if (fishingGame.isSuccess()) { - if (ConfigManager.rodLoseDurability) loseDurability(player); - if (hookLoc.getBlock().getType() == Material.LAVA) { - hookLoc.add(0,0.3,0); - } - if (vanilla != null) { - dropVanillaLoot(player, vanilla, hookLoc, effect.getDoubleLootChance() > Math.random()); - } else if (loot instanceof Mob mob) { - summonMob(player, loot, hookLoc, mob, effect.getScoreMultiplier()); - } else if (loot instanceof DroppedItem droppedItem){ - if (ConfigManager.enableMcMMOLoot && Math.random() < ConfigManager.mcMMOLootChance){ - if (dropMcMMOLoot(player, hookLoc, effect.getDoubleLootChance() > Math.random())){ - return; - } - } - dropCustomFishingLoot(player, hookLoc, droppedItem, effect.getDoubleLootChance() > Math.random(), effect.getScoreMultiplier(), effect.getSizeMultiplier()); - } - } else { - fail(player, loot, vanilla != null); - } - } - - private void dropCustomFishingLoot(Player player, Location location, DroppedItem droppedItem, boolean isDouble, double scoreMultiplier, double sizeMultiplier) { - Pair dropPair = getCustomFishingLootItemStack(droppedItem, player, sizeMultiplier); - FishResultEvent fishResultEvent = new FishResultEvent(player, FishResult.CATCH_SPECIAL_ITEM, isDouble, dropPair.left(), droppedItem.getKey(), droppedItem); - Bukkit.getPluginManager().callEvent(fishResultEvent); - if (fishResultEvent.isCancelled()) { - return; - } - - if (Competition.currentCompetition != null) { - float score = Competition.currentCompetition.getGoal() == CompetitionGoal.MAX_SIZE - || Competition.currentCompetition.getGoal() == CompetitionGoal.TOTAL_SIZE - ? dropPair.right().size() : (float) ((float) droppedItem.getScore() * scoreMultiplier); - Competition.currentCompetition.refreshData(player, score, fishResultEvent.isDouble()); - Competition.currentCompetition.tryJoinCompetition(player); - } - - if (droppedItem.getSuccessActions() != null) - for (Action action : droppedItem.getSuccessActions()) - action.doOn(player, null, dropPair.right()); - - if (plugin.getVersionHelper().isFolia()) { - plugin.getScheduler().runTask(() -> dropItem(player, location, fishResultEvent.isDouble(), dropPair.left()), location); - } else { - dropItem(player, location, fishResultEvent.isDouble(), dropPair.left()); - } - - addStats(player, droppedItem, isDouble ? 2 : 1); - sendSuccessTitle(player, droppedItem.getNick()); - } - - public ItemStack getCustomFishingLootItemStack(DroppedItem droppedItem, Player player) { - return getCustomFishingLootItemStack(droppedItem, player, 1).left(); - } - - public Pair getCustomFishingLootItemStack(DroppedItem droppedItem, @Nullable Player player, double sizeMultiplier) { - ItemStack drop = plugin.getIntegrationManager().build(droppedItem.getMaterial(), player); - FishMeta fishMeta = null; - if (drop.getType() != Material.AIR) { - if (droppedItem.getRandomEnchants() != null) - ItemStackUtils.addRandomEnchants(drop, droppedItem.getRandomEnchants()); - if (droppedItem.isRandomDurability()) - ItemStackUtils.addRandomDamage(drop); - if (ConfigManager.preventPickUp && player != null) - ItemStackUtils.addOwner(drop, player.getName()); - fishMeta = ItemStackUtils.addExtraMeta(drop, droppedItem, sizeMultiplier, player); - } - return Pair.of(drop, fishMeta); - } - - private boolean dropMcMMOLoot(Player player, Location location, boolean isDouble) { - ItemStack itemStack = McMMOTreasure.getTreasure(player); - if (itemStack == null) return false; - - FishResultEvent fishResultEvent = new FishResultEvent(player, FishResult.CATCH_VANILLA_ITEM, isDouble, itemStack, "mcMMO", null); - Bukkit.getPluginManager().callEvent(fishResultEvent); - if (fishResultEvent.isCancelled()) { - return true; - } - - doVanillaActions(player, location, itemStack, fishResultEvent.isDouble()); - new VanillaXPImpl(new Random().nextInt(24), true, 1).doOn(player); - return true; - } - - private void dropVanillaLoot(Player player, VanillaLoot vanillaLoot, Location location, boolean isDouble) { - ItemStack itemStack = vanillaLoot.getItemStack(); - if (ConfigManager.enableMcMMOLoot && Math.random() < ConfigManager.mcMMOLootChance){ - ItemStack mcMMOItemStack = McMMOTreasure.getTreasure(player); - if (mcMMOItemStack != null){ - itemStack = mcMMOItemStack; - } - } - - FishResultEvent fishResultEvent = new FishResultEvent(player, FishResult.CATCH_VANILLA_ITEM, isDouble, itemStack, "vanilla", null); - Bukkit.getPluginManager().callEvent(fishResultEvent); - if (fishResultEvent.isCancelled()) { - return; - } - - doVanillaActions(player, location, itemStack, fishResultEvent.isDouble()); - new VanillaXPImpl(vanillaLoot.getXp(), true, 1).doOn(player); - } - - private void doVanillaActions(Player player, Location location, ItemStack itemStack, boolean isDouble) { - if (Competition.currentCompetition != null) { - Competition.currentCompetition.refreshData(player, (float) plugin.getLootManager().getVanilla_loot().getScore(), isDouble); - Competition.currentCompetition.tryJoinCompetition(player); - } - - LootImpl vanilla = plugin.getLootManager().getVanilla_loot(); - addStats(player, vanilla, isDouble ? 2 : 1); - - if (vanilla.getSuccessActions() != null) - for (Action action : vanilla.getSuccessActions()) - action.doOn(player); - - AdventureUtils.playerSound(player, Sound.Source.PLAYER, Key.key("minecraft:entity.experience_orb.pickup"), 1, 1); - - if (plugin.getVersionHelper().isFolia()) { - plugin.getScheduler().runTask(() -> dropItem(player, location, isDouble, itemStack), location); - } else { - dropItem(player, location, isDouble, itemStack); - } - - sendSuccessTitle(player, itemStack); - } - - private void dropItem(Player player, Location location, boolean isDouble, ItemStack itemStack) { - if (itemStack.getType() == Material.AIR) return; - Entity item = location.getWorld().dropItem(location, itemStack); - Vector vector = player.getLocation().subtract(location).toVector().multiply(0.105); - vector = vector.setY((vector.getY() + 0.2) * 1.18); - item.setVelocity(vector); - if (isDouble) { - Entity item2 = location.getWorld().dropItem(location, itemStack); - item2.setVelocity(vector); - } - } - - private void addStats(Player player, LootImpl loot, int amount) { - player.setStatistic(Statistic.FISH_CAUGHT, player.getStatistic(Statistic.FISH_CAUGHT) + 1); - if (!ConfigManager.enableStatistics) return; - if (loot.isDisableStats()) return; - plugin.getStatisticsManager().addFishAmount(player.getUniqueId(), loot, amount); - } - - private void summonMob(Player player, LootImpl loot, Location location, Mob mob, double scoreMultiplier) { - MobInterface mobInterface = plugin.getIntegrationManager().getMobInterface(); - if (mobInterface == null) return; - - FishResultEvent fishResultEvent = new FishResultEvent(player, FishResult.CATCH_MOB, false, null, loot.getKey(), loot); - if (fishResultEvent.isCancelled()) { - return; - } - - if (Competition.currentCompetition != null) { - float score = Competition.currentCompetition.getGoal() == CompetitionGoal.MAX_SIZE || Competition.currentCompetition.getGoal() == CompetitionGoal.TOTAL_SIZE ? 0 : (float) loot.getScore(); - Competition.currentCompetition.refreshData(player, (float) (score * scoreMultiplier), false); - Competition.currentCompetition.tryJoinCompetition(player); - } - - if (loot.getSuccessActions() != null) - for (Action action : loot.getSuccessActions()) - action.doOn(player); - - mobInterface.summon(player.getLocation(), location, mob); - addStats(player, mob, 1); - sendSuccessTitle(player, loot.getNick()); - } - - @NotNull - private Component getTitleComponent(ItemStack itemStack, String text) { - Component titleComponent = Component.text(""); - int startIndex = 0; - int lootIndex; - while ((lootIndex = text.indexOf("{loot}", startIndex)) != -1) { - String before = text.substring(startIndex, lootIndex); - titleComponent = titleComponent.append(AdventureUtils.getComponentFromMiniMessage(before)); - startIndex = lootIndex + 6; - titleComponent = titleComponent.append(getDisplayName(itemStack)); - } - String after = text.substring(startIndex); - titleComponent = titleComponent.append(AdventureUtils.getComponentFromMiniMessage(after)); - return titleComponent; - } - - private void sendSuccessTitle(Player player, String loot) { - if (!ConfigManager.enableSuccessTitle) return; - plugin.getScheduler().runTaskAsyncLater(() -> AdventureUtils.playerTitle( - player, - ConfigManager.successTitle[new Random().nextInt(ConfigManager.successTitle.length)] - .replace("{loot}", loot) - .replace("{player}", player.getName()), - ConfigManager.successSubTitle[new Random().nextInt(ConfigManager.successSubTitle.length)] - .replace("{loot}", loot) - .replace("{player}", player.getName()), - ConfigManager.successFadeIn, - ConfigManager.successFadeStay, - ConfigManager.successFadeOut - ), 400, TimeUnit.MILLISECONDS); - } - - private void sendSuccessTitle(Player player, ItemStack itemStack) { - if (!ConfigManager.enableSuccessTitle) return; - String title = ConfigManager.successTitle[new Random().nextInt(ConfigManager.successTitle.length)]; - Component titleComponent = getTitleComponent(itemStack, title); - String subTitle = ConfigManager.successSubTitle[new Random().nextInt(ConfigManager.successSubTitle.length)]; - Component subtitleComponent = getTitleComponent(itemStack, subTitle); - plugin.getScheduler().runTaskAsyncLater(() -> AdventureUtils.playerTitle( - player, - titleComponent, - subtitleComponent, - ConfigManager.successFadeIn, - ConfigManager.successFadeStay, - ConfigManager.successFadeOut - ), 400, TimeUnit.MILLISECONDS); - } - - private void loseDurability(Player player) { - if (player.getGameMode() == GameMode.CREATIVE) return; - plugin.getScheduler().runTaskAsyncLater(() -> { - ItemStack rod = getFishingRod(player); - if (rod != null) { - plugin.getIntegrationManager().loseCustomDurability(rod, player); - } - }, 50, TimeUnit.MILLISECONDS); - } - - private ItemStack getFishingRod(Player player) { - ItemStack mainHand = player.getInventory().getItemInMainHand(); - if (mainHand.getType() == Material.FISHING_ROD) { - return mainHand; - } - ItemStack offHand = player.getInventory().getItemInOffHand(); - if (offHand.getType() == Material.FISHING_ROD) { - return offHand; - } - return null; - } - - public void fail(Player player, LootImpl loot, boolean isVanilla) { - FishResultEvent fishResultEvent = new FishResultEvent(player, FishResult.FAILURE, false, null, null, null); - Bukkit.getServer().getPluginManager().callEvent(fishResultEvent); - if (fishResultEvent.isCancelled()) { - return; - } - - if (!isVanilla && loot != null && loot.getFailureActions() != null) { - for (Action action : loot.getFailureActions()) - action.doOn(player); - } - - if (!ConfigManager.enableFailureTitle) return; - plugin.getScheduler().runTaskAsyncLater(() -> AdventureUtils.playerTitle( - player, - ConfigManager.failureTitle[new Random().nextInt(ConfigManager.failureTitle.length)], - ConfigManager.failureSubTitle[new Random().nextInt(ConfigManager.failureSubTitle.length)], - ConfigManager.failureFadeIn, - ConfigManager.failureFadeStay, - ConfigManager.failureFadeOut - ), 400, TimeUnit.MILLISECONDS); - } - - public void showBar(Player player) { - final UUID uuid = player.getUniqueId(); - if (fishingPlayerMap.get(uuid) != null) return; - LootImpl loot = nextLoot.get(uuid); - if (loot != null) { - if (loot == LootImpl.EMPTY) return; - showFishingBar(player, loot); - } - } - - public boolean isCoolDown(Player player, long delay) { - long time = System.currentTimeMillis(); - long last = coolDown.getOrDefault(player.getUniqueId(), time - delay); - if (last + delay > time) { - return true; - } else { - coolDown.put(player.getUniqueId(), time); - return false; - } - } - - private void addEnchantEffect(Effect initialEffect, ItemStack itemStack, FishingCondition fishingCondition) { - for (String key : plugin.getIntegrationManager().getEnchantmentInterface().getEnchants(itemStack)) { - Effect enchantEffect = plugin.getEffectManager().getEnchantEffect(key); - if (enchantEffect != null && enchantEffect.canAddEffect(enchantEffect, fishingCondition)) { - initialEffect.addEffect(enchantEffect); - } - } - } - - public List getPossibleLootList(FishingCondition fishingCondition, boolean finder, Collection values) { - Stream stream = values.stream(); - if (finder) { - stream = stream.filter(LootImpl::isShowInFinder); - } - return stream.filter(loot -> { - RequirementInterface[] requirements = loot.getRequirements(); - if (requirements == null) { - return true; - } - for (RequirementInterface requirement : requirements) { - if (!requirement.isConditionMet(fishingCondition)) { - return false; - } - } - return true; - }).collect(Collectors.toList()); - } - - @Override - public void onInteract(PlayerInteractEvent event) { - ItemStack itemStack = event.getItem(); - final Player player = event.getPlayer(); - if (itemStack == null || itemStack.getType() == Material.AIR) return; - - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound cfCompound = nbtItem.getCompound("CustomFishing"); - if (cfCompound != null && cfCompound.getString("type").equals("util") && cfCompound.getString("id").equals("fishfinder")) { - if (isCoolDown(player, 1000)) return; - useFinder(event.getPlayer()); - return; - } - - Block block = event.getClickedBlock(); - if (block == null) return; - String totemID = nbtItem.getString("Totem"); - if (totemID.equals("")) return; - TotemConfig totem = plugin.getTotemManager().getTotem(totemID); - if (totem == null) return; - if (isCoolDown(player, 1000)) return; - String blockID = plugin.getIntegrationManager().getBlockInterface().getID(block); - if (blockID == null) return; - List totemList = plugin.getTotemManager().getTotemsByCoreID(blockID); - if (totemList == null || !totemList.contains(totem)) return; - - FishingCondition fishingCondition = new FishingCondition(block.getLocation(), player); - if (totem.getRequirements() != null) - for (RequirementInterface requirement : totem.getRequirements()) { - if (!requirement.isConditionMet(fishingCondition)) { - return; - } - } - - Location coreLoc = block.getLocation(); - int direction = plugin.getTotemManager().checkLocationModel(totem.getOriginalModel(), coreLoc); - if (direction == 0) return; - - TotemActivationEvent totemActivationEvent = new TotemActivationEvent(player, coreLoc, totem); - Bukkit.getPluginManager().callEvent(totemActivationEvent); - if (totemActivationEvent.isCancelled()) { - return; - } - - if (activeTotemMap.get(LocationUtils.getSimpleLocation(coreLoc)) != null) { - activeTotemMap.get(LocationUtils.getSimpleLocation(coreLoc)).stop(); - } - - plugin.getTotemManager().removeModel(totem.getFinalModel(), coreLoc, direction); - if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1); - if (totem.getActivatorActions() != null) - for (Action action : totem.getActivatorActions()) { - action.doOn(player); - } - if (totem.getNearbyActions() != null) - for (Action action : totem.getNearbyActions()) { - for (Player nearby : LocationUtils.getNearbyPlayers(coreLoc, totem.getRadius())) { - action.doOn(nearby, player); - } - } - - ActivatedTotem activatedTotem = new ActivatedTotem(coreLoc, totem, this, direction, player.getName()); - activeTotemMap.put(LocationUtils.getSimpleLocation(coreLoc), activatedTotem); - } - - private void useFinder(Player player) { - if (!ConfigManager.getWorldsList().contains(player.getWorld().getName())) { - return; - } - - FishingCondition fishingCondition = new FishingCondition(player.getLocation(), player, "fish_finder", "fish_finder"); - List possibleLoots = getPossibleLootList(fishingCondition, true, plugin.getLootManager().getAllLoots()); - - FishFinderEvent fishFinderEvent = new FishFinderEvent(player, possibleLoots); - Bukkit.getPluginManager().callEvent(fishFinderEvent); - if (fishFinderEvent.isCancelled()) { - return; - } - - if (possibleLoots.size() == 0) { - AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.noLoot); - return; - } - StringJoiner stringJoiner = new StringJoiner(MessageManager.splitChar); - possibleLoots.forEach(loot -> stringJoiner.add(loot.getNick())); - AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.possibleLoots + stringJoiner); - } - - private void showFishingBar(Player player, @NotNull LootImpl loot) { - MiniGameConfig game = loot.getFishingGames() != null - ? loot.getFishingGames()[new Random().nextInt(loot.getFishingGames().length)] - : plugin.getBarMechanicManager().getRandomGame(); - int difficult = game.getRandomDifficulty() + nextEffect.getOrDefault(player.getUniqueId(), new Effect()).getDifficulty(); - MiniGameStartEvent miniGameStartEvent = new MiniGameStartEvent(player, Math.min(10, Math.max(1, difficult))); - Bukkit.getPluginManager().callEvent(miniGameStartEvent); - if (miniGameStartEvent.isCancelled()) { - return; - } - FishingBar fishingBar = game.getRandomBar(); - FishingGame fishingGame = null; - Location hookLoc = getHookLocation(player); - if (hookLoc == null) return; - if (fishingBar instanceof ModeOneBar modeOneBar) { - fishingGame = new ModeOneGame(plugin, this, System.currentTimeMillis() + game.getTime() * 1000L, player, miniGameStartEvent.getDifficulty(), modeOneBar); - } - else if (fishingBar instanceof ModeTwoBar modeTwoBar) { - fishingGame = new ModeTwoGame(plugin, this, System.currentTimeMillis() + game.getTime() * 1000L, player, miniGameStartEvent.getDifficulty(), modeTwoBar, hookLoc); - } - else if (fishingBar instanceof ModeThreeBar modeThreeBar) { - fishingGame = new ModeThreeGame(plugin, this, System.currentTimeMillis() + game.getTime() * 1000L, player, miniGameStartEvent.getDifficulty(), modeThreeBar); - } - if (fishingGame != null) { - fishingPlayerMap.put(player.getUniqueId(), fishingGame); - } - if (loot.getHookActions() != null) { - for (Action action : loot.getHookActions()) { - action.doOn(player); - } - } - player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, game.getTime() * 20,3)); - } - - @Override - public void onQuit(Player player) { - final UUID uuid = player.getUniqueId(); - coolDown.remove(uuid); - nextLoot.remove(uuid); - nextEffect.remove(uuid); - vanillaLoot.remove(uuid); - BobberCheckTask task = hookCheckTaskMap.remove(uuid); - if (task != null) task.stop(); - removeHook(uuid); - } - - public void removeFishingPlayer(Player player) { - fishingPlayerMap.remove(player.getUniqueId()); - } - - private Component getDisplayName(ItemStack itemStack){ - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.getCompound("display"); - if (nbtCompound != null){ - String name = nbtCompound.getString("Name"); - if (!name.equals("")){ - return GsonComponentSerializer.gson().deserialize(name); - } - } - String type = itemStack.getType().toString().toLowerCase(); - if (itemStack.getType().isBlock()) return GsonComponentSerializer.gson().deserialize("{\"translate\":\"block.minecraft." + type + "\"}"); - else return GsonComponentSerializer.gson().deserialize("{\"translate\":\"item.minecraft." + type + "\"}"); - } - - public void removeTotem(Location coreLoc) { - activeTotemMap.remove(LocationUtils.getSimpleLocation(coreLoc)); - } - - public void removePlayerFromLavaFishing(Player player) { - this.hookCheckTaskMap.remove(player.getUniqueId()); - } - - public float getSize(ItemStack itemStack) { - NBTCompound fishMeta = new NBTItem(itemStack).getCompound("FishMeta"); - return fishMeta != null ? fishMeta.getFloat("size") : 0; - } - - public void addTotemBreakDetectToCache(SimpleLocation part, SimpleLocation coreLoc) { - breakDetectionMap.put(part, coreLoc); - } - - public void removeTotemBreakDetectFromCache(SimpleLocation part) { - breakDetectionMap.remove(part); - } - - @Override - public void onBreakBlock(BlockBreakEvent event) { - SimpleLocation coreLoc = breakDetectionMap.get(LocationUtils.getSimpleLocation(event.getBlock().getLocation())); - if (coreLoc != null) { - ActivatedTotem activatedTotem = activeTotemMap.get(coreLoc); - if (activatedTotem != null) { - activatedTotem.stop(); - } - } - } - - public void removeHook(UUID uuid) { - FishHook fishHook = removeHookCache(uuid); - if (fishHook != null) { - plugin.getScheduler().runTask(fishHook::remove, fishHook.getLocation()); - } - } - - public FishHook removeHookCache(UUID uuid) { - return hooks.remove(uuid); - } - - @Nullable - public FishHook getHook(UUID uuid) { - return hooks.get(uuid); - } - - @Nullable - public Location getHookLocation(Player player) { - FishHook fishHook = hooks.get(player.getUniqueId()); - if (fishHook != null) { - return fishHook.getLocation(); - } - return null; - } - - @Override - public void onConsumeItem(PlayerItemConsumeEvent event) { - ItemStack itemStack = event.getItem(); - NBTCompound nbtCompound = new NBTItem(itemStack).getCompound("CustomFishing"); - if (nbtCompound == null) return; - if (!nbtCompound.getString("type").equals("loot")) return; - String lootKey = nbtCompound.getString("id"); - LootImpl loot = plugin.getLootManager().getLoot(lootKey); - if (loot == null) return; - if (!(loot instanceof DroppedItem droppedItem)) return; - final Player player = event.getPlayer(); - if (droppedItem.getConsumeActions() != null) - for (Action action : droppedItem.getConsumeActions()) - action.doOn(player); - } - - public Effect getInitialEffect(Player player) { - boolean noBait = true; - boolean rodOnMainHand = false; - - Effect initialEffect = new Effect(); - initialEffect.setWeightMD(new HashMap<>(8)); - initialEffect.setWeightAS(new HashMap<>(8)); - - final PlayerInventory inventory = player.getInventory(); - final ItemStack mainHandItem = inventory.getItemInMainHand(); - final ItemStack offHandItem = inventory.getItemInOffHand(); - - if (mainHandItem.getType() == Material.FISHING_ROD) { - rodOnMainHand = true; - } - String rod_id = Optional.ofNullable(rodOnMainHand ? CustomFishingAPI.getRodID(mainHandItem) : CustomFishingAPI.getRodID(offHandItem)).orElse("vanilla"); - final FishingCondition fishingCondition = new FishingCondition(player.getLocation(), player, rod_id, null); - - String bait_id = Optional.ofNullable(rodOnMainHand ? CustomFishingAPI.getBaitID(offHandItem) : CustomFishingAPI.getBaitID(mainHandItem)).orElse(""); - Effect baitEffect = plugin.getEffectManager().getBaitEffect(bait_id); - if (baitEffect != null && initialEffect.canAddEffect(baitEffect, fishingCondition)) { - initialEffect.addEffect(baitEffect); - noBait = false; - } - - for (ActivatedTotem activatedTotem : activeTotemMap.values()) { - if (activatedTotem.getNearbyPlayerSet().contains(player)) { - initialEffect.addEffect(activatedTotem.getTotem().getEffect()); - break; - } - } - - if (ConfigManager.enableFishingBag) { - Inventory fishingBag = plugin.getBagDataManager().getPlayerBagData(player.getUniqueId()); - HashSet uniqueUtils = new HashSet<>(4); - if (fishingBag != null) { - for (int i = 0; i < fishingBag.getSize(); i++) { - ItemStack itemStack = fishingBag.getItem(i); - if (itemStack == null || itemStack.getType() == Material.AIR) continue; - NBTCompound cfCompound = new NBTItem(itemStack).getCompound("CustomFishing"); - if (cfCompound == null) continue; - String type = cfCompound.getString("type"); String id = cfCompound.getString("id"); - if (noBait && type.equals("bait")) { - Effect effect = plugin.getEffectManager().getBaitEffect(id); - if (effect != null && itemStack.getAmount() > 0 && initialEffect.canAddEffect(effect, fishingCondition)) { - initialEffect.addEffect(effect); - noBait = false; - bait_id = id; - } - } else if (type.equals("util")) { - Effect utilEffect = plugin.getEffectManager().getUtilEffect(id); - if (utilEffect != null && !uniqueUtils.contains(id)) { - initialEffect.addEffect(utilEffect); - uniqueUtils.add(id); - } - } - } - } - } - - Effect rod_effect = plugin.getEffectManager().getRodEffect(rod_id); - if (rod_effect != null) { - if (initialEffect.canAddEffect(rod_effect, new FishingCondition(player.getLocation(), player, rod_id, bait_id))) { - initialEffect.addEffect(rod_effect); - } else { - return null; - } - initialEffect.setSpecialRodID(rod_id); - } - this.addEnchantEffect(initialEffect, rodOnMainHand ? mainHandItem : offHandItem, fishingCondition); - return initialEffect; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/manager/IntegrationManager.java b/src/main/java/net/momirealms/customfishing/manager/IntegrationManager.java deleted file mode 100644 index 98a72b59..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/IntegrationManager.java +++ /dev/null @@ -1,328 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.helper.Log; -import net.momirealms.customfishing.integration.*; -import net.momirealms.customfishing.integration.block.ItemsAdderBlockImpl; -import net.momirealms.customfishing.integration.block.OraxenBlockImpl; -import net.momirealms.customfishing.integration.block.VanillaBlockImpl; -import net.momirealms.customfishing.integration.enchantment.AEImpl; -import net.momirealms.customfishing.integration.enchantment.VanillaImpl; -import net.momirealms.customfishing.integration.item.*; -import net.momirealms.customfishing.integration.job.EcoJobsImpl; -import net.momirealms.customfishing.integration.job.JobsRebornImpl; -import net.momirealms.customfishing.integration.mob.MythicMobsMobImpl; -import net.momirealms.customfishing.integration.papi.PlaceholderManager; -import net.momirealms.customfishing.integration.quest.BattlePassCFQuest; -import net.momirealms.customfishing.integration.quest.ClueScrollCFQuest; -import net.momirealms.customfishing.integration.quest.NewBetonQuestCFQuest; -import net.momirealms.customfishing.integration.quest.OldBetonQuestCFQuest; -import net.momirealms.customfishing.integration.season.CustomCropsSeasonImpl; -import net.momirealms.customfishing.integration.season.RealisticSeasonsImpl; -import net.momirealms.customfishing.integration.skill.AureliumsImpl; -import net.momirealms.customfishing.integration.skill.EcoSkillsImpl; -import net.momirealms.customfishing.integration.skill.MMOCoreImpl; -import net.momirealms.customfishing.integration.skill.mcMMOImpl; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ConfigUtils; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.Damageable; -import org.bukkit.plugin.PluginManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class IntegrationManager extends Function { - - private SeasonInterface seasonInterface; - private SkillInterface skillInterface; - private ItemInterface[] itemInterfaces; - private MobInterface mobInterface; - private BlockInterface blockInterface; - private JobInterface jobInterface; - private EnchantmentInterface enchantmentInterface; - private final PlaceholderManager placeholderManager; - private VaultHook vaultHook; - private final CustomFishing plugin; - private final PluginManager pluginManager; - - public IntegrationManager(CustomFishing plugin) { - this.plugin = plugin; - this.pluginManager = Bukkit.getPluginManager(); - this.placeholderManager = new PlaceholderManager(plugin); - } - - @Override - public void load() { - this.placeholderManager.load(); - hookSeasons(); - hookSkills(); - hookJobs(); - hookItems(); - hookVault(); - hookMobs(); - hookBlocks(); - hookEnchants(); - } - - @Override - public void unload() { - this.seasonInterface = null; - this.skillInterface = null; - this.itemInterfaces = null; - this.mobInterface = null; - this.blockInterface = null; - this.jobInterface = null; - this.enchantmentInterface = null; - this.placeholderManager.unload(); - } - - private void hookEnchants() { - if (pluginManager.isPluginEnabled("AdvancedEnchantments")) { - this.enchantmentInterface = new AEImpl(); - hookMessage("AdvancedEnchantments"); - } - else if (pluginManager.isPluginEnabled("EcoEnchants")) { - this.enchantmentInterface = new VanillaImpl(); - hookMessage("EcoEnchants"); - } - else { - this.enchantmentInterface = new VanillaImpl(); - } - } - - private void hookMobs() { - if (pluginManager.isPluginEnabled("MythicMobs") && pluginManager.getPlugin("MythicMobs").getDescription().getVersion().startsWith("5")) { - this.mobInterface = new MythicMobsMobImpl(); - } - } - - private void hookBlocks() { - if (pluginManager.isPluginEnabled("Oraxen")) { - this.blockInterface = new OraxenBlockImpl(); - } - else if (pluginManager.isPluginEnabled("ItemsAdder")) { - this.blockInterface = new ItemsAdderBlockImpl(); - } - else { - this.blockInterface = new VanillaBlockImpl(); - } - } - - private void hookSeasons() { - if (pluginManager.isPluginEnabled("RealisticSeasons")) { - this.seasonInterface = new RealisticSeasonsImpl(); - hookMessage("RealisticSeasons"); - } else if (pluginManager.isPluginEnabled("CustomCrops")) { - this.seasonInterface = new CustomCropsSeasonImpl(); - hookMessage("CustomCrops"); - } - } - - private void hookSkills() { - if (pluginManager.isPluginEnabled("mcMMO")) { - this.skillInterface = new mcMMOImpl(); - hookMessage("mcMMO"); - } else if (pluginManager.isPluginEnabled("MMOCore")) { - this.skillInterface = new MMOCoreImpl(ConfigUtils.getConfig("config.yml").getString("other-settings.MMOCore-profession-name", "fishing")); - hookMessage("MMOCore"); - } else if (pluginManager.isPluginEnabled("AureliumSkills")) { - this.skillInterface = new AureliumsImpl(); - hookMessage("AureliumSkills"); - } else if (pluginManager.isPluginEnabled("EcoSkills")) { - this.skillInterface = new EcoSkillsImpl(); - hookMessage("EcoSkills"); - } - } - - private void hookJobs() { - if (this.jobInterface instanceof JobsRebornImpl jobsReborn) { - HandlerList.unregisterAll(jobsReborn); - } - if (pluginManager.isPluginEnabled("Jobs")) { - this.jobInterface = new JobsRebornImpl(); - Bukkit.getPluginManager().registerEvents((Listener) jobInterface, plugin); - hookMessage("JobsReborn"); - } else if (pluginManager.isPluginEnabled("EcoJobs")) { - this.jobInterface = new EcoJobsImpl(); - hookMessage("EcoJobs"); - } - } - - private void hookVault() { - if (pluginManager.isPluginEnabled("Vault")) { - vaultHook = new VaultHook(); - if (!vaultHook.initialize()) { - Log.warn("Failed to initialize Vault!"); - } - else hookMessage("Vault"); - } - } - - private void hookItems() { - List itemInterfaceList = new ArrayList<>(); - if (pluginManager.isPluginEnabled("ItemsAdder")) { - itemInterfaceList.add(new ItemsAdderItemImpl()); - hookMessage("ItemsAdder"); - } - if (pluginManager.isPluginEnabled("Oraxen")) { - itemInterfaceList.add(new OraxenItemImpl()); - hookMessage("Oraxen"); - } - if (pluginManager.isPluginEnabled("MMOItems")) { - itemInterfaceList.add(new MMOItemsItemImpl()); - hookMessage("MMOItems"); - } - if (pluginManager.isPluginEnabled("MythicMobs") && pluginManager.getPlugin("MythicMobs").getDescription().getVersion().startsWith("5")) { - itemInterfaceList.add(new MythicMobsItemImpl()); - hookMessage("MythicMobs"); - } - if (pluginManager.isPluginEnabled("NeigeItems")) { - itemInterfaceList.add(new NeigeItemsImpl()); - hookMessage("NeigeItems"); - } - itemInterfaceList.add(new CustomFishingItemImpl(plugin)); - this.itemInterfaces = itemInterfaceList.toArray(new ItemInterface[0]); - - if (pluginManager.isPluginEnabled("eco")) { - EcoItemRegister.registerItems(); - hookMessage("eco"); - } - } - - public void registerQuests() { - if (pluginManager.isPluginEnabled("ClueScrolls")) { - ClueScrollCFQuest clueScrollCFQuest = new ClueScrollCFQuest(); - Bukkit.getPluginManager().registerEvents(clueScrollCFQuest, plugin); - hookMessage("ClueScrolls"); - } - if (pluginManager.isPluginEnabled("BetonQuest")) { - if (Bukkit.getPluginManager().getPlugin("BetonQuest").getDescription().getVersion().startsWith("2")) NewBetonQuestCFQuest.register(); - else OldBetonQuestCFQuest.register(); - hookMessage("BetonQuest"); - } - if (pluginManager.isPluginEnabled("BattlePass")) { - BattlePassCFQuest battlePassCFQuest = new BattlePassCFQuest(); - Bukkit.getPluginManager().registerEvents(battlePassCFQuest, plugin); - hookMessage("BattlePass"); - } - } - - @Nullable - public SeasonInterface getSeasonInterface() { - return seasonInterface; - } - - @Nullable - public SkillInterface getSkillInterface() { - return skillInterface; - } - - @NotNull - public ItemInterface[] getItemInterfaces() { - return itemInterfaces; - } - - @Nullable - public MobInterface getMobInterface() { - return mobInterface; - } - - @NotNull - public BlockInterface getBlockInterface() { - return blockInterface; - } - - @NotNull - public PlaceholderManager getPlaceholderManager() { - return placeholderManager; - } - - @NotNull - public EnchantmentInterface getEnchantmentInterface() { - return enchantmentInterface; - } - - @Nullable - public JobInterface getJobInterface() { - return jobInterface; - } - - @NotNull - public ItemStack build(String key) { - for (ItemInterface itemInterface : getItemInterfaces()) { - ItemStack itemStack = itemInterface.build(key, null); - if (itemStack != null) { - return itemStack; - } - } - return new ItemStack(Material.AIR); - } - - @NotNull - public ItemStack build(String key, Player player) { - for (ItemInterface itemInterface : getItemInterfaces()) { - ItemStack itemStack = itemInterface.build(key, player); - if (itemStack != null) { - return itemStack; - } - } - return new ItemStack(Material.AIR); - } - - @Nullable - public String getItemID(ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) return null; - for (int i = 0, size = itemInterfaces.length; i < size; i++) { - String id = itemInterfaces[size - i - 1].getID(itemStack); - if (id != null) { - return id; - } - } - return null; - } - - public void loseCustomDurability(ItemStack itemStack, Player player) { - Damageable damageable = (Damageable) itemStack.getItemMeta(); - if (damageable.isUnbreakable()) return; - for (ItemInterface itemInterface : getItemInterfaces()) { - if (itemInterface.loseCustomDurability(itemStack, player)) { - return; - } - } - } - - private void hookMessage(String plugin){ - AdventureUtils.consoleMessage("[CustomFishing] " + plugin + " hooked!"); - } - - @Nullable - public VaultHook getVaultHook() { - return vaultHook; - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/LootManager.java b/src/main/java/net/momirealms/customfishing/manager/LootManager.java deleted file mode 100644 index 4ca242ff..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/LootManager.java +++ /dev/null @@ -1,327 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.MiniGameConfig; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.loot.*; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.object.LeveledEnchantment; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ConfigUtils; -import net.momirealms.customfishing.util.ItemStackUtils; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.MemorySection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.*; - -public class LootManager extends Function { - - private final CustomFishing plugin; - private final HashMap waterLoots; - private final HashMap lavaLoots; - private final HashMap lootItems; - private final HashMap> category; - private LootImpl vanilla_loot; - - public LootManager(CustomFishing plugin) { - this.plugin = plugin; - this.waterLoots = new HashMap<>(); - this.lavaLoots = new HashMap<>(); - this.lootItems = new HashMap<>(); - this.category = new HashMap<>(); - } - - @Nullable - public ItemStack build(String key) { - Item item = lootItems.get(key); - return item == null || item.getMaterial() == Material.AIR ? new ItemStack(Material.AIR) : ItemStackUtils.getFromItem(item); - } - - @Override - public void load() { - this.vanilla_loot = new LootImpl( - "vanilla", - "vanilla", - null, - 0, - false, - 0, - false, - false - ); - this.loadItems(); - this.loadMobs(); - this.loadCategories(); - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + (this.lavaLoots.size() + this.waterLoots.size()) + " loot(s)"); - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + (this.category.size()) + " category(s)"); - } - - @Override - public void unload() { - this.waterLoots.clear(); - this.lavaLoots.clear(); - this.lootItems.clear(); - this.category.clear(); - this.vanilla_loot = null; - } - - @Nullable - public LootImpl getLoot(String key) { - LootImpl loot = this.waterLoots.get(key); - if (loot == null) { - loot = this.lavaLoots.get(key); - } - return loot; - } - - public boolean hasLoot(String key) { - boolean has = this.waterLoots.containsKey(key); - if (!has) { - has = this.lavaLoots.containsKey(key); - } - return has; - } - - private void loadCategories() { - File category_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "categories"); - if (!category_file.exists()) { - if (!category_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "categories" + File.separator + "default.yml", false); - } - File[] files = category_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (String key : config.getKeys(false)) { - List fishIDs = config.getStringList(key); - for (String id : fishIDs) { - if (!waterLoots.containsKey(id) && !lavaLoots.containsKey(id)) { - AdventureUtils.consoleMessage("[CustomFishing] Loot ID " + id + " doesn't exist in category " + key); - } - } - category.put(key, fishIDs); - } - } - } - - private void loadMobs() { - if (Bukkit.getPluginManager().getPlugin("MythicMobs") == null) return; - File mob_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "mobs"); - if (!mob_file.exists()) { - if (!mob_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "mobs" + File.separator + "default.yml", false); - } - File[] files = mob_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - Set keys = config.getKeys(false); - for (String key : keys) { - ConfigurationSection mobSection = config.getConfigurationSection(key); - if (mobSection == null) continue; - if (!mobSection.getBoolean("enable", true)) continue; - Mob loot = new Mob( - key, - mobSection.contains("nick") ? mobSection.getString("nick") : AdventureUtils.replaceLegacy(mobSection.getString("mobID", key)), - getMiniGames(mobSection), - mobSection.getInt("weight",10), - mobSection.getBoolean("show-in-fishfinder", true), - mobSection.getDouble("score",10d), - mobSection.getString("mobID", key), - mobSection.getInt("level", 0), - new MobVector( - mobSection.getDouble("vector.horizontal",1.1), - mobSection.getDouble("vector.vertical",1.3) - ), - mobSection.getBoolean("disable-bar-mechanic", false), - mobSection.getBoolean("disable-stats", false) - ); - if (mobSection.contains("group")) loot.setGroup(mobSection.getString("group")); - setActions(mobSection, loot); - loot.setRequirements(ConfigUtils.getRequirements(mobSection.getConfigurationSection("requirements"))); - - if (mobSection.getBoolean("in-lava", false)) lavaLoots.put(key, loot); - else waterLoots.put(key, loot); - } - } - } - - private void loadItems() { - File loot_file = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "loots"); - if (!loot_file.exists()) { - if (!loot_file.mkdir()) return; - plugin.saveResource("contents" + File.separator + "loots" + File.separator + "default.yml", false); - plugin.saveResource("contents" + File.separator + "loots" + File.separator + "example.yml", false); - } - File[] files = loot_file.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".yml")) continue; - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - Set keys = config.getKeys(false); - for (String key : keys) { - ConfigurationSection lootSection = config.getConfigurationSection(key); - if (lootSection == null) continue; - if (!lootSection.getBoolean("enable", true)) continue; - String material = lootSection.getString("material","COD"); - DroppedItem loot = new DroppedItem( - key, - lootSection.contains("nick") ? lootSection.getString("nick") : AdventureUtils.replaceLegacy(lootSection.getString("display.name", key)), - material.contains(":") ? material : key, - getMiniGames(lootSection), - lootSection.getInt("weight",10), - lootSection.getBoolean("show-in-fishfinder", true), - lootSection.getDouble("score"), - lootSection.getBoolean("random-durability", false), - lootSection.getBoolean("disable-bar-mechanic", false), - lootSection.getBoolean("disable-stats", false) - ); - if (lootSection.contains("group")) loot.setGroup(lootSection.getString("group")); - if (lootSection.contains("size")) { - String[] size = lootSection.getString("size", "1~10").split("~"); - if (size.length != 2) { - AdventureUtils.consoleMessage("[CustomFishing] Wrong size found at " + key); - continue; - } - loot.setSize(size); - } - if (lootSection.contains("price")) { - loot.setBasicPrice((float) lootSection.getDouble("price.base", 0)); - loot.setSizeBonus((float) lootSection.getDouble("price.bonus", 0)); - } - if (lootSection.contains("random-enchantments")) { - List randomEnchants = new ArrayList<>(); - ConfigurationSection enchantSection = lootSection.getConfigurationSection("random-enchantments"); - if (enchantSection != null) { - for (Map.Entry entry : enchantSection.getValues(false).entrySet()) { - if (entry.getValue() instanceof MemorySection memorySection){ - LeveledEnchantment enchantment = new LeveledEnchantment( - NamespacedKey.fromString(memorySection.getString("enchant", "minecraft:sharpness")), - memorySection.getInt("level"), - memorySection.getDouble("chance") - ); - randomEnchants.add(enchantment); - } - } - } - loot.setRandomEnchants(randomEnchants.toArray(new LeveledEnchantment[0])); - } - - setActions(lootSection, loot); - loot.setRequirements(ConfigUtils.getRequirements(lootSection.getConfigurationSection("requirements"))); - if (key.equals("vanilla")) { - vanilla_loot = loot; - continue; - } - if (lootSection.getBoolean("in-lava", false)) lavaLoots.put(key, loot); - else waterLoots.put(key, loot); - //not a CustomFishing loot - if (material.contains(":")) continue; - Item item = new Item(lootSection, key); - if (ConfigManager.addTagToFish) item.setCfTag(new String[] {"loot", key}); - lootItems.put(key, item); - } - } - } - - private void setActions(ConfigurationSection section, LootImpl loot) { - loot.setSuccessActions(ConfigUtils.getActions(section.getConfigurationSection("action.success"), loot.getNick())); - loot.setFailureActions(ConfigUtils.getActions(section.getConfigurationSection("action.failure"), loot.getNick())); - loot.setHookActions(ConfigUtils.getActions(section.getConfigurationSection("action.hook"), loot.getNick())); - loot.setConsumeActions(ConfigUtils.getActions(section.getConfigurationSection("action.consume"), loot.getNick())); - setSuccessAmountAction(section.getConfigurationSection("action.success-times"), loot); - } - - private void setSuccessAmountAction(ConfigurationSection section, LootImpl loot) { - if (section != null) { - HashMap actionMap = new HashMap<>(); - for (String amount : section.getKeys(false)) { - actionMap.put(Integer.parseInt(amount), ConfigUtils.getActions(section.getConfigurationSection(amount), loot.getNick())); - } - loot.setSuccessTimesActions(actionMap); - } - } - - private MiniGameConfig[] getMiniGames(ConfigurationSection section) { - String[] games = section.getStringList("mini-game").size() == 0 ? new String[]{section.getString("mini-game", null)} : section.getStringList("mini-game").toArray(new String[0]); - MiniGameConfig[] gameConfigs = new MiniGameConfig[games.length]; - for (int i = 0, size = games.length; i < size; i++) { - if (games[i] == null) { - return null; - } - MiniGameConfig gameConfig = plugin.getBarMechanicManager().getGameConfig(games[i]); - if (gameConfig == null) { - AdventureUtils.consoleMessage("[CustomFishing] Mini game " + games[i] + " doesn't exist"); - return null; - } - gameConfigs[i] = gameConfig; - } - return gameConfigs; - } - - public HashMap getWaterLoots() { - return waterLoots; - } - - public HashMap getLavaLoots() { - return lavaLoots; - } - - public ArrayList getAllLoots() { - ArrayList loots = new ArrayList<>(waterLoots.values()); - loots.addAll(getLavaLoots().values()); - return loots; - } - - public ArrayList getAllKeys() { - ArrayList loots = new ArrayList<>(); - for (Map.Entry en : waterLoots.entrySet()) { - if (en.getValue() instanceof DroppedItem) { - loots.add(en.getKey()); - } - } - for (Map.Entry en : lavaLoots.entrySet()) { - if (en.getValue() instanceof DroppedItem) { - loots.add(en.getKey()); - } - } - return loots; - } - - @Nullable - public List getCategories(String categoryID) { - return category.get(categoryID); - } - - @NotNull - public LootImpl getVanilla_loot() { - return vanilla_loot; - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/MessageManager.java b/src/main/java/net/momirealms/customfishing/manager/MessageManager.java deleted file mode 100644 index 4b5ff957..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/MessageManager.java +++ /dev/null @@ -1,118 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.util.ConfigUtils; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.io.IOException; - -public class MessageManager { - - public static String prefix; - public static String reload; - public static String nonArgs; - public static String unavailableArgs; - public static String escape; - public static String noPerm; - public static String itemNotExist; - public static String playerNotExist; - public static String noConsole; - public static String wrongAmount; - public static String lackArgs; - public static String notOnline; - public static String giveItem; - public static String getItem; - public static String possibleLoots; - public static String splitChar; - public static String noLoot; - public static String notEnoughPlayers; - public static String noRank; - public static String forceSuccess; - public static String forceFailure; - public static String forceEnd; - public static String forceCancel; - public static String noPlayer; - public static String noScore; - public static String noRod; - public static String hookOther; - public static String reachSellLimit; - public static String setStatistics; - public static String resetStatistics; - public static String negativeStatistics; - public static String statisticsNotExists; - public static String TOTAL_SCORE; - public static String CATCH_AMOUNT; - public static String MAX_SIZE; - public static String TOTAL_SIZE; - - public static void load() { - YamlConfiguration config = ConfigUtils.getConfig("messages" + File.separator + "messages_" + ConfigManager.lang +".yml"); - prefix = getOrSet(config, "prefix", "[CustomFishing] "); - reload = getOrSet(config, "reload", "Reloaded. Took {time}ms."); - nonArgs = getOrSet(config, "none-args", "Arguments cannot be none."); - unavailableArgs = getOrSet(config, "invalid-args", "Invalid arguments."); - escape = getOrSet(config, "escape", "It has been too long since the fish is hooked. Oh my god, it escaped."); - noPerm = getOrSet(config, "no-perm", "You don''t have permission."); - itemNotExist = getOrSet(config, "item-not-exist", "That item does not exist."); - playerNotExist = getOrSet(config, "player-not-exist", "That player does not exist."); - noConsole = getOrSet(config, "no-console", "This command cannot be executed from the console."); - wrongAmount = getOrSet(config, "wrong-amount", "You can''t set an negative amount of items."); - lackArgs = getOrSet(config, "lack-args", "Insufficient arguments."); - notOnline = getOrSet(config, "not-online", "That player is not online."); - giveItem = getOrSet(config, "give-item", "Successfully given player {Player} {Amount}x {Item}."); - getItem = getOrSet(config, "get-item", "Successfully got {Amount}x {Item}."); - possibleLoots = getOrSet(config, "possible-loots", "Possible loots here: "); - splitChar = getOrSet(config, "split-char", ", "); - noLoot = getOrSet(config, "no-loot", "There''s no fish in this place."); - notEnoughPlayers = getOrSet(config, "players-not-enough", "The number of players is not enough for the fishing competition to be started as scheduled."); - noRank = getOrSet(config, "no-rank", "No Rank"); - forceSuccess = getOrSet(config, "force-competition-success", "Forced to start a fishing competition."); - forceFailure = getOrSet(config, "force-competition-failure", "The competition does not exist."); - forceEnd = getOrSet(config, "force-competition-end", "Forced to end the current competition."); - forceCancel = getOrSet(config, "force-competition-cancel", "Forced to cancel the competition"); - noPlayer = getOrSet(config, "no-player", "No player"); - noScore = getOrSet(config, "no-score", "No score"); - noRod = getOrSet(config, "no-rod", "You have to fish with a special rod to get loots."); - hookOther = getOrSet(config, "hook-other-entity", "The hook is hooked on another entity."); - reachSellLimit = getOrSet(config, "reach-sell-limit", "You have earned too much from selling fish! Come tomorrow."); - setStatistics = getOrSet(config, "set-statistics", "Successfully set {Player}''s {Loot} statistics to {Amount}."); - resetStatistics = getOrSet(config, "reset-statistics", "Successfully reset {Player}''s statistics."); - negativeStatistics = getOrSet(config, "negative-statistics", "Amount should be a value no lower than zero."); - statisticsNotExists = getOrSet(config, "statistics-not-exist", "The statistics does not exist."); - TOTAL_SCORE = getOrSet(config, "total_score", "Total score"); - CATCH_AMOUNT = getOrSet(config, "catch_amount", "Catch amount"); - MAX_SIZE = getOrSet(config, "max_size", "Max size"); - TOTAL_SIZE = getOrSet(config, "total_size", "Total size"); - try { - config.save(new File(CustomFishing.getInstance().getDataFolder(), "messages" + File.separator + "messages_" + ConfigManager.lang +".yml")); - } catch (IOException ignore) { - } - } - - private static String getOrSet(ConfigurationSection section, String path, String defaultValue) { - path = "messages." + path; - if (!section.contains(path)) { - section.set(path, defaultValue); - } - return section.getString(path); - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/OffsetManager.java b/src/main/java/net/momirealms/customfishing/manager/OffsetManager.java deleted file mode 100644 index 47bf75a2..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/OffsetManager.java +++ /dev/null @@ -1,135 +0,0 @@ -package net.momirealms.customfishing.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.ConfigUtils; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; - -public class OffsetManager extends Function { - - private CustomFishing plugin; - private final String[] negative; - private final String[] positive; - private String font; - - public OffsetManager(CustomFishing plugin) { - this.plugin = plugin; - this.negative = new String[8]; - this.positive = new String[8]; - } - - @Override - public void load() { - loadConfig(); - } - - public String getFont() { - return font; - } - - private void loadConfig() { - YamlConfiguration config = ConfigUtils.getConfig("config.yml"); - ConfigurationSection section = config.getConfigurationSection("other-settings.offset-characters"); - if (section != null) { - font = section.getString("font", "customfishing:offset_chars"); - positive[0] = section.getString("1"); - positive[1] = section.getString("2"); - positive[2] = section.getString("4"); - positive[3] = section.getString("8"); - positive[4] = section.getString("16"); - positive[5] = section.getString("32"); - positive[6] = section.getString("64"); - positive[7] = section.getString("128"); - negative[0] = section.getString("-1"); - negative[1] = section.getString("-2"); - negative[2] = section.getString("-4"); - negative[3] = section.getString("-8"); - negative[4] = section.getString("-16"); - negative[5] = section.getString("-32"); - negative[6] = section.getString("-64"); - negative[7] = section.getString("-128"); - } - } - - public String getShortestNegChars(int n) { - StringBuilder stringBuilder = new StringBuilder(); - while (n >= 128) { - stringBuilder.append(negative[7]); - n -= 128; - } - if (n - 64 >= 0) { - stringBuilder.append(negative[6]); - n -= 64; - } - if (n - 32 >= 0) { - stringBuilder.append(negative[5]); - n -= 32; - } - if (n - 16 >= 0) { - stringBuilder.append(negative[4]); - n -= 16; - } - if (n - 8 >= 0) { - stringBuilder.append(negative[3]); - n -= 8; - } - if (n - 4 >= 0) { - stringBuilder.append(negative[2]); - n -= 4; - } - if (n - 2 >= 0) { - stringBuilder.append(negative[1]); - n -= 2; - } - if (n - 1 >= 0) { - stringBuilder.append(negative[0]); - } - return stringBuilder.toString(); - } - - public String getShortestPosChars(int n) { - StringBuilder stringBuilder = new StringBuilder(); - while (n >= 128) { - stringBuilder.append(positive[7]); - n -= 128; - } - if (n - 64 >= 0) { - stringBuilder.append(positive[6]); - n -= 64; - } - if (n - 32 >= 0) { - stringBuilder.append(positive[5]); - n -= 32; - } - if (n - 16 >= 0) { - stringBuilder.append(positive[4]); - n -= 16; - } - if (n - 8 >= 0) { - stringBuilder.append(positive[3]); - n -= 8; - } - if (n - 4 >= 0) { - stringBuilder.append(positive[2]); - n -= 4; - } - if (n - 2 >= 0) { - stringBuilder.append(positive[1]); - n -= 2; - } - if (n - 1 >= 0) { - stringBuilder.append(positive[0]); - } - return stringBuilder.toString(); - } - - public String getOffsetChars(int n) { - if (n > 0) { - return getShortestPosChars(n); - } - else { - return getShortestNegChars(-n); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/SellManager.java b/src/main/java/net/momirealms/customfishing/manager/SellManager.java deleted file mode 100644 index 70e45873..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/SellManager.java +++ /dev/null @@ -1,498 +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.manager; - -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.CustomFishing; -import net.momirealms.customfishing.api.event.SellFishEvent; -import net.momirealms.customfishing.data.PlayerSellData; -import net.momirealms.customfishing.fishing.loot.Item; -import net.momirealms.customfishing.listener.InventoryListener; -import net.momirealms.customfishing.listener.JoinQuitListener; -import net.momirealms.customfishing.listener.WindowPacketListener; -import net.momirealms.customfishing.object.InventoryFunction; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ConfigUtils; -import net.momirealms.customfishing.util.InventoryUtils; -import net.momirealms.customfishing.util.ItemStackUtils; -import net.objecthunter.exp4j.Expression; -import net.objecthunter.exp4j.ExpressionBuilder; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.jetbrains.annotations.NotNull; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -public class SellManager extends InventoryFunction { - - private final WindowPacketListener windowPacketListener; - private final InventoryListener inventoryListener; - private final JoinQuitListener joinQuitListener; - private final CustomFishing plugin; - private String formula; - private String title; - private int guiSize; - private String msgNotification; - private String actionbarNotification; - private String titleNotification; - private String subtitleNotification; - private int titleIn; - private int titleStay; - private int titleOut; - private String[] commands; - private Item sellIcon; - private Item denyIcon; - private Key closeKey; - private Key openKey; - private Key successKey; - private Key denyKey; - private Sound.Source soundSource; - private HashMap guiItems; - private HashSet functionIconSlots; - private HashMap customItemPrices = new HashMap<>(); - private boolean sellLimitation; - private int upperLimit; - private final ConcurrentHashMap sellDataMap; - - public SellManager(CustomFishing plugin) { - super(); - this.plugin = plugin; - this.windowPacketListener = new WindowPacketListener(this); - this.inventoryListener = new InventoryListener(this); - this.joinQuitListener = new JoinQuitListener(this); - this.sellDataMap = new ConcurrentHashMap<>(); - } - - @Override - public void load() { - functionIconSlots = new HashSet<>(); - guiItems = new HashMap<>(); - customItemPrices = new HashMap<>(); - loadConfig(); - CustomFishing.getProtocolManager().addPacketListener(windowPacketListener); - Bukkit.getPluginManager().registerEvents(inventoryListener, plugin); - Bukkit.getPluginManager().registerEvents(joinQuitListener, plugin); - } - - @Override - public void unload() { - CustomFishing.getProtocolManager().removePacketListener(windowPacketListener); - HandlerList.unregisterAll(inventoryListener); - HandlerList.unregisterAll(joinQuitListener); - msgNotification = null; - actionbarNotification = null; - commands = null; - titleNotification = null; - } - - @Override - public void disable() { - unload(); - plugin.getDataManager().getDataStorageInterface().saveSellData(sellDataMap.entrySet(), true); - sellDataMap.clear(); - } - - @Override - public void onQuit(Player player) { - UUID uuid = player.getUniqueId(); - PlayerSellData sellData = sellDataMap.remove(uuid); - if (sellData == null) return; - plugin.getScheduler().runTaskAsync(() -> plugin.getDataManager().getDataStorageInterface().saveSellData(uuid, sellData, true)); - } - - @Override - public void onJoin(Player player) { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, false), 1, TimeUnit.SECONDS); - } - - public void joinReadData(Player player, boolean force) { - if (player == null || !player.isOnline()) return; - PlayerSellData sellData = plugin.getDataManager().getDataStorageInterface().loadSellData(player.getUniqueId(), force); - if (sellData != null) { - sellDataMap.put(player.getUniqueId(), sellData); - } else if (!force) { - if (checkTriedTimes(player.getUniqueId())) { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, false), 2500, TimeUnit.MILLISECONDS); - } else { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, true), 2500, TimeUnit.MILLISECONDS); - } - } - } - - private void loadConfig() { - YamlConfiguration config = ConfigUtils.getConfig("sell-fish.yml"); - formula = config.getString("price-formula", "{base} + {bonus} * {size}"); - sellLimitation = config.getBoolean("sell-limitation.enable", false); - upperLimit = config.getInt("sell-limitation.upper-limit", 10000); - title = config.getString("container-title"); - guiSize = config.getInt("rows") * 9; - setSounds(config); - setActions(config); - setIcons(config); - ConfigurationSection configurationSection = config.getConfigurationSection("item-price"); - if (configurationSection == null) { - configurationSection = config.getConfigurationSection("vanilla-item-price"); - } - if (configurationSection != null) { - for (String vanilla : configurationSection.getKeys(false)) { - customItemPrices.put(vanilla.toUpperCase(Locale.ENGLISH), (float) configurationSection.getDouble(vanilla)); - } - } - } - - @SuppressWarnings("all") - private void setSounds(ConfigurationSection config) { - openKey = config.contains("sounds.open") ? Key.key(config.getString("sounds.open")) : null; - closeKey = config.contains("sounds.close") ? Key.key(config.getString("sounds.close")) : null; - successKey = config.contains("sounds.success") ? Key.key(config.getString("sounds.success")) : null; - denyKey = config.contains("sounds.deny") ? Key.key(config.getString("sounds.deny")) : null; - soundSource = Sound.Source.valueOf(config.getString("sounds.type","player").toUpperCase(Locale.ENGLISH)); - } - - private void setActions(ConfigurationSection config) { - if (config.getBoolean("actions.message.enable", false)) { - msgNotification = config.getString("actions.message.text"); - } - if (config.getBoolean("actions.actionbar.enable", false)) { - actionbarNotification = config.getString("actions.actionbar.text"); - } - if (config.getBoolean("actions.title.enable", false)) { - titleNotification = config.getString("actions.title.title"); - subtitleNotification = config.getString("actions.title.subtitle"); - titleIn = config.getInt("actions.title.in"); - titleStay = config.getInt("actions.title.stay"); - titleOut = config.getInt("actions.title.out"); - } - if (config.getBoolean("actions.commands.enable")) { - commands = config.getStringList("actions.commands.value").toArray(new String[0]); - } - } - - private void setIcons(ConfigurationSection config) { - if (config.contains("decorative-icons")){ - ConfigurationSection dec_section = config.getConfigurationSection("decorative-icons"); - if (dec_section != null) { - for (String key : dec_section.getKeys(false)) { - ConfigurationSection item_section = dec_section.getConfigurationSection(key); - if (item_section == null) continue; - Item item = new Item(item_section, key); - ItemStack itemStack = ItemStackUtils.getFromItem(item); - if (item_section.contains("slots")) { - for (int slot : item_section.getIntegerList("slots")) { - guiItems.put(slot - 1, itemStack); - } - } - } - } - } - ConfigurationSection sellIconSection = config.getConfigurationSection("functional-icons.sell"); - if (sellIconSection != null) { - sellIcon = new Item(sellIconSection, "sellIcon"); - } else { - AdventureUtils.consoleMessage("[CustomFishing] Sell icon is missing"); - } - ConfigurationSection denyIconSection = config.getConfigurationSection("functional-icons.deny"); - if (denyIconSection != null) { - denyIcon = new Item(denyIconSection, "denyIcon"); - } else { - AdventureUtils.consoleMessage("[CustomFishing] Deny icon is missing"); - } - for (int slot : config.getIntegerList("functional-icons.slots")) { - guiItems.put(slot - 1, ItemStackUtils.getFromItem(sellIcon)); - functionIconSlots.add(slot - 1); - } - } - - public void openGuiForPlayer(Player player) { - player.closeInventory(); - if (!sellDataMap.containsKey(player.getUniqueId())) { - AdventureUtils.consoleMessage("Sell cache is not loaded for player " + player.getName()); - return; - } - SellGUI sellGUI = new SellGUI(player); - sellGUI.open(); - } - - @Override - public void onClickInventory(InventoryClickEvent event) { - final Player player = (Player) event.getView().getPlayer(); - Inventory inventory = event.getInventory(); - if (!(inventory.getHolder() instanceof SellGUI)) return; - Inventory clickedInventory = event.getClickedInventory(); - if (clickedInventory == null) return; - if (clickedInventory == player.getInventory()) { - if (event.isShiftClick()) { - event.setCancelled(true); - int empty_slot = getEmptySlot(inventory); - if (empty_slot == -1) return; - ItemStack clicked = event.getCurrentItem(); - if (clicked == null || clicked.getType() == Material.AIR) return; - inventory.setItem(empty_slot, clicked.clone()); - clicked.setAmount(0); - } - } else { - int clickedSlot = event.getSlot(); - if (guiItems.containsKey(clickedSlot)) { - event.setCancelled(true); - } - if (functionIconSlots.contains(clickedSlot)) { - List playerItems = getPlayerItems(inventory); - float totalPrice = getTotalPrice(playerItems); - if (totalPrice > 0) { - PlayerSellData sellData = sellDataMap.get(player.getUniqueId()); - - if (sellData == null) { - inventory.close(); - AdventureUtils.playerMessage(player, MessageManager.prefix + "Your data is not loaded! Try to rejoin the server"); - AdventureUtils.consoleMessage("[CustomFishing] Unexpected issue, " + player.getName() + "'s sell-cache is not loaded!"); - if (denyKey != null) AdventureUtils.playerSound(player, soundSource, denyKey, 1, 1); - return; - } - - Calendar calendar = Calendar.getInstance(); - int currentDate = (calendar.get(Calendar.MONTH) + 1) * 100 + calendar.get(Calendar.DATE); - if (currentDate != sellData.getDate()) { - sellData.setDate(currentDate); - sellData.setMoney(0); - } - - double sell = sellData.getMoney(); - - if (sellLimitation && sell + totalPrice > upperLimit) { - inventory.close(); - AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.reachSellLimit); - if (denyKey != null) AdventureUtils.playerSound(player, soundSource, denyKey, 1, 1); - return; - } - - SellFishEvent sellFishEvent = new SellFishEvent(player, totalPrice); - Bukkit.getPluginManager().callEvent(sellFishEvent); - if (sellFishEvent.isCancelled()) { - return; - } - - for (ItemStack playerItem : playerItems) { - if (playerItem == null || playerItem.getType() == Material.AIR) continue; - if (getSingleItemPrice(playerItem) == 0) continue; - playerItem.setAmount(0); - } - - sellData.setMoney(sellFishEvent.getMoney() + sell); - doActions(player, sellFishEvent.getMoney(), upperLimit - sell - sellFishEvent.getMoney()); - inventory.close(); - } else { - for (int slot : functionIconSlots) { - inventory.setItem(slot, ItemStackUtils.getFromItem(denyIcon)); - } - if (denyKey != null) AdventureUtils.playerSound(player, soundSource, denyKey, 1, 1); - } - } - } - - plugin.getScheduler().runTaskAsyncLater(() -> { - ItemStack icon = ItemStackUtils.getFromItem(sellIcon.cloneWithPrice(getTotalPrice(getPlayerItems(inventory)))); - for (int slot : functionIconSlots) { - inventory.setItem(slot, icon); - } - }, 25, TimeUnit.MILLISECONDS); - } - - @Override - public void onDragInventory(InventoryDragEvent event) { - Inventory inventory = event.getInventory(); - if (!(inventory.getHolder() instanceof SellGUI)) return; - for (int i : event.getRawSlots()) { - if (guiItems.containsKey(i)) { - event.setCancelled(true); - return; - } - } - plugin.getScheduler().runTaskAsync(() -> { - ItemStack icon = ItemStackUtils.getFromItem(sellIcon.cloneWithPrice(getTotalPrice(getPlayerItems(inventory)))); - for (int slot : functionIconSlots) { - inventory.setItem(slot, icon); - } - }); - } - - @Override - public void onCloseInventory(InventoryCloseEvent event) { - final Player player = (Player) event.getPlayer(); - Inventory inventory = event.getInventory(); - if (!(inventory.getHolder() instanceof SellGUI)) return; - returnItems(getPlayerItems(inventory), player); - if (closeKey != null) AdventureUtils.playerSound(player, soundSource, closeKey, 1, 1); - } - - private List getPlayerItems(Inventory inventory) { - List items = new ArrayList<>(); - for (int i = 0; i < guiSize; i++) { - if (guiItems.containsKey(i)) continue; - items.add(inventory.getItem(i)); - } - return items; - } - - private int getEmptySlot(Inventory inventory) { - for (int i = 0; i < guiSize; i++) { - if (guiItems.containsKey(i)) continue; - ItemStack item = inventory.getItem(i); - if (item == null || item.getType() == Material.AIR) { - return i; - } - } - return -1; - } - - private void returnItems(List itemStacks, Player player){ - PlayerInventory inventory = player.getInventory(); - for (ItemStack stack : itemStacks) { - if (stack == null || stack.getType() == Material.AIR) continue; - if (hasEmptySlot(inventory)) inventory.addItem(stack); - else player.getLocation().getWorld().dropItemNaturally(player.getLocation(), stack); - } - } - - private boolean hasEmptySlot(PlayerInventory inventory) { - for (ItemStack itemStack : inventory.getStorageContents()) { - if (itemStack == null || itemStack.getType() == Material.AIR) return true; - } - return false; - } - - private float getTotalPrice(List itemStacks){ - float totalPrice = 0; - for (ItemStack stack : itemStacks) { - if (stack == null || stack.getType() == Material.AIR) continue; - float price = getSingleItemPrice(stack); - price *= stack.getAmount(); - totalPrice += price; - } - return totalPrice; - } - - public float getCFFishPrice(NBTItem cfFish) { - NBTCompound fishMeta = cfFish.getCompound("FishMeta"); - if (fishMeta != null) { - float base = fishMeta.getFloat("base"); - float bonus = fishMeta.getFloat("bonus"); - float size = fishMeta.getFloat("size"); - Expression expression = new ExpressionBuilder(formula) - .variables("base", "bonus","size") - .build() - .setVariable("base", base) - .setVariable("bonus", bonus) - .setVariable("size", size); - return (float) expression.evaluate(); - } - return 0; - } - - public float getSingleItemPrice(ItemStack itemStack) { - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound fishMeta = nbtItem.getCompound("FishMeta"); - float price = 0; - if (fishMeta != null) { - float base = fishMeta.getFloat("base"); - float bonus = fishMeta.getFloat("bonus"); - float size = fishMeta.getFloat("size"); - Expression expression = new ExpressionBuilder(formula) - .variables("base", "bonus","size") - .build() - .setVariable("base", base) - .setVariable("bonus", bonus) - .setVariable("size", size); - price = (float) expression.evaluate(); - } - Double money = Optional.ofNullable(nbtItem.getDouble("Price")).orElse(0d); - price += money; - if (price == 0) { - String type = itemStack.getType().name(); - if (nbtItem.hasTag("CustomModelData")) type = type + ":" + nbtItem.getInteger("CustomModelData"); - price = Optional.ofNullable(customItemPrices.get(type)).orElse(0f); - } - return price; - } - - private void doActions(Player player, float earnings, double remains) { - if (titleNotification != null) AdventureUtils.playerTitle(player, titleNotification.replace("{money}", String.format("%.2f", earnings)).replace("{remains}", sellLimitation ? String.format("%.2f", remains) : "unlimited"), subtitleNotification.replace("{money}", String.format("%.2f", earnings)).replace("{remains}", sellLimitation ? String.format("%.2f", remains) : "unlimited"), titleIn * 50, titleStay * 50, titleOut * 50); - if (msgNotification != null) AdventureUtils.playerMessage(player, msgNotification.replace("{money}", String.format("%.2f", earnings)).replace("{remains}", sellLimitation ? String.format("%.2f", remains) : "unlimited")); - if (actionbarNotification != null) AdventureUtils.playerActionbar(player, actionbarNotification.replace("{money}", String.format("%.2f", earnings)).replace("{remains}", sellLimitation ? String.format("%.2f", remains) : "unlimited")); - if (ConfigManager.logEarning) AdventureUtils.consoleMessage("[CustomFishing] Log: " + player.getName() + " earns " + String.format("%.2f", earnings) + " from selling fish"); - if (successKey != null) AdventureUtils.playerSound(player, soundSource, successKey, 1, 1); - if (plugin.getIntegrationManager().getVaultHook() != null) plugin.getIntegrationManager().getVaultHook().getEconomy().depositPlayer(player, earnings); - if (commands != null) - for (String cmd : commands) - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), cmd.replace("{player}", player.getName()).replace("{money}", String.format("%.2f", earnings)).replace("{remains}", sellLimitation ? String.format("%.2f", remains) : "unlimited")); - } - - public double getTodayEarning(Player player) { - PlayerSellData playerSellData = sellDataMap.get(player.getUniqueId()); - if (playerSellData == null) return 0d; - Calendar calendar = Calendar.getInstance(); - int currentDate = (calendar.get(Calendar.MONTH) + 1) * 100 + calendar.get(Calendar.DATE); - if (currentDate != playerSellData.getDate()) { - playerSellData.setDate(currentDate); - playerSellData.setMoney(0); - } - return playerSellData.getMoney(); - } - - public class SellGUI implements InventoryHolder { - - private final Inventory inventory; - private final Player player; - - @Override - public @NotNull Inventory getInventory() { - return inventory; - } - - public SellGUI(Player player) { - this.player = player; - this.inventory = InventoryUtils.createInventory(this, guiSize, plugin.getIntegrationManager().getPlaceholderManager().parse(player, title)); - } - - public void open() { - for (Map.Entry entry : guiItems.entrySet()) { - inventory.setItem(entry.getKey(), entry.getValue()); - } - for (int slot : functionIconSlots) { - inventory.setItem(slot, ItemStackUtils.getFromItem(sellIcon.cloneWithPrice(getTotalPrice(getPlayerItems(inventory))))); - } - if (openKey != null) AdventureUtils.playerSound(player, soundSource, openKey, 1, 1); - player.openInventory(inventory); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/StatisticsManager.java b/src/main/java/net/momirealms/customfishing/manager/StatisticsManager.java deleted file mode 100644 index 2e654676..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/StatisticsManager.java +++ /dev/null @@ -1,159 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.data.PlayerStatisticsData; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import net.momirealms.customfishing.listener.JoinQuitListener; -import net.momirealms.customfishing.object.DataFunction; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; - -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -public class StatisticsManager extends DataFunction { - - private final ConcurrentHashMap statisticsDataMap; - private final JoinQuitListener joinQuitListener; - private final CustomFishing plugin; - - public StatisticsManager(CustomFishing plugin) { - super(); - this.statisticsDataMap = new ConcurrentHashMap<>(); - this.joinQuitListener = new JoinQuitListener(this); - this.plugin = plugin; - } - - @Override - public void load() { - if (!ConfigManager.enableStatistics) return; - Bukkit.getPluginManager().registerEvents(joinQuitListener, plugin); - } - - @Override - public void unload() { - HandlerList.unregisterAll(joinQuitListener); - } - - public void saveStatisticsDataForOnlinePlayers(boolean unlock) { - plugin.getDataManager().getDataStorageInterface().saveStatistics(statisticsDataMap.entrySet(), unlock); - } - - @Override - public void disable() { - unload(); - saveStatisticsDataForOnlinePlayers(true); - statisticsDataMap.clear(); - } - - @Override - public void onQuit(Player player) { - UUID uuid = player.getUniqueId(); - PlayerStatisticsData playerStatisticsData = statisticsDataMap.remove(uuid); - triedTimes.remove(player.getUniqueId()); - if (playerStatisticsData != null) { - plugin.getScheduler().runTaskAsync(() -> plugin.getDataManager().getDataStorageInterface().saveStatistics(uuid, playerStatisticsData, true)); - } - } - - @Override - public void onJoin(Player player) { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, false), 500, TimeUnit.MILLISECONDS); - } - - public void joinReadData(Player player, boolean force) { - if (player == null || !player.isOnline()) return; - PlayerStatisticsData statisticsData = plugin.getDataManager().getDataStorageInterface().loadStatistics(player.getUniqueId(), force); - if (statisticsData != null) { - statisticsDataMap.put(player.getUniqueId(), statisticsData); - } else if (!force) { - if (checkTriedTimes(player.getUniqueId())) { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, false), 2500, TimeUnit.MILLISECONDS); - } else { - plugin.getScheduler().runTaskAsyncLater(() -> joinReadData(player, true), 2500, TimeUnit.MILLISECONDS); - } - } - } - - public void addFishAmount(UUID uuid, LootImpl loot, int amount) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - statisticsData.addFishAmount(loot, uuid, amount); - } - } - - public int getFishAmount(UUID uuid, String key) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - return statisticsData.getFishAmount(key); - } - return -1; - } - - public int getTotalFishAmount(UUID uuid) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - return statisticsData.getTotalCatchAmount(); - } - return -1; - } - - public boolean hasFished(UUID uuid, String key) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - return statisticsData.hasFished(key); - } - return false; - } - - public double getCategoryUnlockProgress(UUID uuid, String category) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - return statisticsData.getCategoryUnlockProgress(category); - } - return -1d; - } - - public int getCategoryTotalFishAmount(UUID uuid, String category) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - return statisticsData.getCategoryTotalFishAmount(category); - } - return -1; - } - - public boolean reset(UUID uuid) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - statisticsData.reset(); - return true; - } - return false; - } - - public void setData(UUID uuid, String key, int amount) { - PlayerStatisticsData statisticsData = statisticsDataMap.get(uuid); - if (statisticsData != null) { - statisticsData.setData(key, amount); - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/manager/TotemManager.java b/src/main/java/net/momirealms/customfishing/manager/TotemManager.java deleted file mode 100644 index 9dd60ff7..00000000 --- a/src/main/java/net/momirealms/customfishing/manager/TotemManager.java +++ /dev/null @@ -1,689 +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.manager; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.action.Action; -import net.momirealms.customfishing.fishing.action.CommandActionImpl; -import net.momirealms.customfishing.fishing.action.MessageActionImpl; -import net.momirealms.customfishing.fishing.totem.CorePos; -import net.momirealms.customfishing.fishing.totem.FinalModel; -import net.momirealms.customfishing.fishing.totem.OriginalModel; -import net.momirealms.customfishing.fishing.totem.TotemConfig; -import net.momirealms.customfishing.integration.BlockInterface; -import net.momirealms.customfishing.object.Function; -import net.momirealms.customfishing.util.AdventureUtils; -import net.momirealms.customfishing.util.ConfigUtils; -import net.momirealms.customfishing.util.LocationUtils; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.*; - -public class TotemManager extends Function { - - private final CustomFishing plugin; - - private final HashMap totems; - private final HashMap> cores; - private final HashMap blockIDs; - private final HashMap invertedIDs; - - public TotemManager(CustomFishing plugin) { - this.plugin = plugin; - totems = new HashMap<>(); - cores = new HashMap<>(); - blockIDs = new HashMap<>(); - invertedIDs = new HashMap<>(); - } - - @Override - public void unload() { - totems.clear(); - cores.clear(); - blockIDs.clear(); - invertedIDs.clear(); - } - - @Override - public void load(){ - loadBlocks(); - loadTotems(); - } - - @Nullable - public TotemConfig getTotem(String key) { - return totems.get(key); - } - - public HashMap getTotems() { - return totems; - } - - @Nullable - public List getTotemsByCoreID(String core) { - return cores.get(core); - } - - public HashMap> getCores() { - return cores; - } - - @Nullable - public String getBlockID(String block) { - return blockIDs.get(block); - } - - public HashMap getBlockIDs() { - return blockIDs; - } - - @Nullable - public String getInvertedBlock(String id) { - return invertedIDs.get(id); - } - - public HashMap getInvertedIDs() { - return invertedIDs; - } - - private void loadBlocks() { - File totem_folder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "totem_blocks"); - if (!totem_folder.exists()) { - if (!totem_folder.mkdir()) return; - plugin.saveResource("contents" + File.separator + "totem_blocks" + File.separator + "default.yml", false); - } - File[] files = totem_folder.listFiles(); - if (files == null) return; - for (File file : files) { - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - config.getKeys(false).forEach(key -> blockIDs.put(key, config.getString(key))); - config.getKeys(false).forEach(key -> invertedIDs.put(config.getString(key), key)); - } - } - - private void loadTotems() { - File totem_folder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + "totems"); - if (!totem_folder.exists()) { - if (!totem_folder.mkdir()) return; - plugin.saveResource("contents" + File.separator + "totems" + File.separator + "default.yml", false); - } - File[] files = totem_folder.listFiles(); - if (files == null) return; - for (File file : files) { - YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (String key : config.getKeys(false)) { - List cores = config.getStringList(key + ".core"); - List flat = config.getStringList(key + ".layer.1"); - int length = flat.get(0).split("\\s+").length; - int width = flat.size(); - int height = Objects.requireNonNull(config.getConfigurationSection(key + ".layer")).getKeys(false).size(); - CorePos corePos = null; - OriginalModel originalModel = new OriginalModel(length, width, height); - FinalModel finalModel = new FinalModel(length, width, height); - for (int k = 0; k < height; k++) { - List layer = config.getStringList(key + ".layer." + (k+1)); - if (layer.size() != width) { - AdventureUtils.consoleMessage("[CustomFishing] Each layer should have the same size! Error exists in totem:" + key + " layer:" + (k + 1)); - return; - } - for (int j = 0; j < width; j++) { - String[] args = layer.get(j).split("\\s+"); - if (args.length != length) { - AdventureUtils.consoleMessage("[CustomFishing] Each layer should have the same size! Error exists in totem:" + key + " layer:" + (k + 1) + " line:" + (k + 1)); - return; - } - for (int i = 0; i < length; i++) { - if (args[i].startsWith("(") && args[i].endsWith(")")) { - String content = args[i].substring(1, args[i].length()-1); - corePos = getCorePos(cores, corePos, originalModel, k, j, i, content); - finalModel.setElement("*", i, j, k); - } - else if (args[i].contains(">")) { - String before = args[i].split(">")[0]; - String after = args[i].split(">")[1]; - finalModel.setElement(after, i, j, k); - corePos = getCorePos(cores, corePos, originalModel, k, j, i, before); - } - else { - String[] elements = args[i].split("\\|"); - originalModel.setElement(elements, i, j, k); - for (String core : cores) { - for (String element : elements) { - if (element.equals(core)) { - corePos = new CorePos(i, j, k); - } - } - } - } - } - } - } - if(corePos == null) { - AdventureUtils.consoleMessage("[CustomTotems] No core block set for totem:" + key); - return; - } - else { - finalModel.setCorePos(corePos); - originalModel.setCorePos(corePos); - } - - TotemConfig totem = new TotemConfig( - originalModel, - finalModel, - config.getInt(key + ".radius", 16), - config.getInt(key + ".duration", 300), - Particle.valueOf(config.getString(key + ".particle", "SPELL_MOB").toUpperCase(Locale.ENGLISH)), - ConfigUtils.getEffect(config.getConfigurationSection(key + ".effect")) - ); - - List actionList = new ArrayList<>(); - List nearActionList = new ArrayList<>(); - if (config.contains(key + ".action")) { - for (String action : Objects.requireNonNull(config.getConfigurationSection(key + ".action")).getKeys(false)) { - switch (action) { - case "commands-activator" -> actionList.add(new CommandActionImpl(config.getStringList(key + ".action." + action).toArray(new String[0]), null, 1)); - case "commands-nearby-players" -> nearActionList.add(new CommandActionImpl(config.getStringList(key + ".action." + action).toArray(new String[0]), null, 1)); - case "messages-activator" -> actionList.add(new MessageActionImpl(config.getStringList(key + ".action." + action).toArray(new String[0]), null, 1)); - case "messages-nearby-players" -> nearActionList.add(new MessageActionImpl(config.getStringList(key + ".action." + action).toArray(new String[0]), null, 1)); - } - } - } - - totem.setActivatorActions(actionList.toArray(new Action[0])); - totem.setNearbyActions(nearActionList.toArray(new Action[0])); - totem.setRequirements(ConfigUtils.getRequirementsWithMsg(config.getConfigurationSection(key + ".requirements"))); - - if (config.getBoolean(key + ".hologram.enable", false)) { - totem.setHoloText(config.getStringList(key + ".hologram.text").toArray(new String[0])); - totem.setHoloOffset(config.getDouble(key + ".hologram.y-offset")); - } - - if (config.contains(key + ".potion-effects")) { - List potionEffectList = new ArrayList<>(); - for (String potion : config.getConfigurationSection(key + ".potion-effects").getKeys(false)) { - PotionEffectType potionType = PotionEffectType.getByName(potion.toUpperCase(Locale.ENGLISH)); - if (potionType == null) continue; - int time = 40; - if (potionType.equals(PotionEffectType.NIGHT_VISION)) time = 400; - PotionEffect potionEffect = new PotionEffect( - potionType, - time, - config.getInt(key + ".potion-effects." + potion, 1) - 1); - potionEffectList.add(potionEffect); - } - totem.setPotionEffects(potionEffectList.toArray(new PotionEffect[0])); - } - - totems.put(key, totem); - - for (String core : cores) { - if (this.cores.get(core) == null){ - List totems = new ArrayList<>(); - totems.add(totem); - this.cores.put(core, totems); - } - else { - this.cores.get(core).add(totem); - } - } - } - } - AdventureUtils.consoleMessage("[CustomFishing] Loaded " + totems.size() + " totem(s)"); - } - - private CorePos getCorePos(List cores, CorePos corePos, OriginalModel originalModel, int k, int j, int i, String content) { - String[] elements = content.split("\\|"); - originalModel.setElement(elements, i, j, k); - for (String core : cores) { - for (String element : elements) { - if (element.equals(core)) { - corePos = new CorePos(i, j, k); - } - } - } - return corePos; - } - - public int checkLocationModel(OriginalModel model, Location location){ - - BlockInterface blockInterface = plugin.getIntegrationManager().getBlockInterface(); - - CorePos corePos = model.getCorePos(); - int xOffset = corePos.getX(); - int yOffset = corePos.getY(); - int zOffset = corePos.getZ(); - - int height = model.getHeight(); - int length = model.getLength(); - int width = model.getWidth(); - - Location startLoc = location.clone().subtract(0, yOffset, 0); - - Label_1: - { - for(int i = 0; i< height; i++) { - Location loc = startLoc.clone().add(-xOffset, i, -zOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(x, 0, z).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_1; - } - } - } - return 1; - } - - Label_2: - { - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(xOffset, i, zOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(-x, 0, -z).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_2; - } - } - } - return 2; - } - - Label_3: - { - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-zOffset, i, xOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(z, 0, -x).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_3; - } - } - } - return 3; - } - - Label_4: - { - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(zOffset, i, -xOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(-z, 0, x).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_4; - } - } - } - return 4; - } - - Label_5: - { - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-zOffset, i, -xOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(z, 0, x).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_5; - } - } - } - return 5; - } - - Label_6: - { - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(zOffset, i, xOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(-z, 0, -x).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_6; - } - } - } - return 6; - } - - Label_7: - { - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-xOffset, i, zOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(x, 0, -z).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_7; - } - } - } - return 7; - } - Label_8: - { - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(xOffset, i, -zOffset); - for (int z = 0; z < width; z++) { - inner: for (int x = 0; x < length; x++) { - String[] elements = model.getElement(x, z, i); - String id = blockInterface.getID(loc.clone().add(-x, 0, z).getBlock()); - for (String element : elements) { - if (element.equals("*")) continue inner; - if (id == null) break; - if (id.equals(element)) continue inner; - } - break Label_8; - } - } - } - return 8; - } - return 0; - } - - public void removeModel(FinalModel model, Location coreLoc, int direction) { - - BlockInterface blockInterface = plugin.getIntegrationManager().getBlockInterface(); - - CorePos corePos = model.getCorePos(); - int xOffset = corePos.getX(); - int yOffset = corePos.getY(); - int zOffset = corePos.getZ(); - - int height = model.getHeight(); - int length = model.getLength(); - int width = model.getWidth(); - - Location startLoc = coreLoc.clone().subtract(0, yOffset, 0); - - switch (direction) { - case 1: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-xOffset, i, -zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(x, 0, z).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")) { - blockInterface.replaceBlock(loc.clone().add(x, 0, z), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(x, 0, z)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - case 2: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(xOffset, i, zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(-x, 0, -z).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")){ - blockInterface.replaceBlock(loc.clone().add(-x, 0, -z), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(-x, 0, -z)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - case 3: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-zOffset, i, xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(z, 0, -x).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")){ - blockInterface.replaceBlock(loc.clone().add(z, 0, -x), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(z, 0, -x)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - case 4: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(zOffset, i, -xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(-z, 0, x).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")){ - blockInterface.replaceBlock(loc.clone().add(-z, 0, x), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(-z, 0, x)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - case 5: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-zOffset, i, -xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(z, 0, x).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")){ - blockInterface.replaceBlock(loc.clone().add(z, 0, x), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(z, 0, x)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - case 6: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(zOffset, i, xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(-z, 0, -x).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")){ - blockInterface.replaceBlock(loc.clone().add(-z, 0, -x), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(-z, 0, -x)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - case 7: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-xOffset, i, zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(x, 0, -z).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")){ - blockInterface.replaceBlock(loc.clone().add(x, 0, -z), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(x, 0, -z)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - case 8: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(xOffset, i, -zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) == null) { - blockInterface.removeBlock(loc.clone().add(-x, 0, z).getBlock()); - continue; - } - if (!model.getElement(x, z, i).equals("*")){ - blockInterface.replaceBlock(loc.clone().add(-x, 0, z), model.getElement(x, z, i)); - } - plugin.getFishingManager().addTotemBreakDetectToCache(LocationUtils.getSimpleLocation(loc.clone().add(-x, 0, z)), LocationUtils.getSimpleLocation(coreLoc)); - } - } - break; - } - } - - public void clearBreakDetectCache(FinalModel model, Location startLoc, int direction) { - CorePos corePos = model.getCorePos(); - int xOffset = corePos.getX(); - int zOffset = corePos.getZ(); - int height = model.getHeight(); - int length = model.getLength(); - int width = model.getWidth(); - switch (direction) { - case 1: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-xOffset, i, -zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(x, 0, z))); - } - } - } - break; - case 2: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(xOffset, i, zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(-x, 0, -z))); - } - } - } - break; - case 3: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-zOffset, i, xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(z, 0, -x))); - } - } - } - break; - case 4: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(zOffset, i, -xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(-z, 0, x))); - } - } - } - break; - case 5: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-zOffset, i, -xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(z, 0, x))); - } - } - } - break; - case 6: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(zOffset, i, xOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(-z, 0, -x))); - } - } - } - break; - case 7: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(-xOffset, i, zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(x, 0, -z))); - } - } - } - break; - case 8: - for (int i = 0; i < height; i++) { - Location loc = startLoc.clone().add(xOffset, i, -zOffset); - for (int z = 0; z < width; z++) - for (int x = 0; x < length; x++) { - if (model.getElement(x, z, i) != null) { - plugin.getFishingManager().removeTotemBreakDetectFromCache(LocationUtils.getSimpleLocation(loc.clone().add(-x, 0, z))); - } - } - } - break; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/object/DataFunction.java b/src/main/java/net/momirealms/customfishing/object/DataFunction.java deleted file mode 100644 index 2b46a83d..00000000 --- a/src/main/java/net/momirealms/customfishing/object/DataFunction.java +++ /dev/null @@ -1,44 +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.object; - -import java.util.HashMap; -import java.util.UUID; - -public abstract class DataFunction extends Function { - - protected final HashMap triedTimes; - - public DataFunction() { - this.triedTimes = new HashMap<>(); - } - - protected boolean checkTriedTimes(UUID uuid) { - Integer previous = triedTimes.get(uuid); - if (previous == null) { - triedTimes.put(uuid, 1); - return true; - } else if (previous > 2) { - triedTimes.remove(uuid); - return false; - } else { - triedTimes.put(uuid, previous + 1); - return true; - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/object/Function.java b/src/main/java/net/momirealms/customfishing/object/Function.java deleted file mode 100644 index f216ba31..00000000 --- a/src/main/java/net/momirealms/customfishing/object/Function.java +++ /dev/null @@ -1,63 +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.object; - -import org.bukkit.entity.Player; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; - -public abstract class Function { - - public void load() { - //empty - } - - public void unload() { - //empty - } - - public void disable() { - //empty - } - - public void onQuit(Player player) { - //empty - } - - public void onJoin(Player player) { - //empty - } - - public void onInteract(PlayerInteractEvent event) { - //empty - } - - public void onBreakBlock(BlockBreakEvent event) { - //empty - } - - public void onConsumeItem(PlayerItemConsumeEvent event) { - //empty - } - - public void onDragInventory(InventoryDragEvent event) { - //empty - } -} diff --git a/src/main/java/net/momirealms/customfishing/object/InventoryFunction.java b/src/main/java/net/momirealms/customfishing/object/InventoryFunction.java deleted file mode 100644 index 2c34a5a0..00000000 --- a/src/main/java/net/momirealms/customfishing/object/InventoryFunction.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.momirealms.customfishing.object; - -import com.comphenix.protocol.events.PacketContainer; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryDragEvent; - -public abstract class InventoryFunction extends DataFunction { - - public void onWindowTitlePacketSend(PacketContainer packet, Player receiver) { - //empty - } - - public void onCloseInventory(InventoryCloseEvent event) { - //empty - } - - public void onClickInventory(InventoryClickEvent event) { - //empty - } - - public void onDragInventory(InventoryDragEvent event) { - - } -} diff --git a/src/main/java/net/momirealms/customfishing/object/LeveledEnchantment.java b/src/main/java/net/momirealms/customfishing/object/LeveledEnchantment.java deleted file mode 100644 index a2f65d8c..00000000 --- a/src/main/java/net/momirealms/customfishing/object/LeveledEnchantment.java +++ /dev/null @@ -1,24 +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.object; - -import org.bukkit.NamespacedKey; - -public record LeveledEnchantment(NamespacedKey key, int level, double chance) { - -} diff --git a/src/main/java/net/momirealms/customfishing/object/SimpleLocation.java b/src/main/java/net/momirealms/customfishing/object/SimpleLocation.java deleted file mode 100644 index d8410362..00000000 --- a/src/main/java/net/momirealms/customfishing/object/SimpleLocation.java +++ /dev/null @@ -1,57 +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.object; - -import java.util.Objects; - -public record SimpleLocation(String worldName, int x, int y, int z) { - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final SimpleLocation other = (SimpleLocation) obj; - if (!Objects.equals(worldName, other.worldName())) { - return false; - } - if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)) { - return false; - } - if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)) { - return false; - } - if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 19 * hash + (worldName != null ? worldName.hashCode() : 0); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); - return hash; - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java b/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java deleted file mode 100644 index 003d1082..00000000 --- a/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java +++ /dev/null @@ -1,50 +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.scheduler; - -import net.momirealms.customfishing.CustomFishing; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; - -import java.util.concurrent.Callable; -import java.util.concurrent.Future; - -public class BukkitSchedulerImpl implements SchedulerPlatform { - - private final CustomFishing plugin; - - public BukkitSchedulerImpl(CustomFishing plugin) { - this.plugin = plugin; - } - - @Override - public Future callSyncMethod(@NotNull Callable task) { - return Bukkit.getScheduler().callSyncMethod(plugin, task); - } - - @Override - public void runTask(Runnable runnable) { - Bukkit.getScheduler().runTask(plugin, runnable); - } - - @Override - public void runTask(Runnable runnable, Location location) { - runTask(runnable); - } -} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/BukkitTimerTask.java b/src/main/java/net/momirealms/customfishing/scheduler/BukkitTimerTask.java deleted file mode 100644 index c7cefce0..00000000 --- a/src/main/java/net/momirealms/customfishing/scheduler/BukkitTimerTask.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.momirealms.customfishing.scheduler; - -import org.bukkit.scheduler.BukkitTask; - -public class BukkitTimerTask implements TimerTask { - - private final BukkitTask bukkitTask; - - public BukkitTimerTask(BukkitTask bukkitTask) { - this.bukkitTask = bukkitTask; - } - - @Override - public void cancel() { - this.bukkitTask.cancel(); - } - - @Override - public boolean isCancelled() { - return bukkitTask.isCancelled(); - } -} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/FoliaSchedulerImpl.java b/src/main/java/net/momirealms/customfishing/scheduler/FoliaSchedulerImpl.java deleted file mode 100644 index 525fd057..00000000 --- a/src/main/java/net/momirealms/customfishing/scheduler/FoliaSchedulerImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.momirealms.customfishing.scheduler; - -import net.momirealms.customfishing.CustomFishing; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; - -import java.util.concurrent.Callable; -import java.util.concurrent.Future; - -public class FoliaSchedulerImpl implements SchedulerPlatform { - - private final CustomFishing plugin; - - public FoliaSchedulerImpl(CustomFishing plugin) { - this.plugin = plugin; - } - - @Override - public Future callSyncMethod(@NotNull Callable task) { - return null; - } - - @Override - public void runTask(Runnable runnable) { - Bukkit.getGlobalRegionScheduler().execute(plugin, runnable); - } - - @Override - public void runTask(Runnable runnable, Location location) { - Bukkit.getRegionScheduler().execute(plugin, location, runnable); - } -} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/FoliaTimerTask.java b/src/main/java/net/momirealms/customfishing/scheduler/FoliaTimerTask.java deleted file mode 100644 index 3da32288..00000000 --- a/src/main/java/net/momirealms/customfishing/scheduler/FoliaTimerTask.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.momirealms.customfishing.scheduler; - -import io.papermc.paper.threadedregions.scheduler.ScheduledTask; - -public class FoliaTimerTask implements TimerTask { - - private final ScheduledTask timerTask; - - public FoliaTimerTask(ScheduledTask timerTask) { - this.timerTask = timerTask; - } - - @Override - public void cancel() { - this.timerTask.cancel(); - } - - @Override - public boolean isCancelled() { - return timerTask.isCancelled(); - } -} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/Scheduler.java b/src/main/java/net/momirealms/customfishing/scheduler/Scheduler.java deleted file mode 100644 index 483d551b..00000000 --- a/src/main/java/net/momirealms/customfishing/scheduler/Scheduler.java +++ /dev/null @@ -1,95 +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.scheduler; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.object.Function; -import org.bukkit.Location; -import org.jetbrains.annotations.NotNull; - -import java.util.concurrent.*; - -public class Scheduler extends Function { - - private final ScheduledThreadPoolExecutor schedule; - private final SchedulerPlatform schedulerPlatform; - - public Scheduler(CustomFishing plugin) { - if (plugin.getVersionHelper().isFolia()) { - this.schedulerPlatform = new FoliaSchedulerImpl(plugin); - } else { - this.schedulerPlatform = new BukkitSchedulerImpl(plugin); - } - this.schedule = new ScheduledThreadPoolExecutor(4); - this.schedule.setMaximumPoolSize(4); - this.schedule.setKeepAliveTime(10, TimeUnit.SECONDS); - this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); - } - - public void reload() { - this.schedule.setCorePoolSize(Math.max(ConfigManager.corePoolSize, 4)); - this.schedule.setMaximumPoolSize(Math.max(Math.max(ConfigManager.maximumPoolSize, 4), ConfigManager.corePoolSize)); - this.schedule.setKeepAliveTime(ConfigManager.keepAliveTime, TimeUnit.SECONDS); - } - - @Override - public void disable() { - this.schedule.shutdown(); - } - - public ScheduledFuture runTaskAsyncLater(Runnable runnable, long delay, TimeUnit timeUnit) { - return this.schedule.schedule(runnable, delay, timeUnit); - } - - public void runTaskAsync(Runnable runnable) { - this.schedule.execute(runnable); - } - - public void runTask(Runnable runnable) { - this.schedulerPlatform.runTask(runnable); - } - - public void runTask(Runnable runnable, Location location) { - this.schedulerPlatform.runTask(runnable, location); - } - - public ScheduledFuture runTaskLater(Runnable runnable, long delay, TimeUnit timeUnit) { - return this.schedule.schedule(() -> runTask(runnable), delay, timeUnit); - } - - public ScheduledFuture runTaskLater(Runnable runnable, long delay, TimeUnit timeUnit, Location location) { - return this.schedule.schedule(() -> runTask(runnable, location), delay, timeUnit); - } - - public Future callSyncMethod(@NotNull Callable task) { - return this.schedulerPlatform.callSyncMethod(task); - } - - public ScheduledFuture runTaskTimerAsync(Runnable runnable, long delay, long interval, TimeUnit timeUnit) { - return this.schedule.scheduleAtFixedRate(runnable, delay, interval, timeUnit); - } - - public ScheduledFuture runTaskTimer(Runnable runnable, long delay, long interval, TimeUnit timeUnit) { - return this.schedule.scheduleAtFixedRate(() -> runTask(runnable), delay, interval, timeUnit); - } - - public ScheduledFuture runTaskTimer(Runnable runnable, long delay, long interval, TimeUnit timeUnit, Location location) { - return this.schedule.scheduleAtFixedRate(() -> runTask(runnable, location), delay, interval, timeUnit); - } -} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/TimerTask.java b/src/main/java/net/momirealms/customfishing/scheduler/TimerTask.java deleted file mode 100644 index eabbbc64..00000000 --- a/src/main/java/net/momirealms/customfishing/scheduler/TimerTask.java +++ /dev/null @@ -1,8 +0,0 @@ -package net.momirealms.customfishing.scheduler; - -public interface TimerTask { - - void cancel(); - - boolean isCancelled(); -} diff --git a/src/main/java/net/momirealms/customfishing/util/AdventureUtils.java b/src/main/java/net/momirealms/customfishing/util/AdventureUtils.java deleted file mode 100644 index cdd42bba..00000000 --- a/src/main/java/net/momirealms/customfishing/util/AdventureUtils.java +++ /dev/null @@ -1,315 +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.util; - -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.format.TextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.title.Title; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.object.Reflection; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class AdventureUtils { - - /** - * Get component from text - * @param text text - * @return component - */ - public static Component getComponentFromMiniMessage(String text) { - return MiniMessage.miniMessage().deserialize(replaceLegacy(text)); - } - - /** - * Send a message to a command sender - * @param sender sender - * @param s message - */ - public static void sendMessage(CommandSender sender, String s) { - if (s == null) return; - if (sender instanceof Player player) playerMessage(player, s); - else consoleMessage(s); - } - - /** - * Send a message to console - * @param s message - */ - public static void consoleMessage(String s) { - if (s == null) return; - Audience au = CustomFishing.getAdventure().sender(Bukkit.getConsoleSender()); - au.sendMessage(getComponentFromMiniMessage(s)); - } - - /** - * Send a message to a player - * @param player player - * @param s message - */ - public static void playerMessage(Player player, String s) { - if (s == null) return; - Audience au = CustomFishing.getAdventure().player(player); - au.sendMessage(getComponentFromMiniMessage(s)); - } - - /** - * Send a title to a player - * @param player player - * @param s1 title - * @param s2 subtitle - * @param in in (ms) - * @param duration duration (ms) - * @param out out (ms) - */ - public static void playerTitle(Player player, String s1, String s2, int in, int duration, int out) { - Audience au = CustomFishing.getAdventure().player(player); - Title.Times times = Title.Times.times(Duration.ofMillis(in), Duration.ofMillis(duration), Duration.ofMillis(out)); - Title title = Title.title(getComponentFromMiniMessage(s1), getComponentFromMiniMessage(s2), times); - au.showTitle(title); - } - - /** - * Send a title to a player - * @param player player - * @param s1 title - * @param s2 subtitle - * @param in in (ms) - * @param duration duration (ms) - * @param out out (ms) - */ - public static void playerTitle(Player player, Component s1, Component s2, int in, int duration, int out) { - Audience au = CustomFishing.getAdventure().player(player); - Title.Times times = Title.Times.times(Duration.ofMillis(in), Duration.ofMillis(duration), Duration.ofMillis(out)); - Title title = Title.title(s1, s2, times); - au.showTitle(title); - } - - /** - * Send an actionbar to a player - * @param player player - * @param s actionbar - */ - public static void playerActionbar(Player player, String s) { - Audience au = CustomFishing.getAdventure().player(player); - au.sendActionBar(getComponentFromMiniMessage(s)); - } - - /** - * Play a sound to a player - * @param player player - * @param source sound source - * @param key sound key - * @param volume volume - * @param pitch pitch - */ - public static void playerSound(Player player, Sound.Source source, Key key, float volume, float pitch) { - Sound sound = Sound.sound(key, source, volume, pitch); - Audience au = CustomFishing.getAdventure().player(player); - au.playSound(sound); - } - - public static String replaceLegacy(String legacy) { - StringBuilder stringBuilder = new StringBuilder(); - char[] chars = legacy.toCharArray(); - for (int i = 0; i < chars.length; i++) { - if (isColorCode(chars[i])) { - if (i + 1 < chars.length) { - switch (chars[i+1]) { - case '0' -> stringBuilder.append(""); - case '1' -> stringBuilder.append(""); - case '2' -> stringBuilder.append(""); - case '3' -> stringBuilder.append(""); - case '4' -> stringBuilder.append(""); - case '5' -> stringBuilder.append(""); - case '6' -> stringBuilder.append(""); - case '7' -> stringBuilder.append(""); - case '8' -> stringBuilder.append(""); - case '9' -> stringBuilder.append(""); - case 'a' -> stringBuilder.append(""); - case 'b' -> stringBuilder.append(""); - case 'c' -> stringBuilder.append(""); - case 'd' -> stringBuilder.append(""); - case 'e' -> stringBuilder.append(""); - case 'f' -> stringBuilder.append(""); - case 'r' -> stringBuilder.append(""); - case 'l' -> stringBuilder.append(""); - case 'm' -> stringBuilder.append(""); - case 'o' -> stringBuilder.append(""); - case 'n' -> stringBuilder.append(""); - case 'k' -> stringBuilder.append(""); - case 'x' -> { - if (i + 13 >= chars.length - || !isColorCode(chars[i+2]) - || !isColorCode(chars[i+4]) - || !isColorCode(chars[i+6]) - || !isColorCode(chars[i+8]) - || !isColorCode(chars[i+10]) - || !isColorCode(chars[i+12])) { - stringBuilder.append(chars[i]); - continue; - } - stringBuilder - .append("<#") - .append(chars[i+3]) - .append(chars[i+5]) - .append(chars[i+7]) - .append(chars[i+9]) - .append(chars[i+11]) - .append(chars[i+13]) - .append(">"); - i += 13; - } - default -> { - stringBuilder.append(chars[i]); - continue; - } - } - i++; - } else { - stringBuilder.append(chars[i]); - } - } else { - stringBuilder.append(chars[i]); - } - } - return stringBuilder.toString(); - } - - private static boolean isColorCode(char c) { - return c == '§' || c == '&'; - } - - public static String replaceMiniMessage(String str) { - String result = str.replace("&","§"); - List miniFormat = new ArrayList<>(); - Pattern pattern = Pattern.compile("<.*?>"); - Matcher matcher = pattern.matcher(str); - while (matcher.find()) miniFormat.add(matcher.group()); - for (String mini : miniFormat) { - StringBuilder replacer = new StringBuilder(); - switch (mini) { - case "" -> replacer = new StringBuilder("§0"); - case "" -> replacer = new StringBuilder("§1"); - case "" -> replacer = new StringBuilder("§2"); - case "" -> replacer = new StringBuilder("§3"); - case "" -> replacer = new StringBuilder("§4"); - case "" -> replacer = new StringBuilder("§5"); - case "" -> replacer = new StringBuilder("§6"); - case "" -> replacer = new StringBuilder("§7"); - case "" -> replacer = new StringBuilder("§8"); - case "" -> replacer = new StringBuilder("§9"); - case "" -> replacer = new StringBuilder("§a"); - case "" -> replacer = new StringBuilder("§b"); - case "" -> replacer = new StringBuilder("§c"); - case "" -> replacer = new StringBuilder("§d"); - case "" -> replacer = new StringBuilder("§e"); - case "" -> replacer = new StringBuilder("§f"); - case "" -> replacer = new StringBuilder("§r"); - case "" -> replacer = new StringBuilder("§l"); - case "" -> replacer = new StringBuilder("§m"); - case "" -> replacer = new StringBuilder("§o"); - case "" -> replacer = new StringBuilder("§n"); - case "" -> replacer = new StringBuilder("§k"); - default -> { - if (mini.length() == 9 && mini.charAt(1) == '#') { - replacer = new StringBuilder("§x"); - for (int i = 2; i < 8; i++) { - replacer.append("§").append(mini.charAt(i)); - } - } - } - } - result = result.replace(mini, replacer.toString()); - } - return result; - } - - public static Object getPaperComponent(Component component) { - try { - Object newComponent; - if (component instanceof TextComponent textComponent) { - Method textComponentMethod = Reflection.componentClass.getMethod("text", String.class); - newComponent = textComponentMethod.invoke(null, textComponent.content()); - TextColor textColor = textComponent.color(); - if (textColor != null) { - String hex = textColor.asHexString(); - Method setColorMethod = Reflection.textComponentClass.getMethod("color", Reflection.textColorClass); - Method getColorFromHex = Reflection.textColorClass.getMethod("fromHexString", String.class); - Object hexColor = getColorFromHex.invoke(null, hex); - newComponent = setColorMethod.invoke(newComponent, hexColor); - } - Key fontKey = textComponent.font(); - if (fontKey != null) { - String namespacedKey = fontKey.asString(); - Method setKeyMethod = Reflection.textComponentClass.getMethod("font", Reflection.keyClass); - Method keyMethod = Reflection.keyClass.getMethod("key", String.class); - Object key = keyMethod.invoke(null, namespacedKey); - newComponent = setKeyMethod.invoke(newComponent, key); - } - for (Map.Entry entry : textComponent.decorations().entrySet()) { - String dec = entry.getKey().name(); - Method getTextDecoration = Reflection.textDecorationClass.getDeclaredMethod("valueOf", String.class); - Object textDecoration = getTextDecoration.invoke(null, dec); - String stat = entry.getValue().name(); - Method getState = Reflection.textDecorationStateClass.getDeclaredMethod("valueOf", String.class); - Object state = getState.invoke(null, stat); - Method applyDecorationMethod = Reflection.textComponentClass.getMethod("decoration", Reflection.textDecorationClass, Reflection.textDecorationStateClass); - newComponent = applyDecorationMethod.invoke(newComponent, textDecoration, state); - } - newComponent = setChildrenComponents(textComponent, newComponent); - } else { - Method textComponentMethod = Reflection.componentClass.getMethod("text", String.class); - newComponent = textComponentMethod.invoke(null, ""); - newComponent = setChildrenComponents(component, newComponent); - } - return newComponent; - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { - exception.printStackTrace(); - return null; - } - } - - private static Object setChildrenComponents(Component component, Object newComponent) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - List children = new ArrayList<>(); - for (Component child : component.children()) { - children.add(getPaperComponent(child)); - } - if (children.size() != 0) { - Method childrenMethod = Reflection.componentClass.getMethod("children", List.class); - newComponent = childrenMethod.invoke(newComponent, children); - } - return newComponent; - } -} diff --git a/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java b/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java deleted file mode 100644 index a5c6d63a..00000000 --- a/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java +++ /dev/null @@ -1,259 +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.util; - -import dev.dejvokep.boostedyaml.YamlDocument; -import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning; -import dev.dejvokep.boostedyaml.settings.dumper.DumperSettings; -import dev.dejvokep.boostedyaml.settings.general.GeneralSettings; -import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings; -import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.Effect; -import net.momirealms.customfishing.fishing.action.*; -import net.momirealms.customfishing.fishing.requirements.*; -import net.momirealms.customfishing.helper.Log; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -import java.io.File; -import java.io.IOException; -import java.util.*; - -public class ConfigUtils { - - /** - * Get a config by name - * @param configName config's name - * @return yaml - */ - public static YamlConfiguration getConfig(String configName) { - File file = new File(CustomFishing.getInstance().getDataFolder(), configName); - if (!file.exists()) CustomFishing.getInstance().saveResource(configName, false); - return YamlConfiguration.loadConfiguration(file); - } - - /** - * Update config - * @param fileName config - */ - public static void update(String fileName, List ignoredSections) { - try { - YamlDocument.create( - new File(CustomFishing.getInstance().getDataFolder(), fileName), - Objects.requireNonNull(CustomFishing.getInstance().getResource(fileName)), - GeneralSettings.DEFAULT, - LoaderSettings.builder().setAutoUpdate(true).build(), - DumperSettings.DEFAULT, - UpdaterSettings.builder().setVersioning(new BasicVersioning("config-version")).addIgnoredRoute("25", "mechanics.mechanic-requirements", '.') - .build() - ); - } catch (IOException e){ - Log.warn(e.getMessage()); - } - } - - private static void setProperties(ConfigurationSection oldSec, ConfigurationSection newSec) { - - } - - /** - * Create a data file if not exists - * @param file file path - * @return yaml data - */ - @SuppressWarnings("ResultOfMethodCallIgnored") - public static YamlConfiguration readData(File file) { - if (!file.exists()) { - try { - file.getParentFile().mkdirs(); - file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - AdventureUtils.consoleMessage("[CustomFishing] Failed to generate data files!"); - } - } - return YamlConfiguration.loadConfiguration(file); - } - - public static RequirementInterface[] getRequirements(ConfigurationSection section) { - if (section != null) { - List requirements = new ArrayList<>(); - for (String type : section.getKeys(false)) { - switch (type) { - case "biome" -> requirements.add(new BiomeImpl(null, new HashSet<>(section.getStringList(type)))); - case "weather" -> requirements.add(new WeatherImpl(null, section.getStringList(type))); - case "ypos" -> requirements.add(new YPosImpl(null, section.getStringList(type))); - case "season" -> requirements.add(new SeasonImpl(null, section.getStringList(type))); - case "world" -> requirements.add(new WorldImpl(null, section.getStringList(type))); - case "permission" -> requirements.add(new PermissionImpl(null, section.getString(type))); - case "time" -> requirements.add(new TimeImpl(null, section.getStringList(type))); - case "skill-level" -> requirements.add(new SkillLevelImpl(null, section.getInt(type))); - case "job-level" -> requirements.add(new JobLevelImpl(null, section.getInt(type))); - case "date" -> requirements.add(new DateImpl(null, new HashSet<>(section.getStringList(type)))); - case "rod" -> requirements.add(new RodImpl(null, new HashSet<>(section.getStringList(type)))); - case "bait" -> requirements.add(new BaitImpl(null, new HashSet<>(section.getStringList(type)))); - case "competition" -> requirements.add(new CompetitionImpl(null, section.getBoolean(type))); - case "papi-condition" -> requirements.add(new CustomPapi(null, Objects.requireNonNull(section.getConfigurationSection(type)).getValues(false))); - } - } - return requirements.toArray(new RequirementInterface[0]); - } - return null; - } - - public static RequirementInterface[] getRequirementsWithMsg(ConfigurationSection section) { - if (section != null) { - List requirements = new ArrayList<>(); - for (String id : section.getKeys(false)) { - ConfigurationSection innerSec = section.getConfigurationSection(id); - if (innerSec == null) continue; - String type = innerSec.getString("type"); - if (type == null) continue; - String[] msg = innerSec.getStringList("message").size() == 0 ? (innerSec.getString("message") == null ? null : new String[]{innerSec.getString("message")}) : innerSec.getStringList("message").toArray(new String[0]); - switch (type) { - case "biome" -> requirements.add(new BiomeImpl(msg, new HashSet<>(innerSec.getStringList("value")))); - case "weather" -> requirements.add(new WeatherImpl(msg, innerSec.getStringList("value"))); - case "ypos" -> requirements.add(new YPosImpl(msg, innerSec.getStringList("value"))); - case "season" -> requirements.add(new SeasonImpl(msg, innerSec.getStringList("value"))); - case "world" -> requirements.add(new WorldImpl(msg, innerSec.getStringList("value"))); - case "permission" -> requirements.add(new PermissionImpl(msg, innerSec.getString("value"))); - case "time" -> requirements.add(new TimeImpl(msg, innerSec.getStringList("value"))); - case "skill-level" -> requirements.add(new SkillLevelImpl(msg, innerSec.getInt("value"))); - case "job-level" -> requirements.add(new JobLevelImpl(msg, innerSec.getInt("value"))); - case "date" -> requirements.add(new DateImpl(msg, new HashSet<>(innerSec.getStringList("value")))); - case "rod" -> requirements.add(new RodImpl(msg, new HashSet<>(innerSec.getStringList("value")))); - case "bait" -> requirements.add(new BaitImpl(msg, new HashSet<>(innerSec.getStringList("value")))); - case "competition" -> requirements.add(new CompetitionImpl(msg, innerSec.getBoolean("value"))); - case "papi-condition" -> requirements.add(new CustomPapi(msg, Objects.requireNonNull(innerSec.getConfigurationSection("value")).getValues(false))); - } - } - return requirements.toArray(new RequirementInterface[0]); - } - return null; - } - - public static Action[] getActions(ConfigurationSection section, String nick) { - if (section != null) { - List actions = new ArrayList<>(); - for (Map.Entry entry : section.getValues(false).entrySet()) { - if (entry.getValue() instanceof ConfigurationSection innerSec) { - String type = innerSec.getString("type"); - if (type == null) continue; - double chance = innerSec.getDouble("chance", 1); - switch (type) { - case "message" -> { - actions.add(new MessageActionImpl( - innerSec.getStringList("value").toArray(new String[0]), - nick, - chance - )); - } - case "command" -> { - actions.add(new CommandActionImpl( - innerSec.getStringList("value").toArray(new String[0]), - nick, - chance - )); - } - case "exp","mending" -> { - actions.add(new VanillaXPImpl( - innerSec.getInt("value"), - type.equals("mending"), - chance - )); - } - case "skill-xp" -> { - actions.add(new SkillXPImpl( - innerSec.getDouble("value"), - chance - )); - } - case "job-xp" -> { - actions.add(new JobXPImpl( - innerSec.getDouble("value"), - chance - )); - } - case "sound" -> { - actions.add(new SoundActionImpl( - Sound.Source.valueOf(innerSec.getString("value.source", "PLAYER").toUpperCase(Locale.ENGLISH)), - Key.key(innerSec.getString("value.key")), - (float) innerSec.getDouble("value.volume"), - (float) innerSec.getDouble("value.pitch"), - chance - )); - } - case "potion-effect" -> { - PotionEffectType potionEffectType = PotionEffectType.getByName(innerSec.getString("value.type", "BLINDNESS").toUpperCase(Locale.ENGLISH)); - if (potionEffectType == null) continue; - actions.add( - new PotionEffectImpl( - new PotionEffect( - potionEffectType, - innerSec.getInt("value.duration"), - innerSec.getInt("value.amplifier") - ), - chance - ) - ); - } - case "chain" -> { - actions.add(new ChainImpl( - getActions(innerSec.getConfigurationSection("value"), nick), - chance - )); - } - } - } - } - return actions.toArray(new Action[0]); - } - return null; - } - - public static Effect getEffect(ConfigurationSection section) { - Effect effect = new Effect(); - if (section == null) return effect; - for (String modifier : section.getKeys(false)) { - switch (modifier) { - case "weight-add" -> { - HashMap as = new HashMap<>(); - Objects.requireNonNull(section.getConfigurationSection(modifier)).getValues(false).forEach((group, value) -> as.put(group, (Integer) value)); - effect.setWeightAS(as); - } - case "weight-multiply" -> { - HashMap md = new HashMap<>(); - Objects.requireNonNull(section.getConfigurationSection(modifier)).getValues(false).forEach((group, value) -> md.put(group, Double.parseDouble(String.valueOf(value))-1)); - effect.setWeightMD(md); - } - case "time" -> effect.setTimeModifier(section.getDouble(modifier)); - case "difficulty" -> effect.setDifficulty(section.getInt(modifier)); - case "double-loot" -> effect.setDoubleLootChance(section.getDouble(modifier)); - case "score" -> effect.setScoreMultiplier(section.getDouble(modifier)); - case "size-multiply" -> effect.setSizeMultiplier(section.getDouble(modifier)); - case "lava-fishing" -> effect.setCanLavaFishing(section.getBoolean(modifier, false)); - } - } - return effect; - } -} diff --git a/src/main/java/net/momirealms/customfishing/util/InventoryUtils.java b/src/main/java/net/momirealms/customfishing/util/InventoryUtils.java deleted file mode 100644 index b069bb44..00000000 --- a/src/main/java/net/momirealms/customfishing/util/InventoryUtils.java +++ /dev/null @@ -1,151 +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.util; - -import net.kyori.adventure.text.Component; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.object.Reflection; -import org.bukkit.Bukkit; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.io.BukkitObjectInputStream; -import org.bukkit.util.io.BukkitObjectOutputStream; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class InventoryUtils { - - /** - * Converts itemStacks to base64 - * @param contents items - * @return base64 - */ - public static @NotNull String toBase64(ItemStack[] contents) { - boolean convert = false; - for (ItemStack content : contents) { - if (content != null) { - convert = true; - break; - } - } - if (convert) { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); - dataOutput.writeInt(contents.length); - for (ItemStack itemStack : contents) { - dataOutput.writeObject(itemStack); - } - dataOutput.close(); - byte[] byteArr = outputStream.toByteArray(); - outputStream.close(); - return Base64Coder.encodeLines(byteArr); - } catch (IOException e) { - throw new RuntimeException("[CustomFishing] Data save error", e); - } - } - return ""; - } - - /** - * Get itemStacks from base64 - * @param base64 base64 - * @return itemStacks - */ - @Nullable - public static ItemStack[] getInventoryItems(String base64) { - ItemStack[] itemStacks = null; - try { - itemStacks = stacksFromBase64(base64); - } catch (IllegalArgumentException exception) { - exception.printStackTrace(); - } - return itemStacks; - } - - private static ItemStack[] stacksFromBase64(String data) { - if (data == null || data.equals("")) return new ItemStack[]{}; - - ByteArrayInputStream inputStream; - try { - inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); - } catch (IllegalArgumentException e) { - return new ItemStack[]{}; - } - BukkitObjectInputStream dataInput = null; - ItemStack[] stacks = null; - try { - dataInput = new BukkitObjectInputStream(inputStream); - stacks = new ItemStack[dataInput.readInt()]; - } catch (IOException e) { - e.printStackTrace(); - } - if (stacks == null) return new ItemStack[]{}; - for (int i = 0; i < stacks.length; i++) { - try { - stacks[i] = (ItemStack) dataInput.readObject(); - } - catch (IOException | ClassNotFoundException | NullPointerException e) { - try { - dataInput.close(); - } catch (IOException exception) { - AdventureUtils.consoleMessage("[CustomFishing] Error! Failed to read fishing bag data"); - } - return null; - } - } - try { - dataInput.close(); - } catch (IOException ignored) { - } - return stacks; - } - - @NotNull - public static Inventory createInventory(InventoryHolder inventoryHolder, int size, Component component) { - try { - Method createInvMethod = Reflection.bukkitClass.getMethod("createInventory", InventoryHolder.class, int.class, Reflection.componentClass); - return (Inventory) createInvMethod.invoke(null, inventoryHolder, size, AdventureUtils.getPaperComponent(component)); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { - exception.printStackTrace(); - throw new RuntimeException("Failed to create inventory"); - } - } - - public static Inventory createInventory(InventoryHolder inventoryHolder, int size, String title) { - if (CustomFishing.getInstance().getVersionHelper().isSpigot()) { - return Bukkit.createInventory(inventoryHolder, size, AdventureUtils.replaceMiniMessage(title)); - } else { - try { - Method createInvMethod = Reflection.bukkitClass.getMethod("createInventory", InventoryHolder.class, int.class, Reflection.componentClass); - return (Inventory) createInvMethod.invoke(null, inventoryHolder, size, AdventureUtils.getPaperComponent(AdventureUtils.getComponentFromMiniMessage(title))); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { - exception.printStackTrace(); - throw new RuntimeException("Failed to create inventory"); - } - } - } -} diff --git a/src/main/java/net/momirealms/customfishing/util/ItemStackUtils.java b/src/main/java/net/momirealms/customfishing/util/ItemStackUtils.java deleted file mode 100644 index 8c6b76d0..00000000 --- a/src/main/java/net/momirealms/customfishing/util/ItemStackUtils.java +++ /dev/null @@ -1,282 +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.util; - -import de.tr7zw.changeme.nbtapi.NBTCompound; -import de.tr7zw.changeme.nbtapi.NBTItem; -import de.tr7zw.changeme.nbtapi.NBTListCompound; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.fishing.FishMeta; -import net.momirealms.customfishing.fishing.loot.DroppedItem; -import net.momirealms.customfishing.fishing.loot.Item; -import net.momirealms.customfishing.fishing.loot.LootImpl; -import net.momirealms.customfishing.manager.ConfigManager; -import net.momirealms.customfishing.object.LeveledEnchantment; -import org.bukkit.Material; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.Damageable; -import org.bukkit.inventory.meta.EnchantmentStorageMeta; -import org.bukkit.inventory.meta.ItemMeta; - -import java.io.File; -import java.io.IOException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; - -public class ItemStackUtils { - - /** - * Build itemStack from item's config - * @param item item - * @return itemStack - */ - public static ItemStack getFromItem(Item item) { - ItemStack itemStack = new ItemStack(item.getMaterial()); - if (item.getMaterial() == Material.AIR) return itemStack; - itemStack.setAmount(item.getAmount()); - ItemMeta itemMeta = itemStack.getItemMeta(); - if (item.getCustomModelData() != 0) itemMeta.setCustomModelData(item.getCustomModelData()); - if (item.isUnbreakable()) itemMeta.setUnbreakable(true); - if (item.getItemFlags() != null) item.getItemFlags().forEach(itemMeta::addItemFlags); - if (item.getEnchantment() != null) { - if (itemStack.getType() == Material.ENCHANTED_BOOK){ - EnchantmentStorageMeta meta = (EnchantmentStorageMeta) itemMeta; - item.getEnchantment().forEach(enchantment -> meta.addStoredEnchant(Objects.requireNonNull(Enchantment.getByKey(enchantment.key())),enchantment.level(),true)); - itemStack.setItemMeta(meta); - } - else { - item.getEnchantment().forEach(enchantment -> itemMeta.addEnchant(Objects.requireNonNull(Enchantment.getByKey(enchantment.key())),enchantment.level(),true)); - itemStack.setItemMeta(itemMeta); - } - } - else { - itemStack.setItemMeta(itemMeta); - } - NBTItem nbtItem = new NBTItem(itemStack); - if (item.getName() != null) { - NBTCompound display = nbtItem.addCompound("display"); - String name = item.getName(); - if (name.contains("&") || name.contains("§")){ - name = AdventureUtils.replaceLegacy(name); - } - display.setString("Name", GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize("" + name))); - } - if (item.getLore() != null) { - NBTCompound display = nbtItem.addCompound("display"); - List lore = display.getStringList("Lore"); - item.getLore().forEach(line -> { - if (line.contains("&") || line.contains("§")){ - line = AdventureUtils.replaceLegacy(line); - } - lore.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize("" + line))); - }); - } - if (item.getCfTag() != null) { - NBTCompound cfCompound = nbtItem.addCompound("CustomFishing"); - cfCompound.setString("type", item.getCfTag()[0]); - cfCompound.setString("id", item.getCfTag()[1]); - } - if (item.getHead64() != null) { - NBTCompound nbtCompound = nbtItem.addCompound("SkullOwner"); - nbtCompound.setUUID("Id", item.isHeadStackable() ? UUID.nameUUIDFromBytes(item.getKey().getBytes()) : UUID.randomUUID()); - NBTListCompound texture = nbtCompound.addCompound("Properties").getCompoundList("textures").addCompound(); - texture.setString("Value", item.getHead64()); - } - if (item.getTotem() != null) { - nbtItem.setString("Totem", item.getTotem()); - } - if (item.getNbt() != null) NBTUtils.setTags(item.getNbt(), nbtItem); - return nbtItem.getItem(); - } - - /** - * Get an itemStack with random durability - * @param itemStack itemStack - */ - public static void addRandomDamage(ItemStack itemStack){ - if (itemStack.getItemMeta() instanceof Damageable damageable){ - damageable.setDamage((int) (itemStack.getType().getMaxDurability() * Math.random())); - itemStack.setItemMeta(damageable); - } - } - - /** - * Adds owner tag - * @param itemStack itemStack - * @param name owner - */ - public static void addOwner(ItemStack itemStack, String name){ - NBTItem nbtItem = new NBTItem(itemStack); - nbtItem.setString("TempOwner", name); - itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - } - - /** - * Add random enchantments - * @param itemStack itemStack - * @param enchantments enchantments - */ - public static void addRandomEnchants(ItemStack itemStack, LeveledEnchantment[] enchantments){ - ItemMeta itemMeta = itemStack.getItemMeta(); - if (itemStack.getType() == Material.ENCHANTED_BOOK){ - EnchantmentStorageMeta meta = (EnchantmentStorageMeta)itemMeta; - for (LeveledEnchantment enchantment : enchantments) { - if (enchantment.chance() > Math.random()) meta.addStoredEnchant(Objects.requireNonNull(Enchantment.getByKey(enchantment.key())),enchantment.level(),true); - } - itemStack.setItemMeta(meta); - } - else { - for (LeveledEnchantment enchantment : enchantments) { - if (enchantment.chance() > Math.random()) itemMeta.addEnchant(Objects.requireNonNull(Enchantment.getByKey(enchantment.key())),enchantment.level(),true); - } - itemStack.setItemMeta(itemMeta); - } - } - - /** - * Add customFishing tags - * - * @param itemStack itemStack - * @param type type - * @param id id - */ - public static void addIdentifier(ItemStack itemStack, String type, String id){ - NBTItem nbtItem = new NBTItem(itemStack); - NBTCompound nbtCompound = nbtItem.addCompound("CustomFishing"); - nbtCompound.setString("type", type); - nbtCompound.setString("id", id); - itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - } - - public static int givePlayerLoot(Player player, String key, int amount){ - LootImpl loot = CustomFishing.getInstance().getLootManager().getLoot(key); - if (!(loot instanceof DroppedItem droppedItem)) return 0; - ItemStack itemStack = CustomFishing.getInstance().getFishingManager().getCustomFishingLootItemStack(droppedItem, player); - if (itemStack.getType() == Material.AIR) return 0; - if (amount != 0) itemStack.setAmount(amount); - player.getInventory().addItem(itemStack); - return itemStack.getAmount(); - } - - public static void givePlayerRod(Player player, String rodKey, int amount){ - Item item = CustomFishing.getInstance().getEffectManager().getRodItem(rodKey); - if (item == null) return; - ItemStack itemStack = getFromItem(item); - if (amount != 0) - for (int i = 0; i < amount; i++) { - player.getInventory().addItem(itemStack); - }else { - player.getInventory().addItem(itemStack); - } - } - - public static void givePlayerBait(Player player, String baitKey, int amount){ - Item item = CustomFishing.getInstance().getEffectManager().getBaitItem(baitKey); - if (item == null) return; - ItemStack itemStack = getFromItem(item); - if (amount != 0) itemStack.setAmount(amount); - player.getInventory().addItem(itemStack); - } - - public static void givePlayerUtil(Player player, String utilKey, int amount){ - Item item = CustomFishing.getInstance().getEffectManager().getUtilItem(utilKey); - if (item == null) return; - ItemStack itemStack = getFromItem(item); - if (amount != 0) itemStack.setAmount(amount); - player.getInventory().addItem(itemStack); - } - - public static boolean saveToFile(ItemStack itemStack, String key){ - if (itemStack == null || itemStack.getType() == Material.AIR || CustomFishing.getInstance().getLootManager().hasLoot(key)) return false; - File file = new File(CustomFishing.getInstance().getDataFolder(), File.separator + "contents/loots" + File.separator + "imported.yml"); - YamlConfiguration data = ConfigUtils.readData(file); - data.set(key + ".material", itemStack.getType().toString()); - data.set(key + ".amount", itemStack.getAmount()); - NBTItem nbtItem = new NBTItem(itemStack); - Map map0 = NBTUtils.compoundToMap(nbtItem); - if (map0.size() != 0) { - data.createSection(key + ".nbt", map0); - } - try { - data.save(file); - CustomFishing.getInstance().getLootManager().unload(); - CustomFishing.getInstance().getLootManager().load(); - } catch (IOException e) { - e.printStackTrace(); - } - return true; - } - - public static FishMeta addExtraMeta(ItemStack itemStack, DroppedItem droppedItem, double sizeMultiplier, Player player) { - NBTItem nbtItem = new NBTItem(itemStack); - if (droppedItem.getBasicPrice() != 0) { - NBTCompound fishMetaCompound = nbtItem.addCompound("FishMeta"); - fishMetaCompound.setFloat("base", droppedItem.getBasicPrice()); - } - if (droppedItem.getSizeBonus() != 0) { - NBTCompound fishMetaCompound = nbtItem.addCompound("FishMeta"); - fishMetaCompound.setFloat("bonus", droppedItem.getSizeBonus()); - } - float size = replaceAndSetSizeProperties(droppedItem.getSize(), nbtItem, sizeMultiplier); - replacePlaceholderInDisplay(nbtItem, player); - itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); - return new FishMeta(size, droppedItem.getBasicPrice(), droppedItem.getSizeBonus()); - } - - private static float replaceAndSetSizeProperties(String[] sizes, NBTItem nbtItem, double sizeMultiplier) { - if (sizes == null) return -1; - float min = Float.parseFloat(sizes[0]); - float max = Float.parseFloat(sizes[1]); - if (max - min < 0) return -1; - float size = (float) ((min + Math.random() * (max - min)) * sizeMultiplier); - String sizeText = String.format("%.1f", size); - NBTCompound nbtCompound = nbtItem.getCompound("display"); - if (nbtCompound == null || !nbtCompound.hasTag("Lore")) return size; - List lore = nbtCompound.getStringList("Lore"); - lore.replaceAll(s -> s.replace("{size}", sizeText)); - NBTCompound fishMetaCompound = nbtItem.addCompound("FishMeta"); - fishMetaCompound.setFloat("size", size); - return size; - } - - private static void replacePlaceholderInDisplay(NBTItem nbtItem, Player player) { - NBTCompound nbtCompound = nbtItem.getCompound("display"); - if (nbtCompound == null) return; - String name = nbtCompound.getString("Name"); - if (!name.equals("")) { - nbtCompound.setString("Name", name - .replace("{player}", player.getName()) - .replace("{date}", LocalDateTime.now().format(DateTimeFormatter.ofPattern(ConfigManager.dateFormat))) - .replace("{worth}", String.format("%.2f", CustomFishing.getInstance().getSellManager().getCFFishPrice(nbtItem)))); - } - List lore = nbtCompound.getStringList("Lore"); - lore.replaceAll(s -> s - .replace("{player}", player.getName()) - .replace("{date}", LocalDateTime.now().format(DateTimeFormatter.ofPattern(ConfigManager.dateFormat))) - .replace("{worth}", String.format("%.2f", CustomFishing.getInstance().getSellManager().getCFFishPrice(nbtItem)))); - } -} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/util/JedisUtils.java b/src/main/java/net/momirealms/customfishing/util/JedisUtils.java deleted file mode 100644 index dd8c2fec..00000000 --- a/src/main/java/net/momirealms/customfishing/util/JedisUtils.java +++ /dev/null @@ -1,88 +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.util; - -import net.momirealms.customfishing.helper.Log; -import org.bukkit.configuration.file.YamlConfiguration; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.JedisPoolConfig; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; - -public class JedisUtils { - - private static JedisPool jedisPool; - - public static Jedis getJedis(){ - return jedisPool.getResource(); - } - - public static void initializeRedis(YamlConfiguration configuration){ - JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); - jedisPoolConfig.setTestWhileIdle(true); - jedisPoolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(30000)); - jedisPoolConfig.setNumTestsPerEvictionRun(-1); - jedisPoolConfig.setMinEvictableIdleTime(Duration.ofMillis(configuration.getInt("Redis.MinEvictableIdleTimeMillis",1800000))); - jedisPoolConfig.setMaxTotal(configuration.getInt("Redis.MaxTotal",8)); - jedisPoolConfig.setMaxIdle(configuration.getInt("Redis.MaxIdle",8)); - jedisPoolConfig.setMinIdle(configuration.getInt("Redis.MinIdle",1)); - jedisPoolConfig.setMaxWait(Duration.ofMillis(configuration.getInt("redis.MaxWaitMillis"))); - if (configuration.getString("Redis.password") != null) { - jedisPool = new JedisPool(jedisPoolConfig, configuration.getString("Redis.host","localhost"), configuration.getInt("Redis.port",6379), 2000, configuration.getString("Redis.password")); - } else { - jedisPool = new JedisPool(jedisPoolConfig, configuration.getString("Redis.host","localhost"), configuration.getInt("Redis.port",6379)); - } - - AdventureUtils.consoleMessage("[CustomFishing] Redis Server Connected!"); - - List minIdleJedisList = new ArrayList<>(jedisPoolConfig.getMinIdle()); - for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) { - Jedis jedis; - try { - jedis = jedisPool.getResource(); - minIdleJedisList.add(jedis); - jedis.ping(); - } catch (Exception e) { - Log.warn(e.getMessage()); - } - } - - for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) { - Jedis jedis; - try { - jedis = minIdleJedisList.get(i); - jedis.close(); - } catch (Exception e) { - Log.warn(e.getMessage()); - } - } - } - - public static void closePool() { - if (jedisPool != null) { - jedisPool.close(); - jedisPool = null; - } - } - public static boolean isPoolEnabled() { - return jedisPool != null && !jedisPool.isClosed(); - } -} diff --git a/src/main/java/net/momirealms/customfishing/util/LocationUtils.java b/src/main/java/net/momirealms/customfishing/util/LocationUtils.java deleted file mode 100644 index fa66f602..00000000 --- a/src/main/java/net/momirealms/customfishing/util/LocationUtils.java +++ /dev/null @@ -1,65 +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.util; - -import net.momirealms.customfishing.CustomFishing; -import net.momirealms.customfishing.object.SimpleLocation; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.stream.Collectors; - -public class LocationUtils { - - public static SimpleLocation getSimpleLocation(Location location) { - return new SimpleLocation(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); - } - - @Nullable - public static Location getLocation(SimpleLocation location) { - World world = Bukkit.getWorld(location.worldName()); - if (world == null) return null; - return new Location(world, location.x(), location.y(), location.z()); - } - - public static Collection getNearbyPlayers(Location location, double radius) { - Collection nearbyPlayers; - if (CustomFishing.getInstance().getVersionHelper().isSpigot()) { - nearbyPlayers = location.getWorld().getNearbyEntities(location, radius, radius, radius) - .stream() - .filter(entity -> entity instanceof Player) - .map(entity -> (Player) entity) - .collect(Collectors.toList()); - } - else { - nearbyPlayers = location.getNearbyPlayers(radius); - } - return nearbyPlayers; - } - - public static double getDistance(Location location1, Location location2) { - double deltaX = location1.getX() - location2.getX(); - double deltaY = location1.getY() - location2.getY(); - double deltaZ = location1.getZ() - location2.getZ(); - return Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); - } -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml deleted file mode 100644 index 48a30169..00000000 --- a/src/main/resources/config.yml +++ /dev/null @@ -1,253 +0,0 @@ -# Wiki: https://mo-mi.gitbook.io/xiaomomi-plugins/ - -# Don't change this unless you are clear about what you are doing -# 请不要修改此项目,除非你明确你在做什么 -config-version: '25' - -# bStats -metrics: true - -# Check for plugin updates -# It works asynchronously and would not cause lag -# 检查更新,异步进行,不会造成卡顿 -update-checker: true - -# You can create language files for your locale and use them -# You are welcomed to submit language files and become one of the contributors -# chinese/english/spanish/turkish -# 你可以自由创建语言文件并使用他们 -lang: english - -# Worlds where fishing mechanic takes effects -# 启用本插件的世界 -worlds: - # Mode: whitelist/blacklist - # 模式:白名单/黑名单 - mode: whitelist - list: - - world - - world_nether - -# Mechanic settings -# 机制设置 -mechanics: - - # Add CustomFishing NBT tags to the loots - # Set it to false if you have problems with stacking - # 为每个战利品增加特殊的CustomFishing NBT标签以被插件识别 - # 禁用此项目将会导致吃食物触发的动作失效 - add-custom-fishing-tags-to-loots: true - - # Disable the fishing bar totally - # 关闭捕鱼条 - disable-bar-mechanic: false - - # The requirements for the plugin to work - # This is designed for servers that want to enable the fishing mechanic at a specific time - # 插件工作所需的条件,比如你希望在特殊事件才启用本插件的机制 - mechanic-requirements: {} - - # Does the fishing bar show up instantly when the fish is hooked - # In this mode, vanilla loots are not available unless you add them to the loot system! - # 是否在鱼咬钩后立刻显示捕鱼条,而不是需要右键后才显示 - # 注意:启用本设置会导致无法获取原版钓鱼战利品 - instant-bar: false - - # other loots - # 其他战利品 - other-loots: - - # Vanilla loots - # 原版战利品 - vanilla: - enable: true - # 0.4 indicates that 40% of the loots are vanilla white the rest are from CustomFishing Loot system - # If there's no custom loot, it would definitely be a vanilla loot - # 0.4代表40%的战利品来自于原版,60%来自CustomFishing物品库 - # 如果钓鱼的地方没有自定义战利品,那么下一个一定是原版战利品 - ratio: 0.4 - - # mcMMO loots - # mcMMO战利品 - mcMMO: - # mcMMO treasure system - # Chance represents the opportunity to **try** and become a treasure of mcMMO - # mcMMO宝藏系统 - # 概率代表尝试变成mcMMO宝藏的概率,但这不意味着50%概率一定会变成mcMMO宝藏 - enable: false - chance: 0.5 - - # Does the special fishing mechanic requires special rod - # 是否需要特殊鱼竿才能体验钓鱼机制 - need-special-rod-to-fish: false - - # Does the CustomFishing loots requires special rod - # 是否需要特殊鱼竿才能获取钓鱼插件物品库的内容 - need-special-rod-for-loots: false - - # Do all the rods have the ability to fish in lava - # 任何鱼竿都能在岩浆中钓鱼吗 - all-rods-fish-in-lava: false - - # Does rod lose durability when player successfully fish - # 钓鱼成功后是否消耗耐久度 - rod-lose-durability: true - - # Competition - # 钓鱼比赛 - fishing-competition: - enable: true - # Enable redis server to sync data between servers - # 启用Redis服务器以跨服同步比赛数据 - redis: false - - # Fishing bag is a place where players can store their baits, utils, rods (Fish optional) - # 渔具袋是玩家存放鱼饵,实用道具,鱼竿的地方,其中的鱼饵会在钓鱼时被消耗 - fishing-bag: - enable: true - # Fishing bag window title - # 渔具袋的容器标题 - bag-title: '{player}''s Fishing Bag' - # Can fishing bag store the loots? (Requires add-custom-fishing-tags-to-loots: true) - # 渔具袋是否能存储钓鱼战利品(需要设置add-custom-fishing-tags-to-loots: true) - can-store-loot: false - # Other whitelist-items - # 允许放入渔具袋的其他物品白名单 - whitelist-items: - - fishing_rod - - # Lava fishing settings - # 岩浆钓鱼设置 - lava-fishing: - # ticks - min-wait-time: 100 - max-wait-time: 600 - - # Splash effect when the bobber falls into water - # 鱼钩落水时的水花飞溅效果 - splash-animation: - water: - enable: true - # config the item in utils - item: water_effect - # ticks - time: 25 - lava: - enable: true - item: lava_effect - # ticks - time: 25 - - # Record the statistics of player's fishing results - # 记录玩家的捕鱼数据 - fishing-statistics: - enable: true - - # enable bait animation - # 启用抛出诱饵的动画 - bait-animation: true - -# Titles -# 标题设置 -titles: - success: - enable: true - title: - - 'GG!' - - 'Good Job!' - subtitle: - - 'You caught a {loot}' - - 'Whoa! Nice catch!' - - 'Oh {loot} here we go!' - - 'Let''s see what it is!' - fade: - # ticks - in: 10 - stay: 30 - out: 10 - failure: - enable: true - title: - - 'Be concentrated!' - - 'What a pity!' - - 'Try next time!' - - 'Bad luck' - subtitle: - - 'The fish escaped...' - fade: - in: 10 - stay: 30 - out: 10 - -# Other settings -# 其他设置 -other-settings: - - # Thread pool settings - # 线程池设置 - thread-pool-settings: - # The size of the core Thread pool, that is, the size of the Thread pool when there is no task to execute - # Increase the size of corePoolSize when you are running a large server with many players fishing at the same time - # 核心线程池大小,即在没有任务需要执行的时候线程池的大小 - corePoolSize: 4 - # The maximum number of threads allowed to be created in the Thread pool. The current number of threads in the Thread pool will not exceed this value - # 线程池中允许创建的最大线程数,线程池中的当前线程数目不会超过该值 - maximumPoolSize: 8 - # If a thread is idle for more than this attribute value, it will exit due to timeout - # 如果一个线程处在空闲状态的时间超过了该属性值,就会因为超时而退出(秒) - keepAliveTime: 10 - - # Hide the data saving information - # 隐藏数据保存日志 - hide-data-saving-info: false - - # date format in {date} placeholder - # {date}变量的格式 - date-format: 'yyyy-MM-dd' - - # Event priority: MONITOR HIGHEST HIGH NORMAL LOW LOWEST - # 事件优先级 - event-priority: NORMAL - - # If enabled, players would not be able to get job exp in vanilla way - # 如果启用,玩家则无法通过原版方式获得Jobs经验 - disable-JobsReborn-fishing-exp: false - - # Convert MMOItems' rod into CustomFishing's rod (Plz use capital letters otherwise it would not be converted) - # keep the same key name both in MMOItems and CustomFishing so rods can inherit the bonus of those in CustomFishing - # 将MMOItems中的鱼竿转换为CustomFishing的鱼竿,只需要保持相同的键名即可继承效果 - convert-MMOItems-rods: false - - # Prevent other players to pick up your fishing loot - # This is useful for players to fish in a public area - # 防止其他玩家抢夺捕鱼战利品 - prevent-other-players-pick-up-loot: false - - # Log the earnings of fish on the console - # 后台记录玩家销售鱼类所得金额 - log-earnings: true - - # Set the MMOCore profession name - # MMOCore职业名 - MMOCore-profession-name: 'customfishing' - - # Set the offset characters' unicodes - # 设置左右偏移字符的unicode - offset-characters: - font: customfishing:offset_chars - '1':  - '2':  - '4':  - '8':  - '16':  - '32':  - '64':  - '128':  - '-1':  - '-2':  - '-4':  - '-8':  - '-16':  - '-32':  - '-64':  - '-128':  \ No newline at end of file diff --git a/src/main/resources/contents/categories/default.yml b/src/main/resources/contents/categories/default.yml deleted file mode 100644 index 71b8d971..00000000 --- a/src/main/resources/contents/categories/default.yml +++ /dev/null @@ -1,51 +0,0 @@ -# %fishingstats_amount_% get the number of a certain fish caught -# %fishingstats_hascaught_% return if a player has caught this fish -# %fishingstats_category_total_% get the total number of a certain category's fish caught -# %fishingstats_category_progress_% get the player's exploration of this category of fish -normal_fish: - - tuna_fish - - pike_fish - - gold_fish - - perch_fish - - mullet_fish - - sardine_fish - - carp_fish - - cat_fish - - octopus - - sunfish - - red_snapper_fish - - salmon_void_fish - - woodskip_fish - - sturgeon_fish - -sliver_star_fish: - - tuna_fish_silver_star - - pike_fish_silver_star - - gold_fish_silver_star - - perch_fish_silver_star - - mullet_fish_silver_star - - sardine_fish_silver_star - - carp_fish_silver_star - - cat_fish_silver_star - - octopus_silver_star - - sunfish_silver_star - - red_snapper_fish_silver_star - - salmon_void_fish_silver_star - - woodskip_fish_silver_star - - sturgeon_fish_silver_star - -golden_star_fish: - - tuna_fish_golden_star - - pike_fish_golden_star - - gold_fish_golden_star - - perch_fish_golden_star - - mullet_fish_golden_star - - sardine_fish_golden_star - - carp_fish_golden_star - - cat_fish_golden_star - - octopus_golden_star - - sunfish_golden_star - - red_snapper_fish_golden_star - - salmon_void_fish_golden_star - - woodskip_fish_golden_star - - sturgeon_fish_golden_star \ No newline at end of file diff --git a/src/main/resources/contents/competitions/default.yml b/src/main/resources/contents/competitions/default.yml deleted file mode 100644 index 9e7697b0..00000000 --- a/src/main/resources/contents/competitions/default.yml +++ /dev/null @@ -1,94 +0,0 @@ -example: - # TOTAL_SCORE - # CATCH_AMOUNT - # MAX_SIZE - # TOTAL_SIZE - # RANDOM - goal: CATCH_AMOUNT - - # Optional - # start-weekday: - # - monday - # - sunday - # Optional - # start-date: - # - 1 - # - 7 - # - 14 - # Optional - # Fishing competition can also be started with a command - start-time: - - '8:30' - - '12:30' - - '18:30' - - # Seconds - duration: 300 - - # Min players to start the competition - min-players: 2 - - # Competition information (it will only be shown to participants) - bossbar: - enable: true - color: WHITE - overlay: PROGRESS - # https://docs.adventure.kyori.net/minimessage/format.html - text: - - '[<#87CEFA>🎣] Time Left: <#E6E6FA>{time}s | Your Rank: <#E6E6FA>{rank} | No.1 Player: <#E6E6FA>{1st_player}' - - '[<#87CEFA>🎣] Time Left: <#E6E6FA>{minute}m{second}s | Your Score: <#E6E6FA>{score} | No.1 Score: <#E6E6FA>{1st_score}' - - '[<#87CEFA>🎣] Time Left: <#E6E6FA>{minute}m{second}s | Goal: <#E6E6FA>{goal}' - refresh-rate: 10 - switch-interval: 200 - only-show-to-participants: true - - command: - start: - - 'say [🎣] Competition started! It''s time to fish' - end: - - 'say [🎣] Competition ended! Let''s see the results' - join: - - 'money give {player} 10' - - broadcast: - start: - - '<#D4F2E7>◤─────────────────────────◥' - - '' - - ' [<#87CEFA>🎣] Fishing Competition' - - '' - - ' <#E1FFFF>Objectives:' - - ' <#B0C4DE>Catch as many fish as possible' - - ' <#B0C4DE>Start fishing to participate!' - - '' - - '<#D4F2E7>◣─────────────────────────◢' - # You can add unlimited player rank info by using {x_player} {x_score} - end: - - '<#D4F2E7>◤─────────────────────────◥' - - '' - - ' [<#87CEFA>🎣] Fishing Competition' - - '' - - ' <#E1FFFF>Results:' - - ' No.①: {1_player} - {1_score}' - - ' No.②: {2_player} - {2_score}' - - ' No.③: {3_player} - {3_score}' - - '' - - '<#D4F2E7>◣─────────────────────────◢' - - # You can customize unlimited ranks' rewards by adding ranks like 4,5,6... - prize: - 1: - commands: - - 'money give {player} 200' - messages: - - '<#FF4500>[!] Congratulations! You got the first prize!' - 2: - commands: - - 'money give {player} 100' - 3: - commands: - - 'money give {player} 50' - participation: - messages: - - '<#FF4500>[!] Thanks for participation! This is the reward!' - commands: - - 'money give {player} 10' \ No newline at end of file diff --git a/src/main/resources/contents/enchants/default.yml b/src/main/resources/contents/enchants/default.yml deleted file mode 100644 index c5165c81..00000000 --- a/src/main/resources/contents/enchants/default.yml +++ /dev/null @@ -1,61 +0,0 @@ -# CustomFishing does not contain an enchantment system but it's able to read enchantments from items and customize its bonus! -# Vanilla enchants -minecraft:luck_of_the_sea: - #levels - 1: - effect: - weight-add: - silver: 2 - gold: 1 - 2: - effect: - weight-add: - silver: 3 - gold: 2 - 3: - effect: - weight-add: - silver: 4 - gold: 3 - 4: - effect: - weight-add: - silver: 6 - gold: 5 - # https://mo-mi.gitbook.io/xiaomomi-plugins/plugin-wiki/customfishing/requirements - requirements: - permission: luck_of_the_sea.admin - -# lucky_catch from EcoEnchants -eco:lucky_catch: - 1: - effect: - double-loot: 0.1 - 2: - effect: - double-loot: 0.2 - 3: - effect: - double-loot: 0.3 - -# You can register an enchantment in EcoEnchants called "easy_catch" -# And then create its effects in CustomFishing! -eco:easy_catch: - 1: - effect: - difficulty: -1 - 2: - effect: - difficulty: -2 - -# AdvancedEnchantments support -AE:lucky: - 1: - effect: - double-loot: 0.1 - 2: - effect: - double-loot: 0.2 - 3: - effect: - double-loot: 0.3 \ No newline at end of file diff --git a/src/main/resources/contents/loots/example.yml b/src/main/resources/contents/loots/example.yml deleted file mode 100644 index eb8ed2d5..00000000 --- a/src/main/resources/contents/loots/example.yml +++ /dev/null @@ -1,264 +0,0 @@ -rainbow_fish: - # Enable - # 是否启用 - enable: false - # Disable bar mechanic for a certain loot - # 为某个战利品关闭捕鱼条机制 - disable-bar-mechanic: false - # Disable statistics for a certain loot - # 关闭此物品的数据记录 - disable-stats: true - # Nick is what to show in fish finder and titles - # 昵称将在标题和找鱼器信息中显示 - nick: Example Fish - # Should it be displayed in fish finder? - # 是否能被找鱼器定位 - show-in-fishfinder: false - # Is this loot only available when player fish in lava - # 是否是岩浆鱼 - in-lava: false - # The weight(relative chance) of getting this fish - # 获得此鱼的权重(相对概率) - weight: 10 - # Optional - # The group of this fish - # 鱼所在的组,可以无限自定义,以供效果识别进行权重操作 - group: normal - # The score to get in competition - # 比赛中获取的分数 - score: 10 - # Specify the fish's mini-games - # 指定鱼的小游戏 - mini-game: - - rainbow - - # Basic elements of an item - # You can use MiniMessage format in name & lore - # legacy color code '&' is supported but not recommended - # https://docs.adventure.kyori.net/minimessage/format.html - material: COD - display: - name: Rainbow Fish - lore: - - This is a rainbow fish! - - It is {size}cm long! - custom-model-data: 1 - # 数量 - amount: 1 - - # unbreakable - # 不可破坏 - unbreakable: false - # Optional - # The size of the fish - # 鱼的大小 - size: 10~200 - - # Optional - # The base price and size bonus, and you can customize price formula in sell-fish.yml - price: - base: 50 - bonus: 0.3 - - # Custom NBT tags - # If you are not sure about the NBT tag. You can use command '/customfishing import xxx' - # (Int) (Byte) (String) (Float) (String) (Double) (Short) (Long) (UUID) (Boolean) (IntArray) (ByteArray) - nbt: - itemsadder: - namespace: (String) momirealms - id: (String) rainbow_fish - - # Available events: consume/success/failure/hook/success-times - # Available actions: message/command/exp/mending/skill-xp/sound/potion-effect - action: - consume: - potion_effect_1: - type: potion-effect - value: - type: blindness - amplifier: 1 - duration: 200 - success: - action_message: - type: message - value: - - You got a {loot} lol! - chance: 1.0 - action_command: - type: command - value: - - say Success command example! - chance: 1.0 - action_exp: - type: exp - value: 10 - chance: 1.0 - action_mending: - type: mending - value: 5 - chance: 1.0 - action_skill-xp: - type: skill-xp - value: 100.0 - chance: 1.0 - action_job-xp: - type: job-xp - value: 10.0 - chance: 1.0 - action_sound: - type: sound - value: - source: PLAYER - key: minecraft:block.amethyst_block.break - volume: 1.0 - pitch: 1.0 - failure: - action_message: - type: message - value: - - The fish escaped! - chance: 1.0 - action_command: - type: command - value: - - say Failure command example! - chance: 1.0 - hook: - action_message: - type: message - value: - - The fish is hooked! - chance: 1.0 - action_command: - type: command - value: - - say Hook command example - chance: 1.0 - success-times: - '1': - action_message: - type: message - value: - - This is the first time you caught a rainbow fish! - chance: 1.0 - '100': - action_message: - type: message - value: - - You have caught rainbow fish for 100 times! - chance: 1.0 - - # Enchantments on the item - enchantments: - minecraft:sharpness: 1 - minecraft:flame: 1 - - # Random Durability (only available on damageable items) - random-durability: false - - # Random Enchantments - # Higher level enchantment should be below the lower ones - random-enchantments: - enchantment_1: - enchant: minecraft:sharpness - chance: 0.3 - level: 1 - enchantment_2: - enchant: minecraft:sharpness - chance: 0.2 - level: 2 - enchantment_3: - enchant: minecraft:sharpness - chance: 0.1 - level: 3 - enchantment_4: - enchant: minecraft:flame - chance: 0.5 - level: 1 - enchantment_5: - enchant: minecraft:unbreaking - chance: 0.2 - level: 1 - enchantment_6: - enchant: minecraft:unbreaking - chance: 0.2 - level: 2 - - # - HIDE_ATTRIBUTES - # - HIDE_DESTROYS - # - HIDE_DYE - # - HIDE_PLACED_ON - # - HIDE_UNBREAKABLE - # - HIDE_POTION_EFFECTS - item_flags: - - HIDE_ENCHANTS - - # https://mo-mi.gitbook.io/xiaomomi-plugins/plugin-wiki/customfishing/requirements - requirements: - - # Biome - biome: - - minecraft:plains - - minecraft:taiga - - # Y coordinate - ypos: - - 50~100 - - 150~200 - - # World weather - weather: - - rain - - clear - - thunder - - # Player permission - permission: customfishing.rainbowfish - - # Specified world - world: - - world - - # Game Time Range - time: - - 0~12000 - - # Requires skill plugin - skill-level: 10 - - # Requires job plugin - job-level: 10 - - # Only occurs when there's a competition - competition: true - - # Requires Season Plugin - season: - - Spring - - Autumn - - # Requires PlaceholderAPI - # Create complex condition as you want - # "||" means one of the conditions is true, it would be true - # "&&" means all the conditions must be true to be true - # available types "==" "!=" ">" "<" ">=" "<=" - papi-condition: - '||': - condition_1: - type: == - papi: '%player_world%' - value: world - condition_2: - type: == - papi: '%player_world%' - value: Island - '&&': - condition_1: - type: '>=' - # compare two placeholders - papi: '%player_health%' - value: '%player_y%' - condition_2: - type: < - papi: '%player_health%' - value: 15 diff --git a/src/main/resources/contents/minigames/default.yml b/src/main/resources/contents/minigames/default.yml deleted file mode 100644 index 221ab4db..00000000 --- a/src/main/resources/contents/minigames/default.yml +++ /dev/null @@ -1,110 +0,0 @@ -rainbow: - # limit time to fish (seconds) - time: 15 - # Fishing bar - # The higher the frequency of a bar, the more likely the bar is - bars: - - rainbow_1 - - rainbow_2 - - rainbow_3 - - rainbow_4 - - rainbow_5 - - rainbow_6 - - rainbow_7 - # Available difficulty: 1-10 - # The higher the frequency of a difficulty, the more likely the difficulty is - difficulty: - - 1 - - 2 - - 2 - - 3 - - 3 - - 3 - - 4 - - 4 - - 5 - -mode_1: - time: 15 - bars: - - bar_1 - - bar_2 - - bar_3 - - bar_4 - - bar_5 - - bar_6 - - bar_7 - - bar_8 - - bar_9 - difficulty: - - 1 - - 2 - - 2 - - 2 - - 3 - - 3 - - 3 - - 4 - - 4 - - 4 - - 4 - - 5 - - 5 - - 6 - -mode_2: - time: 30 - bars: - - bar_10 - difficulty: - - 1 - - 1 - - 1 - - 2 - - 2 - - 2 - - 3 - - 3 - - 3 - - 4 - - 4 - - 4 - - 5 - - 5 - - 6 - -mode_3: - time: 30 - bars: - - bar_11 - difficulty: - - 1 - - 1 - - 2 - - 2 - - 2 - - 3 - - 3 - - 3 - - 4 - - 4 - - 4 - - 5 - - 5 - - 6 - -mixed_mini_games: - time: 30 - bars: - - bar_1 - - bar_2 - - bar_3 - - bar_10 - - bar_11 - difficulty: - - 1 - - 2 - - 3 - - 3 - - 4 - - 4 \ No newline at end of file diff --git a/src/main/resources/contents/mobs/default.yml b/src/main/resources/contents/mobs/default.yml deleted file mode 100644 index fe3c6a48..00000000 --- a/src/main/resources/contents/mobs/default.yml +++ /dev/null @@ -1,26 +0,0 @@ -skeletalknight: - - enable: true - - # MythicMobsID - mobID: SkeletalKnight - - # The level of the mob - level: 0 - - # Name is what to show in fish finder - name: skeletalknight - - # This decides how mythic mob spawn - vector: - horizontal: 1.1 - vertical: 1.2 - - group: creature - weight: 10 - - requirements: - weather: - - thunder - world: - - world \ No newline at end of file diff --git a/src/main/resources/contents/utils/fish_finder.yml b/src/main/resources/contents/utils/fish_finder.yml deleted file mode 100644 index 46f635b7..00000000 --- a/src/main/resources/contents/utils/fish_finder.yml +++ /dev/null @@ -1,7 +0,0 @@ -fishfinder: - material: PAPER - display: - name: 'Fish Finder' - lore: - - 'Right click to see what fish can be caught in this place!' - custom-model-data: 50000 diff --git a/src/main/resources/contents/utils/splash_items.yml b/src/main/resources/contents/utils/splash_items.yml deleted file mode 100644 index 45ed531e..00000000 --- a/src/main/resources/contents/utils/splash_items.yml +++ /dev/null @@ -1,6 +0,0 @@ -water_effect: - material: PAPER - custom-model-data: 49998 -lava_effect: - material: PAPER - custom-model-data: 49999 \ No newline at end of file diff --git a/src/main/resources/contents/utils/totem_items.yml b/src/main/resources/contents/utils/totem_items.yml deleted file mode 100644 index 9d6021f2..00000000 --- a/src/main/resources/contents/utils/totem_items.yml +++ /dev/null @@ -1,5 +0,0 @@ -totem_activator: - material: DIAMOND - display: - name: 'Double Loot Fishing Totem Core' - totem: double_loot_fishing_totem \ No newline at end of file diff --git a/src/main/resources/database.yml b/src/main/resources/database.yml deleted file mode 100644 index c66dc8e4..00000000 --- a/src/main/resources/database.yml +++ /dev/null @@ -1,59 +0,0 @@ -config-version: '1' -# YAML/MySQL/MariaDB -# 存储模式 -data-storage-method: YAML - -# Migrate from 1.2 to 1.3 -# 迁移 1.2->1.3 -# This option would automatically be set to false when migration finishes -# 这个选项会在迁移完毕后自动设置为false -migration: false - -# MySQL settings -MySQL: - host: localhost - port: 3306 - user: root - password: password - database: minecraft - table-prefix: customfishing - properties: - cachePrepStmts: 'true' - prepStmtCacheSize: '250' - prepStmtCacheSqlLimit: '2048' - useSSL: 'false' - verifyServerCertificate: 'false' - Pool-Settings: - maximum-pool-size: 10 - minimum-idle: 10 - maximum-lifetime: 180000 - idle-timeout: 60000 - -MariaDB: - host: localhost - port: 3306 - user: root - password: password - database: minecraft - table-prefix: customfishing - properties: - cachePrepStmts: 'true' - prepStmtCacheSize: '250' - prepStmtCacheSqlLimit: '2048' - Pool-Settings: - maximum-pool-size: 10 - minimum-idle: 10 - maximum-lifetime: 180000 - idle-timeout: 60000 - -# Redis server -# Sync competition scores between servers without lag! -Redis: - host: localhost - #password: 123456 - port: 6379 - MaxTotal: 10 - MaxIdle: 10 - MinIdle: 1 - MaxWaitMillis: 30000 - MinEvictableIdleTimeMillis: 1800000 \ No newline at end of file diff --git a/src/main/resources/messages/messages_english.yml b/src/main/resources/messages/messages_english.yml deleted file mode 100644 index fa3497e3..00000000 --- a/src/main/resources/messages/messages_english.yml +++ /dev/null @@ -1,39 +0,0 @@ -#MiniMessage Format -#https://docs.adventure.kyori.net/minimessage/format.html -messages: - prefix: '[CustomFishing] ' - reload: 'Reloaded. Took {time}ms.' - no-perm: 'You don''t have permission.' - not-online: 'That player is not online.' - item-not-exist: 'That item does not exist.' - player-not-exist: 'That player does not exist.' - escape: 'It has been too long since the fish is hooked. Oh my god, it escaped.' - give-item: 'Successfully given player {Player} {Amount}x {Item}.' - get-item: 'Successfully got {Amount}x {Item}.' - no-console: 'This command cannot be executed from the console.' - wrong-amount: 'You can''t set an negative amount of items.' - lack-args: 'Insufficient arguments.' - none-args: 'Arguments cannot be none.' - invalid-args: 'Invalid arguments.' - possible-loots: 'Possible loots here: ' - split-char: ', ' - hook-other-entity: 'The hook is hooked on another entity.' - reach-sell-limit: 'You have earned too much from selling fish! Come tomorrow.' - no-loot: 'There''s no fish in this place.' - players-not-enough: 'The number of players is not enough for the fishing competition to be started as scheduled.' - force-competition-success: 'Forced to start a fishing competition.' - force-competition-failure: 'The competition does not exist.' - force-competition-end: 'Forced to end the current competition.' - force-competition-cancel: 'Forced to cancel the competition' - no-rod: 'You have to fish with a special rod to get loots.' - no-rank: 'No Rank' - no-player: 'No player' - no-score: 'No score' - set-statistics: 'Successfully set {Player}''s {Loot} statistics to {Amount}.' - reset-statistics: 'Successfully reset {Player}''s statistics.' - negative-statistics: 'Amount should be a value no lower than zero.' - statistics-not-exist: 'The statistics does not exist.' - total_score: 'Total score' - catch_amount: 'Catch amount' - max_size: 'Max size' - total_size: 'Total size' \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml deleted file mode 100644 index 24b89d5f..00000000 --- a/src/main/resources/plugin.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: CustomFishing -version: '${version}' -main: net.momirealms.customfishing.CustomFishing -api-version: 1.17 -authors: [ XiaoMoMi ] -folia-supported: true -depend: - - ProtocolLib -softdepend: - - ItemsAdder - - MythicMobs - - Oraxen - - PlaceholderAPI - - EcoEnchants - - mcMMO - - AureliumSkills - - CustomCrops - - MMOCore - - EcoSkills - - RealisticSeasons - - Jobs - - MMOItems - - eco - - Vault - - BattlePass - - ClueScrolls - - BetonQuest - - AdvancedEnchantments - - EcoJobs - -commands: - customfishing: - usage: /customfishing - description: main command - permission: customfishing.admin - aliases: - - cfishing - fishingbag: - usage: /fishingbag open - description: fishing bag command - sellfish: - usage: /sellfish - description: sell fish command - permission: customfishing.sellfish - -permissions: - customfishing.*: - description: Gives access to all customfishing commands - children: - customfishing.admin: true - customfishing.sellfish: true - customfishing.fishingbag: true - - customfishing.admin: - default: op - customfishing.sellfish: - default: true - fishingbag.rows.1: - default: true - fishingbag.rows.2: - default: false - fishingbag.rows.3: - default: false - fishingbag.rows.4: - default: false - fishingbag.rows.5: - default: false - fishingbag.rows.6: - default: false - fishingbag.open: - default: true \ No newline at end of file diff --git a/src/main/resources/sell-fish.yml b/src/main/resources/sell-fish.yml deleted file mode 100644 index c805cf96..00000000 --- a/src/main/resources/sell-fish.yml +++ /dev/null @@ -1,116 +0,0 @@ -# Container title -# GUI标题 -container-title: 'Sell Fish' - -# GUI行数 -rows: 6 - -# Limit players' daily income -# 限制玩家每日的收入上限 -sell-limitation: - enable: true - upper-limit: 10000 - -# Price formula -# 价格公式 -price-formula: '{base} + {bonus} * {size}' - -# Item price -# 物品出售价格 -item-price: - # Vanilla Items - # 原版物品 - COD: 10 - PUFFERFISH: 10 - SALMON: 10 - TROPICAL_FISH: 10 - # Custom items - # PAPER (CustomModelData: 999) - # 自定义模型物品 - PAPER:999: 5 - -# Sound settings -# 音效设置 -sounds: - open: minecraft:block.chest.open - close: minecraft:block.chest.close - success: minecraft:block.amethyst_block.break - deny: minecraft:block.anvil.destroy - confirm: minecraft:entity.villager.trade - type: player - -# Actions executed for successful sales -# 销售时发生的动作 -actions: - message: - enable: true - text: 'You earned {money}$ from selling the fish! You can still gain {remains}$ from selling fish today' - title: - enable: true - title: 'Success' - subtitle: 'You earned {money}$ from selling the fish' - in: 20 - stay: 40 - out: 20 - actionbar: - enable: true - text: 'You earned {money}$ from selling the fish' - commands: - enable: false - value: - - 'cmi broadcast {player} earned {money}' - -# Functional icons -# 功能性的图标 -functional-icons: - slots: - - 50 - sell: - material: IRON_BLOCK - display: - name: '<#00CED1>Sell the fish' - lore: - - 'You will gain {money}$' - custom-model-data: 1 - deny: - material: REDSTONE_BLOCK - display: - name: 'Denied' - lore: - - 'Nothing to sell!' - custom-model-data: 1 - -# Decorative icons -# Note: AIR is also supported -# 装饰性的图标 -decorative-icons: - glass-pane: - material: BLACK_STAINED_GLASS_PANE - display: - name: ' ' - slots: - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9 - - 10 - - 18 - - 19 - - 27 - - 28 - - 36 - - 37 - - 45 - - 46 - - 47 - - 48 - - 49 - - 51 - - 52 - - 53 - - 54 \ No newline at end of file