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 index 29d52235..78e1c7b5 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/data/PlayerData.java +++ b/api/src/main/java/net/momirealms/customfishing/api/data/PlayerData.java @@ -99,4 +99,8 @@ public class PlayerData { public String getName() { return name; } + + public boolean isLocked() { + return this == LOCKED; + } } 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 index 94f18122..80b4cef4 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/data/StatisticData.java +++ b/api/src/main/java/net/momirealms/customfishing/api/data/StatisticData.java @@ -25,14 +25,23 @@ import java.util.Map; public class StatisticData { - @SerializedName("map") - public Map statisticMap; + @SerializedName(value="amount", alternate={"map"}) + public Map amountMap; - public StatisticData(@NotNull Map data) { - this.statisticMap = data; + @SerializedName("size") + public Map sizeMap; + + public StatisticData() { + this.sizeMap = new HashMap<>(); + this.amountMap = new HashMap<>(); + } + + public StatisticData(@NotNull Map amount, @NotNull Map size) { + this.amountMap = amount; + this.sizeMap = size; } public static StatisticData empty() { - return new StatisticData(new HashMap<>()); + return new StatisticData(); } } 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 index c6073ce1..699bd495 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/MarketManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/MarketManager.java @@ -20,6 +20,8 @@ package net.momirealms.customfishing.api.manager; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import java.util.Map; + public interface MarketManager { /** @@ -56,12 +58,9 @@ public interface MarketManager { /** * Calculates the price based on a formula with provided variables. * - * @param base The base value for the formula. - * @param bonus The bonus value for the formula. - * @param size The size value for the formula. * @return The calculated price based on the formula and provided variables. */ - double getFishPrice(float base, float bonus, float size); + double getFishPrice(Player player, Map vars); /** * Gets the character representing the item slot in the MarketGUI. diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java index 46840904..2f41923a 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java @@ -28,5 +28,6 @@ public enum ActionTrigger { LAND, ACTIVATE, TIMER, - INTERACT + INTERACT, + NEW_SIZE_RECORD } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java index d2b1582c..52de4516 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/CFLoot.java @@ -20,6 +20,7 @@ package net.momirealms.customfishing.api.mechanic.loot; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKey; import org.jetbrains.annotations.NotNull; import java.util.HashMap; @@ -38,6 +39,7 @@ public class CFLoot implements Loot { private double score; private String[] lootGroup; private String filePath; + private StatisticsKey statisticsKey; public CFLoot(String id, LootType type) { this.id = id; @@ -149,6 +151,17 @@ public class CFLoot implements Loot { return this; } + /** + * Set the statistics key for this loot + * + * @param statisticsKey statistics key + * @return The builder. + */ + public Builder statsKey(StatisticsKey statisticsKey) { + this.loot.statisticsKey = statisticsKey; + return this; + } + /** * Add actions triggered by a specific trigger. * @@ -245,6 +258,11 @@ public class CFLoot implements Loot { return this.nick; } + @Override + public StatisticsKey getStatisticKey() { + return this.statisticsKey; + } + /** * Check if this loot should be shown in the finder. * diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java index eb203c67..aa678e38 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/Loot.java @@ -20,6 +20,7 @@ package net.momirealms.customfishing.api.mechanic.loot; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKey; import org.jetbrains.annotations.NotNull; import java.util.HashMap; @@ -55,6 +56,8 @@ public interface Loot { @NotNull String getNick(); + StatisticsKey getStatisticKey(); + /** * Check if this loot should be shown in the finder. * diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java index eeb149ba..081fb28e 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/Statistics.java @@ -32,6 +32,7 @@ import java.util.concurrent.ConcurrentHashMap; public class Statistics { private final ConcurrentHashMap statisticMap; + private final ConcurrentHashMap sizeMap; private int total; /** @@ -40,7 +41,8 @@ public class Statistics { * @param statisticData The initial statistic data. */ public Statistics(StatisticData statisticData) { - this.statisticMap = new ConcurrentHashMap<>(statisticData.statisticMap); + this.statisticMap = new ConcurrentHashMap<>(statisticData.amountMap); + this.sizeMap = new ConcurrentHashMap<>(statisticData.sizeMap); this.total = statisticMap.values().stream().mapToInt(Integer::intValue).sum(); } @@ -52,14 +54,17 @@ public class Statistics { * @param amount The amount of loot to add. */ public synchronized void addLootAmount(Loot loot, Condition condition, int amount) { + if (amount < 1) { + return; + } if (amount == 1) { addSingleLootAmount(loot, condition); return; } - Integer previous = statisticMap.get(loot.getID()); + Integer previous = statisticMap.get(loot.getStatisticKey().getAmountKey()); if (previous == null) previous = 0; int after = previous + amount; - statisticMap.put(loot.getID(), after); + statisticMap.put(loot.getStatisticKey().getAmountKey(), after); total += amount; doSuccessTimesAction(previous, after, condition, loot); } @@ -85,6 +90,13 @@ public class Statistics { } } + public boolean setSizeIfHigher(String loot, float size) { + float previous = sizeMap.getOrDefault(loot, 0f); + if (previous >= size) return false; + sizeMap.put(loot, size); + return true; + } + /** * Adds a single loot amount to the statistics. * @@ -111,8 +123,11 @@ public class Statistics { * @return The amount of the specified loot item. */ public int getLootAmount(String key) { - Integer amount = statisticMap.get(key); - return amount == null ? 0 : amount; + return statisticMap.getOrDefault(key, 0); + } + + public float getSizeRecord(String key) { + return sizeMap.getOrDefault(key, 0f); } /** @@ -132,6 +147,10 @@ public class Statistics { return statisticMap; } + public ConcurrentHashMap getSizeMap() { + return sizeMap; + } + /** * Sets data for a specific key in the statistics. * diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/StatisticsKey.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/StatisticsKey.java new file mode 100644 index 00000000..6d3c1b16 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/statistic/StatisticsKey.java @@ -0,0 +1,20 @@ +package net.momirealms.customfishing.api.mechanic.statistic; + +public class StatisticsKey { + + private final String amountKey; + private final String sizeKey; + + public StatisticsKey(String amountKey, String sizeKey) { + this.amountKey = amountKey; + this.sizeKey = sizeKey; + } + + public String getAmountKey() { + return amountKey; + } + + public String getSizeKey() { + return sizeKey; + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 0056509e..cac05f19 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { allprojects { - version = "2.0.8" + version = "2.0.9" apply() apply(plugin = "java") diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java index 220825c8..6489115e 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java @@ -149,10 +149,8 @@ public class IntegrationManagerImpl implements IntegrationManager { hookMessage("ClueScrolls"); } if (plugin.isHookedPluginEnabled("BetonQuest")) { - if (Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("BetonQuest")).getPluginMeta().getVersion().startsWith("2")) { - BetonQuestHook.register(); - hookMessage("BetonQuest"); - } + BetonQuestHook.register(); + hookMessage("BetonQuest"); } // if (plugin.isHookedPluginEnabled("NotQuests")) { // NotQuestHook notQuestHook = new NotQuestHook(); diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/StatisticsPapi.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/StatisticsPapi.java index 28221e43..7310262c 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/StatisticsPapi.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/StatisticsPapi.java @@ -82,6 +82,9 @@ public class StatisticsPapi extends PlaceholderExpansion { if (split.length == 1) return "Invalid format"; return String.valueOf(statistics.getLootAmount(split[1])); } + case "size-record" -> { + return String.format("%.2f", statistics.getSizeRecord(split[1])); + } case "category" -> { if (split.length == 1) return "Invalid format"; String[] categorySplit = split[1].split("_", 2); diff --git a/plugin/src/main/java/net/momirealms/customfishing/gui/icon/property/requirement/RequirementEditorIcon.java b/plugin/src/main/java/net/momirealms/customfishing/gui/icon/property/requirement/RequirementEditorIcon.java deleted file mode 100644 index 642145cd..00000000 --- a/plugin/src/main/java/net/momirealms/customfishing/gui/icon/property/requirement/RequirementEditorIcon.java +++ /dev/null @@ -1,48 +0,0 @@ -package net.momirealms.customfishing.gui.icon.property.requirement; - -import net.momirealms.customfishing.adventure.AdventureManagerImpl; -import net.momirealms.customfishing.adventure.component.ShadedAdventureComponentWrapper; -import net.momirealms.customfishing.gui.SectionPage; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.jetbrains.annotations.NotNull; -import xyz.xenondevs.invui.item.ItemProvider; -import xyz.xenondevs.invui.item.builder.ItemBuilder; -import xyz.xenondevs.invui.item.impl.AbstractItem; - -public class RequirementEditorIcon extends AbstractItem { - - private final SectionPage sectionPage; - private final String sectionName; - - public RequirementEditorIcon(SectionPage sectionPage, String requirementSectionName) { - this.sectionPage = sectionPage; - this.sectionName = requirementSectionName; - } - - @Override - public ItemProvider getItemProvider() { - ItemBuilder itemBuilder = new ItemBuilder(Material.COMPASS) - .setDisplayName(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage( - "<#B0E0E6>● Requirements" - ))) - .addLoreLines("") - .addLoreLines(new ShadedAdventureComponentWrapper(AdventureManagerImpl.getInstance().getComponentFromMiniMessage( - "<#00FF7F> -> Click to edit requirements" - ))); - - return itemBuilder; - } - - @Override - public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) { - ConfigurationSection reqSection = sectionPage.getSection().getConfigurationSection(sectionName); - if (reqSection == null) - reqSection = sectionPage.getSection().createSection(sectionName); - - - } -} diff --git a/plugin/src/main/java/net/momirealms/customfishing/gui/page/requirement/RequirementEditor.java b/plugin/src/main/java/net/momirealms/customfishing/gui/page/requirement/RequirementEditor.java deleted file mode 100644 index 697dbc6b..00000000 --- a/plugin/src/main/java/net/momirealms/customfishing/gui/page/requirement/RequirementEditor.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.momirealms.customfishing.gui.page.requirement; - -import net.momirealms.customfishing.gui.SectionPage; -import org.bukkit.entity.Player; - -public class RequirementEditor { - - private Player player; - private SectionPage sectionPage; - - public RequirementEditor(Player player, SectionPage sectionPage) { - this.player = player; - this.sectionPage = sectionPage; - } - - -} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java index cd4da07d..9af10e3a 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/competition/Competition.java @@ -79,7 +79,6 @@ public class Competition implements FishingCompetition { this.progress = 1; this.remainingTime = config.getDurationInSeconds(); this.startTime = Instant.now().getEpochSecond(); - this.updatePublicPlaceholders(); this.arrangeTimerTask(); if (config.getBossBarConfig() != null) { @@ -99,6 +98,9 @@ public class Competition implements FishingCompetition { } } + this.ranking.clear(); + this.updatePublicPlaceholders(); + CompetitionEvent competitionStartEvent = new CompetitionEvent(CompetitionEvent.State.START, this); Bukkit.getPluginManager().callEvent(competitionStartEvent); } 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 index 4d12d973..9c2a96f7 100644 --- 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 @@ -20,6 +20,7 @@ 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.setting.CFConfig; import net.momirealms.customfishing.storage.method.database.nosql.RedisManager; import redis.clients.jedis.Jedis; import redis.clients.jedis.resps.Tuple; @@ -35,7 +36,7 @@ public class RedisRankingImpl implements Ranking { @Override public void clear() { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - jedis.zremrangeByRank("cf_competition",0,-1); + jedis.del("cf_competition_" + CFConfig.serverGroup); } } @@ -48,7 +49,7 @@ public class RedisRankingImpl implements Ranking { @Override public CompetitionPlayer getCompetitionPlayer(String player) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - Double score = jedis.zscore("cf_competition", player); + Double score = jedis.zscore("cf_competition_" + CFConfig.serverGroup, player); if (score == null || score == 0) return null; return new CompetitionPlayer(player, Float.parseFloat(score.toString())); } @@ -57,7 +58,7 @@ public class RedisRankingImpl implements Ranking { @Override public CompetitionPlayer getCompetitionPlayer(int rank) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - List player = jedis.zrevrangeWithScores("cf_competition", rank - 1, rank -1); + List player = jedis.zrevrangeWithScores("cf_competition_" + CFConfig.serverGroup, rank - 1, rank -1); if (player == null || player.size() == 0) return null; return new CompetitionPlayer(player.get(0).getElement(), player.get(0).getScore()); } @@ -66,14 +67,14 @@ public class RedisRankingImpl implements Ranking { @Override public void addPlayer(CompetitionPlayer competitionPlayer) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - jedis.zincrby("cf_competition", competitionPlayer.getScore(), competitionPlayer.getPlayer()); + jedis.zincrby("cf_competition_" + CFConfig.serverGroup, competitionPlayer.getScore(), competitionPlayer.getPlayer()); } } @Override public void removePlayer(String player) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - jedis.del("cf_competition", player); + jedis.zrem("cf_competition_" + CFConfig.serverGroup, player); } } @@ -85,7 +86,7 @@ public class RedisRankingImpl implements Ranking { @Override public Iterator> getIterator() { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - List players = jedis.zrevrangeWithScores("cf_competition", 0, -1); + List players = jedis.zrevrangeWithScores("cf_competition_" + CFConfig.serverGroup, 0, -1); return players.stream().map(it -> Pair.of(it.getElement(), it.getScore())).toList().iterator(); } } @@ -98,7 +99,7 @@ public class RedisRankingImpl implements Ranking { @Override public int getSize() { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - long size = jedis.zcard("cf_competition"); + long size = jedis.zcard("cf_competition_" + CFConfig.serverGroup); return (int) size; } } @@ -112,7 +113,7 @@ public class RedisRankingImpl implements Ranking { @Override public int getPlayerRank(String player) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - Long rank = jedis.zrevrank("cf_competition", player); + Long rank = jedis.zrevrank("cf_competition_" + CFConfig.serverGroup, player); if (rank == null) return -1; return (int) (rank + 1); @@ -128,7 +129,7 @@ public class RedisRankingImpl implements Ranking { @Override public double getPlayerScore(String player) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - Double rank = jedis.zscore("cf_competition", player); + Double rank = jedis.zscore("cf_competition_" + CFConfig.serverGroup, player); if (rank == null) return 0; return rank.floatValue(); @@ -144,7 +145,7 @@ public class RedisRankingImpl implements Ranking { @Override public void refreshData(String player, double score) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - jedis.zincrby("cf_competition", score, player); + jedis.zincrby("cf_competition_" + CFConfig.serverGroup, score, player); } } @@ -157,7 +158,7 @@ public class RedisRankingImpl implements Ranking { @Override public void setData(String player, double score) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - jedis.zadd("cf_competition", score, player); + jedis.zadd("cf_competition_" + CFConfig.serverGroup, score, player); } } @@ -170,7 +171,7 @@ public class RedisRankingImpl implements Ranking { @Override public String getPlayerAt(int rank) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - List player = jedis.zrevrange("cf_competition", rank - 1, rank -1); + List player = jedis.zrevrange("cf_competition_" + CFConfig.serverGroup, rank - 1, rank -1); if (player == null || player.size() == 0) return null; return player.get(0); } @@ -185,7 +186,7 @@ public class RedisRankingImpl implements Ranking { @Override public double getScoreAt(int rank) { try (Jedis jedis = RedisManager.getInstance().getJedis()) { - List players = jedis.zrevrangeWithScores("cf_competition", rank - 1, rank -1); + List players = jedis.zrevrangeWithScores("cf_competition_" + CFConfig.serverGroup, 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/fishing/FishingManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java index 22fa3db6..8d262725 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java @@ -678,37 +678,33 @@ public class FishingManagerImpl implements Listener, FishingManager { if (scoreStr != null) { competition.refreshData(player, Double.parseDouble(scoreStr)); } else { + double score = 0; switch (competition.getGoal()) { case CATCH_AMOUNT -> { - fishingPreparation.insertArg("{score}", "1.00"); - competition.refreshData(player, 1); - fishingPreparation.insertArg("{SCORE}", "1"); + score = 1; + competition.refreshData(player, score); } case MAX_SIZE, TOTAL_SIZE -> { String size = fishingPreparation.getArg("{SIZE}"); if (size != null) { - double score = Double.parseDouble(size); - fishingPreparation.insertArg("{score}", String.format("%.2f", score)); + score = Double.parseDouble(size); competition.refreshData(player, score); - fishingPreparation.insertArg("{SCORE}", size); } else { - fishingPreparation.insertArg("{score}", String.format("%.2f", 0.00)); - fishingPreparation.insertArg("{SCORE}", "0"); + score = 0; } } case TOTAL_SCORE -> { - double score = loot.getScore(); - if (score != 0) { - double finalScore = score * effect.getScoreMultiplier() + effect.getScore(); - fishingPreparation.insertArg("{score}", String.format("%.2f", finalScore)); - competition.refreshData(player, finalScore); - fishingPreparation.insertArg("{SCORE}", String.valueOf(finalScore)); + score = loot.getScore(); + if (score > 0) { + score = score * effect.getScoreMultiplier() + effect.getScore(); + competition.refreshData(player, score); } else { - fishingPreparation.insertArg("{score}", "0.00"); - fishingPreparation.insertArg("{SCORE}", "0"); + score = 0; } } } + fishingPreparation.insertArg("{score}", String.format("%.2f", score)); + fishingPreparation.insertArg("{SCORE}", String.valueOf(score)); } } @@ -726,7 +722,15 @@ public class FishingManagerImpl implements Listener, FishingManager { Optional.ofNullable( plugin.getStatisticsManager() .getStatistics(player.getUniqueId()) - ).ifPresent(it -> it.addLootAmount(loot, fishingPreparation, 1)); + ).ifPresent(it -> { + it.addLootAmount(loot, fishingPreparation, 1); + String size = fishingPreparation.getArg("{SIZE}"); + if (size != null) + if (it.setSizeIfHigher(loot.getStatisticKey().getSizeKey(), Float.parseFloat(size))) { + GlobalSettings.triggerLootActions(ActionTrigger.NEW_SIZE_RECORD, fishingPreparation); + loot.triggerActions(ActionTrigger.NEW_SIZE_RECORD, fishingPreparation); + } + }); } /** diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java index 780a0851..1e1be169 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/HookCheckTimerTask.java @@ -188,6 +188,10 @@ public class HookCheckTimerTask implements Runnable { fishingPreparation.insertArg("{x}", String.valueOf(fishHook.getLocation().getBlockX())); fishingPreparation.insertArg("{y}", String.valueOf(fishHook.getLocation().getBlockY())); fishingPreparation.insertArg("{z}", String.valueOf(fishHook.getLocation().getBlockZ())); + if (!nextLoot.disableStats()) { + fishingPreparation.insertArg("{statistics_size}", nextLoot.getStatisticKey().getSizeKey()); + fishingPreparation.insertArg("{statistics_amount}", nextLoot.getStatisticKey().getAmountKey()); + } CustomFishingPlugin.get().getScheduler().runTaskAsync(() -> manager.setTempFishingState(fishingPreparation.getPlayer(), new TempFishingState( initialEffect, fishingPreparation, 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 index 7bcc4a1b..fe0ed915 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java @@ -727,19 +727,13 @@ public class ItemManagerImpl implements ItemManager, Listener { public ItemBuilder price(float base, float bonus) { if (base == 0 && bonus == 0) return this; editors.put("price", (player, nbtItem, placeholders) -> { - if (base != 0) { - placeholders.put("{base}", String.format("%.2f", base)); - placeholders.put("{BASE}", String.valueOf(base)); - } - if (bonus != 0) { - placeholders.put("{bonus}", String.format("%.2f", bonus)); - placeholders.put("{BONUS}", String.valueOf(bonus)); - } - float size = Float.parseFloat(placeholders.getOrDefault("{SIZE}", "0")); + placeholders.put("{base}", String.format("%.2f", base)); + placeholders.put("{BASE}", String.valueOf(base)); + placeholders.put("{bonus}", String.format("%.2f", bonus)); + placeholders.put("{BONUS}", String.valueOf(bonus)); double price = CustomFishingPlugin.get().getMarketManager().getFishPrice( - base, - bonus, - size + player, + placeholders ); nbtItem.setDouble("Price", price); placeholders.put("{price}", String.format("%.2f", price)); diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java index b221a6a2..90883372 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/loot/LootManagerImpl.java @@ -26,6 +26,7 @@ import net.momirealms.customfishing.api.mechanic.loot.CFLoot; import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.api.mechanic.loot.WeightModifier; +import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKey; import net.momirealms.customfishing.api.util.LogUtils; import net.momirealms.customfishing.api.util.WeightUtils; import net.momirealms.customfishing.mechanic.requirement.RequirementManagerImpl; @@ -273,6 +274,7 @@ public class LootManagerImpl implements LootManager { .nick(section.getString("nick", section.getString("display.name", key))) .addActions(plugin.getActionManager().getActionMap(section.getConfigurationSection("events"))) .addTimesActions(plugin.getActionManager().getTimesActionMap(section.getConfigurationSection("events.success-times"))) + .statsKey(new StatisticsKey(section.getString("statistics.amount", key), section.getString("statistics.size", key))) .build(); } } 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 index fcddced6..f70beb66 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/market/MarketManagerImpl.java @@ -429,20 +429,11 @@ public class MarketManagerImpl implements MarketManager, Listener { /** * Calculates the price based on a formula with provided variables. * - * @param base The base value for the formula. - * @param bonus The bonus value for the formula. - * @param size The size value for the formula. * @return The calculated price based on the formula and provided variables. */ @Override - public double getFishPrice(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(); + public double getFishPrice(Player player, Map vars) { + return ConfigUtils.getExpressionValue(player, formula, vars); } /** diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java index 1d0424f2..d7bf6514 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java @@ -213,6 +213,8 @@ public class RequirementManagerImpl implements RequirementManager { this.registerListRequirement(); this.registerEnvironmentRequirement(); this.registerPotionEffectRequirement(); + this.registerSizeRequirement(); + this.registerHasStatsRequirement(); } public HashMap getLootWithWeight(Condition condition) { @@ -1044,6 +1046,35 @@ public class RequirementManagerImpl implements RequirementManager { }); } + private void registerSizeRequirement() { + registerRequirement("has-size", (args, actions, advanced) -> { + boolean has = (boolean) args; + return condition -> { + String size = condition.getArg("{SIZE}"); + if (size != null && has) return true; + if (size == null && !has) return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + + private void registerHasStatsRequirement() { + registerRequirement("has-stats", (args, actions, advanced) -> { + boolean has = (boolean) args; + return condition -> { + String loot = condition.getArg("{loot}"); + Loot lootInstance = plugin.getLootManager().getLoot(loot); + if (lootInstance != null) { + if (!lootInstance.disableStats() && has) return true; + if (lootInstance.disableStats() && !has) return true; + } + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + private void registerEnvironmentRequirement() { registerRequirement("environment", (args, actions, advanced) -> { List environments = ConfigUtils.stringListArgs(args); diff --git a/plugin/src/main/java/net/momirealms/customfishing/setting/CFConfig.java b/plugin/src/main/java/net/momirealms/customfishing/setting/CFConfig.java index 992ac045..5a980022 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/setting/CFConfig.java +++ b/plugin/src/main/java/net/momirealms/customfishing/setting/CFConfig.java @@ -80,7 +80,7 @@ public class CFConfig { // Competition public static boolean redisRanking; - public static List serverGroup; + public static String serverGroup; public static int placeholderLimit; // Data save interval @@ -163,7 +163,7 @@ public class CFConfig { redisRanking = config.getBoolean("mechanics.competition.redis-ranking", false); placeholderLimit = config.getInt("mechanics.competition.placeholder-limit", 3); - serverGroup = ConfigUtils.stringListArgs(config.get("mechanics.competition.server-group","default")); + serverGroup = config.getString("mechanics.competition.server-group","default"); dataSaveInterval = config.getInt("other-settings.data-saving-interval", 600); logDataSaving = config.getBoolean("other-settings.log-data-saving", true); diff --git a/plugin/src/main/java/net/momirealms/customfishing/storage/StorageManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/storage/StorageManagerImpl.java index 86dd9d82..bf48ec47 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/storage/StorageManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/StorageManagerImpl.java @@ -200,7 +200,7 @@ public class StorageManagerImpl implements StorageManager, Listener { return CompletableFuture.completedFuture(Optional.empty()); } PlayerData data = optionalUser.get(); - if (data == PlayerData.LOCKED) { + if (data.isLocked()) { return CompletableFuture.completedFuture(Optional.of(OfflineUserImpl.LOCKED_USER)); } else { OfflineUser offlineUser = new OfflineUserImpl(uuid, data.getName(), data); @@ -343,7 +343,7 @@ public class StorageManagerImpl implements StorageManager, Listener { // Data should not be empty if (optionalData.isEmpty()) return; - if (optionalData.get() == PlayerData.LOCKED) { + if (optionalData.get().isLocked()) { waitForDataLockRelease(uuid, times + 1); } else { putDataInCache(player, optionalData.get()); 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 index 50ce5f6a..cc2541e6 100644 --- 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 @@ -184,7 +184,7 @@ public abstract class AbstractHikariDatabase extends AbstractSQLDatabase impleme .map(element -> element.split(":")) .filter(pair -> pair.length == 2) .collect(Collectors.toMap(pair -> pair[0], pair -> Integer.parseInt(pair[1]))); - builder.setStats(new StatisticData(amountMap)); + builder.setStats(new StatisticData(amountMap, new HashMap<>())); } else { builder.setStats(StatisticData.empty()); } 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 index 4d67a8aa..e3ac1db4 100644 --- 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 @@ -63,12 +63,13 @@ public class YAMLImpl extends AbstractStorage implements LegacyDataStorageInterf File dataFile = getPlayerDataFile(uuid); if (!dataFile.exists()) { if (Bukkit.getPlayer(uuid) != null) { - return CompletableFuture.completedFuture(Optional.of(PlayerData.LOCKED)); - } else { return CompletableFuture.completedFuture(Optional.of(PlayerData.empty())); + } else { + return CompletableFuture.completedFuture(Optional.empty()); } } 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"))) @@ -87,8 +88,13 @@ public class YAMLImpl extends AbstractStorage implements LegacyDataStorageInterf 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()); + ConfigurationSection amountSection = section.createSection("amount"); + ConfigurationSection sizeSection = section.createSection("size"); + for (Map.Entry entry : playerData.getStatistics().amountMap.entrySet()) { + amountSection.set(entry.getKey(), entry.getValue()); + } + for (Map.Entry entry : playerData.getStatistics().sizeMap.entrySet()) { + sizeSection.set(entry.getKey(), entry.getValue()); } try { data.save(getPlayerDataFile(uuid)); @@ -125,15 +131,24 @@ public class YAMLImpl extends AbstractStorage implements LegacyDataStorageInterf * @return The parsed StatisticData object. */ private 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); + HashMap amountMap = new HashMap<>(); + HashMap sizeMap = new HashMap<>(); + if (section == null) { + return new StatisticData(amountMap, sizeMap); } + ConfigurationSection amountSection = section.getConfigurationSection("amount"); + if (amountSection != null) { + for (Map.Entry entry : amountSection.getValues(false).entrySet()) { + amountMap.put(entry.getKey(), (Integer) entry.getValue()); + } + } + ConfigurationSection sizeSection = section.getConfigurationSection("size"); + if (sizeSection != null) { + for (Map.Entry entry : sizeSection.getValues(false).entrySet()) { + sizeMap.put(entry.getKey(), ((Double) entry.getValue()).floatValue()); + } + } + return new StatisticData(amountMap, sizeMap); } @Override @@ -159,7 +174,7 @@ public class YAMLImpl extends AbstractStorage implements LegacyDataStorageInterf map.put(entry.getKey(), integer); } } - builder.setStats(new StatisticData(map)); + builder.setStats(new StatisticData(map, new HashMap<>())); } else { builder.setStats(StatisticData.empty()); } 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 index 94d0d1d9..0380e204 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/storage/user/OfflineUserImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/storage/user/OfflineUserImpl.java @@ -119,7 +119,7 @@ public class OfflineUserImpl implements OfflineUser { return new PlayerData.Builder() .setBagData(new InventoryData(InventoryUtils.stacksToBase64(holder.getInventory().getStorageContents()), holder.getInventory().getSize())) .setEarningData(earningData) - .setStats(new StatisticData(statistics.getStatisticMap())) + .setStats(new StatisticData(statistics.getStatisticMap(), statistics.getSizeMap())) .setName(name) .build(); } diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml index c6287879..8531c0ae 100644 --- a/plugin/src/main/resources/config.yml +++ b/plugin/src/main/resources/config.yml @@ -45,7 +45,46 @@ mechanics: hook: {} bait: {} loot: + new_size_record: + conditional_size_record_action: + type: conditional + value: + conditions: + has-stats: true + actions: + actionbar_action: + type: actionbar + value: '<#FFD700>[New Record] <#FFFFF0>You caught a(n) {nick} which is <#FFA500>{size}cm long!' + sound_action: + type: sound + value: + key: "minecraft:block.note_block.cow_bell" + source: 'player' + volume: 1 + pitch: 1 + delayed_sound: + type: delay + value: + delay: 2 + actions: + sound_action: + type: sound + value: + key: "minecraft:block.note_block.bell" + source: 'player' + volume: 1 + pitch: 1 success: + conditional_size_info_action: + type: conditional + value: + conditions: + has-size: true + has-stats: true + actions: + actionbar_action: + type: actionbar + value: 'You caught a(n) {nick} which is <#F5F5F5>{size}cm long! <#C0C0C0>(Best record: {record}cm)' title_action: type: random-title value: @@ -53,7 +92,7 @@ mechanics: - 'GG!' - 'Good Job!' subtitles: - - 'You caught a {nick}' + - 'You caught a(n) {nick}' - 'Whoa! Nice catch!' - 'Oh {nick} here we go!' - 'Let''s see what it is!' @@ -191,6 +230,8 @@ other-settings: # Requires PlaceholderAPI to work placeholder-register: + '{record}': '%fishingstats_size-record_{loot}%' + # Requires server expansion '{date}': '%server_time_yyyy-MM-dd-HH:mm:ss%' # CustomFishing supports using items/blocks from other plugins diff --git a/plugin/src/main/resources/contents/item/default.yml b/plugin/src/main/resources/contents/item/default.yml index 6f96bcba..6dcc2b50 100644 --- a/plugin/src/main/resources/contents/item/default.yml +++ b/plugin/src/main/resources/contents/item/default.yml @@ -4,6 +4,8 @@ # customized configurations based on your own ideas, # allowing players to experience the uniqueness of your server. +# https://mo-mi.gitbook.io/xiaomomi-plugins/plugin-wiki/customfishing/loot/item + # Vanilla loots settings vanilla: show-in-fishfinder: false @@ -131,6 +133,7 @@ sharpness_book: tag: false material: enchanted_book group: enchantments + nick: "" show-in-fishfinder: false disable-stat: true random-stored-enchantments: @@ -159,6 +162,7 @@ efficiency_book: material: enchanted_book group: enchantments show-in-fishfinder: false + nick: "" disable-stat: true random-stored-enchantments: lv5: @@ -186,6 +190,7 @@ unbreaking_book: material: enchanted_book group: enchantments show-in-fishfinder: false + nick: "" disable-stat: true random-stored-enchantments: lv3: @@ -205,6 +210,7 @@ protection_book: material: enchanted_book group: enchantments show-in-fishfinder: false + nick: "" disable-stat: true random-stored-enchantments: lv4: @@ -226,7 +232,6 @@ protection_book: # Fish tuna_fish: material: cod - nick: Tuna Fish display: name: Tuna Fish lore: @@ -292,7 +297,6 @@ tuna_fish_golden_star: bonus: 0.7 pike_fish: material: cod - nick: Pike Fish display: name: Pike Fish lore: @@ -506,7 +510,6 @@ perch_fish_golden_star: bonus: 3 mullet_fish: material: cod - nick: Mullet Fish display: name: Mullet Fish lore: @@ -575,7 +578,6 @@ mullet_fish_golden_star: bonus: 1.5 sardine_fish: material: cod - nick: Sardine Fish display: name: Sardine Fish lore: @@ -642,7 +644,6 @@ sardine_fish_golden_star: bonus: 3.4 carp_fish: material: cod - nick: Carp Fish display: name: Carp Fish lore: @@ -772,7 +773,6 @@ cat_fish_golden_star: bonus: 2.2 octopus: material: cod - nick: Octopus display: name: Octopus lore: @@ -839,9 +839,8 @@ octopus_golden_star: bonus: 1.5 sunfish: material: cod - nick: <#F5DEB3>Sunfish display: - name: <#F5DEB3>Sunfish + name: <#F5DEB3>Sunfish lore: - It only has one huge head - 'size: {size}cm' @@ -971,8 +970,6 @@ red_snapper_fish_golden_star: bonus: 2.3 salmon_void_fish: material: cod - in-lava: true - nick: Void Salmon display: name: Void Salmon lore: @@ -993,10 +990,9 @@ salmon_void_fish: bonus: 2.4 salmon_void_fish_silver_star: show-in-fishfinder: false - in-lava: true material: cod display: - name: Void Salmon<#F5F5F5>(Silver Star) + name: Void Salmon <#F5F5F5>(Silver Star) lore: - A fish from the hell - It's looking at you... @@ -1017,7 +1013,6 @@ salmon_void_fish_silver_star: bonus: 2.6 salmon_void_fish_golden_star: show-in-fishfinder: false - in-lava: true material: cod display: name: Void Salmon <#FFD700>(Golden Star) @@ -1041,9 +1036,8 @@ salmon_void_fish_golden_star: bonus: 3 woodskip_fish: material: cod - nick: <#CD5C5C>Woodskip Fish display: - name: <#CD5C5C>Woodskip Fish + name: <#CD5C5C>Woodskip Fish lore: - A very sensitive fish that can only - live in pools deep in the forest @@ -1064,7 +1058,7 @@ woodskip_fish_silver_star: show-in-fishfinder: false material: cod display: - name: <#CD5C5C>Woodskip Fish <#F5F5F5>(Silver Star) + name: <#CD5C5C>Woodskip Fish <#F5F5F5>(Silver Star) lore: - A very sensitive fish that can only - live in pools deep in the forest @@ -1087,7 +1081,7 @@ woodskip_fish_golden_star: show-in-fishfinder: false material: cod display: - name: <#CD5C5C>Woodskip Fish <#FFD700>(Golden Star) + name: <#CD5C5C>Woodskip Fish <#FFD700>(Golden Star) lore: - A very sensitive fish that can only - live in pools deep in the forest @@ -1108,9 +1102,8 @@ woodskip_fish_golden_star: bonus: 2.8 sturgeon_fish: material: cod - nick: <#48D1CC>Sturgeon Fish display: - name: <#48D1CC>Sturgeon Fish + name: <#48D1CC>Sturgeon Fish lore: - An ancient bottom-feeder with a dwindling - population. Females can live up to 150 years @@ -1131,7 +1124,7 @@ sturgeon_fish_silver_star: show-in-fishfinder: false material: cod display: - name: <#48D1CC>Sturgeon Fish <#F5F5F5>(Silver Star) + name: <#48D1CC>Sturgeon Fish <#F5F5F5>(Silver Star) lore: - An ancient bottom-feeder with a dwindling - population. Females can live up to 150 years @@ -1154,7 +1147,7 @@ sturgeon_fish_golden_star: show-in-fishfinder: false material: cod display: - name: <#48D1CC>Sturgeon Fish <#FFD700>(Golden Star) + name: <#48D1CC>Sturgeon Fish <#FFD700>(Golden Star) lore: - An ancient bottom-feeder with a dwindling - population. Females can live up to 150 years @@ -1175,7 +1168,6 @@ sturgeon_fish_golden_star: bonus: 10 blue_jellyfish: material: cod - nick: <#87CEFA>Jellyfish display: name: <#87CEFA>Jellyfish lore: @@ -1196,7 +1188,6 @@ blue_jellyfish: blue_jellyfish_silver_star: show-in-fishfinder: false material: cod - nick: <#87CEFA>Jellyfish display: name: <#87CEFA>Jellyfish lore: @@ -1219,7 +1210,6 @@ blue_jellyfish_silver_star: blue_jellyfish_golden_star: show-in-fishfinder: false material: cod - nick: <#87CEFA>Jellyfish display: name: <#87CEFA>Jellyfish lore: @@ -1241,7 +1231,6 @@ blue_jellyfish_golden_star: bonus: 8 pink_jellyfish: material: cod - nick: <#FFC0CB>Jellyfish display: name: <#FFC0CB>Jellyfish lore: @@ -1262,7 +1251,6 @@ pink_jellyfish: pink_jellyfish_silver_star: show-in-fishfinder: false material: cod - nick: <#FFC0CB>Jellyfish display: name: <#FFC0CB>Jellyfish lore: @@ -1285,7 +1273,6 @@ pink_jellyfish_silver_star: pink_jellyfish_golden_star: show-in-fishfinder: false material: cod - nick: <#FFC0CB>Jellyfish display: name: <#FFC0CB>Jellyfish lore: diff --git a/plugin/src/main/resources/market.yml b/plugin/src/main/resources/market.yml index b4fbb5d2..ee0f3acc 100644 --- a/plugin/src/main/resources/market.yml +++ b/plugin/src/main/resources/market.yml @@ -17,7 +17,7 @@ layout: - 'AAAABAAAA' # Price formula (For CustomFishing loots) -price-formula: '{base} + {bonus} * {size}' +price-formula: '{BASE} + {BONUS} * {SIZE}' # Item price (For vanilla items & other plugin items that have CustomModelData) item-price: