diff --git a/bukkit/loader/src/main/resources/commands.yml b/bukkit/loader/src/main/resources/commands.yml
index 1e959b731..125d3e971 100644
--- a/bukkit/loader/src/main/resources/commands.yml
+++ b/bukkit/loader/src/main/resources/commands.yml
@@ -69,12 +69,12 @@ search_recipe_admin:
- /craftengine item search-recipe
- /ce item search-recipe
-totem:
+totem_animation:
enable: true
- permission: ce.command.admin.totem
+ permission: ce.command.admin.totem_animation
usage:
- - /craftengine totem
- - /ce totem
+ - /craftengine feature totem-animation
+ - /ce feature totem-animation
# Debug commands
debug_set_block:
diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml
index 5624e7bd8..9fededa9d 100644
--- a/bukkit/loader/src/main/resources/config.yml
+++ b/bukkit/loader/src/main/resources/config.yml
@@ -152,7 +152,14 @@ image:
sign: true
recipe:
+ # Enable the plugin's recipe system
enable: true
+ # Disable vanilla recipes
+ disable-vanilla-recipes:
+ # Disable all vanilla recipes
+ all: false
+ # Disable the recipes in list
+ list: []
gui:
browser:
diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml
index 760faf424..d2c95dfb1 100644
--- a/bukkit/loader/src/main/resources/translations/en.yml
+++ b/bukkit/loader/src/main/resources/translations/en.yml
@@ -53,7 +53,7 @@ command.search_recipe.not_found: "No recipe found for this item"
command.search_usage.not_found: "No usage found for this item"
command.search_recipe.no_item: "Please hold an item before running this command"
command.search_usage.no_item: "Please hold an item before running this command"
-command.totem.not_totem: "'' is not type of totem_of_undying"
+command.totem_animation.failure.not_totem: "Item '' is not minecraft:totem_of_undying"
warning.config.image.duplicated: "Issue found in file - Duplicated image ''."
warning.config.image.lack_height: "Issue found in file - The image '' is missing the required 'height' argument."
warning.config.image.height_smaller_than_ascent: "Issue found in file - The image '' violates the bitmap image rule: 'height' should be no lower than 'ascent'."
@@ -63,7 +63,7 @@ warning.config.image.invalid_font_name: "Issue found in file - T
warning.config.image.lack_char: "Issue found in file - The image '' is missing the required 'char' argument."
warning.config.image.codepoint_in_use: "Issue found in file - The image '' is using a character[()] in font that has been used by another image ''."
warning.config.image.invalid_codepoint_grid: "Issue found in file - Image '' has an invalid 'chars' codepoint grind."
-warning.config.image.file_not_exist: "Issue found in file - PNG file not found for image ''."
+warning.config.image.file_not_exist: "Issue found in file - PNG file '' not found for image ''."
warning.config.recipe.duplicated: "Issue found in file - Duplicated recipe ''."
warning.config.i18n.unknown_locale: "Issue found in file - Unknown locale ''."
warning.config.template.duplicated: "Issue found in file - Duplicated template ''."
@@ -93,8 +93,13 @@ warning.config.block.state.invalid_state: "Issue found in file -
warning.config.block.state.unavailable_state: "Issue found in file - The block '' is using an unavailable vanilla block state ''."
warning.config.block.state.invalid_vanilla_state_id: "Issue found in file - The block '' is using a vanilla block state '' that exceeds the available slot range '0~'."
warning.config.block.state.conflict: "Issue found in file - The block '' is using a vanilla block state '' that has been occupied by ''."
-warning.config.block.bind_real_state: "Issue found in file - The block '' failed to bind real block state for '' as the state has been occupied by ''."
+warning.config.block.state.bind_real_state: "Issue found in file - The block '' failed to bind real block state for '' as the state has been occupied by ''."
warning.config.block.state.invalid_property_structure: "Issue found in file - The block '' has an invalid property structure ''."
warning.config.block.state.invalid_property: "Issue found in file - Failed to create property '' for block '': ."
warning.config.block.state.no_model_set: "Issue found in file - The block '' is missing the required 'model' or 'models' argument."
-warning.config.block.state.invalid_real_state_id: "Issue found in file - The block '' is using a real block state '' that exceeds the available slot range '0~'. Consider adding more real states in 'additional-real-blocks.yml' if the slots are used up."
\ No newline at end of file
+warning.config.block.state.invalid_real_state_id: "Issue found in file - The block '' is using a real block state '' that exceeds the available slot range '0~'. Consider adding more real states in 'additional-real-blocks.yml' if the slots are used up."
+warning.config.block.state.model.lack_path: "Issue found in file - The block '' is missing the required 'path' option for 'model'."
+warning.config.block.state.model.invalid_resource_location: "Issue found in file - The block '' has a 'path' argument [] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters"
+warning.config.model.generation.conflict: "Issue found in file - Failed to generate model for '' as two or more configurations attempt to generate different json models with the same path: ''"
+warning.config.model.generation.texture.invalid_resource_location: "Issue found in file - The config '' has a '' texture argument [] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters"
+warning.config.model.generation.parent.invalid_resource_location: "Issue found in file - The config '' has a parent argument [] that contains legal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters"
\ No newline at end of file
diff --git a/bukkit/loader/src/main/resources/translations/es.yml b/bukkit/loader/src/main/resources/translations/es.yml
index f04f051a0..eda313eaf 100644
--- a/bukkit/loader/src/main/resources/translations/es.yml
+++ b/bukkit/loader/src/main/resources/translations/es.yml
@@ -53,4 +53,4 @@ command.search_recipe.not_found: "No se encontró ninguna receta para este
command.search_usage.not_found: "No se encontró ningún uso para este objeto"
command.search_recipe.no_item: "Por favor, sostén un objeto antes de ejecutar este comando"
command.search_usage.no_item: "Por favor, sostén un objeto antes de ejecutar este comando"
-command.totem.not_totem: "'' no es del tipo totem_of_undying"
\ No newline at end of file
+command.totem_animation.failure.not_totem: "'' no es del tipo totem_of_undying"
\ No newline at end of file
diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml
index 0cab6ac5d..822f32e54 100644
--- a/bukkit/loader/src/main/resources/translations/zh_cn.yml
+++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml
@@ -53,7 +53,7 @@ command.search_recipe.not_found: "找不到此物品的配方"
command.search_usage.not_found: "找不到此物品的用途"
command.search_recipe.no_item: "请手持物品后再执行此命令"
command.search_usage.no_item: "请手持物品后再执行此命令"
-command.totem.not_totem: "'' 不是 totem_of_undying 类型"
+command.totem_animation.failure.not_totem: "'' 不是 totem_of_undying 类型"
warning.config.image.duplicated: "在文件 中发现问题 - 图片 '' 重复定义"
warning.config.image.lack_height: "在文件 中发现问题 - 图片 '' 缺少必要的 'height' 高度参数"
warning.config.image.height_smaller_than_ascent: "在文件 中发现问题 - 图片 '' 违反位图规则:'height' 高度值不应小于 'ascent' 基准线高度"
@@ -88,4 +88,18 @@ warning.config.block.state.lack_properties: "在文件 中发现
warning.config.block.state.lack_appearances: "在文件 中发现问题 - 方块 '' 的 'states' 配置缺少必要的 'appearances' 外观配置"
warning.config.block.state.lack_variants: "在文件 中发现问题 - 方块 '' 的 'states' 配置缺少必要的 'variants' 变体配置"
warning.config.block.state.variant.lack_appearance: "在文件 中发现问题 - 方块 '' 的 '' 变体配置缺少必要的 'appearance' 外观参数"
-warning.config.block.state.variant.invalid_appearance: "在文件 中发现问题 - 方块 '' 的 '' 变体引用了不存在的外观配置 ''"
\ No newline at end of file
+warning.config.block.state.variant.invalid_appearance: "在文件 中发现问题 - 方块 '' 的 '' 变体引用了不存在的外观配置 ''"
+warning.config.block.state.invalid_state: "在文件 中发现问题 - 方块 '' 使用了无效的原版方块状态 ''"
+warning.config.block.state.unavailable_state: "在文件 中发现问题 - 方块 '' 使用了不可用的原版方块状态 ''"
+warning.config.block.state.invalid_vanilla_state_id: "在文件 中发现问题 - 方块 '' 使用的原版方块状态 '' 超出可用槽位范围 '0~'"
+warning.config.block.state.conflict: "在文件 中发现问题 - 方块 '' 使用的原版方块状态 '' 已被 '' 占用"
+warning.config.block.state.bind_real_state: "在文件 中发现问题 - 方块 '' 未能绑定真实方块状态 '',该状态已被 '' 占用"
+warning.config.block.state.invalid_property_structure: "在文件 中发现问题 - 方块 '' 的属性结构 '' 配置无效"
+warning.config.block.state.invalid_property: "在文件 中发现问题 - 无法为方块 '' 创建属性 '':"
+warning.config.block.state.no_model_set: "在文件 中发现问题 - 方块 '' 缺少必要的 'model' 或 'models' 模型参数"
+warning.config.block.state.invalid_real_state_id: "在文件 中发现问题 - 方块 '' 使用的真实方块状态 '' 超出可用槽位范围 '0~'。若槽位已用尽,请考虑在 additional-real-blocks.yml 中添加更多真实状态"
+warning.config.block.state.model.lack_path: "在文件 中发现问题 - 方块 '' 的 'model' 配置缺少必要的 'path' 路径参数"
+warning.config.block.state.model.invalid_resource_location: "在文件 中发现问题 - 方块 '' 的 'path' 路径参数 [] 包含非法字符,请参考资源路径规范:https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6"
+warning.config.model.generation.conflict: "在文件 中发现问题 - 无法为 '' 生成模型,多个配置尝试用相同路径 '' 生成不同的JSON模型"
+warning.config.model.generation.texture.invalid_resource_location: "在文件 中发现问题 - 配置项 '' 的 '' 纹理参数 [] 包含非法字符,请参考资源路径规范:https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6"
+warning.config.model.generation.parent.invalid_resource_location: "在文件 中发现问题 - 配置项 '' 的父模型参数 [] 包含非法字符,请参考资源路径规范:https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6"
\ No newline at end of file
diff --git a/bukkit/loader/src/main/resources/translations/zh_tw.yml b/bukkit/loader/src/main/resources/translations/zh_tw.yml
index b0d1da410..dfff5088e 100644
--- a/bukkit/loader/src/main/resources/translations/zh_tw.yml
+++ b/bukkit/loader/src/main/resources/translations/zh_tw.yml
@@ -53,4 +53,4 @@ command.search_recipe.not_found: "找不到此物品的配方"
command.search_usage.not_found: "找不到此物品的用途"
command.search_recipe.no_item: "執行此命令前請手持物品"
command.search_usage.no_item: "執行此命令前請手持物品"
-command.totem.not_totem: "'' 不是 totem_of_undying 類型"
\ No newline at end of file
+command.totem_animation.failure.not_totem: "'' 不是 totem_of_undying 類型"
\ 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 c62766b00..a326b0678 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
@@ -21,6 +21,7 @@ import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
+import net.momirealms.craftengine.core.pack.ResourceLocation;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
@@ -367,7 +368,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
return;
}
- Pair pair = parseAppearanceSection(path, id, stateSection);
+ Pair pair = parseAppearanceSection(pack, path, id, stateSection);
if (pair == null) return;
appearances = Map.of("default", pair.right());
@@ -407,7 +408,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
Map tempTypeMap = new HashMap<>();
for (Map.Entry appearanceEntry : appearancesSection.entrySet()) {
if (appearanceEntry.getValue() instanceof Map, ?> appearanceSection) {
- Pair pair = parseAppearanceSection(path, id, MiscUtils.castToMap(appearanceSection, false));
+ Pair pair = parseAppearanceSection(pack, path, id, MiscUtils.castToMap(appearanceSection, false));
if (pair == null) return;
appearances.put(appearanceEntry.getKey(), pair.right());
tempTypeMap.put(appearanceEntry.getKey(), pair.left());
@@ -463,7 +464,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
for (ImmutableBlockState state : block.variantProvider().states()) {
ImmutableBlockState previous = stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()];
if (previous != null && !previous.isEmpty()) {
- TranslationManager.instance().log("warning.config.block.bind_real_state", path.toString(), id.toString(), state.toString(), previous.toString());
+ TranslationManager.instance().log("warning.config.block.state.bind_real_state", path.toString(), id.toString(), state.toString(), previous.toString());
continue;
}
stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()] = state;
@@ -500,7 +501,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
}
@Nullable
- private Pair parseAppearanceSection(Path path, Key id, Map section) {
+ private Pair parseAppearanceSection(Pack pack, Path path, Key id, Map section) {
// require state non null
String vanillaStateString = (String) section.get("state");
if (vanillaStateString == null) {
@@ -538,11 +539,11 @@ public class BukkitBlockManager extends AbstractBlockManager {
List variants = new ArrayList<>();
if (models instanceof Map, ?> singleModelSection) {
- loadVariantModel(variants, MiscUtils.castToMap(singleModelSection, false));
+ loadVariantModel(pack, path, id, variants, MiscUtils.castToMap(singleModelSection, false));
} else if (models instanceof List> modelList) {
for (Object model : modelList) {
if (model instanceof Map,?> singleModelMap) {
- loadVariantModel(variants, MiscUtils.castToMap(singleModelMap, false));
+ loadVariantModel(pack, path, id, variants, MiscUtils.castToMap(singleModelMap, false));
}
}
}
@@ -567,9 +568,17 @@ public class BukkitBlockManager extends AbstractBlockManager {
return Pair.of(block, vanillaStateRegistryId);
}
- private void loadVariantModel(List variants, Map singleModelMap) {
+ private void loadVariantModel(Pack pack, Path path, Key id, List variants, Map singleModelMap) {
JsonObject json = new JsonObject();
String modelPath = (String) singleModelMap.get("path");
+ if (modelPath == null) {
+ TranslationManager.instance().log("warning.config.block.state.model.lack_path", path.toString(), id.toString());
+ return;
+ }
+ if (!ResourceLocation.isValid(modelPath)) {
+ TranslationManager.instance().log("warning.config.block.state.model.invalid_resource_location", path.toString(), id.toString(), modelPath);
+ return;
+ }
json.addProperty("model", modelPath);
if (singleModelMap.containsKey("x")) json.addProperty("x", MiscUtils.getAsInt(singleModelMap.get("x")));
if (singleModelMap.containsKey("y")) json.addProperty("y", MiscUtils.getAsInt(singleModelMap.get("y")));
@@ -577,7 +586,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
if (singleModelMap.containsKey("weight")) json.addProperty("weight", MiscUtils.getAsInt(singleModelMap.get("weight")));
Map generationMap = MiscUtils.castToMap(singleModelMap.get("generation"), true);
if (generationMap != null) {
- prepareModelGeneration(new ModelGeneration(Key.of(modelPath), generationMap));
+ prepareModelGeneration(path, id, new ModelGeneration(Key.of(modelPath), generationMap));
}
variants.add(json);
}
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 ee8bdb884..2e8905231 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
@@ -349,7 +349,7 @@ public class BukkitItemManager extends AbstractItemManager {
// Parse models
ItemModel model = ItemModels.fromMap(modelSection);
for (ModelGeneration generation : model.modelsToGenerate()) {
- prepareModelGeneration(generation);
+ prepareModelGeneration(path, id, generation);
}
if (Config.packMaxVersion() > 21.39f) {
@@ -369,7 +369,7 @@ public class BukkitItemManager extends AbstractItemManager {
// use components
ItemModel model = ItemModels.fromMap(modelSection);
for (ModelGeneration generation : model.modelsToGenerate()) {
- prepareModelGeneration(generation);
+ prepareModelGeneration(path, id, generation);
}
if (Config.packMaxVersion() > 21.39f) {
diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java
index a026bee0f..c047c60cd 100644
--- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java
+++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java
@@ -297,6 +297,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager {
@Override
public void unload() {
+ if (!Config.enableRecipeSystem()) return;
super.unload();
try {
if (VersionHelper.isVersionNewerThan1_21_2()) {
@@ -310,6 +311,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager {
@Override
public void delayedLoad() {
+ if (!Config.enableRecipeSystem()) return;
this.injectDataPackRecipes();
}
@@ -368,12 +370,23 @@ public class BukkitRecipeManager extends AbstractRecipeManager {
for (Object pack : selected) {
packResources.add(Reflections.method$Pack$open.invoke(pack));
}
+
+ boolean hasDisabledAny = !Config.disabledVanillaRecipes().isEmpty();
try (AutoCloseable resourceManager = (AutoCloseable) Reflections.constructor$MultiPackResourceManager.newInstance(Reflections.instance$PackType$SERVER_DATA, packResources)) {
Map