use of io.xol.chunkstories.api.entity.interfaces.EntityUnsaveable in project chunkstories by Hugobros3.
the class ChunkHolderImplementation method compressChunkData.
/**
* This method is called assumming the chunk is well-locked
*/
private CompressedData compressChunkData(final CubicChunk chunk) {
final int changesTakenIntoAccount = chunk.compr_uncomittedBlockModifications.get();
// Stage 1: Compress the actual voxel data
byte[] voxelCompressedData;
if (!chunk.isAirChunk()) {
// Heuristic value for the size of the buffer: fixed voxel size + factor of components & entities
// + chunk.voxelComponents.size() * 1024 + chunk.localEntities.size() * 2048;
int uncompressedStuffBufferSize = 32 * 32 * 32 * 4;
ByteBuffer uncompressedStuff = MemoryUtil.memAlloc(uncompressedStuffBufferSize);
uncompressedStuff.asIntBuffer().put(chunk.chunkVoxelData);
// uncompressedStuff.flip();
ByteBuffer compressedStuff = MemoryUtil.memAlloc(uncompressedStuffBufferSize + 2048);
LZ4Compressor compressor = factory.fastCompressor();
compressor.compress(uncompressedStuff, compressedStuff);
// No longer need that buffer
MemoryUtil.memFree(uncompressedStuff);
// Make a Java byte[] array to put the final stuff in
voxelCompressedData = new byte[compressedStuff.position()];
compressedStuff.flip();
compressedStuff.get(voxelCompressedData);
// No longer need that buffer either
MemoryUtil.memFree(compressedStuff);
} else {
// Just use a symbolic null here
voxelCompressedData = null;
}
// Stage 2: Take care of the voxel components
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream daos = new DataOutputStream(baos);
// ByteBuffer smallBuffer = MemoryUtil.memAlloc(4096);
// byte[] smallArray = new byte[4096];
// ByteBufferOutputStream bbos = new ByteBufferOutputStream(smallBuffer);
ByteArrayOutputStream bbos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bbos);
try {
// For all cells that have components
for (CellComponentsHolder voxelComponents : chunk.allCellComponents.values()) {
// Write a 1 then their in-chunk index
daos.writeByte((byte) 0x01);
daos.writeInt(voxelComponents.getIndex());
// For all components in this cell
for (Entry<String, VoxelComponent> entry : voxelComponents.all()) {
// Write component name
daos.writeUTF(entry.getKey());
// Push the component in the temporary buffer
entry.getValue().push(region.handler, dos);
// smallBuffer.flip();
byte[] bytesPushed = bbos.toByteArray();
bbos.reset();
// Write how many bytes the temporary buffer now contains
// int bytesPushed = smallBuffer.limit();
daos.writeShort(bytesPushed.length);
// Get those bytes as an array then write it in the compressed stuff
// smallBuffer.get(smallArray);
daos.write(bytesPushed, 0, bytesPushed.length);
// Reset the temporary buffer
// smallBuffer.clear();
}
daos.writeUTF("\n");
}
// Write the final 00, so to be clear we are done with voxel components
daos.writeByte((byte) 0x00);
// Since we output to a local buffer, any failure is viewed as catastrophic
} catch (IOException e) {
assert false;
}
// Extract the byte array from the baos
byte[] voxelComponentsData = baos.toByteArray();
// MemoryUtil.memFree(smallBuffer);
// Stage 3: Compress entities
baos.reset();
for (Entity entity : chunk.localEntities) {
// Don't save controllable entities
if (entity.exists() && !(entity instanceof EntityUnsaveable && !((EntityUnsaveable) entity).shouldSaveIntoRegion())) {
EntitySerializer.writeEntityToStream(daos, region.handler, entity);
}
}
EntitySerializer.writeEntityToStream(daos, region.handler, null);
byte[] entityData = baos.toByteArray();
// Remove whatever modifications existed when the method started, this is for avoiding concurrent modifications not being taken into account
chunk.compr_uncomittedBlockModifications.addAndGet(-changesTakenIntoAccount);
return new CompressedData(voxelCompressedData, voxelComponentsData, entityData);
}
Aggregations