feat: minestom entities

This commit is contained in:
Christian Bergschneider
2025-01-01 20:39:09 +01:00
parent b4ab3769b0
commit d1f881ca2c
10 changed files with 224 additions and 8 deletions

View File

@@ -0,0 +1,17 @@
package com.dfsek.terra.minestom;
import com.dfsek.terra.api.util.vector.Vector3;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
public class MinestomAdapter {
public static Vector3 adapt(Point point) {
return Vector3.of(point.x(), point.y(), point.z());
}
public static Pos adapt(Vector3 vector) {
return new Pos(vector.getX(), vector.getY(), vector.getZ());
}
}

View File

@@ -0,0 +1,13 @@
package com.dfsek.terra.minestom.api;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
/**
* Allows adding AI to generated entities using custom entity types
*/
public interface EntityFactory {
Entity createEntity(EntityType type);
}

View File

@@ -0,0 +1,14 @@
package com.dfsek.terra.minestom.entity;
import com.dfsek.terra.minestom.api.EntityFactory;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
public class DefaultEntityFactory implements EntityFactory {
@Override
public Entity createEntity(EntityType type) {
return new Entity(type);
}
}

View File

@@ -0,0 +1,62 @@
package com.dfsek.terra.minestom.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 com.dfsek.terra.minestom.world.TerraMinestomWorld;
public class DeferredMinestomEntity implements Entity {
private final EntityType type;
private double x;
private double y;
private double z;
private TerraMinestomWorld world;
public DeferredMinestomEntity(double x, double y, double z, EntityType type, TerraMinestomWorld world) {
this.x = x;
this.y = y;
this.z = z;
this.type = type;
this.world = world;
}
@Override
public Vector3 position() {
return Vector3.of(x, y, z);
}
@Override
public void position(Vector3 position) {
x = position.getX();
y = position.getY();
z = position.getZ();
}
@Override
public void world(ServerWorld world) {
this.world = (TerraMinestomWorld) world;
}
@Override
public ServerWorld world() {
return world;
}
@Override
public Object getHandle() {
return this;
}
public void spawn() {
int chunkX = (int) x >> 4;
int chunkZ = (int) z >> 4;
if(!world.getHandle().isChunkLoaded(chunkX, chunkZ)) {
return;
}
MinestomEntity.spawn(x, y, z, type, world);
}
}

View File

@@ -0,0 +1,55 @@
package com.dfsek.terra.minestom.entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.minestom.MinestomAdapter;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Entity;
import net.minestom.server.instance.Instance;
public class MinestomEntity implements com.dfsek.terra.api.entity.Entity {
private final Entity delegate;
private final TerraMinestomWorld world;
public MinestomEntity(Entity delegate, TerraMinestomWorld world) {
this.delegate = delegate;
this.world = world;
}
@Override
public Vector3 position() {
return MinestomAdapter.adapt(delegate.getPosition());
}
@Override
public void position(Vector3 position) {
delegate.teleport(MinestomAdapter.adapt(position));
}
@Override
public void world(ServerWorld world) {
delegate.setInstance(((TerraMinestomWorld) world).getHandle());
}
@Override
public ServerWorld world() {
return world;
}
@Override
public Object getHandle() {
return delegate;
}
public static MinestomEntity spawn(double x, double y, double z, EntityType type, TerraMinestomWorld world) {
Instance instance = world.getHandle();
Entity entity = world.getEntityFactory().createEntity(((MinestomEntityType) type).getHandle());
entity.setInstance(instance, new Pos(x, y, z));
return new MinestomEntity(entity, world);
}
}

View File

@@ -0,0 +1,18 @@
package com.dfsek.terra.minestom.entity;
import net.minestom.server.entity.EntityType;
public class MinestomEntityType implements com.dfsek.terra.api.entity.EntityType {
private final EntityType delegate;
public MinestomEntityType(String id) {
delegate = EntityType.fromNamespaceId(id);
}
@Override
public EntityType getHandle() {
return delegate;
}
}

View File

@@ -11,6 +11,8 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
import com.dfsek.terra.minestom.entity.DeferredMinestomEntity;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.Block.Setter;
@@ -62,7 +64,10 @@ public class MinestomProtoWorld implements ProtoWorld {
@Override
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
return null;
TerraMinestomWorld world = (TerraMinestomWorld) this.world;
DeferredMinestomEntity entity = new DeferredMinestomEntity(x, y, z, entityType, world);
world.enqueueEntitySpawn(entity);
return entity;
}
@Override

View File

@@ -5,6 +5,8 @@ import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.minestom.block.MinestomBlockState;
import com.dfsek.terra.minestom.entity.MinestomEntityType;
import net.minestom.server.instance.block.Block;
import org.jetbrains.annotations.NotNull;
@@ -24,6 +26,6 @@ public class MinestomWorldHandle implements WorldHandle {
@Override
public @NotNull EntityType getEntity(@NotNull String id) {
return null;
return new MinestomEntityType(id);
}
}

View File

@@ -5,6 +5,7 @@ import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.Chunk;
@@ -13,10 +14,19 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.info.WorldProperties;
import com.dfsek.terra.minestom.api.EntityFactory;
import com.dfsek.terra.minestom.block.MinestomBlockState;
import com.dfsek.terra.minestom.entity.DeferredMinestomEntity;
import com.dfsek.terra.minestom.entity.MinestomEntity;
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
import net.minestom.server.world.DimensionType;
import java.util.ArrayList;
import java.util.HashMap;
public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
private final Instance instance;
@@ -24,8 +34,9 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
private final long seed;
private final DimensionType dimensionType;
private final MinestomChunkGeneratorWrapper wrapper;
private final EntityFactory factory;
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed) {
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory factory) {
this.instance = instance;
this.pack = pack;
this.seed = seed;
@@ -36,6 +47,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
pack.getGeneratorProvider().newInstance(pack),
this
);
this.factory = factory;
instance.setGenerator(this.wrapper);
}
@@ -47,17 +59,17 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
@Override
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
instance.setBlock(x, y, z, (Block) data.getHandle());
}
@Override
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
return null;
return MinestomEntity.spawn(x, y, z, entityType, this);
}
@Override
public BlockState getBlockState(int x, int y, int z) {
return null;
return new MinestomBlockState(instance.getBlock(x, y, z));
}
@Override
@@ -96,11 +108,21 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
}
@Override
public Object getHandle() {
public Instance getHandle() {
return instance;
}
public DimensionType getDimensionType() {
return dimensionType;
}
public EntityFactory getEntityFactory() {
return factory;
}
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());
}
}

View File

@@ -5,6 +5,8 @@ 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.EntityFactory;
import com.dfsek.terra.minestom.entity.DefaultEntityFactory;
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.Instance;
@@ -16,6 +18,7 @@ public class TerraMinestomWorldBuilder {
private final Instance instance;
private ConfigPack pack;
private long seed = new Random().nextLong();
private EntityFactory factory = new DefaultEntityFactory();
private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; }
@@ -56,7 +59,12 @@ public class TerraMinestomWorldBuilder {
return this;
}
public TerraMinestomWorldBuilder entityFactory(EntityFactory factory) {
this.factory = factory;
return this;
}
public TerraMinestomWorld attach() {
return new TerraMinestomWorld(instance, pack, seed);
return new TerraMinestomWorld(instance, pack, seed, factory);
}
}