Implemented TestChunkCodec and removed chunk generation from client
This commit is contained in:
parent
c9087e7215
commit
ef928b382f
@ -25,7 +25,7 @@ public class DataBuffer {
|
|||||||
@Override
|
@Override
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if (DataBuffer.this.position >= buffer.size()) return -1;
|
if (DataBuffer.this.position >= buffer.size()) return -1;
|
||||||
int result = buffer.getQuick(DataBuffer.this.position);
|
int result = buffer.getQuick(DataBuffer.this.position) & 0xFF;
|
||||||
++DataBuffer.this.position;
|
++DataBuffer.this.position;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -394,6 +394,24 @@ implements GenericChunk<
|
|||||||
report(null, tile);
|
report(null, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(TileData tile, int tag) {
|
||||||
|
addFarthest(tile);
|
||||||
|
|
||||||
|
int assignedTag = getIndexByTag(tag);
|
||||||
|
|
||||||
|
if (assignedTag == tag) return;
|
||||||
|
if (assignedTag == -1) {
|
||||||
|
throw new IllegalArgumentException("Tag " + tag + " already used by tile at index " + getIndexByTag(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
indicesByTag[tagsByIndex[size() - 1]] = -1;
|
||||||
|
tagsByIndex[size() - 1] = tag;
|
||||||
|
indicesByTag[tag] = size() - 1;
|
||||||
|
|
||||||
|
assert checkConsistency();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileData remove(int index) {
|
public TileData remove(int index) {
|
||||||
TileData previous = get(index); // checks index
|
TileData previous = get(index); // checks index
|
||||||
|
@ -26,6 +26,16 @@ extends GenericTileStack<
|
|||||||
@Override
|
@Override
|
||||||
public abstract void add(int index, TileData tile);
|
public abstract void add(int index, TileData tile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specified tile at the end of this stack assigning it the provided tag.
|
||||||
|
* This method is useful for copying stacks when preserving tags is necessary.
|
||||||
|
* @param tile the tile to add
|
||||||
|
* @param tag the tag to assign the new tile
|
||||||
|
* @throws IllegalArgumentException if this stack already contains a tile with the
|
||||||
|
* provided tag
|
||||||
|
*/
|
||||||
|
public abstract void load(TileData tile, int tag);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the tile at the specified position in this stack with the specified tile.
|
* Replaces the tile at the specified position in this stack with the specified tile.
|
||||||
* @param index index of the tile to replace
|
* @param index index of the tile to replace
|
||||||
|
@ -1,26 +1,59 @@
|
|||||||
package ru.windcorp.progressia.test;
|
package ru.windcorp.progressia.test;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import gnu.trove.map.TObjectIntMap;
|
||||||
|
import gnu.trove.map.hash.TObjectIntHashMap;
|
||||||
|
import ru.windcorp.jputil.functions.ThrowingConsumer;
|
||||||
import ru.windcorp.progressia.common.io.ChunkCodec;
|
import ru.windcorp.progressia.common.io.ChunkCodec;
|
||||||
import ru.windcorp.progressia.common.world.ChunkData;
|
import ru.windcorp.progressia.common.world.ChunkData;
|
||||||
import ru.windcorp.progressia.common.world.DecodingException;
|
import ru.windcorp.progressia.common.world.DecodingException;
|
||||||
import ru.windcorp.progressia.common.world.WorldData;
|
import ru.windcorp.progressia.common.world.WorldData;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockFace;
|
||||||
|
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||||
|
import ru.windcorp.progressia.common.world.tile.TileDataRegistry;
|
||||||
|
|
||||||
public class TestChunkCodec extends ChunkCodec {
|
public class TestChunkCodec extends ChunkCodec {
|
||||||
|
|
||||||
public TestChunkCodec() {
|
private static class Palette<E> {
|
||||||
super("Test:TestCodec", 0x00);
|
private final List<E> nidToElement = new ArrayList<>();
|
||||||
|
private final TObjectIntMap<E> elementToNid = new TObjectIntHashMap<>();
|
||||||
|
|
||||||
|
public void add(E element) {
|
||||||
|
if (elementToNid.containsKey(element)) return;
|
||||||
|
|
||||||
|
nidToElement.add(element);
|
||||||
|
elementToNid.put(element, elementToNid.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public E getByNid(int nid) {
|
||||||
public ChunkData decode(WorldData world, Vec3i position, InputStream data) throws DecodingException, IOException {
|
return nidToElement.get(nid);
|
||||||
ChunkData chunk = new ChunkData(position, world);
|
}
|
||||||
TestContent.generateChunk(chunk);
|
|
||||||
return chunk;
|
public int getNid(E element) {
|
||||||
|
return elementToNid.get(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return nidToElement.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestChunkCodec() {
|
||||||
|
super("Test:TestCodec", 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -28,9 +61,168 @@ public class TestChunkCodec extends ChunkCodec {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decoding
|
||||||
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(ChunkData chunk, OutputStream output) throws IOException {
|
public ChunkData decode(WorldData world, Vec3i position, InputStream inputStream) throws DecodingException, IOException {
|
||||||
// Do nothing. Heh.
|
DataInput input = new DataInputStream(inputStream);
|
||||||
|
|
||||||
|
BlockData[] blockPalette = readBlockPalette(input);
|
||||||
|
TileData[] tilePalette = readTilePalette(input);
|
||||||
|
|
||||||
|
ChunkData chunk = new ChunkData(position, world);
|
||||||
|
readBlocks(input, blockPalette, chunk);
|
||||||
|
readTiles(input, tilePalette, chunk);
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockData[] readBlockPalette(DataInput input) throws IOException {
|
||||||
|
BlockData[] palette = new BlockData[input.readInt()];
|
||||||
|
|
||||||
|
for (int nid = 0; nid < palette.length; ++nid) {
|
||||||
|
String id = input.readUTF();
|
||||||
|
palette[nid] = BlockDataRegistry.getInstance().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TileData[] readTilePalette(DataInput input) throws IOException {
|
||||||
|
TileData[] palette = new TileData[input.readInt()];
|
||||||
|
|
||||||
|
for (int nid = 0; nid < palette.length; ++nid) {
|
||||||
|
String id = input.readUTF();
|
||||||
|
palette[nid] = TileDataRegistry.getInstance().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readBlocks(DataInput input, BlockData[] blockPalette, ChunkData chunk) throws IOException {
|
||||||
|
try {
|
||||||
|
chunk.forEachBiC(guard(v -> {
|
||||||
|
chunk.setBlock(v, blockPalette[input.readInt()], false);
|
||||||
|
}));
|
||||||
|
} catch (UncheckedIOException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readTiles(DataInput input, TileData[] tilePalette, ChunkData chunk) throws IOException {
|
||||||
|
Vec3i bic = new Vec3i();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int xOrEndMarker = input.readByte() & 0xFF;
|
||||||
|
if (xOrEndMarker == 0xFF) break;
|
||||||
|
|
||||||
|
bic.set(xOrEndMarker, input.readByte() & 0xFF, input.readByte() & 0xFF);
|
||||||
|
BlockFace face = BlockFace.getFaces().get(input.readByte() & 0xFF);
|
||||||
|
|
||||||
|
int tiles = input.readByte() & 0xFF;
|
||||||
|
|
||||||
|
for (int i = 0; i < tiles; ++i) {
|
||||||
|
TileData tile = tilePalette[input.readInt()];
|
||||||
|
int tag = input.readInt();
|
||||||
|
chunk.getTiles(bic, face).load(tile, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encoding
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(ChunkData chunk, OutputStream outputStream) throws IOException {
|
||||||
|
|
||||||
|
DataOutput output = new DataOutputStream(outputStream);
|
||||||
|
|
||||||
|
Palette<BlockData> blockPalette = createBlockPalette(chunk);
|
||||||
|
Palette<TileData> tilePalette = createTilePalette(chunk);
|
||||||
|
|
||||||
|
writeBlockPalette(blockPalette, output);
|
||||||
|
writeTilePalette(tilePalette, output);
|
||||||
|
|
||||||
|
writeBlocks(chunk, blockPalette, output);
|
||||||
|
writeTiles(chunk, tilePalette, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Palette<BlockData> createBlockPalette(ChunkData chunk) {
|
||||||
|
Palette<BlockData> blockPalette = new Palette<>();
|
||||||
|
chunk.forEachBiC(v -> blockPalette.add(chunk.getBlock(v)));
|
||||||
|
return blockPalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Palette<TileData> createTilePalette(ChunkData chunk) {
|
||||||
|
Palette<TileData> tilePalette = new Palette<>();
|
||||||
|
chunk.forEachTile((ts, t) -> tilePalette.add(t));
|
||||||
|
return tilePalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeBlockPalette(Palette<BlockData> blockPalette, DataOutput output) throws IOException {
|
||||||
|
output.writeInt(blockPalette.size());
|
||||||
|
for (int nid = 0; nid < blockPalette.size(); ++nid) {
|
||||||
|
BlockData block = blockPalette.getByNid(nid);
|
||||||
|
output.writeUTF(block.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeTilePalette(Palette<TileData> tilePalette, DataOutput output) throws IOException {
|
||||||
|
output.writeInt(tilePalette.size());
|
||||||
|
for (int nid = 0; nid < tilePalette.size(); ++nid) {
|
||||||
|
TileData tile = tilePalette.getByNid(nid);
|
||||||
|
output.writeUTF(tile.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeBlocks(ChunkData chunk, Palette<BlockData> blockPalette, DataOutput output) throws IOException {
|
||||||
|
try {
|
||||||
|
chunk.forEachBiC(guard(v -> {
|
||||||
|
output.writeInt(blockPalette.getNid(chunk.getBlock(v)));
|
||||||
|
}));
|
||||||
|
} catch (UncheckedIOException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeTiles(ChunkData chunk, Palette<TileData> tilePalette, DataOutput output) throws IOException {
|
||||||
|
Vec3i bic = new Vec3i();
|
||||||
|
|
||||||
|
try {
|
||||||
|
chunk.forEachTileStack(guard(ts -> {
|
||||||
|
if (ts.isEmpty()) return;
|
||||||
|
|
||||||
|
ts.getBlockInChunk(bic);
|
||||||
|
output.writeByte(bic.x);
|
||||||
|
output.writeByte(bic.y);
|
||||||
|
output.writeByte(bic.z);
|
||||||
|
|
||||||
|
output.writeByte(ts.getFace().getId());
|
||||||
|
output.writeByte(ts.size());
|
||||||
|
|
||||||
|
for (int index = 0; index < ts.size(); ++index) {
|
||||||
|
output.writeInt(tilePalette.getNid(ts.get(index)));
|
||||||
|
output.writeInt(ts.getTagByIndex(index));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} catch (UncheckedIOException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
output.writeByte(0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <V> Consumer<V> guard(ThrowingConsumer<? super V, IOException> action) {
|
||||||
|
return v -> {
|
||||||
|
try {
|
||||||
|
action.accept(v);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user