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 index fc55dcec..c568e28a 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/PlaceholderManager.java @@ -36,5 +36,7 @@ public interface PlaceholderManager { String parse(@Nullable OfflinePlayer player, String text, Map placeholders); + String parseCacheable(Player player, String text); + List parse(@Nullable OfflinePlayer player, List list, Map replacements); } 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 fea18c92..ad3869b8 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 @@ -21,7 +21,7 @@ public class CFLoot implements Loot { private boolean disableStats; private boolean instanceGame; private double score; - private String lootGroup; + private String[] lootGroup; public CFLoot(String id, LootType type) { this.id = id; @@ -77,8 +77,8 @@ public class CFLoot implements Loot { return this; } - public Builder lootGroup(String group) { - this.loot.lootGroup = group; + public Builder lootGroup(String[] groups) { + this.loot.lootGroup = groups; return this; } @@ -148,7 +148,7 @@ public class CFLoot implements Loot { } @Override - public String getLootGroup() { + public String[] getLootGroup() { return lootGroup; } 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 a552c49e..cbd9b5a4 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 @@ -71,7 +71,7 @@ public interface Loot { */ boolean disableStats(); - String getLootGroup(); + String[] getLootGroup(); /** * Get the game config 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 index 419fd13e..4e5a4ecc 100644 --- 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 @@ -17,6 +17,8 @@ package net.momirealms.customfishing.api.mechanic.loot; +import org.bukkit.entity.Player; + public interface Modifier { - double modify(double weight); + double modify(Player player, double weight); } \ No newline at end of file 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 06e330fc..bf168b1a 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java @@ -1,3 +1,20 @@ +/* + * 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; import net.momirealms.customfishing.adventure.AdventureManagerImpl; @@ -7,10 +24,12 @@ 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.block.ItemsAdderBlockImpl; 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.mob.MythicMobsLibraryImpl; import net.momirealms.customfishing.compatibility.season.CustomCropsSeasonImpl; import net.momirealms.customfishing.compatibility.season.RealisticSeasonsImpl; import org.bukkit.inventory.ItemStack; @@ -42,6 +61,7 @@ public class IntegrationManagerImpl implements IntegrationManager { public void init() { if (plugin.isHookedPluginEnabled("ItemsAdder")) { plugin.getItemManager().registerItemLibrary(new ItemsAdderItemImpl()); + plugin.getBlockManager().registerBlockLibrary(new ItemsAdderBlockImpl()); hookMessage("ItemsAdder"); } if (plugin.isHookedPluginEnabled("MMOItems")) { @@ -58,6 +78,7 @@ public class IntegrationManagerImpl implements IntegrationManager { } if (plugin.isHookedPluginEnabled("MythicMobs")) { plugin.getItemManager().registerItemLibrary(new MythicMobsItemImpl()); + plugin.getMobManager().registerMobLibrary(new MythicMobsLibraryImpl()); hookMessage("MythicMobs"); } if (plugin.isHookedPluginEnabled("EcoJobs")) { diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java index 34b47423..59253928 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/papi/PlaceholderManagerImpl.java @@ -26,10 +26,8 @@ import org.bukkit.configuration.file.YamlConfiguration; 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.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -43,6 +41,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager { private final HashMap customPlaceholderMap; private CompetitionPapi competitionPapi; private StatisticsPapi statisticsPapi; + private final ConcurrentHashMap cachedPlaceholders; public PlaceholderManagerImpl(CustomFishingPlugin plugin) { instance = this; @@ -50,6 +49,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager { this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); this.pattern = Pattern.compile("\\{[^{}]+}"); this.customPlaceholderMap = new HashMap<>(); + this.cachedPlaceholders = new ConcurrentHashMap<>(); if (this.hasPapi) { competitionPapi = new CompetitionPapi(plugin); statisticsPapi = new StatisticsPapi(plugin); @@ -116,7 +116,10 @@ public class PlaceholderManagerImpl implements PlaceholderManager { public String parse(@Nullable OfflinePlayer player, String text, Map placeholders) { var list = detectPlaceholders(text); for (String papi : list) { - String replacer = placeholders.get(papi); + String replacer = null; + if (placeholders != null) { + replacer = placeholders.get(papi); + } if (replacer == null) { String custom = customPlaceholderMap.get(papi); if (custom != null) { @@ -130,6 +133,19 @@ public class PlaceholderManagerImpl implements PlaceholderManager { return text; } + @Override + public String parseCacheable(Player player, String text) { + var list = detectPlaceholders(text); + CachedPlaceholder cachedPlaceholder = cachedPlaceholders.computeIfAbsent(player.getUniqueId(), k -> new CachedPlaceholder()); + for (String papi : list) { + String custom = customPlaceholderMap.get(papi); + if (custom != null) { + text = text.replace(papi, cachedPlaceholder.get(player, custom)); + } + } + return text; + } + @Override public List parse(@Nullable OfflinePlayer player, List list, Map replacements) { return list.stream() @@ -140,4 +156,36 @@ public class PlaceholderManagerImpl implements PlaceholderManager { public static PlaceholderManagerImpl getInstance() { return instance; } + + public boolean hasPapi() { + return hasPapi; + } + + public static class CachedPlaceholder { + + private long lastUpdated; + private final HashMap cached; + + public CachedPlaceholder() { + this.lastUpdated = 0; + this.cached = new HashMap<>(); + } + + public synchronized String get(Player player, String custom) { + long current = System.currentTimeMillis(); + if (current - lastUpdated > 3000) { + lastUpdated = current; + String parsed = ParseUtils.setPlaceholders(player, custom); + cached.put(custom, parsed); + return parsed; + } else { + String cachedStr = cached.get(custom); + if (cachedStr != null) + return cachedStr; + String parsed = ParseUtils.setPlaceholders(player, custom); + cached.put(custom, parsed); + return parsed; + } + } + } } 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 30699a77..21630e20 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 @@ -603,9 +603,10 @@ public class FishingManagerImpl implements Listener, FishingManager { return null; } + Player player = fishingPreparation.getPlayer(); for (Pair pair : initialEffect.getLootWeightModifier()) { double previous = lootWithWeight.getOrDefault(pair.left(), 0d); - lootWithWeight.put(pair.left(), pair.right().modify(previous)); + lootWithWeight.put(pair.left(), pair.right().modify(player, previous)); } String key = WeightUtils.getRandom(lootWithWeight); 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 6487aef8..f88d27d8 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 @@ -25,6 +25,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.util.LogUtils; +import net.momirealms.customfishing.util.ConfigUtils; import org.apache.commons.lang3.StringUtils; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; @@ -46,7 +47,7 @@ public class LootManagerImpl implements LootManager { public static boolean instantGame; public static boolean showInFinder; public static String gameGroup; - public static String lootGroup; + public static String[] lootGroup; } public LootManagerImpl(CustomFishingPlugin plugin) { @@ -140,10 +141,12 @@ public class LootManagerImpl implements LootManager { } else { lootMap.put(entry.getKey(), loot); } - String group = loot.getLootGroup(); + String[] group = loot.getLootGroup(); if (group != null) { - List groupMembers = lootGroupMap.computeIfAbsent(group, k -> new ArrayList<>()); - groupMembers.add(loot.getID()); + for (String g : group) { + List groupMembers = lootGroupMap.computeIfAbsent(g, k -> new ArrayList<>()); + groupMembers.add(loot.getID()); + } } } } @@ -156,13 +159,14 @@ public class LootManagerImpl implements LootManager { .instantGame(section.getBoolean("instant-game", GlobalSetting.instantGame)) .showInFinder(section.getBoolean("show-in-fishfinder", GlobalSetting.showInFinder)) .gameConfig(section.getString("game-group", GlobalSetting.gameGroup)) - .lootGroup(section.getString("loot-group", GlobalSetting.lootGroup)) + .lootGroup(ConfigUtils.stringListArgs(Optional.ofNullable(section.get("loot-group")).orElse(GlobalSetting.lootGroup)).toArray(new String[0])) .nick(section.getString("nick", section.getString("display.name", key))) .addActions(getActionMap(section.getConfigurationSection("events"))) .addTimesActions(getTimesActionMap(section.getConfigurationSection("events.success-times"))) .build(); } + private HashMap getActionMap(ConfigurationSection section) { HashMap actionMap = new HashMap<>(); if (section == null) return actionMap; 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 index 91e26ef2..645c264f 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/ConditionalLoots.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/ConditionalLoots.java @@ -21,6 +21,7 @@ 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 org.bukkit.entity.Player; import java.util.HashMap; import java.util.List; @@ -41,10 +42,10 @@ public class ConditionalLoots { this.subLoots = subLoots; } - synchronized public void combine(HashMap weightMap) { + synchronized public void combine(Player player, HashMap weightMap) { for (Pair modifierPair : this.modifierList) { double previous = weightMap.getOrDefault(modifierPair.left(), 0d); - weightMap.put(modifierPair.left(), modifierPair.right().modify(previous)); + weightMap.put(modifierPair.left(), modifierPair.right().modify(player, previous)); } } 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 179df566..ba39d91e 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 @@ -36,6 +36,7 @@ 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; @@ -146,11 +147,12 @@ public class RequirementManagerImpl implements RequirementManager { HashMap lootWeightMap = new HashMap<>(); Queue> lootQueue = new LinkedList<>(); lootQueue.add(conditionalLootsMap); + Player player = condition.getPlayer(); while (!lootQueue.isEmpty()) { HashMap currentLootMap = lootQueue.poll(); for (ConditionalLoots loots : currentLootMap.values()) { if (loots.isConditionsMet(condition)) { - loots.combine(lootWeightMap); + loots.combine(player, lootWeightMap); if (loots.getSubLoots() != null) { lootQueue.add(loots.getSubLoots()); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java index 2b6f527c..7441b221 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java +++ b/plugin/src/main/java/net/momirealms/customfishing/util/ConfigUtils.java @@ -20,6 +20,9 @@ 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 net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; +import net.objecthunter.exp4j.Expression; +import net.objecthunter.exp4j.ExpressionBuilder; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; @@ -37,6 +40,8 @@ public class ConfigUtils { list.add(member); } else if (object instanceof List members) { list.addAll((Collection) members); + } else if (object instanceof String[] strings) { + list.addAll(List.of(strings)); } return list; } @@ -101,23 +106,37 @@ public class ConfigUtils { switch (text.charAt(0)) { case '/' -> { double arg = Double.parseDouble(text.substring(1)); - return weight -> weight / arg; + return (player, weight) -> weight / arg; } case '*' -> { double arg = Double.parseDouble(text.substring(1)); - return weight -> weight * arg; + return (player, weight) -> weight * arg; } case '-' -> { double arg = Double.parseDouble(text.substring(1)); - return weight -> weight - arg; + return (player, weight) -> weight - arg; } case '%' -> { double arg = Double.parseDouble(text.substring(1)); - return weight -> weight % arg; + return (player, weight) -> weight % arg; } case '+' -> { double arg = Double.parseDouble(text.substring(1)); - return weight -> weight + arg; + return (player, weight) -> weight + arg; + } + case '=' -> { + String formula = text.substring(1); + boolean hasPapi = PlaceholderManagerImpl.getInstance().hasPapi(); + return (player, weight) -> { + String temp = formula; + if (hasPapi) + temp = PlaceholderManagerImpl.getInstance().parseCacheable(player, formula); + Expression expression = new ExpressionBuilder(temp) + .variables("0") + .build() + .setVariable("0", weight); + return expression.evaluate(); + }; } default -> throw new IllegalArgumentException("Invalid weight: " + text); }