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
|
||||
public int read() throws IOException {
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
@ -394,6 +394,24 @@ implements GenericChunk<
|
||||
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
|
||||
public TileData remove(int index) {
|
||||
TileData previous = get(index); // checks index
|
||||
|
@ -26,6 +26,16 @@ extends GenericTileStack<
|
||||
@Override
|
||||
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.
|
||||
* @param index index of the tile to replace
|
||||
|
@ -1,26 +1,59 @@
|
||||
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.InputStream;
|
||||
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 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.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.DecodingException;
|
||||
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 TestChunkCodec() {
|
||||
super("Test:TestCodec", 0x00);
|
||||
private static class Palette<E> {
|
||||
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 ChunkData decode(WorldData world, Vec3i position, InputStream data) throws DecodingException, IOException {
|
||||
ChunkData chunk = new ChunkData(position, world);
|
||||
TestContent.generateChunk(chunk);
|
||||
return chunk;
|
||||
public E getByNid(int nid) {
|
||||
return nidToElement.get(nid);
|
||||
}
|
||||
|
||||
public int getNid(E element) {
|
||||
return elementToNid.get(element);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return nidToElement.size();
|
||||
}
|
||||
}
|
||||
|
||||
public TestChunkCodec() {
|
||||
super("Test:TestCodec", 0x00);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -28,9 +61,168 @@ public class TestChunkCodec extends ChunkCodec {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decoding
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void encode(ChunkData chunk, OutputStream output) throws IOException {
|
||||
// Do nothing. Heh.
|
||||
public ChunkData decode(WorldData world, Vec3i position, InputStream inputStream) throws DecodingException, IOException {
|
||||
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