minor world gen refactoring
This commit is contained in:
+101
-105
@@ -94,24 +94,31 @@ public interface IFullDataSource
|
||||
FullDataPointIdMap getMapping();
|
||||
|
||||
/**
|
||||
* @param highestGeneratorDetailLevel the smallest numerical detail level that the un-generated positions should be split into
|
||||
* @param generatorDetailLevel the detail level that the un-generated positions should be split into.
|
||||
* @param onlyReturnPositionsTheGeneratorCanAccept
|
||||
* If true this will only return positions with the same detail level as generatorDetailLevel. <br>
|
||||
* If false this will return the lowest detail level possible for totally empty sections. <br>
|
||||
* As of 2023-9-28 both have been tested and confirmed working with the Batch world generator, the only difference is that
|
||||
* the task list will be deceptively small if this value is false.
|
||||
*
|
||||
* @return the list of {@link DhSectionPos} that aren't generated in this data source.
|
||||
*/
|
||||
default ArrayList<DhSectionPos> getUngeneratedPosList(byte highestGeneratorDetailLevel, boolean onlyReturnPositionsTheGeneratorCanAccept)
|
||||
default ArrayList<DhSectionPos> getUngeneratedPosList(byte generatorDetailLevel, boolean onlyReturnPositionsTheGeneratorCanAccept)
|
||||
{
|
||||
ArrayList<DhSectionPos> posArray = this.getUngeneratedPosList(this.getSectionPos(), highestGeneratorDetailLevel);
|
||||
ArrayList<DhSectionPos> posArray = this.getUngeneratedPosListForQuadrant(this.getSectionPos(), generatorDetailLevel);
|
||||
|
||||
if (onlyReturnPositionsTheGeneratorCanAccept)
|
||||
{
|
||||
LinkedList<DhSectionPos> posList = new LinkedList<>(posArray);
|
||||
|
||||
// subdivide positions until they match the generatorDetailLevel
|
||||
ArrayList<DhSectionPos> cleanedPosArray = new ArrayList<>();
|
||||
while (posList.size() > 0)
|
||||
{
|
||||
DhSectionPos pos = posList.remove();
|
||||
if (pos.getDetailLevel() > highestGeneratorDetailLevel)
|
||||
if (pos.getDetailLevel() > generatorDetailLevel)
|
||||
{
|
||||
pos.forEachChild((childPos) -> { posList.push(childPos); });
|
||||
pos.forEachChild((childPos) -> posList.push(childPos));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -126,142 +133,131 @@ public interface IFullDataSource
|
||||
return posArray;
|
||||
}
|
||||
}
|
||||
default ArrayList<DhSectionPos> getUngeneratedPosList(DhSectionPos quadrantPos, byte highestGeneratorDetailLevel)
|
||||
default ArrayList<DhSectionPos> getUngeneratedPosListForQuadrant(DhSectionPos quadrantPos, byte generatorDetailLevel)
|
||||
{
|
||||
ArrayList<DhSectionPos> ungeneratedPosList = new ArrayList<>();
|
||||
|
||||
int sourceRelWidth = this.getWidthInDataPoints();
|
||||
int sourceRelWidthInDataPoints = this.getWidthInDataPoints();
|
||||
|
||||
|
||||
if (quadrantPos.getDetailLevel() < highestGeneratorDetailLevel)
|
||||
{
|
||||
throw new IllegalArgumentException("detail level lower than world generator can accept.");
|
||||
}
|
||||
else if (quadrantPos.getDetailLevel() == highestGeneratorDetailLevel)
|
||||
if (quadrantPos.getDetailLevel() == generatorDetailLevel)
|
||||
{
|
||||
// we are at the highest detail level the world generator can accept,
|
||||
// we either need to generate this whole section, or not at all
|
||||
|
||||
// TODO combine duplicate code
|
||||
|
||||
byte childDetailLevel = (byte) (quadrantPos.getDetailLevel());
|
||||
|
||||
int quadrantDetailLevelDiff = this.getSectionPos().getDetailLevel() - childDetailLevel;
|
||||
int widthInSecPos = BitShiftUtil.powerOfTwo(quadrantDetailLevelDiff);
|
||||
int relWidthForSecPos = sourceRelWidth / widthInSecPos;
|
||||
|
||||
DhSectionPos minSecPos = this.getSectionPos().convertNewToDetailLevel(childDetailLevel);
|
||||
DhSectionPos inputPos = quadrantPos;
|
||||
|
||||
|
||||
|
||||
int minRelX = inputPos.getX() - minSecPos.getX();
|
||||
int minRelZ = inputPos.getZ() - minSecPos.getZ();
|
||||
int maxRelX = minRelX + 1;
|
||||
int maxRelZ = minRelZ + 1;
|
||||
|
||||
minRelX = minRelX * relWidthForSecPos;
|
||||
minRelZ = minRelZ * relWidthForSecPos;
|
||||
maxRelX = maxRelX * relWidthForSecPos;
|
||||
maxRelZ = maxRelZ * relWidthForSecPos;
|
||||
|
||||
|
||||
boolean quadrantFullyGenerated = true;
|
||||
for (int relX = minRelX; relX < maxRelX; relX++)
|
||||
{
|
||||
for (int relZ = minRelZ; relZ < maxRelZ; relZ++)
|
||||
{
|
||||
SingleColumnFullDataAccessor column = this.tryGet(relX, relZ);
|
||||
if (column == null || !column.doesColumnExist())
|
||||
{
|
||||
// no data for this relative position
|
||||
quadrantFullyGenerated = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!quadrantFullyGenerated)
|
||||
ESectionPopulationState populationState = this.getPopulationStateForPos(quadrantPos, sourceRelWidthInDataPoints);
|
||||
if (populationState != ESectionPopulationState.COMPLETE)
|
||||
{
|
||||
// at least 1 data point is missing,
|
||||
// this whole section must be regenerated
|
||||
// this whole section must be generated
|
||||
ungeneratedPosList.add(quadrantPos);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (quadrantPos.getDetailLevel() > generatorDetailLevel)
|
||||
{
|
||||
// TODO comment
|
||||
// TODO combine duplicate code
|
||||
|
||||
byte childDetailLevel = (byte) (quadrantPos.getDetailLevel() - 1);
|
||||
|
||||
// detail level too low for world generator, check child positions
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int quadrantDetailLevelDiff = this.getSectionPos().getDetailLevel() - childDetailLevel;
|
||||
int widthInSecPos = BitShiftUtil.powerOfTwo(quadrantDetailLevelDiff);
|
||||
int relWidthForSecPos = sourceRelWidth / widthInSecPos;
|
||||
|
||||
DhSectionPos minSecPos = this.getSectionPos().convertNewToDetailLevel(childDetailLevel);
|
||||
DhSectionPos inputPos = quadrantPos.getChildByIndex(i);
|
||||
|
||||
|
||||
|
||||
int minRelX = inputPos.getX() - minSecPos.getX();
|
||||
int minRelZ = inputPos.getZ() - minSecPos.getZ();
|
||||
int maxRelX = minRelX + 1;
|
||||
int maxRelZ = minRelZ + 1;
|
||||
|
||||
minRelX = minRelX * relWidthForSecPos;
|
||||
minRelZ = minRelZ * relWidthForSecPos;
|
||||
maxRelX = maxRelX * relWidthForSecPos;
|
||||
maxRelZ = maxRelZ * relWidthForSecPos;
|
||||
|
||||
|
||||
|
||||
boolean quadrantFullyGenerated = true;
|
||||
boolean quadrantEmpty = true;
|
||||
for (int relX = minRelX; relX < maxRelX; relX++)
|
||||
{
|
||||
for (int relZ = minRelZ; relZ < maxRelZ; relZ++)
|
||||
{
|
||||
SingleColumnFullDataAccessor column = this.tryGet(relX, relZ);
|
||||
if (column == null || !column.doesColumnExist())
|
||||
{
|
||||
// no data for this relative position
|
||||
quadrantFullyGenerated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// data exists for this pos
|
||||
quadrantEmpty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (quadrantFullyGenerated)
|
||||
ESectionPopulationState populationState = this.getPopulationStateForPos(inputPos, sourceRelWidthInDataPoints);
|
||||
if (populationState == ESectionPopulationState.COMPLETE)
|
||||
{
|
||||
// no generation necessary
|
||||
continue;
|
||||
}
|
||||
else if (quadrantEmpty)
|
||||
else if (populationState == ESectionPopulationState.EMPTY)
|
||||
{
|
||||
// nothing exists for this sub quadrant, add this sub-quadrant's position
|
||||
ungeneratedPosList.add(inputPos);
|
||||
}
|
||||
else
|
||||
else if (populationState == ESectionPopulationState.PARTIAL)
|
||||
{
|
||||
// some data exists in this quadrant, but not all that we need
|
||||
// recurse down to determine which sub-quadrant positions will need generation
|
||||
|
||||
ungeneratedPosList.addAll(this.getUngeneratedPosList(inputPos, highestGeneratorDetailLevel));
|
||||
ungeneratedPosList.addAll(this.getUngeneratedPosListForQuadrant(inputPos, generatorDetailLevel));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("detail level lower than world generator can accept.");
|
||||
}
|
||||
|
||||
return ungeneratedPosList;
|
||||
}
|
||||
default ESectionPopulationState getPopulationStateForPos(DhSectionPos inputPos, int sourceRelWidthInDataPoints)
|
||||
{
|
||||
// TODO comment
|
||||
|
||||
byte childDetailLevel = inputPos.getDetailLevel();
|
||||
|
||||
int quadrantDetailLevelDiff = this.getSectionPos().getDetailLevel() - childDetailLevel;
|
||||
int widthInSecPos = BitShiftUtil.powerOfTwo(quadrantDetailLevelDiff);
|
||||
int relWidthForSecPos = sourceRelWidthInDataPoints / widthInSecPos;
|
||||
|
||||
DhSectionPos minSecPos = this.getSectionPos().convertNewToDetailLevel(childDetailLevel);
|
||||
|
||||
|
||||
|
||||
int minRelX = inputPos.getX() - minSecPos.getX();
|
||||
int maxRelX = minRelX + 1;
|
||||
|
||||
int minRelZ = inputPos.getZ() - minSecPos.getZ();
|
||||
int maxRelZ = minRelZ + 1;
|
||||
|
||||
minRelX = minRelX * relWidthForSecPos;
|
||||
maxRelX = maxRelX * relWidthForSecPos;
|
||||
|
||||
minRelZ = minRelZ * relWidthForSecPos;
|
||||
maxRelZ = maxRelZ * relWidthForSecPos;
|
||||
|
||||
|
||||
|
||||
boolean quadrantFullyGenerated = true;
|
||||
boolean quadrantEmpty = true;
|
||||
for (int relX = minRelX; relX < maxRelX; relX++)
|
||||
{
|
||||
for (int relZ = minRelZ; relZ < maxRelZ; relZ++)
|
||||
{
|
||||
SingleColumnFullDataAccessor column = this.tryGet(relX, relZ);
|
||||
if (column == null || !column.doesColumnExist())
|
||||
{
|
||||
// no data for this relative position
|
||||
quadrantFullyGenerated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// data exists for this pos
|
||||
quadrantEmpty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (quadrantFullyGenerated)
|
||||
{
|
||||
// no generation necessary
|
||||
return ESectionPopulationState.COMPLETE;
|
||||
}
|
||||
else if (quadrantEmpty)
|
||||
{
|
||||
// nothing exists for this sub quadrant, add this sub-quadrant's position
|
||||
return ESectionPopulationState.EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// some data exists in this quadrant, but not all that we need
|
||||
// recurse down to determine which sub-quadrant positions will need generation
|
||||
return ESectionPopulationState.PARTIAL;
|
||||
}
|
||||
}
|
||||
enum ESectionPopulationState
|
||||
{
|
||||
COMPLETE,
|
||||
EMPTY,
|
||||
PARTIAL
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
|
||||
|
||||
|
||||
public boolean doesFileExist;
|
||||
//TODO: Atm can't find a better way to store when genQueue is checked.
|
||||
/** indicates if this file has been checked for missing sections to generate or not */
|
||||
public boolean genQueueChecked = false;
|
||||
|
||||
public AbstractFullDataSourceLoader fullDataSourceLoader;
|
||||
|
||||
+3
-17
@@ -57,7 +57,6 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
|
||||
private final IDhApiWorldGenerator generator;
|
||||
|
||||
/** contains the positions that need to be generated */
|
||||
//private final QuadTree<WorldGenTask> waitingTaskQuadTree;
|
||||
private final ConcurrentHashMap<DhSectionPos, WorldGenTask> waitingTasks = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentHashMap<DhSectionPos, InProgressWorldGenTaskGroup> inProgressGenTasksByLodPos = new ConcurrentHashMap<>();
|
||||
@@ -115,11 +114,6 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
|
||||
this.largestDataDetail = generator.getLargestDataDetailLevel();
|
||||
this.smallestDataDetail = generator.getSmallestDataDetailLevel();
|
||||
|
||||
//FIXME: Currently resizing view dist doesn't update this, causing some gen task to fail.
|
||||
int treeWidth = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH * 2; // TODO the *2 is to allow for generation edge cases, and should probably be removed at some point
|
||||
byte treeMinDetailLevel = LodUtil.CHUNK_DETAIL_LEVEL; // The min level should be at least fill in 1 ChunkSizedFullDataAccessor.
|
||||
//this.waitingTaskQuadTree = new QuadTree<>(treeWidth, DhBlockPos2D.ZERO /*the quad tree will be re-centered later*/, treeMinDetailLevel);
|
||||
|
||||
|
||||
if (this.minGranularity < LodUtil.CHUNK_DETAIL_LEVEL)
|
||||
{
|
||||
@@ -164,17 +158,9 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
|
||||
LodUtil.assertTrue(pos.getDetailLevel() > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
|
||||
|
||||
//if (this.waitingTaskQuadTree.isSectionPosInBounds(requestPos))
|
||||
{
|
||||
CompletableFuture<WorldGenResult> future = new CompletableFuture<>();
|
||||
//this.waitingTaskQuadTree.setValue(requestPos, new WorldGenTask(pos, requiredDataDetail, tracker, future));
|
||||
waitingTasks.put(pos, new WorldGenTask(pos, requiredDataDetail, tracker, future));
|
||||
return future;
|
||||
}
|
||||
//else
|
||||
//{
|
||||
//return CompletableFuture.completedFuture(WorldGenResult.CreateFail());
|
||||
//}
|
||||
CompletableFuture<WorldGenResult> future = new CompletableFuture<>();
|
||||
this.waitingTasks.put(pos, new WorldGenTask(pos, requiredDataDetail, tracker, future));
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user