Fix SNBT writing

This commit is contained in:
Zoë Gidiere
2025-10-05 20:23:54 -06:00
parent a80b94ad45
commit 48586eb523
5 changed files with 131 additions and 13 deletions

View File

@@ -20,13 +20,16 @@ package com.dfsek.terra.mod.handle;
import com.dfsek.terra.api.block.state.BlockStateExtended;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.command.argument.BlockArgumentParser;
import net.minecraft.command.argument.BlockArgumentParser.BlockResult;
import net.minecraft.command.argument.BlockStateArgument;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,6 +54,15 @@ public class MinecraftWorldHandle implements WorldHandle {
if (blockResult.nbt() != null) {
net.minecraft.block.BlockState state = blockResult.blockState();
NbtCompound nbtCompound = blockResult.nbt();
if (state.hasBlockEntity()) {
BlockEntity blockEntity = ((BlockEntityProvider) state.getBlock()).createBlockEntity(new BlockPos(0, 0, 0), state);
nbtCompound.putInt("x", 0);
nbtCompound.putInt("y", 0);
nbtCompound.putInt("z", 0);
nbtCompound.put("id", BlockEntity.TYPE_CODEC, blockEntity.getType());
}
blockState = (BlockStateExtended) new BlockStateArgument(state, blockResult.properties().keySet(), nbtCompound);
} else {
blockState = (BlockState) blockResult.blockState();

View File

@@ -18,20 +18,30 @@
package com.dfsek.terra.mod.mixin.implementations.terra.chunk;
import com.dfsek.seismic.math.coord.CoordFunctions;
import com.dfsek.terra.api.block.state.BlockStateExtended;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.render.DimensionEffects.End;
import net.minecraft.command.argument.BlockStateArgument;
import net.minecraft.fluid.Fluid;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.WorldProperties;
import net.minecraft.world.biome.source.BiomeAccess;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.feature.EndGatewayFeature;
import net.minecraft.world.tick.MultiTickScheduler;
import net.minecraft.world.tick.OrderedTick;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
@@ -44,7 +54,7 @@ import com.dfsek.terra.api.world.chunk.Chunk;
@Mixin(ChunkRegion.class)
@Implements(@Interface(iface = Chunk.class, prefix = "terraChunk$"))
public abstract class ChunkRegionMixin {
public abstract class ChunkRegionMixin implements StructureWorldAccess {
@Shadow
@Final
@@ -62,14 +72,41 @@ public abstract class ChunkRegionMixin {
@Final
private MultiTickScheduler<Fluid> fluidTickScheduler;
@Shadow
public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos);
@Shadow
@Nullable
public abstract boolean setBlockState(BlockPos pos, net.minecraft.block.BlockState state, int flags, int maxUpdateDepth);
public void terraChunk$setBlock(int x, int y, int z, @NotNull BlockState data, boolean physics) {
ChunkPos pos = centerPos.getPos();
BlockPos blockPos = new BlockPos(CoordFunctions.chunkAndRelativeToAbsolute(pos.x, x), y, CoordFunctions.chunkAndRelativeToAbsolute(pos.z, z));
boolean isExtended = data.isExtended() && data.getClass().equals(BlockStateArgument.class);
if (isExtended) {
((BlockStateArgument) data).setBlockState(world, blockPos, 0);
BlockStateArgument arg = ((BlockStateArgument) data);
net.minecraft.block.BlockState state = arg.getBlockState();
setBlockState(blockPos, state, 0, 512);
net.minecraft.world.chunk.Chunk chunk = getChunk(blockPos);
BlockEntity blockEntity;
NbtCompound nbt = ((NbtCompound) (Object) ((BlockStateExtended)data).getData());
if ("DUMMY".equals(nbt.getString("id", ""))) {
if (state.hasBlockEntity()) {
blockEntity = ((BlockEntityProvider)state.getBlock()).createBlockEntity(blockPos, state);
} else {
blockEntity = null;
}
} else {
blockEntity = BlockEntity.createFromNbt(blockPos, state, nbt, this.world.getRegistryManager());
}
if (blockEntity != null) {
blockEntity.setWorld(this.world);
chunk.setBlockEntity(blockEntity);
}
} else {
((ChunkRegion) (Object) this).setBlockState(blockPos, (net.minecraft.block.BlockState) data, 0);
setBlockState(blockPos, (net.minecraft.block.BlockState) data, 0, 512);
}
if(physics) {

View File

@@ -17,6 +17,9 @@
package com.dfsek.terra.mod.mixin.implementations.terra.chunk;
import com.dfsek.terra.api.block.state.BlockStateExtended;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.command.argument.BlockStateArgument;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.command.SetBlockCommand;
@@ -52,12 +55,18 @@ public abstract class WorldChunkMixin {
@Nullable
public abstract net.minecraft.block.BlockState setBlockState(BlockPos pos, net.minecraft.block.BlockState state, int flags);
@Shadow
protected abstract BlockEntity loadBlockEntity(BlockPos pos, NbtCompound nbt);
@SuppressWarnings("ConstantValue")
public void terra$setBlock(int x, int y, int z, BlockState data, boolean physics) {
BlockPos blockPos = new BlockPos(x, y, z);
boolean isExtended = data.isExtended() && data.getClass().equals(BlockStateArgument.class);
if (isExtended) {
((BlockStateArgument) data).setBlockState((net.minecraft.server.world.ServerWorld) world, blockPos, 0);
BlockStateArgument arg = ((BlockStateArgument) data);
net.minecraft.block.BlockState state = arg.getBlockState();
setBlockState(blockPos, state, 0);
loadBlockEntity(blockPos, ((NbtCompound) (Object) ((BlockStateExtended)data).getData()));
} else {
setBlockState(blockPos, (net.minecraft.block.BlockState) data, 0);
}

View File

@@ -17,14 +17,19 @@
package com.dfsek.terra.mod.mixin.implementations.terra.world;
import com.dfsek.terra.api.block.state.BlockStateExtended;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.FluidBlock;
import net.minecraft.command.argument.BlockStateArgument;
import net.minecraft.entity.SpawnReason;
import net.minecraft.fluid.Fluid;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.collection.BoundedRegionArray;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkGenerationStep;
@@ -56,7 +61,7 @@ import com.dfsek.terra.mod.util.MinecraftUtil;
@Mixin(ChunkRegion.class)
@Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$"))
public abstract class ChunkRegionMixin {
public abstract class ChunkRegionMixin implements StructureWorldAccess {
private ConfigPack terra$config;
@@ -95,17 +100,36 @@ public abstract class ChunkRegionMixin {
int flags = physics ? 3 : 1042;
boolean isExtended = data.isExtended() && data.getClass().equals(BlockStateArgument.class);
if (isExtended) {
((BlockStateArgument) data).setBlockState(world, blockPos, flags);
BlockStateArgument arg = ((BlockStateArgument) data);
net.minecraft.block.BlockState state = arg.getBlockState();
setBlockState(blockPos, state, flags);
net.minecraft.world.chunk.Chunk chunk = getChunk(blockPos);
net.minecraft.block.entity.BlockEntity blockEntity;
NbtCompound nbt = ((NbtCompound) (Object) ((BlockStateExtended)data).getData());
if ("DUMMY".equals(nbt.getString("id", ""))) {
if (state.hasBlockEntity()) {
blockEntity = ((BlockEntityProvider)state.getBlock()).createBlockEntity(blockPos, state);
} else {
blockEntity = null;
}
} else {
blockEntity = net.minecraft.block.entity.BlockEntity.createFromNbt(blockPos, state, nbt, getRegistryManager());
}
if (blockEntity != null) {
blockEntity.setWorld(world);
chunk.setBlockEntity(blockEntity);
}
} else {
((ChunkRegion) (Object) this).setBlockState(blockPos, (net.minecraft.block.BlockState) data, flags);
setBlockState(blockPos, (net.minecraft.block.BlockState) data, flags);
}
if(physics) {
net.minecraft.block.BlockState state = isExtended ? ((BlockStateArgument) data).getBlockState() : ((net.minecraft.block.BlockState) data);
if(state.isLiquid()) {
fluidTickScheduler.scheduleTick(OrderedTick.create(state.getFluidState().getFluid(), blockPos));
getFluidTickScheduler().scheduleTick(OrderedTick.create(state.getFluidState().getFluid(), blockPos));
} else {
blockTickScheduler.scheduleTick(OrderedTick.create(state.getBlock(), blockPos));
getBlockTickScheduler().scheduleTick(OrderedTick.create(state.getBlock(), blockPos));
}
}
}

View File

@@ -17,16 +17,25 @@
package com.dfsek.terra.mod.mixin.implementations.terra.world;
import com.dfsek.terra.api.block.state.BlockStateExtended;
import com.dfsek.terra.mod.mixin.invoke.FluidBlockInvoker;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.FluidBlock;
import net.minecraft.command.argument.BlockStateArgument;
import net.minecraft.entity.SpawnReason;
import net.minecraft.fluid.Fluid;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.MutableWorldProperties;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.tick.MultiTickScheduler;
import net.minecraft.world.tick.OrderedTick;
import net.minecraft.world.tick.WorldTickScheduler;
@@ -54,17 +63,24 @@ import org.spongepowered.asm.mixin.Shadow;
@Mixin(net.minecraft.server.world.ServerWorld.class)
@Implements(@Interface(iface = ServerWorld.class, prefix = "terra$"))
public abstract class ServerWorldMixin {
public abstract class ServerWorldMixin extends World {
protected ServerWorldMixin(MutableWorldProperties properties, RegistryKey<World> registryRef, DynamicRegistryManager registryManager,
RegistryEntry<DimensionType> dimensionEntry, boolean isClient, boolean debugWorld, long seed,
int maxChainedNeighborUpdates) {
super(properties, registryRef, registryManager, dimensionEntry, isClient, debugWorld, seed, maxChainedNeighborUpdates);
}
@Shadow
public abstract WorldTickScheduler<Block> getBlockTickScheduler();
@Shadow
public abstract WorldTickScheduler<Fluid> getFluidTickScheduler();
public Entity terra$spawnEntity(double x, double y, double z, EntityType entityType) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(null, SpawnReason.CHUNK_GENERATION);
entity.setPos(x, y, z);
((net.minecraft.server.world.ServerWorld) (Object) this).spawnEntity(entity);
spawnEntity(entity);
return (Entity) entity;
}
@@ -73,10 +89,30 @@ public abstract class ServerWorldMixin {
int flags = physics ? 3 : 1042;
boolean isExtended = data.isExtended() && data.getClass().equals(BlockStateArgument.class);
if (isExtended) {
((BlockStateArgument) data).setBlockState(((net.minecraft.server.world.ServerWorld) (Object) this), blockPos, flags);
BlockStateArgument arg = ((BlockStateArgument) data);
net.minecraft.block.BlockState state = arg.getBlockState();
setBlockState(blockPos, state, flags);
net.minecraft.world.chunk.Chunk chunk = getChunk(blockPos);
net.minecraft.block.entity.BlockEntity blockEntity;
NbtCompound nbt = ((NbtCompound) (Object) ((BlockStateExtended)data).getData());
if ("DUMMY".equals(nbt.getString("id", ""))) {
if (state.hasBlockEntity()) {
blockEntity = ((BlockEntityProvider)state.getBlock()).createBlockEntity(blockPos, state);
} else {
blockEntity = null;
}
} else {
blockEntity = net.minecraft.block.entity.BlockEntity.createFromNbt(blockPos, state, nbt, getRegistryManager());
}
if (blockEntity != null) {
blockEntity.setWorld(this);
chunk.setBlockEntity(blockEntity);
}
} else {
((net.minecraft.server.world.ServerWorld) (Object) this).setBlockState(blockPos, (net.minecraft.block.BlockState) data, flags);
setBlockState(blockPos, (net.minecraft.block.BlockState) data, flags);
}
if(physics) {
net.minecraft.block.BlockState state = isExtended ? ((BlockStateArgument) data).getBlockState() : ((net.minecraft.block.BlockState) data);
if(state.isLiquid()) {