mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
新增merchant_trade函数
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package net.momirealms.craftengine.bukkit.util;
|
package net.momirealms.craftengine.bukkit.util;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.inventory.InventoryAction;
|
import org.bukkit.event.inventory.InventoryAction;
|
||||||
import org.bukkit.event.inventory.InventoryEvent;
|
import org.bukkit.event.inventory.InventoryEvent;
|
||||||
@@ -74,6 +75,11 @@ public final class LegacyInventoryUtils {
|
|||||||
player.openMerchant(merchant, true);
|
player.openMerchant(merchant, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static Merchant createMerchant() {
|
||||||
|
return Bukkit.createMerchant("Villager");
|
||||||
|
}
|
||||||
|
|
||||||
public static Player getPlayerFromInventoryEvent(InventoryEvent event) {
|
public static Player getPlayerFromInventoryEvent(InventoryEvent event) {
|
||||||
return (Player) event.getView().getPlayer();
|
return (Player) event.getView().getPlayer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.bukkit.inventory.Merchant;
|
import org.bukkit.inventory.Merchant;
|
||||||
import org.bukkit.inventory.MerchantRecipe;
|
import org.bukkit.inventory.MerchantRecipe;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -91,26 +92,4 @@ public class BukkitPlatform implements Platform {
|
|||||||
}
|
}
|
||||||
return new BukkitParticleType(particle, name);
|
return new BukkitParticleType(particle, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void openMerchant(Player player, Component title, List<MerchantOffer<?>> offers) {
|
|
||||||
Merchant merchant = Bukkit.createMerchant();
|
|
||||||
List<MerchantRecipe> recipes = merchant.getRecipes();
|
|
||||||
for (MerchantOffer<?> offer : offers) {
|
|
||||||
MerchantRecipe merchantRecipe = new MerchantRecipe((ItemStack) offer.result().getItem(), 0, Integer.MAX_VALUE, offer.xp() > 0, offer.xp(), 0);
|
|
||||||
merchantRecipe.addIngredient((ItemStack) offer.cost1().getItem());
|
|
||||||
offer.cost2().ifPresent(it -> merchantRecipe.addIngredient((ItemStack) it.getItem()));
|
|
||||||
recipes.add(merchantRecipe);
|
|
||||||
}
|
|
||||||
merchant.setRecipes(recipes);
|
|
||||||
if (title != null) {
|
|
||||||
try {
|
|
||||||
Object minecraftMerchant = CraftBukkitReflections.method$CraftMerchant$getMerchant.invoke(merchant);
|
|
||||||
CraftBukkitReflections.field$MinecraftMerchant$title.set(minecraftMerchant, ComponentUtils.adventureToMinecraft(title));
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
this.plugin.logger().warn("Failed to update merchant title", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LegacyInventoryUtils.openMerchant((org.bukkit.entity.Player) player.platformPlayer(), merchant);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,44 @@
|
|||||||
package net.momirealms.craftengine.bukkit.plugin.gui;
|
package net.momirealms.craftengine.bukkit.plugin.gui;
|
||||||
|
|
||||||
|
import io.papermc.paper.event.player.PlayerPurchaseEvent;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.momirealms.craftengine.bukkit.block.entity.BlockEntityHolder;
|
import net.momirealms.craftengine.bukkit.block.entity.BlockEntityHolder;
|
||||||
import net.momirealms.craftengine.bukkit.block.entity.SimpleStorageBlockEntity;
|
import net.momirealms.craftengine.bukkit.block.entity.SimpleStorageBlockEntity;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
|
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||||
|
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.InventoryUtils;
|
import net.momirealms.craftengine.bukkit.util.InventoryUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
|
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
|
||||||
|
import net.momirealms.craftengine.core.item.trade.MerchantOffer;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.plugin.gui.*;
|
import net.momirealms.craftengine.core.plugin.gui.*;
|
||||||
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.ExperienceOrb;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.Merchant;
|
||||||
|
import org.bukkit.inventory.MerchantRecipe;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class BukkitGuiManager implements GuiManager, Listener {
|
public class BukkitGuiManager implements GuiManager, Listener {
|
||||||
|
public static final int CRAFT_ENGINE_MAGIC_MERCHANT_NUMBER = 1821981731;
|
||||||
private static BukkitGuiManager instance;
|
private static BukkitGuiManager instance;
|
||||||
private final BukkitCraftEngine plugin;
|
private final BukkitCraftEngine plugin;
|
||||||
|
|
||||||
@@ -135,6 +150,43 @@ public class BukkitGuiManager implements GuiManager, Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 为了修复没有经验的问题
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||||
|
public void onMerchantTrade(PlayerPurchaseEvent event) {
|
||||||
|
MerchantRecipe trade = event.getTrade();
|
||||||
|
if (trade.getMaxUses() == CRAFT_ENGINE_MAGIC_MERCHANT_NUMBER) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
int exp = trade.getVillagerExperience();
|
||||||
|
if (exp <= 0) return;
|
||||||
|
EntityUtils.spawnEntity(player.getWorld(), player.getLocation(), EntityType.EXPERIENCE_ORB, entity -> {
|
||||||
|
ExperienceOrb orb = (ExperienceOrb) entity;
|
||||||
|
orb.setExperience(exp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openMerchant(net.momirealms.craftengine.core.entity.player.Player player, Component title, List<MerchantOffer<?>> offers) {
|
||||||
|
Merchant merchant = VersionHelper.isOrAbove1_21_4() ? Bukkit.createMerchant() : LegacyInventoryUtils.createMerchant();
|
||||||
|
List<MerchantRecipe> recipes = new ArrayList<>();
|
||||||
|
for (MerchantOffer<?> offer : offers) {
|
||||||
|
MerchantRecipe merchantRecipe = new MerchantRecipe((ItemStack) offer.result().getItem(), 0, CRAFT_ENGINE_MAGIC_MERCHANT_NUMBER, false, offer.xp(), 0);
|
||||||
|
merchantRecipe.addIngredient((ItemStack) offer.cost1().getItem());
|
||||||
|
offer.cost2().ifPresent(it -> merchantRecipe.addIngredient((ItemStack) it.getItem()));
|
||||||
|
recipes.add(merchantRecipe);
|
||||||
|
}
|
||||||
|
merchant.setRecipes(recipes);
|
||||||
|
if (title != null) {
|
||||||
|
try {
|
||||||
|
Object minecraftMerchant = CraftBukkitReflections.method$CraftMerchant$getMerchant.invoke(merchant);
|
||||||
|
CraftBukkitReflections.field$MinecraftMerchant$title.set(minecraftMerchant, ComponentUtils.adventureToMinecraft(title));
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
this.plugin.logger().warn("Failed to update merchant title", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LegacyInventoryUtils.openMerchant((org.bukkit.entity.Player) player.platformPlayer(), merchant);
|
||||||
|
}
|
||||||
|
|
||||||
public static BukkitGuiManager instance() {
|
public static BukkitGuiManager instance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -466,6 +466,9 @@ warning.config.function.set_variable.missing_value: "<yellow>Issue found in file
|
|||||||
warning.config.function.toast.missing_toast: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'toast' argument for 'toast' function.</yellow>"
|
warning.config.function.toast.missing_toast: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'toast' argument for 'toast' function.</yellow>"
|
||||||
warning.config.function.toast.missing_icon: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'icon' argument for 'toast' function.</yellow>"
|
warning.config.function.toast.missing_icon: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'icon' argument for 'toast' function.</yellow>"
|
||||||
warning.config.function.toast.invalid_advancement_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid advancement type '<arg:2>' for 'toast' function. Allowed types: [<arg:3>].</yellow>"
|
warning.config.function.toast.invalid_advancement_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid advancement type '<arg:2>' for 'toast' function. Allowed types: [<arg:3>].</yellow>"
|
||||||
|
warning.config.function.merchant_trade.missing_offers: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'offers' argument for 'merchant_trade' function.</yellow>"
|
||||||
|
warning.config.function.merchant_trade.offer.missing_cost_1: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'cost-1' argument for merchant trade offers.</yellow>"
|
||||||
|
warning.config.function.merchant_trade.offer.missing_result: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'result' argument for merchant trade offers.</yellow>"
|
||||||
warning.config.selector.missing_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'type' argument for selector.</yellow>"
|
warning.config.selector.missing_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'type' argument for selector.</yellow>"
|
||||||
warning.config.selector.invalid_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector type '<arg:2>'.</yellow>"
|
warning.config.selector.invalid_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector type '<arg:2>'.</yellow>"
|
||||||
warning.config.selector.invalid_target: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector target '<arg:2>'.</yellow>"
|
warning.config.selector.invalid_target: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector target '<arg:2>'.</yellow>"
|
||||||
|
|||||||
@@ -491,13 +491,24 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExceptionCollector<LocalizedResourceConfigException> eCollector1 = new ExceptionCollector<>();
|
||||||
|
|
||||||
|
Map<EventTrigger, List<Function<PlayerOptionalContext>>> events;
|
||||||
|
try {
|
||||||
|
events = EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event"));
|
||||||
|
} catch (LocalizedResourceConfigException e) {
|
||||||
|
eCollector1.add(e);
|
||||||
|
events = Map.of();
|
||||||
|
}
|
||||||
|
LootTable<?> lootTable;
|
||||||
|
try {
|
||||||
|
lootTable = LootTable.fromMap(ResourceConfigUtils.getAsMapOrNull(section.get("loot"), "loot"));
|
||||||
|
} catch (LocalizedResourceConfigException e) {
|
||||||
|
eCollector1.add(e);
|
||||||
|
lootTable = null;
|
||||||
|
}
|
||||||
// 创建自定义方块
|
// 创建自定义方块
|
||||||
AbstractCustomBlock customBlock = (AbstractCustomBlock) createCustomBlock(
|
AbstractCustomBlock customBlock = (AbstractCustomBlock) createCustomBlock(holder, variantProvider, events, lootTable);
|
||||||
holder,
|
|
||||||
variantProvider,
|
|
||||||
EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")),
|
|
||||||
LootTable.fromMap(ResourceConfigUtils.getAsMapOrNull(section.get("loot"), "loot"))
|
|
||||||
);
|
|
||||||
BlockBehavior blockBehavior = createBlockBehavior(customBlock, MiscUtils.getAsMapList(ResourceConfigUtils.get(section, "behavior", "behaviors")));
|
BlockBehavior blockBehavior = createBlockBehavior(customBlock, MiscUtils.getAsMapList(ResourceConfigUtils.get(section, "behavior", "behaviors")));
|
||||||
|
|
||||||
Map<String, Map<String, Object>> appearanceConfigs;
|
Map<String, Map<String, Object>> appearanceConfigs;
|
||||||
@@ -592,7 +603,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
|||||||
// 至少有一个外观吧
|
// 至少有一个外观吧
|
||||||
Objects.requireNonNull(anyAppearance, "any appearance should not be null");
|
Objects.requireNonNull(anyAppearance, "any appearance should not be null");
|
||||||
|
|
||||||
ExceptionCollector<LocalizedResourceConfigException> exceptionCollector = new ExceptionCollector<>();
|
ExceptionCollector<LocalizedResourceConfigException> eCollector2 = new ExceptionCollector<>();
|
||||||
if (!singleState) {
|
if (!singleState) {
|
||||||
Map<String, Object> variantsSection = ResourceConfigUtils.getAsMapOrNull(stateSection.get("variants"), "variants");
|
Map<String, Object> variantsSection = ResourceConfigUtils.getAsMapOrNull(stateSection.get("variants"), "variants");
|
||||||
if (variantsSection != null) {
|
if (variantsSection != null) {
|
||||||
@@ -602,7 +613,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
|||||||
// 先解析nbt,找到需要修改的方块状态
|
// 先解析nbt,找到需要修改的方块状态
|
||||||
CompoundTag tag = BlockNbtParser.deserialize(variantProvider, variantNBT);
|
CompoundTag tag = BlockNbtParser.deserialize(variantProvider, variantNBT);
|
||||||
if (tag == null) {
|
if (tag == null) {
|
||||||
exceptionCollector.add(new LocalizedResourceConfigException("warning.config.block.state.property.invalid_format", variantNBT));
|
eCollector2.add(new LocalizedResourceConfigException("warning.config.block.state.property.invalid_format", variantNBT));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
List<ImmutableBlockState> possibleStates = variantProvider.getPossibleStates(tag);
|
List<ImmutableBlockState> possibleStates = variantProvider.getPossibleStates(tag);
|
||||||
@@ -612,11 +623,11 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
|||||||
possibleState.setSettings(BlockSettings.ofFullCopy(possibleState.settings(), anotherSetting));
|
possibleState.setSettings(BlockSettings.ofFullCopy(possibleState.settings(), anotherSetting));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String appearanceName = ResourceConfigUtils.getAsString(variantSection.get("appearance"));
|
String appearanceName = ResourceConfigUtils.getAsStringOrNull(variantSection.get("appearance"));
|
||||||
if (appearanceName != null) {
|
if (appearanceName != null) {
|
||||||
BlockStateAppearance appearance = appearances.get(appearanceName);
|
BlockStateAppearance appearance = appearances.get(appearanceName);
|
||||||
if (appearance == null) {
|
if (appearance == null) {
|
||||||
exceptionCollector.add(new LocalizedResourceConfigException("warning.config.block.state.variant.invalid_appearance", variantNBT, appearanceName));
|
eCollector2.add(new LocalizedResourceConfigException("warning.config.block.state.variant.invalid_appearance", variantNBT, appearanceName));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (ImmutableBlockState possibleState : possibleStates) {
|
for (ImmutableBlockState possibleState : possibleStates) {
|
||||||
@@ -675,8 +686,11 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
|||||||
AbstractBlockManager.this.byId.put(customBlock.id(), customBlock);
|
AbstractBlockManager.this.byId.put(customBlock.id(), customBlock);
|
||||||
|
|
||||||
// 抛出次要警告
|
// 抛出次要警告
|
||||||
exceptionCollector.throwIfPresent();
|
eCollector2.throwIfPresent();
|
||||||
}, () -> GsonHelper.get().toJson(section)));
|
}, () -> GsonHelper.get().toJson(section)));
|
||||||
|
|
||||||
|
// 抛出次要警告
|
||||||
|
eCollector1.throwIfPresent();
|
||||||
}, () -> GsonHelper.get().toJson(section)));
|
}, () -> GsonHelper.get().toJson(section)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,4 @@ public interface Platform {
|
|||||||
World getWorld(String name);
|
World getWorld(String name);
|
||||||
|
|
||||||
ParticleType getParticleType(Key name);
|
ParticleType getParticleType(Key name);
|
||||||
|
|
||||||
void openMerchant(Player player, Component title, List<MerchantOffer<?>> offers);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public class EventFunctions {
|
|||||||
register(CommonFunctions.SET_VARIABLE, new SetVariableFunction.FactoryImpl<>(EventConditions::fromMap));
|
register(CommonFunctions.SET_VARIABLE, new SetVariableFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||||
register(CommonFunctions.TOAST, new ToastFunction.FactoryImpl<>(EventConditions::fromMap));
|
register(CommonFunctions.TOAST, new ToastFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||||
register(CommonFunctions.DAMAGE, new DamageFunction.FactoryImpl<>(EventConditions::fromMap));
|
register(CommonFunctions.DAMAGE, new DamageFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||||
|
register(CommonFunctions.MERCHANT_TRADE, new MerchantTradeFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void register(Key key, FunctionFactory<PlayerOptionalContext> factory) {
|
public static void register(Key key, FunctionFactory<PlayerOptionalContext> factory) {
|
||||||
|
|||||||
@@ -35,4 +35,5 @@ public final class CommonFunctions {
|
|||||||
public static final Key TOAST = Key.of("craftengine:toast");
|
public static final Key TOAST = Key.of("craftengine:toast");
|
||||||
public static final Key SET_VARIABLE = Key.of("craftengine:set_variable");
|
public static final Key SET_VARIABLE = Key.of("craftengine:set_variable");
|
||||||
public static final Key DAMAGE = Key.of("craftengine:damage");
|
public static final Key DAMAGE = Key.of("craftengine:damage");
|
||||||
|
public static final Key MERCHANT_TRADE = Key.of("craftengine:merchant_trade");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class DamageFunction<CTX extends Context> extends AbstractConditionalFunc
|
|||||||
@Override
|
@Override
|
||||||
public Function<CTX> create(Map<String, Object> arguments) {
|
public Function<CTX> create(Map<String, Object> arguments) {
|
||||||
PlayerSelector<CTX> selector = PlayerSelectors.fromObject(arguments.getOrDefault("target", "self"), conditionFactory());
|
PlayerSelector<CTX> selector = PlayerSelectors.fromObject(arguments.getOrDefault("target", "self"), conditionFactory());
|
||||||
Key damageType = Key.of(ResourceConfigUtils.getAsString(arguments.getOrDefault("damage-type", "generic")));
|
Key damageType = Key.of(ResourceConfigUtils.getAsStringOrNull(arguments.getOrDefault("damage-type", "generic")));
|
||||||
NumberProvider amount = NumberProviders.fromObject(arguments.getOrDefault("amount", 1f));
|
NumberProvider amount = NumberProviders.fromObject(arguments.getOrDefault("amount", 1f));
|
||||||
return new DamageFunction<>(selector, damageType, amount, getPredicates(arguments));
|
return new DamageFunction<>(selector, damageType, amount, getPredicates(arguments));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package net.momirealms.craftengine.core.plugin.context.function;
|
||||||
|
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
|
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||||
|
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||||
|
import net.momirealms.craftengine.core.item.modifier.ComponentsModifier;
|
||||||
|
import net.momirealms.craftengine.core.item.modifier.TagsModifier;
|
||||||
|
import net.momirealms.craftengine.core.item.trade.MerchantOffer;
|
||||||
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.*;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
|
||||||
|
import net.momirealms.craftengine.core.util.*;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class MerchantTradeFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||||
|
private final String title;
|
||||||
|
private final PlayerSelector<CTX> selector;
|
||||||
|
private final LazyReference<List<MerchantOffer<?>>> offers;
|
||||||
|
|
||||||
|
public MerchantTradeFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, String title, LazyReference<List<MerchantOffer<?>>> offers) {
|
||||||
|
super(predicates);
|
||||||
|
this.title = title;
|
||||||
|
this.selector = selector;
|
||||||
|
this.offers = offers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runInternal(CTX ctx) {
|
||||||
|
if (this.selector == null) {
|
||||||
|
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
|
||||||
|
CraftEngine.instance().guiManager().openMerchant(it, this.title == null ? null : AdventureHelper.miniMessage().deserialize(this.title, ctx.tagResolvers()), this.offers.get());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
for (Player viewer : this.selector.get(ctx)) {
|
||||||
|
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
|
||||||
|
CraftEngine.instance().guiManager().openMerchant(viewer, this.title == null ? null : AdventureHelper.miniMessage().deserialize(this.title, relationalContext.tagResolvers()), this.offers.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Key type() {
|
||||||
|
return CommonFunctions.MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
|
||||||
|
|
||||||
|
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
|
||||||
|
super(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
@Override
|
||||||
|
public Function<CTX> create(Map<String, Object> arguments) {
|
||||||
|
String title = ResourceConfigUtils.getAsStringOrNull(arguments.get("title"));
|
||||||
|
List<TempOffer> merchantOffers = ResourceConfigUtils.parseConfigAsList(ResourceConfigUtils.requireNonNullOrThrow(arguments.get("offers"), "warning.config.function.merchant_trade.missing_offers"), map -> {
|
||||||
|
Object cost1 = ResourceConfigUtils.requireNonNullOrThrow(map.get("cost-1"), "warning.config.function.merchant_trade.offer.missing_cost_1");
|
||||||
|
Object cost2 = map.get("cost-2");
|
||||||
|
Object result = ResourceConfigUtils.requireNonNullOrThrow(map.get("result"), "warning.config.function.merchant_trade.offer.missing_result");
|
||||||
|
int exp = ResourceConfigUtils.getAsInt(map.get("experience"), "experience");
|
||||||
|
return new TempOffer(cost1, cost2, result, exp);
|
||||||
|
});
|
||||||
|
return new MerchantTradeFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), title,
|
||||||
|
LazyReference.lazyReference(() -> {
|
||||||
|
List<MerchantOffer<?>> offers = new ArrayList<>(merchantOffers.size());
|
||||||
|
for (TempOffer offer : merchantOffers) {
|
||||||
|
Item cost1 = parseIngredient(offer.cost1);
|
||||||
|
Optional cost2 = Optional.ofNullable(parseIngredient(offer.cost2));
|
||||||
|
Item result = parseIngredient(offer.result);
|
||||||
|
offers.add(new MerchantOffer<>(cost1, cost2, result, false, 0, Integer.MAX_VALUE, offer.exp, 0, 0, 0));
|
||||||
|
}
|
||||||
|
return offers;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public record TempOffer(Object cost1, Object cost2, Object result, int exp) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private Item<?> parseIngredient(Object arguments) {
|
||||||
|
if (arguments == null) return null;
|
||||||
|
if (arguments instanceof Map<?,?> map) {
|
||||||
|
Map<String, Object> args = MiscUtils.castToMap(map, false);
|
||||||
|
String itemName = args.getOrDefault("item", "minecraft:stone").toString();
|
||||||
|
Item<Object> item = createSafeItem(itemName);
|
||||||
|
if (args.containsKey("count")) {
|
||||||
|
item.count(ResourceConfigUtils.getAsInt(args.get("count"), "count"));
|
||||||
|
}
|
||||||
|
if (VersionHelper.isOrAbove1_20_5() && args.containsKey("components")) {
|
||||||
|
item = new ComponentsModifier<>(MiscUtils.castToMap(args.get("components"), false)).apply(item, ItemBuildContext.empty());
|
||||||
|
}
|
||||||
|
if (!VersionHelper.isOrAbove1_20_5() && args.containsKey("nbt")) {
|
||||||
|
item = new TagsModifier<>(MiscUtils.castToMap(args.get("nbt"), false)).apply(item, ItemBuildContext.empty());
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
} else {
|
||||||
|
String itemName = arguments.toString();
|
||||||
|
return createSafeItem(itemName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Item<Object> createSafeItem(String itemName) {
|
||||||
|
Key itemId = Key.of(itemName);
|
||||||
|
Item<Object> item = CraftEngine.instance().itemManager().createWrappedItem(itemId, null);
|
||||||
|
if (item == null) {
|
||||||
|
item = CraftEngine.instance().itemManager().createWrappedItem(ItemKeys.STONE, null);
|
||||||
|
assert item != null;
|
||||||
|
item.itemNameComponent(Component.text(itemName).color(NamedTextColor.RED));
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,11 @@ package net.momirealms.craftengine.core.plugin.gui;
|
|||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
|
import net.momirealms.craftengine.core.item.trade.MerchantOffer;
|
||||||
import net.momirealms.craftengine.core.plugin.Manageable;
|
import net.momirealms.craftengine.core.plugin.Manageable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface GuiManager extends Manageable {
|
public interface GuiManager extends Manageable {
|
||||||
|
|
||||||
void openInventory(Player player, GuiType guiType);
|
void openInventory(Player player, GuiType guiType);
|
||||||
@@ -11,4 +14,6 @@ public interface GuiManager extends Manageable {
|
|||||||
void updateInventoryTitle(Player player, Component component);
|
void updateInventoryTitle(Player player, Component component);
|
||||||
|
|
||||||
Inventory createInventory(Gui gui, int size);
|
Inventory createInventory(Gui gui, int size);
|
||||||
|
|
||||||
|
void openMerchant(Player player, Component title, List<MerchantOffer<?>> offers);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.locale;
|
package net.momirealms.craftengine.core.plugin.locale;
|
||||||
|
|
||||||
|
import aQute.bnd.annotation.jpms.Open;
|
||||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||||
import net.momirealms.craftengine.core.util.ArrayUtils;
|
import net.momirealms.craftengine.core.util.ArrayUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class LocalizedException extends RuntimeException {
|
public class LocalizedException extends RuntimeException {
|
||||||
private final String node;
|
private final String node;
|
||||||
@@ -72,8 +74,8 @@ public class LocalizedException extends RuntimeException {
|
|||||||
|
|
||||||
private String generateLocalizedMessage() {
|
private String generateLocalizedMessage() {
|
||||||
try {
|
try {
|
||||||
String rawMessage = TranslationManager.instance()
|
String rawMessage = Optional.ofNullable(TranslationManager.instance()
|
||||||
.miniMessageTranslation(this.node);
|
.miniMessageTranslation(this.node)).orElse(this.node);
|
||||||
String cleanMessage = AdventureHelper.miniMessage()
|
String cleanMessage = AdventureHelper.miniMessage()
|
||||||
.stripTags(rawMessage);
|
.stripTags(rawMessage);
|
||||||
for (int i = 0; i < arguments.length; i++) {
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public final class ResourceConfigUtils {
|
|||||||
return raw != null ? function.apply(raw) : defaultValue;
|
return raw != null ? function.apply(raw) : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getAsString(@Nullable Object raw) {
|
public static String getAsStringOrNull(@Nullable Object raw) {
|
||||||
if (raw == null) {
|
if (raw == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user