refactor and comment LodWorldGenerator

This commit is contained in:
James Seibel
2021-09-25 16:09:29 -05:00
parent 8627b87aa4
commit 209e2579c3
@@ -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<ChunkPos> positionWaitingToBeGenerated = new HashSet<>();
public Set<ChunkPos> 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
}