diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/BlockData.java b/common/api/src/main/java/com/dfsek/terra/api/block/BlockData.java deleted file mode 100644 index c8c7e6f5d..000000000 --- a/common/api/src/main/java/com/dfsek/terra/api/block/BlockData.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.api.block; - -import com.dfsek.terra.api.Handle; - - -public interface BlockData extends Handle { - String toString(); -} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockState.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockState.java index 440a29669..47086f49b 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockState.java +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockState.java @@ -12,12 +12,13 @@ import java.util.function.Consumer; import com.dfsek.terra.api.Handle; import com.dfsek.terra.api.block.BlockType; import com.dfsek.terra.api.block.state.properties.Property; +import com.dfsek.terra.api.data.Extendable; /** * Contains basic data about a {@link BlockType} in the world */ -public interface BlockState extends Handle { +public interface BlockState extends Handle, Extendable { /** * Whether this {@link BlockState} matches another. @@ -115,12 +116,4 @@ public interface BlockState extends Handle { * @return Whether this state is air */ boolean isAir(); - - /** - * Get whether this BlockState is an extended state. - * Extended states are states that contain extra data not normally present in a BlockState. - * - * @return Whether this state is extended. - */ - default boolean isExtended() { return false; } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockStateExtended.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockStateExtended.java index 72faaf9a7..1e0617119 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockStateExtended.java +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockStateExtended.java @@ -1,6 +1,6 @@ package com.dfsek.terra.api.block.state; -import com.dfsek.terra.api.block.BlockData; +import com.dfsek.terra.api.data.ExtendedData; public interface BlockStateExtended extends BlockState { @@ -9,7 +9,7 @@ public interface BlockStateExtended extends BlockState { * * @return BlockData of this BlockStateExtended */ - BlockData getData(); + ExtendedData getData(); /** * Sets the BlockData. @@ -18,7 +18,7 @@ public interface BlockStateExtended extends BlockState { * * @return New BlockStateExtended with the given BlockData */ - BlockStateExtended setData(BlockData data); + BlockStateExtended setData(ExtendedData data); /** * Gets the BlockState. diff --git a/common/api/src/main/java/com/dfsek/terra/api/data/Extendable.java b/common/api/src/main/java/com/dfsek/terra/api/data/Extendable.java new file mode 100644 index 000000000..76303b505 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/data/Extendable.java @@ -0,0 +1,11 @@ +package com.dfsek.terra.api.data; + +public interface Extendable { + /** + * Get whether this BlockState is an extended state. + * Extended states are states that contain extra data not normally present in a BlockState. + * + * @return Whether this state is extended. + */ + default boolean isExtended() { return false; } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/data/ExtendedData.java b/common/api/src/main/java/com/dfsek/terra/api/data/ExtendedData.java new file mode 100644 index 000000000..2ec67162c --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/data/ExtendedData.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.data; + +import com.dfsek.terra.api.Handle; + + +public interface ExtendedData extends Handle { + String toString(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/entity/EntityType.java b/common/api/src/main/java/com/dfsek/terra/api/entity/EntityType.java index 7196edccf..aa5b3a9eb 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/entity/EntityType.java +++ b/common/api/src/main/java/com/dfsek/terra/api/entity/EntityType.java @@ -8,7 +8,8 @@ package com.dfsek.terra.api.entity; import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.data.Extendable; -public interface EntityType extends Handle { +public interface EntityType extends Handle, Extendable { } diff --git a/common/api/src/main/java/com/dfsek/terra/api/entity/EntityTypeExtended.java b/common/api/src/main/java/com/dfsek/terra/api/entity/EntityTypeExtended.java new file mode 100644 index 000000000..5fdec1b42 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/entity/EntityTypeExtended.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.api.entity; + +import com.dfsek.terra.api.data.ExtendedData; + + +public interface EntityTypeExtended extends EntityType { + /** + * Gets the BlockData. + * + * @return BlockData of this EntityTypeExtended + */ + ExtendedData getData(); + + /** + * Sets the BlockData. + * + * @param data BlockData to set + * + * @return New EntityTypeExtended with the given BlockData + */ + EntityTypeExtended setData(ExtendedData data); + + /** + * Gets the EntityType. + * + * @return Raw EntityType of this EntityTypeExtended + */ + EntityType getType(); + + @Override + default boolean isExtended() { return true; } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java index 3ed61d67b..605a64dbb 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java @@ -17,6 +17,7 @@ package com.dfsek.terra.mod.handle; +import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.BlockEntityProvider; import net.minecraft.block.Blocks; @@ -25,7 +26,11 @@ 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.nbt.StringNbtReader; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntry.Reference; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; @@ -36,6 +41,9 @@ import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockStateExtended; import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.mod.implmentation.FabricEntityTypeExtended; + +import static net.minecraft.command.argument.BlockArgumentParser.INVALID_BLOCK_ID_EXCEPTION; public class MinecraftWorldHandle implements WorldHandle { @@ -45,6 +53,7 @@ public class MinecraftWorldHandle implements WorldHandle { private static final Logger logger = LoggerFactory.getLogger(MinecraftWorldHandle.class); + @SuppressWarnings("DataFlowIssue") @Override public @NotNull BlockState createBlockState(@NotNull String data) { try { @@ -61,8 +70,12 @@ public class MinecraftWorldHandle implements WorldHandle { nbtCompound.putInt("z", 0); nbtCompound.put("id", BlockEntity.TYPE_CODEC, blockEntity.getType()); + + blockState = (BlockStateExtended) new BlockStateArgument(state, blockResult.properties().keySet(), nbtCompound); + } else { + blockState = (BlockState) state; } - blockState = (BlockStateExtended) new BlockStateArgument(state, blockResult.properties().keySet(), nbtCompound); + } else { blockState = (BlockState) blockResult.blockState(); } @@ -80,10 +93,39 @@ public class MinecraftWorldHandle implements WorldHandle { } @Override - public @NotNull EntityType getEntity(@NotNull String id) { - if(!id.contains(":")) throw new IllegalArgumentException("Invalid entity identifier " + id); - Identifier identifier = Identifier.tryParse(id); - if(identifier == null) identifier = Identifier.tryParse(id); - return (EntityType) Registries.ENTITY_TYPE.getEntry(identifier).orElseThrow().value(); + public @NotNull EntityType getEntity(@NotNull String data) { + try { + Identifier identifier; + NbtCompound nbtData = null; + StringReader reader = new StringReader(data); + + int i = reader.getCursor(); + + identifier = Identifier.fromCommandInput(reader); + + net.minecraft.entity.EntityType entity = + (net.minecraft.entity.EntityType) ((Reference) Registries.ENTITY_TYPE.getOptional( + RegistryKey.of(RegistryKeys.ENTITY_TYPE, identifier)).orElseThrow(() -> { + reader.setCursor(i); + return INVALID_BLOCK_ID_EXCEPTION.createWithContext(reader, identifier.toString()); + })).value(); + + if(reader.canRead() && reader.peek() == '{') { + nbtData = StringNbtReader.readCompoundAsArgument(reader); + nbtData.putString("id", entity.getRegistryEntry().registryKey().getValue().toString()); + } + + EntityType entityType; + if(nbtData != null) { + entityType = new FabricEntityTypeExtended(entity, nbtData); + } else { + entityType = (EntityType) entity; + } + + if(identifier == null) throw new IllegalArgumentException("Invalid data: " + data); + return entityType; + } catch(CommandSyntaxException e) { + throw new RuntimeException(e); + } } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/implmentation/FabricEntityTypeExtended.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/implmentation/FabricEntityTypeExtended.java new file mode 100644 index 000000000..6500668ab --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/implmentation/FabricEntityTypeExtended.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.mod.implmentation; + +import net.minecraft.nbt.NbtCompound; + +import com.dfsek.terra.api.data.ExtendedData; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.entity.EntityTypeExtended; + + +public record FabricEntityTypeExtended(net.minecraft.entity.EntityType entityType, NbtCompound nbtCompound) + implements EntityTypeExtended { + @SuppressWarnings("DataFlowIssue") + @Override + public ExtendedData getData() { + return (ExtendedData) ((Object) nbtCompound); + } + + @SuppressWarnings("DataFlowIssue") + @Override + public EntityTypeExtended setData(ExtendedData data) { + return new FabricEntityTypeExtended(entityType, data.getClass().equals(NbtCompound.class) ? ((NbtCompound) ((Object) data)) : null); + } + + @Override + public EntityType getType() { + return (EntityType) entityType; + } + + @Override + public Object getHandle() { + return entityType; + } +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java index 002759eb4..7ca93489d 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java @@ -36,6 +36,7 @@ import com.dfsek.terra.api.block.entity.MobSpawner; import com.dfsek.terra.api.block.entity.SerialState; import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.mod.CommonPlatform; +import com.dfsek.terra.mod.implmentation.FabricEntityTypeExtended; import com.dfsek.terra.mod.mixin.access.MobSpawnerLogicAccessor; @@ -66,7 +67,10 @@ public abstract class MobSpawnerBlockEntityMixin extends BlockEntity { } else { rand = Random.create(); } - setEntityType((net.minecraft.entity.EntityType) creatureType, rand); + net.minecraft.entity.EntityType entityType = + (((net.minecraft.entity.EntityType) (creatureType.isExtended() && creatureType.getClass().equals( + FabricEntityTypeExtended.class) ? ((FabricEntityTypeExtended) creatureType).getType() : creatureType))); + setEntityType(entityType, rand); } public int terra$getDelay() { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateArgumentMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateArgumentMixin.java index 9b4626ec8..2798f0508 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateArgumentMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateArgumentMixin.java @@ -15,10 +15,10 @@ import org.spongepowered.asm.mixin.Shadow; import java.util.Set; import java.util.function.Predicate; -import com.dfsek.terra.api.block.BlockData; import com.dfsek.terra.api.block.BlockType; import com.dfsek.terra.api.block.state.BlockStateExtended; import com.dfsek.terra.api.block.state.properties.Property; +import com.dfsek.terra.api.data.ExtendedData; @Mixin(BlockStateArgument.class) @@ -72,19 +72,23 @@ public abstract class BlockStateArgumentMixin implements Predicate) entityType).create(world, SpawnReason.CHUNK_GENERATION); - entity.setPos(x, y, z); - spawnEntity(entity); + @SuppressWarnings("DataFlowIssue") + public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType data) { + boolean isExtended = data.isExtended() && data.getClass().equals(FabricEntityTypeExtended.class); + net.minecraft.entity.Entity entity; + if(isExtended) { + FabricEntityTypeExtended type = ((FabricEntityTypeExtended) data); + NbtCompound nbt = (NbtCompound) ((Object) type.getData()); + entity = net.minecraft.entity.EntityType.loadEntityWithPassengers(nbt, world, SpawnReason.CHUNK_GENERATION, (entityx) -> { + entityx.refreshPositionAndAngles(x, y, z, entityx.getYaw(), entityx.getPitch()); + return entityx; + }); + spawnEntity(entity); + } else { + entity = ((net.minecraft.entity.EntityType) data).create(world, SpawnReason.CHUNK_GENERATION); + entity.setPos(x, y, z); + spawnEntity(entity); + } + return (Entity) entity; } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java index b2d48550d..7e7f762d3 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ServerWorldMixin.java @@ -50,6 +50,7 @@ import com.dfsek.terra.api.world.chunk.Chunk; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; import com.dfsek.terra.mod.generation.TerraBiomeSource; +import com.dfsek.terra.mod.implmentation.FabricEntityTypeExtended; import com.dfsek.terra.mod.util.MinecraftUtil; @@ -69,10 +70,23 @@ public abstract class ServerWorldMixin extends World { public abstract WorldTickScheduler 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); - spawnEntity(entity); + public Entity terra$spawnEntity(double x, double y, double z, EntityType data) { + boolean isExtended = data.isExtended() && data.getClass().equals(FabricEntityTypeExtended.class); + net.minecraft.entity.Entity entity; + if(isExtended) { + FabricEntityTypeExtended type = ((FabricEntityTypeExtended) data); + NbtCompound nbt = (NbtCompound) ((Object) type.getData()); + entity = net.minecraft.entity.EntityType.loadEntityWithPassengers(nbt, this, SpawnReason.CHUNK_GENERATION, (entityx) -> { + entityx.refreshPositionAndAngles(x, y, z, entityx.getYaw(), entityx.getPitch()); + return entityx; + }); + spawnEntity(entity); + } else { + entity = ((net.minecraft.entity.EntityType) data).create(this, SpawnReason.CHUNK_GENERATION); + entity.setPos(x, y, z); + spawnEntity(entity); + } + return (Entity) entity; }