mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-01 23:47:50 +00:00
feat: base terrain generation with minestom
This commit is contained in:
parent
0a952cff4c
commit
983cb1f012
@ -75,4 +75,8 @@ object Versions {
|
||||
const val nbt = "6.1"
|
||||
const val logback = "1.5.8"
|
||||
}
|
||||
|
||||
object Minestom {
|
||||
const val minestom = "187931e50b"
|
||||
}
|
||||
}
|
34
platforms/minestom/build.gradle.kts
Normal file
34
platforms/minestom/build.gradle.kts
Normal file
@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
application
|
||||
}
|
||||
|
||||
val javaMainClass = "com.dfsek.terra.minestom.TerraMinestomExample"
|
||||
|
||||
dependencies {
|
||||
shadedApi(project(":common:implementation:base"))
|
||||
|
||||
//shadedApi("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO)
|
||||
//shadedApi("com.github.Querz", "NBT", Versions.CLI.nbt)
|
||||
|
||||
shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||
|
||||
implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom)
|
||||
implementation("org.slf4j", "slf4j-simple", Versions.Libraries.slf4j)
|
||||
}
|
||||
|
||||
tasks.withType<Jar> {
|
||||
entryCompression = ZipEntryCompression.STORED
|
||||
manifest {
|
||||
attributes(
|
||||
"Main-Class" to javaMainClass,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set(javaMainClass)
|
||||
}
|
||||
|
||||
tasks.getByName("run").setProperty("workingDir", file("./run"))
|
||||
|
||||
addonDir(project.file("./run/terra/addons"), tasks.named("run").get())
|
@ -0,0 +1,73 @@
|
||||
package com.dfsek.terra.minestom;
|
||||
|
||||
import com.dfsek.tectonic.api.TypeRegistry;
|
||||
|
||||
import com.dfsek.tectonic.api.loader.type.TypeLoader;
|
||||
|
||||
import com.dfsek.terra.AbstractPlatform;
|
||||
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
|
||||
import com.dfsek.terra.api.handle.ItemHandle;
|
||||
import com.dfsek.terra.api.handle.WorldHandle;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.PlatformBiome;
|
||||
|
||||
import com.dfsek.terra.minestom.item.MinestomItemHandle;
|
||||
|
||||
import com.dfsek.terra.minestom.world.MinestomWorldHandle;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
public final class MinestomPlatform extends AbstractPlatform {
|
||||
private static MinestomPlatform INSTANCE = null;
|
||||
private final MinestomWorldHandle worldHandle = new MinestomWorldHandle();
|
||||
private final MinestomItemHandle itemHandle = new MinestomItemHandle();
|
||||
|
||||
private MinestomPlatform() {
|
||||
load();
|
||||
getEventManager().callEvent(new PlatformInitializationEvent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
super.register(registry);
|
||||
registry.registerLoader(PlatformBiome.class, (TypeLoader<PlatformBiome>) (annotatedType, o, configLoader, depthTracker) -> () -> o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reload() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull WorldHandle getWorldHandle() {
|
||||
return worldHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemHandle getItemHandle() {
|
||||
return itemHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String platformName() {
|
||||
return "Minestom";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull File getDataFolder() {
|
||||
File file = new File("./terra/");
|
||||
if (!file.exists()) file.mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
public static MinestomPlatform getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new MinestomPlatform();
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra.minestom;
|
||||
|
||||
import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
|
||||
|
||||
public class TerraMinestomExample {
|
||||
public static void main(String[] args) {
|
||||
MinecraftServer server = MinecraftServer.init();
|
||||
|
||||
Instance instance = MinecraftServer
|
||||
.getInstanceManager()
|
||||
.createInstanceContainer();
|
||||
|
||||
TerraMinestomWorldBuilder.from(instance)
|
||||
.packById("OVERWORLD")
|
||||
.attach();
|
||||
|
||||
for(int x = -1; x <= 1; x++) {
|
||||
for(int z = -1; z <= 1; z++) {
|
||||
instance.loadChunk(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
MinecraftServer.getGlobalEventHandler().addListener(AsyncPlayerConfigurationEvent.class, event -> {
|
||||
event.setSpawningInstance(instance);
|
||||
event.getPlayer().setGameMode(GameMode.CREATIVE);
|
||||
event.getPlayer().setRespawnPoint(new Pos(0.0, 100.0, 0.0));
|
||||
});
|
||||
|
||||
server.start("localhost", 25565);
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.dfsek.terra.minestom.block;
|
||||
|
||||
import com.dfsek.terra.api.block.BlockType;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.block.state.properties.Property;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class MinestomBlockState implements BlockState {
|
||||
private final Block block;
|
||||
|
||||
public MinestomBlockState(Block block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public MinestomBlockState(String data) {
|
||||
if (!data.contains("[")) {
|
||||
block = Block.fromNamespaceId(data);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] split = data.split("\\[");
|
||||
String namespaceId = split[0];
|
||||
String properties = split[1].substring(0, split[1].length() - 1);
|
||||
Block block = Block.fromNamespaceId(namespaceId);
|
||||
HashMap<String, String> propertiesMap = new HashMap<>();
|
||||
|
||||
for (String property : properties.split(",")) {
|
||||
String[] kv = property.split("=");
|
||||
propertiesMap.put(kv[0].strip(), kv[1].strip());
|
||||
}
|
||||
|
||||
assert block != null;
|
||||
this.block = block.withProperties(propertiesMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(BlockState other) {
|
||||
return ((MinestomBlockState) other).block == block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> boolean has(Property<T> property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> T get(Property<T> property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> BlockState set(Property<T> property, T value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockType getBlockType() {
|
||||
return new MinestomBlockType(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString(boolean properties) {
|
||||
String name = block.namespace().asString();
|
||||
if (!properties) {
|
||||
return name;
|
||||
}
|
||||
|
||||
name += "[" + block
|
||||
.properties()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(entry ->
|
||||
entry.getKey() + "=" + entry.getValue()
|
||||
)
|
||||
.collect(Collectors.joining(",")) + "]";
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
return block.isAir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return block;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.dfsek.terra.minestom.block;
|
||||
|
||||
import com.dfsek.terra.api.block.BlockType;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
|
||||
public class MinestomBlockType implements BlockType {
|
||||
private final Block block;
|
||||
|
||||
public MinestomBlockType(Block block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getDefaultState() {
|
||||
return new MinestomBlockState(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return block.isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWater() {
|
||||
return block.isLiquid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return block;
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.dfsek.terra.minestom.chunk;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.generator.UnitModifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class MinestomProtoChunk implements ProtoChunk {
|
||||
private static final Logger log = LoggerFactory.getLogger(MinestomProtoChunk.class);
|
||||
private final int minHeight;
|
||||
private final int maxHeight;
|
||||
private final UnitModifier modifier;
|
||||
|
||||
public MinestomProtoChunk(int maxHeight, int minHeight, @NotNull UnitModifier modifier) {
|
||||
this.minHeight = minHeight;
|
||||
this.maxHeight = maxHeight;
|
||||
this.modifier = modifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
|
||||
try {
|
||||
modifier.setRelative(x, y - minHeight, z, (Block) blockState.getHandle());
|
||||
} catch(Exception e) {
|
||||
log.error("Failed setting Block at {} {} {} to {} (min={}, max={})", x, y, z, blockState.getHandle(), minHeight, maxHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
System.out.println("Block access at " + x + ", " + y + ", " + z + " is not supported.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return modifier;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.dfsek.terra.minestom.chunk;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import com.dfsek.terra.minestom.block.MinestomBlockState;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class TerraMinestomChunk implements Chunk {
|
||||
private net.minestom.server.instance.Chunk delegate;
|
||||
private final ServerWorld world;
|
||||
|
||||
public TerraMinestomChunk(net.minestom.server.instance.Chunk delegate, ServerWorld world) {
|
||||
this.delegate = delegate;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
delegate.setBlock(x, y, z, (Block) data.getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return new MinestomBlockState(delegate.getBlock(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getChunkX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getChunkZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.dfsek.terra.minestom.item;
|
||||
|
||||
import com.dfsek.terra.api.handle.ItemHandle;
|
||||
import com.dfsek.terra.api.inventory.Item;
|
||||
import com.dfsek.terra.api.inventory.item.Enchantment;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class MinestomItemHandle implements ItemHandle {
|
||||
@Override
|
||||
public Item createItem(String data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enchantment getEnchantment(String id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Enchantment> getEnchantments() {
|
||||
return Set.of();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
|
||||
import com.dfsek.terra.minestom.chunk.MinestomProtoChunk;
|
||||
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.instance.generator.GenerationUnit;
|
||||
import net.minestom.server.instance.generator.Generator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class MinestomChunkGeneratorWrapper implements Generator {
|
||||
private final ChunkGenerator generator;
|
||||
private final TerraMinestomWorld world;
|
||||
|
||||
public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world) {
|
||||
this.generator = generator;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public ChunkGenerator getGenerator() {
|
||||
return generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(@NotNull GenerationUnit generationUnit) {
|
||||
MinestomProtoChunk protoChunk = new MinestomProtoChunk(
|
||||
world.getMaxHeight(),
|
||||
world.getMinHeight(),
|
||||
generationUnit.modifier()
|
||||
);
|
||||
Point start = generationUnit.absoluteStart();
|
||||
generator.generateChunkData(protoChunk, world, world.getBiomeProvider(), start.chunkX(), start.chunkZ());
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.handle.WorldHandle;
|
||||
|
||||
import com.dfsek.terra.minestom.block.MinestomBlockState;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class MinestomWorldHandle implements WorldHandle {
|
||||
private static final MinestomBlockState AIR = new MinestomBlockState(Block.AIR);
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState createBlockState(@NotNull String data) {
|
||||
return new MinestomBlockState(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState air() {
|
||||
return AIR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getEntity(@NotNull String id) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
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.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
|
||||
public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
|
||||
private final Instance instance;
|
||||
private final MinestomChunkGeneratorWrapper wrapper;
|
||||
private final ConfigPack pack;
|
||||
private final long seed;
|
||||
private final DimensionType dimensionType;
|
||||
|
||||
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed) {
|
||||
this.instance = instance;
|
||||
this.wrapper = new MinestomChunkGeneratorWrapper(
|
||||
pack.getGeneratorProvider().newInstance(pack),
|
||||
this
|
||||
);
|
||||
this.pack = pack;
|
||||
this.seed = seed;
|
||||
|
||||
this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType());
|
||||
|
||||
instance.setGenerator(this.wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return wrapper.getGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
return pack.getBiomeProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return dimensionType.maxY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return dimensionType.minY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return instance;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
|
||||
import com.dfsek.terra.minestom.MinestomPlatform;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.instance.Instance;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
||||
public class TerraMinestomWorldBuilder {
|
||||
private final Instance instance;
|
||||
private ConfigPack pack;
|
||||
private long seed = new Random().nextLong();
|
||||
|
||||
private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; }
|
||||
|
||||
public static TerraMinestomWorldBuilder from(Instance instance) {
|
||||
return new TerraMinestomWorldBuilder(instance);
|
||||
}
|
||||
|
||||
public static TerraMinestomWorldBuilder builder() {
|
||||
return new TerraMinestomWorldBuilder(MinecraftServer.getInstanceManager().createInstanceContainer());
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder pack(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder packById(String id) {
|
||||
this.pack = MinestomPlatform
|
||||
.getInstance()
|
||||
.getConfigRegistry()
|
||||
.getByID(id)
|
||||
.orElseThrow();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder findPack(Function<CheckedRegistry<ConfigPack>, ConfigPack> fn) {
|
||||
this.pack = fn.apply(MinestomPlatform.getInstance().getConfigRegistry());
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder seed(long seed) {
|
||||
this.seed = seed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorld attach() {
|
||||
return new TerraMinestomWorld(instance, pack, seed);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user