From 753ce7e05ae2be411c416f2614868b583fa38e67 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sun, 18 May 2025 19:44:58 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=8B=E5=8A=A8?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=97=A7=E7=89=88=E6=A8=A1=E5=9E=8B=E8=A6=86?= =?UTF-8?q?=E5=86=99=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/translations/en.yml | 2 + .../src/main/resources/translations/zh_cn.yml | 29 ++++++-- .../bukkit/block/BukkitBlockManager.java | 30 +++++---- .../bukkit/item/BukkitItemManager.java | 1 - .../core/item/AbstractItemManager.java | 66 ++++++++----------- .../core/pack/AbstractPackManager.java | 4 +- .../core/pack/model/LegacyItemModel.java | 36 ++++++++-- .../core/pack/model/LegacyOverridesModel.java | 6 +- .../core/util/IntIdentityList.java | 4 +- gradle.properties | 6 +- 10 files changed, 111 insertions(+), 73 deletions(-) diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index c33a67965..ba193d14e 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -156,6 +156,8 @@ warning.config.item.behavior.block.missing_block: "Issue found in file < warning.config.item.behavior.furniture.missing_furniture: "Issue found in file - The item '' is missing the required 'furniture' argument for 'furniture_item' behavior." warning.config.item.behavior.liquid_collision.missing_block: "Issue found in file - The item '' is missing the required 'block' argument for 'liquid_collision_block_item' behavior." warning.config.item.legacy_model.missing_path: "Issue found in file - The item '' is missing the require 'path' argument for legacy-model." +warning.config.item.legacy_model.overrides.missing_path: "Issue found in file - The item '' is missing the require 'path' argument for legacy-model overrides." +warning.config.item.legacy_model.overrides.missing_predicate: "Issue found in file - The item '' is missing the require 'predicate' argument for legacy-model overrides." warning.config.item.legacy_model.cannot_convert: "Issue found in file - Cannot convert 1.21.4+ items to legacy format for item ''. Please manually create 'legacy-model' section for this item." warning.config.item.model.invalid_type: "Issue found in file - The item '' is using an invalid model type ''." warning.config.item.model.tint.missing_type: "Issue found in file - The item '' is missing the required 'type' argument for tint." diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index ea6b6e9b8..9b35e58a3 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -90,8 +90,10 @@ warning.config.condition.match_block_property.missing_properties: "在 warning.config.condition.match_item.missing_id: "在文件 发现问题 - 配置项 '' 缺少 'match_item' 条件所需的 'id' 参数" warning.config.condition.table_bonus.missing_enchantment: "在文件 发现问题 - 配置项 '' 缺少 'table_bonus' 条件所需的 'enchantment' 参数" warning.config.condition.table_bonus.missing_chances: "在文件 发现问题 - 配置项 '' 缺少 'table_bonus' 条件所需的 'chances' 参数" - - +warning.config.condition.permission.missing_permission: "在文件 中发现问题 - 配置项 '' 缺少 'permission' 条件必需的 'permission' 参数" +warning.config.condition.equals.missing_value1: "在文件 中发现问题 - 配置项 '' 缺少 'equals' 条件必需的 'value1' 参数" +warning.config.condition.equals.missing_value2: "在文件 中发现问题 - 配置项 '' 缺少 'equals' 条件必需的 'value2' 参数" +warning.config.condition.expression.missing_expression: "在文件 中发现问题 - 配置项 '' 缺少 'expression' 条件必需的 'expression' 参数" warning.config.structure.not_section: "在文件 发现问题 - 配置项 '' 应为配置段落 但实际类型为 ''" warning.config.image.duplicate: "在文件 发现问题 - 重复的图片配置 '' 请检查其他文件中是否存在相同配置" warning.config.image.missing_height: "在文件 发现问题 - 图片 '' 缺少必需的 'height' 参数" @@ -147,11 +149,16 @@ warning.config.item.invalid_custom_model_data: "在文件 发现 warning.config.item.bad_custom_model_data: "在文件 发现问题 - 物品 '' 使用的自定义模型数据 '' 数值过大 建议使用小于 16,777,216 的值" warning.config.item.custom_model_data_conflict: "在文件 发现问题 - 物品 '' 使用的自定义模型数据 '' 已被物品 '' 占用" warning.config.item.missing_model_id: "在文件 发现问题 - 物品 '' 缺少必需的 'custom-model-data' 或 'item-model' 参数" +warning.config.item.missing_model: "在文件 中发现问题 - 物品 '' 缺少支持 1.21.4+ 资源包必需的 'model' 配置项" warning.config.item.behavior.missing_type: "在文件 发现问题 - 物品 '' 的行为配置缺少必需的 'type' 参数" warning.config.item.behavior.invalid_type: "在文件 发现问题 - 物品 '' 使用了无效的行为类型 ''" warning.config.item.behavior.block.missing_block: "在文件 发现问题 - 物品 '' 的 'block_item' 行为缺少必需的 'block' 参数" warning.config.item.behavior.furniture.missing_furniture: "在文件 发现问题 - 物品 '' 的 'furniture_item' 行为缺少必需的 'furniture' 参数" warning.config.item.behavior.liquid_collision.missing_block: "在文件 发现问题 - 物品 '' 的 'liquid_collision_block_item' 行为缺少必需的 'block' 参数" +warning.config.item.legacy_model.missing_path: "在文件 中发现问题 - 物品 '' 的旧版模型(legacy-model)缺少必需的 'path' 参数" +warning.config.item.legacy_model.overrides.missing_path: "在文件 中发现问题 - 物品 '' 的旧版模型覆写规则(overrides)缺少必需的 'path' 参数" +warning.config.item.legacy_model.overrides.missing_predicate: "在文件 中发现问题 - 物品 '' 的旧版模型覆写规则(overrides)缺少必需的 'predicate' 参数" +warning.config.item.legacy_model.cannot_convert: "在文件 中发现问题 - 无法将物品 '' 自动转换为旧版格式,请手动为此物品创建 'legacy-model' 配置项" warning.config.item.model.invalid_type: "在文件 发现问题 - 物品 '' 使用了无效的模型类型 ''" warning.config.item.model.tint.missing_type: "在文件 发现问题 - 物品 '' 的染色配置缺少必需的 'type' 参数" warning.config.item.model.tint.invalid_type: "在文件 发现问题 - 物品 '' 使用了无效的染色类型 ''" @@ -298,10 +305,18 @@ warning.config.conflict_matcher.all_of.missing_terms: "在 config.yml warning.config.conflict_matcher.any_of.missing_terms: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 任一匹配器缺少必需的 'terms' 参数" warning.config.conflict_resolution.missing_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案缺少必需的 'type' 参数" warning.config.conflict_resolution.invalid_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案使用了无效类型 ''" -warning.config.event.missing_trigger: "Issue found in file - The config '' is missing the required 'on' argument for event triggers." -warning.config.event.invalid_trigger: "Issue found in file - The config '' is using an invalid event trigger ''." +warning.config.event.missing_trigger: "在文件 中发现问题 - 配置项 '' 缺少事件触发器必需的 'on' 参数" +warning.config.event.invalid_trigger: "在文件 中发现问题 - 配置项 '' 使用了无效的事件触发器 ''" warning.config.event.condition.missing_type: "在文件 - 配置项 '' 的事件条件缺少 'type' 参数" warning.config.event.condition.invalid_type: "在文件 - 配置项 '' 使用了无效的事件条件类型 ''" -warning.config.function.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for function." -warning.config.function.invalid_type: "Issue found in file - The config '' is using an invalid function type ''." -warning.config.function.command.missing_command: "Issue found in file - The config '' is missing the required 'command' argument for 'command' function." \ No newline at end of file +warning.config.function.missing_type: "在文件 中发现问题 - 配置项 '' 缺少函数必需的 'type' 参数" +warning.config.function.invalid_type: "在文件 中发现问题 - 配置项 '' 使用了无效的函数类型 ''" +warning.config.function.command.missing_command: "在文件 中发现问题 - 配置项 '' 缺少 'command' 函数必需的 'command' 参数" +warning.config.function.actionbar.missing_actionbar: "在文件 中发现问题 - 配置项 '' 缺少 'actionbar' 函数必需的 'actionbar' 参数" +warning.config.function.message.missing_message: "在文件 中发现问题 - 配置项 '' 缺少 'message' 函数必需的 'message' 参数" +warning.config.selector.missing_type: "在文件 中发现问题 - 配置项 '' 缺少选择器必需的 'type' 参数" +warning.config.selector.invalid_type: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器类型 ''" +warning.config.selector.invalid_target: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器目标 ''" +warning.config.resource_pack.item_model.conflict.vanilla: "无法为 '' 生成物品模型,因为该物品模型已被原版物品占用" +warning.config.resource_pack.item_model.already_exist: "无法为 '' 生成物品模型,因为文件 '' 已存在" +warning.config.resource_pack.model.generation.already_exist: "无法生成模型,因为模型文件 '' 已存在" \ No newline at end of file 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 7d77e45fe..7a039f9b2 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 @@ -7,6 +7,10 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.dejvokep.boostedyaml.YamlDocument; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector; @@ -55,11 +59,11 @@ public class BukkitBlockManager extends AbstractBlockManager { private final BlockParser blockParser; // A temporary map used to detect whether the same block state corresponds to multiple models. - private final Map tempRegistryIdConflictMap = new HashMap<>(); + private final Map tempRegistryIdConflictMap = new Int2ObjectOpenHashMap<>(); // A temporary map that converts the custom block registered on the server to the vanilla block ID. - private final Map tempBlockAppearanceConvertor = new HashMap<>(); + private final Map tempBlockAppearanceConvertor = new Int2IntOpenHashMap(); // A temporary map that stores the model path of a certain vanilla block state - private final Map tempVanillaBlockStateModels = new HashMap<>(); + private final Map tempVanillaBlockStateModels = new Int2ObjectOpenHashMap<>(); // The total amount of blocks registered private int customBlockCount; @@ -79,10 +83,10 @@ public class BukkitBlockManager extends AbstractBlockManager { private ImmutableSet affectedSoundBlocks; private ImmutableMap soundMapper; // A list to record the order of registration - private List blockRegisterOrder = new ArrayList<>(); + private List blockRegisterOrder = new ObjectArrayList<>(); // a reverted mapper - private final Map> appearanceToRealState = new HashMap<>(); + private final Map> appearanceToRealState = new Int2ObjectOpenHashMap<>(); // Used to store override information of json files private final Map> blockStateOverrides = new HashMap<>(); // for mod, real block id -> state models @@ -232,11 +236,11 @@ public class BukkitBlockManager extends AbstractBlockManager { } public ImmutableMap> blockAppearanceArranger() { - return blockAppearanceArranger; + return this.blockAppearanceArranger; } public ImmutableMap> realBlockArranger() { - return realBlockArranger; + return this.realBlockArranger; } @Nullable @@ -275,7 +279,7 @@ public class BukkitBlockManager extends AbstractBlockManager { try { Class modClass = ReflectionUtils.getClazz(CraftEngine.MOD_CLASS); Field amountField = ReflectionUtils.getDeclaredField(modClass, "vanillaRegistrySize"); - vanillaStateCount = (int) amountField.get(null); + vanillaStateCount = amountField.getInt(null); } catch (Exception e) { vanillaStateCount = RegistryUtils.currentBlockRegistrySize(); plugin.logger().severe("Fatal error", e); @@ -481,7 +485,7 @@ public class BukkitBlockManager extends AbstractBlockManager { } stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()] = state; tempBlockAppearanceConvertor.put(state.customBlockState().registryId(), state.vanillaBlockState().registryId()); - appearanceToRealState.computeIfAbsent(state.vanillaBlockState().registryId(), k -> new ArrayList<>()).add(state.customBlockState().registryId()); + appearanceToRealState.computeIfAbsent(state.vanillaBlockState().registryId(), k -> new IntArrayList()).add(state.customBlockState().registryId()); } BukkitBlockManager.this.byId.put(id, block); @@ -649,9 +653,9 @@ public class BukkitBlockManager extends AbstractBlockManager { YamlDocument mappings = Config.instance().loadOrCreateYamlData("mappings.yml"); Map blockStateMappings = loadBlockStateMappings(mappings); this.validateBlockStateMappings(mappingFile, blockStateMappings); - Map stateMap = new HashMap<>(); + Map stateMap = new Int2ObjectOpenHashMap<>(); Map blockTypeCounter = new LinkedHashMap<>(); - Map appearanceMapper = new HashMap<>(); + Map appearanceMapper = new Int2IntOpenHashMap(); Map> appearanceArranger = new HashMap<>(); for (Map.Entry entry : blockStateMappings.entrySet()) { this.processBlockStateMapping(mappingFile, entry, stateMap, blockTypeCounter, appearanceMapper, appearanceArranger); @@ -727,7 +731,7 @@ public class BukkitBlockManager extends AbstractBlockManager { counter.compute(key, (k, count) -> count == null ? 1 : count + 1); stateMap.put(beforeId, entry.getKey()); stateMap.put(afterId, entry.getValue()); - arranger.computeIfAbsent(key, (k) -> new ArrayList<>()).add(beforeId); + arranger.computeIfAbsent(key, (k) -> new IntArrayList()).add(beforeId); } else { String previousState = stateMap.get(previous); plugin.logger().warn(mappingFile, "Duplicate entry: '" + previousState + "' equals '" + entry.getKey() + "'"); @@ -776,7 +780,7 @@ public class BukkitBlockManager extends AbstractBlockManager { Object clientSideBlock = getBlockFromRegistry(createResourceLocation(clientSideBlockType)); int amount = blockWithCount.getValue(); - List stateIds = new ArrayList<>(); + List stateIds = new IntArrayList(); for (int i = 0; i < amount; i++) { Key realBlockKey = createRealBlockKey(clientSideBlockType, i); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index 175a35013..b961ac758 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -36,7 +36,6 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java index d0dd2f51c..ce2e61986 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java @@ -258,6 +258,16 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl public class ItemParser implements ConfigParser { public static final String[] CONFIG_SECTION_NAME = new String[] {"items", "item"}; + private static final float VERSION_1_21_2 = 21.2f; + private static final float VERSION_1_21_4 = 21.4f; + + private boolean isModernFormatRequired() { + return Config.packMaxVersion() >= VERSION_1_21_4; + } + + private boolean needsLegacyCompatibility() { + return Config.packMinVersion() < VERSION_1_21_4; + } @Override public String[] sectionId() { @@ -338,7 +348,7 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl // add it to category if (section.containsKey("category")) { - plugin.itemBrowserManager().addExternalCategoryMember(id, MiscUtils.getAsStringList(section.get("category")).stream().map(Key::of).toList()); + AbstractItemManager.this.plugin.itemBrowserManager().addExternalCategoryMember(id, MiscUtils.getAsStringList(section.get("category")).stream().map(Key::of).toList()); } // model part, can be null @@ -353,7 +363,7 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl throw new LocalizedResourceConfigException("warning.config.item.missing_model_id"); } // 1.21.4+必须要配置model区域 - if (Config.packMaxVersion() >= 21.4f && modelSection == null) { + if (isModernFormatRequired() && modelSection == null) { throw new LocalizedResourceConfigException("warning.config.item.missing_model"); } @@ -362,47 +372,22 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl // 旧版格式 TreeSet legacyOverridesModels = null; - if (Config.packMaxVersion() >= 21.4f) { + if (isModernFormatRequired() || (needsLegacyCompatibility() && legacyModelSection == null)) { modernModel = ItemModels.fromMap(modelSection); for (ModelGeneration generation : modernModel.modelsToGenerate()) { prepareModelGeneration(generation); } - // 如果最低支持版本低于1.21.4,则需要准备旧版overrides模型 - if (Config.packMinVersion() < 21.4f) { - // 如果有旧版格式,就用旧版 - if (legacyModelSection != null) { - LegacyItemModel legacyItemModel = LegacyItemModel.fromMap(legacyModelSection); - for (ModelGeneration generation : legacyItemModel.modelsToGenerate()) { - prepareModelGeneration(generation); - } - legacyOverridesModels = new TreeSet<>(legacyItemModel.overrides()); - } else { - // 否则把新版格式并转换为旧版 - legacyOverridesModels = new TreeSet<>(); - processModelRecursively(modernModel, new LinkedHashMap<>(), legacyOverridesModels, material, customModelData); - if (legacyOverridesModels.isEmpty()) { - TranslationManager.instance().log("warning.config.item.legacy_model.cannot_convert", path.toString(), id.asString()); - } - } - } } - // 最高支持版本不超过1.21.4,所以新版model格式为非必需 - else { - // 如果有旧版格式,就用旧版 + if (needsLegacyCompatibility()) { if (legacyModelSection != null) { - LegacyItemModel legacyItemModel = LegacyItemModel.fromMap(legacyModelSection); + LegacyItemModel legacyItemModel = LegacyItemModel.fromMap(legacyModelSection, customModelData); for (ModelGeneration generation : legacyItemModel.modelsToGenerate()) { prepareModelGeneration(generation); } legacyOverridesModels = new TreeSet<>(legacyItemModel.overrides()); } else { - // 否则读新版格式并转换为旧版 - ItemModel model = ItemModels.fromMap(modelSection); - for (ModelGeneration generation : model.modelsToGenerate()) { - prepareModelGeneration(generation); - } legacyOverridesModels = new TreeSet<>(); - processModelRecursively(model, new LinkedHashMap<>(), legacyOverridesModels, material, customModelData); + processModelRecursively(modernModel, new LinkedHashMap<>(), legacyOverridesModels, material, customModelData); if (legacyOverridesModels.isEmpty()) { TranslationManager.instance().log("warning.config.item.legacy_model.cannot_convert", path.toString(), id.asString()); } @@ -413,29 +398,30 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl if (customModelData != 0) { // use custom model data // check conflict - Map conflict = cmdConflictChecker.computeIfAbsent(material, k -> new HashMap<>()); + Map conflict = AbstractItemManager.this.cmdConflictChecker.computeIfAbsent(material, k -> new HashMap<>()); if (conflict.containsKey(customModelData)) { throw new LocalizedResourceConfigException("warning.config.item.custom_model_data_conflict", String.valueOf(customModelData), conflict.get(customModelData).toString()); } conflict.put(customModelData, id); // Parse models - if (Config.packMaxVersion() >= 21.4f && modernModel != null) { - TreeMap map = modernOverrides.computeIfAbsent(material, k -> new TreeMap<>()); + if (isModernFormatRequired() && modernModel != null) { + TreeMap map = AbstractItemManager.this.modernOverrides.computeIfAbsent(material, k -> new TreeMap<>()); map.put(customModelData, modernModel); } - if (Config.packMinVersion() < 21.4f && legacyOverridesModels != null && !legacyOverridesModels.isEmpty()) { - TreeSet lom = legacyOverrides.computeIfAbsent(material, k -> new TreeSet<>()); + if (needsLegacyCompatibility() && legacyOverridesModels != null && !legacyOverridesModels.isEmpty()) { + TreeSet lom = AbstractItemManager.this.legacyOverrides.computeIfAbsent(material, k -> new TreeSet<>()); lom.addAll(legacyOverridesModels); } } // use item model if (itemModelKey != null) { - if (Config.packMaxVersion() >= 21.4f && modernModel != null) { - modernItemModels1_21_4.put(itemModelKey, modernModel); + if (isModernFormatRequired() && modernModel != null) { + AbstractItemManager.this.modernItemModels1_21_4.put(itemModelKey, modernModel); } - if (Config.packMaxVersion() >= 21.2f && Config.packMinVersion() < 21.4f && legacyOverridesModels != null && !legacyOverridesModels.isEmpty()) { - modernItemModels1_21_2.put(itemModelKey, legacyOverridesModels); + if (Config.packMaxVersion() >= VERSION_1_21_2 && needsLegacyCompatibility() && legacyOverridesModels != null && !legacyOverridesModels.isEmpty()) { + TreeSet lom = AbstractItemManager.this.modernItemModels1_21_2.computeIfAbsent(itemModelKey, k -> new TreeSet<>()); + lom.addAll(legacyOverridesModels); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 4cd03a29b..a91f3b95d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -428,8 +428,10 @@ public abstract class AbstractPackManager implements PackManager { Yaml yaml = new Yaml(new StringKeyConstructor(new LoaderOptions())); for (Pack pack : loadedPacks()) { if (!pack.enabled()) continue; + Path configurationFolderPath = pack.configurationFolder(); + if (!Files.isDirectory(configurationFolderPath)) continue; try { - Files.walkFileTree(pack.configurationFolder(), new SimpleFileVisitor<>() { + Files.walkFileTree(configurationFolderPath, new SimpleFileVisitor<>() { @Override public @NotNull FileVisitResult visitFile(@NotNull Path path, @NotNull BasicFileAttributes attrs) { if (Files.isRegularFile(path) && path.getFileName().toString().endsWith(".yml")) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java index 81db56d2e..925b2bb87 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java @@ -1,10 +1,13 @@ package net.momirealms.craftengine.core.pack.model; import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration; +import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,13 +34,38 @@ public class LegacyItemModel { return path; } - public static LegacyItemModel fromMap(Map legacyModel) { + @SuppressWarnings("unchecked") + public static LegacyItemModel fromMap(Map legacyModel, int customModelData) { String legacyModelPath = ResourceConfigUtils.requireNonEmptyStringOrThrow(legacyModel.get("path"), "warning.config.item.legacy_model.missing_path"); Map generation = MiscUtils.castToMap(legacyModel.get("generation"), true); - ModelGeneration modelGeneration = null; + ModelGeneration baseModelGeneration = null; if (generation != null) { - modelGeneration = ModelGeneration.of(Key.of(legacyModelPath), generation); + baseModelGeneration = ModelGeneration.of(Key.of(legacyModelPath), generation); + } + List> overrides = (List>) legacyModel.get("overrides"); + if (overrides != null) { + List modelGenerations = new ArrayList<>(); + List legacyOverridesModels = new ArrayList<>(); + if (baseModelGeneration != null) modelGenerations.add(baseModelGeneration); + legacyOverridesModels.add(new LegacyOverridesModel(new HashMap<>(), legacyModelPath, customModelData)); + for (Map override : overrides) { + String overrideModelPath = ResourceConfigUtils.requireNonEmptyStringOrThrow(override.get("path"), () -> new LocalizedResourceConfigException("warning.config.item.legacy_model.overrides.missing_path")); + Map predicate = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(override.get("predicate"), "warning.config.item.legacy_model.overrides.missing_predicate"), false); + if (predicate.isEmpty()) { + throw new LocalizedResourceConfigException("warning.config.item.legacy_model.overrides.missing_predicate"); + } + Map overrideGeneration = MiscUtils.castToMap(override.get("generation"), true); + if (overrideGeneration != null) { + modelGenerations.add(ModelGeneration.of(Key.of(overrideModelPath), overrideGeneration)); + } + legacyOverridesModels.add(new LegacyOverridesModel(predicate, overrideModelPath, customModelData)); + } + return new LegacyItemModel(legacyModelPath, legacyOverridesModels, modelGenerations); + } else { + return new LegacyItemModel(legacyModelPath, + List.of(new LegacyOverridesModel(new HashMap<>(), legacyModelPath, customModelData)), + baseModelGeneration == null ? List.of() : List.of(baseModelGeneration) + ); } - LegacyOverridesModel legacyOverridesModel = new LegacyOverridesModel(); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java index 07d6d1e7f..6d63b08f2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java @@ -2,7 +2,9 @@ package net.momirealms.craftengine.core.pack.model; import com.google.gson.JsonObject; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -11,8 +13,8 @@ public class LegacyOverridesModel implements Comparable { private final String model; private final int customModelData; - public LegacyOverridesModel(Map predicate, String model, int customModelData) { - this.predicate = predicate; + public LegacyOverridesModel(@Nullable Map predicate, @NotNull String model, int customModelData) { + this.predicate = predicate == null ? new HashMap<>() : predicate; this.model = model; this.customModelData = customModelData; if (customModelData > 0) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java b/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java index c6f539f05..a60be053e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java @@ -1,9 +1,9 @@ package net.momirealms.craftengine.core.util; +import it.unimi.dsi.fastutil.ints.IntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -13,7 +13,7 @@ public class IntIdentityList implements IndexedIterable { public IntIdentityList(int size) { this.size = size; - list = new ArrayList<>(size); + list = new IntArrayList(size); for (int i = 0; i < size; i++) { list.add(i); } diff --git a/gradle.properties b/gradle.properties index 1fabb99a5..a350543e3 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.54.1 -config_version=32 -lang_version=12 +project_version=0.0.54.2 +config_version=33 +lang_version=13 project_group=net.momirealms latest_supported_version=1.21.5 From e08f65271a572953e8a32cd8a7227f730ace64bb Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sun, 18 May 2025 20:26:53 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=B8=8D=E6=AD=BB?= =?UTF-8?q?=E5=9B=BE=E8=85=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/block/BukkitBlockManager.java | 1 + .../bukkit/item/BukkitItemManager.java | 1 + .../bukkit/item/ComponentTypes.java | 1 + .../feature/TotemAnimationCommand.java | 36 ++++++++++++++++--- .../craftengine/core/item/ComponentKeys.java | 1 + .../core/pack/model/LegacyItemModel.java | 6 ++-- .../core/util/IntIdentityList.java | 1 + 7 files changed, 38 insertions(+), 9 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 7a039f9b2..6f0b2a94d 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 @@ -8,6 +8,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.dejvokep.boostedyaml.YamlDocument; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index b961ac758..175a35013 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -36,6 +36,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Function; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java index d755ab11b..ae037f19f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java @@ -26,6 +26,7 @@ public class ComponentTypes { public static final Object CUSTOM_DATA = getComponentType(ComponentKeys.CUSTOM_DATA); public static final Object PROFILE = getComponentType(ComponentKeys.PROFILE); public static final Object DYED_COLOR = getComponentType(ComponentKeys.DYED_COLOR); + public static final Object DEATH_PROTECTION = getComponentType(ComponentKeys.DEATH_PROTECTION); private ComponentTypes() {} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java index 1f21b667e..e0381d921 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TotemAnimationCommand.java @@ -1,15 +1,17 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.bukkit.item.ComponentTypes; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.bukkit.util.MaterialUtils; import net.momirealms.craftengine.bukkit.util.PlayerUtils; -import net.momirealms.craftengine.core.item.CustomItem; +import net.momirealms.craftengine.core.item.*; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; import net.momirealms.craftengine.core.plugin.command.FlagKeys; import net.momirealms.craftengine.core.plugin.locale.MessageConstants; import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; @@ -23,9 +25,13 @@ import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; import org.incendo.cloud.bukkit.parser.selector.MultiplePlayerSelectorParser; import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.context.CommandInput; +import org.incendo.cloud.parser.flag.CommandFlag; +import org.incendo.cloud.parser.standard.StringParser; import org.incendo.cloud.suggestion.Suggestion; import org.incendo.cloud.suggestion.SuggestionProvider; +import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; public class TotemAnimationCommand extends BukkitCommandFeature { @@ -45,18 +51,38 @@ public class TotemAnimationCommand extends BukkitCommandFeature { return CompletableFuture.completedFuture(plugin().itemManager().cachedTotemSuggestions()); } })) + .flag(CommandFlag.builder("sound_event").withComponent(NamespacedKeyParser.namespacedKeyParser()).build()) + .flag(CommandFlag.builder("sound_location").withComponent(NamespacedKeyParser.namespacedKeyParser()).build()) .handler(context -> { NamespacedKey namespacedKey = context.get("id"); Key key = Key.of(namespacedKey.namespace(), namespacedKey.value()); - CustomItem item = plugin().itemManager().getCustomItem(key).orElse(null); - if (item == null || MaterialUtils.getMaterial(item.material()) != Material.TOTEM_OF_UNDYING) { + CustomItem customItem = plugin().itemManager().getCustomItem(key).orElse(null); + if (customItem == null || (!VersionHelper.isOrAbove1_21_2() && customItem.material().equals(ItemKeys.TOTEM_OF_UNDYING))) { handleFeedback(context, MessageConstants.COMMAND_TOTEM_NOT_TOTEM, Component.text(key.toString())); return; } - ItemStack totem = item.buildItemStack(); + Item item = customItem.buildItem(ItemBuildContext.EMPTY); + if (VersionHelper.isOrAbove1_21_2()) { + if (context.flags().contains("sound_location")) { + String soundResourceLocation = context.flags().getValue("sound_location").get().toString(); + if (soundResourceLocation != null) { + item.setComponent(ComponentTypes.DEATH_PROTECTION, Map.of("death_effects", List.of(Map.of("type", "play_sound", "sound", Map.of( + "sound_id", soundResourceLocation + ))))); + } + } else if (context.flags().contains("sound_event")) { + String soundEvent = context.flags().getValue("sound_event").get().toString(); + if (soundEvent != null) { + item.setComponent(ComponentTypes.DEATH_PROTECTION, Map.of("death_effects", List.of(Map.of("type", "play_sound", "sound", soundEvent)))); + } + } else { + item.setComponent(ComponentTypes.DEATH_PROTECTION, Map.of()); + } + } + ItemStack totemItem = item.load(); MultiplePlayerSelector selector = context.get("players"); for (Player player : selector.values()) { - PlayerUtils.sendTotemAnimation(player, totem); + PlayerUtils.sendTotemAnimation(player, totemItem); } }); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java b/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java index 597639121..bc64868d0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java @@ -23,4 +23,5 @@ public class ComponentKeys { public static final Key CUSTOM_DATA = Key.of("minecraft", "custom_data"); public static final Key PROFILE = Key.of("minecraft", "profile"); public static final Key DYED_COLOR = Key.of("minecraft", "dyed_color"); + public static final Key DEATH_PROTECTION = Key.of("minecraft", "death_protection"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java index 925b2bb87..aa1cdf921 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyItemModel.java @@ -5,11 +5,9 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import software.amazon.awssdk.services.s3.endpoints.internal.Value; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class LegacyItemModel { private final List modelsToGenerate; diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java b/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java index a60be053e..fcceb235b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/IntIdentityList.java @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; From af5c63e94006457ec33d70600bcaab468b667aac Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sun, 18 May 2025 20:39:51 +0800 Subject: [PATCH 3/4] Update AbstractItemManager.java --- .../momirealms/craftengine/core/item/AbstractItemManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java index ce2e61986..ab3693dda 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java @@ -291,7 +291,7 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl .register(new ResourceKey<>(BuiltInRegistries.OPTIMIZED_ITEM_ID.key().location(), id), id)); boolean isVanillaItem = isVanillaItem(id); - Key material = Key.from(isVanillaItem ? id.value() : ResourceConfigUtils.requireNonEmptyStringOrThrow(section.get("material"), "warning.config.item.missing_material")); + Key material = Key.from(isVanillaItem ? id.value() : ResourceConfigUtils.requireNonEmptyStringOrThrow(section.get("material"), "warning.config.item.missing_material").toLowerCase(Locale.ENGLISH)); int customModelData = ResourceConfigUtils.getAsInt(section.getOrDefault("custom-model-data", 0), "custom-model-data"); if (customModelData < 0) { throw new LocalizedResourceConfigException("warning.config.item.invalid_custom_model_data", String.valueOf(customModelData)); From 15475b05383a99ffebff8b17fadece0a9164df4a Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Mon, 19 May 2025 04:22:01 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/util/LegacyInventoryUtils.java | 28 ++++ bukkit/loader/src/main/resources/config.yml | 1 - bukkit/loader/src/main/resources/mappings.yml | 128 +++++++++--------- .../default/configuration/blocks.yml | 11 ++ .../src/main/resources/translations/en.yml | 3 + .../src/main/resources/translations/zh_cn.yml | 3 + .../bukkit/plugin/gui/BukkitGuiManager.java | 53 +++++++- .../bukkit/plugin/gui/BukkitInventory.java | 2 +- .../context/condition/EqualsCondition.java | 2 +- .../function/AbstractConditionalFunction.java | 2 +- .../context/function/CommonFunctions.java | 3 +- .../context/function/OpenWindowFunction.java | 77 +++++++++++ .../plugin/context/function/RunFunction.java | 79 +++++++++++ .../core/plugin/event/EventFunctions.java | 2 + .../core/plugin/gui/GuiManager.java | 6 + .../craftengine/core/plugin/gui/GuiType.java | 11 ++ .../core/plugin/scheduler/RegionExecutor.java | 4 + 17 files changed, 342 insertions(+), 73 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiType.java diff --git a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java index c2249eced..f009e3583 100644 --- a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java +++ b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java @@ -37,4 +37,32 @@ public class LegacyInventoryUtils { public static InventoryView getView(PrepareAnvilEvent event) { return event.getView(); } + + public static void openAnvil(Player player) { + player.openAnvil(null, true); + } + + public static void openCartographyTable(Player player) { + player.openCartographyTable(null, true); + } + + public static void openEnchanting(Player player) { + player.openEnchanting(null, true); + } + + public static void openGrindstone(Player player) { + player.openGrindstone(null, true); + } + + public static void openLoom(Player player) { + player.openLoom(null, true); + } + + public static void openSmithingTable(Player player) { + player.openSmithingTable(null, true); + } + + public static void openWorkbench(Player player) { + player.openWorkbench(null, true); + } } diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index 778670b6e..18053ebc2 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -63,7 +63,6 @@ resource-pack: merge-external-folders: - ModelEngine/resource pack - BetterModel/build - - BetterHud/build merge-external-zip-files: - CustomNameplates/resourcepack.zip delivery: diff --git a/bukkit/loader/src/main/resources/mappings.yml b/bukkit/loader/src/main/resources/mappings.yml index 5038f1f8f..94fa679ec 100644 --- a/bukkit/loader/src/main/resources/mappings.yml +++ b/bukkit/loader/src/main/resources/mappings.yml @@ -1328,70 +1328,70 @@ minecraft:tripwire[attached=true,disarmed=false,east=true,north=true,south=true, ######################################################################################################################################################################################################################## # Can make transparent blocks, but the collision shape is relatively random. Not as useful as leaves. # Chorus Plant -#minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true]# -minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] -minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +##minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true]# +#minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=false,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=false]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=false,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=true,south=false,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=true,north=false,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=false,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=true,east=false,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] +#minecraft:chorus_plant[down=false,east=true,north=true,south=true,up=true,west=true]: minecraft:chorus_plant[down=true,east=true,north=true,south=true,up=true,west=true] ######################################################################################################################################################################################################################## # Ideal block for making 1x1x1 interactive blocks. Best substitute when other blocks are insufficient in appearance. # Note Block diff --git a/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml b/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml index 02ea65f95..4baf0dd0b 100644 --- a/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml +++ b/bukkit/loader/src/main/resources/resources/default/configuration/blocks.yml @@ -61,6 +61,17 @@ items#misc: type: falling_block hurt-amount: 4 max-hurt: 80 + events: + - on: right_click + functions: + - type: run + functions: + - type: open_window + gui-type: anvil + - type: cancel_event + conditions: + - type: expression + expression: "!" settings: template: - default:pickaxe_power/level_4 diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index ba193d14e..39ec93ddc 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -314,6 +314,9 @@ warning.config.function.invalid_type: "Issue found in file - The warning.config.function.command.missing_command: "Issue found in file - The config '' is missing the required 'command' argument for 'command' function." warning.config.function.actionbar.missing_actionbar: "Issue found in file - The config '' is missing the required 'actionbar' argument for 'actionbar' function." warning.config.function.message.missing_message: "Issue found in file - The config '' is missing the required 'message' argument for 'message' function." +warning.config.function.open_window.missing_gui_type: "Issue found in file - The config '' is missing the required 'gui-type' argument for 'open_window' function." +warning.config.function.open_window.invalid_gui_type: "Issue found in file - The config '' is using an invalid gui type for 'open_window' function. Allowed types: []." +warning.config.function.run.missing_functions: "Issue found in file - The config '' is missing the required 'functions' argument for 'run' 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/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index 9b35e58a3..a1d692f6e 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -314,6 +314,9 @@ warning.config.function.invalid_type: "在文件 中发现问题 warning.config.function.command.missing_command: "在文件 中发现问题 - 配置项 '' 缺少 'command' 函数必需的 'command' 参数" warning.config.function.actionbar.missing_actionbar: "在文件 中发现问题 - 配置项 '' 缺少 'actionbar' 函数必需的 'actionbar' 参数" warning.config.function.message.missing_message: "在文件 中发现问题 - 配置项 '' 缺少 'message' 函数必需的 'message' 参数" +warning.config.function.open_window.missing_gui_type: "在文件 中发现问题 - 配置项 '' 缺少 'open_window' 函数必需的 'gui-type' 参数" +warning.config.function.open_window.invalid_gui_type: "在文件 中发现问题 - 配置项 '' 为 'open_window' 函数使用了无效的 GUI 类型 . 允许的类型: []。" +warning.config.function.run.missing_functions: "在文件 中发现问题 - 配置项 '' 缺少 'run' 函数必需的 'functions' 参数" warning.config.selector.missing_type: "在文件 中发现问题 - 配置项 '' 缺少选择器必需的 'type' 参数" warning.config.selector.invalid_type: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器类型 ''" warning.config.selector.invalid_target: "在文件 中发现问题 - 配置项 '' 使用了无效的选择器目标 ''" diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java index 79b1528a5..9062dc5b6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java @@ -1,10 +1,13 @@ package net.momirealms.craftengine.bukkit.plugin.gui; +import net.kyori.adventure.text.Component; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.core.plugin.gui.AbstractGui; -import net.momirealms.craftengine.core.plugin.gui.Gui; -import net.momirealms.craftengine.core.plugin.gui.GuiManager; -import net.momirealms.craftengine.core.plugin.gui.Inventory; +import net.momirealms.craftengine.bukkit.util.ComponentUtils; +import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.gui.*; +import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -13,6 +16,7 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.inventory.MenuType; public class BukkitGuiManager implements GuiManager, Listener { private final BukkitCraftEngine plugin; @@ -31,6 +35,47 @@ public class BukkitGuiManager implements GuiManager, Listener { HandlerList.unregisterAll(this); } + @SuppressWarnings("UnstableApiUsage") + @Override + public void openInventory(net.momirealms.craftengine.core.entity.player.Player player, GuiType guiType) { + Player bukkitPlayer = (Player) player.platformPlayer(); + if (VersionHelper.isOrAbove1_21_4()) { + switch (guiType) { + case ANVIL -> MenuType.ANVIL.create(bukkitPlayer).open(); + case LOOM -> MenuType.LOOM.create(bukkitPlayer).open(); + case ENCHANTMENT -> MenuType.ENCHANTMENT.create(bukkitPlayer).open(); + case CRAFTING -> MenuType.CRAFTING.create(bukkitPlayer).open(); + case CARTOGRAPHY -> MenuType.CARTOGRAPHY_TABLE.create(bukkitPlayer).open(); + case SMITHING -> MenuType.SMITHING.create(bukkitPlayer).open(); + case GRINDSTONE -> MenuType.GRINDSTONE.create(bukkitPlayer).open(); + } + } else { + switch (guiType) { + case ANVIL -> LegacyInventoryUtils.openAnvil(bukkitPlayer); + case LOOM -> LegacyInventoryUtils.openLoom(bukkitPlayer); + case GRINDSTONE -> LegacyInventoryUtils.openGrindstone(bukkitPlayer); + case SMITHING -> LegacyInventoryUtils.openSmithingTable(bukkitPlayer); + case CRAFTING -> LegacyInventoryUtils.openWorkbench(bukkitPlayer); + case ENCHANTMENT -> LegacyInventoryUtils.openEnchanting(bukkitPlayer); + case CARTOGRAPHY -> LegacyInventoryUtils.openCartographyTable(bukkitPlayer); + } + } + } + + @Override + public void updateInventoryTitle(net.momirealms.craftengine.core.entity.player.Player player, Component component) { + Object nmsPlayer = player.serverPlayer(); + try { + Object containerMenu = Reflections.field$Player$containerMenu.get(nmsPlayer); + int containerId = Reflections.field$AbstractContainerMenu$containerId.getInt(containerMenu); + Object menuType = Reflections.field$AbstractContainerMenu$menuType.get(containerMenu); + Object packet = Reflections.constructor$ClientboundOpenScreenPacket.newInstance(containerId, menuType, ComponentUtils.adventureToMinecraft(component)); + player.sendPacket(packet, false); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to update inventory title", e); + } + } + @Override public Inventory createInventory(Gui gui, int size) { CraftEngineInventoryHolder holder = new CraftEngineInventoryHolder(gui); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitInventory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitInventory.java index d7bb0b932..13464fc7b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitInventory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitInventory.java @@ -31,7 +31,7 @@ public class BukkitInventory implements Inventory { Reflections.field$Player$containerMenu.set(nmsPlayer, menu); Reflections.method$ServerPlayer$initMenu.invoke(nmsPlayer, menu); } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to update inventory title", e); + CraftEngine.instance().logger().warn("Failed to create bukkit inventory", e); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EqualsCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EqualsCondition.java index bc48c0a1a..68a84533c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EqualsCondition.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EqualsCondition.java @@ -33,7 +33,7 @@ public class EqualsCondition implements Condition { @Override public Condition create(Map arguments) { String value1 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value1"), "warning.config.condition.equals.missing_value1"); - String value2 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value1"), "warning.config.condition.equals.missing_value2"); + String value2 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value2"), "warning.config.condition.equals.missing_value2"); return new EqualsCondition<>(TextProviders.fromString(value1), TextProviders.fromString(value2)); } } 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 394552424..44d22ba1a 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 @@ -51,7 +51,7 @@ public abstract class AbstractConditionalFunction implement } else if (predicates instanceof Map map) { return List.of(factory.apply(MiscUtils.castToMap(map, false))); } - throw new IllegalArgumentException("Unsupported condition type: " + predicates.getClass().getSimpleName()); + 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/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java index ed0bd1e32..f0df7a51c 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 @@ -5,11 +5,12 @@ import net.momirealms.craftengine.core.util.Key; public final class CommonFunctions { private CommonFunctions() {} - public static final Key RUN_ALL = Key.of("craftengine:run_all"); + public static final Key RUN = Key.of("craftengine:run"); public static final Key COMMAND = Key.of("craftengine:command"); public static final Key MESSAGE = Key.of("craftengine:message"); public static final Key ACTIONBAR = Key.of("craftengine:actionbar"); public static final Key TITLE = Key.of("craftengine:title"); + public static final Key OPEN_WINDOW = Key.of("craftengine:open_window"); public static final Key PARTICLE = Key.of("craftengine:particle"); public static final Key SOUND = Key.of("craftengine:sound"); public static final Key POTION_EFFECT = Key.of("craftengine:potion_effect"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java new file mode 100644 index 000000000..242149a45 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java @@ -0,0 +1,77 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +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.plugin.context.text.TextProvider; +import net.momirealms.craftengine.core.plugin.context.text.TextProviders; +import net.momirealms.craftengine.core.plugin.gui.GuiType; +import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import net.momirealms.craftengine.core.util.*; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +public class OpenWindowFunction extends AbstractConditionalFunction { + private final PlayerSelector selector; + private final GuiType guiType; + private final TextProvider optionalTitle; + + public OpenWindowFunction(List> predicates, @Nullable PlayerSelector selector, GuiType guiType, TextProvider optionalTitle) { + super(predicates); + this.selector = selector; + this.guiType = guiType; + this.optionalTitle = optionalTitle; + } + + @Override + public void runInternal(CTX ctx) { + Optional owner = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + if (this.selector == null) { + owner.ifPresent(it -> { + CraftEngine.instance().guiManager().openInventory(it, this.guiType); + if (this.optionalTitle != null) { + CraftEngine.instance().guiManager().updateInventoryTitle(it, AdventureHelper.miniMessage().deserialize(this.optionalTitle.get(ctx), ctx.tagResolvers())); + } + }); + } else { + for (Player viewer : this.selector.get(ctx)) { + CraftEngine.instance().guiManager().openInventory(viewer, this.guiType); + if (this.optionalTitle != null) { + RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY)); + CraftEngine.instance().guiManager().updateInventoryTitle(viewer, AdventureHelper.miniMessage().deserialize(this.optionalTitle.get(relationalContext), relationalContext.tagResolvers())); + } + } + } + } + + @Override + public Key type() { + return CommonFunctions.OPEN_WINDOW; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + TextProvider title = Optional.ofNullable(arguments.get("title")).map(String::valueOf).map(TextProviders::fromString).orElse(null); + String rawType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("gui-type"), "warning.config.function.open_window.missing_gui_type"); + try { + GuiType type = GuiType.valueOf(rawType.toUpperCase(Locale.ENGLISH)); + return new OpenWindowFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), type, title); + } catch (IllegalArgumentException e) { + throw new LocalizedResourceConfigException("warning.config.function.open_window.invalid_gui_type", e, rawType, EnumUtils.toString(GuiType.values())); + } + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java new file mode 100644 index 000000000..1cc08eb6c --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RunFunction.java @@ -0,0 +1,79 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +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.plugin.event.EventFunctions; +import net.momirealms.craftengine.core.util.*; +import net.momirealms.craftengine.core.world.WorldPosition; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class RunFunction extends AbstractConditionalFunction { + private final List> functions; + private final NumberProvider delay; + + public RunFunction(List> functions, NumberProvider delay, List> predicates) { + super(predicates); + this.functions = functions; + this.delay = delay; + } + + @Override + public void runInternal(CTX ctx) { + int delay = this.delay.getInt(ctx); + if (delay <= 0) { + for (Function function : functions) { + function.run(ctx); + } + } else { + Optional position = ctx.getOptionalParameter(DirectContextParameters.POSITION); + if (!VersionHelper.isFolia() || position.isEmpty()) { + CraftEngine.instance().scheduler().sync().runLater(() -> { + for (Function function : functions) { + function.run(ctx); + } + }, delay); + } else { + WorldPosition pos = position.get(); + CraftEngine.instance().scheduler().sync().runLater(() -> { + for (Function function : functions) { + function.run(ctx); + } + }, delay, pos.world().platformWorld(), MCUtils.fastFloor(pos.x()) >> 4, MCUtils.fastFloor(pos.z()) >> 4); + } + } + } + + @Override + public Key type() { + return CommonFunctions.RUN; + } + + public static class FactoryImpl extends AbstractFactory { + private final java.util.function.Function, Function> functionFactory; + + public FactoryImpl(java.util.function.Function, Function> functionFactory, java.util.function.Function, Condition> conditionFactory) { + super(conditionFactory); + this.functionFactory = functionFactory; + } + + @Override + public Function create(Map arguments) { + NumberProvider delay = NumberProviders.fromObject(arguments.getOrDefault("delay", 0)); + @SuppressWarnings("unchecked") + List> functions = (List>) ResourceConfigUtils.requireNonNullOrThrow(arguments.get("functions"), "warning.config.function.run.missing_functions"); + List> fun = new ArrayList<>(); + for (Map function : functions) { + fun.add(this.functionFactory.apply(function)); + } + return new RunFunction<>(fun, delay, getPredicates(arguments)); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java index 91d28760f..001d58f81 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/event/EventFunctions.java @@ -24,7 +24,9 @@ public class EventFunctions { register(CommonFunctions.MESSAGE, new MessageFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.ACTIONBAR, new ActionBarFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.TITLE, new TitleFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.OPEN_WINDOW, new OpenWindowFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.CANCEL_EVENT, new CancelEventFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.RUN, new RunFunction.FactoryImpl<>(EventFunctions::fromMap, EventConditions::fromMap)); } public static void register(Key key, FunctionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiManager.java index 8c4e25cb1..c23e6f7e8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiManager.java @@ -1,8 +1,14 @@ package net.momirealms.craftengine.core.plugin.gui; +import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.plugin.Manageable; public interface GuiManager extends Manageable { + void openInventory(Player player, GuiType guiType); + + void updateInventoryTitle(Player player, Component component); + Inventory createInventory(Gui gui, int size); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiType.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiType.java new file mode 100644 index 000000000..f004bfa2e --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/GuiType.java @@ -0,0 +1,11 @@ +package net.momirealms.craftengine.core.plugin.gui; + +public enum GuiType { + ANVIL, + CARTOGRAPHY, + ENCHANTMENT, + GRINDSTONE, + LOOM, + SMITHING, + CRAFTING +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/RegionExecutor.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/RegionExecutor.java index cbe7c938a..c77bbb0e1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/RegionExecutor.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/scheduler/RegionExecutor.java @@ -20,6 +20,10 @@ public interface RegionExecutor extends Executor { SchedulerTask runAsyncLater(Runnable runnable, long delay); + default SchedulerTask runLater(Runnable runnable, long delay) { + return runLater(runnable, delay, null, 0 ,0); + } + SchedulerTask runLater(Runnable runnable, long delay, W world, int x, int z); SchedulerTask runRepeating(Runnable runnable, long delay, long period, W world, int x, int z);