Skip to content
This repository was archived by the owner on Mar 8, 2024. It is now read-only.

Commit 7b0a56c

Browse files
committed
Starlight 0.0.2-RC3
1. Fix chunk relighting In order to make relighting more reliable, move the emptiness map lookups to their own cache. This allows us to not clobber/use emptiness map values for chunks that were not relight during the call. More importantly, fix a typo where we supplied the wrong chunk argument to the emptiness change function for chunk neighbours - this caused the nibbles for the target chunk to be clobbered. 2. Fix broken edge checks While edge checks are not currently used, it doesn't mean they should be broken. Edge checks should be able to happen on null nibbles for block lighting (sky lighting will not have nibbles marked null during edge checks). 3. Make handleEmptySectionChanges non-relaxed serverside For the server, it should be that the chunks in 1 radius are loaded during this call. 4. Fix incorrect neighbour nibble init logic We need to be copying the whole array, not just the first 9 values. 5. Fix potential missed updateVisible calls rewriteNibbleCacheForSkylight could set a value in the cache to null and not update the nibble. Now the call will call updateVisible when removing nibbles from the cache. 6. Fix skylight propagation on the -1 chunk section Allow sources to be set up on y=-16, and fix light retrieval for y < -16
1 parent 1da2560 commit 7b0a56c

File tree

9 files changed

+92
-64
lines changed

9 files changed

+92
-64
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Starlight (BETA)
1+
Starlight (Fabric) (BETA)
22
==
33
Fabric mod for completely rewriting the vanilla light engine.
44

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ minecraft_version=1.16.4
66
yarn_mappings=1.16.4+build.7
77
loader_version=0.10.8
88
# Mod Properties
9-
mod_version=0.0.2-RC2
9+
mod_version=0.0.2-RC3
1010
maven_group=ca.spottedleaf.starlight
1111
archives_base_name=starlight
1212
# Dependencies

src/main/java/ca/spottedleaf/starlight/common/light/BlockStarLightEngine.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ protected boolean canUseChunk(final Chunk chunk) {
3737
return chunk.getStatus().isAtLeast(ChunkStatus.LIGHT) && (this.isClientSide || chunk.isLightOn());
3838
}
3939

40+
@Override
41+
protected boolean[][] getEmptinessMap(final Chunk chunk) {
42+
return null;
43+
}
44+
4045
@Override
4146
protected void handleEmptySectionChanges(final ChunkProvider lightAccess, final Chunk chunk,
4247
final Boolean[] emptinessChanges, final boolean unlit) {}

src/main/java/ca/spottedleaf/starlight/common/light/SkyStarLightEngine.java

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ protected void handleEmptySectionChanges(final ChunkProvider lightAccess, final
4949
final int chunkX = chunk.getPos().x;
5050
final int chunkZ = chunk.getPos().z;
5151

52+
final boolean[][] chunkEmptinessMap = this.getEmptinessMap(chunkX, chunkZ);
53+
5254
// index = (cx + 2) + 5*(cz + 2)
5355
long loadedNeighboursBitset = 0L;
5456
long unloadedNeighbourBitset = 0L;
@@ -60,7 +62,7 @@ protected void handleEmptySectionChanges(final ChunkProvider lightAccess, final
6062
continue;
6163
}
6264

63-
final boolean[][] neighbourEmptinessMap = ((ExtendedChunk)neighbour).getEmptinessMap();
65+
final boolean[][] neighbourEmptinessMap = this.getEmptinessMap(dx + chunkX, dz + chunkZ);
6466
for (int i = 0; i < neighbourEmptinessMap.length; ++i) {
6567
// index = (cx + 1) + 3*(cz + 1)
6668
final int dx2 = (i % 3) - 1;
@@ -80,14 +82,11 @@ protected void handleEmptySectionChanges(final ChunkProvider lightAccess, final
8082
loadedNeighboursBitset |= 1L << ((0 + 2) + 5*(0 + 2));
8183

8284
final boolean[] needsDeInitCheck = new boolean[9];
83-
final boolean needsInit = ((ExtendedChunk)chunk).getEmptinessMap()[ExtendedChunk.getEmptinessMapIndex(0, 0)] == null;
85+
final boolean needsInit = unlit || chunkEmptinessMap[ExtendedChunk.getEmptinessMapIndex(0, 0)] == null;
8486
if (needsInit) {
85-
((ExtendedChunk)chunk).getEmptinessMap()[ExtendedChunk.getEmptinessMapIndex(0, 0)] = new boolean[16];
87+
chunkEmptinessMap[ExtendedChunk.getEmptinessMapIndex(0, 0)] = new boolean[16];;
8688
}
8789

88-
// index = (cx + 2) + 5*(cz + 2)
89-
final boolean[][] chunkEmptinessMap = ((ExtendedChunk)chunk).getEmptinessMap();
90-
9190
// this chunk is new, so we need to init neighbours
9291
// because this chunk might have been modified inbetween loading/saving, we have to rewrite the emptiness map
9392
// for our neighbours, so don't bother checking if they exist & whether they even needed a de-init recalc
@@ -99,19 +98,20 @@ protected void handleEmptySectionChanges(final ChunkProvider lightAccess, final
9998
// when it does though, it'll come by and initialise our map for it
10099
continue;
101100
}
101+
final boolean[][] neighbourEmptinessMap = this.getEmptinessMap(dx + chunkX, dz + chunkZ);
102102

103103
if (needsInit && (dx | dz) != 0) {
104104
// init neighbour
105-
neighbour.getEmptinessMap()[ExtendedChunk.getEmptinessMapIndex(-dx, -dz)] = new boolean[16];
105+
neighbourEmptinessMap[ExtendedChunk.getEmptinessMapIndex(-dx, -dz)] = new boolean[16];
106106

107-
if (neighbour.getEmptinessMap()[ExtendedChunk.getEmptinessMapIndex(0, 0)] != null) {
107+
if (neighbourEmptinessMap[ExtendedChunk.getEmptinessMapIndex(0, 0)] != null) {
108108
// init ourselves
109109
System.arraycopy(
110-
neighbour.getEmptinessMap()[ExtendedChunk.getEmptinessMapIndex(0, 0)],
110+
neighbourEmptinessMap[ExtendedChunk.getEmptinessMapIndex(0, 0)],
111111
0,
112112
chunkEmptinessMap[ExtendedChunk.getEmptinessMapIndex(dx, dz)] = new boolean[16],
113113
0,
114-
9
114+
16
115115
);
116116
}
117117
}
@@ -161,7 +161,7 @@ protected void handleEmptySectionChanges(final ChunkProvider lightAccess, final
161161
}
162162

163163
// update neighbour map
164-
neighbour.getEmptinessMap()[ExtendedChunk.getEmptinessMapIndex(-dx, -dz)][sectionY] = empty;
164+
this.getEmptinessMap(dx + chunkX, dz + chunkZ)[ExtendedChunk.getEmptinessMapIndex(-dx, -dz)][sectionY] = empty;
165165
}
166166
}
167167
}
@@ -176,11 +176,11 @@ protected void handleEmptySectionChanges(final ChunkProvider lightAccess, final
176176
final int neighbourX = (i % 3) - 1 + chunkX;
177177
final int neighbourZ = (i / 3) - 1 + chunkZ;
178178

179-
final boolean[][] neighbourEmptinessMap = ((ExtendedChunk)this.getChunkInCache(neighbourX, neighbourZ)).getEmptinessMap();
179+
final boolean[][] neighbourEmptinessMap = this.getEmptinessMap(neighbourX, neighbourZ);
180180

181181
for (int sectionY = 16; sectionY >= -1; --sectionY) {
182182
final SWMRNibbleArray nibble = this.getNibbleFromCache(neighbourX, sectionY, neighbourZ);
183-
if (nibble.isNullNibbleUpdating()) {
183+
if (nibble == null || nibble.isNullNibbleUpdating()) {
184184
// already null
185185
continue;
186186
}
@@ -234,8 +234,7 @@ protected final void initNibbleForLitChunk(final SWMRNibbleArray currNibble, fin
234234
return;
235235
}
236236

237-
final boolean[] emptinessMap = ((ExtendedChunk)this.getChunkInCache(chunkX, chunkZ))
238-
.getEmptinessMap()[ExtendedChunk.getEmptinessMapIndex(0, 0)];
237+
final boolean[] emptinessMap = this.getEmptinessMap(chunkX, chunkZ)[ExtendedChunk.getEmptinessMapIndex(0, 0)];
239238

240239
// are we above this chunk's lowest empty section?
241240
int lowestY = -2;
@@ -284,6 +283,7 @@ protected final void rewriteNibbleCacheForSkylight(final Chunk chunk) {
284283
if (nibble != null && nibble.isNullNibbleUpdating()) {
285284
// stop propagation in these areas
286285
this.nibbleCache[index] = null;
286+
nibble.updateVisible();
287287
}
288288
}
289289
}
@@ -361,6 +361,11 @@ protected SWMRNibbleArray[] getNibblesOnChunk(final Chunk chunk) {
361361
return ((ExtendedChunk)chunk).getSkyNibbles();
362362
}
363363

364+
@Override
365+
protected boolean[][] getEmptinessMap(final Chunk chunk) {
366+
return ((ExtendedChunk)chunk).getEmptinessMap();
367+
}
368+
364369
@Override
365370
protected void setNibbles(final Chunk chunk, final SWMRNibbleArray[] to) {
366371
((ExtendedChunk)chunk).setSkyNibbles(to);
@@ -472,7 +477,7 @@ protected void propagateBlockChanges(final ChunkProvider lightAccess, final Chun
472477
// ensure section is checked
473478
this.checkNullSection(columnX >> 4, maxPropagationY >> 4, columnZ >> 4, true);
474479

475-
for (int currY = maxPropagationY; currY >= -15; --currY) {
480+
for (int currY = maxPropagationY; currY >= (-1 << 4); --currY) {
476481
if ((currY & 15) == 15) {
477482
// ensure section is checked
478483
this.checkNullSection(columnX >> 4, (currY >> 4), columnZ >> 4, true);
@@ -611,7 +616,7 @@ protected void lightChunk(final ChunkProvider lightAccess, final Chunk chunk, fi
611616
final int maxZ = worldChunkZ + 16;
612617
for (int currZ = minZ; currZ <= maxZ; ++currZ) {
613618
for (int currX = minX; currX <= maxX; ++currX) {
614-
int maxY = -33;
619+
int maxY = ((-1 -1) << 4);
615620

616621
// ensure the section below is always checked
617622
this.checkNullSection(currX >> 4, highestNonEmptySection, currZ >> 4, false);
@@ -725,12 +730,12 @@ protected void lightChunk(final ChunkProvider lightAccess, final Chunk chunk, fi
725730
// not required to propagate here, but this will reduce the hit of the edge checks
726731
this.performLightIncrease(lightAccess);
727732

728-
for (int y = -1; y <= 16; ++y) {
733+
for (int y = 16; y >= -1; --y) {
729734
this.checkNullSection(chunkX, y, chunkZ, false);
730735
}
731736
this.checkChunkEdges(lightAccess, chunk, -1, 16);
732737
} else {
733-
for (int y = -1; y <= highestNonEmptySection; ++y) {
738+
for (int y = highestNonEmptySection; y >= -1; --y) {
734739
this.checkNullSection(chunkX, y, chunkZ, false);
735740
}
736741
this.propagateNeighbourLevels(lightAccess, chunk, -1, highestNonEmptySection);
@@ -797,7 +802,7 @@ protected final int tryPropagateSkylight(final BlockView world, final int worldX
797802
above = AIR_BLOCK_STATE;
798803
}
799804

800-
for (;startY >= -15; --startY) {
805+
for (;startY >= (-1 << 4); --startY) {
801806
if ((startY & 15) == 15) {
802807
// ensure this section is always checked
803808
this.checkNullSection(worldX >> 4, startY >> 4, worldZ >> 4, extrudeInitialised);

src/main/java/ca/spottedleaf/starlight/common/light/StarLightEngine.java

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ public AxisDirection getOpposite() {
9898
// index = x + (z * 5)
9999
protected final Chunk[] chunkCache = new Chunk[5 * 5];
100100

101+
// index = x + (z * 5)
102+
protected final boolean[][][] emptinessMapCache = new boolean[5 * 5][][];
103+
101104
protected final BlockPos.Mutable mutablePos1 = new BlockPos.Mutable();
102105
protected final BlockPos.Mutable mutablePos2 = new BlockPos.Mutable();
103106
protected final BlockPos.Mutable mutablePos3 = new BlockPos.Mutable();
@@ -176,6 +179,7 @@ protected final void setupCaches(final ChunkProvider chunkProvider, final int ce
176179
this.setChunkInCache(cx, cz, chunk);
177180
this.setBlocksForChunkInCache(cx, cz, chunk.getSectionArray());
178181
this.setNibblesForChunkInCache(cx, cz, this.getNibblesOnChunk(chunk));
182+
this.setEmptinessMapCache(cx, cz, this.getEmptinessMap(chunk));
179183
}
180184
}
181185
}
@@ -247,6 +251,7 @@ protected final void destroyCaches() {
247251
Arrays.fill(this.sectionCache, null);
248252
Arrays.fill(this.nibbleCache, null);
249253
Arrays.fill(this.chunkCache, null);
254+
Arrays.fill(this.emptinessMapCache, null);
250255
if (this.isClientSide) {
251256
Arrays.fill(this.notifyUpdateCache, false);
252257
}
@@ -349,6 +354,14 @@ protected final void setLightLevel(final int sectionIndex, final int localIndex,
349354
}
350355
}
351356

357+
protected final boolean[][] getEmptinessMap(final int chunkX, final int chunkZ) {
358+
return this.emptinessMapCache[chunkX + 5*chunkZ + this.chunkIndexOffset];
359+
}
360+
361+
protected final void setEmptinessMapCache(final int chunkX, final int chunkZ, final boolean[][] emptinessMap) {
362+
this.emptinessMapCache[chunkX + 5*chunkZ + this.chunkIndexOffset] = emptinessMap;
363+
}
364+
352365
public static SWMRNibbleArray[] getFilledEmptyLight() {
353366
final SWMRNibbleArray[] ret = getEmptyLightArray();
354367

@@ -363,13 +376,14 @@ public static SWMRNibbleArray[] getEmptyLightArray() {
363376
return new SWMRNibbleArray[16 - (-1) + 1];
364377
}
365378

379+
protected abstract boolean[][] getEmptinessMap(final Chunk chunk);
380+
366381
protected abstract SWMRNibbleArray[] getNibblesOnChunk(final Chunk chunk);
367382

368383
protected abstract void setNibbles(final Chunk chunk, final SWMRNibbleArray[] to);
369384

370385
protected abstract boolean canUseChunk(final Chunk chunk);
371386

372-
// TODO include section changes
373387
public final void blocksChangedInChunk(final ChunkProvider lightAccess, final int chunkX, final int chunkZ,
374388
final Set<BlockPos> positions, final Boolean[] changedSections) {
375389
this.setupCaches(lightAccess, chunkX * 16 + 7, 128, chunkZ * 16 + 7, this.isClientSide);
@@ -410,7 +424,7 @@ protected void checkChunkEdge(final ChunkProvider lightAccess, final Chunk chunk
410424
final SWMRNibbleArray neighbourNibble = this.getNibbleFromCache(chunkX + neighbourOffX,
411425
chunkY, chunkZ + neighbourOffZ);
412426

413-
if (neighbourNibble == null || neighbourNibble.isNullNibbleUpdating()) {
427+
if (neighbourNibble == null) {
414428
continue;
415429
}
416430

@@ -527,7 +541,7 @@ protected final void propagateNeighbourLevels(final ChunkProvider lightAccess, f
527541

528542
for (int currSectionY = toSection; currSectionY >= fromSection; --currSectionY) {
529543
final SWMRNibbleArray currNibble = this.getNibbleFromCache(chunkX, currSectionY, chunkZ);
530-
if (this.skylightPropagator && currNibble == null) {
544+
if (currNibble == null) {
531545
continue;
532546
}
533547
for (final AxisDirection direction : ONLY_HORIZONTAL_DIRECTIONS) {
@@ -537,16 +551,7 @@ protected final void propagateNeighbourLevels(final ChunkProvider lightAccess, f
537551
final SWMRNibbleArray neighbourNibble = this.getNibbleFromCache(chunkX + neighbourOffX,
538552
currSectionY, chunkZ + neighbourOffZ);
539553

540-
if (neighbourNibble == null || neighbourNibble.isNullNibbleUpdating()) {
541-
continue;
542-
}
543-
544-
if (this.skylightPropagator && currNibble.isNullNibbleUpdating()) {
545-
// TODO in what situation does this happen? Pretty sure it's erroneous.
546-
continue;
547-
}
548-
549-
if (!neighbourNibble.isInitialisedUpdating()) {
554+
if (neighbourNibble == null || !neighbourNibble.isInitialisedUpdating()) {
550555
// can't pull from 0
551556
continue;
552557
}
@@ -588,9 +593,9 @@ protected final void propagateNeighbourLevels(final ChunkProvider lightAccess, f
588593
for (int currY = currSectionY << 4, maxY = currY | 15; currY <= maxY; ++currY) {
589594
for (int i = 0, currX = startX, currZ = startZ; i < 16; ++i, currX += incX, currZ += incZ) {
590595
final int level = neighbourNibble.getUpdating(
591-
(currX & 15) |
592-
(currZ & 15) << 4 |
593-
(currY & 15) << 8
596+
(currX & 15)
597+
| ((currZ & 15) << 4)
598+
| ((currY & 15) << 8)
594599
);
595600

596601
if (level <= 1) {
@@ -627,7 +632,7 @@ public static Boolean[] getEmptySectionsForChunk(final Chunk chunk) {
627632

628633
public final void handleEmptySectionChanges(final ChunkProvider lightAccess, final int chunkX, final int chunkZ,
629634
final Boolean[] emptinessChanges) {
630-
this.setupCaches(lightAccess, chunkX * 16 + 7, 128, chunkZ * 16 + 7, true);
635+
this.setupCaches(lightAccess, chunkX * 16 + 7, 128, chunkZ * 16 + 7, this.isClientSide);
631636
if (this.isClientSide) {
632637
// force current chunk into cache
633638
final Chunk chunk = (Chunk)lightAccess.getChunk(chunkX, chunkZ);
@@ -638,6 +643,7 @@ public final void handleEmptySectionChanges(final ChunkProvider lightAccess, fin
638643
this.setChunkInCache(chunkX, chunkZ, chunk);
639644
this.setBlocksForChunkInCache(chunkX, chunkZ, chunk.getSectionArray());
640645
this.setNibblesForChunkInCache(chunkX, chunkZ, this.getNibblesOnChunk(chunk));
646+
this.setEmptinessMapCache(chunkX, chunkZ, this.getEmptinessMap(chunk));
641647
}
642648
try {
643649
final Chunk chunk = this.getChunkInCache(chunkX, chunkZ);
@@ -701,6 +707,7 @@ public final void light(final ChunkProvider lightAccess, final int chunkX, final
701707
this.setChunkInCache(chunkX, chunkZ, chunk);
702708
this.setBlocksForChunkInCache(chunkX, chunkZ, chunk.getSectionArray());
703709
this.setNibblesForChunkInCache(chunkX, chunkZ, this.getNibblesOnChunk(chunk));
710+
this.setEmptinessMapCache(chunkX, chunkZ, this.getEmptinessMap(chunk));
704711

705712
try {
706713
this.handleEmptySectionChanges(lightAccess, chunk, emptySections, true);
@@ -721,10 +728,13 @@ protected final void relightChunk(final ChunkProvider lightAccess, final Chunk c
721728
this.setupEncodeOffset(chunkPos.x * 16 + 7, 128, chunkPos.z * 16 + 7);
722729

723730
try {
731+
final SWMRNibbleArray[] chunkNibbles = getFilledEmptyLight();
732+
724733
this.setChunkInCache(chunkPos.x, chunkPos.z, chunk);
725734
this.setBlocksForChunkInCache(chunkPos.x, chunkPos.z, chunk.getSectionArray());
726-
final SWMRNibbleArray[] chunkNibbles = getFilledEmptyLight();
727735
this.setNibblesForChunkInCache(chunkPos.x, chunkPos.z, chunkNibbles);
736+
this.setEmptinessMapCache(chunkPos.x, chunkPos.z, new boolean[9][]);
737+
728738
this.handleEmptySectionChanges(lightAccess, chunk, getEmptySectionsForChunk(chunk), true);
729739
this.lightChunk(lightAccess, chunk, false);
730740

@@ -745,7 +755,9 @@ protected final void relightChunk(final ChunkProvider lightAccess, final Chunk c
745755
this.setChunkInCache(cx, cz, neighbourChunk);
746756
this.setBlocksForChunkInCache(cx, cz, neighbourChunk.getSectionArray());
747757
this.setNibblesForChunkInCache(cx, cz, getFilledEmptyLight());
748-
this.handleEmptySectionChanges(lightAccess, chunk, getEmptySectionsForChunk(neighbourChunk), true);
758+
this.setEmptinessMapCache(cx, cz, new boolean[9][]);
759+
760+
this.handleEmptySectionChanges(lightAccess, neighbourChunk, getEmptySectionsForChunk(neighbourChunk), true);
749761
this.lightChunk(lightAccess, neighbourChunk, false);
750762
}
751763
}

0 commit comments

Comments
 (0)