diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
index 26c0d8304..f895b247d 100644
--- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
+++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
@@ -199,11 +199,11 @@ public class LodBufferBuilder
{
for (int zRegion = 0; zRegion < lodDim.getWidth(); zRegion++)
{
- if (lodDim.isRegionToRegen(xRegion, zRegion) || fullRegen)
+ if (lodDim.doesRegionNeedBufferRegen(xRegion, zRegion) || fullRegen)
{
RegionPos regionPos = new RegionPos(
- xRegion + lodDim.getCenterX() - Math.floorDiv(lodDim.getWidth(), 2),
- zRegion + lodDim.getCenterZ() - Math.floorDiv(lodDim.getWidth(), 2));
+ xRegion + lodDim.getCenterRegionPosX() - Math.floorDiv(lodDim.getWidth(), 2),
+ zRegion + lodDim.getCenterRegionPosZ() - Math.floorDiv(lodDim.getWidth(), 2));
// local position in the vbo and bufferBuilder arrays
BufferBuilder currentBuffer = buildableBuffers[xRegion][zRegion];
@@ -449,7 +449,7 @@ public class LodBufferBuilder
{
for (int z = 0; z < buildableBuffers.length; z++)
{
- if (fullRegen || lodDim.isRegionToRegen(x, z))
+ if (fullRegen || lodDim.doesRegionNeedBufferRegen(x, z))
{
// for some reason BufferBuilder.vertexCounts
// isn't reset unless this is called, which can cause
@@ -469,7 +469,7 @@ public class LodBufferBuilder
{
for (int x = 0; x < buildableBuffers.length; x++)
for (int z = 0; z < buildableBuffers.length; z++)
- if (buildableBuffers[x][z] != null && buildableBuffers[x][z].building() && (fullRegen || lodDim.isRegionToRegen(x, z)))
+ if (buildableBuffers[x][z] != null && buildableBuffers[x][z].building() && (fullRegen || lodDim.doesRegionNeedBufferRegen(x, z)))
buildableBuffers[x][z].end();
}
@@ -490,11 +490,11 @@ public class LodBufferBuilder
{
for (int z = 0; z < buildableVbos.length; z++)
{
- if (fullRegen || lodDim.isRegionToRegen(x, z))
+ if (fullRegen || lodDim.doesRegionNeedBufferRegen(x, z))
{
ByteBuffer builderBuffer = buildableBuffers[x][z].popNextBuffer().getSecond();
vboUpload(buildableVbos[x][z], builderBuffer);
- lodDim.setRegenByArrayIndex(x, z, false);
+ lodDim.setRegenRegionBufferByArrayIndex(x, z, false);
}
}
}
diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java
index 83863ea11..7fc9b0e8e 100644
--- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java
+++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java
@@ -238,10 +238,10 @@ public class LodDimensionFileHandler
{
for (int j = 0; j < lodDimension.getWidth(); j++)
{
- if (lodDimension.isRegionToRegen(i,j) && lodDimension.getRegionByArrayIndex(i,j) != null)
+ if (lodDimension.doesRegionNeedBufferRegen(i,j) && lodDimension.getRegionByArrayIndex(i,j) != null)
{
saveRegionToFile(lodDimension.getRegionByArrayIndex(i,j));
- lodDimension.setRegenByArrayIndex(i, j,false);
+ lodDimension.setRegenRegionBufferByArrayIndex(i, j,false);
}
}
}
diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java
index 0159c5010..fb8984d46 100644
--- a/src/main/java/com/seibel/lod/objects/LodDimension.java
+++ b/src/main/java/com/seibel/lod/objects/LodDimension.java
@@ -28,7 +28,11 @@ import com.seibel.lod.enums.GenerationPriority;
import com.seibel.lod.enums.LodTemplate;
import com.seibel.lod.enums.VerticalQuality;
import com.seibel.lod.handlers.LodDimensionFileHandler;
-import com.seibel.lod.util.*;
+import com.seibel.lod.util.DataPointUtil;
+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;
import net.minecraft.util.math.ChunkPos;
@@ -43,54 +47,45 @@ import net.minecraft.world.server.ServerWorld;
*
* @author Leonardo Amato
* @author James Seibel
- * @version 9-18-2021
+ * @version 9-26-2021
*/
public class LodDimension
{
-
public final DimensionType dimension;
-
- /**
- * measured in regions
- */
+
+ /** measured in regions */
private volatile int width;
- /**
- * measured in regions
- */
+ /** measured in regions */
private volatile int halfWidth;
-
+
// these three variables are private to force use of the getWidth() method
// which is a safer way to get the width then directly asking the arrays
- /**
- * stores all the regions in this dimension
- */
+ /** stores all the regions in this dimension */
public volatile LodRegion[][] regions;
-
- /**
- * stores if the region at the given x and z index needs to be saved to disk
- */
+
+ /** stores if the region at the given x and z index needs to be saved to disk */
private volatile boolean[][] isRegionDirty;
- /**
- * stores if the region at the given x and z index needs to be regenerated
- */
- private volatile boolean[][] regionNeedsRegen;
- /**
- * stores if the buffer size at the given x and z index needs to be changed
- */
- private volatile boolean[][] setupBuffer;
-
+ /** stores if the region at the given x and z index needs to be regenerated */
+ private volatile boolean[][] regenRegionBuffer;
+ /** stores if the buffer size at the given x and z index needs to be changed */
+ private volatile boolean[][] recreateRegionBuffer;
+
/**
* if true that means there are regions in this dimension
* that need to have their buffers rebuilt.
*/
- public volatile boolean regenDimension = false;
-
- private volatile RegionPos center;
- private volatile ChunkPos lastGenChunk;
- private volatile ChunkPos lastCutChunk;
+ public volatile boolean regenDimensionBuffers = false;
+
private LodDimensionFileHandler fileHandler;
- private ExecutorService cutAndGenThreads = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - cutAndGen"));
-
+
+ private volatile RegionPos center;
+
+ /** prevents the cutAndExpandThread from expanding at the same location multiple times */
+ private volatile ChunkPos lastExpandedChunk;
+ /** prevents the cutAndExpandThread from cutting at the same location multiple times */
+ private volatile ChunkPos lastCutChunk;
+ private ExecutorService cutAndExpandThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - Cut and Expand"));
+
/**
* Creates the dimension centered at (0,0)
*
@@ -99,60 +94,55 @@ public class LodDimension
public LodDimension(DimensionType newDimension, LodWorld lodWorld, int newWidth)
{
lastCutChunk = null;
- lastGenChunk = null;
+ lastExpandedChunk = null;
dimension = newDimension;
width = newWidth;
halfWidth = width / 2;
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
+
if (newDimension != null && lodWorld != null)
{
try
{
-
File saveDir;
if (mc.hasSingleplayerServer())
{
// local world
-
+
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(newDimension);
-
+
// provider needs a separate variable to prevent
// the compiler from complaining
ServerChunkProvider provider = serverWorld.getChunkSource();
saveDir = new File(provider.dataStorage.dataFolder.getCanonicalFile().getPath() + File.separatorChar + "lod");
- } else
+ }
+ else
{
// connected to server
-
+
saveDir = new File(mc.getGameDirectory().getCanonicalFile().getPath() +
- File.separatorChar + "lod server data" + File.separatorChar + mc.getCurrentDimensionId());
+ File.separatorChar + "lod server data" + File.separatorChar + mc.getCurrentDimensionId());
}
-
+
fileHandler = new LodDimensionFileHandler(saveDir, this);
- } catch (IOException e)
+ }
+ catch (IOException e)
{
// the file handler wasn't able to be created
// we won't be able to read or write any files
}
}
-
-
+
+
regions = new LodRegion[width][width];
isRegionDirty = new boolean[width][width];
- regionNeedsRegen = new boolean[width][width];
- setupBuffer = new boolean[width][width];
-
- //treeGenerator((int) mc.player.getX(),(int) mc.player.getZ());
-
- // populate isRegionDirty
- for (int i = 0; i < width; i++)
- for (int j = 0; j < width; j++)
- isRegionDirty[i][j] = false;
-
+ regenRegionBuffer = new boolean[width][width];
+ recreateRegionBuffer = new boolean[width][width];
+
center = new RegionPos(0, 0);
}
-
-
+
+
/**
* Move the center of this LodDimension and move all owned
* regions over by the given x and z offset.
@@ -163,28 +153,24 @@ public class LodDimension
{
int xOffset = regionOffset.x;
int zOffset = regionOffset.z;
-
+
// if the x or z offset is equal to or greater than
- // the total size, just delete the current data
+ // the total width, just delete the current data
// and update the centerX and/or centerZ
if (Math.abs(xOffset) >= width || Math.abs(zOffset) >= width)
{
for (int x = 0; x < width; x++)
- {
for (int z = 0; z < width; z++)
- {
regions[x][z] = null;
- }
- }
-
+
// update the new center
center.x += xOffset;
center.z += zOffset;
-
+
return;
}
-
-
+
+
// X
if (xOffset > 0)
{
@@ -199,7 +185,8 @@ public class LodDimension
regions[x][z] = null;
}
}
- } else
+ }
+ else
{
// move everything over to the right (as the center moves to the left)
for (int x = width - 1; x >= 0; x--)
@@ -209,14 +196,12 @@ public class LodDimension
if (x + xOffset >= 0)
regions[x][z] = regions[x + xOffset][z];
else
- {
regions[x][z] = null;
- }
}
}
}
-
-
+
+
// Z
if (zOffset > 0)
{
@@ -231,7 +216,8 @@ public class LodDimension
regions[x][z] = null;
}
}
- } else
+ }
+ else
{
// move everything down (as the center moves up)
for (int x = 0; x < width; x++)
@@ -245,62 +231,58 @@ public class LodDimension
}
}
}
-
-
+
+
// update the new center
center.x += xOffset;
center.z += zOffset;
}
-
-
+
+
/**
- * return needed memory in bytes
+ * return the minimum needed memory in bytes
*/
public int getMinMemoryNeeded()
{
int count = 0;
LodRegion region;
-
+
for (int x = 0; x < regions.length; x++)
{
for (int z = 0; z < regions.length; z++)
{
region = regions[x][z];
if (region != null)
- {
count += region.getMinMemoryNeeded(LodConfig.CLIENT.graphics.lodTemplate.get());
- }
}
}
return count;
}
-
-
+
+
/**
- * Gets the region at the given X and Z
+ * Gets the region at the given LevelPos
*
* Returns null if the region doesn't exist
* or is outside the loaded area.
*/
- public LodRegion getRegion(byte detailLevel, int posX, int posZ)
+ public LodRegion getRegion(byte detailLevel, int levelPosX, int levelPosZ)
{
- int xRegion = LevelPosUtil.getRegion(detailLevel, posX);
- int zRegion = LevelPosUtil.getRegion(detailLevel, posZ);
+ int xRegion = LevelPosUtil.getRegion(detailLevel, levelPosX);
+ int zRegion = LevelPosUtil.getRegion(detailLevel, levelPosZ);
int xIndex = (xRegion - center.x) + halfWidth;
int zIndex = (zRegion - center.z) + halfWidth;
-
+
if (!regionIsInRange(xRegion, zRegion))
return null;
- //throw new ArrayIndexOutOfBoundsException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " out of range");
- else if (regions[xIndex][zIndex] == null)
- return null;
- //throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " not currently initialized");
+ //throw new ArrayIndexOutOfBoundsException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " out of range");
else if (regions[xIndex][zIndex].getMinDetailLevel() > detailLevel)
return null;
//throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " currently only reach level " + regions[xIndex][zIndex].getMinDetailLevel());
+
return regions[xIndex][zIndex];
}
-
+
/**
* Gets the region at the given X and Z
*
@@ -311,24 +293,20 @@ public class LodDimension
{
int xIndex = (regionPosX - center.x) + halfWidth;
int zIndex = (regionPosZ - center.z) + halfWidth;
-
+
if (!regionIsInRange(regionPosX, regionPosZ))
return null;
- //throw new ArrayIndexOutOfBoundsException("Region " + regionPosX + " " + regionPosZ + " out of range");
- else if (regions[xIndex][zIndex] == null)
- return null;
- //throw new InvalidParameterException("Region " + regionPosX + " " + regionPosZ + " not currently initialized");
+ //throw new ArrayIndexOutOfBoundsException("Region " + regionPosX + " " + regionPosZ + " out of range");
+
return regions[xIndex][zIndex];
}
-
- /**
- * Useful when needing to iterate over every region.
- */
+
+ /** Useful when iterating over every region. */
public LodRegion getRegionByArrayIndex(int xIndex, int zIndex)
{
return regions[xIndex][zIndex];
}
-
+
/**
* Overwrite the LodRegion at the location of newRegion with newRegion.
*
@@ -338,77 +316,87 @@ public class LodDimension
{
int xIndex = (newRegion.regionPosX - center.x) + halfWidth;
int zIndex = (newRegion.regionPosZ - center.z) + halfWidth;
-
+
if (!regionIsInRange(newRegion.regionPosX, newRegion.regionPosZ))
// out of range
throw new ArrayIndexOutOfBoundsException("Region " + newRegion.regionPosX + ", " + newRegion.regionPosZ + " out of range");
-
+
regions[xIndex][zIndex] = newRegion;
}
-
-
+
+
/**
- *
+ * Deletes nodes that are a higher detail then necessary, freeing
+ * up memory.
*/
- public void treeCutter(int playerPosX, int playerPosZ)
+ public void cutRegionNodesAsync(int playerPosX, int playerPosZ)
{
ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ));
+
if (lastCutChunk == null)
lastCutChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1);
+
+ // don't run the tree cutter multiple times
+ // for the same location
if (newPlayerChunk.x != lastCutChunk.x || newPlayerChunk.z != lastCutChunk.z)
{
lastCutChunk = newPlayerChunk;
+
Thread thread = new Thread(() ->
{
int regionX;
int regionZ;
int minDistance;
byte detail;
- byte levelToCut;
-
+ byte minAllowedDetailLevel;
+
+ // go over every region in the dimension
for (int x = 0; x < regions.length; x++)
{
for (int z = 0; z < regions.length; z++)
{
regionX = (x + center.x) - halfWidth;
regionZ = (z + center.z) - halfWidth;
- //we start checking from the first circle. If the whole region is in the circle
- //we proceed to cut all the level lower than the level of circle 1 and we break
- //if this is not the case w
+
if (regions[x][z] != null)
{
+ // check what detail level this region should be
+ // and cut it if it is higher then that
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ);
detail = DetailDistanceUtil.getTreeCutDetailFromDistance(minDistance);
- levelToCut = DetailDistanceUtil.getCutLodDetail(detail);
- if (regions[x][z].getMinDetailLevel() > levelToCut)
+ minAllowedDetailLevel = DetailDistanceUtil.getCutLodDetail(detail);
+
+ if (regions[x][z].getMinDetailLevel() > minAllowedDetailLevel)
{
- regions[x][z].cutTree(levelToCut);
- setupBuffer[x][z] = true;
+ regions[x][z].cutTree(minAllowedDetailLevel);
+ recreateRegionBuffer[x][z] = true;
}
}
-
}// region z
}// region z
-
});
- cutAndGenThreads.execute(thread);
+
+ cutAndExpandThread.execute(thread);
}
}
-
- /**
- *
- */
- public void treeGenerator(int playerPosX, int playerPosZ)
+
+ /** Either expands or loads all regions in the rendered LOD area */
+ public void expandOrLoadRegionsAsync(int playerPosX, int playerPosZ)
{
DistanceGenerationMode generationMode = LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get();
ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ));
VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.lodQualityMode.get();
-
- if (lastGenChunk == null)
- lastGenChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1);
- if (newPlayerChunk.x != lastGenChunk.x || newPlayerChunk.z != lastGenChunk.z)
+
+
+ if (lastExpandedChunk == null)
+ lastExpandedChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1);
+
+ // don't run the expander multiple times
+ // for the same location
+ if (newPlayerChunk.x != lastExpandedChunk.x || newPlayerChunk.z != lastExpandedChunk.z)
{
- lastGenChunk = newPlayerChunk;
+ lastExpandedChunk = newPlayerChunk;
+
Thread thread = new Thread(() ->
{
int regionX;
@@ -417,6 +405,7 @@ public class LodDimension
int minDistance;
byte detail;
byte levelToGen;
+
for (int x = 0; x < regions.length; x++)
{
for (int z = 0; z < regions.length; z++)
@@ -425,57 +414,60 @@ public class LodDimension
regionZ = (z + center.z) - halfWidth;
final RegionPos regionPos = new RegionPos(regionX, regionZ);
region = regions[x][z];
- //We require that the region we are checking is loaded with at least this level
-
+
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ);
detail = DetailDistanceUtil.getTreeGenDetailFromDistance(minDistance);
levelToGen = DetailDistanceUtil.getLodGenDetail(detail).detailLevel;
+
+ // check that the region isn't null and at least this detail level
if (region == null || region.getGenerationMode() != generationMode)
{
- //First case, region has to be initialized
-
- //We check if there is a file at the target level
+ // First case, region has to be created
+
+ // try to get the region from file
regions[x][z] = getRegionFromFile(regionPos, levelToGen, generationMode, verticalQuality);
-
- //if there is no file we initialize the region
+
+ // if there is no region file create a empty region
if (regions[x][z] == null)
- {
regions[x][z] = new LodRegion(levelToGen, regionPos, generationMode, verticalQuality);
- }
- regionNeedsRegen[x][z] = true;
- regenDimension = true;
- setupBuffer[x][z] = true;
-
- } else if (region.getMinDetailLevel() > levelToGen)
+
+ regenRegionBuffer[x][z] = true;
+ regenDimensionBuffers = true;
+ recreateRegionBuffer[x][z] = true;
+ }
+ else if (region.getMinDetailLevel() > levelToGen)
{
- //Second case, region has been initialized but at a higher level
- //We expand the region by introducing the missing layer
+ // Second case, the region exists at a higher detail level.
+
+ // Expand the region by introducing the missing layer
region.expand(levelToGen);
- setupBuffer[x][z] = true;
+ recreateRegionBuffer[x][z] = true;
}
}
}
});
- cutAndGenThreads.execute(thread);
+
+ cutAndExpandThread.execute(thread);
}
}
-
+
/**
* Add the given LOD to this dimension at the coordinate
* stored in the LOD. If an LOD already exists at the given
- * coordinates it will be overwritten.
+ * coordinate it will be overwritten.
*/
public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data, boolean dontSave)
{
-
- // don't continue if the region can't be saved
int regionPosX = LevelPosUtil.getRegion(detailLevel, posX);
int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ);
-
+
+ // don't continue if the region can't be saved
LodRegion region = getRegion(regionPosX, regionPosZ);
if (region == null)
return false;
+
boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, data);
+
// only save valid LODs to disk
if (!dontSave && fileHandler != null)
{
@@ -484,152 +476,169 @@ public class LodDimension
// mark the region as dirty so it will be saved to disk
int xIndex = (regionPosX - center.x) + halfWidth;
int zIndex = (regionPosZ - center.z) + halfWidth;
+
isRegionDirty[xIndex][zIndex] = true;
- regionNeedsRegen[xIndex][zIndex] = true;
- regenDimension = true;
- } catch (ArrayIndexOutOfBoundsException e)
+ regenRegionBuffer[xIndex][zIndex] = true;
+ regenDimensionBuffers = true;
+ }
+ catch (ArrayIndexOutOfBoundsException e)
{
e.printStackTrace();
- // This method was probably called when the dimension was changing size.
+ // If this happens, the method was probably
+ // called when the dimension was changing size.
// Hopefully this shouldn't be an issue.
}
}
+
return nodeAdded;
}
-
- public void setToRegen(int xRegion, int zRegion)
+
+ /** marks the region at the given region position to have its buffer rebuilt */
+ public void markRegionBufferToRegen(int xRegion, int zRegion)
{
int xIndex = (xRegion - center.x) + halfWidth;
int zIndex = (zRegion - center.z) + halfWidth;
- regionNeedsRegen[xIndex][zIndex] = true;
+ regenRegionBuffer[xIndex][zIndex] = true;
}
-
+
/**
- * method to get all the quadtree level that have to be generated based on the position of the player
- *
- * @return list of quadTrees
+ * Returns every position that need to be generated based on the position of the player
*/
public PosToGenerateContainer getDataToGenerate(int maxDataToGenerate, int playerPosX, int playerPosZ)
{
PosToGenerateContainer posToGenerate;
LodRegion region;
+ // TODO what are dx, dz, and t?
int x, z, dx, dz, t;
x = 0;
z = 0;
dx = 0;
dz = -1;
+
+ // TODO please comment what this code is doing
switch (LodConfig.CLIENT.worldGenerator.generationPriority.get())
{
- default:
- case NEAR_FIRST:
- posToGenerate = new PosToGenerateContainer((byte) 10, maxDataToGenerate, 0, playerPosX, playerPosZ);
- int playerChunkX = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerPosX);
- int playerChunkZ = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerPosZ);
- int xChunkToCheck;
- int zChunkToCheck;
- byte detailLevel;
- int posX;
- int posZ;
- long data;
- int numbChunksWide = (width) * 32;
- int circleLimit = Integer.MAX_VALUE;
- for (int i = 0; i < numbChunksWide * numbChunksWide; i++)
+ default:
+ case NEAR_FIRST:
+ posToGenerate = new PosToGenerateContainer((byte) 10, maxDataToGenerate, 0, playerPosX, playerPosZ);
+
+ int playerChunkX = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerPosX);
+ int playerChunkZ = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerPosZ);
+
+ int xChunkToCheck;
+ int zChunkToCheck;
+ byte detailLevel;
+ int posX;
+ int posZ;
+ long data;
+ int numbChunksWide = (width) * 32;
+ int circleLimit = Integer.MAX_VALUE;
+
+ for (int i = 0; i < numbChunksWide * numbChunksWide; i++)
+ {
+ // use this for circular generation
+ if (maxDataToGenerate < 0)
{
- // use this for square generation
-
- // use this for circular generation
- if (maxDataToGenerate < 0)
- {
- if (circleLimit < Math.abs(x) && circleLimit < Math.abs(z))
- break;
- } else if (maxDataToGenerate == 0)
- {
+ if (circleLimit < Math.abs(x) && circleLimit < Math.abs(z))
+ break;
+ }
+ else if (maxDataToGenerate == 0)
+ {
+ maxDataToGenerate--;
+ circleLimit = (int) (Math.abs(x) * 1.41f);
+ }
+
+ xChunkToCheck = x + playerChunkX;
+ zChunkToCheck = z + playerChunkZ;
+
+ region = getRegion(LodUtil.CHUNK_DETAIL_LEVEL, xChunkToCheck, zChunkToCheck);
+ if (region == null)
+ continue;
+
+ detailLevel = region.getMinDetailLevel();
+
+ posX = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, xChunkToCheck, detailLevel);
+ posZ = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, zChunkToCheck, detailLevel);
+ data = getSingleData(detailLevel, posX, posZ);
+
+ if (DataPointUtil.getGenerationMode(data) < LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get().complexity)
+ {
+ posToGenerate.addPosToGenerate(detailLevel, posX, posZ);
+ if (maxDataToGenerate >= 0)
maxDataToGenerate--;
- circleLimit = (int) (Math.abs(x) * 1.41f);
- }
-
- xChunkToCheck = x + playerChunkX;
- zChunkToCheck = z + playerChunkZ;
- //distance = LevelPosUtil.maxDistance(LodUtil.CHUNK_DETAIL_LEVEL, xChunkToCheck, zChunkToCheck, playerChunkX, playerChunkZ);
- region = getRegion(LodUtil.CHUNK_DETAIL_LEVEL, xChunkToCheck, zChunkToCheck);
- if (region == null)
- continue;
- detailLevel = region.getMinDetailLevel();
-
- posX = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, xChunkToCheck, detailLevel);
- posZ = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, zChunkToCheck, detailLevel);
- data = getSingleData(detailLevel, posX, posZ);
- if (DataPointUtil.getGenerationMode(data) < LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get().complexity)
- {
- posToGenerate.addPosToGenerate(detailLevel, posX, posZ);
- if (maxDataToGenerate >= 0)
- maxDataToGenerate--;
- }
- if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z)))
- {
- t = dx;
- dx = -dz;
- dz = t;
- }
- x += dx;
- z += dz;
}
- break;
- case FAR_FIRST:
- posToGenerate = new PosToGenerateContainer((byte) 8, maxDataToGenerate, (int) (maxDataToGenerate * 0.25), playerPosX, playerPosZ);
- int n = regions.length;
- int xRegion;
- int zRegion;
-
- for (int i = 0; i < width * width; i++)
+
+ if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z)))
{
- xRegion = x + center.x;
- zRegion = z + center.z;
- region = getRegion(xRegion, zRegion);
- if (region != null)
- region.getDataToGenerate(posToGenerate, playerPosX, playerPosZ);
- if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z)))
- {
- t = dx;
- dx = -dz;
- dz = t;
- }
- x += dx;
- z += dz;
+ t = dx;
+ dx = -dz;
+ dz = t;
}
- break;
+ x += dx;
+ z += dz;
+ }
+ break;
+
+
+ case FAR_FIRST:
+ posToGenerate = new PosToGenerateContainer((byte) 8, maxDataToGenerate, (int) (maxDataToGenerate * 0.25), playerPosX, playerPosZ);
+
+ int xRegion;
+ int zRegion;
+
+ for (int i = 0; i < width * width; i++)
+ {
+ xRegion = x + center.x;
+ zRegion = z + center.z;
+
+ region = getRegion(xRegion, zRegion);
+ if (region != null)
+ region.getDataToGenerate(posToGenerate, playerPosX, playerPosZ);
+
+
+ if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z)))
+ {
+ t = dx;
+ dx = -dz;
+ dz = t;
+ }
+ x += dx;
+ z += dz;
+ }
+ break;
}
return posToGenerate;
}
-
+
/**
- * method to get all the nodes that have to be rendered based on the position of the player
- *
- * @return list of nodes
+ * Returns every node that should be rendered based on the position of the player.
+ *
+ * TODO why isn't posToRender returned? it would make it a bit more clear what is happening
*/
public void getDataToRender(PosToRenderContainer posToRender, RegionPos regionPos, int playerPosX,
- int playerPosZ)
+ int playerPosZ)
{
LodRegion region = getRegion(regionPos.x, regionPos.z);
if (region != null)
region.getDataToRender(posToRender, playerPosX, playerPosZ, LodConfig.CLIENT.worldGenerator.generationPriority.get() == GenerationPriority.NEAR_FIRST);
}
-
+
+ /**
+ * Determines how many vertical LODs could be used
+ * for the given region at the given detail level
+ */
public int getMaxVerticalData(byte detailLevel, int posX, int posZ)
{
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
- throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
-
+ throw new IllegalArgumentException("getMaxVerticalData given a level of [" + detailLevel + "] when [" + LodUtil.REGION_DETAIL_LEVEL + "] is the max.");
+
LodRegion region = getRegion(detailLevel, posX, posZ);
-
if (region == null)
- {
return 0;
- }
-
+
return region.getMaxVerticalData(detailLevel);
}
-
+
/**
* Get the data point at the given X and Z coordinates
* in this dimension.
@@ -641,18 +650,15 @@ public class LodDimension
{
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
-
+
LodRegion region = getRegion(detailLevel, posX, posZ);
-
if (region == null)
- {
return DataPointUtil.EMPTY_DATA;
- }
-
+
return region.getData(detailLevel, posX, posZ, verticalIndex);
}
-
-
+
+
/**
* Get the data point at the given X and Z coordinates
* in this dimension.
@@ -664,49 +670,59 @@ public class LodDimension
{
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
-
+
LodRegion region = getRegion(detailLevel, posX, posZ);
-
if (region == null)
- {
return DataPointUtil.EMPTY_DATA;
- }
-
+
return region.getSingleData(detailLevel, posX, posZ);
}
-
+
+ /** Clears the given region */
public void clear(byte detailLevel, int posX, int posZ)
{
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
-
+
LodRegion region = getRegion(detailLevel, posX, posZ);
-
if (region == null)
- {
return;
- }
-
+
region.clear(detailLevel, posX, posZ);
}
-
- public boolean isRegionToRegen(int xIndex, int zIndex)
- {
- return regionNeedsRegen[xIndex][zIndex];
- }
-
- public boolean isBufferToSetup(int xIndex, int zIndex)
- {
- return setupBuffer[xIndex][zIndex];
- }
-
- public void setRegenByArrayIndex(int xIndex, int zIndex, boolean newRegen)
- {
- regionNeedsRegen[xIndex][zIndex] = newRegen;
- }
-
+
/**
- * Get the data point at the given X and Z coordinates
+ * Returns if the buffer at the given array index needs
+ * to have its buffer regenerated.
+ */
+ public boolean doesRegionNeedBufferRegen(int xIndex, int zIndex)
+ {
+ return regenRegionBuffer[xIndex][zIndex];
+ }
+
+ /**
+ * TODO we aren't currently using this, is there a reason for that?
+ * is this significantly different than regenRegionBuffer?
+ *
+ * Returns if the buffer at the given array index needs
+ * to have its buffer resized.
+ */
+ public boolean doesRegionNeedBufferResized(int xIndex, int zIndex)
+ {
+ return recreateRegionBuffer[xIndex][zIndex];
+ }
+
+ /**
+ * Sets if the buffer at the given array index needs
+ * to have its buffer regenerated.
+ */
+ public void setRegenRegionBufferByArrayIndex(int xIndex, int zIndex, boolean newRegen)
+ {
+ regenRegionBuffer[xIndex][zIndex] = newRegen;
+ }
+
+ /**
+ * Get the data point at the given LevelPos
* in this dimension.
*
* Returns null if the LodChunk doesn't exist or
@@ -716,45 +732,39 @@ public class LodDimension
{
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
-
+
LodRegion region = getRegion(detailLevel, posX, posZ);
-
-
if (region == null)
- {
return;
- }
+
region.updateArea(detailLevel, posX, posZ);
}
-
+
/**
- * return true if and only if the node at that position exist
+ * Returns true if a region exists at the given LevelPos
*/
public boolean doesDataExist(byte detailLevel, int posX, int posZ)
{
LodRegion region = getRegion(detailLevel, posX, posZ);
-
if (region == null)
- {
return false;
- }
-
+
return region.doesDataExist(detailLevel, posX, posZ);
}
-
+
/**
- * Get the region at the given X and Z coordinates from the
- * RegionFileHandler.
+ * Loads the region at the given RegionPos from file,
+ * if a file exists for that region.
*/
- public LodRegion getRegionFromFile(RegionPos regionPos, byte detailLevel, DistanceGenerationMode
- generationMode, VerticalQuality verticalQuality)
+ public LodRegion getRegionFromFile(RegionPos regionPos, byte detailLevel,
+ DistanceGenerationMode generationMode, VerticalQuality verticalQuality)
{
if (fileHandler != null)
return fileHandler.loadRegionFromFile(detailLevel, regionPos, generationMode, verticalQuality);
else
return null;
}
-
+
/**
* Save all dirty regions in this LodDimension to file.
*/
@@ -762,31 +772,32 @@ public class LodDimension
{
fileHandler.saveDirtyRegionsToFileAsync();
}
-
-
+
+
/**
- * Returns whether the region at the given X and Z coordinates
+ * Returns whether the region at the given RegionPos
* is within the loaded range.
*/
public boolean regionIsInRange(int regionX, int regionZ)
{
int xIndex = (regionX - center.x) + halfWidth;
int zIndex = (regionZ - center.z) + halfWidth;
-
+
return xIndex >= 0 && xIndex < width && zIndex >= 0 && zIndex < width;
}
-
-
- public int getCenterX()
+
+ /** Returns the dimension's center region position X value */
+ public int getCenterRegionPosX()
{
return center.x;
}
-
- public int getCenterZ()
+
+ /** Returns the dimension's center region position Z value */
+ public int getCenterRegionPosZ()
{
return center.z;
}
-
+
/**
* returns the width of the dimension in regions
*/
@@ -798,35 +809,36 @@ public class LodDimension
// source to make sure it is in sync with region
// and isRegionDirty
return regions.length;
- } else
+ }
+ else
{
return width;
}
}
-
-
+
+ /** Update the width of this dimension, in regions */
public void setRegionWidth(int newWidth)
{
width = newWidth;
halfWidth = Math.floorDiv(width, 2);
-
+
regions = new LodRegion[width][width];
isRegionDirty = new boolean[width][width];
- regionNeedsRegen = new boolean[width][width];
- setupBuffer = new boolean[width][width];
-
+ regenRegionBuffer = new boolean[width][width];
+ recreateRegionBuffer = new boolean[width][width];
+
// populate isRegionDirty
for (int i = 0; i < width; i++)
for (int j = 0; j < width; j++)
isRegionDirty[i][j] = false;
}
-
-
+
+
@Override
public String toString()
{
LodRegion region;
-
+
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Dimension : \n");
for (int x = 0; x < regions.length; x++)
@@ -838,7 +850,7 @@ public class LodDimension
{
stringBuilder.append("n");
stringBuilder.append("\t");
-
+
} else
{
stringBuilder.append(region.getMinDetailLevel());
@@ -849,11 +861,11 @@ public class LodDimension
}
return stringBuilder.toString();
}
-
+
public int getMemoryRequired(int x, int z, LodTemplate template)
{
/*return regions[x][z].getMinMemoryNeeded(template);*/
-
+
/*TODO add memory use calculated with the following cases
switch (LodConfig.CLIENT.graphics.detailDropOff.get())
{
diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java
index 8b763f51c..b6015883f 100644
--- a/src/main/java/com/seibel/lod/objects/LodRegion.java
+++ b/src/main/java/com/seibel/lod/objects/LodRegion.java
@@ -449,6 +449,7 @@ public class LodRegion
}
/**
+ * TODO what does this do?
* @param detailLevel
*/
public void expand(byte detailLevel)
diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java
index 652f70c22..4922d4c36 100644
--- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java
+++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java
@@ -128,8 +128,8 @@ public class ClientProxy
viewDistanceChangedEvent();
playerMoveEvent(lodDim);
- lodDim.treeCutter((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
- lodDim.treeGenerator((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
+ lodDim.cutRegionNodesAsync((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
+ lodDim.expandOrLoadRegionsAsync((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
// Note to self:
@@ -313,7 +313,7 @@ public class ClientProxy
{
// make sure the dimension is centered
RegionPos playerRegionPos = new RegionPos(mc.getPlayer().blockPosition());
- RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterX(), playerRegionPos.z - lodDim.getCenterZ());
+ RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterRegionPosX(), playerRegionPos.z - lodDim.getCenterRegionPosZ());
if (worldRegionOffset.x != 0 || worldRegionOffset.z != 0)
{
lodWorld.saveAllDimensions();
diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java
index f71f4110a..46e761278 100644
--- a/src/main/java/com/seibel/lod/render/LodRenderer.java
+++ b/src/main/java/com/seibel/lod/render/LodRenderer.java
@@ -287,7 +287,7 @@ public class LodRenderer
{
for (int j = 0; j < vbos.length; j++)
{
- RegionPos vboPos = new RegionPos(i + lodDim.getCenterX() - lodDim.getWidth() / 2, j + lodDim.getCenterZ() - lodDim.getWidth() / 2);
+ RegionPos vboPos = new RegionPos(i + lodDim.getCenterRegionPosX() - lodDim.getWidth() / 2, j + lodDim.getCenterRegionPosZ() - lodDim.getWidth() / 2);
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(renderInfo.getBlockPosition(), cameraDir, vboPos.blockPos()))
{
if ((i > halfWidth - quarterWidth && i < halfWidth + quarterWidth) && (j > halfWidth - quarterWidth && j < halfWidth + quarterWidth))
@@ -821,10 +821,10 @@ public class LodRenderer
// check if there is any newly generated terrain to show
if (newTime - prevChunkTime > LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.get())
{
- if (lodDim.regenDimension)
+ if (lodDim.regenDimensionBuffers)
{
partialRegen = true;
- lodDim.regenDimension = false;
+ lodDim.regenDimensionBuffers = false;
}
prevChunkTime = newTime;
}
@@ -864,7 +864,7 @@ public class LodRenderer
{
vanillaRenderedChunks[xIndex][zIndex] = true;
vanillaRenderedChunksChanged = true;
- lodDim.setToRegen(pos.getRegionX(), pos.getRegionZ());
+ lodDim.markRegionBufferToRegen(pos.getRegionX(), pos.getRegionZ());
}
}
}