Renderer/src/main/java/electrosphere/server/block/manager/ServerBlockManager.java
austin e8c38584fa
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
fix block meshes
2024-11-24 11:16:31 -05:00

197 lines
6.4 KiB
Java

package electrosphere.server.block.manager;
import electrosphere.client.block.BlockChunkCache;
import electrosphere.client.block.BlockChunkData;
import electrosphere.engine.Globals;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.server.block.diskmap.ServerBlockChunkDiskMap;
import electrosphere.util.annotation.Exclude;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import org.joml.Vector3i;
/**
* Provides an interface for the server to query information about block chunks
*/
public class ServerBlockManager {
/**
* The number of threads for chunk generation
*/
public static final int GENERATION_THREAD_POOL_SIZE = 2;
/**
* The parent world data
*/
ServerWorldData parent;
/**
* The cache of chunks
*/
@Exclude
BlockChunkCache chunkCache = new BlockChunkCache();
//The map of chunk position <-> file on disk containing chunk data
ServerBlockChunkDiskMap chunkDiskMap = null;
/**
* The threadpool for chunk generation
*/
@Exclude
static final ExecutorService chunkExecutorService = Executors.newFixedThreadPool(GENERATION_THREAD_POOL_SIZE);
/**
* Constructor
*/
public ServerBlockManager(
ServerWorldData parent
){
this.parent = parent;
}
ServerBlockManager(){
}
/**
* Inits the chunk disk map
*/
public void generate(){
this.chunkDiskMap = ServerBlockChunkDiskMap.init();
}
/**
* Saves the block cache backing this manager to a save file
* @param saveName The name of the save
*/
public void save(String saveName){
//for each chunk, save via disk map
for(BlockChunkData chunk : this.chunkCache.getContents()){
chunkDiskMap.saveToDisk(chunk);
}
//save disk map itself
if(chunkDiskMap != null){
chunkDiskMap.save();
}
}
/**
* Loads a block manager from a save file
* @param saveName The name of the save
*/
public void load(String saveName){
//load chunk disk map
chunkDiskMap = ServerBlockChunkDiskMap.init(saveName);
}
/**
* Evicts all cached chunks
*/
public void evictAll(){
this.chunkCache.clear();
}
/**
* Performs logic once a server chunk is available
* @param worldX The world x position
* @param worldY The world y position
* @param worldZ The world z position
* @return The BlockChunkData
*/
public BlockChunkData getChunk(int worldX, int worldY, int worldZ){
Globals.profiler.beginAggregateCpuSample("ServerBlockManager.getChunk");
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
BlockChunkData returnedChunk = null;
if(chunkCache.containsChunk(worldX,worldY,worldZ,BlockChunkData.LOD_FULL_RES)){
returnedChunk = chunkCache.get(worldX,worldY,worldZ, BlockChunkData.LOD_FULL_RES);
} else {
//pull from disk if it exists
if(chunkDiskMap != null){
if(chunkDiskMap.containsBlocksAtPosition(worldX, worldY, worldZ)){
returnedChunk = chunkDiskMap.getBlockChunk(worldX, worldY, worldZ);
}
}
//generate if it does not exist
if(returnedChunk == null){
returnedChunk = BlockChunkData.allocate();
returnedChunk.setWorldX(worldX);
returnedChunk.setWorldY(worldY);
returnedChunk.setWorldZ(worldZ);
returnedChunk.setHomogenousValue(0);
if(worldX == 0 && worldY == 0 && worldZ == 0){
returnedChunk.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS);
for(int x = 3; x < 16; x++){
for(int y = 8; y < 16; y++){
for(int z = 3; z < 16; z++){
returnedChunk.setType(x, y, z, 1);
}
}
}
}
}
this.chunkCache.add(worldX, worldY, worldZ, BlockChunkData.LOD_FULL_RES, returnedChunk);
}
Globals.profiler.endCpuSample();
return returnedChunk;
}
/**
* Performs logic once a server chunk is available
* @param worldX The world x position
* @param worldY The world y position
* @param worldZ The world z position
* @param stride The stride of the data
* @param onLoad The logic to run once the chunk is available
*/
public void getChunkAsync(int worldX, int worldY, int worldZ, int stride, Consumer<BlockChunkData> onLoad){
Globals.profiler.beginAggregateCpuSample("ServerBlockManager.getChunkAsync");
chunkExecutorService.submit(new ServerBlockChunkGenerationThread(chunkDiskMap, chunkCache, worldX, worldY, worldZ, stride, onLoad));
Globals.profiler.endCpuSample();
}
/**
* Saves a given position's chunk to disk.
* Uses the current global save name
* @param position The position to save
*/
public void savePositionToDisk(Vector3i position){
if(chunkDiskMap != null){
chunkDiskMap.saveToDisk(getChunk(position.x, position.y, position.z));
}
}
/**
* Applies an edit to a block at a given location
* @param worldPos The world coordinates of the chunk to modify
* @param voxelPos The voxel coordinates of the voxel to modify
* @param type The type of block
* @param metadata The metadata of the block
*/
public void editBlockAtLocationToValue(Vector3i worldPos, Vector3i voxelPos, short type, short metadata){
if(chunkCache.containsChunk(worldPos.x,worldPos.y,worldPos.z,BlockChunkData.LOD_FULL_RES)){
BlockChunkData chunk = chunkCache.get(worldPos.x,worldPos.y,worldPos.z, BlockChunkData.LOD_FULL_RES);
chunk.setType(voxelPos.x, voxelPos.y, voxelPos.z, type);
chunk.setType(voxelPos.x, voxelPos.y, voxelPos.z, metadata);
}
}
/**
* Sets the parent world data of this manager
* @param serverWorldData The parent world data
*/
public void setParent(ServerWorldData serverWorldData){
this.parent = serverWorldData;
}
/**
* Closes the generation threadpool
*/
public void closeThreads(){
chunkExecutorService.shutdownNow();
}
}