continue work on janky pregenerator

This commit is contained in:
dfsek 2021-01-04 01:29:51 -07:00
parent ee093397d3
commit 75fbda5a9f
10 changed files with 265 additions and 32 deletions

View File

@ -160,4 +160,9 @@ public class Location implements Cloneable {
public Vector3 toVector() {
return vector.clone();
}
@Override
public String toString() {
return "(" + getX() + ", " + getY() + ", " + getZ() + ")";
}
}

View File

@ -152,8 +152,10 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
Palette<BlockData> stairPalette = stairs.get(down.getMaterial());
if(stairPalette != null) {
BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone();
Stairs stairNew = (Stairs) stair;
if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part.
if(stair instanceof Stairs) {
Stairs stairNew = (Stairs) stair;
if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part.
}
}
}
BlockData slab = slabs.getOrDefault(down.getMaterial(), blank).get(0, block.getBlockX(), block.getBlockZ());
@ -171,9 +173,11 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
Palette<BlockData> stairPalette = stairs.get(up.getMaterial());
if(stairPalette != null) {
BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone();
Stairs stairNew = (Stairs) stair.clone();
stairNew.setHalf(Bisected.Half.TOP);
if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part.
if(stair instanceof Stairs) {
Stairs stairNew = (Stairs) stair.clone();
stairNew.setHalf(Bisected.Half.TOP);
if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part.
}
}
}
BlockData slab = slabs.getOrDefault(up.getMaterial(), blank).get(0, block.getBlockX(), block.getBlockZ()).clone();

View File

@ -0,0 +1,17 @@
package com.dfsek.terra;
import net.querz.mca.MCAUtil;
public final class DirectUtils {
/**
* Compute long region ID from chunk coords
*
* @param x X
* @param z Z
* @return Region IS
*/
public static long regionID(int x, int z) {
return (((long) MCAUtil.chunkToRegion(x)) << 32) | (MCAUtil.chunkToRegion(z) & 0xffffffffL);
}
}

View File

@ -15,6 +15,18 @@ public class Data implements BlockData, MaterialData {
this.data.putString("Name", noProp);
}
public Data(CompoundTag tag) {
if(tag == null) {
this.data = new CompoundTag();
data.putString("Name", "minecraft:air");
} else {
this.data = tag;
}
String id = data.getString("Name");
if(id.contains("[")) noProp = id.substring(0, id.indexOf('[')); // Strip properties for now TODO: actually do properties lol
else noProp = id;
}
@Override
public MaterialData getMaterial() {
return this;
@ -68,4 +80,15 @@ public class Data implements BlockData, MaterialData {
public CompoundTag getHandle() {
return data;
}
@Override
public int hashCode() {
return noProp.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Data)) return false;
return ((Data) obj).noProp.equals(noProp);
}
}

View File

@ -0,0 +1,85 @@
package com.dfsek.terra.platform;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.MaterialData;
import com.dfsek.terra.api.platform.block.state.BlockState;
import net.jafama.FastMath;
public class DirectBlock implements Block {
private final DirectWorld world;
private final Vector3 pos;
public DirectBlock(DirectWorld world, Vector3 pos) {
this.world = world;
this.pos = pos;
}
@Override
public void setBlockData(BlockData data, boolean physics) {
world.compute(FastMath.floorDiv(pos.getBlockX(), 16), FastMath.floorDiv(pos.getBlockZ(), 16)).setBlockStateAt(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), ((Data) data).getHandle(), false);
}
@Override
public BlockData getBlockData() {
return new Data(world.getData(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()));
}
@Override
public BlockState getState() {
return new DirectBlockState();
}
@Override
public Block getRelative(BlockFace face) {
return world.getBlockAt(pos.getBlockX() + face.getModX(), pos.getBlockY() + face.getModY(), pos.getBlockZ() + face.getModZ());
}
@Override
public Block getRelative(BlockFace face, int len) {
return world.getBlockAt(pos.getBlockX() + face.getModX() * len, pos.getBlockY() + face.getModY() * len, pos.getBlockZ() + face.getModZ() * len);
}
@Override
public boolean isEmpty() {
return getBlockData().getAsString().equals("minecraft:air");
}
@Override
public Location getLocation() {
return pos.toLocation(world);
}
@Override
public MaterialData getType() {
return new Data(world.getData(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()));
}
@Override
public int getX() {
return pos.getBlockX();
}
@Override
public int getZ() {
return pos.getBlockY();
}
@Override
public int getY() {
return pos.getBlockY();
}
@Override
public boolean isPassable() {
return false;
}
@Override
public Object getHandle() {
return world;
}
}

View File

@ -0,0 +1,42 @@
package com.dfsek.terra.platform;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.state.BlockState;
public class DirectBlockState implements BlockState {
@Override
public Block getBlock() {
return null;
}
@Override
public int getX() {
return 0;
}
@Override
public int getY() {
return 0;
}
@Override
public int getZ() {
return 0;
}
@Override
public BlockData getBlockData() {
return null;
}
@Override
public boolean update(boolean applyPhysics) {
return false;
}
@Override
public Object getHandle() {
return null;
}
}

View File

@ -1,20 +1,25 @@
package com.dfsek.terra.platform;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.World;
import net.querz.mca.Chunk;
import net.querz.nbt.tag.CompoundTag;
import org.jetbrains.annotations.NotNull;
public class DirectChunkData implements ChunkGenerator.ChunkData {
public class DirectChunkData implements ChunkGenerator.ChunkData, com.dfsek.terra.api.platform.world.Chunk {
private final Chunk delegate;
private final int offX;
private final int offZ;
private final DirectWorld world;
private final int x;
private final int z;
public DirectChunkData(Chunk delegate, int offX, int offZ) {
public DirectChunkData(Chunk delegate, DirectWorld world, int x, int z) {
this.delegate = delegate;
this.offX = offX;
this.offZ = offZ;
this.world = world;
this.x = x;
this.z = z;
}
@Override
@ -38,4 +43,24 @@ public class DirectChunkData implements ChunkGenerator.ChunkData {
if(tag == null) return new Data("minecraft:air");
return new Data(tag.getString("Name"));
}
@Override
public int getX() {
return x;
}
@Override
public int getZ() {
return z;
}
@Override
public World getWorld() {
return world;
}
@Override
public Block getBlock(int x, int y, int z) {
return new DirectBlock(world, new Vector3(x + (this.x << 4), y, z + (this.z << 4)));
}
}

View File

@ -1,6 +1,8 @@
package com.dfsek.terra.platform;
import com.dfsek.terra.DirectUtils;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.Chunk;
@ -8,13 +10,20 @@ import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.entity.Entity;
import com.dfsek.terra.api.platform.world.entity.EntityType;
import net.jafama.FastMath;
import net.querz.mca.MCAFile;
import net.querz.mca.MCAUtil;
import net.querz.nbt.tag.CompoundTag;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class DirectWorld implements World {
private final long seed;
private final GenWrapper generator;
private final Map<Long, MCAFile> files = new HashMap<>();
public DirectWorld(long seed, GenWrapper generator) {
this.seed = seed;
@ -53,7 +62,10 @@ public class DirectWorld implements World {
@Override
public Chunk getChunkAt(int x, int z) {
return null;
MCAFile file = compute(x, z);
net.querz.mca.Chunk chunk = file.getChunk(x, z);
if(chunk == null) chunk = net.querz.mca.Chunk.newChunk();
return new DirectChunkData(chunk, this, x, z);
}
@Override
@ -63,12 +75,12 @@ public class DirectWorld implements World {
@Override
public Block getBlockAt(int x, int y, int z) {
return null;
return new DirectBlock(this, new Vector3(x, y, z));
}
@Override
public Block getBlockAt(Location l) {
return null;
return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ());
}
@Override
@ -85,4 +97,16 @@ public class DirectWorld implements World {
public Object getHandle() {
return generator;
}
public MCAFile compute(int x, int z) {
return files.computeIfAbsent(DirectUtils.regionID(x, z), k -> new MCAFile(MCAUtil.chunkToRegion(x), MCAUtil.chunkToRegion(z)));
}
public CompoundTag getData(int x, int y, int z) {
return compute(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)).getBlockStateAt(x, y, z);
}
public Map<Long, MCAFile> getFiles() {
return files;
}
}

View File

@ -4,6 +4,7 @@ import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.MaterialData;
import com.dfsek.terra.api.platform.world.Tree;
import java.util.Collections;
import java.util.Random;
import java.util.Set;
@ -20,6 +21,6 @@ public class RawTree implements Tree { // TODO: implement
@Override
public Set<MaterialData> getSpawnable() {
return null;
return Collections.emptySet();
}
}

View File

@ -1,26 +1,28 @@
package com.dfsek.terra.region;
import com.dfsek.terra.StandalonePlugin;
import com.dfsek.terra.api.platform.generator.ChunkGenerator;
import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.generation.MasterChunkGenerator;
import com.dfsek.terra.generation.math.SamplerCache;
import com.dfsek.terra.platform.DirectChunkData;
import com.dfsek.terra.platform.DirectWorld;
import com.dfsek.terra.platform.GenWrapper;
import net.querz.mca.Chunk;
import com.dfsek.terra.population.CavePopulator;
import com.dfsek.terra.population.FloraPopulator;
import com.dfsek.terra.population.OrePopulator;
import com.dfsek.terra.population.StructurePopulator;
import com.dfsek.terra.population.TreePopulator;
import net.querz.mca.MCAFile;
import net.querz.mca.MCAUtil;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Generator {
private final Map<Long, MCAFile> files = new HashMap<>();
private final long seed;
public Generator(long seed) {
@ -29,7 +31,7 @@ public class Generator {
public void generate() throws IOException {
int rad = 50;
int rad = 25;
StandalonePlugin plugin = new StandalonePlugin();
plugin.load();
@ -38,26 +40,31 @@ public class Generator {
MasterChunkGenerator generator = new MasterChunkGenerator(plugin.getRegistry().get("DEFAULT"), plugin, new SamplerCache(plugin));
GenWrapper wrapper = new GenWrapper(generator);
FloraPopulator floraPopulator = new FloraPopulator(plugin);
StructurePopulator structurePopulator = new StructurePopulator(plugin);
TreePopulator treePopulator = new TreePopulator(plugin);
OrePopulator orePopulator = new OrePopulator(plugin);
CavePopulator cavePopulator = new CavePopulator(plugin);
int count = 0;
List<Double> times = new GlueList<>();
DirectWorld world = new DirectWorld(seed, wrapper);
for(int cx = -rad; cx <= rad; cx++) {
for(int cz = -rad; cz <= rad; cz++) {
long start = System.nanoTime();
long key = (((long) MCAUtil.chunkToRegion(cx)) << 32) | (MCAUtil.chunkToRegion(cz) & 0xffffffffL);
DirectChunkData chunkData = (DirectChunkData) world.getChunkAt(cx, cz);
generator.generateChunkData(world, null, cx, cz, chunkData);
int finalCx = cx;
int finalCz = cz;
MCAFile file = files.computeIfAbsent(key, k -> new MCAFile(MCAUtil.chunkToRegion(finalCx), MCAUtil.chunkToRegion(finalCz)));
cavePopulator.populate(world, new FastRandom(MathUtil.getCarverChunkSeed(cx, cz, seed)), chunkData);
structurePopulator.populate(world, new FastRandom(MathUtil.getCarverChunkSeed(cx, cz, seed)), chunkData);
orePopulator.populate(world, new FastRandom(MathUtil.getCarverChunkSeed(cx, cz, seed)), chunkData);
floraPopulator.populate(world, new FastRandom(MathUtil.getCarverChunkSeed(cx, cz, seed)), chunkData);
treePopulator.populate(world, new FastRandom(MathUtil.getCarverChunkSeed(cx, cz, seed)), chunkData);
Chunk chunk = Chunk.newChunk();
ChunkGenerator.ChunkData chunkData = new DirectChunkData(chunk, cx, cz);
generator.generateChunkData(new DirectWorld(seed, wrapper), null, cx, cz, chunkData);
file.setChunk(cx, cz, chunk);
long end = System.nanoTime() - start;
count++;
@ -75,7 +82,7 @@ public class Generator {
}
}
for(Map.Entry<Long, MCAFile> entry : files.entrySet()) {
for(Map.Entry<Long, MCAFile> entry : world.getFiles().entrySet()) {
entry.getValue().cleanupPalettesAndBlockStates();
int x = (int) (entry.getKey() >> 32);
int z = (int) (long) entry.getKey();