Let's hope this is fine

This commit is contained in:
Nassim Jahnke 2023-06-07 20:03:53 +02:00
parent 3fbb00319f
commit c1bbde4bc6
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
4 changed files with 944 additions and 216 deletions

View File

@ -2533,7 +2533,7 @@ index 1cb95db25a20d38faacd99a5805630c1598e9db3..d99b2235038eb1aba8cda474c4aa51e2
@Override
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index c48318d9d5882dd87e423aecf27c31994af42bdb..e65c889dd1a84a1a8959d1cb80a8c233c3600a6f 100644
index c48318d9d5882dd87e423aecf27c31994af42bdb..77e5b1725a6b8264c098ab91aaf87ae19aedd145 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -8,6 +8,7 @@ import com.mojang.logging.LogUtils;
@ -2578,6 +2578,15 @@ index c48318d9d5882dd87e423aecf27c31994af42bdb..e65c889dd1a84a1a8959d1cb80a8c233
}
// CraftBukkit end
@@ -513,7 +513,7 @@ public abstract class PlayerList {
}
- public String remove(ServerPlayer entityplayer) { // CraftBukkit - return string
+ public net.kyori.adventure.text.Component remove(ServerPlayer entityplayer) { // CraftBukkit - return string // Paper - return Component
ServerLevel worldserver = entityplayer.serverLevel();
entityplayer.awardStat(Stats.LEAVE_GAME);
@@ -524,7 +524,7 @@ public abstract class PlayerList {
entityplayer.closeContainer();
}
@ -2784,7 +2793,7 @@ index 4c62df5a3781ec9df4a5c5f1b528649e6e8a62d1..affd1b8c7589ba59330dc0b6fc803cce
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
index 8e35fecb84fb9ed61cb31d218f8a21bb7cabeb48..5ba1c6a8e266883a1342815ec54f13df9054165b 100644
index 8e35fecb84fb9ed61cb31d218f8a21bb7cabeb48..41c863a104d53b6c6feb4576d5b62cead229efec 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
@@ -185,6 +185,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
@ -2795,6 +2804,34 @@ index 8e35fecb84fb9ed61cb31d218f8a21bb7cabeb48..5ba1c6a8e266883a1342815ec54f13df
((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit
}
}
@@ -208,20 +209,22 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
// CraftBukkit start
Player player1 = ((ServerPlayer) player).getBukkitEntity();
- String[] lines = new String[4];
+ // Paper start
+ List<net.kyori.adventure.text.Component> lines = new java.util.ArrayList<>();
for (int j = 0; j < messages.size(); ++j) {
- lines[j] = CraftChatMessage.fromComponent(text.getMessage(j, player.isTextFilteringEnabled()));
+ lines.add(io.papermc.paper.adventure.PaperAdventure.asAdventure(text.getMessage(j, player.isTextFilteringEnabled())));
}
SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player1, lines);
player.level().getCraftServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
- Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines());
- for (int j = 0; j < components.length; j++) {
- text = text.setMessage(j, components[j]);
+ // Paper start
+ for (int j = 0; j < 4; j++) {
+ text = text.setMessage(j, io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(j)));
}
+ // Paper end
}
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index 614e567eb1ef10ac7514909a8425e29ac3627d3d..60596c4ac2ebb8caf19d65591624275ba63b0199 100644
--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java

View File

@ -11,10 +11,10 @@ public net.minecraft.world.level.chunk.LevelChunkSection states
diff --git a/src/main/java/ca/spottedleaf/starlight/common/light/BlockStarLightEngine.java b/src/main/java/ca/spottedleaf/starlight/common/light/BlockStarLightEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a04eb6449d33d3f15c354b2ac98198f4ac12758
index 0000000000000000000000000000000000000000..09ddbbfdf656aa347830941abd7c994fac05d1c5
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/starlight/common/light/BlockStarLightEngine.java
@@ -0,0 +1,288 @@
@@ -0,0 +1,279 @@
+package ca.spottedleaf.starlight.common.light;
+
+import net.minecraft.core.BlockPos;
@ -218,58 +218,49 @@ index 0000000000000000000000000000000000000000..4a04eb6449d33d3f15c354b2ac98198f
+ this.performLightDecrease(lightAccess);
+ }
+
+ protected Iterator<BlockPos> getSources(final LightChunkGetter lightAccess, final ChunkAccess chunk) {
+ if (chunk instanceof ImposterProtoChunk || chunk instanceof LevelChunk) {
+ // implementation on Chunk is pretty awful, so write our own here. The big optimisation is
+ // skipping empty sections, and the far more optimised reading of types.
+ List<BlockPos> sources = new ArrayList<>();
+ protected List<BlockPos> getSources(final LightChunkGetter lightAccess, final ChunkAccess chunk) {
+ final List<BlockPos> sources = new ArrayList<>();
+
+ int offX = chunk.getPos().x << 4;
+ int offZ = chunk.getPos().z << 4;
+ final int offX = chunk.getPos().x << 4;
+ final int offZ = chunk.getPos().z << 4;
+
+ final LevelChunkSection[] sections = chunk.getSections();
+ for (int sectionY = this.minSection; sectionY <= this.maxSection; ++sectionY) {
+ final LevelChunkSection section = sections[sectionY - this.minSection];
+ if (section == null || section.hasOnlyAir()) {
+ // no sources in empty sections
+ continue;
+ }
+ final PalettedContainer<BlockState> states = section.states;
+ final int offY = sectionY << 4;
+
+ for (int index = 0; index < (16 * 16 * 16); ++index) {
+ final BlockState state = states.get(index);
+ if (state.getLightEmission() <= 0) {
+ continue;
+ }
+
+ // index = x | (z << 4) | (y << 8)
+ sources.add(new BlockPos(offX | (index & 15), offY | (index >>> 8), offZ | ((index >>> 4) & 15)));
+ }
+ final LevelChunkSection[] sections = chunk.getSections();
+ for (int sectionY = this.minSection; sectionY <= this.maxSection; ++sectionY) {
+ final LevelChunkSection section = sections[sectionY - this.minSection];
+ if (section == null || section.hasOnlyAir()) {
+ // no sources in empty sections
+ continue;
+ }
+ if (!section.maybeHas((final BlockState state) -> {
+ return state.getLightEmission() > 0;
+ })) {
+ // no light sources in palette
+ continue;
+ }
+ final PalettedContainer<BlockState> states = section.states;
+ final int offY = sectionY << 4;
+
+ return sources.iterator();
+ } else {
+ // world gen and lighting run in parallel, and if lighting keeps up it can be lighting chunks that are
+ // being generated. In the nether, lava will add a lot of sources. This resulted in quite a few CME crashes.
+ // So all we do spinloop until we can collect a list of sources, and even if it is out of date we will pick up
+ // the missing sources from checkBlock.
+ for (;;) {
+ try {
+ return chunk.getLights().collect(Collectors.toList()).iterator();
+ } catch (final Exception cme) {
+ for (int index = 0; index < (16 * 16 * 16); ++index) {
+ final BlockState state = states.get(index);
+ if (state.getLightEmission() <= 0) {
+ continue;
+ }
+
+ // index = x | (z << 4) | (y << 8)
+ sources.add(new BlockPos(offX | (index & 15), offY | (index >>> 8), offZ | ((index >>> 4) & 15)));
+ }
+ }
+
+ return sources;
+ }
+
+ @Override
+ public void lightChunk(final LightChunkGetter lightAccess, final ChunkAccess chunk, final boolean needsEdgeChecks) {
+ // setup sources
+ final int emittedMask = this.emittedLightMask;
+ for (final Iterator<BlockPos> positions = this.getSources(lightAccess, chunk); positions.hasNext();) {
+ final BlockPos pos = positions.next();
+ final List<BlockPos> positions = this.getSources(lightAccess, chunk);
+ for (int i = 0, len = positions.size(); i < len; ++i) {
+ final BlockPos pos = positions.get(i);
+ final BlockState blockState = this.getBlockState(pos.getX(), pos.getY(), pos.getZ());
+ final int emittedLight = blockState.getLightEmission() & emittedMask;
+
@ -1466,7 +1457,7 @@ index 0000000000000000000000000000000000000000..5f771962afb44175d446f138c8e74532
+}
diff --git a/src/main/java/ca/spottedleaf/starlight/common/light/StarLightEngine.java b/src/main/java/ca/spottedleaf/starlight/common/light/StarLightEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b0d92c68407cdb09ed8aac271b625d92db87017
index 0000000000000000000000000000000000000000..ad1eeebe6de219143492b94da309cb54ae9e0a5b
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/starlight/common/light/StarLightEngine.java
@@ -0,0 +1,1572 @@
@ -1537,7 +1528,7 @@ index 0000000000000000000000000000000000000000..1b0d92c68407cdb09ed8aac271b625d9
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.nms = Direction.fromNormal(x, y, z);
+ this.nms = Direction.fromDelta(x, y, z);
+ this.everythingButThisDirection = (long)(ALL_DIRECTIONS_BITSET ^ (1 << this.ordinal()));
+ // positive is always even, negative is always odd. Flip the 1 bit to get the negative direction.
+ this.everythingButTheOppositeDirection = (long)(ALL_DIRECTIONS_BITSET ^ (1 << (this.ordinal() ^ 1)));
@ -3044,10 +3035,10 @@ index 0000000000000000000000000000000000000000..1b0d92c68407cdb09ed8aac271b625d9
+}
diff --git a/src/main/java/ca/spottedleaf/starlight/common/light/StarLightInterface.java b/src/main/java/ca/spottedleaf/starlight/common/light/StarLightInterface.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a5fa60cb8156fe254a123e237d957ccb82f7195
index 0000000000000000000000000000000000000000..146c78a333e47cb4d8aa97700e19a12ca176ce76
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/starlight/common/light/StarLightInterface.java
@@ -0,0 +1,665 @@
@@ -0,0 +1,673 @@
+package ca.spottedleaf.starlight.common.light;
+
+import ca.spottedleaf.starlight.common.util.CoordinateUtils;
@ -3134,8 +3125,8 @@ index 0000000000000000000000000000000000000000..9a5fa60cb8156fe254a123e237d957cc
+ }
+
+ @Override
+ public void onBlockEmissionIncrease(final BlockPos blockPos, final int i) {
+ // skylight doesn't care
+ public void propagateLightSources(final ChunkPos chunkPos) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
@ -3145,12 +3136,12 @@ index 0000000000000000000000000000000000000000..9a5fa60cb8156fe254a123e237d957cc
+ }
+
+ @Override
+ public int runUpdates(final int i, final boolean bl, final boolean bl2) {
+ public int runLightUpdates() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableLightSources(final ChunkPos chunkPos, final boolean bl) {
+ public void setLightEnabled(final ChunkPos chunkPos, final boolean bl) {
+ throw new UnsupportedOperationException();
+ }
+
@ -3191,8 +3182,8 @@ index 0000000000000000000000000000000000000000..9a5fa60cb8156fe254a123e237d957cc
+ }
+
+ @Override
+ public void onBlockEmissionIncrease(final BlockPos blockPos, final int i) {
+ this.checkBlock(blockPos);
+ public void propagateLightSources(final ChunkPos chunkPos) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
@ -3202,12 +3193,12 @@ index 0000000000000000000000000000000000000000..9a5fa60cb8156fe254a123e237d957cc
+ }
+
+ @Override
+ public int runUpdates(final int i, final boolean bl, final boolean bl2) {
+ public int runLightUpdates() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void enableLightSources(final ChunkPos chunkPos, final boolean bl) {
+ public void setLightEnabled(final ChunkPos chunkPos, final boolean bl) {
+ throw new UnsupportedOperationException();
+ }
+
@ -3234,6 +3225,14 @@ index 0000000000000000000000000000000000000000..9a5fa60cb8156fe254a123e237d957cc
+ };
+ }
+
+ public boolean hasSkyLight() {
+ return this.hasSkyLight;
+ }
+
+ public boolean hasBlockLight() {
+ return this.hasBlockLight;
+ }
+
+ protected int getSkyLightValue(final BlockPos blockPos, final ChunkAccess chunk) {
+ if (!this.hasSkyLight) {
+ return 0;
@ -4081,7 +4080,7 @@ index 0000000000000000000000000000000000000000..177d0a969f3d72a34e773e8309c3719a
+}
diff --git a/src/main/java/ca/spottedleaf/starlight/common/util/SaveUtil.java b/src/main/java/ca/spottedleaf/starlight/common/util/SaveUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..6df9e01731d7fcbe279736b8fc18396595b95574
index 0000000000000000000000000000000000000000..8d1fd22c8b8b0ea3afce6fc3e92057194f82669f
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/starlight/common/util/SaveUtil.java
@@ -0,0 +1,192 @@
@ -4103,7 +4102,7 @@ index 0000000000000000000000000000000000000000..6df9e01731d7fcbe279736b8fc183965
+
+ private static final Logger LOGGER = LogUtils.getLogger();
+
+ private static final int STARLIGHT_LIGHT_VERSION = 8;
+ private static final int STARLIGHT_LIGHT_VERSION = 9;
+
+ public static int getLightVersion() {
+ return STARLIGHT_LIGHT_VERSION;
@ -4464,10 +4463,10 @@ index 0000000000000000000000000000000000000000..7784d72ddd6db00c674e22759c00c430
+ }
+}
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
index 941ca1b44c7cac656bdd76c7095887b1c3570aec..30e330cc3a2f51e4ec9555671e3eeb7bb14bdfa3 100644
index 32d186fefa5ff8afedcceacea0c6fa1cefbd5490..4620e64d8eb81520b75fbfbc64603e5887c7b016 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -55,7 +55,7 @@ public class ChunkHolder {
@@ -53,7 +53,7 @@ public class ChunkHolder {
private volatile CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage
private volatile CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage
private volatile CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> entityTickingChunkFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage
@ -4477,10 +4476,10 @@ index 941ca1b44c7cac656bdd76c7095887b1c3570aec..30e330cc3a2f51e4ec9555671e3eeb7b
private final DebugBuffer<ChunkHolder.ChunkSaveDebug> chunkToSaveHistory;
public int oldTicketLevel;
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 091c9e9bdbe4e956386df011ddf01cba42c30da1..578849f64de38dc75cdefeb243422c4c89a5c69c 100644
index a645263f148a25e5b4baeed51775eb8e7f596fe8..19bd6f9aee3ccb1af1b010ee51a54aa2d0bf9c84 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -134,7 +134,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -133,7 +133,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private final LongSet entitiesInLevel;
public final ServerLevel level;
private final ThreadedLevelLightEngine lightEngine;
@ -4490,10 +4489,10 @@ index 091c9e9bdbe4e956386df011ddf01cba42c30da1..578849f64de38dc75cdefeb243422c4c
private final RandomState randomState;
private final ChunkGeneratorStructureState chunkGeneratorState;
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
index fbe62a31ab199d83a1db0a4e0b1a813824e6f2c2..d38ad1b1eee92a6dbd2b79b4fcdb8959cdb4007d 100644
index d8b83c8c89143d78620f812c491a1950e3218eb1..f3c9a3dbb6f0e6f825b7477c89ed72ed52845419 100644
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
@@ -390,7 +390,7 @@ public abstract class DistanceManager {
@@ -386,7 +386,7 @@ public abstract class DistanceManager {
}
public void removeTicketsOnClosing() {
@ -4503,7 +4502,7 @@ index fbe62a31ab199d83a1db0a4e0b1a813824e6f2c2..d38ad1b1eee92a6dbd2b79b4fcdb8959
while (objectiterator.hasNext()) {
diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c832839e5aa9af 100644
index 65d72701b13c25dd701533833055e77c2aff9db8..10c9512be71f1b7eec7e0c74dc0e118d0b51735b 100644
--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
@@ -23,6 +23,17 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
@ -4522,10 +4521,10 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
+// Paper end
+
public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCloseable {
public static final int DEFAULT_BATCH_SIZE = 1000;
private static final Logger LOGGER = LogUtils.getLogger();
private final ProcessorMailbox<Runnable> taskMailbox;
@@ -32,13 +43,154 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
private volatile int taskPerBatch = 5;
@@ -33,12 +44,153 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
private final int taskPerBatch = 1000;
private final AtomicBoolean scheduled = new AtomicBoolean();
+ // Paper start - replace light engine impl
@ -4550,8 +4549,8 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
+ // Paper start - replace light engine impl
+ protected final ChunkAccess getChunk(final int chunkX, final int chunkZ) {
+ return ((ServerLevel)this.theLightEngine.getWorld()).getChunkSource().getChunkAtImmediately(chunkX, chunkZ);
}
+ }
+
+ protected long relightCounter;
+
+ public int relight(java.util.Set<ChunkPos> chunks_param,
@ -4674,18 +4673,17 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
+ if (sky == 15) return 15;
+ final int block = this.theLightEngine.getBlockReader().getLightValue(pos);
+ return Math.max(sky, block);
+ }
}
+ // Paper end - replace light engine imp
+
@Override
public void close() {
}
@@ -55,15 +207,16 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@@ -51,15 +203,16 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void checkBlock(BlockPos pos) {
- BlockPos blockPos = pos.immutable();
- this.addTask(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ThreadedLevelLightEngine.TaskType.POST_UPDATE, Util.name(() -> {
- this.addTask(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
- super.checkBlock(blockPos);
- }, () -> {
- return "checkBlock " + blockPos;
@ -4703,7 +4701,7 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
this.addTask(pos.x, pos.z, () -> {
return 0;
}, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
@@ -86,17 +239,16 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@@ -82,17 +235,16 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void updateSectionStatus(SectionPos pos, boolean notReady) {
@ -4722,20 +4720,28 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
}
@Override
public void enableLightSources(ChunkPos pos, boolean retainData) {
public void propagateLightSources(ChunkPos chunkPos) {
+ if (true) return; // Paper - replace light engine impl
this.addTask(pos.x, pos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
super.enableLightSources(pos, retainData);
this.addTask(chunkPos.x, chunkPos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
super.propagateLightSources(chunkPos);
}, () -> {
@@ -106,6 +258,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@@ -102,6 +254,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void queueSectionData(LightLayer lightType, SectionPos pos, @Nullable DataLayer nibbles, boolean nonEdge) {
public void setLightEnabled(ChunkPos pos, boolean retainData) {
+ if (true) return; // Paper - replace light engine impl
this.addTask(pos.x, pos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
super.setLightEnabled(pos, retainData);
}, () -> {
@@ -111,6 +264,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void queueSectionData(LightLayer lightType, SectionPos pos, @Nullable DataLayer nibbles) {
+ if (true) return; // Paper - replace light engine impl
this.addTask(pos.x(), pos.z(), () -> {
return 0;
}, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
@@ -131,6 +284,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@@ -136,6 +290,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void retainData(ChunkPos pos, boolean retainData) {
@ -4743,7 +4749,15 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
this.addTask(pos.x, pos.z, () -> {
return 0;
}, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
@@ -153,6 +307,37 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@@ -146,6 +301,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
}
public CompletableFuture<ChunkAccess> initializeLight(ChunkAccess chunk, boolean bl) {
+ if (true) return CompletableFuture.completedFuture(chunk); // Paper - replace light engine impl
ChunkPos chunkPos = chunk.getPos();
this.addTask(chunkPos.x, chunkPos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
LevelChunkSection[] levelChunkSections = chunk.getSections();
@@ -171,6 +327,37 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
}
public CompletableFuture<ChunkAccess> lightChunk(ChunkAccess chunk, boolean excludeBlocks) {
@ -4781,7 +4795,7 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
ChunkPos chunkPos = chunk.getPos();
chunk.setLightCorrect(false);
this.addTask(chunkPos.x, chunkPos.z, ThreadedLevelLightEngine.TaskType.PRE_UPDATE, Util.name(() -> {
@@ -187,7 +372,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@@ -191,7 +378,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
}
public void tryScheduleUpdate() {
@ -4790,11 +4804,11 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283
this.taskMailbox.tell(() -> {
this.runUpdate();
this.scheduled.set(false);
@@ -209,7 +394,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@@ -213,7 +400,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
}
objectListIterator.back(j);
- super.runUpdates(Integer.MAX_VALUE, true, true);
- super.runLightUpdates();
+ this.theLightEngine.propagateChanges(); // Paper - rewrite light engine
for(int var5 = 0; objectListIterator.hasNext() && var5 < i; ++var5) {
@ -4812,18 +4826,18 @@ index 0d536d72ac918fbd403397ff369d10143ee9c204..6051e5f272838ef23276a90e21c2fc82
public static <T> TicketType<T> create(String name, Comparator<T> argumentComparator) {
return new TicketType<>(name, argumentComparator, 0L);
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index 2cb3463f3d77a32ada67a6251707d741d18910ca..0eb877c80c6492d03681c70f7866ad705a62454e 100644
index 88b1aabec2812252c54d0901ccd1eba0216cb7c3..803f3ebaa9fe43c88f461168ee43fc6ba920a764 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -751,6 +751,7 @@ public abstract class BlockBehaviour implements FeatureElement {
this.emissiveRendering = blockbase_info.emissiveRendering;
this.offsetFunction = blockbase_info.offsetFunction;
@@ -807,6 +807,7 @@ public abstract class BlockBehaviour implements FeatureElement {
this.spawnParticlesOnBreak = blockbase_info.spawnParticlesOnBreak;
this.instrument = blockbase_info.instrument;
this.replaceable = blockbase_info.replaceable;
+ this.conditionallyFullOpaque = this.isOpaque() & this.isTransparentOnSomeFaces(); // Paper
}
// Paper start
@@ -759,6 +760,18 @@ public abstract class BlockBehaviour implements FeatureElement {
private boolean calculateSolid() {
@@ -835,6 +836,18 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.shapeExceedsCube;
}
// Paper end
@ -4842,19 +4856,19 @@ index 2cb3463f3d77a32ada67a6251707d741d18910ca..0eb877c80c6492d03681c70f7866ad70
public void initCache() {
this.fluidState = ((Block) this.owner).getFluidState(this.asState());
@@ -767,6 +780,7 @@ public abstract class BlockBehaviour implements FeatureElement {
@@ -843,6 +856,7 @@ public abstract class BlockBehaviour implements FeatureElement {
this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState());
}
this.shapeExceedsCube = this.cache == null || this.cache.largeCollisionShape; // Paper - moved from actual method to here
+ this.opacityIfCached = this.cache == null || this.isConditionallyFullOpaque() ? -1 : this.cache.lightBlock; // Paper - starlight - cache opacity for light
this.legacySolid = this.calculateSolid();
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 3fdbb777d4722596cc4df79b2d4d7b9c553580fd..1b7496cec0ba5a95615a069e3168bd46308d0b40 100644
index e5e562f75e7d4b6a750f192842940c5e3af81e7d..2caac1a3d80e6c490aa16aa6bc1067065b665c69 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -81,6 +81,47 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
@@ -86,6 +86,47 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(ChunkAccess.DATA_TYPE_REGISTRY);
// CraftBukkit end
@ -4900,13 +4914,13 @@ index 3fdbb777d4722596cc4df79b2d4d7b9c553580fd..1b7496cec0ba5a95615a069e3168bd46
+ }
+ // Paper end - rewrite light engine
public ChunkAccess(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor heightLimitView, Registry<Biome> biome, long inhabitedTime, @Nullable LevelChunkSection[] sectionArrayInitializer, @Nullable BlendingData blendingData) {
public ChunkAccess(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor heightLimitView, Registry<Biome> biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] sectionArray, @Nullable BlendingData blendingData) {
this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field lookups
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
index f4aab0bf544ef5c889c02e41389b1656cf1e4932..e2278ed457a7342d0d1b1a5fc1b5bdef6358816b 100644
index 70a05fe758565131bbb39c18d6b674a6368ffa45..fb5a06a908d2b42bf0530b62ed648548499d9f87 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java
@@ -293,6 +293,17 @@ public class ChunkStatus {
@@ -258,6 +258,17 @@ public class ChunkStatus {
return this.chunkType;
}
@ -4925,7 +4939,7 @@ index f4aab0bf544ef5c889c02e41389b1656cf1e4932..e2278ed457a7342d0d1b1a5fc1b5bdef
return (ChunkStatus) BuiltInRegistries.CHUNK_STATUS.get(ResourceLocation.tryParse(id));
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
index 587cc435a58d28e14e88860c8348425101334eda..2eb92dde607d7c8968cb07c6f3c24e1c45e9990f 100644
index ca0991b07def35b4697ba6d5569bf9a080e48a1c..f49cc61840c6588fca301b4c5c3aaeede03a323e 100644
--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java
@@ -21,6 +21,40 @@ public class EmptyLevelChunk extends LevelChunk {
@ -4970,12 +4984,12 @@ index 587cc435a58d28e14e88860c8348425101334eda..2eb92dde607d7c8968cb07c6f3c24e1c
public BlockState getBlockState(BlockPos pos) {
return Blocks.VOID_AIR.defaultBlockState();
diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
index 80b98e6667f1a0c21d019c58a8a0d4cc5b0f48e1..8033c8741a0f73919a357893652592b317bfb417 100644
index 6bb508105641b5729572736c5c3f9bd6711e309a..60e760b42dd6471a229dfd45490dcf8c51979d35 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -31,6 +31,48 @@ public class ImposterProtoChunk extends ProtoChunk {
private final LevelChunk wrapped;
private final boolean allowWrites;
@@ -39,6 +39,48 @@ public class ImposterProtoChunk extends ProtoChunk {
this.allowWrites = propagateToWrapped;
}
+ // Paper start - rewrite light engine
+ @Override
@ -5019,14 +5033,14 @@ index 80b98e6667f1a0c21d019c58a8a0d4cc5b0f48e1..8033c8741a0f73919a357893652592b3
+ }
+ // Paper end - rewrite light engine
+
public ImposterProtoChunk(LevelChunk wrapped, boolean bl) {
super(wrapped.getPos(), UpgradeData.EMPTY, wrapped.levelHeightAccessor, wrapped.getLevel().registryAccess().registryOrThrow(Registries.BIOME), wrapped.getBlendingData());
this.wrapped = wrapped;
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 13202fc9f73f3485328b923de8c1e6080f08e773..975973e858ceb8340d2fdad54f636627d16612fd 100644
index 6e1ace21431f679d55a2580dc23c32cf5f75b2af..9bd0e817cf717fe6257ceb4ace6bf6f5eed9eb82 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -93,6 +93,10 @@ public class LevelChunk extends ChunkAccess {
@@ -90,6 +90,10 @@ public class LevelChunk extends ChunkAccess {
public LevelChunk(Level world, ChunkPos pos, UpgradeData upgradeData, LevelChunkTicks<Block> blockTickScheduler, LevelChunkTicks<Fluid> fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sectionArrayInitializer, @Nullable LevelChunk.PostLoadProcessor entityLoader, @Nullable BlendingData blendingData) {
super(pos, upgradeData, world, world.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, sectionArrayInitializer, blendingData);
@ -5035,9 +5049,9 @@ index 13202fc9f73f3485328b923de8c1e6080f08e773..975973e858ceb8340d2fdad54f636627
+ this.setSkyNibbles(ca.spottedleaf.starlight.common.light.StarLightEngine.getFilledEmptyLight(world));
+ // Paper end - rewrite light engine
this.tickersInLevel = Maps.newHashMap();
this.clientLightReady = false;
this.level = (ServerLevel) world; // CraftBukkit - type
@@ -223,6 +227,12 @@ public class LevelChunk extends ChunkAccess {
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap();
@@ -219,6 +223,12 @@ public class LevelChunk extends ChunkAccess {
public LevelChunk(ServerLevel world, ProtoChunk protoChunk, @Nullable LevelChunk.PostLoadProcessor entityLoader) {
this(world, protoChunk.getPos(), protoChunk.getUpgradeData(), protoChunk.unpackBlockTicks(), protoChunk.unpackFluidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), entityLoader, protoChunk.getBlendingData());
@ -5064,10 +5078,10 @@ index afba733824d84d650e669eda028bf4d28cf006b4..cd82985b0aa821dccc0484f328407381
return data.palette.valueFor(data.storage.get(index));
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
index 92a64c49b1c7227a5b34488ea15d3d8adb0f9c80..0b67858f8d6689b34816f9556f3424af512a7401 100644
index 38ec21faaa16df5485a81a581506700a5ab0a440..b2c0c7fd06fcd720b4c0875f08a90b6b672c96b2 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -55,6 +55,12 @@ public class ProtoChunk extends ChunkAccess {
@@ -53,6 +53,12 @@ public class ProtoChunk extends ChunkAccess {
public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] sections, ProtoChunkTicks<Block> blockTickScheduler, ProtoChunkTicks<Fluid> fluidTickScheduler, LevelHeightAccessor world, Registry<Biome> biomeRegistry, @Nullable BlendingData blendingData) {
super(pos, upgradeData, world, biomeRegistry, 0L, sections, blendingData);
@ -5081,7 +5095,7 @@ index 92a64c49b1c7227a5b34488ea15d3d8adb0f9c80..0b67858f8d6689b34816f9556f3424af
this.fluidTicks = fluidTickScheduler;
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc1bfdbc7d 100644
index cc1d7626a82881c4410d65c6a33dadae7ab07172..24892ae367e19038625e243bcdf1bb694632ede5 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -84,6 +84,14 @@ public class ChunkSerializer {
@ -5089,7 +5103,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
public static final String SKY_LIGHT_TAG = "SkyLight";
+ // Paper start - replace light engine impl
+ private static final int STARLIGHT_LIGHT_VERSION = 8;
+ private static final int STARLIGHT_LIGHT_VERSION = 9;
+
+ private static final String BLOCKLIGHT_STATE_TAG = "starlight.blocklight_state";
+ private static final String SKYLIGHT_STATE_TAG = "starlight.skylight_state";
@ -5110,7 +5124,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
LevelChunkSection[] achunksection = new LevelChunkSection[i];
boolean flag1 = world.dimensionType().hasSkyLight();
ServerChunkCache chunkproviderserver = world.getChunkSource();
LevelLightEngine lightengine = chunkproviderserver.getLightEngine();
LevelLightEngine levellightengine = chunkproviderserver.getLightEngine();
+ // Paper start
+ ca.spottedleaf.starlight.common.light.SWMRNibbleArray[] blockNibbles = ca.spottedleaf.starlight.common.light.StarLightEngine.getFilledEmptyLight(world);
+ ca.spottedleaf.starlight.common.light.SWMRNibbleArray[] skyNibbles = ca.spottedleaf.starlight.common.light.StarLightEngine.getFilledEmptyLight(world);
@ -5130,13 +5144,13 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
byte b0 = nbttagcompound1.getByte("Y");
int k = world.getSectionIndexFromSectionY(b0);
@@ -149,19 +164,39 @@ public class ChunkSerializer {
@@ -151,19 +166,39 @@ public class ChunkSerializer {
boolean flag3 = nbttagcompound1.contains("BlockLight", 7);
boolean flag4 = flag1 && nbttagcompound1.contains("SkyLight", 7);
- if (flag3 || flag4) {
- if (!flag2) {
- lightengine.retainData(chunkPos, true);
- levellightengine.retainData(chunkPos, true);
- flag2 = true;
- }
-
@ -5146,7 +5160,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
+ int y = sectionData.getByte("Y");
+ // Paper end - rewrite the light engine
if (flag3) {
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight")), true);
- levellightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight")));
+ // Paper start - rewrite the light engine
+ // this is where our diff is
+ blockNibbles[y - minSection] = new ca.spottedleaf.starlight.common.light.SWMRNibbleArray(sectionData.getByteArray("BlockLight").clone(), sectionData.getInt(BLOCKLIGHT_STATE_TAG)); // clone for data safety
@ -5156,7 +5170,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
}
if (flag4) {
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight")), true);
- levellightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight")));
+ // Paper start - rewrite the light engine
+ // we store under the same key so mod programs editing nbt
+ // can still read the data, hopefully.
@ -5178,7 +5192,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
}
}
@@ -190,6 +225,8 @@ public class ChunkSerializer {
@@ -192,6 +227,8 @@ public class ChunkSerializer {
}, chunkPos);
object1 = new LevelChunk(world.getLevel(), chunkPos, chunkconverter, levelchunkticks, levelchunkticks1, l, achunksection, ChunkSerializer.postLoadChunk(world, nbt), blendingdata);
@ -5187,7 +5201,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
} else {
ProtoChunkTicks<Block> protochunkticklist = ProtoChunkTicks.load(nbt.getList("block_ticks", 10), (s) -> {
return BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(s));
@@ -198,6 +235,8 @@ public class ChunkSerializer {
@@ -200,6 +237,8 @@ public class ChunkSerializer {
return BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(s));
}, chunkPos);
ProtoChunk protochunk = new ProtoChunk(chunkPos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, iregistry, blendingdata);
@ -5196,7 +5210,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
object1 = protochunk;
protochunk.setInhabitedTime(l);
@@ -342,6 +381,12 @@ public class ChunkSerializer {
@@ -314,6 +353,12 @@ public class ChunkSerializer {
// CraftBukkit end
public static CompoundTag write(ServerLevel world, ChunkAccess chunk) {
@ -5209,7 +5223,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
ChunkPos chunkcoordintpair = chunk.getPos();
CompoundTag nbttagcompound = NbtUtils.addCurrentDataVersion(new CompoundTag());
@@ -391,11 +436,14 @@ public class ChunkSerializer {
@@ -363,11 +408,14 @@ public class ChunkSerializer {
for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) {
int j = chunk.getSectionIndexFromSectionY(i);
boolean flag1 = j >= 0 && j < achunksection.length;
@ -5228,7 +5242,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
if (flag1) {
LevelChunkSection chunksection = achunksection[j];
@@ -410,13 +458,27 @@ public class ChunkSerializer {
@@ -382,13 +430,27 @@ public class ChunkSerializer {
nbttagcompound1.put("biomes", (Tag) dataresult1.getOrThrow(false, logger1::error));
}
@ -5260,7 +5274,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
if (!nbttagcompound1.isEmpty()) {
nbttagcompound1.putByte("Y", (byte) i);
@@ -427,7 +489,8 @@ public class ChunkSerializer {
@@ -399,7 +461,8 @@ public class ChunkSerializer {
nbttagcompound.put("sections", nbttaglist);
if (flag) {
@ -5270,7 +5284,7 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc
}
ListTag nbttaglist1 = new ListTag();
@@ -502,6 +565,17 @@ public class ChunkSerializer {
@@ -473,6 +536,17 @@ public class ChunkSerializer {
}));
}