Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public class TerraMinestomExample {
private TerraMinestomWorld world;

public static void main(String[] args) {
System.setProperty("minestom.registry.unsafe-ops", "true");

TerraMinestomExample example = new TerraMinestomExample();
example.createNewInstance();
example.attachTerra();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dfsek.terra.minestom.api;


import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;

Expand All @@ -9,5 +10,22 @@
* Allows adding AI to generated entities using custom entity types
*/
public interface EntityFactory {
/**
* Creates a new entity of the specified type.
*
* @param type the type of the entity to be created
* @return the created entity instance
*/
Entity createEntity(EntityType type);

/**
* Creates a new entity of the specified type with additional data.
*
* @param type the type of the entity to be created
* @param data the additional data for the entity, represented as a CompoundBinaryTag
* @return the created entity instance
*/
default Entity createEntity(EntityType type, CompoundBinaryTag data) {
return createEntity(type);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.dfsek.terra.minestom.block;

import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.TagStringIO;
import net.minestom.server.instance.block.Block;

import java.io.IOException;
import java.util.HashMap;
import java.util.Objects;
import java.util.stream.Collectors;
Expand All @@ -10,38 +13,84 @@
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.block.state.properties.Property;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MinestomBlockState implements BlockState {

public record MinestomBlockState(Block block) implements BlockState {
private static final Logger LOGGER = LoggerFactory.getLogger(MinestomBlockState.class);
public static final MinestomBlockState AIR = new MinestomBlockState(Block.AIR);
private final Block block;
private static final TagStringIO tagStringIO = TagStringIO.tagStringIO();

public MinestomBlockState(Block block) {
if(block == null) {
this.block = Block.AIR;
} else {
this.block = block;
}
public MinestomBlockState {
block = Objects.requireNonNullElse(block, Block.AIR);
}

public MinestomBlockState(String data) {
if(!data.contains("[")) {
block = Block.fromKey(data);
return;
public static MinestomBlockState fromStateId(String data) {
CompoundBinaryTag nbt = CompoundBinaryTag.empty();
int splitIndex = data.indexOf('{');
if(splitIndex != -1) {
String fullId = data;
data = data.substring(0, splitIndex);
String dataString = fullId.substring(splitIndex);
try {
nbt = tagStringIO.asCompound(dataString);
} catch(IOException exception) {
LOGGER.warn("Invalid entity data, will be ignored: {}", dataString);
}
}

int openBracketIndex = data.indexOf('[');
int closeBracketIndex = data.indexOf(']');

if(openBracketIndex == -1 || closeBracketIndex == -1 || closeBracketIndex < openBracketIndex) {
// no or invalid properties
Block block = Block.fromKey(data);
if(block != null && !nbt.isEmpty()) {
block = block.withNbt(nbt);
}
return new MinestomBlockState(block);
}

String[] split = data.split("\\[");
String namespaceId = split[0];
String properties = split[1].substring(0, split[1].length() - 1);
String namespaceId = data.substring(0, openBracketIndex);
String propertiesContent = data.substring(openBracketIndex + 1, closeBracketIndex);
Block block = Block.fromKey(namespaceId);
if (block == null) {
LOGGER.error("Invalid block ID found during parsing: {}", namespaceId);
return new MinestomBlockState(Block.AIR);
}

HashMap<String, String> propertiesMap = new HashMap<>();
int current = 0;
while (current < propertiesContent.length()) {
int nextComma = propertiesContent.indexOf(',', current);
String property;

if (nextComma == -1) {
property = propertiesContent.substring(current);
current = propertiesContent.length();
} else {
property = propertiesContent.substring(current, nextComma);
current = nextComma + 1;
}

int equalsIndex = property.indexOf('=');

if (equalsIndex == -1) {
LOGGER.warn("Invalid block property syntax (missing '=') in string: {}", property);
continue;
}

String key = property.substring(0, equalsIndex).strip();
String value = property.substring(equalsIndex + 1).strip();
propertiesMap.put(key, value);
}

for(String property : properties.split(",")) {
String[] kv = property.split("=");
propertiesMap.put(kv[0].strip(), kv[1].strip());
if(!nbt.isEmpty()) {
block = block.withNbt(nbt);
}

assert block != null;
this.block = block.withProperties(propertiesMap);
return new MinestomBlockState(block.withProperties(propertiesMap));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,27 @@
public class CachedChunk implements ProtoChunk {
private final int minHeight;
private final int maxHeight;
private final Block[] blocks;
private final MinestomBlockState[] blocks;

public CachedChunk(int minHeight, int maxHeight) {
this.minHeight = minHeight;
this.maxHeight = maxHeight;
this.blocks = new Block[16 * (maxHeight - minHeight + 1) * 16];
Arrays.fill(blocks, Block.AIR);
this.blocks = new MinestomBlockState[16 * (maxHeight - minHeight + 1) * 16];
Arrays.fill(blocks, MinestomBlockState.AIR);
}

public void writeRelative(UnitModifier modifier) {
modifier.setAllRelative((x, y, z) -> blocks[getIndex(x, y + minHeight, z)]);
modifier.setAllRelative((x, y, z) -> blocks[getIndex(x, y + minHeight, z)].block());
}

@Override
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
Block block = (Block) blockState.getHandle();
MinestomBlockState minestomBlockState = (MinestomBlockState) blockState;
Block block = minestomBlockState.block();
if(block == null) return;
int index = getIndex(x, y, z);
if(index > blocks.length || index < 0) return;
blocks[index] = block;
blocks[index] = minestomBlockState;
}

private int getIndex(int x, int y, int z) {
Expand All @@ -46,7 +47,7 @@ private int getIndex(int x, int y, int z) {
public @NotNull BlockState getBlock(int x, int y, int z) {
int index = getIndex(x, y, z);
if(index > blocks.length || index < 0) return MinestomBlockState.AIR;
return new MinestomBlockState(blocks[index]);
return blocks[index];
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
import net.minestom.server.world.DimensionType;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -15,7 +16,7 @@

public class GeneratedChunkCache {
private static final Logger log = LoggerFactory.getLogger(GeneratedChunkCache.class);
private final LoadingCache<Pair<Integer, Integer>, CachedChunk> cache;
private final LoadingCache<@NotNull Long, CachedChunk> cache;
private final DimensionType dimensionType;
private final ChunkGenerator generator;
private final ServerWorld world;
Expand All @@ -29,7 +30,7 @@ public GeneratedChunkCache(DimensionType dimensionType, ChunkGenerator generator
this.cache = Caffeine.newBuilder()
.maximumSize(128)
.recordStats()
.build((Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
.build((Long key) -> generateChunk(unpackX(key), unpackZ(key)));
}

private CachedChunk generateChunk(int x, int z) {
Expand All @@ -50,6 +51,18 @@ public void displayStats() {
}

public CachedChunk at(int x, int z) {
return cache.get(Pair.of(x, z));
return cache.get(pack(x, z));
}

private long pack(final int x, final int z) {
return ((long) x) << 32 | z & 0xFFFFFFFFL;
}

private int unpackX(long key) {
return (int) (key >>> 32);
}

private int unpackZ(long key) {
return (int) key;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public MinestomEntity(Entity delegate, TerraMinestomWorld world) {

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());
MinestomEntityType entityType = (MinestomEntityType) type;
Entity entity = world.getEntityFactory().createEntity(entityType.getHandle(), entityType.getData());
entity.setInstance(instance, new Pos(x, y, z));
return new MinestomEntity(entity, world);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,47 @@
package com.dfsek.terra.minestom.entity;

import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.TagStringIO;
import net.minestom.server.entity.EntityType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;


public class MinestomEntityType implements com.dfsek.terra.api.entity.EntityType {
private static final Logger LOGGER = LoggerFactory.getLogger(MinestomEntityType.class);
private static final TagStringIO tagStringIO = TagStringIO.tagStringIO();
private final EntityType delegate;
private final CompoundBinaryTag data;

public MinestomEntityType(String id) {
int splitIndex = id.indexOf('{');
if(splitIndex != -1) {
String fullId = id;
id = id.substring(0, splitIndex);
String dataString = fullId.substring(splitIndex);
CompoundBinaryTag data;
try {
data = tagStringIO.asCompound(dataString);
} catch(IOException exception) {
LOGGER.warn("Invalid entity data, will be ignored: {}", dataString);
data = CompoundBinaryTag.empty();
}
this.data = data;
} else {
this.data = CompoundBinaryTag.empty();
}

delegate = EntityType.fromKey(id);
}

@Override
public EntityType getHandle() {
return delegate;
}

public CompoundBinaryTag getData() {
return data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class MinestomWorldHandle implements WorldHandle {

@Override
public @NotNull BlockState createBlockState(@NotNull String data) {
return new MinestomBlockState(data);
return MinestomBlockState.fromStateId(data);
}

@Override
Expand Down