Renderer/src/main/java/electrosphere/server/fluid/diskmap/FluidDiskMap.java
austin 72e6a6d0cb
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
server fluid storage conversion
2024-11-30 13:23:20 -05:00

206 lines
7.7 KiB
Java

package electrosphere.server.fluid.diskmap;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterOutputStream;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.fluid.manager.ServerFluidChunk;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.util.FileUtils;
/**
* An interface for accessing the disk map of chunk information
*/
public class FluidDiskMap {
//The map of world position+chunk type to the file that actually houses that information
Map<String,String> worldPosFileMap = new HashMap<String,String>();
/**
* Constructor
*/
public FluidDiskMap(){
}
/**
* Gets a key for a given chunk file based on a world coordinate
* @param worldX The x component
* @param worldY The y component
* @param worldZ The z component
* @return The key
*/
private static String getFluidChunkKey(int worldX, int worldY, int worldZ){
return worldX + "_" + worldY + "_" + worldZ + "f";
}
/**
* Initializes a diskmap based on a given save name
* @param saveName The save name
*/
public void init(String saveName){
LoggerInterface.loggerEngine.DEBUG("INIT CHUNK MAP " + saveName);
if(FileUtils.getSaveFile(saveName, "chunk.map").exists()){
worldPosFileMap = FileUtils.loadObjectFromSavePath(saveName, "fluid.map", Map.class);
LoggerInterface.loggerEngine.DEBUG("POS FILE MAP: " + worldPosFileMap.keySet());
} else {
worldPosFileMap = new HashMap<String,String>();
}
}
/**
* Saves the disk map to disk
*/
public void save(){
FileUtils.serializeObjectToSavePath(Globals.currentSave.getName(), "fluid.map", worldPosFileMap);
}
/**
* Checks if the map contains a given chunk position
* @param worldX The x component
* @param worldY The y component
* @param worldZ The z component
* @return True if the map contains the chunk, false otherwise
*/
public boolean containsFluidAtPosition(int worldX, int worldY, int worldZ){
return worldPosFileMap.containsKey(getFluidChunkKey(worldX, worldY, worldZ));
}
/**
* Gets the server fluid chunk from disk if it exists, otherwise returns null
* @param worldX The x coordinate
* @param worldY The y coordinate
* @param worldZ The z coordinate
* @return The server fluid chunk if it exists, null otherwise
*/
public ServerFluidChunk getFluidChunk(int worldX, int worldY, int worldZ){
LoggerInterface.loggerEngine.INFO("Load chunk " + worldX + " " + worldY + " " + worldZ);
ServerFluidChunk rVal = null;
if(containsFluidAtPosition(worldX, worldY, worldZ)){
//read file
String fileName = worldPosFileMap.get(getFluidChunkKey(worldX, worldY, worldZ));
byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSave.getName(), fileName);
//decompress
byte[] rawData = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
InflaterOutputStream inflaterInputStream = new InflaterOutputStream(out);
try {
inflaterInputStream.write(rawDataCompressed);
inflaterInputStream.flush();
inflaterInputStream.close();
rawData = out.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//parse
if(rawData != null){
ByteBuffer buffer = ByteBuffer.wrap(rawData);
FloatBuffer floatView = buffer.asFloatBuffer();
int DIM = ServerTerrainChunk.CHUNK_DIMENSION;
rVal = new ServerFluidChunk(worldX, worldY, worldZ);
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
rVal.setWeight(x, y, z, floatView.get());
}
}
}
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
rVal.setVelocityX(x, y, z, floatView.get());
}
}
}
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
rVal.setVelocityY(x, y, z, floatView.get());
}
}
}
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
rVal.setVelocityZ(x, y, z, floatView.get());
}
}
}
}
}
return rVal;
}
/**
* Saves a fluid chunk to disk
* @param fluidChunk The fluid chunk
*/
public void saveToDisk(ServerFluidChunk fluidChunk){
LoggerInterface.loggerEngine.DEBUG("Save to disk: " + fluidChunk.getWorldX() + " " + fluidChunk.getWorldY() + " " + fluidChunk.getWorldZ());
//get the file name for this chunk
String fileName = null;
String chunkKey = getFluidChunkKey(fluidChunk.getWorldX(),fluidChunk.getWorldY(),fluidChunk.getWorldZ());
if(worldPosFileMap.containsKey(chunkKey)){
fileName = worldPosFileMap.get(chunkKey);
} else {
fileName = chunkKey + ".dat";
}
//generate binary for the file
int DIM = ServerTerrainChunk.CHUNK_DIMENSION;
ByteBuffer buffer = ByteBuffer.allocate(DIM * DIM * DIM * 4 + DIM * DIM * DIM * 4 + DIM * DIM * DIM * 4 + DIM * DIM * DIM * 4);
FloatBuffer floatView = buffer.asFloatBuffer();
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
floatView.put(fluidChunk.getWeight(x, y, z));
}
}
}
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
floatView.put(fluidChunk.getVelocityX(x,y,z));
}
}
}
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
floatView.put(fluidChunk.getVelocityY(x,y,z));
}
}
}
for(int x = 0; x < DIM; x++){
for(int y = 0; y < DIM; y++){
for(int z = 0; z < DIM; z++){
floatView.put(fluidChunk.getVelocityZ(x,y,z));
}
}
}
//compress
ByteArrayOutputStream out = new ByteArrayOutputStream();
DeflaterOutputStream deflaterInputStream = new DeflaterOutputStream(out);
try {
deflaterInputStream.write(buffer.array());
deflaterInputStream.flush();
deflaterInputStream.close();
//write to disk
FileUtils.saveBinaryToSavePath(Globals.currentSave.getName(), fileName, out.toByteArray());
//save to the map of filenames
worldPosFileMap.put(chunkKey,fileName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}