diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java index 7365ef00c..a51998ade 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java @@ -9,11 +9,11 @@ import java.util.concurrent.atomic.AtomicInteger; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.PosToGenerateContainer; import com.seibel.lod.render.LodRenderer; import com.seibel.lod.util.DetailDistanceUtil; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; import com.seibel.lod.wrappers.MinecraftWrapper; @@ -26,51 +26,47 @@ import net.minecraftforge.common.WorldWorkerManager; * A singleton that handles all long distance LOD world generation. * * @author James Seibel - * @version 8-24-2021 + * @version 9-25-2021 */ public class LodWorldGenerator { public MinecraftWrapper mc = MinecraftWrapper.INSTANCE; - - /** - * This holds the thread used to generate new LODs off the main thread. - */ + + /** This holds the thread used to generate new LODs off the main thread. */ private ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " world generator")); - - /** - * we only want to queue up one generator thread at a time - */ + + /** we only want to queue up one generator thread at a time */ private boolean generatorThreadRunning = false; - + /** - * how many chunks to generate outside of the player's view distance at one + * How many chunks to generate outside of the player's view distance at one * time. (or more specifically how many requests to make at one time). I * multiply by 8 to make sure there is always a buffer of chunk requests, to * make sure the CPU is always busy and we can generate LODs as quickly as * possible. */ public int maxChunkGenRequests; - + /** * This keeps track of how many chunk generation requests are on going. This is * to limit how many chunks are queued at once. To prevent chunks from being * generated for a long time in an area the player is no longer in. */ public AtomicInteger numberOfChunksWaitingToGenerate = new AtomicInteger(0); - - public Set positionWaitingToBeGenerated = new HashSet<>(); - + + public Set positionsWaitingToBeGenerated = new HashSet<>(); + /** * Singleton copy of this object */ public static final LodWorldGenerator INSTANCE = new LodWorldGenerator(); - - + + private LodWorldGenerator() { - + } - + /** * Queues up LodNodeGenWorkers for the given lodDimension. * @@ -80,15 +76,15 @@ public class LodWorldGenerator public void queueGenerationRequests(LodDimension lodDim, LodRenderer renderer, LodBuilder lodBuilder) { if (LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get() != DistanceGenerationMode.NONE - && !generatorThreadRunning - && mc.hasSingleplayerServer()) + && !generatorThreadRunning + && mc.hasSingleplayerServer()) { // the thread is now running, don't queue up another thread generatorThreadRunning = true; - + // just in case the config changed maxChunkGenRequests = LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get() * 8; - + Thread generatorThread = new Thread(() -> { try @@ -96,103 +92,99 @@ public class LodWorldGenerator // round the player's block position down to the nearest chunk BlockPos int playerPosX = mc.getPlayer().blockPosition().getX(); int playerPosZ = mc.getPlayer().blockPosition().getZ(); - - // if we don't have a full number of chunks to generate in chunksToGen - // we can top it off from this reserve - - + + //=======================================// - // create the generation Request objects // + // fill in positionsWaitingToBeGenerated // //=======================================// - + ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); - + PosToGenerateContainer posToGenerate = lodDim.getDataToGenerate( maxChunkGenRequests, playerPosX, playerPosZ); - //System.out.println(posToGenerate); - //here we prepare two sorted set - //the first contains the near pos to render - //the second contain the far pos to render + + byte detailLevel; int posX; int posZ; - boolean nearOrFar = true; - boolean stopSwitch = false; - int near = 0; - int far = 0; - - for (int index = 0; index < posToGenerate.getNumberOfPos(); index++) + int nearIndex = 0; + int farIndex = 0; + + for (int i = 0; i < posToGenerate.getNumberOfPos(); i++) { - if (posToGenerate.getNthDetail(near, true) != 0 && near < posToGenerate.getNumberOfNearPos()) + // I wish there was a way to compress this code, but I'm not aware of + // a easy way to do so. + + // add the near positions + if (posToGenerate.getNthDetail(nearIndex, true) != 0 && nearIndex < posToGenerate.getNumberOfNearPos()) { - detailLevel = (byte) (posToGenerate.getNthDetail(near, true) - 1); - posX = posToGenerate.getNthPosX(near, true); - posZ = posToGenerate.getNthPosZ(near, true); - near++; + detailLevel = (byte) (posToGenerate.getNthDetail(nearIndex, true) - 1); + posX = posToGenerate.getNthPosX(nearIndex, true); + posZ = posToGenerate.getNthPosZ(nearIndex, true); + nearIndex++; + ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel, posX), LevelPosUtil.getChunkPos(detailLevel, posZ)); if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) { // prevent generating the same chunk multiple times - if (positionWaitingToBeGenerated.contains(chunkPos)) - { + if (positionsWaitingToBeGenerated.contains(chunkPos)) continue; - } } - - // don't add null chunkPos (which shouldn't happen anyway) - // or add more to the generation queue - if (chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) - continue; - - positionWaitingToBeGenerated.add(chunkPos); + + // don't add more to the generation queue then allowed + if (numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) + break; + + positionsWaitingToBeGenerated.add(chunkPos); numberOfChunksWaitingToGenerate.addAndGet(1); LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DetailDistanceUtil.getDistanceGenerationMode(detailLevel), lodBuilder, lodDim, serverWorld); WorldWorkerManager.addWorker(genWorker); } - - - if (posToGenerate.getNthDetail(far, false) != 0 && far < posToGenerate.getNumberOfFarPos()) + + + // add the far positions + if (posToGenerate.getNthDetail(farIndex, false) != 0 && farIndex < posToGenerate.getNumberOfFarPos()) { - detailLevel = (byte) (posToGenerate.getNthDetail(far, false) - 1); - posX = posToGenerate.getNthPosX(far, false); - posZ = posToGenerate.getNthPosZ(far, false); - far++; + detailLevel = (byte) (posToGenerate.getNthDetail(farIndex, false) - 1); + posX = posToGenerate.getNthPosX(farIndex, false); + posZ = posToGenerate.getNthPosZ(farIndex, false); + farIndex++; + ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel, posX), LevelPosUtil.getChunkPos(detailLevel, posZ)); if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) { // prevent generating the same chunk multiple times - if (positionWaitingToBeGenerated.contains(chunkPos)) - { + if (positionsWaitingToBeGenerated.contains(chunkPos)) continue; - } } - - // don't add null chunkPos (which shouldn't happen anyway) - // or add more to the generation queue - if (chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) - continue; - - positionWaitingToBeGenerated.add(chunkPos); + + // don't add more to the generation queue then allowed + if (numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) + break; + + positionsWaitingToBeGenerated.add(chunkPos); numberOfChunksWaitingToGenerate.addAndGet(1); LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DetailDistanceUtil.getDistanceGenerationMode(detailLevel), lodBuilder, lodDim, serverWorld); WorldWorkerManager.addWorker(genWorker); } } - - } catch (Exception e) + + } + catch (Exception e) { // this shouldn't ever happen, but just in case e.printStackTrace(); - } finally + } + finally { generatorThreadRunning = false; } }); - + mainGenThread.execute(generatorThread); } // if distanceGenerationMode != DistanceGenerationMode.NONE && !generatorThreadRunning - } - + } // queueGenerationRequests + }