diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml
index 37c7bea86..ef65e98c7 100644
--- a/bukkit/loader/src/main/resources/translations/en.yml
+++ b/bukkit/loader/src/main/resources/translations/en.yml
@@ -38,11 +38,11 @@ argument.parse.failure.aggregate.missing: "Missing component ''Invalid component '': "
argument.parse.failure.either: "Could not resolve or from ''"
argument.parse.failure.namedtextcolor: "'' is not a named text color"
-command.reload.config.success: "Configs reloaded in ms."
+command.reload.config.success: "Configs reloaded in ms. (Async: ms | Sync: ms)"
command.reload.config.failure: "Config reload failed. Check console logs."
command.reload.pack.success: "Resource pack reloaded in ms."
command.reload.pack.failure: "Resource pack reload failed. Check console logs."
-command.reload.all.success: "Reload completed in ms."
+command.reload.all.success: "Reload completed in ms. (Async: ms | Sync: ms | Pack: ms)"
command.reload.all.failure: "Reload failed. Check console logs."
command.item.get.success: "Got "
command.item.get.failure.not_exist: "'>"
@@ -54,6 +54,7 @@ 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"
+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'."
warning.config.image.no_file: "Issue found in file - The image '' is missing the required 'file' argument."
@@ -78,4 +79,13 @@ warning.config.item.lack_material: "Issue found in file - The it
warning.config.item.invalid_material: "Issue found in file - The item '' is using an invalid material type ''."
warning.config.item.bad_custom_model_data_value: "Issue found in file - The item '' is using a custom model data [] that is too large. It's recommended to use a value lower than 16,777,216."
warning.config.item.custom_model_data_conflict: "Issue found in file - The item '' is using a custom model data [] that has been occupied by item ''"
-warning.config.item.lack_model_id: "Issue found in file - The item '' is missing the required 'custom-model-data' or 'item-model' argument."
\ No newline at end of file
+warning.config.item.lack_model_id: "Issue found in file - The item '' is missing the required 'custom-model-data' or 'item-model' argument."
+warning.config.block.duplicated: "Issue found in file - Duplicated block ''."
+warning.config.block.lack_state: "Issue found in file - The block '' is missing the required 'state' argument."
+warning.config.block.lack_real_id: "Issue found in file - The block '' is missing the required 'id' argument for 'state'."
+warning.config.block.state.lack_state: "Issue found in file - The block '' is missing the required 'state' argument for 'state'."
+warning.config.block.state.lack_properties: "Issue found in file - The block '' is missing the required 'properties' section for 'states'."
+warning.config.block.state.lack_appearances: "Issue found in file - The block '' is missing the required 'appearances' section for 'states'."
+warning.config.block.state.lack_variants: "Issue found in file - The block '' is missing the required 'variants' section for 'states'."
+warning.config.block.state.variant.lack_appearance: "Issue found in file - The block '' is missing the required 'appearance' argument for variant ''."
+warning.config.block.state.variant.invalid_appearance: "Issue found in file - The block '' has an error that the variant '' is using a non-existing appearance ''."
\ 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 23de3a017..f04f051a0 100644
--- a/bukkit/loader/src/main/resources/translations/es.yml
+++ b/bukkit/loader/src/main/resources/translations/es.yml
@@ -38,11 +38,11 @@ argument.parse.failure.aggregate.missing: "Componente Faltante ''Componente Invalido '': "
argument.parse.failure.either: "No se ha podido resolver o de ''"
argument.parse.failure.namedtextcolor: "'' no es un color de texto con nombre"
-command.reload.config.success: "Recargado. Tomó ms."
+command.reload.config.success: "Recargado. Tomó ms. (Async: ms | Sync: ms)"
command.reload.config.failure: "Error al recargar la configuración. Por favor, revisa el registro de la consola."
command.reload.pack.success: "Paquete de recursos recargado. Tomó ms."
command.reload.pack.failure: "Error al recargar el paquete de recursos. Por favor, revisa el registro de la consola."
-command.reload.all.success: "Todo recargado. Tomó ms."
+command.reload.all.success: "Todo recargado. Tomó ms. (Async: ms | Sync: ms | Pack: ms)"
command.reload.all.failure: "Error al recargar. Por favor, revisa el registro de la consola."
command.item.get.success: "Obtener "
command.item.get.failure.not_exist: "'>"
diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml
index 29cb7a370..498ebfe90 100644
--- a/bukkit/loader/src/main/resources/translations/zh_cn.yml
+++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml
@@ -38,11 +38,11 @@ argument.parse.failure.aggregate.missing: "缺少组件 ''"
argument.parse.failure.aggregate.failure: "无效的组件 '': "
argument.parse.failure.either: "无法从 '' 解析 或 "
argument.parse.failure.namedtextcolor: "'' 不是颜色代码"
-command.reload.config.success: "重新加载配置完成. 耗时 毫秒"
+command.reload.config.success: "重新加载配置完成. 耗时 毫秒 (异步: ms | 同步: ms)"
command.reload.config.failure: "重新加载配置失败,请检查控制台日志。"
command.reload.pack.success: "资源包重新加载完成. 耗时 毫秒"
command.reload.pack.failure: "重新加载资源包失败,请检查控制台日志。"
-command.reload.all.success: "全部重新加载完成. 耗时 毫秒"
+command.reload.all.success: "全部重新加载完成. 耗时 毫秒 (异步: ms | 同步: ms | 资源包: ms)"
command.reload.all.failure: "重新加载失败,请检查控制台日志。"
command.item.get.success: "获得个"
command.item.get.failure.not_exist: "'>"
diff --git a/bukkit/loader/src/main/resources/translations/zh_tw.yml b/bukkit/loader/src/main/resources/translations/zh_tw.yml
index 37aae210f..b0d1da410 100644
--- a/bukkit/loader/src/main/resources/translations/zh_tw.yml
+++ b/bukkit/loader/src/main/resources/translations/zh_tw.yml
@@ -38,11 +38,11 @@ argument.parse.failure.aggregate.missing: "缺少元件 ''"
argument.parse.failure.aggregate.failure: "無效的元件 '': "
argument.parse.failure.either: "無法從 '' 解析 或 "
argument.parse.failure.namedtextcolor: "'' 不是顏色代碼"
-command.reload.config.success: "重新加載配置完成. 耗時 毫秒"
+command.reload.config.success: "重新加載配置完成. 耗時 毫秒 (非同步: ms | 同步: ms)"
command.reload.config.failure: "重新加載配置失敗,請檢查控制台日誌。"
command.reload.pack.success: "資源包重新加載完成. 耗時 毫秒"
command.reload.pack.failure: "重新加載資源包失敗,請檢查控制台日誌。"
-command.reload.all.success: "全部重新加載完成. 耗時 毫秒"
+command.reload.all.success: "全部重新加載完成. 耗時 毫秒 (非同步: ms | 同步: ms | 資源包: ms)"
command.reload.all.failure: "重新加載失敗,請檢查控制台日誌。"
command.item.get.success: "獲得個"
command.item.get.failure.not_exist: "'>"
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 0757e0cf4..071cade69 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
@@ -19,10 +19,13 @@ import net.momirealms.craftengine.core.block.*;
import net.momirealms.craftengine.core.block.properties.Properties;
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.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
+import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
+import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
import net.momirealms.craftengine.core.registry.WritableRegistry;
@@ -45,6 +48,7 @@ import java.util.*;
public class BukkitBlockManager extends AbstractBlockManager {
private static BukkitBlockManager instance;
private final BukkitCraftEngine plugin;
+ 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<>();
@@ -57,7 +61,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
private int customBlockCount;
// CraftEngine objects
- private final Map id2CraftEngineBlocks = new HashMap<>();
+ private final Map byId = new HashMap<>();
private final ImmutableBlockState[] stateId2ImmutableBlockStates;
// Minecraft objects
@@ -96,6 +100,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
public BukkitBlockManager(BukkitCraftEngine plugin) {
super(plugin);
this.plugin = plugin;
+ this.blockParser = new BlockParser();
this.initVanillaRegistry();
this.loadMappingsAndAdditionalBlocks();
if (plugin.hasMod() && plugin.requiresRestart()) {
@@ -150,7 +155,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
super.clearModelsToGenerate();
this.clearCache();
this.appearanceToRealState.clear();
- this.id2CraftEngineBlocks.clear();
+ this.byId.clear();
this.cachedSuggestions.clear();
this.blockStateOverrides.clear();
this.modBlockStates.clear();
@@ -221,6 +226,11 @@ public class BukkitBlockManager extends AbstractBlockManager {
return Collections.unmodifiableMap(this.modBlockStates);
}
+ @Override
+ public ConfigSectionParser parser() {
+ return this.blockParser;
+ }
+
@Override
public Map> blockOverrides() {
return Collections.unmodifiableMap(this.blockStateOverrides);
@@ -228,12 +238,12 @@ public class BukkitBlockManager extends AbstractBlockManager {
@Override
public Map blocks() {
- return Collections.unmodifiableMap(this.id2CraftEngineBlocks);
+ return Collections.unmodifiableMap(this.byId);
}
@Override
public Optional getBlock(Key key) {
- return Optional.ofNullable(this.id2CraftEngineBlocks.get(key));
+ return Optional.ofNullable(this.byId.get(key));
}
@Override
@@ -246,7 +256,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
this.cachedSuggestions.clear();
this.namespacesInUse.clear();
Set states = new HashSet<>();
- for (CustomBlock block : this.id2CraftEngineBlocks.values()) {
+ for (CustomBlock block : this.byId.values()) {
states.add(block.id().toString());
this.namespacesInUse.add(block.id().namespace());
for (ImmutableBlockState state : block.variantProvider().states()) {
@@ -368,100 +378,134 @@ public class BukkitBlockManager extends AbstractBlockManager {
}
}
- @Override
- public void parseSection(Pack pack, Path path, Key id, Map section) {
- // read block settings
- BlockSettings settings = BlockSettings.fromMap(MiscUtils.castToMap(section.getOrDefault("settings", Map.of()), false));
- // read loot table
- LootTable lootTable = LootTable.fromMap(MiscUtils.castToMap(section.getOrDefault("loot", Map.of()), false));
- // read states
- Map> properties;
- Map appearances;
- Map variants;
- Map stateSection = MiscUtils.castToMap(section.get("state"), true);
- if (stateSection != null) {
- properties = Map.of();
- int internalId = MiscUtils.getAsInt(stateSection.getOrDefault("id", -1));
- if (PreConditions.runIfTrue(internalId < 0, () -> plugin.logger().warn(path, "No state id configured for block " + id))) return;
- Pair pair = parseAppearanceSection(path, stateSection, id);
- if (pair == null) return;
- appearances = Map.of("default", pair.right());
- Key internalBlockId = Key.of(CraftEngine.NAMESPACE, pair.left().value() + "_" + internalId);
- int internalBlockRegistryId = MiscUtils.getAsInt(this.internalId2StateId.getOrDefault(internalBlockId, -1));
- if (internalBlockRegistryId == -1) {
- plugin.logger().warn(path, "Failed to register " + id + " because id " + internalId + " is not a value between 0~" + (MiscUtils.getAsInt(this.registeredRealBlockSlots.get(pair.left()))-1) +
- ". Consider editing additional-real-blocks.yml if the number of real block IDs is insufficient while there are still available appearances");
- return;
- }
- variants = Map.of("", new VariantState("default", settings, internalBlockRegistryId));
- } else {
- Map statesSection = MiscUtils.castToMap(section.get("states"), true);
- if (statesSection == null) {
- plugin.logger().warn(path, "No states configured for block " + id);
- return;
- }
- Map propertySection = MiscUtils.castToMap(statesSection.get("properties"), true);
- if (PreConditions.isNull(propertySection, () -> plugin.logger().warn(path, "No properties configured for block " + id))) return;
- properties = parseProperties(path, propertySection);
- Map appearancesSection = MiscUtils.castToMap(statesSection.get("appearances"), true);
- if (PreConditions.isNull(appearancesSection, () -> plugin.logger().warn(path, "No appearances configured for block " + id))) return;
- appearances = new HashMap<>();
- Map tempTypeMap = new HashMap<>();
- for (Map.Entry appearanceEntry : appearancesSection.entrySet()) {
- if (appearanceEntry.getValue() instanceof Map, ?> appearanceSection) {
- Pair pair = parseAppearanceSection(path, MiscUtils.castToMap(appearanceSection, false), id);
- if (pair == null) return;
- appearances.put(appearanceEntry.getKey(), pair.right());
- tempTypeMap.put(appearanceEntry.getKey(), pair.left());
- }
- }
- Map variantsSection = MiscUtils.castToMap(statesSection.get("variants"), true);
- if (PreConditions.isNull(variantsSection, () -> plugin.logger().warn(path, "No variants configured for block " + id))) return;
- variants = new HashMap<>();
- for (Map.Entry variantEntry : variantsSection.entrySet()) {
- if (variantEntry.getValue() instanceof Map, ?> variantSection0) {
- Map variantSection = MiscUtils.castToMap(variantSection0, false);
- String variantName = variantEntry.getKey();
- String appearance = (String) variantSection.get("appearance");
- if (appearance == null) {
- plugin.logger().warn(path, "No appearance configured for variant " + variantName);
- return;
- }
- if (!appearances.containsKey(appearance)) {
- plugin.logger().warn(path, appearance + " is not a valid appearance for block " + id);
- return;
- }
- int internalId = MiscUtils.getAsInt(variantSection.getOrDefault("id", -1));
- Key baseBlock = tempTypeMap.get(appearance);
- Key internalBlockId = Key.of(CraftEngine.NAMESPACE, baseBlock.value() + "_" + internalId);
- int internalBlockRegistryId = MiscUtils.getAsInt(this.internalId2StateId.getOrDefault(internalBlockId, -1));
- if (internalBlockRegistryId == -1) {
- plugin.logger().warn(path, "Failed to register " + id + " because id " + internalId + " is not a value between 0~" + (MiscUtils.getAsInt(this.registeredRealBlockSlots.getOrDefault(baseBlock, 1))-1) +
- ". Consider editing additional-real-blocks.yml if the number of real block IDs is insufficient while there are still available appearances");
- return;
- }
- Map anotherSetting = MiscUtils.castToMap(variantSection.get("settings"), true);
- variants.put(variantName, new VariantState(appearance, anotherSetting == null ? settings : BlockSettings.ofFullCopy(settings, anotherSetting), internalBlockRegistryId));
- }
- }
+ public class BlockParser implements ConfigSectionParser {
+ public static final String[] CONFIG_SECTION_NAME = new String[] {"blocks", "block"};
+
+ @Override
+ public String[] sectionId() {
+ return CONFIG_SECTION_NAME;
}
- // create or get block holder
- Holder.Reference holder = BuiltInRegistries.BLOCK.get(id).orElseGet(() ->
- ((WritableRegistry) BuiltInRegistries.BLOCK).registerForHolder(new ResourceKey<>(BuiltInRegistries.BLOCK.key().location(), id)));
- // create block
- Map behaviorSection = MiscUtils.castToMap(section.getOrDefault("behavior", Map.of()), false);
- BukkitCustomBlock block = new BukkitCustomBlock(id, holder, properties, appearances, variants, settings, behaviorSection, lootTable);
+ @Override
+ public int loadingSequence() {
+ return LoadingSequence.BLOCK;
+ }
- // bind appearance
- bindAppearance(block);
- this.id2CraftEngineBlocks.put(id, block);
+ @Override
+ public void parseSection(Pack pack, Path path, Key id, Map section) {
+ if (byId.containsKey(id)) {
+ TranslationManager.instance().log("warning.config.block.duplicated", path.toString(), id.toString());
+ return;
+ }
- // generate mod assets
- if (ConfigManager.generateModAssets()) {
- for (ImmutableBlockState state : block.variantProvider().states()) {
- Key realBlockId = BlockStateUtils.getBlockOwnerIdFromState(state.customBlockState());
- this.modBlockStates.put(realBlockId, this.tempVanillaBlockStateModels.get(state.vanillaBlockState().registryId()));
+ // read block settings
+ BlockSettings settings = BlockSettings.fromMap(MiscUtils.castToMap(section.getOrDefault("settings", Map.of()), false));
+ // read loot table
+ LootTable lootTable = LootTable.fromMap(MiscUtils.castToMap(section.getOrDefault("loot", Map.of()), false));
+ // read states
+ Map> properties;
+ Map appearances;
+ Map variants;
+ Map stateSection = MiscUtils.castToMap(section.get("state"), true);
+ if (stateSection != null) {
+ properties = Map.of();
+ int internalId = MiscUtils.getAsInt(stateSection.getOrDefault("id", -1));
+ if (internalId < 0) {
+ TranslationManager.instance().log("warning.config.block.lack_real_id", path.toString(), id.toString());
+ return;
+ }
+ Pair pair = parseAppearanceSection(path, id, stateSection);
+ if (pair == null) return;
+ appearances = Map.of("default", pair.right());
+ Key internalBlockId = Key.of(CraftEngine.NAMESPACE, pair.left().value() + "_" + internalId);
+ int internalBlockRegistryId = MiscUtils.getAsInt(internalId2StateId.getOrDefault(internalBlockId, -1));
+ if (internalBlockRegistryId == -1) {
+ plugin.logger().warn(path, "Failed to register " + id + " because id " + internalId + " is not a value between 0~" + (MiscUtils.getAsInt(registeredRealBlockSlots.get(pair.left()))-1) +
+ ". Consider editing additional-real-blocks.yml if the number of real block IDs is insufficient while there are still available appearances");
+ return;
+ }
+ variants = Map.of("", new VariantState("default", settings, internalBlockRegistryId));
+ } else {
+ Map statesSection = MiscUtils.castToMap(section.get("states"), true);
+ if (statesSection == null) {
+ TranslationManager.instance().log("warning.config.block.lack_state", path.toString(), id.toString());
+ return;
+ }
+ Map propertySection = MiscUtils.castToMap(statesSection.get("properties"), true);
+ if (propertySection == null) {
+ TranslationManager.instance().log("warning.config.block.state.lack_properties", path.toString(), id.toString());
+ return;
+ }
+ properties = parseProperties(path, propertySection);
+ Map appearancesSection = MiscUtils.castToMap(statesSection.get("appearances"), true);
+ if (appearancesSection == null) {
+ TranslationManager.instance().log("warning.config.block.state.lack_appearances", path.toString(), id.toString());
+ return;
+ }
+
+ appearances = new HashMap<>();
+ 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));
+ if (pair == null) return;
+ appearances.put(appearanceEntry.getKey(), pair.right());
+ tempTypeMap.put(appearanceEntry.getKey(), pair.left());
+ }
+ }
+
+ Map variantsSection = MiscUtils.castToMap(statesSection.get("variants"), true);
+ if (variantsSection == null) {
+ TranslationManager.instance().log("warning.config.block.state.lack_variants", path.toString(), id.toString());
+ return;
+ }
+
+ variants = new HashMap<>();
+ for (Map.Entry variantEntry : variantsSection.entrySet()) {
+ if (variantEntry.getValue() instanceof Map, ?> variantSection0) {
+ Map variantSection = MiscUtils.castToMap(variantSection0, false);
+ String variantName = variantEntry.getKey();
+ String appearance = (String) variantSection.get("appearance");
+ if (appearance == null) {
+ TranslationManager.instance().log("warning.config.block.state.variant.lack_appearance", path.toString(), id.toString(), variantName);
+ return;
+ }
+ if (!appearances.containsKey(appearance)) {
+ TranslationManager.instance().log("warning.config.block.state.variant.invalid_appearance", path.toString(), id.toString(), variantName, appearance);
+ return;
+ }
+ int internalId = MiscUtils.getAsInt(variantSection.getOrDefault("id", -1));
+ Key baseBlock = tempTypeMap.get(appearance);
+ Key internalBlockId = Key.of(CraftEngine.NAMESPACE, baseBlock.value() + "_" + internalId);
+ int internalBlockRegistryId = MiscUtils.getAsInt(internalId2StateId.getOrDefault(internalBlockId, -1));
+ if (internalBlockRegistryId == -1) {
+ plugin.logger().warn(path, "Failed to register " + id + " because id " + internalId + " is not a value between 0~" + (MiscUtils.getAsInt(registeredRealBlockSlots.getOrDefault(baseBlock, 1))-1) +
+ ". Consider editing additional-real-blocks.yml if the number of real block IDs is insufficient while there are still available appearances");
+ return;
+ }
+ Map anotherSetting = MiscUtils.castToMap(variantSection.get("settings"), true);
+ variants.put(variantName, new VariantState(appearance, anotherSetting == null ? settings : BlockSettings.ofFullCopy(settings, anotherSetting), internalBlockRegistryId));
+ }
+ }
+ }
+ // create or get block holder
+ Holder.Reference holder = BuiltInRegistries.BLOCK.get(id).orElseGet(() ->
+ ((WritableRegistry) BuiltInRegistries.BLOCK).registerForHolder(new ResourceKey<>(BuiltInRegistries.BLOCK.key().location(), id)));
+ // create block
+ Map behaviorSection = MiscUtils.castToMap(section.getOrDefault("behavior", Map.of()), false);
+
+ BukkitCustomBlock block = new BukkitCustomBlock(id, holder, properties, appearances, variants, settings, behaviorSection, lootTable);
+
+ // bind appearance
+ bindAppearance(block);
+ byId.put(id, block);
+
+ // generate mod assets
+ if (ConfigManager.generateModAssets()) {
+ for (ImmutableBlockState state : block.variantProvider().states()) {
+ Key realBlockId = BlockStateUtils.getBlockOwnerIdFromState(state.customBlockState());
+ modBlockStates.put(realBlockId, tempVanillaBlockStateModels.get(state.vanillaBlockState().registryId()));
+ }
}
}
}
@@ -493,10 +537,13 @@ public class BukkitBlockManager extends AbstractBlockManager {
}
@Nullable
- private Pair parseAppearanceSection(Path path, Map section, Key id) {
+ private Pair parseAppearanceSection(Path path, Key id, Map section) {
String vanillaStateString = (String) section.get("state");
- if (PreConditions.isNull(vanillaStateString,
- () -> this.plugin.logger().warn(path, "No block state found for: " + id))) return null;
+ if (vanillaStateString == null) {
+ TranslationManager.instance().log("warning.config.block.state.lack_state", path.toString(), id.toString());
+ return null;
+ }
+
int vanillaStateRegistryId;
try {
vanillaStateRegistryId = parseVanillaStateRegistryId(vanillaStateString);
diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java
index 511a3845b..40b96fe9d 100644
--- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java
+++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java
@@ -176,7 +176,7 @@ public class BlockItemBehavior extends ItemBehavior {
throw new IllegalArgumentException("Missing required parameter 'block' for block_item behavior");
}
if (id instanceof Map, ?> map) {
- BukkitBlockManager.instance().parseSection(pack, path, key, MiscUtils.castToMap(map, false));
+ BukkitBlockManager.instance().parser().parseSection(pack, path, key, MiscUtils.castToMap(map, false));
return new BlockItemBehavior(key);
} else {
return new BlockItemBehavior(Key.of(id.toString()));
diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java
index 1163a1ab8..09a8575b3 100644
--- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java
+++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java
@@ -67,7 +67,7 @@ public class LiquidCollisionBlockItemBehavior extends BlockItemBehavior {
}
int offset = MiscUtils.getAsInt(arguments.getOrDefault("y-offset", 1));
if (id instanceof Map, ?> map) {
- BukkitBlockManager.instance().parseSection(pack, path, key, MiscUtils.castToMap(map, false));
+ BukkitBlockManager.instance().parser().parseSection(pack, path, key, MiscUtils.castToMap(map, false));
return new LiquidCollisionBlockItemBehavior(key, offset);
} else {
return new LiquidCollisionBlockItemBehavior(Key.of(id.toString()), offset);
diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java
index e6fff1b0b..bac46d3a0 100644
--- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java
+++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java
@@ -37,10 +37,7 @@ public class ReloadCommand extends BukkitCommandFeature {
plugin().scheduler().executeAsync(() -> {
try {
RELOAD_PACK_FLAG = true;
- long time1 = System.currentTimeMillis();
- plugin().reload();
- long time2 = System.currentTimeMillis();
- handleFeedback(context, MessageConstants.COMMAND_RELOAD_CONFIG_SUCCESS, Component.text(time2 - time1));
+ plugin().reload((a, b) -> handleFeedback(context, MessageConstants.COMMAND_RELOAD_CONFIG_SUCCESS, Component.text(a + b), Component.text(a), Component.text(b)));
} catch (Exception e) {
handleFeedback(context, MessageConstants.COMMAND_RELOAD_CONFIG_FAILURE);
plugin().logger().warn("Failed to reload config", e);
@@ -60,16 +57,17 @@ public class ReloadCommand extends BukkitCommandFeature {
});
} else if (argument == ReloadArgument.ALL) {
plugin().scheduler().executeAsync(() -> {
- long time1 = System.currentTimeMillis();
- plugin().reload();
- try {
- plugin().packManager().generateResourcePack();
- long time2 = System.currentTimeMillis();
- handleFeedback(context, MessageConstants.COMMAND_RELOAD_ALL_SUCCESS, Component.text(time2 - time1));
- } catch (Exception e) {
- handleFeedback(context, MessageConstants.COMMAND_RELOAD_ALL_FAILURE);
- plugin().logger().warn("Failed to generate resource pack", e);
- }
+ plugin().reload((a, b) -> {
+ try {
+ long time1 = System.currentTimeMillis();
+ plugin().packManager().generateResourcePack();
+ long time2 = System.currentTimeMillis();
+ handleFeedback(context, MessageConstants.COMMAND_RELOAD_ALL_SUCCESS, Component.text(a + b + time2 - time1), Component.text(a), Component.text(b), Component.text(time2 - time1));
+ } catch (Exception e) {
+ handleFeedback(context, MessageConstants.COMMAND_RELOAD_ALL_FAILURE);
+ plugin().logger().warn("Failed to generate resource pack", e);
+ }
+ });
});
}
});
diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java
index 4b20d0e78..7b5d27868 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockManager.java
@@ -13,16 +13,9 @@ import java.util.Collection;
import java.util.Map;
import java.util.Optional;
-public interface BlockManager extends Reloadable, ModelGenerator, ConfigSectionParser {
- String[] CONFIG_SECTION_NAME = new String[] {"blocks", "block"};
+public interface BlockManager extends Reloadable, ModelGenerator {
- default String[] sectionId() {
- return CONFIG_SECTION_NAME;
- }
-
- default int loadingSequence() {
- return LoadingSequence.BLOCK;
- }
+ ConfigSectionParser parser();
Collection modelsToGenerate();
diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java
index 2f51310ce..988dc9228 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java
@@ -136,6 +136,11 @@ public abstract class AbstractFontManager implements FontManager {
@Override
public void parseSection(Pack pack, Path path, Key id, Map section) {
+ if (images.containsKey(id)) {
+ TranslationManager.instance().log("warning.config.image.duplicated", path.toString(), id.toString());
+ return;
+ }
+
Object heightObj = section.get("height");
if (heightObj == null) {
TranslationManager.instance().log("warning.config.image.lack_height", path.toString(), id.toString());
diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java
index 88e5967fd..e6c8b01f5 100644
--- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java
+++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java
@@ -34,6 +34,8 @@ import org.apache.logging.log4j.LogManager;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -98,7 +100,12 @@ public abstract class CraftEngine implements Plugin {
@Override
public void reload() {
+ reload((a, b) -> {});
+ }
+
+ public void reload(BiConsumer time) {
if (this.isReloading) return;
+ long time1 = System.currentTimeMillis();
this.isReloading = true;
this.configManager.reload();
// reset debugger
@@ -130,9 +137,12 @@ public abstract class CraftEngine implements Plugin {
this.soundManager.delayedLoad();
this.fontManager.delayedLoad();
this.recipeManager.delayedLoad();
+ long time2 = System.currentTimeMillis();
scheduler().sync().run(() -> {
try {
this.recipeManager.runSyncTasks();
+ long time3 = System.currentTimeMillis();
+ time.accept(time2 - time1, time3 - time2);
} finally {
this.isReloading = false;
}
@@ -194,7 +204,7 @@ public abstract class CraftEngine implements Plugin {
// register furniture parser
this.packManager.registerConfigSectionParser(this.furnitureManager.parser());
// register block parser
- this.packManager.registerConfigSectionParser(this.blockManager);
+ this.packManager.registerConfigSectionParser(this.blockManager.parser());
// register recipe parser
this.packManager.registerConfigSectionParser(this.recipeManager.parser());
// register category parser