9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-19 15:09:24 +00:00

improve placeholders

This commit is contained in:
XiaoMoMi
2024-08-29 00:59:50 +08:00
parent ed3be887f8
commit 19c0a98257
12 changed files with 117 additions and 20 deletions

View File

@@ -93,6 +93,11 @@ public interface Context<T> {
*/ */
T holder(); T holder();
/**
* Reset the custom data
*/
void clearCustomData();
/** /**
* Creates a player-specific context. * Creates a player-specific context.
* *

View File

@@ -83,6 +83,8 @@ public class ContextKeys<T> {
public static final ContextKeys<Integer> CLICKS_LEFT = of("left_clicks", Integer.class); public static final ContextKeys<Integer> CLICKS_LEFT = of("left_clicks", Integer.class);
public static final ContextKeys<Integer> REQUIRED_TIMES = of("clicks", Integer.class); public static final ContextKeys<Integer> REQUIRED_TIMES = of("clicks", Integer.class);
public static final ContextKeys<EquipmentSlot> SLOT = of("hand", EquipmentSlot.class); public static final ContextKeys<EquipmentSlot> SLOT = of("hand", EquipmentSlot.class);
public static final ContextKeys<Double> BONUS = of("bonus", Double.class);
public static final ContextKeys<Double> BASE = of("base", Double.class);
private final String key; private final String key;
private final Class<T> type; private final Class<T> type;

View File

@@ -21,7 +21,9 @@ import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -95,6 +97,20 @@ public final class PlayerContextImpl implements Context<Player> {
return player; return player;
} }
@Override
public void clearCustomData() {
List<ContextKeys<?>> toRemove = new ArrayList<>();
for (Map.Entry<ContextKeys<?>, Object> entry : args.entrySet()) {
if (entry.getKey().key().startsWith("data_")) {
toRemove.add(entry.getKey());
}
}
for (ContextKeys<?> key : toRemove) {
args.remove(key);
placeholderMap.remove("{" + key.key() + "}");
}
}
@Override @Override
public String toString() { public String toString() {
return "PlayerContext{" + return "PlayerContext{" +

View File

@@ -37,6 +37,7 @@ import net.momirealms.customfishing.api.mechanic.game.Game;
import net.momirealms.customfishing.api.mechanic.game.GamingPlayer; import net.momirealms.customfishing.api.mechanic.game.GamingPlayer;
import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.loot.LootType; import net.momirealms.customfishing.api.mechanic.loot.LootType;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager; import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager;
import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.api.util.EventUtils;
import net.momirealms.customfishing.api.util.PlayerUtils; import net.momirealms.customfishing.api.util.PlayerUtils;
@@ -58,10 +59,7 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/** /**
* Represents a custom fishing hook. * Represents a custom fishing hook.
@@ -185,7 +183,13 @@ public class CustomFishingHook {
context.arg(ContextKeys.NICK, loot.nick()); context.arg(ContextKeys.NICK, loot.nick());
context.arg(ContextKeys.LOOT, loot.type()); context.arg(ContextKeys.LOOT, loot.type());
context.clearCustomData();
for (Map.Entry<String, TextValue<Player>> entry : loot.customData().entrySet()) {
context.arg(ContextKeys.of("data_" + entry.getKey(), String.class), entry.getValue().render(context));
}
plugin.debug("Next loot: " + loot.id()); plugin.debug("Next loot: " + loot.id());
plugin.debug(context);
// get its basic properties // get its basic properties
Effect baseEffect = loot.baseEffect().toEffect(context); Effect baseEffect = loot.baseEffect().toEffect(context);
tempEffect.combine(baseEffect); tempEffect.combine(baseEffect);

View File

@@ -19,10 +19,13 @@ package net.momirealms.customfishing.api.mechanic.loot;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect; import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue; import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys; import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Map;
public interface Loot { public interface Loot {
class DefaultProperties { class DefaultProperties {
@@ -127,6 +130,13 @@ public interface Loot {
*/ */
LootBaseEffect baseEffect(); LootBaseEffect baseEffect();
/**
* Get the custom data
*
* @return custom data
*/
Map<String, TextValue<Player>> customData();
/** /**
* Create a new builder for constructing a Loot instance. * Create a new builder for constructing a Loot instance.
* *
@@ -237,6 +247,14 @@ public interface Loot {
*/ */
Builder lootBaseEffect(LootBaseEffect lootBaseEffect); Builder lootBaseEffect(LootBaseEffect lootBaseEffect);
/**
* Set the custom data
*
* @param customData the custom data
* @return The builder instance.
*/
Builder customData(Map<String, TextValue<Player>> customData);
/** /**
* Set if the loot go directly into inventory * Set if the loot go directly into inventory
* *

View File

@@ -19,10 +19,14 @@ package net.momirealms.customfishing.api.mechanic.loot;
import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect; import net.momirealms.customfishing.api.mechanic.effect.LootBaseEffect;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue; import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys; import net.momirealms.customfishing.api.mechanic.statistic.StatisticsKeys;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
@@ -42,8 +46,9 @@ public class LootImpl implements Loot {
private final String[] groups; private final String[] groups;
private final LootBaseEffect lootBaseEffect; private final LootBaseEffect lootBaseEffect;
private final MathValue<Player> toInventory; private final MathValue<Player> toInventory;
private final Map<String, TextValue<Player>> customData;
public LootImpl(LootType type, boolean instantGame, boolean disableGame, boolean disableStatistics, boolean showInFinder, boolean preventGrabbing, String id, String nick, StatisticsKeys statisticsKeys, MathValue<Player> score, String[] groups, LootBaseEffect lootBaseEffect, MathValue<Player> toInventory) { public LootImpl(LootType type, boolean instantGame, boolean disableGame, boolean disableStatistics, boolean showInFinder, boolean preventGrabbing, String id, String nick, StatisticsKeys statisticsKeys, MathValue<Player> score, String[] groups, LootBaseEffect lootBaseEffect, MathValue<Player> toInventory, Map<String, TextValue<Player>> customData) {
this.type = type; this.type = type;
this.instantGame = instantGame; this.instantGame = instantGame;
this.disableGame = disableGame; this.disableGame = disableGame;
@@ -57,6 +62,7 @@ public class LootImpl implements Loot {
this.lootBaseEffect = lootBaseEffect; this.lootBaseEffect = lootBaseEffect;
this.preventGrabbing = preventGrabbing; this.preventGrabbing = preventGrabbing;
this.toInventory = toInventory; this.toInventory = toInventory;
this.customData = customData;
} }
@Override @Override
@@ -125,6 +131,11 @@ public class LootImpl implements Loot {
return lootBaseEffect; return lootBaseEffect;
} }
@Override
public Map<String, TextValue<Player>> customData() {
return customData;
}
public static class BuilderImpl implements Builder { public static class BuilderImpl implements Builder {
private LootType type = DEFAULT_TYPE; private LootType type = DEFAULT_TYPE;
@@ -140,6 +151,7 @@ public class LootImpl implements Loot {
private String[] groups = new String[0]; private String[] groups = new String[0];
private LootBaseEffect lootBaseEffect = null; private LootBaseEffect lootBaseEffect = null;
private MathValue<Player> toInventory = MathValue.plain(0); private MathValue<Player> toInventory = MathValue.plain(0);
private Map<String, TextValue<Player>> customData = new LinkedHashMap<>();
@Override @Override
public Builder type(LootType type) { public Builder type(LootType type) {
@@ -202,6 +214,11 @@ public class LootImpl implements Loot {
return this; return this;
} }
@Override @Override
public Builder customData(Map<String, TextValue<Player>> customData) {
this.customData.putAll(customData);
return this;
}
@Override
public Builder toInventory(MathValue<Player> toInventory) { public Builder toInventory(MathValue<Player> toInventory) {
this.toInventory = toInventory; this.toInventory = toInventory;
return this; return this;
@@ -221,7 +238,8 @@ public class LootImpl implements Loot {
score, score,
groups, groups,
requireNonNull(lootBaseEffect), requireNonNull(lootBaseEffect),
toInventory toInventory,
customData
); );
} }
} }

View File

@@ -24,6 +24,7 @@ import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -36,7 +37,7 @@ public class BukkitPlaceholderManager implements PlaceholderManager {
private final BukkitCustomFishingPlugin plugin; private final BukkitCustomFishingPlugin plugin;
private boolean hasPapi; private boolean hasPapi;
private final HashMap<String, Function<OfflinePlayer, String>> customPlaceholderMap; private final HashMap<String, BiFunction<OfflinePlayer, Map<String, String>, String>> customPlaceholderMap;
private static BukkitPlaceholderManager instance; private static BukkitPlaceholderManager instance;
/** /**
@@ -56,7 +57,7 @@ public class BukkitPlaceholderManager implements PlaceholderManager {
@Override @Override
public void load() { public void load() {
this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
this.customPlaceholderMap.put("{random}", (p) -> String.valueOf(RandomUtils.generateRandomDouble(0, 1))); this.customPlaceholderMap.put("{random}", (p, map) -> String.valueOf(RandomUtils.generateRandomDouble(0, 1)));
} }
/** /**
@@ -80,12 +81,12 @@ public class BukkitPlaceholderManager implements PlaceholderManager {
@Override @Override
public boolean registerCustomPlaceholder(String placeholder, String original) { public boolean registerCustomPlaceholder(String placeholder, String original) {
if (this.customPlaceholderMap.containsKey(placeholder)) return false; if (this.customPlaceholderMap.containsKey(placeholder)) return false;
this.customPlaceholderMap.put(placeholder, (p) -> PlaceholderAPIUtils.parse(p, original)); this.customPlaceholderMap.put(placeholder, (p, map) -> PlaceholderAPIUtils.parse(p, parse(p, original, map)));
return true; return true;
} }
@Override @Override
public boolean registerCustomPlaceholder(String placeholder, Function<OfflinePlayer, String> provider) { public boolean registerCustomPlaceholder(String placeholder, BiFunction<OfflinePlayer, Map<String, String>, String> provider) {
if (this.customPlaceholderMap.containsKey(placeholder)) return false; if (this.customPlaceholderMap.containsKey(placeholder)) return false;
this.customPlaceholderMap.put(placeholder, provider); this.customPlaceholderMap.put(placeholder, provider);
return true; return true;
@@ -110,7 +111,7 @@ public class BukkitPlaceholderManager implements PlaceholderManager {
result = replacements.get(placeholder); result = replacements.get(placeholder);
if (result != null) if (result != null)
return result; return result;
String custom = Optional.ofNullable(customPlaceholderMap.get(placeholder)).map(supplier -> supplier.apply(player)).orElse(null); String custom = Optional.ofNullable(customPlaceholderMap.get(placeholder)).map(supplier -> supplier.apply(player, replacements)).orElse(null);
if (custom == null) if (custom == null)
return placeholder; return placeholder;
return setPlaceholders(player, custom); return setPlaceholders(player, custom);
@@ -125,12 +126,13 @@ public class BukkitPlaceholderManager implements PlaceholderManager {
replacer = replacements.get(papi); replacer = replacements.get(papi);
} }
if (replacer == null) { if (replacer == null) {
String custom = Optional.ofNullable(customPlaceholderMap.get(papi)).map(supplier -> supplier.apply(player)).orElse(null); String custom = Optional.ofNullable(customPlaceholderMap.get(papi)).map(supplier -> supplier.apply(player, replacements)).orElse(null);
if (custom != null) if (custom != null)
replacer = setPlaceholders(player, parse(player, custom, replacements)); replacer = setPlaceholders(player, parse(player, custom, replacements));
} }
if (replacer != null) if (replacer != null) {
text = text.replace(papi, replacer); text = text.replace(papi, replacer);
}
} }
return text; return text;
} }

View File

@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -46,7 +47,7 @@ public interface PlaceholderManager extends Reloadable {
* @param provider the value provider * @param provider the value provider
* @return true if the placeholder was successfully registered, false otherwise * @return true if the placeholder was successfully registered, false otherwise
*/ */
boolean registerCustomPlaceholder(String placeholder, Function<OfflinePlayer, String> provider); boolean registerCustomPlaceholder(String placeholder, BiFunction<OfflinePlayer, Map<String, String>, String> provider);
/** /**
* Resolves all placeholders within a given text. * Resolves all placeholders within a given text.

View File

@@ -68,6 +68,7 @@ import net.momirealms.customfishing.bukkit.util.ItemStackUtils;
import net.momirealms.customfishing.bukkit.util.ParticleUtils; import net.momirealms.customfishing.bukkit.util.ParticleUtils;
import net.momirealms.customfishing.common.config.node.Node; import net.momirealms.customfishing.common.config.node.Node;
import net.momirealms.customfishing.common.helper.AdventureHelper; import net.momirealms.customfishing.common.helper.AdventureHelper;
import net.momirealms.customfishing.common.helper.ExpressionHelper;
import net.momirealms.customfishing.common.helper.VersionHelper; import net.momirealms.customfishing.common.helper.VersionHelper;
import net.momirealms.customfishing.common.item.AbstractItem; import net.momirealms.customfishing.common.item.AbstractItem;
import net.momirealms.customfishing.common.item.Item; import net.momirealms.customfishing.common.item.Item;
@@ -511,9 +512,17 @@ public class BukkitConfigManager extends ConfigManager {
MathValue<Player> bonus = MathValue.auto(section.get("bonus", "0")); MathValue<Player> bonus = MathValue.auto(section.get("bonus", "0"));
return (item, context) -> { return (item, context) -> {
double basePrice = base.evaluate(context); double basePrice = base.evaluate(context);
context.arg(ContextKeys.BASE, basePrice);
double bonusPrice = bonus.evaluate(context); double bonusPrice = bonus.evaluate(context);
float size = Optional.ofNullable(context.arg(ContextKeys.SIZE)).orElse(0f); context.arg(ContextKeys.BONUS, bonusPrice);
double price = basePrice + bonusPrice * size; String formula = plugin.getMarketManager().getFormula();
TextValue<Player> playerTextValue = TextValue.auto(formula);
String rendered = playerTextValue.render(context);
List<String> unparsed = plugin.getPlaceholderManager().resolvePlaceholders(rendered);
for (String unparsedValue : unparsed) {
rendered = rendered.replace(unparsedValue, "0");
}
double price = ExpressionHelper.evaluate(rendered);
item.setTag(price, "Price"); item.setTag(price, "Price");
context.arg(ContextKeys.PRICE, price); context.arg(ContextKeys.PRICE, price);
context.arg(ContextKeys.PRICE_FORMATTED, String.format("%.2f", price)); context.arg(ContextKeys.PRICE_FORMATTED, String.format("%.2f", price));
@@ -961,6 +970,20 @@ public class BukkitConfigManager extends ConfigManager {
} }
private void registerBuiltInLootParser() { private void registerBuiltInLootParser() {
this.registerLootParser(object -> {
Section section = (Section) object;
Map<String, TextValue<Player>> data = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : section.getStringRouteMappedValues(false).entrySet()) {
if (entry.getValue() instanceof String str) {
data.put(entry.getKey(), TextValue.auto(str));
} else {
data.put(entry.getKey(), TextValue.auto(entry.getValue().toString()));
}
}
return builder -> {
builder.customData(data);
};
}, "custom-data");
this.registerLootParser(object -> { this.registerLootParser(object -> {
if (object instanceof Boolean b) { if (object instanceof Boolean b) {
return builder -> builder.toInventory(MathValue.plain(b ? 1 : 0)); return builder -> builder.toInventory(MathValue.plain(b ? 1 : 0));

View File

@@ -27,6 +27,8 @@ import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys; import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem; import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
import net.momirealms.customfishing.api.mechanic.item.ItemManager; import net.momirealms.customfishing.api.mechanic.item.ItemManager;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.api.util.EventUtils;
import net.momirealms.customfishing.bukkit.integration.item.CustomFishingItemProvider; import net.momirealms.customfishing.bukkit.integration.item.CustomFishingItemProvider;
import net.momirealms.customfishing.bukkit.item.damage.CustomDurabilityItem; import net.momirealms.customfishing.bukkit.item.damage.CustomDurabilityItem;
@@ -136,6 +138,11 @@ public class BukkitItemManager implements ItemManager, Listener {
public ItemStack build(@NotNull Context<Player> context, @NotNull CustomFishingItem item) { public ItemStack build(@NotNull Context<Player> context, @NotNull CustomFishingItem item) {
ItemStack itemStack = getOriginalStack(context.holder(), item.material()); ItemStack itemStack = getOriginalStack(context.holder(), item.material());
if (itemStack.getType() == Material.AIR) return itemStack; if (itemStack.getType() == Material.AIR) return itemStack;
plugin.getLootManager().getLoot(item.id()).ifPresent(loot -> {
for (Map.Entry<String, TextValue<Player>> entry : loot.customData().entrySet()) {
context.arg(ContextKeys.of("data_" + entry.getKey(), String.class), entry.getValue().render(context));
}
});
itemStack.setAmount(Math.max(1, (int) item.amount().evaluate(context))); itemStack.setAmount(Math.max(1, (int) item.amount().evaluate(context)));
Item<ItemStack> wrappedItemStack = factory.wrap(itemStack); Item<ItemStack> wrappedItemStack = factory.wrap(itemStack);
for (BiConsumer<Item<ItemStack>, Context<Player>> consumer : item.tagConsumers()) { for (BiConsumer<Item<ItemStack>, Context<Player>> consumer : item.tagConsumers()) {

View File

@@ -342,7 +342,7 @@ public class ItemStackUtils {
values.add(MathValue.auto(toTypeAndData((String) o).right())); values.add(MathValue.auto(toTypeAndData((String) o).right()));
} }
itemEditors.add(((item, context) -> { itemEditors.add(((item, context) -> {
List<Double> doubles = values.stream().map(unparsed -> (double) unparsed.evaluate(context)).toList(); List<Double> doubles = values.stream().map(unparsed -> unparsed.evaluate(context)).toList();
item.set(doubles, (Object[]) currentRoute); item.set(doubles, (Object[]) currentRoute);
})); }));
} }
@@ -392,8 +392,9 @@ public class ItemStackUtils {
} }
case DOUBLE -> { case DOUBLE -> {
MathValue<Player> mathValue = MathValue.auto(pair.right()); MathValue<Player> mathValue = MathValue.auto(pair.right());
System.out.println(pair.right());
itemEditors.add(((item, context) -> { itemEditors.add(((item, context) -> {
item.set((double) mathValue.evaluate(context), (Object[]) currentRoute); item.set(mathValue.evaluate(context), (Object[]) currentRoute);
})); }));
} }
case FLOAT -> { case FLOAT -> {

View File

@@ -123,7 +123,7 @@ mechanics:
value: value:
priority_1: priority_1:
conditions: conditions:
lava-fishing: true in-lava: true
actions: actions:
fake_item_action: fake_item_action:
type: fake-item type: fake-item
@@ -133,7 +133,7 @@ mechanics:
item: lava_effect item: lava_effect
priority_2: priority_2:
conditions: conditions:
lava-fishing: false in-water: true
actions: actions:
fake_item_action: fake_item_action:
type: fake-item type: fake-item