Fix DH beacon detection logic mutating input block pos

alternate title: Fix DH beacon detection logic breaking the lighting engine
This commit is contained in:
James Seibel
2024-08-29 19:54:36 -05:00
parent 1d6d712483
commit ed39b6181f
5 changed files with 39 additions and 25 deletions
@@ -76,12 +76,12 @@ public class DhLightingEngine
// try-finally to handle the stableArray resources
StableLightPosStack blockLightPosQueue = null;
StableLightPosStack skyLightPosQueue = null;
StableLightPosStack blockLightWorldPosQueue = null;
StableLightPosStack skyLightWorldPosQueue = null;
try
{
blockLightPosQueue = StableLightPosStack.borrowStableLightPosArray();
skyLightPosQueue = StableLightPosStack.borrowStableLightPosArray();
blockLightWorldPosQueue = StableLightPosStack.borrowStableLightPosArray();
skyLightWorldPosQueue = StableLightPosStack.borrowStableLightPosArray();
@@ -114,11 +114,15 @@ public class DhLightingEngine
//==================//
// set block lights //
//==================//
// get and set the adjacent chunk's initial block lights
final DhBlockPos relLightBlockPos = PRIMARY_BLOCK_POS_REF.get();
final DhBlockPos relBlockPos = SECONDARY_BLOCK_POS_REF.get();
ArrayList<DhBlockPos> blockLightPosList = chunk.getBlockLightPosList();
ArrayList<DhBlockPos> blockLightPosList = chunk.getWorldBlockLightPosList();
for (int blockLightIndex = 0; blockLightIndex < blockLightPosList.size(); blockLightIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
{
DhBlockPos blockLightPos = blockLightPosList.get(blockLightIndex);
@@ -127,14 +131,18 @@ public class DhLightingEngine
// get the light
IBlockStateWrapper blockState = chunk.getBlockState(relLightBlockPos);
int lightValue = blockState.getLightEmission();
blockLightPosQueue.push(blockLightPos.x, blockLightPos.y, blockLightPos.z, lightValue);
blockLightWorldPosQueue.push(blockLightPos.x, blockLightPos.y, blockLightPos.z, lightValue);
// set the light
blockLightPos.mutateToChunkRelativePos(relBlockPos);
chunk.setDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, lightValue);
}
//================//
// set sky lights //
//================//
// get and set the adjacent chunk's initial skylights,
// if the dimension has skylights
if (maxSkyLight > 0)
@@ -160,7 +168,7 @@ public class DhLightingEngine
// add sky light to the queue
DhBlockPos skyLightPos = new DhBlockPos(chunk.getMinBlockX() + relX, y, chunk.getMinBlockZ() + relZ);
skyLightPosQueue.push(skyLightPos.x, skyLightPos.y, skyLightPos.z, maxSkyLight);
skyLightWorldPosQueue.push(skyLightPos.x, skyLightPos.y, skyLightPos.z, maxSkyLight);
// set the chunk's sky light
skyLightPos.mutateToChunkRelativePos(relBlockPos);
@@ -180,12 +188,12 @@ public class DhLightingEngine
}
// block light
this.propagateLightPosList(blockLightPosQueue, adjacentChunkHolder,
this.propagateLightPosList(blockLightWorldPosQueue, adjacentChunkHolder,
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z),
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, newLightValue));
// sky light
this.propagateLightPosList(skyLightPosQueue, adjacentChunkHolder,
this.propagateLightPosList(skyLightWorldPosQueue, adjacentChunkHolder,
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z),
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, newLightValue));
}
@@ -195,8 +203,8 @@ public class DhLightingEngine
}
finally
{
StableLightPosStack.returnStableLightPosArray(blockLightPosQueue);
StableLightPosStack.returnStableLightPosArray(skyLightPosQueue);
StableLightPosStack.returnStableLightPosArray(blockLightWorldPosQueue);
StableLightPosStack.returnStableLightPosArray(skyLightWorldPosQueue);
}
@@ -145,13 +145,17 @@ public class DhBlockPos
}
}
/** Returns a new {@link DhBlockPos} limits to a value between 0 and 15 (inclusive) */
public DhBlockPos convertToChunkRelativePos() { return this.mutateToChunkRelativePos(null); }
/** Returns a new {@link DhBlockPos} limited to a value between 0 and 15 (inclusive) */
public DhBlockPos createChunkRelativePos() { return this.mutateOrCreateChunkRelativePos(null); }
/** Limits the input {@link DhBlockPos} to a value between 0 and 15 (inclusive) */
public void mutateToChunkRelativePos(DhBlockPos mutableBlockPos) { this.mutateOrCreateChunkRelativePos(mutableBlockPos); }
/**
* Limits the block position to a value between 0 and 15 (inclusive)
* If not null, mutates "mutableBlockPos"
*
* @return the mutated or created {@link DhBlockPos}
*/
public DhBlockPos mutateToChunkRelativePos(@Nullable DhBlockPos mutableBlockPos)
private DhBlockPos mutateOrCreateChunkRelativePos(@Nullable DhBlockPos mutableBlockPos)
{
// move the position into the range -15 and +15
int relX = (this.x % LodUtil.CHUNK_WIDTH);
@@ -351,7 +351,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
// ))
{
// prepare this section for rendering
// TODO this should fire for the lowest detail level first to improve loading speed
if (!renderSection.gpuUploadInProgress() && renderSection.renderBuffer == null)
{
nodesNeedingLoading.add(renderSection);
@@ -90,7 +90,8 @@ public interface IChunkWrapper extends IBindable
int getSkyLight(int relX, int relY, int relZ);
ArrayList<DhBlockPos> getBlockLightPosList();
/** Note: don't modify this array, it will only be generated once and then shared between uses */
ArrayList<DhBlockPos> getWorldBlockLightPosList();
default boolean blockPosInsideChunk(DhBlockPos blockPos) { return this.blockPosInsideChunk(blockPos.x, blockPos.y, blockPos.z); }
@@ -321,14 +322,15 @@ public interface IChunkWrapper extends IBindable
}
// light emitting blocks (if the light changes then the LOD definitely needs to be updated)
ArrayList<DhBlockPos> lightPosList = this.getBlockLightPosList();
final DhBlockPos relPos = new DhBlockPos();
ArrayList<DhBlockPos> lightPosList = this.getWorldBlockLightPosList();
for (int i = 0; i < lightPosList.size(); i++)
{
DhBlockPos pos = lightPosList.get(i);
pos = pos.mutateToChunkRelativePos(pos);
pos.mutateToChunkRelativePos(relPos);
hash = (hash * primeBlockMultiplier) + this.getBlockState(pos.x, pos.y, pos.z).hashCode();
hash = (hash * primeHeightMultiplier) + pos.y;
hash = (hash * primeBlockMultiplier) + this.getBlockState(relPos.x, relPos.y, relPos.z).hashCode();
hash = (hash * primeHeightMultiplier) + relPos.y;
}
@@ -342,11 +344,12 @@ public interface IChunkWrapper extends IBindable
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(this, neighbourChunkList);
// since beacons emit light we can check only the positions that are emitting light
ArrayList<DhBlockPos> blockPosList = this.getBlockLightPosList();
final DhBlockPos relPos = new DhBlockPos();
ArrayList<DhBlockPos> blockPosList = this.getWorldBlockLightPosList();
for (int i = 0; i < blockPosList.size(); i++)
{
DhBlockPos pos = blockPosList.get(i);
DhBlockPos relPos = pos.convertToChunkRelativePos();
pos.mutateToChunkRelativePos(relPos);
IBlockStateWrapper block = this.getBlockState(relPos);
@@ -367,7 +370,7 @@ public interface IChunkWrapper extends IBindable
@Nullable
static Color getBeaconColor(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder)
{
DhBlockPos beaconRelPos = beaconPos.convertToChunkRelativePos();
DhBlockPos beaconRelPos = beaconPos.createChunkRelativePos();
DhBlockPos baseRelPos = new DhBlockPos(0, beaconRelPos.y-1, 0);
@@ -399,7 +399,7 @@ public class LightingTestChunkWrapper implements IChunkWrapper
}
@Override
public ArrayList<DhBlockPos> getBlockLightPosList() { return this.blockLightPosList; }
public ArrayList<DhBlockPos> getWorldBlockLightPosList() { return this.blockLightPosList; }
@Override
public boolean doNearbyChunksExist() { return false; }