mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-22 16:39:28 +00:00
内部id自动绑定
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.block;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.UnsafeCompositeBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BlockGenerator;
|
||||
@@ -16,15 +16,18 @@ import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.RegistryUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.TagUtils;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviors;
|
||||
import net.momirealms.craftengine.core.block.behavior.EmptyBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.parser.BlockStateParser;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
|
||||
@@ -61,7 +64,7 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
super(plugin, RegistryUtils.currentBlockRegistrySize(), Config.serverSideBlocks());
|
||||
this.plugin = plugin;
|
||||
this.registerServerSideCustomBlocks(Config.serverSideBlocks());
|
||||
this.registerEmptyBlock();
|
||||
EmptyBlock.initialize();
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@@ -114,6 +117,21 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
super.delayedLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBehavior createBlockBehavior(CustomBlock customBlock, List<Map<String, Object>> behaviorConfig) {
|
||||
if (behaviorConfig == null || behaviorConfig.isEmpty()) {
|
||||
return new EmptyBlockBehavior();
|
||||
} else if (behaviorConfig.size() == 1) {
|
||||
return BlockBehaviors.fromMap(customBlock, behaviorConfig.getFirst());
|
||||
} else {
|
||||
List<AbstractBlockBehavior> behaviors = new ArrayList<>();
|
||||
for (Map<String, Object> config : behaviorConfig) {
|
||||
behaviors.add((AbstractBlockBehavior) BlockBehaviors.fromMap(customBlock, config));
|
||||
}
|
||||
return new UnsafeCompositeBlockBehavior(customBlock, behaviors);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resendTags() {
|
||||
// if there's no change
|
||||
@@ -258,17 +276,6 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
BlockRegistryMirror.init(states, new BukkitBlockStateWrapper(MBlocks.STONE$defaultState, BlockStateUtils.blockStateToId(MBlocks.STONE$defaultState)));
|
||||
}
|
||||
|
||||
private void registerEmptyBlock() {
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).registerForHolder(ResourceKey.create(BuiltInRegistries.BLOCK.key().location(), Key.withDefaultNamespace("empty")));
|
||||
EmptyBlock emptyBlock = new EmptyBlock(Key.withDefaultNamespace("empty"), holder);
|
||||
holder.bindValue(emptyBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CustomBlock.Builder platformBuilder(Key id) {
|
||||
return BukkitCustomBlock.builder(id);
|
||||
}
|
||||
|
||||
// 注册服务端侧的真实方块
|
||||
private void registerServerSideCustomBlocks(int count) {
|
||||
// 这个会影响全局调色盘
|
||||
@@ -379,6 +386,14 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
return this.vanillaBlockStateCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CustomBlock createCustomBlock(@NotNull Holder.Reference<CustomBlock> holder,
|
||||
@NotNull BlockStateVariantProvider variantProvider,
|
||||
@NotNull Map<EventTrigger, List<Function<PlayerOptionalContext>>> events,
|
||||
@Nullable LootTable<?> lootTable) {
|
||||
return new BukkitCustomBlock(holder, variantProvider, events, lootTable);
|
||||
}
|
||||
|
||||
public boolean isOpenableBlockSoundRemoved(Object blockOwner) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,139 +1,27 @@
|
||||
package net.momirealms.craftengine.bukkit.block;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.UnsafeCompositeBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.SoundUtils;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviors;
|
||||
import net.momirealms.craftengine.core.block.behavior.EmptyBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.block.AbstractCustomBlock;
|
||||
import net.momirealms.craftengine.core.block.BlockStateVariantProvider;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class BukkitCustomBlock extends AbstractCustomBlock {
|
||||
|
||||
private BukkitCustomBlock(
|
||||
@NotNull Key id,
|
||||
public BukkitCustomBlock(
|
||||
@NotNull Holder.Reference<CustomBlock> holder,
|
||||
@NotNull Map<String, Property<?>> properties,
|
||||
@NotNull Map<String, BlockStateAppearance> appearances,
|
||||
@NotNull Map<String, BlockStateVariant> variantMapper,
|
||||
@NotNull BlockSettings settings,
|
||||
@NotNull BlockStateVariantProvider variantProvider,
|
||||
@NotNull Map<EventTrigger, List<Function<PlayerOptionalContext>>> events,
|
||||
@Nullable List<Map<String, Object>> behavior,
|
||||
@Nullable LootTable<?> lootTable
|
||||
) {
|
||||
super(id, holder, properties, appearances, variantMapper, settings, events, behavior, lootTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockBehavior setupBehavior(List<Map<String, Object>> behaviorConfig) {
|
||||
if (behaviorConfig == null || behaviorConfig.isEmpty()) {
|
||||
return new EmptyBlockBehavior();
|
||||
} else if (behaviorConfig.size() == 1) {
|
||||
return BlockBehaviors.fromMap(this, behaviorConfig.getFirst());
|
||||
} else {
|
||||
List<AbstractBlockBehavior> behaviors = new ArrayList<>();
|
||||
for (Map<String, Object> config : behaviorConfig) {
|
||||
behaviors.add((AbstractBlockBehavior) BlockBehaviors.fromMap(this, config));
|
||||
}
|
||||
return new UnsafeCompositeBlockBehavior(this, behaviors);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public LootTable<ItemStack> lootTable() {
|
||||
return (LootTable<ItemStack>) super.lootTable();
|
||||
}
|
||||
|
||||
public static Builder builder(Key id) {
|
||||
return new BuilderImpl(id);
|
||||
}
|
||||
|
||||
public static class BuilderImpl implements Builder {
|
||||
protected final Key id;
|
||||
protected Map<String, Property<?>> properties;
|
||||
protected Map<String, BlockStateAppearance> appearances;
|
||||
protected Map<String, BlockStateVariant> variantMapper;
|
||||
protected BlockSettings settings;
|
||||
protected List<Map<String, Object>> behavior;
|
||||
protected LootTable<?> lootTable;
|
||||
protected Map<EventTrigger, List<Function<PlayerOptionalContext>>> events;
|
||||
|
||||
public BuilderImpl(Key id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder events(Map<EventTrigger, List<Function<PlayerOptionalContext>>> events) {
|
||||
this.events = events;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder appearances(Map<String, BlockStateAppearance> appearances) {
|
||||
this.appearances = appearances;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder behavior(List<Map<String, Object>> behavior) {
|
||||
this.behavior = behavior;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder lootTable(LootTable<?> lootTable) {
|
||||
this.lootTable = lootTable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder properties(Map<String, Property<?>> properties) {
|
||||
this.properties = properties;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder settings(BlockSettings settings) {
|
||||
this.settings = settings;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder variantMapper(Map<String, BlockStateVariant> variantMapper) {
|
||||
this.variantMapper = variantMapper;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CustomBlock build() {
|
||||
// create or get block holder
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).getOrRegisterForHolder(ResourceKey.create(BuiltInRegistries.BLOCK.key().location(), this.id));
|
||||
return new BukkitCustomBlock(this.id, holder, this.properties, this.appearances, this.variantMapper, this.settings, this.events, this.behavior, this.lootTable);
|
||||
}
|
||||
super(holder, variantProvider, events, lootTable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.PendingConfigSection;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
@@ -232,6 +233,15 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
return this.blockId;
|
||||
}
|
||||
|
||||
static void addPendingSection(Pack pack, Path path, String node, Key key, Map<?, ?> map) {
|
||||
if (map.containsKey(key.toString())) {
|
||||
// 防呆
|
||||
BukkitBlockManager.instance().blockParser().addPendingConfigSection(new PendingConfigSection(pack, path, node, key, MiscUtils.castToMap(map.get(key.toString()), false)));
|
||||
} else {
|
||||
BukkitBlockManager.instance().blockParser().addPendingConfigSection(new PendingConfigSection(pack, path, node, key, MiscUtils.castToMap(map, false)));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, String node, Key key, Map<String, Object> arguments) {
|
||||
@@ -240,12 +250,7 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.behavior.block.missing_block", new IllegalArgumentException("Missing required parameter 'block' for block_item behavior"));
|
||||
}
|
||||
if (id instanceof Map<?, ?> map) {
|
||||
if (map.containsKey(key.toString())) {
|
||||
// 防呆
|
||||
BukkitBlockManager.instance().blockParser().parseSection(pack, path, node, key, MiscUtils.castToMap(map.get(key.toString()), false));
|
||||
} else {
|
||||
BukkitBlockManager.instance().blockParser().parseSection(pack, path, node, key, MiscUtils.castToMap(map, false));
|
||||
}
|
||||
addPendingSection(pack, path, node, key, map);
|
||||
return new BlockItemBehavior(key);
|
||||
} else {
|
||||
return new BlockItemBehavior(Key.of(id.toString()));
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.PendingConfigSection;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
@@ -43,15 +44,10 @@ public class DoubleHighBlockItemBehavior extends BlockItemBehavior {
|
||||
public ItemBehavior create(Pack pack, Path path, String node, Key key, Map<String, Object> arguments) {
|
||||
Object id = arguments.get("block");
|
||||
if (id == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.behavior.double_high.missing_block", new IllegalArgumentException("Missing required parameter 'block' for double_high_block_item behavior"));
|
||||
throw new LocalizedResourceConfigException("warning.config.item.behavior.double_high.missing_block");
|
||||
}
|
||||
if (id instanceof Map<?, ?> map) {
|
||||
if (map.containsKey(key.toString())) {
|
||||
// 防呆
|
||||
BukkitBlockManager.instance().blockParser().parseSection(pack, path, node, key, MiscUtils.castToMap(map.get(key.toString()), false));
|
||||
} else {
|
||||
BukkitBlockManager.instance().blockParser().parseSection(pack, path, node, key, MiscUtils.castToMap(map, false));
|
||||
}
|
||||
addPendingSection(pack, path, node, key, map);
|
||||
return new DoubleHighBlockItemBehavior(key);
|
||||
} else {
|
||||
return new DoubleHighBlockItemBehavior(Key.of(id.toString()));
|
||||
|
||||
@@ -41,12 +41,7 @@ public class WallBlockItemBehavior extends BlockItemBehavior {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.behavior.wall_block.missing_block", new IllegalArgumentException("Missing required parameter 'block' for wall_block_item behavior"));
|
||||
}
|
||||
if (id instanceof Map<?, ?> map) {
|
||||
if (map.containsKey(key.toString())) {
|
||||
// 防呆
|
||||
BukkitBlockManager.instance().blockParser().parseSection(pack, path, node, key, MiscUtils.castToMap(map.get(key.toString()), false));
|
||||
} else {
|
||||
BukkitBlockManager.instance().blockParser().parseSection(pack, path, node, key, MiscUtils.castToMap(map, false));
|
||||
}
|
||||
addPendingSection(pack, path, node, key, map);
|
||||
return new WallBlockItemBehavior(key);
|
||||
} else {
|
||||
return new WallBlockItemBehavior(Key.of(id.toString()));
|
||||
|
||||
@@ -1,26 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class DebugAppearanceStateUsageCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
|
||||
@@ -1,26 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class DebugRealStateUsageCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ images:
|
||||
templates:
|
||||
internal:icon/2d:
|
||||
material: arrow
|
||||
custom-model-data: ${model_data}
|
||||
data:
|
||||
item-name: ${name}
|
||||
lore: ${lore}
|
||||
@@ -92,6 +93,7 @@ items:
|
||||
internal:next_page_0:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1000
|
||||
texture: next_page_0
|
||||
name: <!i><#FAFAD2><i18n:internal.next_page>
|
||||
lore:
|
||||
@@ -99,6 +101,7 @@ items:
|
||||
internal:next_page_1:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1001
|
||||
texture: next_page_1
|
||||
name: <!i><#808080><i18n:internal.next_page>
|
||||
lore:
|
||||
@@ -106,6 +109,7 @@ items:
|
||||
internal:previous_page_0:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1002
|
||||
texture: previous_page_0
|
||||
name: <!i><#FAFAD2><i18n:internal.previous_page>
|
||||
lore:
|
||||
@@ -113,6 +117,7 @@ items:
|
||||
internal:previous_page_1:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1003
|
||||
texture: previous_page_1
|
||||
name: <!i><#808080><i18n:internal.previous_page>
|
||||
lore:
|
||||
@@ -120,29 +125,34 @@ items:
|
||||
internal:return:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1004
|
||||
texture: return
|
||||
name: <!i><#DAA520><i18n:internal.return>
|
||||
lore: null
|
||||
internal:next_recipe_0:
|
||||
material: arrow
|
||||
custom-model-data: 1000
|
||||
data:
|
||||
item-name: <!i><#FAFAD2><i18n:internal.next_recipe>
|
||||
lore:
|
||||
- <!i><#F5F5F5><arg:current_page>/<arg:max_page>
|
||||
internal:next_recipe_1:
|
||||
material: arrow
|
||||
custom-model-data: 1001
|
||||
data:
|
||||
item-name: <!i><#808080><i18n:internal.next_recipe>
|
||||
lore:
|
||||
- <!i><#696969><arg:current_page>/<arg:max_page>
|
||||
internal:previous_recipe_0:
|
||||
material: arrow
|
||||
custom-model-data: 1002
|
||||
data:
|
||||
item-name: <!i><#FAFAD2><i18n:internal.previous_recipe>
|
||||
lore:
|
||||
- <!i><#F5F5F5><arg:current_page>/<arg:max_page>
|
||||
internal:previous_recipe_1:
|
||||
material: arrow
|
||||
custom-model-data: 1003
|
||||
data:
|
||||
item-name: <!i><#808080><i18n:internal.previous_recipe>
|
||||
lore:
|
||||
@@ -150,6 +160,7 @@ items:
|
||||
internal:get_item:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1005
|
||||
texture: get_item
|
||||
name: <!i><#DAA520><i18n:internal.get_item>
|
||||
lore:
|
||||
@@ -158,6 +169,7 @@ items:
|
||||
internal:cooking_info:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1006
|
||||
texture: cooking_info
|
||||
name: <!i><#FF8C00><i18n:internal.cooking_info>
|
||||
lore:
|
||||
@@ -166,6 +178,7 @@ items:
|
||||
internal:exit:
|
||||
template: internal:icon/2d
|
||||
arguments:
|
||||
model_data: 1007
|
||||
texture: exit
|
||||
name: <!i><#DAA520><i18n:internal.exit>
|
||||
lore: null
|
||||
@@ -184,7 +184,7 @@ warning.config.item.invalid_material: "<yellow>Problem in Datei <arg:0> gefunden
|
||||
warning.config.item.invalid_custom_model_data: "<yellow>Problem in Datei <arg:0> gefunden - Das Item '<arg:1>' verwendet eine negative Custom-Model-Data '<arg:2>', was ungültig ist.</yellow>"
|
||||
warning.config.item.bad_custom_model_data: "<yellow>Problem in Datei <arg:0> gefunden - Das Item '<arg:1>' verwendet eine Custom-Model-Data '<arg:2>', die zu groß ist. Es wird empfohlen, einen Wert unter 16.777.216 zu verwenden.</yellow>"
|
||||
warning.config.item.item_model.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Das Item '<arg:1>' verwendet eine ungültige 'item-model'-Option, da dieses Item-Model bereits von einem Vanilla-Item belegt ist.</yellow>"
|
||||
warning.config.item.custom_model_data_conflict: "<yellow>Problem in Datei <arg:0> gefunden - Das Item '<arg:1>' verwendet eine Custom-Model-Data '<arg:2>', die bereits von Item '<arg:3>' belegt ist.</yellow>"
|
||||
warning.config.item.custom_model_data.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Das Item '<arg:1>' verwendet eine Custom-Model-Data '<arg:2>', die bereits von Item '<arg:3>' belegt ist.</yellow>"
|
||||
warning.config.item.invalid_component: "<yellow>Problem in Datei <arg:0> gefunden - Das Item '<arg:1>' verwendet einen nicht existierenden Component-Typ '<arg:2>'.</yellow>"
|
||||
warning.config.item.missing_model_id: "<yellow>Problem in Datei <arg:0> gefunden - Beim Item '<arg:1>' fehlt das erforderliche 'custom-model-data'- oder 'item-model'-Argument.</yellow>"
|
||||
warning.config.item.missing_model: "<yellow>Problem in Datei <arg:0> gefunden - Beim Item '<arg:1>' fehlt der erforderliche 'model'-Abschnitt für die Unterstützung von Resource Packs ab 1.21.4+.</yellow>"
|
||||
@@ -252,18 +252,15 @@ warning.config.block.state.property.missing_type: "<yellow>Problem in Datei <arg
|
||||
warning.config.block.state.property.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet das ungültige Typ-Argument '<arg:2>' für die Property '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.property.integer.invalid_range: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet das ungültige 'range'-Argument '<arg:2>' für die Integer-Property '<arg:3>'. Korrekte Syntax: 1~2.</yellow>"
|
||||
warning.config.block.state.property.invalid_format: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet ein ungültiges Block-State-Property-Format '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.missing_real_id: "<yellow>Problem in Datei <arg:0> gefunden - Beim Block '<arg:1>' fehlt das erforderliche 'id'-Argument für 'state'. 'id' ist die serverseitige Block-ID, die für jeden Block-State-Typ eindeutig ist. Wenn du einen serverseitigen Block mit 'note_block' und ID 30 erstellst, wäre die echte Block-ID 'craftengine:note_block_30'.</yellow>"
|
||||
warning.config.block.state.missing_state: "<yellow>Problem in Datei <arg:0> gefunden - Beim Block '<arg:1>' fehlt das erforderliche 'state'-Argument für 'state'.</yellow>"
|
||||
warning.config.block.state.missing_properties: "<yellow>Problem in Datei <arg:0> gefunden - Beim Block '<arg:1>' fehlt der erforderliche 'properties'-Abschnitt für 'states'.</yellow>"
|
||||
warning.config.block.state.missing_appearances: "<yellow>Problem in Datei <arg:0> gefunden - Beim Block '<arg:1>' fehlt der erforderliche 'appearances'-Abschnitt für 'states'.</yellow>"
|
||||
warning.config.block.state.missing_variants: "<yellow>Problem in Datei <arg:0> gefunden - Beim Block '<arg:1>' fehlt der erforderliche 'variants'-Abschnitt für 'states'.</yellow>"
|
||||
warning.config.block.state.variant.missing_appearance: "<yellow>Problem in Datei <arg:0> gefunden - Beim Block '<arg:1>' fehlt das erforderliche 'appearance'-Argument für die Variante '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.variant.invalid_appearance: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' hat einen Fehler, dass die Variante '<arg:2>' eine nicht existierende Appearance '<arg:3>' verwendet.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen ungültigen Vanilla-Block-State '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.unavailable_vanilla: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen nicht verfügbaren Vanilla-Block-State '<arg:2>'. Bitte gib diesen State in der mappings.yml frei.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen Vanilla-Block-State '<arg:2>', der den verfügbaren Slot-Bereich '0~<arg:3>' überschreitet.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen Vanilla-Block-State '<arg:2>', der bereits von '<arg:3>' belegt ist.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' konnte den echten Block-State für '<arg:2>' nicht binden, da der State bereits von '<arg:3>' belegt ist.</yellow>"
|
||||
warning.config.block.state.id.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' konnte den echten Block-State für '<arg:2>' nicht binden, da der State bereits von '<arg:3>' belegt ist.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Problem in Datei <arg:0> gefunden - Beim Block '<arg:1>' fehlt die erforderliche 'path'-Option für 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' hat ein 'path'-Argument '<arg:2>', das ungültige Zeichen enthält. Bitte lies https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
|
||||
warning.config.block.state.model.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' versucht, das Model '<arg:2>' an den Block-State '<arg:3>' zu binden, der bereits an das Model '<arg:4>' gebunden ist.</yellow>"
|
||||
|
||||
@@ -192,8 +192,8 @@ warning.config.item.invalid_material: "<yellow>Issue found in file <arg:0> - The
|
||||
warning.config.item.invalid_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a negative custom model data '<arg:2>' which is invalid.</yellow>"
|
||||
warning.config.item.bad_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that is too large. It's recommended to use a value lower than 16,777,216.</yellow>"
|
||||
warning.config.item.item_model.conflict: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an invalid 'item-model' option because this item model has been occupied by a vanilla item.</yellow>"
|
||||
warning.config.item.custom_model_data_conflict: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that has been occupied by item '<arg:3>'.</yellow>"
|
||||
warning.config.item.custom_model_data_exhausted: "<yellow>Issue found in file <arg:0> - Cannot allocate custom model data for item '<arg:1>' as the custom model data has already been exhausted.</yellow>"
|
||||
warning.config.item.custom_model_data.conflict: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that has been occupied by item '<arg:3>'.</yellow>"
|
||||
warning.config.item.custom_model_data.exhausted: "<yellow>Issue found in file <arg:0> - Cannot allocate custom model data for item '<arg:1>' as the custom model data has already been exhausted.</yellow>"
|
||||
warning.config.item.invalid_component: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a non-existing component type '<arg:2>'.</yellow>"
|
||||
warning.config.item.missing_model_id: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'custom-model-data' or 'item-model' argument.</yellow>"
|
||||
warning.config.item.missing_model: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'model' section for 1.21.4+ resource pack support.</yellow>"
|
||||
@@ -264,7 +264,6 @@ warning.config.block.state.property.missing_type: "<yellow>Issue found in file <
|
||||
warning.config.block.state.property.invalid_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using the invalid type argument '<arg:2>' for property '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.property.integer.invalid_range: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using the invalid 'range' argument '<arg:2>' for integer property '<arg:3>'. Correct syntax: 1~2.</yellow>"
|
||||
warning.config.block.state.property.invalid_format: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using an invalid block state property format '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.missing_real_id: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'id' argument for 'state'. 'id' is the serverside block id which is unique for each type of block state. If you create a serverside side block with 'note_block' and id 30, then the real block id would be 'craftengine:note_block_30'.</yellow>"
|
||||
warning.config.block.state.missing_state: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'state' argument for 'state'.</yellow>"
|
||||
warning.config.block.state.missing_properties: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'properties' section for 'states'.</yellow>"
|
||||
warning.config.block.state.missing_appearances: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'appearances' section for 'states'.</yellow>"
|
||||
@@ -274,14 +273,13 @@ warning.config.block.state.entity_renderer.item_display.missing_item: "<yellow>I
|
||||
warning.config.block.state.entity_renderer.text_display.missing_text: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'text' argument for 'text_display' entity renderer.</yellow>"
|
||||
warning.config.block.state.entity_renderer.better_model.missing_model: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'model' argument for 'better_model' entity renderer.</yellow>"
|
||||
warning.config.block.state.entity_renderer.model_engine.missing_model: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'model' argument for 'model_engine' entity renderer.</yellow>"
|
||||
warning.config.block.state.variant.missing_appearance: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'appearance' argument for variant '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.variant.invalid_appearance: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' has an error that the variant '<arg:2>' is using a non-existing appearance '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using an invalid vanilla block state '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.unavailable_vanilla: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using an unavailable vanilla block state '<arg:2>'. Please free that state in mappings.yml.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using a vanilla block state '<arg:2>' that exceeds the available slot range '0~<arg:3>'.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using a vanilla block state '<arg:2>' that has been occupied by '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' failed to bind real block state '<arg:4>' for '<arg:2>' as the state has been occupied by '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using a real block state '<arg:2>' that exceeds the available slot range '0~<arg:3>'. Consider adding more serverside blocks in 'config.yml' if the slots are used up.</yellow>"
|
||||
warning.config.block.state.invalid_id: "<yellow>Issue found in file <arg:0> - The block state ID range (<arg:2>) used by block '<arg:1>' is outside the valid range of 0 to <arg:3>. Please add more server-side blocks in 'config.yml' if the current slots are exhausted.</yellow>"
|
||||
warning.config.block.state.id.conflict: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' failed to bind real block state '<arg:4>' for '<arg:2>' as the state has been occupied by '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.id.exhausted: "<yellow>Issue found in file <arg:0> - Cannot allocate enough real block state for block '<arg:1>'. Please add more server-side blocks in 'config.yml' and restart if the current slots are exhausted.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'path' option for 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' has a 'path' argument '<arg:2>' that contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
|
||||
warning.config.block.state.model.conflict: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is trying to bind model '<arg:2>' to block state '<arg:3>' which has already been bound to model '<arg:4>'</yellow>"
|
||||
|
||||
@@ -121,7 +121,7 @@ warning.config.item.settings.unknown: "<yellow>Problema encontrado en el archivo
|
||||
warning.config.item.missing_material: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'material'.</yellow>"
|
||||
warning.config.item.invalid_material: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' está usando un tipo de material inválido '<arg:2>'.</yellow>"
|
||||
warning.config.item.bad_custom_model_data: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' está usando un dato de modelo personalizado demasiado grande '<arg:2>'. Se recomienda usar un valor menor a 16.777.216.</yellow>"
|
||||
warning.config.item.custom_model_data_conflict: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' está usando un dato de modelo personalizado '<arg:2>' que está ocupado por el objeto '<arg:3>'.</yellow>"
|
||||
warning.config.item.custom_model_data.conflict: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' está usando un dato de modelo personalizado '<arg:2>' que está ocupado por el objeto '<arg:3>'.</yellow>"
|
||||
warning.config.item.missing_model_id: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'custom-model-data' o 'item-model'.</yellow>"
|
||||
warning.config.item.behavior.missing_type: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'type' para el comportamiento del objeto.</yellow>"
|
||||
warning.config.item.behavior.invalid_type: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' está usando un tipo de comportamiento de objeto inválido '<arg:2>'.</yellow>"
|
||||
@@ -175,18 +175,15 @@ warning.config.block.state.property.missing_type: "<yellow>Problema encontrado e
|
||||
warning.config.block.state.property.invalid_type: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un argumento 'type' inválido '<arg:2>' para la propiedad '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.property.integer.invalid_range: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un argumento 'range' inválido '<arg:2>' para la propiedad entero '<arg:3>'. Sintaxis correcta: 1~2.</yellow>"
|
||||
warning.config.block.state.property.invalid_format: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un formato de propiedad de estado de bloque inválido '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.missing_real_id: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece del argumento requerido 'id' para 'state'. 'id' es el id de bloque del lado del servidor que es único para cada tipo de estado de bloque. Si creas un bloque del lado del servidor con 'note_block' e id 30, el id de bloque real será 'craftengine:note_block_30'.</yellow>"
|
||||
warning.config.block.state.missing_state: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece del argumento requerido 'state' para 'state'.</yellow>"
|
||||
warning.config.block.state.missing_properties: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece de la sección requerida 'properties' para 'states'.</yellow>"
|
||||
warning.config.block.state.missing_appearances: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece de la sección requerida 'appearances' para 'states'.</yellow>"
|
||||
warning.config.block.state.missing_variants: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece de la sección requerida 'variants' para 'states'.</yellow>"
|
||||
warning.config.block.state.variant.missing_appearance: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece del argumento requerido 'appearance' para la variante '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.variant.invalid_appearance: "<yellow>Problema encontrado en el archivo <arg:0> - Hay un error en el bloque '<arg:1>' donde la variante '<arg:2>' está usando una apariencia inexistente '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un estado de bloque vanilla inválido '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.unavailable_vanilla: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un estado de bloque vanilla no disponible '<arg:2>'. Por favor libera este estado en el archivo mappings.yml.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un estado de bloque vanilla '<arg:2>' que excede el rango de slots disponible '0~<arg:3>'.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un estado de bloque vanilla '<arg:2>' que está ocupado por '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' falló al vincular el estado de bloque real para '<arg:2>' porque está ocupado por el estado '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.id.conflict: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' falló al vincular el estado de bloque real para '<arg:2>' porque está ocupado por el estado '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece de la opción requerida 'path' para 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' tiene un argumento 'path' '<arg:2>' que contiene caracteres prohibidos. Por favor lee https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
warning.config.block.settings.unknown: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un tipo de configuración desconocido '<arg:2>'.</yellow>"
|
||||
|
||||
@@ -161,7 +161,7 @@ warning.config.item.missing_material: "<yellow>Проблема найдена
|
||||
warning.config.item.invalid_material: "<yellow>Проблема найдена в файле <arg:0> - Предмет '<arg:1>' использует недопустимый тип материала '<arg:2>'.</yellow>"
|
||||
warning.config.item.invalid_custom_model_data: "<yellow>Проблема найдена в файле <arg:0> - Предмет '<arg:1>' использует отрицательные данные пользовательской модели '<arg:2>', что недействительно.</yellow>"
|
||||
warning.config.item.bad_custom_model_data: "<yellow>Проблема найдена в файле <arg:0> - Предмет '<arg:1>' использует пользовательскую модель данных '<arg:2>', которая имеет слишком большое значение. Рекомендуется использовать значение ниже 16,777,216.</yellow>"
|
||||
warning.config.item.custom_model_data_conflict: "<yellow>Проблема найдена в файле <arg:0> - Предмет '<arg:1>' использует пользовательскую модель данных '<arg:2>', которая занята элементом '<arg:3>'.</yellow>"
|
||||
warning.config.item.custom_model_data.conflict: "<yellow>Проблема найдена в файле <arg:0> - Предмет '<arg:1>' использует пользовательскую модель данных '<arg:2>', которая занята элементом '<arg:3>'.</yellow>"
|
||||
warning.config.item.invalid_component: "<yellow>Проблема найдена в файле <arg:0> - Предмет '<arg:1>' использует несуществующий тип компонента '<arg:2>'.</yellow>"
|
||||
warning.config.item.missing_model_id: "<yellow>Проблема найдена в файле <arg:0> - В предмете '<arg:1>' отсутствует необходимый 'custom-model-data' или 'item-model' аргумент.</yellow>"
|
||||
warning.config.item.missing_model: "<yellow>Проблема найдена в файле <arg:0> - В предмете '<arg:1>' отсутствует необходимый 'model' раздел для поддержки пакета ресурсов 1.21.4+.</yellow>"
|
||||
@@ -225,18 +225,15 @@ warning.config.block.state.property.missing_type: "<yellow>Проблема на
|
||||
warning.config.block.state.property.invalid_type: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует недопустимый аргумент типа '<arg:2>' для свойства '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.property.integer.invalid_range: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует недействительный 'range' аргумент '<arg:2>' для integer свойства '<arg:3>'. Правильный синтаксис: 1~2.</yellow>"
|
||||
warning.config.block.state.property.invalid_format: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' имеет недействительный формат свойства состояния блока '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.missing_real_id: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'id' аргумент для 'state'. 'id' это идентификатор блока на стороне сервера, который уникален для каждого типа состояния блока. Если вы создаете блок на стороне сервера с 'note_block' и идентификатор 30, тогда реальный идентификатор блока будет 'craftengine:note_block_30'.</yellow>"
|
||||
warning.config.block.state.missing_state: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'state' аргумент для 'state'.</yellow>"
|
||||
warning.config.block.state.missing_properties: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'properties' раздел для 'states'.</yellow>"
|
||||
warning.config.block.state.missing_appearances: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'appearances' раздел для 'states'.</yellow>"
|
||||
warning.config.block.state.missing_variants: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'variants' раздел для 'states'.</yellow>"
|
||||
warning.config.block.state.variant.missing_appearance: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'appearance' аргумент для варианта '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.variant.invalid_appearance: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' имеет ошибку, что вариант '<arg:2>' использует несуществующий внешний вид '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' имеет недействительное состояние ванильного блока '<arg:2>'.</yellow>"
|
||||
warning.config.block.state.unavailable_vanilla: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует недоступное состояние ванильного блока '<arg:2>'. Пожалуйста, освободите это состояние в mappings.yml.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует состояние ванильного блока '<arg:2>', что превышает доступный диапазон слотов '0~<arg:3>'.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует состояние ванильного блока '<arg:2>' которое занято '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Проблема найдена в файле <arg:0> - Блоку '<arg:1>' не удалось привязать реальное состояние блока для '<arg:2>', так как состояние занято '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.id.conflict: "<yellow>Проблема найдена в файле <arg:0> - Блоку '<arg:1>' не удалось привязать реальное состояние блока для '<arg:2>', так как состояние занято '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'path' опция для 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' имеет 'path' аргумент '<arg:2>' содержит недопустимые символы. Пожалуйста, прочтите https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
|
||||
warning.config.block.settings.unknown: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует неизвестный тип настройки '<arg:2>'.</yellow>"
|
||||
|
||||
@@ -120,7 +120,7 @@ warning.config.item.settings.unknown: "<yellow><arg:0> dosyasında sorun bulundu
|
||||
warning.config.item.missing_material: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası gerekli 'material' argümanı eksik.</yellow>"
|
||||
warning.config.item.invalid_material: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası geçersiz bir malzeme türü '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.item.bad_custom_model_data: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası çok büyük bir özel model verisi '<arg:2>' kullanıyor. 16.777.216'dan düşük bir değer kullanmanız önerilir.</yellow>"
|
||||
warning.config.item.custom_model_data_conflict: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, '<arg:3>' eşyası tarafından işgal edilmiş bir özel model verisi '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.item.custom_model_data.conflict: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, '<arg:3>' eşyası tarafından işgal edilmiş bir özel model verisi '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.item.missing_model_id: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası gerekli 'custom-model-data' veya 'item-model' argümanı eksik.</yellow>"
|
||||
warning.config.item.behavior.missing_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, eşya davranışı için gerekli 'type' argümanı eksik.</yellow>"
|
||||
warning.config.item.behavior.invalid_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası geçersiz bir eşya davranış türü '<arg:2>' kullanıyor.</yellow>"
|
||||
@@ -173,18 +173,15 @@ warning.config.block.state.property.missing_type: "<yellow><arg:0> dosyasında s
|
||||
warning.config.block.state.property.invalid_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, '<arg:3>' özelliği için geçersiz bir 'type' argümanı '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.block.state.property.integer.invalid_range: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, '<arg:3>' tamsayı özelliği için geçersiz bir 'range' argümanı '<arg:2>' kullanıyor. Doğru sözdizimi: 1~2.</yellow>"
|
||||
warning.config.block.state.property.invalid_format: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, geçersiz bir blok durum özelliği formatı '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.block.state.missing_real_id: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, 'state' için gerekli 'id' argümanı eksik. 'id', her blok durumu türü için benzersiz olan sunucu tarafı blok kimliğidir. 'note_block' ve id 30 ile bir sunucu tarafı blok oluşturursanız, gerçek blok kimliği 'craftengine:note_block_30' olur.</yellow>"
|
||||
warning.config.block.state.missing_state: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, 'state' için gerekli 'state' argümanı eksik.</yellow>"
|
||||
warning.config.block.state.missing_properties: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, 'states' için gerekli 'properties' bölümü eksik.</yellow>"
|
||||
warning.config.block.state.missing_appearances: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, 'states' için gerekli 'appearances' bölümü eksik.</yellow>"
|
||||
warning.config.block.state.missing_variants: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, 'states' için gerekli 'variants' bölümü eksik.</yellow>"
|
||||
warning.config.block.state.variant.missing_appearance: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, '<arg:2>' varyantı için gerekli 'appearance' argümanı eksik.</yellow>"
|
||||
warning.config.block.state.variant.invalid_appearance: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğunda, '<arg:2>' varyantının var olmayan bir görünüm '<arg:3>' kullandığı bir hata var.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu geçersiz bir vanilya blok durumu '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.block.state.unavailable_vanilla: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu kullanılamayan bir vanilya blok durumu '<arg:2>' kullanıyor. Lütfen bu durumu mappings.yml dosyasında serbest bırakın.</yellow>"
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, mevcut yuva aralığı '0~<arg:3>' aşan bir vanilya blok durumu '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, '<arg:3>' tarafından işgal edilmiş bir vanilya blok durumu '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, durum '<arg:3>' tarafından işgal edildiği için '<arg:2>' için gerçek blok durumu bağlamada başarısız oldu.</yellow>"
|
||||
warning.config.block.state.id.conflict: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, durum '<arg:3>' tarafından işgal edildiği için '<arg:2>' için gerçek blok durumu bağlamada başarısız oldu.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, 'model' için gerekli 'path' seçeneği eksik.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğunun, yasak karakterler içeren bir 'path' argümanı '<arg:2>' var. Lütfen https://minecraft.wiki/w/Resource_location#Legal_characters sayfasını okuyun.</yellow>"
|
||||
warning.config.block.settings.unknown: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu bilinmeyen bir ayar türü '<arg:2>' kullanıyor.</yellow>"
|
||||
|
||||
@@ -192,7 +192,7 @@ warning.config.item.invalid_material: "<yellow>在文件 <arg:0> 发现问题 -
|
||||
warning.config.item.invalid_custom_model_data: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用了无效的负数模型值 '<arg:2>'</yellow>"
|
||||
warning.config.item.bad_custom_model_data: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用的自定义模型数据 '<arg:2>' 数值过大 建议使用小于 16,777,216 的值</yellow>"
|
||||
warning.config.item.item_model.conflict: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用了无效的 'item-model' 选项. 这个 item-model 已经存在对应的原版物品</yellow>"
|
||||
warning.config.item.custom_model_data_conflict: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用的自定义模型数据 '<arg:2>' 已被物品 '<arg:3>' 占用</yellow>"
|
||||
warning.config.item.custom_model_data.conflict: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用的自定义模型数据 '<arg:2>' 已被物品 '<arg:3>' 占用</yellow>"
|
||||
warning.config.item.invalid_component: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用了未知的数据组件 '<arg:2>'</yellow>"
|
||||
warning.config.item.missing_model_id: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 缺少必需的 'custom-model-data' 或 'item-model' 参数</yellow>"
|
||||
warning.config.item.missing_model: "<yellow>在文件 <arg:0> 中发现问题 - 物品 '<arg:1>' 缺少支持 1.21.4+ 资源包必需的 'model' 配置项</yellow>"
|
||||
@@ -260,19 +260,16 @@ warning.config.block.state.property.missing_type: "<yellow>在文件 <arg:0> 发
|
||||
warning.config.block.state.property.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的属性 '<arg:3>' 使用了无效的类型参数 '<arg:2>'</yellow>"
|
||||
warning.config.block.state.property.integer.invalid_range: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的整数属性 '<arg:3>' 使用了无效的范围参数 '<arg:2>' 正确语法: 1~2</yellow>"
|
||||
warning.config.block.state.property.invalid_format: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用了无效的方块状态属性格式 '<arg:2>'</yellow>"
|
||||
warning.config.block.state.missing_real_id: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'state' 缺少必需的 'id' 参数 该 ID 是服务端方块 ID 用于唯一标识每种方块状态类型</yellow>"
|
||||
warning.config.block.state.missing_state: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'state' 缺少必需的 'state' 参数</yellow>"
|
||||
warning.config.block.state.missing_properties: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'states' 缺少必需的 'properties' 段落</yellow>"
|
||||
warning.config.block.state.missing_appearances: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'states' 缺少必需的 'appearances' 段落</yellow>"
|
||||
warning.config.block.state.missing_variants: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'states' 缺少必需的 'variants' 段落</yellow>"
|
||||
warning.config.block.state.variant.missing_appearance: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的变体 '<arg:2>' 缺少必需的 'appearance' 参数</yellow>"
|
||||
warning.config.block.state.variant.invalid_appearance: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的变体 '<arg:2>' 使用了不存在的 appearance '<arg:3>'</yellow>"
|
||||
warning.config.block.state.invalid_vanilla: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用了无效的原版方块状态 '<arg:2>'</yellow>"
|
||||
warning.config.block.state.unavailable_vanilla: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用了不可用的原版方块状态 '<arg:2>' 请在 mappings.yml 中释放该状态</yellow>"
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用的原版方块状态 '<arg:2>' 超出可用槽位范围 '0~<arg:3>'</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用的原版方块状态 '<arg:2>' 已被 '<arg:3>' 占用</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 无法为 '<arg:2>' 绑定真实方块状态 '<arg:4>' 因该状态已被 '<arg:3>' 占用</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用的真实方块状态 '<arg:2>' 超出可用槽位范围 '0~<arg:3>' 如果槽位已用尽 请在 config.yml 中添加更多服务端侧方块</yellow>"
|
||||
warning.config.block.state.id.conflict: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 无法为 '<arg:2>' 绑定真实方块状态 '<arg:4>' 因该状态已被 '<arg:3>' 占用</yellow>"
|
||||
warning.config.block.state.invalid_id: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用的真实方块状态 '<arg:2>' 超出可用槽位范围 '0~<arg:3>' 如果槽位已用尽 请在 config.yml 中添加更多服务端侧方块</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'model' 缺少必需的 'path' 选项</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'path' 参数 '<arg:2>' 包含非法字符 请参考 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</yellow>"
|
||||
warning.config.block.state.model.conflict: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 正尝试将模型 '<arg:2>' 绑定到方块状态 '<arg:3>' 上, 但是此状态已绑定了另一个模型 '<arg:4>'</yellow>"
|
||||
|
||||
@@ -1,32 +1,54 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement;
|
||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig;
|
||||
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigs;
|
||||
import net.momirealms.craftengine.core.block.parser.BlockNbtParser;
|
||||
import net.momirealms.craftengine.core.block.properties.Properties;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.AbstractItemManager;
|
||||
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.PendingConfigSection;
|
||||
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
||||
import net.momirealms.craftengine.core.pack.cache.IdAllocator;
|
||||
import net.momirealms.craftengine.core.pack.model.generation.AbstractModelGenerator;
|
||||
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.*;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||
import net.momirealms.craftengine.core.plugin.config.IdSectionConfigParser;
|
||||
import net.momirealms.craftengine.core.plugin.config.SectionConfigParser;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedException;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public abstract class AbstractBlockManager extends AbstractModelGenerator implements BlockManager {
|
||||
@@ -50,6 +72,8 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
protected final Map<Key, Key> soundReplacements = new HashMap<>(512, 0.5f);
|
||||
// 用于note_block:0这样格式的自动分配
|
||||
protected final Map<Key, List<BlockStateWrapper>> blockStateArranger = new HashMap<>();
|
||||
// 根据registry id找note_block:x中的x值
|
||||
protected final Map<Integer, Integer> reversedBlockStateArranger = new HashMap<>();
|
||||
// 全方块状态映射文件,用于网络包映射
|
||||
protected final int[] blockStateMappings;
|
||||
// 原版方块状态数量
|
||||
@@ -103,6 +127,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
this.byId.clear();
|
||||
this.soundReplacements.clear();
|
||||
this.blockStateArranger.clear();
|
||||
this.reversedBlockStateArranger.clear();
|
||||
this.appearanceToRealState.clear();
|
||||
Arrays.fill(this.blockStateMappings, -1);
|
||||
Arrays.fill(this.immutableBlockStates, EmptyBlock.STATE);
|
||||
@@ -125,20 +150,12 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
return Optional.ofNullable(this.byId.get(id));
|
||||
}
|
||||
|
||||
protected void addBlockInternal(Key id, CustomBlock customBlock) {
|
||||
ExceptionCollector<LocalizedResourceConfigException> exceptionCollector = new ExceptionCollector<>();
|
||||
protected void addBlockInternal(CustomBlock customBlock) {
|
||||
// 绑定外观状态等
|
||||
for (ImmutableBlockState state : customBlock.variantProvider().states()) {
|
||||
int internalId = state.customBlockState().registryId();
|
||||
int appearanceId = state.vanillaBlockState().registryId();
|
||||
int index = internalId - this.vanillaBlockStateCount;
|
||||
ImmutableBlockState previous = this.immutableBlockStates[index];
|
||||
// todo 应当提前判断位置
|
||||
if (previous != null && !previous.isEmpty()) {
|
||||
exceptionCollector.add(new LocalizedResourceConfigException("warning.config.block.state.bind_failed",
|
||||
state.toString(), previous.toString(), getBlockOwnerId(previous.customBlockState()).toString()));
|
||||
continue;
|
||||
}
|
||||
this.immutableBlockStates[index] = state;
|
||||
this.blockStateMappings[internalId] = appearanceId;
|
||||
this.appearanceToRealState.computeIfAbsent(appearanceId, k -> new IntArrayList()).add(internalId);
|
||||
@@ -147,8 +164,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
this.modBlockStateOverrides.put(getBlockOwnerId(state.customBlockState()), this.tempVanillaBlockStateModels.get(appearanceId));
|
||||
}
|
||||
}
|
||||
this.byId.put(id, customBlock);
|
||||
exceptionCollector.throwIfPresent();
|
||||
this.byId.put(customBlock.id(), customBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -210,17 +226,22 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
return Optional.ofNullable(this.appearanceToRealState.get(appearanceStateId)).orElse(List.of());
|
||||
}
|
||||
|
||||
public abstract BlockBehavior createBlockBehavior(CustomBlock customBlock, List<Map<String, Object>> behaviorConfig);
|
||||
|
||||
protected abstract void resendTags();
|
||||
|
||||
protected abstract boolean isVanillaBlock(Key id);
|
||||
|
||||
protected abstract Key getBlockOwnerId(int id);
|
||||
|
||||
protected abstract CustomBlock.Builder platformBuilder(Key id);
|
||||
|
||||
protected abstract void setVanillaBlockTags(Key id, List<String> tags);
|
||||
|
||||
public abstract int vanillaBlockStateCount();
|
||||
protected abstract int vanillaBlockStateCount();
|
||||
|
||||
protected abstract CustomBlock createCustomBlock(@NotNull Holder.Reference<CustomBlock> holder,
|
||||
@NotNull BlockStateVariantProvider variantProvider,
|
||||
@NotNull Map<EventTrigger, List<Function<PlayerOptionalContext>>> events,
|
||||
@Nullable LootTable<?> lootTable);
|
||||
|
||||
public class BlockStateMappingParser implements SectionConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[]{"block-state-mappings", "block-state-mapping"};
|
||||
@@ -261,7 +282,9 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
continue;
|
||||
}
|
||||
AbstractBlockManager.this.blockStateMappings[beforeState.registryId()] = afterState.registryId();
|
||||
AbstractBlockManager.this.blockStateArranger.computeIfAbsent(getBlockOwnerId(beforeState), k -> new ArrayList<>()).add(afterState);
|
||||
List<BlockStateWrapper> blockStateWrappers = AbstractBlockManager.this.blockStateArranger.computeIfAbsent(getBlockOwnerId(beforeState), k -> new ArrayList<>());
|
||||
blockStateWrappers.add(beforeState);
|
||||
AbstractBlockManager.this.reversedBlockStateArranger.put(beforeState.registryId(), blockStateWrappers.size() - 1);
|
||||
}
|
||||
exceptionCollector.throwIfPresent();
|
||||
}
|
||||
@@ -269,6 +292,63 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
|
||||
public class BlockParser implements IdSectionConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[]{"blocks", "block"};
|
||||
private final IdAllocator internalIdAllocator;
|
||||
private final Map<Key, IdAllocator> appearanceIdAllocators = new HashMap<>();
|
||||
private final List<PendingConfigSection> pendingConfigSections = new ArrayList<>();
|
||||
|
||||
public BlockParser() {
|
||||
this.internalIdAllocator = new IdAllocator(AbstractBlockManager.this.plugin.dataFolderPath().resolve("cache").resolve("custom-block-states.json"));
|
||||
}
|
||||
|
||||
public void addPendingConfigSection(PendingConfigSection section) {
|
||||
this.pendingConfigSections.add(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcess() {
|
||||
this.internalIdAllocator.processPendingAllocations();
|
||||
try {
|
||||
this.internalIdAllocator.saveToCache();
|
||||
} catch (IOException e) {
|
||||
AbstractBlockManager.this.plugin.logger().warn("Error while saving custom block state allocation", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preProcess() {
|
||||
this.internalIdAllocator.reset(0, Config.serverSideBlocks() - 1);
|
||||
try {
|
||||
this.internalIdAllocator.loadFromCache();
|
||||
} catch (IOException e) {
|
||||
AbstractBlockManager.this.plugin.logger().warn("Error while loading custom block state allocation cache", e);
|
||||
}
|
||||
for (PendingConfigSection section : this.pendingConfigSections) {
|
||||
ResourceConfigUtils.runCatching(
|
||||
section.path(),
|
||||
section.node(),
|
||||
() -> parseSection(section.pack(), section.path(), section.node(), section.id(), section.config()),
|
||||
() -> GsonHelper.get().toJson(section.config())
|
||||
);
|
||||
}
|
||||
this.pendingConfigSections.clear();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IdAllocator getOrCreateAppearanceIdAllocator(Key type) {
|
||||
if (!AbstractBlockManager.this.blockStateArranger.containsKey(type)) {
|
||||
return null;
|
||||
}
|
||||
return this.appearanceIdAllocators.computeIfAbsent(type, k -> {
|
||||
IdAllocator newAllocator = new IdAllocator(plugin.dataFolderPath().resolve("cache").resolve("visual-block-states").resolve(k.value() + ".json"));
|
||||
newAllocator.reset(0, AbstractBlockManager.this.blockStateArranger.get(type).size());
|
||||
try {
|
||||
newAllocator.loadFromCache();
|
||||
} catch (IOException e) {
|
||||
AbstractBlockManager.this.plugin.logger().warn("Error while loading visual block states cache for block " + k.asString(), e);
|
||||
}
|
||||
return newAllocator;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] sectionId() {
|
||||
@@ -289,7 +369,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
if (AbstractBlockManager.this.byId.containsKey(id)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.duplicate");
|
||||
}
|
||||
parseCustomBlock(id, section);
|
||||
parseCustomBlock(path, node, id, section);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,86 +384,171 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
}
|
||||
}
|
||||
|
||||
private void parseCustomBlock(Key id, Map<String, Object> section) {
|
||||
// 获取方块设置
|
||||
private void parseCustomBlock(Path path, String node, Key id, Map<String, Object> section) {
|
||||
// 获取共享方块设置
|
||||
BlockSettings settings = BlockSettings.fromMap(id, MiscUtils.castToMap(section.get("settings"), true));
|
||||
// 读取基础外观配置
|
||||
Map<String, Property<?>> properties;
|
||||
Map<String, BlockStateAppearance> appearances;
|
||||
Map<String, BlockStateVariant> variants;
|
||||
// 读取states区域
|
||||
Map<String, Object> stateSection = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(
|
||||
ResourceConfigUtils.get(section, "state", "states"), "warning.config.block.missing_state"), true);
|
||||
Map<String, Object> stateSection = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "state", "states"), "warning.config.block.missing_state"), true);
|
||||
boolean singleState = !stateSection.containsKey("properties");
|
||||
// 单方块状态
|
||||
if (singleState) {
|
||||
int internalId = ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("id"), "warning.config.block.state.missing_real_id"), "id");
|
||||
// 获取原版外观的注册表id
|
||||
BlockStateWrapper appearanceState = parsePluginFormattedBlockState(ResourceConfigUtils.requireNonEmptyStringOrThrow(stateSection.get("state"), "warning.config.block.state.missing_state"));
|
||||
Optional<BlockEntityElementConfig<? extends BlockEntityElement>[]> blockEntityRenderer = parseBlockEntityRender(stateSection.get("entity-renderer"));
|
||||
// 为原版外观赋予外观模型并检查模型冲突
|
||||
this.arrangeModelForStateAndVerify(appearanceState, ResourceConfigUtils.get(stateSection, "model", "models"));
|
||||
// 设置参数
|
||||
properties = Map.of();
|
||||
appearances = Map.of("", new BlockStateAppearance(appearanceState, blockEntityRenderer));
|
||||
variants = Map.of("", new BlockStateVariant("", settings, getInternalBlockState(internalId)));
|
||||
}
|
||||
// 多方块状态
|
||||
else {
|
||||
properties = parseBlockProperties(ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("properties"), "warning.config.block.state.missing_properties"), "properties"));
|
||||
appearances = parseBlockAppearances(ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("appearances"), "warning.config.block.state.missing_appearances"), "appearances"));
|
||||
variants = parseBlockVariants(
|
||||
ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("variants"), "warning.config.block.state.missing_variants"), "variants"),
|
||||
appearances::containsKey, settings
|
||||
);
|
||||
}
|
||||
// 读取方块的property,通过property决定
|
||||
Map<String, Property<?>> properties = singleState ? Map.of() : parseBlockProperties(ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("properties"), "warning.config.block.state.missing_properties"), "properties"));
|
||||
// 注册方块容器
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).getOrRegisterForHolder(ResourceKey.create(BuiltInRegistries.BLOCK.key().location(), id));
|
||||
|
||||
addBlockInternal(id, platformBuilder(id)
|
||||
.appearances(appearances)
|
||||
.variantMapper(variants)
|
||||
.properties(properties)
|
||||
.settings(settings)
|
||||
.lootTable(LootTable.fromMap(ResourceConfigUtils.getAsMapOrNull(section.get("loot"), "loot")))
|
||||
.behavior(MiscUtils.getAsMapList(ResourceConfigUtils.get(section, "behavior", "behaviors")))
|
||||
.events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")))
|
||||
.build());
|
||||
}
|
||||
// 根据properties生成variant provider
|
||||
BlockStateVariantProvider variantProvider = new BlockStateVariantProvider(holder, (owner, propertyMap) -> {
|
||||
ImmutableBlockState blockState = new ImmutableBlockState(owner, propertyMap);
|
||||
blockState.setSettings(settings);
|
||||
return blockState;
|
||||
}, properties);
|
||||
|
||||
private Map<String, BlockStateVariant> parseBlockVariants(Map<String, Object> variantsSection,
|
||||
Predicate<String> appearanceValidator,
|
||||
BlockSettings parentSettings) {
|
||||
Map<String, BlockStateVariant> variants = new HashMap<>();
|
||||
for (Map.Entry<String, Object> entry : variantsSection.entrySet()) {
|
||||
Map<String, Object> variantSection = ResourceConfigUtils.getAsMap(entry.getValue(), entry.getKey());
|
||||
String variantNBT = entry.getKey();
|
||||
String appearance = ResourceConfigUtils.requireNonEmptyStringOrThrow(variantSection.get("appearance"), "warning.config.block.state.variant.missing_appearance");
|
||||
if (!appearanceValidator.test(appearance)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.variant.invalid_appearance", variantNBT, appearance);
|
||||
ImmutableList<ImmutableBlockState> states = variantProvider.states();
|
||||
List<CompletableFuture<Integer>> internalIdAllocators = new ArrayList<>(states.size());
|
||||
|
||||
// 如果用户指定了起始id
|
||||
if (stateSection.containsKey("id")) {
|
||||
int startingId = ResourceConfigUtils.getAsInt(stateSection.get("id"), "id");
|
||||
int endingId = startingId + states.size() - 1;
|
||||
if (startingId < 0 || endingId >= Config.serverSideBlocks()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_id", startingId + "~" + endingId, String.valueOf(Config.serverSideBlocks() - 1));
|
||||
}
|
||||
// 先检测范围冲突
|
||||
List<Pair<String, Integer>> conflicts = this.internalIdAllocator.getFixedIdsBetween(startingId, endingId);
|
||||
if (!conflicts.isEmpty()) {
|
||||
ExceptionCollector<LocalizedResourceConfigException> exceptionCollector = new ExceptionCollector<>();
|
||||
for (Pair<String, Integer> conflict : conflicts) {
|
||||
int internalId = conflict.right();
|
||||
int index = internalId - startingId;
|
||||
exceptionCollector.add(new LocalizedResourceConfigException("warning.config.block.state.id.conflict", states.get(index).toString(), conflict.left(), BlockManager.createCustomBlockKey(internalId).toString()));
|
||||
}
|
||||
exceptionCollector.throwIfPresent();
|
||||
}
|
||||
// 强行分配id
|
||||
for (ImmutableBlockState blockState : states) {
|
||||
String blockStateId = blockState.toString();
|
||||
internalIdAllocators.add(this.internalIdAllocator.assignFixedId(blockStateId, startingId++));
|
||||
}
|
||||
}
|
||||
// 未指定,则使用自动分配
|
||||
else {
|
||||
for (ImmutableBlockState blockState : states) {
|
||||
String blockStateId = blockState.toString();
|
||||
internalIdAllocators.add(this.internalIdAllocator.requestAutoId(blockStateId));
|
||||
}
|
||||
BlockStateWrapper internalBlockState = getInternalBlockState(ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(variantSection.get("id"), "warning.config.block.state.missing_real_id"), "id"));
|
||||
Map<String, Object> anotherSetting = ResourceConfigUtils.getAsMapOrNull(variantSection.get("settings"), "settings");
|
||||
variants.put(variantNBT, new BlockStateVariant(appearance, anotherSetting == null ? parentSettings : BlockSettings.ofFullCopy(parentSettings, anotherSetting), internalBlockState));
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
|
||||
private BlockStateWrapper getInternalBlockState(int internalId) {
|
||||
if (internalId >= Config.serverSideBlocks()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id", BlockManager.createCustomBlockKey(internalId).asString(), String.valueOf(Config.serverSideBlocks() - 1));
|
||||
}
|
||||
return BlockRegistryMirror.byId(internalId + vanillaBlockStateCount());
|
||||
}
|
||||
CompletableFutures.allOf(internalIdAllocators).thenRun(() -> ResourceConfigUtils.runCatching(path, node, () -> {
|
||||
for (int i = 0; i < internalIdAllocators.size(); i++) {
|
||||
CompletableFuture<Integer> future = internalIdAllocators.get(i);
|
||||
try {
|
||||
int internalId = future.get();
|
||||
states.get(i).setCustomBlockState(BlockRegistryMirror.byId(internalId + AbstractBlockManager.this.vanillaBlockStateCount));
|
||||
} catch (ExecutionException e) {
|
||||
Throwable cause = e.getCause();
|
||||
// 这里不会有conflict了,因为之前已经判断过了
|
||||
if (cause instanceof IdAllocator.IdExhaustedException) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.id.exhausted");
|
||||
} else {
|
||||
Debugger.BLOCK.warn(() -> "Unknown error while allocating internal block state id.", cause);
|
||||
return;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
AbstractBlockManager.this.plugin.logger().warn("Interrupted while parsing allocating internal block state", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, BlockStateAppearance> parseBlockAppearances(Map<String, Object> appearancesSection) {
|
||||
Map<String, BlockStateAppearance> appearances = new HashMap<>();
|
||||
for (Map.Entry<String, Object> entry : appearancesSection.entrySet()) {
|
||||
Map<String, Object> appearanceSection = ResourceConfigUtils.getAsMap(entry.getValue(), entry.getKey());
|
||||
BlockStateWrapper appearanceId = parsePluginFormattedBlockState(ResourceConfigUtils.requireNonEmptyStringOrThrow(
|
||||
appearanceSection.get("state"), "warning.config.block.state.missing_state"));
|
||||
this.arrangeModelForStateAndVerify(appearanceId, ResourceConfigUtils.get(appearanceSection, "model", "models"));
|
||||
appearances.put(entry.getKey(), new BlockStateAppearance(appearanceId, parseBlockEntityRender(appearanceSection.get("entity-renderer"))));
|
||||
}
|
||||
return appearances;
|
||||
// 创建自定义方块
|
||||
AbstractCustomBlock customBlock = (AbstractCustomBlock) createCustomBlock(
|
||||
holder,
|
||||
variantProvider,
|
||||
EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")),
|
||||
LootTable.fromMap(ResourceConfigUtils.getAsMapOrNull(section.get("loot"), "loot"))
|
||||
);
|
||||
BlockBehavior blockBehavior = createBlockBehavior(customBlock, MiscUtils.getAsMapList(ResourceConfigUtils.get(section, "behavior", "behaviors")));
|
||||
customBlock.setBehavior(blockBehavior);
|
||||
holder.bindValue(customBlock);
|
||||
|
||||
// 单状态
|
||||
if (singleState) {
|
||||
BlockStateWrapper appearanceState = parsePluginFormattedBlockState(ResourceConfigUtils.requireNonEmptyStringOrThrow(stateSection.get("state"), "warning.config.block.state.missing_state"));
|
||||
this.arrangeModelForStateAndVerify(appearanceState, ResourceConfigUtils.get(stateSection, "model", "models"));
|
||||
ImmutableBlockState onlyState = states.getFirst();
|
||||
// 为唯一的状态绑定外观
|
||||
onlyState.setVanillaBlockState(appearanceState);
|
||||
parseBlockEntityRender(stateSection.get("entity-renderer")).ifPresent(onlyState::setConstantRenderers);
|
||||
} else {
|
||||
BlockStateWrapper anyAppearanceState = null;
|
||||
Map<String, Object> appearancesSection = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("appearances"), "warning.config.block.state.missing_appearances"), "appearances");
|
||||
// 也不能为空
|
||||
if (appearancesSection.isEmpty()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.missing_appearances");
|
||||
}
|
||||
Map<String, BlockStateAppearance> appearances = Maps.newHashMap();
|
||||
// 先解析所有的外观
|
||||
for (Map.Entry<String, Object> entry : appearancesSection.entrySet()) {
|
||||
Map<String, Object> appearanceSection = ResourceConfigUtils.getAsMap(entry.getValue(), entry.getKey());
|
||||
// 解析对应的视觉方块
|
||||
BlockStateWrapper appearanceState = parsePluginFormattedBlockState(ResourceConfigUtils.requireNonEmptyStringOrThrow(appearanceSection.get("state"), "warning.config.block.state.missing_state"));
|
||||
this.arrangeModelForStateAndVerify(appearanceState, ResourceConfigUtils.get(appearanceSection, "model", "models"));
|
||||
appearances.put(entry.getKey(), new BlockStateAppearance(appearanceState, parseBlockEntityRender(appearanceSection.get("entity-renderer"))));
|
||||
if (anyAppearanceState == null) {
|
||||
anyAppearanceState = appearanceState;
|
||||
}
|
||||
}
|
||||
// 解析变体
|
||||
Map<String, Object> variantsSection = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("variants"), "warning.config.block.state.missing_variants"), "variants");
|
||||
for (Map.Entry<String, Object> entry : variantsSection.entrySet()) {
|
||||
Map<String, Object> variantSection = ResourceConfigUtils.getAsMap(entry.getValue(), entry.getKey());
|
||||
String variantNBT = entry.getKey();
|
||||
// 先解析nbt,找到需要修改的方块状态
|
||||
CompoundTag tag = BlockNbtParser.deserialize(variantProvider, variantNBT);
|
||||
if (tag == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.property.invalid_format", variantNBT);
|
||||
}
|
||||
List<ImmutableBlockState> possibleStates = variantProvider.getPossibleStates(tag);
|
||||
Map<String, Object> anotherSetting = ResourceConfigUtils.getAsMapOrNull(variantSection.get("settings"), "settings");
|
||||
if (anotherSetting != null) {
|
||||
for (ImmutableBlockState possibleState : possibleStates) {
|
||||
possibleState.setSettings(BlockSettings.ofFullCopy(possibleState.settings(), anotherSetting));
|
||||
}
|
||||
}
|
||||
String appearanceName = ResourceConfigUtils.getAsString(variantSection.get("appearance"));
|
||||
if (appearanceName != null) {
|
||||
BlockStateAppearance appearance = appearances.get(appearanceName);
|
||||
if (appearance == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.variant.invalid_appearance", variantNBT, appearanceName);
|
||||
}
|
||||
for (ImmutableBlockState possibleState : possibleStates) {
|
||||
possibleState.setVanillaBlockState(appearance.blockState());
|
||||
appearance.blockEntityRenderer().ifPresent(possibleState::setConstantRenderers);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 为没有外观的方块状态填充
|
||||
for (ImmutableBlockState blockState : states) {
|
||||
if (blockState.vanillaBlockState() == null) {
|
||||
blockState.setVanillaBlockState(anyAppearanceState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取方块实体行为
|
||||
EntityBlockBehavior entityBlockBehavior = blockBehavior.getEntityBehavior();
|
||||
boolean isEntityBlock = entityBlockBehavior != null;
|
||||
|
||||
// 绑定行为
|
||||
for (ImmutableBlockState blockState : states) {
|
||||
blockState.setBehavior(blockBehavior);
|
||||
if (isEntityBlock) {
|
||||
blockState.setBlockEntityType(entityBlockBehavior.blockEntityType());
|
||||
}
|
||||
}
|
||||
|
||||
// 添加方块
|
||||
addBlockInternal(customBlock);
|
||||
|
||||
}, () -> GsonHelper.get().toJson(section)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.momirealms.craftengine.core.block.behavior.EmptyBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.parser.BlockNbtParser;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
@@ -11,7 +8,6 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
@@ -23,79 +19,31 @@ import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public abstract class AbstractCustomBlock implements CustomBlock {
|
||||
protected final Holder<CustomBlock> holder;
|
||||
protected final Key id;
|
||||
protected final Holder.Reference<CustomBlock> holder;
|
||||
protected final BlockStateVariantProvider variantProvider;
|
||||
protected final Map<String, Property<?>> properties;
|
||||
protected final BlockBehavior behavior;
|
||||
protected final BiFunction<BlockPlaceContext, ImmutableBlockState, ImmutableBlockState> placementFunction;
|
||||
protected final ImmutableBlockState defaultState;
|
||||
protected final Map<EventTrigger, List<Function<PlayerOptionalContext>>> events;
|
||||
@Nullable
|
||||
protected final LootTable<?> lootTable;
|
||||
protected BlockBehavior behavior = EmptyBlockBehavior.INSTANCE;
|
||||
|
||||
protected AbstractCustomBlock(
|
||||
@NotNull Key id,
|
||||
@NotNull Holder.Reference<CustomBlock> holder,
|
||||
@NotNull Map<String, Property<?>> properties,
|
||||
@NotNull Map<String, BlockStateAppearance> appearances,
|
||||
@NotNull Map<String, BlockStateVariant> variantMapper,
|
||||
@NotNull BlockSettings settings,
|
||||
@NotNull BlockStateVariantProvider variantProvider,
|
||||
@NotNull Map<EventTrigger, List<Function<PlayerOptionalContext>>> events,
|
||||
@Nullable List<Map<String, Object>> behaviorConfig,
|
||||
@Nullable LootTable<?> lootTable
|
||||
) {
|
||||
holder.bindValue(this);
|
||||
this.holder = holder;
|
||||
this.id = id;
|
||||
this.lootTable = lootTable;
|
||||
this.properties = ImmutableMap.copyOf(properties);
|
||||
this.events = events;
|
||||
this.variantProvider = new BlockStateVariantProvider(holder, ImmutableBlockState::new, properties);
|
||||
this.variantProvider = variantProvider;
|
||||
this.defaultState = this.variantProvider.getDefaultState();
|
||||
this.behavior = setupBehavior(behaviorConfig);
|
||||
List<BiFunction<BlockPlaceContext, ImmutableBlockState, ImmutableBlockState>> placements = new ArrayList<>(4);
|
||||
for (Map.Entry<String, Property<?>> propertyEntry : this.properties.entrySet()) {
|
||||
for (Map.Entry<String, Property<?>> propertyEntry : this.variantProvider.properties().entrySet()) {
|
||||
placements.add(Property.createStateForPlacement(propertyEntry.getKey(), propertyEntry.getValue()));
|
||||
}
|
||||
this.placementFunction = composite(placements);
|
||||
EntityBlockBehavior entityBlockBehavior = this.behavior.getEntityBehavior();
|
||||
boolean isEntityBlock = entityBlockBehavior != null;
|
||||
|
||||
for (Map.Entry<String, BlockStateVariant> entry : variantMapper.entrySet()) {
|
||||
String nbtString = entry.getKey();
|
||||
CompoundTag tag = BlockNbtParser.deserialize(this, nbtString);
|
||||
if (tag == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.property.invalid_format", nbtString);
|
||||
}
|
||||
List<ImmutableBlockState> possibleStates = this.getPossibleStates(tag);
|
||||
if (possibleStates.size() != 1) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.property.invalid_format", nbtString);
|
||||
}
|
||||
BlockStateVariant blockStateVariant = entry.getValue();
|
||||
BlockStateAppearance blockStateAppearance = appearances.get(blockStateVariant.appearance());
|
||||
// Late init states
|
||||
ImmutableBlockState state = possibleStates.getFirst();
|
||||
state.setSettings(blockStateVariant.settings());
|
||||
state.setVanillaBlockState(blockStateAppearance.blockState());
|
||||
state.setCustomBlockState(blockStateVariant.blockState());
|
||||
blockStateAppearance.blockEntityRenderer().ifPresent(state::setConstantRenderers);
|
||||
}
|
||||
|
||||
// double check if there's any invalid state
|
||||
for (ImmutableBlockState state : this.variantProvider().states()) {
|
||||
state.setBehavior(this.behavior);
|
||||
if (state.settings() == null) {
|
||||
state.setSettings(settings);
|
||||
}
|
||||
if (isEntityBlock) {
|
||||
state.setBlockEntityType(entityBlockBehavior.blockEntityType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected BlockBehavior setupBehavior(List<Map<String, Object>> behaviorConfig) {
|
||||
return EmptyBlockBehavior.INSTANCE;
|
||||
}
|
||||
|
||||
private static BiFunction<BlockPlaceContext, ImmutableBlockState, ImmutableBlockState> composite(List<BiFunction<BlockPlaceContext, ImmutableBlockState, ImmutableBlockState>> placements) {
|
||||
@@ -137,28 +85,16 @@ public abstract class AbstractCustomBlock implements CustomBlock {
|
||||
@NotNull
|
||||
@Override
|
||||
public final Key id() {
|
||||
return this.id;
|
||||
return this.holder.key().location();
|
||||
}
|
||||
|
||||
public void setBehavior(@Nullable BlockBehavior behavior) {
|
||||
this.behavior = behavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImmutableBlockState> getPossibleStates(CompoundTag nbt) {
|
||||
List<ImmutableBlockState> tempStates = new ArrayList<>();
|
||||
tempStates.add(defaultState());
|
||||
for (Property<?> property : this.variantProvider.getDefaultState().getProperties()) {
|
||||
Tag value = nbt.get(property.name());
|
||||
if (value != null) {
|
||||
tempStates.replaceAll(immutableBlockState -> ImmutableBlockState.with(immutableBlockState, property, property.unpack(value)));
|
||||
} else {
|
||||
List<ImmutableBlockState> newStates = new ArrayList<>();
|
||||
for (ImmutableBlockState state : tempStates) {
|
||||
for (Object possibleValue : property.possibleValues()) {
|
||||
newStates.add(ImmutableBlockState.with(state, property, possibleValue));
|
||||
}
|
||||
}
|
||||
tempStates = newStates;
|
||||
}
|
||||
}
|
||||
return tempStates;
|
||||
return this.variantProvider.getPossibleStates(nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -179,12 +115,12 @@ public abstract class AbstractCustomBlock implements CustomBlock {
|
||||
|
||||
@Override
|
||||
public @Nullable Property<?> getProperty(String name) {
|
||||
return this.properties.get(name);
|
||||
return this.variantProvider.getProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Property<?>> properties() {
|
||||
return this.properties.values();
|
||||
return this.variantProvider.properties().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockStateHolder {
|
||||
protected final Holder<CustomBlock> owner;
|
||||
protected final Holder.Reference<CustomBlock> owner;
|
||||
private final Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap;
|
||||
private Map<Property<?>, ImmutableBlockState[]> withMap;
|
||||
|
||||
public BlockStateHolder(Holder<CustomBlock> owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap) {
|
||||
public BlockStateHolder(Holder.Reference<CustomBlock> owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap) {
|
||||
this.owner = owner;
|
||||
this.propertyMap = new Reference2ObjectArrayMap<>(propertyMap);
|
||||
}
|
||||
@@ -39,9 +39,9 @@ public class BlockStateHolder {
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this.propertyMap.isEmpty()) {
|
||||
return this.owner.value().id().toString();
|
||||
return this.owner.key().location().toString();
|
||||
}
|
||||
return this.owner.value().id() + "[" + getPropertiesAsString() + "]";
|
||||
return this.owner.key().location() + "[" + getPropertiesAsString() + "]";
|
||||
}
|
||||
|
||||
public String getPropertiesAsString() {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
public class BlockStateVariant {
|
||||
private final String appearance;
|
||||
private final BlockSettings settings;
|
||||
private final BlockStateWrapper blockState;
|
||||
|
||||
public BlockStateVariant(String appearance, BlockSettings settings, BlockStateWrapper blockState) {
|
||||
this.appearance = appearance;
|
||||
this.settings = settings;
|
||||
this.blockState = blockState;
|
||||
}
|
||||
|
||||
public String appearance() {
|
||||
return appearance;
|
||||
}
|
||||
|
||||
public BlockSettings settings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public BlockStateWrapper blockState() {
|
||||
return blockState;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -23,7 +25,7 @@ public final class BlockStateVariantProvider {
|
||||
private final ImmutableList<ImmutableBlockState> states;
|
||||
private final Holder<CustomBlock> owner;
|
||||
|
||||
public BlockStateVariantProvider(Holder<CustomBlock> owner, Factory<Holder<CustomBlock>, ImmutableBlockState> factory, Map<String, Property<?>> propertiesMap) {
|
||||
public BlockStateVariantProvider(Holder.Reference<CustomBlock> owner, Factory<Holder.Reference<CustomBlock>, ImmutableBlockState> factory, Map<String, Property<?>> propertiesMap) {
|
||||
this.owner = owner;
|
||||
this.properties = ImmutableSortedMap.copyOf(propertiesMap);
|
||||
|
||||
@@ -59,6 +61,27 @@ public final class BlockStateVariantProvider {
|
||||
this.states = ImmutableList.copyOf(list);
|
||||
}
|
||||
|
||||
public List<ImmutableBlockState> getPossibleStates(CompoundTag nbt) {
|
||||
List<ImmutableBlockState> tempStates = new ArrayList<>();
|
||||
ImmutableBlockState defaultState = getDefaultState();
|
||||
tempStates.add(defaultState);
|
||||
for (Property<?> property : defaultState.getProperties()) {
|
||||
Tag value = nbt.get(property.name());
|
||||
if (value != null) {
|
||||
tempStates.replaceAll(immutableBlockState -> ImmutableBlockState.with(immutableBlockState, property, property.unpack(value)));
|
||||
} else {
|
||||
List<ImmutableBlockState> newStates = new ArrayList<>();
|
||||
for (ImmutableBlockState state : tempStates) {
|
||||
for (Object possibleValue : property.possibleValues()) {
|
||||
newStates.add(ImmutableBlockState.with(state, property, possibleValue));
|
||||
}
|
||||
}
|
||||
tempStates = newStates;
|
||||
}
|
||||
}
|
||||
return tempStates;
|
||||
}
|
||||
|
||||
public interface Factory<O, S> {
|
||||
S create(O owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap);
|
||||
}
|
||||
@@ -80,6 +103,11 @@ public final class BlockStateVariantProvider {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ImmutableSortedMap<String, Property<?>> properties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Property<?> getProperty(String name) {
|
||||
return this.properties.get(name);
|
||||
|
||||
@@ -40,23 +40,4 @@ public interface CustomBlock {
|
||||
ImmutableBlockState getStateForPlacement(BlockPlaceContext context);
|
||||
|
||||
void setPlacedBy(BlockPlaceContext context, ImmutableBlockState state);
|
||||
|
||||
interface Builder {
|
||||
|
||||
Builder events(Map<EventTrigger, List<Function<PlayerOptionalContext>>> events);
|
||||
|
||||
Builder appearances(Map<String, BlockStateAppearance> appearances);
|
||||
|
||||
Builder behavior(List<Map<String, Object>> behavior);
|
||||
|
||||
Builder lootTable(LootTable<?> lootTable);
|
||||
|
||||
Builder properties(Map<String, Property<?>> properties);
|
||||
|
||||
Builder settings(BlockSettings settings);
|
||||
|
||||
Builder variantMapper(Map<String, BlockStateVariant> variantMapper);
|
||||
|
||||
@NotNull CustomBlock build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import net.momirealms.craftengine.core.block.behavior.EmptyBlockBehavior;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class EmptyBlock extends AbstractCustomBlock {
|
||||
public static EmptyBlock INSTANCE;
|
||||
public static ImmutableBlockState STATE;
|
||||
public static final EmptyBlock INSTANCE;
|
||||
public static final ImmutableBlockState STATE;
|
||||
|
||||
public EmptyBlock(Key id, Holder.Reference<CustomBlock> holder) {
|
||||
super(id, holder, Map.of(), Map.of(), Map.of(), BlockSettings.of(), Map.of(), List.of(), null);
|
||||
INSTANCE = this;
|
||||
STATE = defaultState();
|
||||
static {
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK)
|
||||
.registerForHolder(ResourceKey.create(BuiltInRegistries.BLOCK.key().location(), Key.withDefaultNamespace("empty")));
|
||||
INSTANCE = new EmptyBlock(holder);
|
||||
holder.bindValue(INSTANCE);
|
||||
STATE = INSTANCE.defaultState();
|
||||
STATE.setSettings(BlockSettings.of());
|
||||
STATE.setBehavior(EmptyBlockBehavior.INSTANCE);
|
||||
}
|
||||
|
||||
private EmptyBlock(Holder.Reference<CustomBlock> holder) {
|
||||
super(holder, new BlockStateVariantProvider(holder, ImmutableBlockState::new, Map.of()), Map.of(), null);
|
||||
}
|
||||
|
||||
public static void initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class ImmutableBlockState extends BlockStateHolder {
|
||||
private BlockEntityElementConfig<? extends BlockEntityElement>[] renderers;
|
||||
|
||||
ImmutableBlockState(
|
||||
Holder<CustomBlock> owner,
|
||||
Holder.Reference<CustomBlock> owner,
|
||||
Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap
|
||||
) {
|
||||
super(owner, propertyMap);
|
||||
@@ -129,7 +129,7 @@ public final class ImmutableBlockState extends BlockStateHolder {
|
||||
public CompoundTag toNbtToSave(CompoundTag properties) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.put("properties", properties);
|
||||
tag.put("id", NBT.createString(this.owner.value().id().asString()));
|
||||
tag.put("id", NBT.createString(this.owner.key().location().asString()));
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,18 +2,16 @@ package net.momirealms.craftengine.core.block;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class InactiveCustomBlock extends AbstractCustomBlock {
|
||||
private final Map<CompoundTag, ImmutableBlockState> cachedData = new HashMap<>();
|
||||
|
||||
public InactiveCustomBlock(Key id, Holder.Reference<CustomBlock> holder) {
|
||||
super(id, holder, Map.of(), Map.of(), Map.of(), BlockSettings.of(), Map.of(), List.of(), null);
|
||||
public InactiveCustomBlock(Holder.Reference<CustomBlock> holder) {
|
||||
super(holder, new BlockStateVariantProvider(holder, ImmutableBlockState::new, Map.of()), Map.of(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.core.block.parser;
|
||||
|
||||
import net.momirealms.craftengine.core.block.BlockStateVariantProvider;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.util.StringReader;
|
||||
@@ -7,11 +8,13 @@ import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class BlockNbtParser {
|
||||
private BlockNbtParser() {}
|
||||
|
||||
@Nullable
|
||||
public static CompoundTag deserialize(@NotNull CustomBlock block, @NotNull String data) {
|
||||
public static CompoundTag deserialize(@NotNull Function<String, Property<?>> propertyProvider, @NotNull String data) {
|
||||
StringReader reader = StringReader.simple(data);
|
||||
CompoundTag properties = new CompoundTag();
|
||||
while (reader.canRead()) {
|
||||
@@ -24,7 +27,7 @@ public final class BlockNbtParser {
|
||||
if (propertyValue.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Property<?> property = block.getProperty(propertyName);
|
||||
Property<?> property = propertyProvider.apply(propertyName);
|
||||
if (property != null) {
|
||||
property.createOptionalTag(propertyValue).ifPresent(tag -> {
|
||||
properties.put(propertyName, tag);
|
||||
@@ -38,4 +41,14 @@ public final class BlockNbtParser {
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CompoundTag deserialize(@NotNull CustomBlock block, @NotNull String data) {
|
||||
return deserialize(block::getProperty, data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CompoundTag deserialize(@NotNull BlockStateVariantProvider variantProvider, @NotNull String data) {
|
||||
return deserialize(variantProvider::getProperty, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
@@ -424,17 +425,27 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
||||
}
|
||||
|
||||
// 当模型值完成分配的时候
|
||||
customModelDataFuture.whenComplete((customModelData, throwable) -> ResourceConfigUtils.runCatching(path, node, () -> {
|
||||
|
||||
customModelDataFuture.whenComplete((cmd, throwable) -> ResourceConfigUtils.runCatching(path, node, () -> {
|
||||
int customModelData;
|
||||
if (throwable != null) {
|
||||
// 检测custom model data 冲突
|
||||
if (throwable instanceof IdAllocator.IdConflictException exception) {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.custom_model_data_conflict", String.valueOf(exception.id()), exception.previousOwner());
|
||||
if (section.containsKey("model") || section.containsKey("legacy-model")) {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.custom_model_data.conflict", String.valueOf(exception.id()), exception.previousOwner());
|
||||
}
|
||||
customModelData = exception.id();
|
||||
}
|
||||
// custom model data 已被用尽,不太可能
|
||||
else if (throwable instanceof IdAllocator.IdExhaustedException) {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.custom_model_data_exhausted");
|
||||
throw new LocalizedResourceConfigException("warning.config.item.custom_model_data.exhausted");
|
||||
}
|
||||
// 未知错误
|
||||
else {
|
||||
Debugger.ITEM.warn(() -> "Unknown error while allocating custom model data.", throwable);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
customModelData = cmd;
|
||||
}
|
||||
|
||||
// item model
|
||||
|
||||
@@ -6,13 +6,10 @@ import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemBehaviors {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.momirealms.craftengine.core.pack;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public record PendingConfigSection(Pack pack, Path path, String node, Key id, Map<String, Object> config) {
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import net.momirealms.craftengine.core.util.FileUtils;
|
||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
@@ -57,6 +58,9 @@ public class IdAllocator {
|
||||
continue;
|
||||
}
|
||||
allocateId(id, future);
|
||||
} else {
|
||||
// 避免其他条目分配到过时的值上
|
||||
this.occupiedIdSet.set(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +124,18 @@ public class IdAllocator {
|
||||
return CompletableFuture.completedFuture(id);
|
||||
}
|
||||
|
||||
public List<Pair<String, Integer>> getFixedIdsBetween(int minId, int maxId) {
|
||||
BiMap<Integer, String> inverse = this.forcedIdMap.inverse();
|
||||
List<Pair<String, Integer>> result = new ArrayList<>();
|
||||
for (int i = minId; i <= maxId; i++) {
|
||||
String s = inverse.get(i);
|
||||
if (s != null) {
|
||||
result.add(Pair.of(s, i));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求自动分配ID
|
||||
* @param name 名称
|
||||
@@ -205,8 +221,6 @@ public class IdAllocator {
|
||||
* 保存缓存到文件
|
||||
*/
|
||||
public void saveToCache() throws IOException {
|
||||
FileUtils.createDirectoriesSafe(this.cacheFilePath.getParent());
|
||||
|
||||
// 创建按ID排序的TreeMap
|
||||
Map<Integer, String> sortedById = new TreeMap<>();
|
||||
for (Map.Entry<String, Integer> entry : this.cachedIdMap.entrySet()) {
|
||||
@@ -219,7 +233,14 @@ public class IdAllocator {
|
||||
sortedJsonObject.addProperty(entry.getValue(), entry.getKey());
|
||||
}
|
||||
|
||||
GsonHelper.writeJsonFile(sortedJsonObject, this.cacheFilePath);
|
||||
if (sortedJsonObject.isEmpty()) {
|
||||
if (Files.exists(this.cacheFilePath)) {
|
||||
Files.delete(this.cacheFilePath);
|
||||
}
|
||||
} else {
|
||||
FileUtils.createDirectoriesSafe(this.cacheFilePath.getParent());
|
||||
GsonHelper.writeJsonFile(sortedJsonObject, this.cacheFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IdConflictException extends RuntimeException {
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.registry;
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -89,7 +90,7 @@ public interface Holder<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public @NotNull String toString() {
|
||||
return "Direct{" + this.value + "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,13 @@ public final class ResourceConfigUtils {
|
||||
return raw != null ? function.apply(raw) : defaultValue;
|
||||
}
|
||||
|
||||
public static String getAsString(@Nullable Object raw) {
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
return raw.toString();
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>> E getAsEnum(Object o, Class<E> clazz, E defaultValue) {
|
||||
if (o == null) {
|
||||
return defaultValue;
|
||||
|
||||
@@ -76,7 +76,7 @@ public final class DefaultSectionSerializer {
|
||||
Holder<CustomBlock> owner = BuiltInRegistries.BLOCK.get(key).orElseGet(() -> {
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).registerForHolder(
|
||||
ResourceKey.create(BuiltInRegistries.BLOCK.key().location(), key));
|
||||
InactiveCustomBlock inactiveBlock = new InactiveCustomBlock(key, holder);
|
||||
InactiveCustomBlock inactiveBlock = new InactiveCustomBlock(holder);
|
||||
holder.bindValue(inactiveBlock);
|
||||
return holder;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user