From a67e1d37787d7083fd40550b9be0c9512d1496f5 Mon Sep 17 00:00:00 2001
From: XiaoMoMi <972454774@qq.com>
Date: Thu, 23 Oct 2025 18:40:20 +0800
Subject: [PATCH 1/5] =?UTF-8?q?=E9=87=8D=E6=96=B0=E5=AE=89=E6=8E=92?=
=?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E9=A1=BA=E5=BA=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
common-files/src/main/resources/config.yml | 175 +++++++++++----------
1 file changed, 94 insertions(+), 81 deletions(-)
diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml
index f2f55ecfd..0b0edda7b 100644
--- a/common-files/src/main/resources/config.yml
+++ b/common-files/src/main/resources/config.yml
@@ -13,57 +13,6 @@ resource-pack:
# This option determines the location of the generated resource pack
# You can use either an absolute path or a relative path here
path: "./generated/resource_pack.zip"
- # Should those images in minecraft:default font also work in minecraft:uniform
- override-uniform-font: true
- # Generate assets for CraftEngine fabric mod
- # Note: fabric mod is used for clientside Axiom/WorldEdit mod
- generate-mod-assets: false
- # Resource pack protection
- protection:
- # Warning: Do not attempt to unzip the resource pack with crash tools enabled.
- # You can enable all the methods at the same time.
- crash-tools:
- method-1: false
- method-2: false
- method-3: false # Enable this would increase the resource pack size by 0.67MB
- # [Premium Exclusive]
- # Obfuscate your resource pack
- obfuscation:
- enable: false
- seed: 0 # 0 = random seed
- fake-directory: false
- escape-unicode: false
- resource-location:
- enable: true
- random-namespace:
- amount: 16 # 0 = disable
- length: 9
- random-path:
- source: obf
- depth: 16
- anti-unzip: false
- random-atlas:
- images-per-canvas: 32 # 0 = disable
- # Sometimes, some vanilla files that have been overwritten might be mistakenly obfuscated.
- # Please add the ignored textures/models/sounds here.
- bypass-textures:
- # - minecraft:block/farmland
- - "@legacy_unicode"
- - "@vanilla_textures"
- bypass-models:
- - "@vanilla_models"
- bypass-sounds: []
- bypass-equipments: []
- # Validate if there is any error in the resource pack, such as missing textures or models
- # If your resource pack is compliant with the standard, you can disable validation to improve the resource pack generation speed.
- validation:
- enable: true
- # [Premium Exclusive]
- # Fix images that are not within the texture atlas. It is unreasonable to always rely on plugins to fix your mistakes.
- # You should strive to make your resource pack more standardized after gaining some experience with resource packs.
- fix-atlas: true
- # Define the name of the overlay folders
- overlay-format: "ce_overlay_{version}"
# Allowed values:
# - 1.20.1, 1.21, 1.21.8, etc.
# - LATEST: the latest client version
@@ -73,42 +22,24 @@ resource-pack:
max: LATEST
# Remove 1.21.5+ tinted_leaves particles
remove-tinted-leaves-particle: true
+ # Define the name of the overlay folders
+ overlay-format: "ce_overlay_{version}"
+ # Should those images in minecraft:default font also work in minecraft:uniform
+ override-uniform-font: true
+ # Generate assets for CraftEngine fabric mod
+ # Note: fabric mod is used for clientside Axiom/WorldEdit mod
+ generate-mod-assets: false
+ # Exclude the shaders when generating the resource pack
+ exclude-core-shaders: false
+ # Merge other packs
merge-external-folders:
- "ModelEngine/resource pack"
merge-external-zip-files:
- "CustomNameplates/resourcepack.zip"
- "BetterModel/build.zip"
exclude-file-extensions: ["md", "psd", "bbmodel", "db", "ini", "DS_Store"]
- # Exclude the shaders when generating the resource pack
- exclude-core-shaders: false
- delivery:
- # Send the resource pack on joining the server
- send-on-join: true
- kick-if-declined: true
- kick-if-failed-to-apply: false
- prompt: "To fully experience our server,please accept our custom resource pack. "
- # If you are hosting the resource pack by yourself, replace `localhost` with your server ip otherwise it would only work on your local pc
- # If using BungeeCord or Velocity, consider using a proxy-side plugin to handle resource pack delivery.
- # Read this page for more host types: https://xiao-momi.github.io/craft-engine-wiki/getting_start/set_up_host
- hosting:
- - type: "self"
- ip: "localhost"
- port: 8163
- protocol: "http"
- deny-non-minecraft-request: true
- one-time-token: true
- rate-limit:
- max-requests: 10
- reset-interval: 30
- # Upload the resource pack automatically on generation
- # When disabled, you must manually trigger uploads using the /ce upload command
- auto-upload: true
- # The file to upload
- file-to-upload: "./generated/resource_pack.zip"
- # Resend the resource pack to players upon successful upload
- resend-on-upload: true
- # Whether a verified player UUID is required to get the resource pack
- strict-player-uuid-validation: true
+ # Provide the solution for when a file conflict is encountered
+ # https://xiao-momi.github.io/craft-engine-wiki/reference/file_conflict
duplicated-files-handler:
- term:
type: any_of
@@ -150,6 +81,88 @@ resource-pack:
suffix: "minecraft/atlases"
resolution:
type: merge_atlas
+ # Validate if there is any error in the resource pack, such as missing textures or models
+ # If your resource pack is compliant with the standard, you can disable validation to improve the resource pack generation speed.
+ validation:
+ enable: true
+ # [Premium Exclusive]
+ # Fix images that are not within the texture atlas. It is unreasonable to always rely on plugins to fix your mistakes.
+ # You should strive to make your resource pack more standardized after gaining some experience with resource packs.
+ fix-atlas: true
+ # Optimize your resource pack by reducing its size
+ optimization:
+ enable: true
+ png:
+ color-quantization: true
+ lossless-bit-depth: true
+ remove-metadata: true
+ model:
+ minimize: true
+ bypass-textures: []
+ # Protect your resource pack from being cracked by others
+ protection:
+ # Prevent thieves from extracting your resource pack. These options will crash their software.
+ crash-tools:
+ method-1: false
+ method-2: false
+ method-3: false # Enable this would increase the resource pack size by 0.67MB
+ # [Premium Exclusive]
+ # Obfuscate your resource pack to prevent thieves from restoring its original structure
+ obfuscation:
+ enable: false
+ seed: 0 # 0 = random seed
+ fake-directory: false # Create fake folders to deceive thieves
+ escape-unicode: false # Escape the JSON to make it human-unreadable
+ resource-location:
+ enable: true
+ random-namespace:
+ amount: 8 # 0 = disable
+ length: 9
+ random-path:
+ source: obf
+ depth: 8
+ anti-unzip: false
+ random-atlas:
+ images-per-canvas: 256 # 0 = disable
+ # Sometimes, some vanilla files that have been overwritten might be mistakenly obfuscated
+ # Please add the ignored textures/models/sounds here if that happens
+ bypass-textures:
+ # - minecraft:block/farmland
+ - "@legacy_unicode"
+ - "@vanilla_textures"
+ bypass-models:
+ - "@vanilla_models"
+ bypass-sounds: []
+ bypass-equipments: []
+ # This section controls how to send the resource pack to players
+ delivery:
+ # Send the resource pack on joining the server
+ send-on-join: true
+ kick-if-declined: true
+ kick-if-failed-to-apply: false
+ prompt: "To fully experience our server,please accept our custom resource pack. "
+ # Whether a verified player UUID is required to download the resource pack
+ strict-player-uuid-validation: true
+ # Upload the resource pack automatically on generation
+ # When disabled, you must manually trigger uploads using the /ce upload command
+ auto-upload: true
+ # Resend the resource pack to players upon successful upload
+ resend-on-upload: true
+ # The file to upload
+ file-to-upload: "./generated/resource_pack.zip"
+ # If you are hosting the resource pack by yourself, replace `localhost` with your server ip otherwise it would only work on your local pc
+ # If using BungeeCord or Velocity, consider using a proxy-side plugin to handle resource pack delivery.
+ # Read this page for more host types: https://xiao-momi.github.io/craft-engine-wiki/getting_start/set_up_host
+ hosting:
+ - type: "self"
+ ip: "localhost"
+ port: 8163
+ protocol: "http"
+ deny-non-minecraft-request: true
+ one-time-token: true
+ rate-limit:
+ max-requests: 10
+ reset-interval: 30
item:
# [Premium Exclusive]
From a0fc9efb25624416bfaff3b08790c9b0268d39db Mon Sep 17 00:00:00 2001
From: XiaoMoMi <972454774@qq.com>
Date: Thu, 23 Oct 2025 18:42:17 +0800
Subject: [PATCH 2/5] =?UTF-8?q?=E4=BC=98=E5=8C=96text=20provider?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../craftengine/core/plugin/context/text/TagTextProvider.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/text/TagTextProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/text/TagTextProvider.java
index 11c63ac21..4942d64cb 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/text/TagTextProvider.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/text/TagTextProvider.java
@@ -18,8 +18,8 @@ public class TagTextProvider implements TextProvider {
@Override
public String get(Context context) {
- Component resultComponent = AdventureHelper.customMiniMessage().deserialize(this.text, context.tagResolvers());
- return AdventureHelper.plainTextContent(resultComponent);
+ Component resultComponent = AdventureHelper.miniMessage().deserialize(this.text, context.tagResolvers());
+ return AdventureHelper.strictMiniMessage().serialize(resultComponent);
}
@Override
From fb8b72d279e889a59078a932415c9ad5cda81c6f Mon Sep 17 00:00:00 2001
From: XiaoMoMi <972454774@qq.com>
Date: Thu, 23 Oct 2025 19:53:19 +0800
Subject: [PATCH 3/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=86=E6=94=AF?=
=?UTF-8?q?=E5=87=BD=E6=95=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/resources/translations/en.yml | 2 +
.../entry/AlternativesLootEntryContainer.java | 3 +-
.../core/loot/entry/LootEntryContainers.java | 2 +
.../plugin/context/event/EventFunctions.java | 3 +
.../function/AbstractConditionalFunction.java | 68 +++++++++++++++----
.../context/function/AllOfFunction.java | 31 +++++++++
.../context/function/CommonFunctions.java | 5 ++
.../context/function/DummyFunction.java | 16 +++++
.../plugin/context/function/Function.java | 23 +++++++
.../context/function/IfElseFunction.java | 56 +++++++++++++++
.../plugin/context/function/WhenFunction.java | 63 +++++++++++++++++
11 files changed, 259 insertions(+), 13 deletions(-)
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AllOfFunction.java
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DummyFunction.java
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/IfElseFunction.java
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/WhenFunction.java
diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml
index 7ebdaae1c..935633551 100644
--- a/common-files/src/main/resources/translations/en.yml
+++ b/common-files/src/main/resources/translations/en.yml
@@ -472,6 +472,8 @@ warning.config.function.toast.invalid_advancement_type: "Issue found in
warning.config.function.merchant_trade.missing_offers: "Issue found in file - The config '' is missing the required 'offers' argument for 'merchant_trade' function. "
warning.config.function.merchant_trade.offer.missing_cost_1: "Issue found in file - The config '' is missing the required 'cost-1' argument for merchant trade offers. "
warning.config.function.merchant_trade.offer.missing_result: "Issue found in file - The config '' is missing the required 'result' argument for merchant trade offers. "
+warning.config.function.when.missing_source: "Issue found in file - The config '' is missing the required 'source' argument for 'when' function. "
+warning.config.function.if_else.missing_rules: "Issue found in file - The config '' is missing the required 'rules' argument for 'if_else' function. "
warning.config.selector.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for selector. "
warning.config.selector.invalid_type: "Issue found in file - The config '' is using an invalid selector type ''. "
warning.config.selector.invalid_target: "Issue found in file - The config '' is using an invalid selector target ''. "
diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/AlternativesLootEntryContainer.java b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/AlternativesLootEntryContainer.java
index 9ed2f42e4..18cb4ff0b 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/AlternativesLootEntryContainer.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/AlternativesLootEntryContainer.java
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.loot.LootConditions;
import net.momirealms.craftengine.core.loot.LootContext;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.util.Key;
+import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.*;
@@ -40,7 +41,7 @@ public class AlternativesLootEntryContainer extends AbstractCompositeLootEntr
@SuppressWarnings("unchecked")
@Override
public LootEntryContainer create(Map arguments) {
- List> containers = Optional.ofNullable(arguments.get("children"))
+ List> containers = Optional.ofNullable(ResourceConfigUtils.get(arguments, "children", "terms", "branches"))
.map(it -> (List>) new ArrayList>(LootEntryContainers.fromMapList((List>) it)))
.orElse(Collections.emptyList());
List> conditions = Optional.ofNullable(arguments.get("conditions"))
diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java
index d2d8abaeb..82c667a40 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java
@@ -14,12 +14,14 @@ import java.util.Map;
public class LootEntryContainers {
public static final Key ALTERNATIVES = Key.from("craftengine:alternatives");
+ public static final Key IF_ELSE = Key.from("craftengine:if_else");
public static final Key ITEM = Key.from("craftengine:item");
public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item");
public static final Key EXP = Key.from("craftengine:exp");
static {
register(ALTERNATIVES, AlternativesLootEntryContainer.FACTORY);
+ register(IF_ELSE, AlternativesLootEntryContainer.FACTORY);
register(ITEM, SingleItemLootEntryContainer.FACTORY);
register(EXP, ExpLootEntryContainer.FACTORY);
register(FURNITURE_ITEM, FurnitureItemLootEntryContainer.FACTORY);
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java
index 4646eeb92..b7a2d6c46 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java
@@ -48,6 +48,9 @@ public class EventFunctions {
register(CommonFunctions.DAMAGE, new DamageFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.MERCHANT_TRADE, new MerchantTradeFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.REMOVE_ENTITY, new RemoveEntityFunction.FactoryImpl<>(EventConditions::fromMap));
+ register(CommonFunctions.IF_ELSE, new IfElseFunction.FactoryImpl<>(EventConditions::fromMap, EventFunctions::fromMap));
+ register(CommonFunctions.ALTERNATIVES, new IfElseFunction.FactoryImpl<>(EventConditions::fromMap, EventFunctions::fromMap));
+ register(CommonFunctions.WHEN, new WhenFunction.FactoryImpl<>(EventConditions::fromMap, EventFunctions::fromMap));
}
public static void register(Key key, FunctionFactory factory) {
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AbstractConditionalFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AbstractConditionalFunction.java
index 4c20d65a7..1f90610f2 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AbstractConditionalFunction.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AbstractConditionalFunction.java
@@ -28,29 +28,73 @@ public abstract class AbstractConditionalFunction implement
protected abstract void runInternal(CTX ctx);
public static abstract class AbstractFactory implements FunctionFactory {
- private final java.util.function.Function, Condition> factory;
+ protected final java.util.function.Function, Condition> conditionFactory;
- public AbstractFactory(java.util.function.Function, Condition> factory) {
- this.factory = factory;
+ public AbstractFactory(java.util.function.Function, Condition> conditionFactory) {
+ this.conditionFactory = conditionFactory;
}
public java.util.function.Function, Condition> conditionFactory() {
- return factory;
+ return this.conditionFactory;
}
protected List> getPredicates(Map arguments) {
+ if (arguments == null) return List.of();
Object predicates = arguments.get("conditions");
if (predicates == null) return List.of();
- if (predicates instanceof List> list) {
- List> conditions = new ArrayList<>(list.size());
- for (Object o : list) {
- conditions.add(factory.apply(MiscUtils.castToMap(o, false)));
+ switch (predicates) {
+ case List> list -> {
+ List> conditions = new ArrayList<>(list.size());
+ for (Object o : list) {
+ conditions.add(this.conditionFactory.apply(MiscUtils.castToMap(o, false)));
+ }
+ return conditions;
+ }
+ case Map, ?> map -> {
+ return List.of(this.conditionFactory.apply(MiscUtils.castToMap(map, false)));
+ }
+ default -> {
+ return List.of();
+ }
+ }
+ }
+ }
+
+ public static abstract class AbstractFunctionalFactory extends AbstractFactory {
+ protected final java.util.function.Function, Function> functionFactory;
+
+ public AbstractFunctionalFactory(java.util.function.Function, Condition> factory, java.util.function.Function, Function> functionFactory) {
+ super(factory);
+ this.functionFactory = functionFactory;
+ }
+
+ public java.util.function.Function, Function> functionFactory() {
+ return functionFactory;
+ }
+
+ protected List> getFunctions(Map arguments) {
+ if (arguments == null) return List.of();
+ Object functions = arguments.get("functions");
+ return parseFunctions(functions);
+ }
+
+ protected List> parseFunctions(Object functions) {
+ if (functions == null) return List.of();
+ switch (functions) {
+ case List> list -> {
+ List> conditions = new ArrayList<>(list.size());
+ for (Object o : list) {
+ conditions.add(this.functionFactory.apply(MiscUtils.castToMap(o, false)));
+ }
+ return conditions;
+ }
+ case Map, ?> map -> {
+ return List.of(this.functionFactory.apply(MiscUtils.castToMap(map, false)));
+ }
+ default -> {
+ return List.of();
}
- return conditions;
- } else if (predicates instanceof Map,?> map) {
- return List.of(factory.apply(MiscUtils.castToMap(map, false)));
}
- throw new UnsupportedOperationException("Unsupported conditions argument class type: " + predicates.getClass().getSimpleName());
}
}
}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AllOfFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AllOfFunction.java
new file mode 100644
index 000000000..1f2810c24
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/AllOfFunction.java
@@ -0,0 +1,31 @@
+package net.momirealms.craftengine.core.plugin.context.function;
+
+import net.momirealms.craftengine.core.plugin.context.Context;
+import net.momirealms.craftengine.core.util.Key;
+
+import java.util.Collection;
+
+public class AllOfFunction implements Function {
+ private final Function[] functions;
+
+ public AllOfFunction(Function[] functions) {
+ this.functions = functions;
+ }
+
+ @SuppressWarnings("unchecked")
+ public AllOfFunction(Collection> functions) {
+ this.functions = functions.toArray(new Function[0]);
+ }
+
+ @Override
+ public void run(CTX ctx) {
+ for (Function function : this.functions) {
+ function.run(ctx);
+ }
+ }
+
+ @Override
+ public Key type() {
+ return CommonFunctions.ALL_OF;
+ }
+}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java
index ce9dff89a..273343022 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java
@@ -37,4 +37,9 @@ public final class CommonFunctions {
public static final Key DAMAGE = Key.of("craftengine:damage");
public static final Key MERCHANT_TRADE = Key.of("craftengine:merchant_trade");
public static final Key REMOVE_ENTITY = Key.of("craftengine:remove_entity");
+ public static final Key IF_ELSE = Key.of("craftengine:if_else");
+ public static final Key ALTERNATIVES = Key.of("craftengine:alternatives");
+ public static final Key WHEN = Key.of("craftengine:when");
+ public static final Key ALL_OF = Key.of("craftengine:all_of");
+ public static final Key DUMMY = Key.of("craftengine:dummy");
}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DummyFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DummyFunction.java
new file mode 100644
index 000000000..080be0808
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DummyFunction.java
@@ -0,0 +1,16 @@
+package net.momirealms.craftengine.core.plugin.context.function;
+
+import net.momirealms.craftengine.core.plugin.context.Context;
+import net.momirealms.craftengine.core.util.Key;
+
+public class DummyFunction implements Function {
+
+ @Override
+ public void run(CTX ctx) {
+ }
+
+ @Override
+ public Key type() {
+ return CommonFunctions.DUMMY;
+ }
+}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/Function.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/Function.java
index 968feb369..9296ba624 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/Function.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/Function.java
@@ -3,9 +3,32 @@ package net.momirealms.craftengine.core.plugin.context.function;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.util.Key;
+import java.util.List;
+
public interface Function {
void run(CTX ctx);
Key type();
+
+ static Function allOf(List> functions) {
+ if (functions == null || functions.isEmpty()) {
+ return new DummyFunction<>();
+ }
+ if (functions.size() == 1) {
+ return functions.getFirst();
+ }
+ return new AllOfFunction<>(functions);
+ }
+
+ @SafeVarargs
+ static Function allOf(Function... functions) {
+ if (functions == null || functions.length == 0) {
+ return new DummyFunction<>();
+ }
+ if (functions.length == 1) {
+ return functions[0];
+ }
+ return new AllOfFunction<>(functions);
+ }
}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/IfElseFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/IfElseFunction.java
new file mode 100644
index 000000000..70611d061
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/IfElseFunction.java
@@ -0,0 +1,56 @@
+package net.momirealms.craftengine.core.plugin.context.function;
+
+import net.momirealms.craftengine.core.plugin.context.Condition;
+import net.momirealms.craftengine.core.plugin.context.Context;
+import net.momirealms.craftengine.core.util.Key;
+import net.momirealms.craftengine.core.util.MiscUtils;
+import net.momirealms.craftengine.core.util.Pair;
+import net.momirealms.craftengine.core.util.ResourceConfigUtils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+
+public class IfElseFunction extends AbstractConditionalFunction {
+ private final List, Function>> conditions;
+
+ public IfElseFunction(List> predicates, List, Function>> conditions) {
+ super(predicates);
+ this.conditions = conditions;
+ }
+
+ @Override
+ public void runInternal(CTX ctx) {
+ for (Pair, Function> condition : this.conditions) {
+ if (condition.left().test(ctx)) {
+ condition.right().run(ctx);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public Key type() {
+ return CommonFunctions.IF_ELSE;
+ }
+
+ public static class FactoryImpl extends AbstractFunctionalFactory {
+
+ public FactoryImpl(java.util.function.Function, Condition> conditionFactory, java.util.function.Function, Function> functionFactory) {
+ super(conditionFactory, functionFactory);
+ }
+
+ @Override
+ public Function create(Map arguments) {
+ List, Function>> branches = ResourceConfigUtils.parseConfigAsList(
+ ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "rules", "rule"), "warning.config.function.if_else.missing_rules"),
+ map -> {
+ List> conditions = getPredicates(map);
+ List> functions = getFunctions(map);
+ return new Pair<>(MiscUtils.allOf(conditions), Function.allOf(functions));
+ }
+ );
+ return new IfElseFunction<>(getPredicates(arguments), branches);
+ }
+ }
+}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/WhenFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/WhenFunction.java
new file mode 100644
index 000000000..fa55a77a9
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/WhenFunction.java
@@ -0,0 +1,63 @@
+package net.momirealms.craftengine.core.plugin.context.function;
+
+import net.momirealms.craftengine.core.plugin.context.Condition;
+import net.momirealms.craftengine.core.plugin.context.Context;
+import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
+import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
+import net.momirealms.craftengine.core.util.Key;
+import net.momirealms.craftengine.core.util.MiscUtils;
+import net.momirealms.craftengine.core.util.Pair;
+import net.momirealms.craftengine.core.util.ResourceConfigUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class WhenFunction extends AbstractConditionalFunction {
+ private final TextProvider source;
+ private final Map> whenMap;
+ private final Function fallback;
+
+ public WhenFunction(List> predicates, TextProvider source, Map> whenMap, Function fallback) {
+ super(predicates);
+ this.whenMap = whenMap;
+ this.source = source;
+ this.fallback = fallback;
+ }
+
+ @Override
+ public void runInternal(CTX ctx) {
+ String text = this.source.get(ctx);
+ Function function = this.whenMap.getOrDefault(text, this.fallback);
+ function.run(ctx);
+ }
+
+ @Override
+ public Key type() {
+ return CommonFunctions.IF_ELSE;
+ }
+
+ public static class FactoryImpl extends AbstractFunctionalFactory {
+
+ public FactoryImpl(java.util.function.Function, Condition> conditionFactory, java.util.function.Function, Function> functionFactory) {
+ super(conditionFactory, functionFactory);
+ }
+
+ @Override
+ public Function create(Map arguments) {
+ TextProvider source = TextProviders.fromString(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("source"), "warning.config.function.when.missing_source"));
+ List, Function>> list = ResourceConfigUtils.parseConfigAsList(arguments.get("cases"), map -> {
+ List when = MiscUtils.getAsStringList(map.get("when"));
+ List> functions = getFunctions(map);
+ return Pair.of(when, Function.allOf(functions));
+ });
+ Map> whenMap = new HashMap<>();
+ for (Pair, Function> pair : list) {
+ for (String when : pair.left()) {
+ whenMap.put(when, pair.right());
+ }
+ }
+ return new WhenFunction<>(getPredicates(arguments), source, whenMap, Function.allOf(parseFunctions(arguments.get("fallback"))));
+ }
+ }
+}
From 21a89a818bb0e8727a4d3cbe55b424998fc4c53c Mon Sep 17 00:00:00 2001
From: XiaoMoMi <972454774@qq.com>
Date: Thu, 23 Oct 2025 20:41:02 +0800
Subject: [PATCH 4/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84?=
=?UTF-8?q?=E6=96=B9=E5=9D=97=E7=9B=B8=E5=85=B3=E5=87=BD=E6=95=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../blocks/ender_pearl_flower.yml | 7 +-
.../configuration/blocks/magma_plant.yml | 3 +-
.../src/main/resources/translations/en.yml | 2 +
core/build.gradle.kts | 2 +-
.../craftengine/core/loot/LootConditions.java | 1 +
.../context/condition/CommonConditions.java | 1 +
.../context/condition/HasItemCondition.java | 38 ++++++++
.../context/condition/HasPlayerCondition.java | 2 +-
.../context/condition/MatchItemCondition.java | 2 +-
.../plugin/context/event/EventConditions.java | 1 +
.../plugin/context/event/EventFunctions.java | 2 +
.../context/function/CommonFunctions.java | 2 +
.../context/function/PlaceBlockFunction.java | 11 ++-
.../function/TransformBlockFunction.java | 96 +++++++++++++++++++
.../function/UpdateBlockPropertyFunction.java | 78 +++++++++++++++
15 files changed, 233 insertions(+), 15 deletions(-)
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasItemCondition.java
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TransformBlockFunction.java
create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateBlockPropertyFunction.java
diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml b/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml
index 1966ea9b1..0847ee653 100644
--- a/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml
+++ b/common-files/src/main/resources/resources/default/configuration/blocks/ender_pearl_flower.yml
@@ -64,11 +64,8 @@ blocks:
- type: match_block_property
properties:
age: 2
- - type: '!is_null'
- argument: item_in_hand
- - type: equals
- value1:
- value2: default:ender_pearl_flower_seeds
+ - type: match_item
+ id: default:ender_pearl_flower_seeds
functions:
- type: break_block
x:
diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml b/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml
index 6161f21e8..7eb0e196b 100644
--- a/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml
+++ b/common-files/src/main/resources/resources/default/configuration/blocks/magma_plant.yml
@@ -132,10 +132,9 @@ blocks:
- type: match_block_property
properties:
age: 3
- - type: 'is_null'
- argument: item_in_hand
- type: hand
hand: main_hand
+ - type: '!has_item'
functions:
- type: break_block
x:
diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml
index 935633551..9ebd2a6fb 100644
--- a/common-files/src/main/resources/translations/en.yml
+++ b/common-files/src/main/resources/translations/en.yml
@@ -474,6 +474,8 @@ warning.config.function.merchant_trade.offer.missing_cost_1: "Issue foun
warning.config.function.merchant_trade.offer.missing_result: "Issue found in file - The config '' is missing the required 'result' argument for merchant trade offers. "
warning.config.function.when.missing_source: "Issue found in file - The config '' is missing the required 'source' argument for 'when' function. "
warning.config.function.if_else.missing_rules: "Issue found in file - The config '' is missing the required 'rules' argument for 'if_else' function. "
+warning.config.function.update_block_property.missing_properties: "Issue found in file - The config '' is missing the required 'properties' argument for 'update_block_property' function. "
+warning.config.function.transform_block.missing_block: "Issue found in file - The config '' is missing the required 'block' argument for 'transform_block' function. "
warning.config.selector.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for selector. "
warning.config.selector.invalid_type: "Issue found in file - The config '' is using an invalid selector type ''. "
warning.config.selector.invalid_target: "Issue found in file - The config '' is using an invalid selector target ''. "
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index 9efbbf559..9ad35c52d 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -21,7 +21,7 @@ dependencies {
implementation("net.momirealms:sparrow-nbt-codec:${rootProject.properties["sparrow_nbt_version"]}")
implementation("net.momirealms:sparrow-nbt-legacy-codec:${rootProject.properties["sparrow_nbt_version"]}")
// S3
- implementation("net.momirealms:craft-engine-s3:0.7")
+ implementation("net.momirealms:craft-engine-s3:0.8")
// Util
compileOnly("net.momirealms:sparrow-util:${rootProject.properties["sparrow_util_version"]}")
// Adventure
diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java
index 48a06d68d..eea0f0f4b 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/loot/LootConditions.java
@@ -25,6 +25,7 @@ public class LootConditions {
register(CommonConditions.ANY_OF, new AnyOfCondition.FactoryImpl<>(LootConditions::fromMap));
register(CommonConditions.ALL_OF, new AllOfCondition.FactoryImpl<>(LootConditions::fromMap));
register(CommonConditions.HAS_PLAYER, new HasPlayerCondition.FactoryImpl<>());
+ register(CommonConditions.HAS_ITEM, new HasItemCondition.FactoryImpl<>());
register(CommonConditions.ENCHANTMENT, new EnchantmentCondition.Factory<>());
register(CommonConditions.INVERTED, new InvertedCondition.FactoryImpl<>(LootConditions::fromMap));
register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>());
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java
index ea6b27e80..991ea9e0a 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java
@@ -11,6 +11,7 @@ public final class CommonConditions {
public static final Key ANY_OF = Key.of("craftengine:any_of");
public static final Key INVERTED = Key.of("craftengine:inverted");
public static final Key MATCH_ITEM = Key.of("craftengine:match_item");
+ public static final Key HAS_ITEM = Key.of("craftengine:has_item");
public static final Key MATCH_ENTITY = Key.of("craftengine:match_entity");
public static final Key MATCH_BLOCK = Key.of("craftengine:match_block");
public static final Key MATCH_BLOCK_PROPERTY = Key.from("craftengine:match_block_property");
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasItemCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasItemCondition.java
new file mode 100644
index 000000000..213ffd206
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasItemCondition.java
@@ -0,0 +1,38 @@
+package net.momirealms.craftengine.core.plugin.context.condition;
+
+import net.momirealms.craftengine.core.item.Item;
+import net.momirealms.craftengine.core.plugin.context.Condition;
+import net.momirealms.craftengine.core.plugin.context.Context;
+import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
+import net.momirealms.craftengine.core.util.ItemUtils;
+import net.momirealms.craftengine.core.util.Key;
+
+import java.util.Map;
+import java.util.Optional;
+
+public class HasItemCondition implements Condition {
+
+ public HasItemCondition() {
+ }
+
+ @Override
+ public Key type() {
+ return CommonConditions.HAS_ITEM;
+ }
+
+ @Override
+ public boolean test(CTX ctx) {
+ Optional- > item = ctx.getOptionalParameter(DirectContextParameters.ITEM_IN_HAND);
+ if (item.isEmpty()) return false;
+ Item> itemInHand = item.get();
+ return !ItemUtils.isEmpty(itemInHand);
+ }
+
+ public static class FactoryImpl
implements ConditionFactory {
+
+ @Override
+ public Condition create(Map arguments) {
+ return new HasItemCondition<>();
+ }
+ }
+}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasPlayerCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasPlayerCondition.java
index 580a34b95..69d6f211e 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasPlayerCondition.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/HasPlayerCondition.java
@@ -14,7 +14,7 @@ public class HasPlayerCondition implements Condition {
@Override
public Key type() {
- return CommonConditions.IS_NULL;
+ return CommonConditions.HAS_PLAYER;
}
@Override
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchItemCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchItemCondition.java
index f6c7f78a8..ae467cf1b 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchItemCondition.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/MatchItemCondition.java
@@ -35,7 +35,7 @@ public class MatchItemCondition implements Condition {
@Override
public Condition create(Map arguments) {
- List ids = MiscUtils.getAsStringList(arguments.get("id"));
+ List ids = MiscUtils.getAsStringList(ResourceConfigUtils.get(arguments, "id", "item"));
if (ids.isEmpty()) {
throw new LocalizedResourceConfigException("warning.config.condition.match_item.missing_id");
}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java
index e6cd3a304..6e34277e6 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java
@@ -17,6 +17,7 @@ public class EventConditions {
static {
register(CommonConditions.HAS_PLAYER, new HasPlayerCondition.FactoryImpl<>());
+ register(CommonConditions.HAS_ITEM, new HasItemCondition.FactoryImpl<>());
register(CommonConditions.MATCH_ITEM, new MatchItemCondition.FactoryImpl<>());
register(CommonConditions.MATCH_ENTITY, new MatchEntityCondition.FactoryImpl<>());
register(CommonConditions.MATCH_BLOCK, new MatchBlockCondition.FactoryImpl<>());
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java
index b7a2d6c46..16cadd38a 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java
@@ -24,6 +24,8 @@ public class EventFunctions {
register(CommonFunctions.CANCEL_EVENT, new CancelEventFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.RUN, new RunFunction.FactoryImpl<>(EventFunctions::fromMap, EventConditions::fromMap));
register(CommonFunctions.PLACE_BLOCK, new PlaceBlockFunction.FactoryImpl<>(EventConditions::fromMap));
+ register(CommonFunctions.UPDATE_BLOCK_PROPERTY, new UpdateBlockPropertyFunction.FactoryImpl<>(EventConditions::fromMap));
+ register(CommonFunctions.TRANSFORM_BLOCK, new TransformBlockFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.BREAK_BLOCK, new BreakBlockFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.UPDATE_INTERACTION_TICK, new UpdateInteractionFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.SET_COUNT, new SetCountFunction.FactoryImpl<>(EventConditions::fromMap));
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java
index 273343022..a9be4559c 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java
@@ -20,6 +20,8 @@ public final class CommonFunctions {
public static final Key UPDATE_INTERACTION_TICK = Key.of("craftengine:update_interaction_tick");
public static final Key SET_COUNT = Key.of("craftengine:set_count");
public static final Key PLACE_BLOCK = Key.of("craftengine:place_block");
+ public static final Key TRANSFORM_BLOCK = Key.of("craftengine:transform_block");
+ public static final Key UPDATE_BLOCK_PROPERTY = Key.of("craftengine:update_block_property");
public static final Key SET_FOOD = Key.of("craftengine:set_food");
public static final Key SET_COOLDOWN = Key.of("craftengine:set_cooldown");
public static final Key REMOVE_COOLDOWN = Key.of("craftengine:remove_cooldown");
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java
index 3068766eb..4734cb594 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/PlaceBlockFunction.java
@@ -58,11 +58,12 @@ public class PlaceBlockFunction extends AbstractConditional
@Override
public Function create(Map arguments) {
String state = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("block-state"), "warning.config.function.place_block.missing_block_state");
- NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", ""));
- NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", ""));
- NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", ""));
- NumberProvider flags = Optional.ofNullable(arguments.get("update-flags")).map(NumberProviders::fromObject).orElse(NumberProviders.direct(UpdateOption.UPDATE_ALL.flags()));
- return new PlaceBlockFunction<>(LazyReference.lazyReference(() -> CraftEngine.instance().blockManager().createBlockState(state)), x, y, z, flags, getPredicates(arguments));
+ return new PlaceBlockFunction<>(LazyReference.lazyReference(() -> CraftEngine.instance().blockManager().createBlockState(state)),
+ NumberProviders.fromObject(arguments.getOrDefault("x", "")),
+ NumberProviders.fromObject(arguments.getOrDefault("y", "")),
+ NumberProviders.fromObject(arguments.getOrDefault("z", "")),
+ Optional.ofNullable(arguments.get("update-flags")).map(NumberProviders::fromObject).orElse(NumberProviders.direct(UpdateOption.UPDATE_ALL.flags())),
+ getPredicates(arguments));
}
}
}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TransformBlockFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TransformBlockFunction.java
new file mode 100644
index 000000000..2183d51c6
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/TransformBlockFunction.java
@@ -0,0 +1,96 @@
+package net.momirealms.craftengine.core.plugin.context.function;
+
+import net.momirealms.craftengine.core.block.BlockStateWrapper;
+import net.momirealms.craftengine.core.block.UpdateOption;
+import net.momirealms.craftengine.core.plugin.CraftEngine;
+import net.momirealms.craftengine.core.plugin.context.Condition;
+import net.momirealms.craftengine.core.plugin.context.Context;
+import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
+import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
+import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
+import net.momirealms.craftengine.core.util.Key;
+import net.momirealms.craftengine.core.util.LazyReference;
+import net.momirealms.craftengine.core.util.MiscUtils;
+import net.momirealms.craftengine.core.util.ResourceConfigUtils;
+import net.momirealms.craftengine.core.world.World;
+import net.momirealms.craftengine.core.world.WorldPosition;
+import net.momirealms.sparrow.nbt.CompoundTag;
+import net.momirealms.sparrow.nbt.Tag;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+public class TransformBlockFunction extends AbstractConditionalFunction {
+ private final LazyReference lazyBlockState;
+ private final CompoundTag properties;
+ private final NumberProvider x;
+ private final NumberProvider y;
+ private final NumberProvider z;
+ private final NumberProvider updateFlags;
+
+ public TransformBlockFunction(LazyReference lazyBlockState, CompoundTag properties, NumberProvider x, NumberProvider y, NumberProvider z, NumberProvider updateFlags, List> predicates) {
+ super(predicates);
+ this.properties = properties;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.updateFlags = updateFlags;
+ this.lazyBlockState = lazyBlockState;
+ }
+
+ @Override
+ public void runInternal(CTX ctx) {
+ Optional optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION);
+ if (optionalWorldPosition.isPresent()) {
+ World world = optionalWorldPosition.get().world();
+ int x = MiscUtils.fastFloor(this.x.getDouble(ctx));
+ int y = MiscUtils.fastFloor(this.y.getDouble(ctx));
+ int z = MiscUtils.fastFloor(this.z.getDouble(ctx));
+ BlockStateWrapper existingBlockState = world.getBlockAt(x, y, z).blockState().withProperties(this.properties);
+ CompoundTag newProperties = new CompoundTag();
+ for (String propertyName : existingBlockState.getPropertyNames()) {
+ newProperties.putString(propertyName, String.valueOf(existingBlockState.getProperty(propertyName)).toLowerCase(Locale.ROOT));
+ }
+ if (!this.properties.isEmpty()) {
+ for (Map.Entry tagEntry : this.properties.entrySet()) {
+ newProperties.put(tagEntry.getKey(), tagEntry.getValue());
+ }
+ }
+ world.setBlockAt(x, y, z, this.lazyBlockState.get().withProperties(newProperties), this.updateFlags.getInt(ctx));
+ }
+ }
+
+ @Override
+ public Key type() {
+ return CommonFunctions.TRANSFORM_BLOCK;
+ }
+
+ public static class FactoryImpl extends AbstractFactory {
+
+ public FactoryImpl(java.util.function.Function, Condition> factory) {
+ super(factory);
+ }
+
+ @Override
+ public Function create(Map arguments) {
+ String block = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("block"), "warning.config.function.transform_block.missing_block");
+ CompoundTag properties = new CompoundTag();
+ Map propertiesMap = MiscUtils.castToMap(arguments.get("properties"), true);
+ if (propertiesMap != null) {
+ for (Map.Entry entry : propertiesMap.entrySet()) {
+ properties.putString(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ }
+ return new TransformBlockFunction<>(
+ LazyReference.lazyReference(() -> CraftEngine.instance().blockManager().createBlockState(block)),
+ properties,
+ NumberProviders.fromObject(arguments.getOrDefault("x", "")),
+ NumberProviders.fromObject(arguments.getOrDefault("y", "")),
+ NumberProviders.fromObject(arguments.getOrDefault("z", "")),
+ Optional.ofNullable(arguments.get("update-flags")).map(NumberProviders::fromObject).orElse(NumberProviders.direct(UpdateOption.UPDATE_ALL.flags())),
+ getPredicates(arguments));
+ }
+ }
+}
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateBlockPropertyFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateBlockPropertyFunction.java
new file mode 100644
index 000000000..4993e5465
--- /dev/null
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/UpdateBlockPropertyFunction.java
@@ -0,0 +1,78 @@
+package net.momirealms.craftengine.core.plugin.context.function;
+
+import net.momirealms.craftengine.core.block.BlockStateWrapper;
+import net.momirealms.craftengine.core.block.UpdateOption;
+import net.momirealms.craftengine.core.plugin.context.Condition;
+import net.momirealms.craftengine.core.plugin.context.Context;
+import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
+import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
+import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
+import net.momirealms.craftengine.core.util.Key;
+import net.momirealms.craftengine.core.util.MiscUtils;
+import net.momirealms.craftengine.core.util.ResourceConfigUtils;
+import net.momirealms.craftengine.core.world.ExistingBlock;
+import net.momirealms.craftengine.core.world.World;
+import net.momirealms.craftengine.core.world.WorldPosition;
+import net.momirealms.sparrow.nbt.CompoundTag;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class UpdateBlockPropertyFunction extends AbstractConditionalFunction {
+ private final CompoundTag properties;
+ private final NumberProvider x;
+ private final NumberProvider y;
+ private final NumberProvider z;
+ private final NumberProvider updateFlags;
+
+ public UpdateBlockPropertyFunction(CompoundTag properties, NumberProvider x, NumberProvider y, NumberProvider z, NumberProvider updateFlags, List> predicates) {
+ super(predicates);
+ this.properties = properties;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.updateFlags = updateFlags;
+ }
+
+ @Override
+ public void runInternal(CTX ctx) {
+ Optional optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION);
+ if (optionalWorldPosition.isPresent()) {
+ World world = optionalWorldPosition.get().world();
+ int x = MiscUtils.fastFloor(this.x.getDouble(ctx));
+ int y = MiscUtils.fastFloor(this.y.getDouble(ctx));
+ int z = MiscUtils.fastFloor(this.z.getDouble(ctx));
+ ExistingBlock blockAt = world.getBlockAt(x, y, z);
+ BlockStateWrapper wrapper = blockAt.blockState().withProperties(this.properties);
+ world.setBlockAt(x, y, z, wrapper, this.updateFlags.getInt(ctx));
+ }
+ }
+
+ @Override
+ public Key type() {
+ return CommonFunctions.UPDATE_BLOCK_PROPERTY;
+ }
+
+ public static class FactoryImpl extends AbstractFactory {
+
+ public FactoryImpl(java.util.function.Function, Condition> factory) {
+ super(factory);
+ }
+
+ @Override
+ public Function create(Map arguments) {
+ Map state = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(arguments.get("properties"), "warning.config.function.update_block_property.missing_properties"), "properties");
+ CompoundTag properties = new CompoundTag();
+ for (Map.Entry entry : state.entrySet()) {
+ properties.putString(entry.getKey(), String.valueOf(entry.getValue()));
+ }
+ return new UpdateBlockPropertyFunction<>(properties,
+ NumberProviders.fromObject(arguments.getOrDefault("x", "")),
+ NumberProviders.fromObject(arguments.getOrDefault("y", "")),
+ NumberProviders.fromObject(arguments.getOrDefault("z", "")),
+ Optional.ofNullable(arguments.get("update-flags")).map(NumberProviders::fromObject).orElse(NumberProviders.direct(UpdateOption.UPDATE_ALL.flags())),
+ getPredicates(arguments));
+ }
+ }
+}
From efb45c2325ea413394394bac6a1cedcd40421cbf Mon Sep 17 00:00:00 2001
From: XiaoMoMi <972454774@qq.com>
Date: Thu, 23 Oct 2025 21:31:38 +0800
Subject: [PATCH 5/5] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=93=AA?=
=?UTF-8?q?=E4=BA=9B=E6=96=B9=E5=9D=97=E6=94=AF=E6=8C=81deceive?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../bukkit/block/BukkitBlockManager.java | 32 ++++++++++++-------
common-files/src/main/resources/config.yml | 29 ++++++++++-------
.../core/plugin/config/Config.java | 27 +++++++++++++---
gradle.properties | 6 ++--
4 files changed, 64 insertions(+), 30 deletions(-)
diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java
index 78ea579f3..4863daacb 100644
--- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java
+++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java
@@ -31,6 +31,7 @@ import net.momirealms.craftengine.core.util.Tristate;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.bukkit.Bukkit;
import org.bukkit.Material;
+import org.bukkit.Registry;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -416,19 +417,26 @@ public final class BukkitBlockManager extends AbstractBlockManager {
@SuppressWarnings("unchecked")
private void deceiveBukkitRegistry() {
try {
- Material material;
- try {
- material = Material.valueOf(Config.deceiveBukkitMaterial().value().toUpperCase(Locale.ROOT));
- } catch (IllegalArgumentException e) {
- this.plugin.logger().warn(Config.deceiveBukkitMaterial() + " is not a valid material", e);
- material = Material.STONE;
- }
- if (!material.isBlock()) {
- this.plugin.logger().warn(Config.deceiveBukkitMaterial() + " is not a valid bukkit block material");
- material = Material.STONE;
- }
Map magicMap = (Map) CraftBukkitReflections.field$CraftMagicNumbers$BLOCK_MATERIAL.get(null);
- for (DelegatingBlock customBlock : this.customBlocks) {
+ Set invalid = new HashSet<>();
+ for (int i = 0; i < this.customBlocks.length; i++) {
+ DelegatingBlock customBlock = this.customBlocks[i];
+ String value = Config.deceiveBukkitMaterial(i).value();
+ Material material;
+ try {
+ material = Material.valueOf(value.toUpperCase(Locale.ROOT));
+ } catch (IllegalArgumentException e) {
+ if (invalid.add(value)) {
+ this.plugin.logger().warn("Cannot load 'deceive-bukkit-material'. '" + value + "' is an invalid bukkit material", e);
+ }
+ material = Material.BRICKS;
+ }
+ if (!material.isBlock()) {
+ if (invalid.add(value)) {
+ this.plugin.logger().warn("Cannot load 'deceive-bukkit-material'. '" + value + "' is an invalid bukkit block material");
+ }
+ material = Material.BRICKS;
+ }
magicMap.put(customBlock, material);
}
} catch (ReflectiveOperationException e) {
diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml
index 0b0edda7b..2f76bcea0 100644
--- a/common-files/src/main/resources/config.yml
+++ b/common-files/src/main/resources/config.yml
@@ -90,15 +90,15 @@ resource-pack:
# You should strive to make your resource pack more standardized after gaining some experience with resource packs.
fix-atlas: true
# Optimize your resource pack by reducing its size
- optimization:
- enable: true
- png:
- color-quantization: true
- lossless-bit-depth: true
- remove-metadata: true
- model:
- minimize: true
- bypass-textures: []
+# optimization:
+# enable: true
+# png:
+# color-quantization: true
+# lossless-bit-depth: true
+# remove-metadata: true
+# model:
+# minimize: true
+# bypass-textures: []
# Protect your resource pack from being cracked by others
protection:
# Prevent thieves from extracting your resource pack. These options will crash their software.
@@ -221,7 +221,7 @@ equipment:
block:
# This decides the amount of real blocks on serverside. You should only consider increasing this value when your server state is insufficient.
- # It is recommended to increase it by 500 each time. This option requires a restart to apply.
+ # It is recommended to increase it by 1000 each time. This option requires a restart to apply.
serverside-blocks: 2000
# Enables the sound system, which prevents the client from hearing some non-custom block sounds and improves the client experience.
sound-system:
@@ -251,7 +251,14 @@ block:
extended-interaction-range: 0.5
# Defines the value returned by Bukkit block.getMaterial()
# If another plugin causes incompatibility due to its reliance on this method, try changing this option to a different vanilla block.
- deceive-bukkit-material: stone
+ deceive-bukkit-material:
+ default: bricks
+ # The numbers here represent the internal real IDs of the blocks.
+ # This means that overriding certain blocks needs to be done under the condition of forcibly assigning internal IDs.
+ # A restart is required to apply the changes.
+ overrides:
+ 0: bricks
+ 1~8: bricks
furniture:
# Hide technical entities used for storing furniture metadata.
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java
index 05ada618e..f6034b052 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java
@@ -126,7 +126,8 @@ public class Config {
protected int block$predict_breaking_interval;
protected double block$extended_interaction_range;
protected boolean block$chunk_relighter;
- protected Key block$deceive_bukkit_material;
+ protected Key block$deceive_bukkit_material$default;
+ protected Map block$deceive_bukkit_material$overrides;
protected int block$serverside_blocks = -1;
protected boolean recipe$enable;
@@ -250,6 +251,7 @@ public class Config {
.addIgnoredRoute(PluginProperties.getValue("config"), "chunk-system.process-invalid-blocks.convert", '.')
.addIgnoredRoute(PluginProperties.getValue("config"), "chunk-system.process-invalid-furniture.convert", '.')
.addIgnoredRoute(PluginProperties.getValue("config"), "item.custom-model-data-starting-value.overrides", '.')
+ .addIgnoredRoute(PluginProperties.getValue("config"), "block.deceive-bukkit-material.overrides", '.')
.build());
}
try {
@@ -439,8 +441,25 @@ public class Config {
block$predict_breaking_interval = Math.max(config.getInt("block.predict-breaking.interval", 10), 1);
block$extended_interaction_range = Math.max(config.getDouble("block.predict-breaking.extended-interaction-range", 0.5), 0.0);
block$chunk_relighter = config.getBoolean("block.chunk-relighter", true);
- block$deceive_bukkit_material = Key.of(config.getString("block.deceive-bukkit-material", "stone"));
if (firstTime) {
+ block$deceive_bukkit_material$default = Key.of(config.getString("block.deceive-bukkit-material.default", "bricks"));
+ block$deceive_bukkit_material$overrides = new HashMap<>();
+ Section overridesSection = config.getSection("block.deceive-bukkit-material.overrides");
+ if (overridesSection != null) {
+ for (Map.Entry entry : overridesSection.getStringRouteMappedValues(false).entrySet()) {
+ String key = entry.getKey();
+ Key value = Key.of(String.valueOf(entry.getValue()));
+ if (key.contains("~")) {
+ int min = Integer.parseInt(key.split("~")[0]);
+ int max = Integer.parseInt(key.split("~")[1]);
+ for (int i = min; i <= max; i++) {
+ block$deceive_bukkit_material$overrides.put(i, value);
+ }
+ } else {
+ block$deceive_bukkit_material$overrides.put(Integer.valueOf(key), value);
+ }
+ }
+ }
block$serverside_blocks = Math.min(config.getInt("block.serverside-blocks", 2000), 10_0000);
if (block$serverside_blocks < 0) block$serverside_blocks = 0;
}
@@ -774,8 +793,8 @@ public class Config {
return instance.resource_pack$protection$obfuscation$resource_location$bypass_equipments;
}
- public static Key deceiveBukkitMaterial() {
- return instance.block$deceive_bukkit_material;
+ public static Key deceiveBukkitMaterial(int id) {
+ return instance.block$deceive_bukkit_material$overrides.getOrDefault(id, instance.block$deceive_bukkit_material$default);
}
public static boolean generateModAssets() {
diff --git a/gradle.properties b/gradle.properties
index b8f0acd34..76946be09 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,9 +2,9 @@ org.gradle.jvmargs=-Xmx1G
# Project settings
# Rule: [major update].[feature update].[bug fix]
-project_version=0.0.64.19
-config_version=49
-lang_version=35
+project_version=0.0.64.20
+config_version=50
+lang_version=36
project_group=net.momirealms
latest_supported_version=1.21.10