From 27d79905d0efebc3d919f7e1314301228f822581 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 11 Feb 2025 23:32:44 +0800 Subject: [PATCH 1/3] Add formula factory --- .../default/configuration/templates.yml | 15 +-- .../function/ApplyBonusCountFunction.java | 92 ++++++++++++++++++- .../core/registry/BuiltInRegistries.java | 2 + .../craftengine/core/registry/Registries.java | 2 + 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml index 0c2f24287..142f12bec 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml @@ -329,13 +329,14 @@ templates: conditions: - type: enchantment predicate: minecraft:silk_touch>=1 - - type: item - item: "{ore_drop}" - functions: - - type: apply_bonus - enchantment: minecraft:fortune - formula: ore_drops - - type: explosion_decay + - type: item + item: "{ore_drop}" + functions: + - type: apply_bonus + enchantment: minecraft:fortune + formula: + type: ore_drops + - type: explosion_decay loot_table:leaves: pools: - rolls: 1 diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java b/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java index 9405d6e74..9c9522eec 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java @@ -4,12 +4,25 @@ import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.LootContext; import net.momirealms.craftengine.core.loot.condition.LootCondition; +import net.momirealms.craftengine.core.loot.condition.LootConditions; import net.momirealms.craftengine.core.loot.parameter.LootParameters; +import net.momirealms.craftengine.core.loot.provider.FixedNumberProvider; +import net.momirealms.craftengine.core.loot.provider.NumberProviderFactory; +import net.momirealms.craftengine.core.loot.provider.UniformNumberProvider; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Holder; +import net.momirealms.craftengine.core.registry.Registries; +import net.momirealms.craftengine.core.registry.WritableRegistry; import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.RandomUtils; +import net.momirealms.craftengine.core.util.ResourceKey; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; public class ApplyBonusCountFunction extends AbstractLootConditionalFunction { public static final Factory FACTORY = new Factory<>(); @@ -26,7 +39,7 @@ public class ApplyBonusCountFunction extends AbstractLootConditionalFunction< protected Item applyInternal(Item item, LootContext context) { Optional> itemInHand = context.getOptionalParameter(LootParameters.TOOL); int level = itemInHand.map(value -> value.getEnchantment(this.enchantment).map(Enchantment::level).orElse(0)).orElse(0); - int newCount = formula.apply(item.count(), level); + int newCount = this.formula.apply(item.count(), level); item.count(newCount); return item; } @@ -38,9 +51,21 @@ public class ApplyBonusCountFunction extends AbstractLootConditionalFunction< public static class Factory implements LootFunctionFactory { + @SuppressWarnings("unchecked") @Override public LootFunction create(Map arguments) { - return null; + String enchantment = (String) arguments.get("enchantment"); + if (enchantment == null || enchantment.isEmpty()) { + throw new IllegalArgumentException("enchantment is required"); + } + Map formulaMap = MiscUtils.castToMap(arguments.get("formula"), true); + if (formulaMap == null) { + throw new IllegalArgumentException("formula is required"); + } + List conditions = Optional.ofNullable(arguments.get("conditions")) + .map(it -> LootConditions.fromMapList((List>) it)) + .orElse(Collections.emptyList()); + return new ApplyBonusCountFunction<>(conditions, Key.from(enchantment), Formulas.fromMap(formulaMap)); } } @@ -49,4 +74,67 @@ public class ApplyBonusCountFunction extends AbstractLootConditionalFunction< Key type(); } + + public interface FormulaFactory { + + Formula create(Map arguments); + } + + public static class Formulas { + public static final Key ORE_DROPS = Key.of("craftengine:ore_drops"); + + static { + register(ORE_DROPS, OreDrops.FACTORY); + } + + public static void register(Key key, FormulaFactory factory) { + Holder.Reference holder = ((WritableRegistry) BuiltInRegistries.FORMULA_FACTORY) + .registerForHolder(new ResourceKey<>(Registries.FORMULA_FACTORY.location(), key)); + holder.bindValue(factory); + } + + public static Formula fromMap(Map map) { + String type = (String) map.get("type"); + if (type == null) { + throw new NullPointerException("number type cannot be null"); + } + Key key = Key.withDefaultNamespace(type, "craftengine"); + FormulaFactory factory = BuiltInRegistries.FORMULA_FACTORY.getValue(key); + if (factory == null) { + throw new IllegalArgumentException("Unknown formula type: " + type); + } + return factory.create(map); + } + } + + public static class OreDrops implements Formula { + public static final Factory FACTORY = new Factory(); + private static final OreDrops INSTANCE = new OreDrops(); + + @Override + public int apply(int initialCount, int enchantmentLevel) { + if (enchantmentLevel > 0) { + int i = ThreadLocalRandom.current().nextInt(enchantmentLevel + 2) - 1; + if (i < 0) { + i = 0; + } + return initialCount * (i + 1); + } else { + return initialCount; + } + } + + @Override + public Key type() { + return Formulas.ORE_DROPS; + } + + public static class Factory implements FormulaFactory { + + @Override + public Formula create(Map arguments) { + return INSTANCE; + } + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java index 01d643c65..8b6a3ecdc 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java @@ -7,6 +7,7 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.recipe.RecipeFactory; import net.momirealms.craftengine.core.loot.condition.LootConditionFactory; import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory; +import net.momirealms.craftengine.core.loot.function.ApplyBonusCountFunction; import net.momirealms.craftengine.core.loot.function.LootFunctionFactory; import net.momirealms.craftengine.core.loot.provider.NumberProviderFactory; import net.momirealms.craftengine.core.pack.model.ItemModelFactory; @@ -37,6 +38,7 @@ public class BuiltInRegistries { public static final Registry CONDITION_PROPERTY_FACTORY = createRegistry(Registries.CONDITION_PROPERTY_FACTORY); public static final Registry SELECT_PROPERTY_FACTORY = createRegistry(Registries.SELECT_PROPERTY_FACTORY); public static final Registry> RECIPE_FACTORY = createRegistry(Registries.RECIPE_FACTORY); + public static final Registry FORMULA_FACTORY = createRegistry(Registries.FORMULA_FACTORY); private static Registry createRegistry(ResourceKey> key) { return new MappedRegistry<>(key); diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java index bb829c583..e7f030d1a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java @@ -7,6 +7,7 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.recipe.RecipeFactory; import net.momirealms.craftengine.core.loot.condition.LootConditionFactory; import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory; +import net.momirealms.craftengine.core.loot.function.ApplyBonusCountFunction; import net.momirealms.craftengine.core.loot.function.LootFunctionFactory; import net.momirealms.craftengine.core.loot.provider.NumberProviderFactory; import net.momirealms.craftengine.core.pack.model.ItemModelFactory; @@ -38,4 +39,5 @@ public class Registries { public static final ResourceKey> CONDITION_PROPERTY_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("condition_property_factory")); public static final ResourceKey> SELECT_PROPERTY_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("select_property_factory")); public static final ResourceKey>> RECIPE_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("recipe_factory")); + public static final ResourceKey> FORMULA_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("formula_factory")); } From b6e93d75384c59f24abfbde06522ccca198c61f7 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 11 Feb 2025 23:33:23 +0800 Subject: [PATCH 2/3] Update templates.yml --- .../resources/resources/default/configuration/templates.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml index 142f12bec..3e739a5cd 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml @@ -319,8 +319,6 @@ templates: loot_table:ore: pools: - rolls: 1 - conditions: - - type: survives_explosion entries: - type: alternatives children: From 4c13a0b7cf83b90dcfca8507ebb0ee46e1db8115 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 11 Feb 2025 23:42:23 +0800 Subject: [PATCH 3/3] Update BlockEventListener.java --- .../craftengine/bukkit/block/BlockEventListener.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index 786bcee1d..ec0334f21 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -12,6 +12,7 @@ import net.momirealms.craftengine.core.block.EmptyBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.PushReaction; import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.parameter.LootParameters; import net.momirealms.craftengine.core.plugin.config.ConfigManager; @@ -116,10 +117,12 @@ public class BlockEventListener implements Listener { return; } + BukkitServerPlayer serverPlayer = plugin.adapt(player); // drop items ContextHolder.Builder builder = ContextHolder.builder(); builder.withParameter(LootParameters.LOCATION, vec3d); builder.withParameter(LootParameters.PLAYER, plugin.adapt(player)); + builder.withParameter(LootParameters.TOOL, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND)); for (Item item : state.getDrops(builder, world)) { world.dropItemNaturally(vec3d, item); }