feat: allow external block entity implementations

This commit is contained in:
Christian Bergschneider 2025-01-02 23:22:44 +01:00
parent cb2841ed4f
commit ff153ddc21
No known key found for this signature in database
GPG Key ID: 3991F97F5FA28D3E
6 changed files with 70 additions and 15 deletions

View File

@ -0,0 +1,16 @@
package com.dfsek.terra.minestom.api;
import com.dfsek.terra.api.block.entity.BlockEntity;
import net.minestom.server.coordinate.BlockVec;
import org.jetbrains.annotations.Nullable;
/**
* Represents a factory interface for creating instances of BlockEntity
* at a specified BlockVec position. This is not implemented directly because
* Minestom does not define a way to build block entities out of the box.
*/
public interface BlockEntityFactory {
@Nullable BlockEntity createBlockEntity(BlockVec position);
}

View File

@ -0,0 +1,14 @@
package com.dfsek.terra.minestom.block;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.minestom.api.BlockEntityFactory;
import net.minestom.server.coordinate.BlockVec;
public class DefaultBlockEntityFactory implements BlockEntityFactory {
@Override
public BlockEntity createBlockEntity(BlockVec position) {
return null;
}
}

View File

@ -6,6 +6,8 @@ import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
import net.minestom.server.coordinate.Pos;
public class DeferredMinestomEntity implements Entity {
private final EntityType type;
@ -27,6 +29,10 @@ public class DeferredMinestomEntity implements Entity {
return Vector3.of(x, y, z);
}
public Pos pos() {
return new Pos(x, y, z);
}
@Override
public void position(Vector3 position) {
x = position.getX();

View File

@ -63,7 +63,7 @@ public class MinestomProtoWorld implements ProtoWorld {
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
TerraMinestomWorld world = this.world;
DeferredMinestomEntity entity = new DeferredMinestomEntity(x, y, z, entityType, world);
world.enqueueEntitySpawn(entity);
world.enqueue(entity.pos(), (chunk) -> entity.spawn());
return entity;
}
@ -77,7 +77,7 @@ public class MinestomProtoWorld implements ProtoWorld {
@Override
public BlockEntity getBlockEntity(int x, int y, int z) {
return null;
return world.getBlockEntity(x, y, z);
}
@Override

View File

@ -13,17 +13,21 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.info.WorldProperties;
import com.dfsek.terra.minestom.api.BlockEntityFactory;
import com.dfsek.terra.minestom.api.EntityFactory;
import com.dfsek.terra.minestom.block.MinestomBlockState;
import com.dfsek.terra.minestom.api.filter.ChunkFilter;
import com.dfsek.terra.minestom.entity.DeferredMinestomEntity;
import com.dfsek.terra.minestom.entity.MinestomEntity;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.BlockVec;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
import net.minestom.server.world.DimensionType;
import java.util.function.Consumer;
public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
private final Instance instance;
@ -31,21 +35,30 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
private final long seed;
private final DimensionType dimensionType;
private final MinestomChunkGeneratorWrapper wrapper;
private final EntityFactory factory;
private final EntityFactory entityFactory;
private final BlockEntityFactory blockEntityFactory;
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory factory, ChunkFilter filter) {
public TerraMinestomWorld(
Instance instance,
ConfigPack pack,
long seed,
EntityFactory entityFactory,
ChunkFilter filter,
BlockEntityFactory blockEntityFactory
) {
this.instance = instance;
this.pack = pack;
this.seed = seed;
this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType());
this.blockEntityFactory = blockEntityFactory;
this.wrapper = new MinestomChunkGeneratorWrapper(
pack.getGeneratorProvider().newInstance(pack),
this,
filter
);
this.factory = factory;
this.entityFactory = entityFactory;
instance.setGenerator(this.wrapper);
}
@ -76,7 +89,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
@Override
public BlockEntity getBlockEntity(int x, int y, int z) {
return null;
return blockEntityFactory.createBlockEntity(new BlockVec(x, y, z));
}
@Override
@ -119,12 +132,10 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
}
public EntityFactory getEntityFactory() {
return factory;
return entityFactory;
}
public void enqueueEntitySpawn(DeferredMinestomEntity deferredMinestomEntity) {
int chunkX = deferredMinestomEntity.position().getBlockX() >> 4;
int chunkZ = deferredMinestomEntity.position().getBlockZ() >> 4;
instance.loadChunk(chunkX, chunkZ).thenAccept(chunk -> deferredMinestomEntity.spawn());
public void enqueue(Point position, Consumer<net.minestom.server.instance.Chunk> action) {
instance.loadChunk(position.chunkX(), position.chunkZ()).thenAccept(action);
}
}

View File

@ -5,8 +5,10 @@ import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.minestom.MinestomPlatform;
import com.dfsek.terra.minestom.api.BlockEntityFactory;
import com.dfsek.terra.minestom.api.EntityFactory;
import com.dfsek.terra.minestom.api.filter.ChunkFilter;
import com.dfsek.terra.minestom.block.DefaultBlockEntityFactory;
import com.dfsek.terra.minestom.entity.DefaultEntityFactory;
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.Instance;
@ -20,8 +22,9 @@ public class TerraMinestomWorldBuilder {
private final Instance instance;
private ConfigPack pack;
private long seed = new Random().nextLong();
private EntityFactory factory = new DefaultEntityFactory();
private EntityFactory entityFactory = new DefaultEntityFactory();
private ChunkFilter filter;
private BlockEntityFactory blockEntityFactory = new DefaultBlockEntityFactory();
private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; }
@ -63,7 +66,12 @@ public class TerraMinestomWorldBuilder {
}
public TerraMinestomWorldBuilder entityFactory(EntityFactory factory) {
this.factory = factory;
this.entityFactory = factory;
return this;
}
public TerraMinestomWorldBuilder blockEntityFactory(BlockEntityFactory factory) {
this.blockEntityFactory = factory;
return this;
}
@ -73,6 +81,6 @@ public class TerraMinestomWorldBuilder {
}
public TerraMinestomWorld attach() {
return new TerraMinestomWorld(instance, pack, seed, factory, filter);
return new TerraMinestomWorld(instance, pack, seed, entityFactory, filter, blockEntityFactory);
}
}