diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 413fc8cb3..48d1fa1b1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -6,15 +6,9 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BlockGenerator; import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; -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.MBuiltInRegistries; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.*; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; -import net.momirealms.craftengine.bukkit.util.BlockStateUtils; -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.bukkit.util.*; import net.momirealms.craftengine.core.block.*; import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; import net.momirealms.craftengine.core.block.behavior.BlockBehaviors; @@ -59,6 +53,8 @@ public final class BukkitBlockManager extends AbstractBlockManager { private final Set replacedBlockSounds = new HashSet<>(); // 用于缓存string形式的方块状态到原版方块状态 private final Map blockStateCache = new HashMap<>(1024); + // 用于临时存储可燃烧自定义方块的列表 + private final List burnableBlocks = new ArrayList<>(); public BukkitBlockManager(BukkitCraftEngine plugin) { super(plugin, RegistryUtils.currentBlockRegistrySize(), Config.serverSideBlocks()); @@ -95,6 +91,11 @@ public final class BukkitBlockManager extends AbstractBlockManager { Arrays.fill(this.blockStateMappings, -1); this.previousClientBoundTags = this.clientBoundTags; this.clientBoundTags = new HashMap<>(); + for (DelegatingBlock block : this.burnableBlocks) { + this.igniteOdds.remove(block); + this.burnOdds.remove(block); + } + this.burnableBlocks.clear(); if (EmptyBlock.STATE != null) Arrays.fill(this.immutableBlockStates, EmptyBlock.STATE); for (DelegatingBlock block : this.customBlocks) { @@ -252,6 +253,82 @@ public final class BukkitBlockManager extends AbstractBlockManager { } } + @Override + protected void applyPlatformSettings(ImmutableBlockState state) { + DelegatingBlockState nmsState = (DelegatingBlockState) state.customBlockState().literalObject(); + nmsState.setBlockState(state); + Object nmsVisualState = state.vanillaBlockState().literalObject(); + + BlockSettings settings = state.settings(); + try { + CoreReflections.field$BlockStateBase$lightEmission.set(nmsState, settings.luminance()); + CoreReflections.field$BlockStateBase$burnable.set(nmsState, settings.burnable()); + CoreReflections.field$BlockStateBase$hardness.set(nmsState, settings.hardness()); + CoreReflections.field$BlockStateBase$replaceable.set(nmsState, settings.replaceable()); + Object mcMapColor = CoreReflections.method$MapColor$byId.invoke(null, settings.mapColor().id); + CoreReflections.field$BlockStateBase$mapColor.set(nmsState, mcMapColor); + CoreReflections.field$BlockStateBase$instrument.set(nmsState, CoreReflections.instance$NoteBlockInstrument$values[settings.instrument().ordinal()]); + CoreReflections.field$BlockStateBase$pushReaction.set(nmsState, CoreReflections.instance$PushReaction$values[settings.pushReaction().ordinal()]); + boolean canOcclude = settings.canOcclude() == Tristate.UNDEFINED ? BlockStateUtils.isOcclude(nmsVisualState) : settings.canOcclude().asBoolean(); + CoreReflections.field$BlockStateBase$canOcclude.set(nmsState, canOcclude); + boolean useShapeForLightOcclusion = settings.useShapeForLightOcclusion() == Tristate.UNDEFINED ? CoreReflections.field$BlockStateBase$useShapeForLightOcclusion.getBoolean(nmsVisualState) : settings.useShapeForLightOcclusion().asBoolean(); + CoreReflections.field$BlockStateBase$useShapeForLightOcclusion.set(nmsState, useShapeForLightOcclusion); + CoreReflections.field$BlockStateBase$isRedstoneConductor.set(nmsState, settings.isRedstoneConductor().asBoolean() ? ALWAYS_TRUE : ALWAYS_FALSE); + CoreReflections.field$BlockStateBase$isSuffocating.set(nmsState, settings.isSuffocating().asBoolean() ? ALWAYS_TRUE : ALWAYS_FALSE); + CoreReflections.field$BlockStateBase$isViewBlocking.set(nmsState, settings.isViewBlocking() == Tristate.UNDEFINED ? settings.isSuffocating().asBoolean() ? ALWAYS_TRUE : ALWAYS_FALSE : (settings.isViewBlocking().asBoolean() ? ALWAYS_TRUE : ALWAYS_FALSE)); + + DelegatingBlock nmsBlock = (DelegatingBlock) BlockStateUtils.getBlockOwner(nmsState); + ObjectHolder shapeHolder = nmsBlock.shapeDelegate(); + shapeHolder.bindValue(new BukkitBlockShape(nmsVisualState, Optional.ofNullable(state.settings().supportShapeBlockState()).map(it -> Objects.requireNonNull(createVanillaBlockState(it), "Illegal block state: " + it).literalObject()).orElse(null))); + ObjectHolder behaviorHolder = nmsBlock.behaviorDelegate(); + behaviorHolder.bindValue(state.behavior()); + + CoreReflections.field$BlockBehaviour$explosionResistance.set(nmsBlock, settings.resistance()); + CoreReflections.field$BlockBehaviour$friction.set(nmsBlock, settings.friction()); + CoreReflections.field$BlockBehaviour$speedFactor.set(nmsBlock, settings.speedFactor()); + CoreReflections.field$BlockBehaviour$jumpFactor.set(nmsBlock, settings.jumpFactor()); + CoreReflections.field$BlockBehaviour$soundType.set(nmsBlock, SoundUtils.toSoundType(settings.sounds())); + + CoreReflections.method$BlockStateBase$initCache.invoke(nmsState); + boolean isConditionallyFullOpaque = canOcclude & useShapeForLightOcclusion; + if (!VersionHelper.isOrAbove1_21_2()) { + CoreReflections.field$BlockStateBase$isConditionallyFullOpaque.set(nmsState, isConditionallyFullOpaque); + } + + if (VersionHelper.isOrAbove1_21_2()) { + int blockLight = settings.blockLight() != -1 ? settings.blockLight() : CoreReflections.field$BlockStateBase$lightBlock.getInt(nmsVisualState); + CoreReflections.field$BlockStateBase$lightBlock.set(nmsState, blockLight); + boolean propagatesSkylightDown = settings.propagatesSkylightDown() == Tristate.UNDEFINED ? CoreReflections.field$BlockStateBase$propagatesSkylightDown.getBoolean(nmsVisualState) : settings.propagatesSkylightDown().asBoolean(); + CoreReflections.field$BlockStateBase$propagatesSkylightDown.set(nmsState, propagatesSkylightDown); + } else { + Object cache = CoreReflections.field$BlockStateBase$cache.get(nmsState); + int blockLight = settings.blockLight() != -1 ? settings.blockLight() : CoreReflections.field$BlockStateBase$Cache$lightBlock.getInt(CoreReflections.field$BlockStateBase$cache.get(nmsVisualState)); + CoreReflections.field$BlockStateBase$Cache$lightBlock.set(cache, blockLight); + boolean propagatesSkylightDown = settings.propagatesSkylightDown() == Tristate.UNDEFINED ? CoreReflections.field$BlockStateBase$Cache$propagatesSkylightDown.getBoolean(CoreReflections.field$BlockStateBase$cache.get(nmsVisualState)) : settings.propagatesSkylightDown().asBoolean(); + CoreReflections.field$BlockStateBase$Cache$propagatesSkylightDown.set(cache, propagatesSkylightDown); + if (!isConditionallyFullOpaque) { + CoreReflections.field$BlockStateBase$opacityIfCached.set(nmsState, blockLight); + } + } + + CoreReflections.field$BlockStateBase$fluidState.set(nmsState, settings.fluidState() ? MFluids.WATER$defaultState : MFluids.EMPTY$defaultState); + CoreReflections.field$BlockStateBase$isRandomlyTicking.set(nmsState, settings.isRandomlyTicking()); + Object holder = BukkitCraftEngine.instance().blockManager().getMinecraftBlockHolder(state.customBlockState().registryId()); + Set tags = new HashSet<>(); + for (Key tag : settings.tags()) { + tags.add(CoreReflections.method$TagKey$create.invoke(null, MRegistries.BLOCK, KeyUtils.toResourceLocation(tag))); + } + CoreReflections.field$Holder$Reference$tags.set(holder, tags); + if (settings.burnable()) { + this.igniteOdds.put(nmsBlock, settings.burnChance()); + this.burnOdds.put(nmsBlock, settings.fireSpreadChance()); + this.burnableBlocks.add(nmsBlock); + } + } catch (ReflectiveOperationException e) { + this.plugin.logger().warn("Failed to apply platform block settings for block state " + state, e); + } + } + private BlockSounds toBlockSounds(Object soundType) throws ReflectiveOperationException { return new BlockSounds( toSoundData(CoreReflections.field$SoundType$breakSound.get(soundType), SoundData.SoundValue.FIXED_1, SoundData.SoundValue.FIXED_0_8), diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index 0bbb93176..0d4bdd343 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -1235,6 +1235,16 @@ public final class CoreReflections { ReflectionUtils.getMethod(clazz$PushReaction, new String[] { "values" }) ); + public static final Object[] instance$PushReaction$values; + + static { + try { + instance$PushReaction$values = (Object[]) method$PushReaction$values.invoke(null); + } catch (ReflectiveOperationException e) { + throw new ReflectionInitException("Failed to init PushReaction", e); + } + } + public static final Class clazz$NoteBlockInstrument = requireNonNull( BukkitReflectionUtils.findReobfOrMojmapClass( "world.level.block.state.properties.BlockPropertyInstrument", @@ -1246,6 +1256,16 @@ public final class CoreReflections { ReflectionUtils.getMethod(clazz$NoteBlockInstrument, new String[] { "values" }) ); + public static final Object[] instance$NoteBlockInstrument$values; + + static { + try { + instance$NoteBlockInstrument$values = (Object[]) method$NoteBlockInstrument$values.invoke(null); + } catch (ReflectiveOperationException e) { + throw new ReflectionInitException("Failed to init NoteBlockInstrument", e); + } + } + public static final Class clazz$BlockStateBase = requireNonNull( BukkitReflectionUtils.findReobfOrMojmapClass( "world.level.block.state.BlockBase$BlockData", diff --git a/common-files/src/main/resources/translations/de.yml b/common-files/src/main/resources/translations/de.yml index 1513a684b..a02740112 100644 --- a/common-files/src/main/resources/translations/de.yml +++ b/common-files/src/main/resources/translations/de.yml @@ -255,7 +255,6 @@ warning.config.block.state.property.invalid_format: "Problem in Datei Problem in Datei gefunden - Beim Block '' fehlt das erforderliche 'state'-Argument für 'state'." warning.config.block.state.missing_properties: "Problem in Datei gefunden - Beim Block '' fehlt der erforderliche 'properties'-Abschnitt für 'states'." warning.config.block.state.missing_appearances: "Problem in Datei gefunden - Beim Block '' fehlt der erforderliche 'appearances'-Abschnitt für 'states'." -warning.config.block.state.missing_variants: "Problem in Datei gefunden - Beim Block '' fehlt der erforderliche 'variants'-Abschnitt für 'states'." warning.config.block.state.variant.invalid_appearance: "Problem in Datei gefunden - Der Block '' hat einen Fehler, dass die Variante '' eine nicht existierende Appearance '' verwendet." warning.config.block.state.invalid_vanilla: "Problem in Datei gefunden - Der Block '' verwendet einen ungültigen Vanilla-Block-State ''." warning.config.block.state.unavailable_vanilla: "Problem in Datei gefunden - Der Block '' verwendet einen nicht verfügbaren Vanilla-Block-State ''. Bitte gib diesen State in der mappings.yml frei." diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index 652e823a8..e15c5f89d 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -267,7 +267,6 @@ warning.config.block.state.property.invalid_format: "Issue found in file warning.config.block.state.missing_state: "Issue found in file - The block '' is missing the required 'state' argument for 'state'." warning.config.block.state.missing_properties: "Issue found in file - The block '' is missing the required 'properties' section for 'states'." warning.config.block.state.missing_appearances: "Issue found in file - The block '' is missing the required 'appearances' section for 'states'." -warning.config.block.state.missing_variants: "Issue found in file - The block '' is missing the required 'variants' section for 'states'." warning.config.block.state.entity_renderer.invalid_type: "Issue found in file - The block '' is using an invalid entity renderer type ''." warning.config.block.state.entity_renderer.item_display.missing_item: "Issue found in file - The block '' is missing the required 'item' argument for 'item_display' entity renderer." warning.config.block.state.entity_renderer.text_display.missing_text: "Issue found in file - The block '' is missing the required 'text' argument for 'text_display' entity renderer." diff --git a/common-files/src/main/resources/translations/es.yml b/common-files/src/main/resources/translations/es.yml index d65bc899a..eaa30b979 100644 --- a/common-files/src/main/resources/translations/es.yml +++ b/common-files/src/main/resources/translations/es.yml @@ -178,7 +178,6 @@ warning.config.block.state.property.invalid_format: "Problema encontrado warning.config.block.state.missing_state: "Problema encontrado en el archivo - El bloque '' carece del argumento requerido 'state' para 'state'." warning.config.block.state.missing_properties: "Problema encontrado en el archivo - El bloque '' carece de la sección requerida 'properties' para 'states'." warning.config.block.state.missing_appearances: "Problema encontrado en el archivo - El bloque '' carece de la sección requerida 'appearances' para 'states'." -warning.config.block.state.missing_variants: "Problema encontrado en el archivo - El bloque '' carece de la sección requerida 'variants' para 'states'." warning.config.block.state.variant.invalid_appearance: "Problema encontrado en el archivo - Hay un error en el bloque '' donde la variante '' está usando una apariencia inexistente ''." warning.config.block.state.invalid_vanilla: "Problema encontrado en el archivo - El bloque '' está usando un estado de bloque vanilla inválido ''." warning.config.block.state.unavailable_vanilla: "Problema encontrado en el archivo - El bloque '' está usando un estado de bloque vanilla no disponible ''. Por favor libera este estado en el archivo mappings.yml." diff --git a/common-files/src/main/resources/translations/ru_ru.yml b/common-files/src/main/resources/translations/ru_ru.yml index be8170d1a..e3d30278c 100644 --- a/common-files/src/main/resources/translations/ru_ru.yml +++ b/common-files/src/main/resources/translations/ru_ru.yml @@ -228,7 +228,6 @@ warning.config.block.state.property.invalid_format: "Проблема н warning.config.block.state.missing_state: "Проблема найдена в файле - В блоке '' отсутствует необходимый 'state' аргумент для 'state'." warning.config.block.state.missing_properties: "Проблема найдена в файле - В блоке '' отсутствует необходимый 'properties' раздел для 'states'." warning.config.block.state.missing_appearances: "Проблема найдена в файле - В блоке '' отсутствует необходимый 'appearances' раздел для 'states'." -warning.config.block.state.missing_variants: "Проблема найдена в файле - В блоке '' отсутствует необходимый 'variants' раздел для 'states'." warning.config.block.state.variant.invalid_appearance: "Проблема найдена в файле - Блок '' имеет ошибку, что вариант '' использует несуществующий внешний вид ''." warning.config.block.state.invalid_vanilla: "Проблема найдена в файле - Блок '' имеет недействительное состояние ванильного блока ''." warning.config.block.state.unavailable_vanilla: "Проблема найдена в файле - Блок '' использует недоступное состояние ванильного блока ''. Пожалуйста, освободите это состояние в mappings.yml." diff --git a/common-files/src/main/resources/translations/tr.yml b/common-files/src/main/resources/translations/tr.yml index d283b67c1..b62967f92 100644 --- a/common-files/src/main/resources/translations/tr.yml +++ b/common-files/src/main/resources/translations/tr.yml @@ -176,7 +176,6 @@ warning.config.block.state.property.invalid_format: " dosyasında warning.config.block.state.missing_state: " dosyasında sorun bulundu - '' bloğu, 'state' için gerekli 'state' argümanı eksik." warning.config.block.state.missing_properties: " dosyasında sorun bulundu - '' bloğu, 'states' için gerekli 'properties' bölümü eksik." warning.config.block.state.missing_appearances: " dosyasında sorun bulundu - '' bloğu, 'states' için gerekli 'appearances' bölümü eksik." -warning.config.block.state.missing_variants: " dosyasında sorun bulundu - '' bloğu, 'states' için gerekli 'variants' bölümü eksik." warning.config.block.state.variant.invalid_appearance: " dosyasında sorun bulundu - '' bloğunda, '' varyantının var olmayan bir görünüm '' kullandığı bir hata var." warning.config.block.state.invalid_vanilla: " dosyasında sorun bulundu - '' bloğu geçersiz bir vanilya blok durumu '' kullanıyor." warning.config.block.state.unavailable_vanilla: " dosyasında sorun bulundu - '' bloğu kullanılamayan bir vanilya blok durumu '' kullanıyor. Lütfen bu durumu mappings.yml dosyasında serbest bırakın." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 04bea5c58..9d0175d00 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -263,7 +263,6 @@ warning.config.block.state.property.invalid_format: "在文件 warning.config.block.state.missing_state: "在文件 发现问题 - 方块 '' 的 'state' 缺少必需的 'state' 参数" warning.config.block.state.missing_properties: "在文件 发现问题 - 方块 '' 的 'states' 缺少必需的 'properties' 段落" warning.config.block.state.missing_appearances: "在文件 发现问题 - 方块 '' 的 'states' 缺少必需的 'appearances' 段落" -warning.config.block.state.missing_variants: "在文件 发现问题 - 方块 '' 的 'states' 缺少必需的 'variants' 段落" warning.config.block.state.variant.invalid_appearance: "在文件 发现问题 - 方块 '' 的变体 '' 使用了不存在的 appearance ''" warning.config.block.state.invalid_vanilla: "在文件 发现问题 - 方块 '' 使用了无效的原版方块状态 ''" warning.config.block.state.unavailable_vanilla: "在文件 发现问题 - 方块 '' 使用了不可用的原版方块状态 '' 请在 mappings.yml 中释放该状态" diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java index bd39b0a59..c1a8fd25a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java @@ -6,7 +6,6 @@ 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; @@ -14,7 +13,6 @@ import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityEl 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; @@ -49,7 +47,6 @@ 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 { protected final BlockParser blockParser; @@ -150,7 +147,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem return Optional.ofNullable(this.byId.get(id)); } - protected void addBlockInternal(CustomBlock customBlock) { + protected void addCustomBlock(CustomBlock customBlock) { // 绑定外观状态等 for (ImmutableBlockState state : customBlock.variantProvider().states()) { int internalId = state.customBlockState().registryId(); @@ -159,6 +156,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem this.immutableBlockStates[index] = state; this.blockStateMappings[internalId] = appearanceId; this.appearanceToRealState.computeIfAbsent(appearanceId, k -> new IntArrayList()).add(internalId); + this.applyPlatformSettings(state); // generate mod assets if (Config.generateModAssets()) { this.modBlockStateOverrides.put(getBlockOwnerId(state.customBlockState()), this.tempVanillaBlockStateModels.get(appearanceId)); @@ -167,6 +165,8 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem this.byId.put(customBlock.id(), customBlock); } + protected abstract void applyPlatformSettings(ImmutableBlockState state); + @Override public ConfigParser[] parsers() { return new ConfigParser[]{this.blockParser, this.blockStateMappingParser}; @@ -546,7 +546,7 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem } // 添加方块 - addBlockInternal(customBlock); + addCustomBlock(customBlock); }, () -> GsonHelper.get().toJson(section))); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java b/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java index 1868cd5fe..71368dae1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java @@ -8,9 +8,9 @@ public final class LoadingSequence { public static final int GLOBAL_VAR = 10; public static final int LANG = 20; public static final int TRANSLATION = 30; - public static final int BLOCK = 40; - public static final int EQUIPMENT = 50; - public static final int ITEM = 60; + public static final int EQUIPMENT = 40; + public static final int ITEM = 50; + public static final int BLOCK = 60; public static final int FURNITURE = 70; public static final int IMAGE = 80; public static final int RECIPE = 90;