start chunk save and load

pull/12/head
valoeghese 2020-02-27 23:27:00 +13:00
parent c66c09b8ac
commit 916fb380ea
3 changed files with 119 additions and 23 deletions

View File

@ -2,7 +2,7 @@ package com.github.halotroop.litecraft.logic;
import tk.valoeghese.sod.BinaryData;
public interface StoredData {
public interface DataStorage {
void read(BinaryData data);
void write(BinaryData data);
}

View File

@ -1,18 +1,24 @@
package com.github.halotroop.litecraft.types.block;
import java.util.*;
import com.github.hydos.ginger.engine.obj.ModelLoader;
import com.github.hydos.ginger.engine.render.models.TexturedModel;
public class Block
{
public static final Block AIR = new Block(new Properties().visible(false));
public static final Block DIRT = new Block("block/cubes/soil/dirt.png", new Properties());
public static final Block STONE = new Block("block/cubes/stone/basic/gneiss.png", new Properties());
public static final Block AIR = new Block(new Properties("air").visible(false));
public static final Block DIRT = new Block("block/cubes/soil/dirt.png", new Properties("dirt"));
public static final Block STONE = new Block("block/cubes/stone/basic/gneiss.png", new Properties("stone"));
public static class Properties
{ // add properties to this builder!
private boolean visible = true;
private boolean fullCube = true;
private final String identifier;
public Properties(String identifier)
{ this.identifier = identifier; }
public Properties fullCube(boolean fullCube)
{
@ -20,21 +26,22 @@ public class Block
return this;
}
public boolean isFullCube()
{ return fullCube; }
public boolean isVisible()
{ return visible; }
public Properties visible(boolean visible)
{
this.visible = visible;
return this;
}
}
public final TexturedModel model;
public final boolean visible;
private final boolean visible, fullCube;
public final String identifier;
public boolean isFullCube()
{ return this.fullCube; }
public boolean isVisible()
{ return this.visible; }
protected Block(Properties properties)
{ this((TexturedModel) null, properties); }
@ -46,5 +53,15 @@ public class Block
{
this.model = model;
this.visible = properties.visible;
this.fullCube = properties.fullCube;
this.identifier = properties.identifier;
IDENTIFIER_TO_BLOCK.put(this.identifier, this);
}
public static final Block getBlock(String identifier)
{
return IDENTIFIER_TO_BLOCK.get(identifier);
}
private static final Map<String, Block> IDENTIFIER_TO_BLOCK = new HashMap<>();
}

View File

@ -1,16 +1,20 @@
package com.github.halotroop.litecraft.world;
import java.util.*;
import java.util.function.ToIntFunction;
import com.github.halotroop.litecraft.logic.DataStorage;
import com.github.halotroop.litecraft.types.block.*;
import com.github.halotroop.litecraft.world.block.*;
import com.github.halotroop.litecraft.world.block.BlockRenderer;
import com.github.halotroop.litecraft.world.gen.WorldGenConstants;
import com.github.hydos.ginger.engine.math.vectors.Vector3f;
import com.github.hydos.ginger.engine.render.renderers.ObjectRenderer;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.longs.*;
import it.unimi.dsi.fastutil.objects.*;
import tk.valoeghese.sod.*;
public class Chunk implements BlockAccess, WorldGenConstants
public class Chunk implements BlockAccess, WorldGenConstants, DataStorage
{
/** @param x in-chunk x coordinate.
* @param y in-chunk y coordinate.
@ -18,7 +22,7 @@ public class Chunk implements BlockAccess, WorldGenConstants
* @return creates a long that represents a coordinate, for use as a key in maps. */
private static long posHash(int x, int y, int z)
{ return ((long) x & MAX_POS) | (((long) y & MAX_POS) << POS_SHIFT) | (((long) z & MAX_POS) << DOUBLE_SHIFT); }
List<BlockEntity> renderList;
private final Long2ObjectMap<Block> blocks = new Long2ObjectArrayMap<>();
private final Long2ObjectMap<BlockEntity> blockEntities = new Long2ObjectArrayMap<>();
@ -70,7 +74,7 @@ public class Chunk implements BlockAccess, WorldGenConstants
}
}
}
blockRenderer.render(renderList);
}
}
@ -91,7 +95,6 @@ public class Chunk implements BlockAccess, WorldGenConstants
this.blocks.put(hash, block);
if (this.render)
{
// TODO remove current block entity from game data when this class is integrated with the game
this.blockEntities.put(hash, new BlockEntity(block, new Vector3f(this.chunkStartX + x, this.chunkStartY + y, this.chunkStartZ + z)));
}
}
@ -109,10 +112,10 @@ public class Chunk implements BlockAccess, WorldGenConstants
long hash = posHash(x, y, z);
Block block = this.blocks.get(hash);
if (block.visible) this.blockEntities.put(hash, new BlockEntity(block,
new Vector3f(
this.chunkStartX + x,
this.chunkStartY + y,
this.chunkStartZ + z)));
new Vector3f(
this.chunkStartX + x,
this.chunkStartY + y,
this.chunkStartZ + z)));
}
}
}
@ -128,4 +131,80 @@ public class Chunk implements BlockAccess, WorldGenConstants
public boolean isFullyGenerated()
{ return this.fullyGenerated; }
@Override
public void read(BinaryData data)
{
Int2ObjectMap<Block> palette = new Int2ObjectArrayMap<>();
DataSection paletteData = data.get("palette");
boolean readInt = true; // whether the thing from the palette to be read is int
int intIdCache = 0;
for (Object o : paletteData)
{
if (readInt)
{
intIdCache = (int) o;
readInt = false;
}
else
{
palette.put(intIdCache, Block.getBlock((String) o));
readInt = true;
}
}
DataSection blockData = data.get("block");
long posHash = 0L; // also the index
for (int z = 0; z < CHUNK_SIZE; ++z) // z, y, x order for data saving and loading so we can use incremental pos hashes
{
for (int y = 0; y < CHUNK_SIZE; ++y)
{
for (int x = 0; x < CHUNK_SIZE; ++x)
{
this.blocks.put(posHash, palette.get(blockData.readInt((int) posHash)));
++posHash;
}
}
}
}
private int nextId; // for saving
@Override
public void write(BinaryData data)
{
Object2IntMap<Block> palette = new Object2IntArrayMap<>(); // block to int id
DataSection paletteData = new DataSection();
DataSection blockData = new DataSection();
long posHash = 0L;
nextId = 0;
ToIntFunction<Block> nextIdProvider = b -> nextId++;
for (int z = 0; z < CHUNK_SIZE; ++z) // z, y, x order for data saving and loading so we can use incremental pos hashes
{
for (int y = 0; y < CHUNK_SIZE; ++y)
{
for (int x = 0; x < CHUNK_SIZE; ++x)
{
Block b = this.blocks.get(posHash);
blockData.writeInt(palette.computeIntIfAbsent(b, nextIdProvider));
++posHash;
}
}
}
palette.forEach((b, id) -> {
paletteData.writeInt(id);
paletteData.writeString(b.identifier);
});
data.put("palette", paletteData);
data.put("block", blockData);
}
}