Skip to content

Commit 36132bd

Browse files
committed
chore: experimental unsafe setter for lighting to bypass light data copy
1 parent ef9184a commit 36132bd

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

src/main/java/net/hollowcube/polar/PolarLoader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,9 @@ private void loadSection(@NotNull PolarSection sectionData, @NotNull Section sec
271271

272272
// Light
273273
if (loadLighting && sectionData.blockLightContent() != LightContent.MISSING)
274-
section.setBlockLight(getLightArray(sectionData.blockLightContent(), sectionData.blockLight()));
274+
UnsafeOps.unsafeUpdateBlockLightArray(section.blockLight(), getLightArray(sectionData.blockLightContent(), sectionData.blockLight()));
275275
if (loadLighting && sectionData.skyLightContent() != LightContent.MISSING)
276-
section.setSkyLight(getLightArray(sectionData.skyLightContent(), sectionData.skyLight()));
276+
UnsafeOps.unsafeUpdateSkyLightArray(section.skyLight(), getLightArray(sectionData.skyLightContent(), sectionData.skyLight()));
277277
}
278278

279279
static byte[] getLightArray(@NotNull LightContent content, byte @Nullable [] data) {

src/main/java/net/hollowcube/polar/StreamingPolarLoader.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,18 +245,18 @@ private void readSection(@NotNull NetworkBuffer buffer, @NotNull Section section
245245
: (buffer.read(BOOLEAN) ? PolarSection.LightContent.PRESENT : PolarSection.LightContent.MISSING);
246246
byte[] blockLight = blockLightContent == PolarSection.LightContent.PRESENT ? buffer.read(LIGHT_DATA) : null;
247247
if (loadLighting && blockLightContent != PolarSection.LightContent.MISSING)
248-
section.setBlockLight(getLightArray(blockLightContent, blockLight));
248+
unsafeUpdateBlockLightArray(section.blockLight(), getLightArray(blockLightContent, blockLight));
249249

250250
var skyLightContent = version >= PolarWorld.VERSION_IMPROVED_LIGHT
251251
? PolarSection.LightContent.VALUES[buffer.read(BYTE)]
252252
: (buffer.read(BOOLEAN) ? PolarSection.LightContent.PRESENT : PolarSection.LightContent.MISSING);
253253
byte[] skyLight = skyLightContent == PolarSection.LightContent.PRESENT ? buffer.read(LIGHT_DATA) : null;
254254
if (loadLighting && skyLightContent != PolarSection.LightContent.MISSING)
255-
section.setSkyLight(getLightArray(skyLightContent, skyLight));
255+
unsafeUpdateSkyLightArray(section.skyLight(), getLightArray(skyLightContent, skyLight));
256256
} else if (buffer.read(BOOLEAN)) {
257257
if (loadLighting) {
258-
section.setBlockLight(buffer.read(LIGHT_DATA));
259-
section.setSkyLight(buffer.read(LIGHT_DATA));
258+
unsafeUpdateBlockLightArray(section.blockLight(), buffer.read(LIGHT_DATA));
259+
unsafeUpdateSkyLightArray(section.skyLight(), buffer.read(LIGHT_DATA));
260260
} else {
261261
buffer.advanceRead(2048 * 2); // Skip the data
262262
}

src/main/java/net/hollowcube/polar/UnsafeOps.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,29 @@
55
import net.minestom.server.instance.DynamicChunk;
66
import net.minestom.server.instance.InstanceContainer;
77
import net.minestom.server.instance.block.Block;
8+
import net.minestom.server.instance.light.Light;
89
import org.jetbrains.annotations.NotNull;
910
import org.jetbrains.annotations.Nullable;
1011

1112
import java.lang.invoke.MethodHandle;
1213
import java.lang.invoke.MethodHandles;
14+
import java.util.concurrent.atomic.AtomicBoolean;
1315

1416
final class UnsafeOps {
1517
private static final MethodHandle CACHE_CHUNK_HANDLE;
1618
private static final MethodHandle NEEDS_HEIGHTMAP_REFRESH_SETTER;
1719
private static final MethodHandle DYNAMIC_CHUNK_ENTRIES_GETTER;
1820
private static final MethodHandle DYNAMIC_CHUNK_TICKABLE_MAP_GETTER;
1921

22+
private static final MethodHandle BLOCK_LIGHT_CONTENT_SETTER;
23+
private static final MethodHandle BLOCK_LIGHT_CONTENT_PROPAGATION_SETTER;
24+
private static final MethodHandle BLOCK_LIGHT_IS_VALID_BORDERS_SETTER;
25+
private static final MethodHandle BLOCK_LIGHT_NEEDS_SEND_GETTER;
26+
private static final MethodHandle SKY_LIGHT_CONTENT_SETTER;
27+
private static final MethodHandle SKY_LIGHT_CONTENT_PROPAGATION_SETTER;
28+
private static final MethodHandle SKY_LIGHT_IS_VALID_BORDERS_SETTER;
29+
private static final MethodHandle SKY_LIGHT_NEEDS_SEND_GETTER;
30+
2031
static void unsafeCacheChunk(@NotNull InstanceContainer instance, @NotNull Chunk chunk) {
2132
try {
2233
CACHE_CHUNK_HANDLE.invokeExact(instance, chunk);
@@ -55,6 +66,30 @@ static void unsafeSetNeedsCompleteHeightmapRefresh(@NotNull Chunk chunk, boolean
5566
} else return null;
5667
}
5768

69+
static void unsafeUpdateBlockLightArray(@NotNull Light light, byte[] content) {
70+
try {
71+
BLOCK_LIGHT_CONTENT_SETTER.invoke(light, content);
72+
BLOCK_LIGHT_CONTENT_PROPAGATION_SETTER.invoke(light, content);
73+
BLOCK_LIGHT_IS_VALID_BORDERS_SETTER.invoke(light, true);
74+
var needsSend = (AtomicBoolean) BLOCK_LIGHT_NEEDS_SEND_GETTER.invoke(light);
75+
needsSend.set(true);
76+
} catch (Throwable t) {
77+
throw new RuntimeException(t);
78+
}
79+
}
80+
81+
static void unsafeUpdateSkyLightArray(@NotNull Light light, byte[] content) {
82+
try {
83+
SKY_LIGHT_CONTENT_SETTER.invoke(light, content);
84+
SKY_LIGHT_CONTENT_PROPAGATION_SETTER.invoke(light, content);
85+
SKY_LIGHT_IS_VALID_BORDERS_SETTER.invoke(light, true);
86+
var needsSend = (AtomicBoolean) SKY_LIGHT_NEEDS_SEND_GETTER.invoke(light);
87+
needsSend.set(true);
88+
} catch (Throwable t) {
89+
throw new RuntimeException(t);
90+
}
91+
}
92+
5893
static {
5994
try {
6095
var lookup = MethodHandles.privateLookupIn(InstanceContainer.class, MethodHandles.lookup());
@@ -75,5 +110,26 @@ static void unsafeSetNeedsCompleteHeightmapRefresh(@NotNull Chunk chunk, boolean
75110
} catch (IllegalAccessException | NoSuchFieldException e) {
76111
throw new RuntimeException(e);
77112
}
113+
114+
try {
115+
var blockLight = Class.forName("net.minestom.server.instance.light.BlockLight");
116+
var lookup = MethodHandles.privateLookupIn(blockLight, MethodHandles.lookup());
117+
BLOCK_LIGHT_CONTENT_SETTER = lookup.unreflectSetter(blockLight.getDeclaredField("content"));
118+
BLOCK_LIGHT_CONTENT_PROPAGATION_SETTER = lookup.unreflectSetter(blockLight.getDeclaredField("contentPropagation"));
119+
BLOCK_LIGHT_IS_VALID_BORDERS_SETTER = lookup.unreflectSetter(blockLight.getDeclaredField("isValidBorders"));
120+
BLOCK_LIGHT_NEEDS_SEND_GETTER = lookup.unreflectGetter(blockLight.getDeclaredField("needsSend"));
121+
} catch (NoSuchFieldException | ClassNotFoundException | IllegalAccessException e) {
122+
throw new RuntimeException(e);
123+
}
124+
try {
125+
var skyLight = Class.forName("net.minestom.server.instance.light.SkyLight");
126+
var lookup = MethodHandles.privateLookupIn(skyLight, MethodHandles.lookup());
127+
SKY_LIGHT_CONTENT_SETTER = lookup.unreflectSetter(skyLight.getDeclaredField("content"));
128+
SKY_LIGHT_CONTENT_PROPAGATION_SETTER = lookup.unreflectSetter(skyLight.getDeclaredField("contentPropagation"));
129+
SKY_LIGHT_IS_VALID_BORDERS_SETTER = lookup.unreflectSetter(skyLight.getDeclaredField("isValidBorders"));
130+
SKY_LIGHT_NEEDS_SEND_GETTER = lookup.unreflectGetter(skyLight.getDeclaredField("needsSend"));
131+
} catch (NoSuchFieldException | ClassNotFoundException | IllegalAccessException e) {
132+
throw new RuntimeException(e);
133+
}
78134
}
79135
}

0 commit comments

Comments
 (0)