package electrosphere.server.terrain.manager; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import electrosphere.engine.Globals; import electrosphere.logger.LoggerInterface; import electrosphere.server.terrain.diskmap.ChunkDiskMap; import electrosphere.server.terrain.generation.interfaces.ChunkGenerator; /** * A job that fetches a chunk, either by generating it or by reading it from disk */ public class ChunkGenerationThread implements Runnable { /** * The number of milliseconds to wait per iteration */ static final int WAIT_TIME_MS = 2; /** * The maximum number of iterations to wait before failing */ static final int MAX_TIME_TO_WAIT = 10; /** * The chunk disk map */ ChunkDiskMap chunkDiskMap; /** * The chunk cache on the server */ ServerChunkCache chunkCache; /** * The chunk generator */ ChunkGenerator chunkGenerator; /** * The world x coordinate */ int worldX; /** * The world y coordinate */ int worldY; /** * The world z coordinate */ int worldZ; /** * The stride of the data */ int stride; /** * The work to do once the chunk is available */ Consumer onLoad; /** * Creates the chunk generation job * @param chunkDiskMap The chunk disk map * @param chunkCache The chunk cache on the server * @param chunkGenerator The chunk generator * @param worldX The world x coordinate * @param worldY The world y coordinate * @param worldZ The world z coordinate * @param stride The stride of the data * @param onLoad The work to do once the chunk is available */ public ChunkGenerationThread( ChunkDiskMap chunkDiskMap, ServerChunkCache chunkCache, ChunkGenerator chunkGenerator, int worldX, int worldY, int worldZ, int stride, Consumer onLoad ){ this.chunkDiskMap = chunkDiskMap; this.chunkCache = chunkCache; this.chunkGenerator = chunkGenerator; this.worldX = worldX; this.worldY = worldY; this.worldZ = worldZ; this.stride = stride; this.onLoad = onLoad; } @Override public void run() { ServerTerrainChunk chunk = null; int i = 0; try { while(chunk == null && i < MAX_TIME_TO_WAIT && Globals.threadManager.shouldKeepRunning()){ if(chunkCache.containsChunk(worldX, worldY, worldZ, stride)){ chunk = chunkCache.get(worldX, worldY, worldZ, stride); } else { //pull from disk if it exists if(chunkDiskMap != null){ if(chunkDiskMap.containsTerrainAtPosition(worldX, worldY, worldZ)){ chunk = chunkDiskMap.getTerrainChunk(worldX, worldY, worldZ); } } //generate if it does not exist if(chunk == null){ chunk = chunkGenerator.generateChunk(worldX, worldY, worldZ, stride); } if(chunk != null){ chunkCache.add(worldX, worldY, worldZ, stride, chunk); } } if(chunk == null){ try { TimeUnit.MILLISECONDS.sleep(WAIT_TIME_MS); } catch (InterruptedException e) { e.printStackTrace(); } } i++; } if(i >= MAX_TIME_TO_WAIT){ throw new Error("Failed to resolve chunk!"); } this.onLoad.accept(chunk); } catch (Error e){ LoggerInterface.loggerEngine.ERROR(e); } } }