fix Fabric entity spawning

This commit is contained in:
dfsek 2022-06-16 15:59:25 -07:00
parent 355805347b
commit c96e908a1e
7 changed files with 210 additions and 71 deletions

View File

@ -0,0 +1,52 @@
package com.dfsek.terra.fabric.entity;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import net.minecraft.world.ServerWorldAccess;
public class DelegateEntity implements Entity {
private Vector3 position;
private ServerWorld world;
private final EntityType type;
public DelegateEntity(Vector3 position, ServerWorld world, EntityType type) {
this.world = world;
this.position = position;
this.type = type;
}
@Override
public Vector3 position() {
return position;
}
@Override
public void position(Vector3 position) {
this.position = position;
}
@Override
public ServerWorld world() {
return world;
}
@Override
public void world(ServerWorld world) {
this.world = world;
}
@Override
public Object getHandle() {
return this;
}
public net.minecraft.entity.Entity createMinecraftEntity(ServerWorldAccess world) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) type).create(world.toServerWorld());
entity.setPos(position.getX(), position.getY(), position.getZ());
return entity;
}
}

View File

@ -0,0 +1,10 @@
package com.dfsek.terra.fabric.entity;
import java.util.List;
public interface DelegateEntityHolder {
List<DelegateEntity> getAndClearTerraEntities();
void addTerraEntity(DelegateEntity entity);
}

View File

@ -27,6 +27,8 @@ import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.api.world.info.WorldProperties;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.data.Codecs; import com.dfsek.terra.fabric.data.Codecs;
import com.dfsek.terra.fabric.entity.DelegateEntityHolder;
import com.dfsek.terra.fabric.mixin.access.ChunkRegionAccessor;
import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor;
import com.dfsek.terra.fabric.util.FabricAdapter; import com.dfsek.terra.fabric.util.FabricAdapter;
@ -95,7 +97,8 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
ChunkPos pos = chunk.getPos(); ChunkPos pos = chunk.getPos();
((BiomeProviderHolder) chunk) ((BiomeProviderHolder) chunk)
.terra$setHeldBiomeProvider(pack.getBiomeProvider() .terra$setHeldBiomeProvider(pack.getBiomeProvider()
.caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(), pos.x, pos.z)); .caching((ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(), pos.x,
pos.z));
} }
return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk); return super.populateBiomes(biomeRegistry, executor, noiseConfig, blender, structureAccessor, chunk);
} }
@ -116,6 +119,13 @@ public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.C
@Override @Override
public void populateEntities(ChunkRegion region) { public void populateEntities(ChunkRegion region) {
((ChunkRegionAccessor) region)
.getChunks()
.forEach(
chunk -> ((DelegateEntityHolder) chunk)
.getAndClearTerraEntities()
.forEach(entity -> chunk.addEntity(entity.createMinecraftEntity(region)))
);
if(!this.settings.value().mobGenerationDisabled()) { if(!this.settings.value().mobGenerationDisabled()) {
ChunkPos chunkPos = region.getCenterPos(); ChunkPos chunkPos = region.getCenterPos();
RegistryEntry<Biome> registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1)); RegistryEntry<Biome> registryEntry = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1));

View File

@ -0,0 +1,15 @@
package com.dfsek.terra.fabric.mixin.access;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.chunk.Chunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(ChunkRegion.class)
public interface ChunkRegionAccessor {
@Accessor("chunks")
List<Chunk> getChunks();
}

View File

@ -0,0 +1,46 @@
package com.dfsek.terra.fabric.mixin.entity_holder;
import com.dfsek.terra.fabric.entity.DelegateEntity;
import com.dfsek.terra.fabric.entity.DelegateEntityHolder;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.HeightLimitView;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.ProtoChunk;
import net.minecraft.world.chunk.UpgradeData;
import net.minecraft.world.gen.chunk.BlendingData;
import net.minecraft.world.tick.SimpleTickScheduler;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@Mixin(ProtoChunk.class)
@Implements(@Interface(iface = DelegateEntityHolder.class, prefix = "terra$"))
public class ProtoChunkMixin {
private AtomicReference<List<DelegateEntity>> terra$entities;
@Inject(method = "<init>*", at = @At("RETURN"))
public void injectConstructor(CallbackInfo ci) {
this.terra$entities = new AtomicReference<>(new ArrayList<>());
}
public List<DelegateEntity> terra$getAndClearTerraEntities() {
return terra$entities.getAndSet(new ArrayList<>());
}
public void terra$addTerraEntity(DelegateEntity entity) {
this.terra$entities.updateAndGet(list -> {
list.add(entity);
return list;
});
}
}

View File

@ -28,6 +28,8 @@ import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.fabric.entity.DelegateEntity;
import com.dfsek.terra.fabric.entity.DelegateEntityHolder;
import com.dfsek.terra.fabric.generation.BiomeProviderHolder; import com.dfsek.terra.fabric.generation.BiomeProviderHolder;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.generation.TerraBiomeSource;
@ -47,13 +49,15 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Mixin(ChunkRegion.class) @Mixin(ChunkRegion.class)
@Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$")) @Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$"))
public abstract class ChunkRegionMixin { public abstract class ChunkRegionMixin {
private ConfigPack config; private ConfigPack terra$config;
@Shadow @Shadow
@Final @Final
@ -70,27 +74,28 @@ public abstract class ChunkRegionMixin {
@Final @Final
private MultiTickScheduler<Fluid> fluidTickScheduler; private MultiTickScheduler<Fluid> fluidTickScheduler;
@SuppressWarnings("deprecation") @Shadow
private final Lazy<BiomeProvider> caching = Lazy.lazy(() -> ((TerraBiomeSource) ((ChunkRegion) (Object) this) public abstract net.minecraft.server.world.ServerWorld toServerWorld();
.toServerWorld()
.getChunkManager()
.getChunkGenerator()
.getBiomeSource()).getProvider().caching((ProtoWorld) this));
@Shadow
public abstract Chunk getChunk(int chunkX, int chunkZ);
private Lazy<BiomeProvider> caching;
@SuppressWarnings("deprecation")
@Inject(at = @At("RETURN"), @Inject(at = @At("RETURN"),
method = "<init>(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V") method = "<init>(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V")
public void injectConstructor(net.minecraft.server.world.ServerWorld world, List<net.minecraft.world.chunk.Chunk> list, public void injectConstructor(net.minecraft.server.world.ServerWorld world, List<net.minecraft.world.chunk.Chunk> list,
ChunkStatus chunkStatus, int i, ChunkStatus chunkStatus, int i,
CallbackInfo ci) { CallbackInfo ci) {
this.config = ((ServerWorld) world).getPack(); this.terra$config = ((ServerWorld) world).getPack();
this.caching = Lazy.lazy(() -> ((TerraBiomeSource) ((ChunkRegion) (Object) this)
.toServerWorld()
.getChunkManager()
.getChunkGenerator()
.getBiomeSource()).getProvider().caching((ProtoWorld) this));
} }
public Entity terraWorld$spawnEntity(Vector3 location, EntityType entityType) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(null);
entity.setPos(location.getX(), location.getY(), location.getZ());
((ChunkRegion) (Object) this).spawnEntity(entity);
return (Entity) entity;
}
@Intrinsic(displace = true) @Intrinsic(displace = true)
public void terraWorld$setBlockState(int x, int y, int z, BlockState data, boolean physics) { public void terraWorld$setBlockState(int x, int y, int z, BlockState data, boolean physics) {
@ -139,10 +144,9 @@ public abstract class ChunkRegionMixin {
} }
public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(null); DelegateEntity entity = new DelegateEntity(Vector3.of(x, y, z), (ServerWorld) this.toServerWorld(), entityType);
entity.setPos(x, y, z); ((DelegateEntityHolder) getChunk((int) x / 16, (int) z / 16)).addTerraEntity(entity);
((ChunkRegion) (Object) this).spawnEntity(entity); return entity;
return (Entity) entity;
} }
public int terraWorld$centerChunkX() { public int terraWorld$centerChunkX() {
@ -158,6 +162,6 @@ public abstract class ChunkRegionMixin {
} }
public ConfigPack terraWorld$getPack() { public ConfigPack terraWorld$getPack() {
return config; return terra$config;
} }
} }

View File

@ -1,53 +1,55 @@
{ {
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "com.dfsek.terra.fabric.mixin", "package": "com.dfsek.terra.fabric.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
"access.MobSpawnerLogicAccessor", "access.ChunkRegionAccessor",
"access.StateAccessor", "access.MobSpawnerLogicAccessor",
"access.StructureAccessorAccessor", "access.StateAccessor",
"cache.ChunkRegionMixin", "access.StructureAccessorAccessor",
"cache.ProtoChunkMixin", "cache.ChunkRegionMixin",
"compat.GenerationSettingsFloraFeaturesMixin", "cache.ProtoChunkMixin",
"fix.NetherFossilOptimization", "compat.GenerationSettingsFloraFeaturesMixin",
"implementations.BiomeMixin", "entity_holder.ProtoChunkMixin",
"implementations.HandleImplementationMixin", "fix.NetherFossilOptimization",
"implementations.block.BlockMixin", "implementations.BiomeMixin",
"implementations.block.entity.BlockEntityMixin", "implementations.HandleImplementationMixin",
"implementations.block.entity.LootableContainerBlockEntityMixin", "implementations.block.BlockMixin",
"implementations.block.entity.MobSpawnerBlockEntityMixin", "implementations.block.entity.BlockEntityMixin",
"implementations.block.entity.SignBlockEntityMixin", "implementations.block.entity.LootableContainerBlockEntityMixin",
"implementations.block.state.BlockStateMixin", "implementations.block.entity.MobSpawnerBlockEntityMixin",
"implementations.block.state.PropertyMixin", "implementations.block.entity.SignBlockEntityMixin",
"implementations.chunk.ChunkRegionMixin", "implementations.block.state.BlockStateMixin",
"implementations.chunk.WorldChunkMixin", "implementations.block.state.PropertyMixin",
"implementations.chunk.data.ProtoChunkMixin", "implementations.chunk.ChunkRegionMixin",
"implementations.entity.EntityMixin", "implementations.chunk.WorldChunkMixin",
"implementations.entity.EntityTypeMixin", "implementations.chunk.data.ProtoChunkMixin",
"implementations.entity.PlayerEntityMixin", "implementations.entity.EntityMixin",
"implementations.entity.ServerCommandSourceMixin", "implementations.entity.EntityTypeMixin",
"implementations.inventory.LockableContainerBlockEntityMixin", "implementations.entity.PlayerEntityMixin",
"implementations.inventory.item.ItemMixin", "implementations.entity.ServerCommandSourceMixin",
"implementations.inventory.item.ItemStackMixin", "implementations.inventory.LockableContainerBlockEntityMixin",
"implementations.inventory.meta.EnchantmentMixin", "implementations.inventory.item.ItemMixin",
"implementations.inventory.meta.ItemStackDamageableMixin", "implementations.inventory.item.ItemStackMixin",
"implementations.inventory.meta.ItemStackMetaMixin", "implementations.inventory.meta.EnchantmentMixin",
"implementations.world.ChunkRegionMixin", "implementations.inventory.meta.ItemStackDamageableMixin",
"implementations.world.ServerWorldMixin", "implementations.inventory.meta.ItemStackMetaMixin",
"lifecycle.DataPackContentsMixin", "implementations.world.ChunkRegionMixin",
"lifecycle.MinecraftServerMixin", "implementations.world.ServerWorldMixin",
"lifecycle.NoiseConfigMixin", "lifecycle.DataPackContentsMixin",
"lifecycle.RegistryMixin" "lifecycle.MinecraftServerMixin",
], "lifecycle.NoiseConfigMixin",
"client": [ "lifecycle.RegistryMixin"
"lifecycle.client.MinecraftClientMixin" ],
], "client": [
"server": [ "lifecycle.client.MinecraftClientMixin"
"lifecycle.server.ServerMainMixin" ],
], "server": [
"injectors": { "lifecycle.server.ServerMainMixin"
"defaultRequire": 1 ],
}, "injectors": {
"refmap": "terra-refmap.json" "defaultRequire": 1
},
"refmap": "terra-refmap.json"
} }