-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Adding chunk serialization events #9990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
| From: derverdox <mail.ysp@web.de> | ||
| Date: Thu, 30 Nov 2023 01:22:24 +0100 | ||
| Subject: [PATCH] Adding ChunkSerialization and Generation events. | ||
|
|
||
| This patch adds new Chunk events that are called during the serialization / generation process of chunks. | ||
| A problem some developers may face while using the ChunkLoad or ChunkUnload events is the fact that they are called synchronously. | ||
| These proposed events are called during the process. | ||
|
|
||
| The use case of such events is that heavy saving / loading tasks from cache to the chunk nbt container or vice versa are executed asynchronously aswell but in the same thread | ||
| that saves / loads / generates the chunk. | ||
|
|
||
| diff --git a/src/main/java/io/papermc/paper/event/chunk/ChunkDataEvent.java b/src/main/java/io/papermc/paper/event/chunk/ChunkDataEvent.java | ||
| new file mode 100644 | ||
| index 0000000000000000000000000000000000000000..73c94926c975360f9b7c79f910dd09a0f3346058 | ||
| --- /dev/null | ||
| +++ b/src/main/java/io/papermc/paper/event/chunk/ChunkDataEvent.java | ||
| @@ -0,0 +1,61 @@ | ||
| +package io.papermc.paper.event.chunk; | ||
| + | ||
| +import org.bukkit.Bukkit; | ||
| +import org.bukkit.Chunk; | ||
| +import org.bukkit.World; | ||
| +import org.bukkit.event.Event; | ||
| +import org.bukkit.event.HandlerList; | ||
| +import org.bukkit.persistence.PersistentDataContainer; | ||
| +import org.jetbrains.annotations.NotNull; | ||
| +import org.jetbrains.annotations.Nullable; | ||
| + | ||
| +public abstract class ChunkDataEvent extends Event { | ||
| + private static final HandlerList handlers = new HandlerList(); | ||
| + private final World world; | ||
| + private final Chunk chunk; | ||
| + private final int chunkX; | ||
| + private final int chunkZ; | ||
| + private final PersistentDataContainer persistentDataContainer; | ||
| + | ||
| + public ChunkDataEvent(@NotNull World world, @Nullable Chunk chunk, int chunkX, int chunkZ, @NotNull PersistentDataContainer chunkPersistentDataContainer) { | ||
| + super(!Bukkit.isPrimaryThread()); | ||
| + this.world = world; | ||
| + this.chunk = chunk; | ||
| + this.chunkX = chunkX; | ||
| + this.chunkZ = chunkZ; | ||
| + this.persistentDataContainer = chunkPersistentDataContainer; | ||
| + } | ||
| + | ||
| + public int getChunkX() { | ||
| + return chunkX; | ||
| + } | ||
| + | ||
| + public int getChunkZ() { | ||
| + return chunkZ; | ||
| + } | ||
| + | ||
| + @Nullable | ||
| + public Chunk getChunk() { | ||
| + return this.chunk; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should get docs as to when the chunk is null or not null |
||
| + } | ||
| + | ||
| + @NotNull | ||
| + public World getWorld() { | ||
| + return this.world; | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + public PersistentDataContainer getPersistentDataContainer() { | ||
| + return this.persistentDataContainer; | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + public static HandlerList getHandlerList() { | ||
| + return handlers; | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + public HandlerList getHandlers() { | ||
| + return handlers; | ||
| + } | ||
| +} | ||
| diff --git a/src/main/java/io/papermc/paper/event/chunk/ChunkDeserializeEvent.java b/src/main/java/io/papermc/paper/event/chunk/ChunkDeserializeEvent.java | ||
| new file mode 100644 | ||
| index 0000000000000000000000000000000000000000..e90357708c7d06150f446161d7761b6e22fb64d5 | ||
| --- /dev/null | ||
| +++ b/src/main/java/io/papermc/paper/event/chunk/ChunkDeserializeEvent.java | ||
| @@ -0,0 +1,32 @@ | ||
| +package io.papermc.paper.event.chunk; | ||
| + | ||
| +import org.bukkit.Chunk; | ||
| +import org.bukkit.World; | ||
| +import org.bukkit.event.HandlerList; | ||
| +import org.bukkit.persistence.PersistentDataContainer; | ||
| +import org.jetbrains.annotations.NotNull; | ||
| +import org.jetbrains.annotations.Nullable; | ||
| + | ||
| +/** | ||
| + * Called when a chunk is loaded from disk. | ||
| + * You can use this event to manipulate the persistent data container of the chunk after it is loaded. | ||
| + * Since by default chunk loading is asynchronously on paper this might be an alternative to the ChunkLoadEvent in some cases. | ||
| + * This event might get called asynchronously. | ||
| + */ | ||
| +public class ChunkDeserializeEvent extends ChunkDataEvent { | ||
| + private static final HandlerList handlers = new HandlerList(); | ||
| + public ChunkDeserializeEvent(@NotNull final World world, @Nullable final Chunk chunk, final int chunkX, final int chunkZ, @NotNull final PersistentDataContainer chunkPersistentDataContainer) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra line between the field and constructor |
||
| + super(world, chunk, chunkX, chunkZ, chunkPersistentDataContainer); | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + @Override | ||
| + public HandlerList getHandlers() { | ||
| + return handlers; | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + public static HandlerList getHandlerList() { | ||
| + return handlers; | ||
| + } | ||
| +} | ||
| diff --git a/src/main/java/io/papermc/paper/event/chunk/ChunkGenerateEvent.java b/src/main/java/io/papermc/paper/event/chunk/ChunkGenerateEvent.java | ||
| new file mode 100644 | ||
| index 0000000000000000000000000000000000000000..1f279d528ce2be534911686a4574596334ea944a | ||
| --- /dev/null | ||
| +++ b/src/main/java/io/papermc/paper/event/chunk/ChunkGenerateEvent.java | ||
| @@ -0,0 +1,32 @@ | ||
| +package io.papermc.paper.event.chunk; | ||
| + | ||
| +import org.bukkit.Chunk; | ||
| +import org.bukkit.World; | ||
| +import org.bukkit.event.HandlerList; | ||
| +import org.bukkit.persistence.PersistentDataContainer; | ||
| +import org.jetbrains.annotations.NotNull; | ||
| +import org.jetbrains.annotations.Nullable; | ||
| + | ||
| +/** | ||
| + * Called when a chunk is generated. | ||
| + * You can use this event to manipulate the persistent data container of the chunk before it is generated. | ||
| + * Since by default chunk generation is asynchronously on paper this might be an alternative to the ChunkLoadEvent in some cases. | ||
| + * This event is might get called asynchronously. | ||
| + */ | ||
| +public class ChunkGenerateEvent extends ChunkDataEvent { | ||
| + private static final HandlerList handlers = new HandlerList(); | ||
| + public ChunkGenerateEvent(@NotNull final World world, @Nullable final Chunk chunk, final int chunkX, final int chunkZ, @NotNull final PersistentDataContainer chunkPersistentDataContainer) { | ||
| + super(world, chunk, chunkX, chunkZ, chunkPersistentDataContainer); | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + @Override | ||
| + public HandlerList getHandlers() { | ||
| + return handlers; | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + public static HandlerList getHandlerList() { | ||
| + return handlers; | ||
| + } | ||
| +} | ||
| diff --git a/src/main/java/io/papermc/paper/event/chunk/ChunkSerializeEvent.java b/src/main/java/io/papermc/paper/event/chunk/ChunkSerializeEvent.java | ||
| new file mode 100644 | ||
| index 0000000000000000000000000000000000000000..77d7711f1c8513e4f1895a187cc758c376ab93e7 | ||
| --- /dev/null | ||
| +++ b/src/main/java/io/papermc/paper/event/chunk/ChunkSerializeEvent.java | ||
| @@ -0,0 +1,43 @@ | ||
| +package io.papermc.paper.event.chunk; | ||
| + | ||
| +import org.bukkit.Chunk; | ||
| +import org.bukkit.World; | ||
| +import org.bukkit.event.HandlerList; | ||
| +import org.bukkit.persistence.PersistentDataContainer; | ||
| +import org.jetbrains.annotations.NotNull; | ||
| +import org.jetbrains.annotations.Nullable; | ||
| + | ||
| +/** | ||
| + * Called when a chunk is saved to disk. | ||
| + * You can use this event to manipulate the persistent data container of the chunk after it is loaded. | ||
| + * Since by default chunk saving is asynchronously on paper this might be an alternative to the ChunkUnloadEvent in some cases. | ||
| + * This event might get called asynchronously. | ||
| + */ | ||
| +public class ChunkSerializeEvent extends ChunkDataEvent { | ||
| + private static final HandlerList handlers = new HandlerList(); | ||
| + private final boolean unloaded; | ||
| + | ||
| + public ChunkSerializeEvent(@NotNull final World world, @Nullable final Chunk chunk, final int chunkX, final int chunkZ, @NotNull final PersistentDataContainer chunkPersistentDataContainer, boolean unloaded) { | ||
| + super(world, chunk, chunkX, chunkZ, chunkPersistentDataContainer); | ||
| + this.unloaded = unloaded; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Gets if this chunk was unloaded after being saved | ||
| + * @return true if the chunk is also unloaded | ||
| + */ | ||
| + public boolean isUnloaded() { | ||
| + return this.unloaded; | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + @Override | ||
| + public HandlerList getHandlers() { | ||
| + return handlers; | ||
| + } | ||
| + | ||
| + @NotNull | ||
| + public static HandlerList getHandlerList() { | ||
| + return handlers; | ||
| + } | ||
| +} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
| From: derverdox <mail.ysp@web.de> | ||
| Date: Thu, 30 Nov 2023 01:22:23 +0100 | ||
| Subject: [PATCH] Adding ChunkSerialization and Generation events. | ||
|
|
||
| diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java | ||
| index b66a7d4aab887309579154815a0d4abf9de506b0..9c403423551db5280edaca5869e42e23ae6aa5c2 100644 | ||
| --- a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java | ||
| +++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java | ||
| @@ -1817,7 +1817,9 @@ public final class NewChunkHolder { | ||
| public void run() { | ||
| final CompoundTag toSerialize; | ||
| try { | ||
| - toSerialize = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData); | ||
| + // Paper start - add ChunkDataEvents | ||
| + toSerialize = ChunkSerializer.saveChunk(this.world, this.chunk, this.asyncSaveData, false); | ||
| + // Paper end - add ChunkDataEvents | ||
|
Comment on lines
+15
to
+17
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Single line changes just get a |
||
| } catch (final ThreadDeath death) { | ||
| throw death; | ||
| } catch (final Throwable throwable) { | ||
| @@ -1825,7 +1827,9 @@ public final class NewChunkHolder { | ||
| this.world.chunkTaskScheduler.scheduleChunkTask(this.chunk.locX, this.chunk.locZ, () -> { | ||
| final CompoundTag synchronousSave; | ||
| try { | ||
| - synchronousSave = ChunkSerializer.saveChunk(AsyncChunkSerializeTask.this.world, AsyncChunkSerializeTask.this.chunk, AsyncChunkSerializeTask.this.asyncSaveData); | ||
| + // Paper start - add ChunkDataEvents | ||
| + synchronousSave = ChunkSerializer.saveChunk(AsyncChunkSerializeTask.this.world, AsyncChunkSerializeTask.this.chunk, AsyncChunkSerializeTask.this.asyncSaveData, false); | ||
| + // Paper end - add ChunkDataEvents | ||
| } catch (final ThreadDeath death) { | ||
| throw death; | ||
| } catch (final Throwable throwable2) { | ||
| @@ -1881,7 +1885,9 @@ public final class NewChunkHolder { | ||
| } | ||
| } | ||
|
|
||
| - final CompoundTag save = ChunkSerializer.saveChunk(this.world, chunk, null); | ||
| + // Paper start - add ChunkDataEvents | ||
| + final CompoundTag save = ChunkSerializer.saveChunk(this.world, chunk, null, unloading); | ||
| + // Paper end - add ChunkDataEvents | ||
|
|
||
| if (unloading) { | ||
| completing = true; | ||
| 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 a907b79fd8291a0e92db138f37239d17424188a1..802735bf4f34ed225ab08252c0f10b4c5bb915a0 100644 | ||
| --- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java | ||
| +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java | ||
| @@ -27,6 +27,7 @@ import net.minecraft.world.level.levelgen.GenerationStep; | ||
| import net.minecraft.world.level.levelgen.Heightmap; | ||
| import net.minecraft.world.level.levelgen.blending.Blender; | ||
| import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; | ||
| +import org.bukkit.craftbukkit.event.CraftEventFactory; | ||
|
|
||
| public class ChunkStatus { | ||
|
|
||
| @@ -68,6 +69,9 @@ public class ChunkStatus { | ||
| } | ||
|
|
||
| worldserver.onStructureStartsAvailable(ichunkaccess); | ||
| + // Paper start - add ChunkDataEvents | ||
| + CraftEventFactory.callChunkGenerateEvent(worldserver, ichunkaccess, ichunkaccess.persistentDataContainer); | ||
| + // Paper end - add ChunkDataEvents | ||
| return CompletableFuture.completedFuture(Either.left(ichunkaccess)); | ||
| }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { | ||
| worldserver.onStructureStartsAvailable(ichunkaccess); | ||
| 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 1379084a80ce25644f13736b4a5ee5fabbd9ec1f..fedfdcf893478d9df9e35851d0ab4edb9a30856f 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 | ||
| @@ -67,6 +67,7 @@ import net.minecraft.world.level.lighting.LevelLightEngine; | ||
| import net.minecraft.world.level.material.Fluid; | ||
| import net.minecraft.world.ticks.LevelChunkTicks; | ||
| import net.minecraft.world.ticks.ProtoChunkTicks; | ||
| +import org.bukkit.craftbukkit.event.CraftEventFactory; | ||
| import org.slf4j.Logger; | ||
|
|
||
| public class ChunkSerializer { | ||
| @@ -366,6 +367,9 @@ public class ChunkSerializer { | ||
| } | ||
|
|
||
| if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { | ||
| + // Paper start - add ChunkDataEvents | ||
| + CraftEventFactory.callChunkDeserializeEvent(world, (ChunkAccess) object1, ((ChunkAccess) object1).persistentDataContainer); | ||
| + // Paper start - add ChunkDataEvents | ||
| return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object1, false)); // Paper - Async chunk loading | ||
| } else { | ||
| ProtoChunk protochunk1 = (ProtoChunk) object1; | ||
| @@ -401,6 +405,9 @@ public class ChunkSerializer { | ||
| protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound5.getLongArray(s1), ((ChunkAccess) object1).getMinBuildHeight())); | ||
| } | ||
|
|
||
| + // Paper start - add ChunkDataEvents | ||
| + CraftEventFactory.callChunkDeserializeEvent(world, (ChunkAccess) object1, ((ChunkAccess) object1).persistentDataContainer); | ||
| + // Paper end - add ChunkDataEvents | ||
| return new InProgressChunkHolder(protochunk1); // Paper - Async chunk loading | ||
| } | ||
| } | ||
| @@ -452,11 +459,12 @@ public class ChunkSerializer { | ||
| // CraftBukkit end | ||
|
|
||
| public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { | ||
| - // Paper start | ||
| - return saveChunk(world, chunk, null); | ||
| + // Paper start - add ChunkDataEvents | ||
| + return saveChunk(world, chunk, null, false); | ||
| + | ||
| } | ||
| - public static CompoundTag saveChunk(ServerLevel world, ChunkAccess chunk, @org.checkerframework.checker.nullness.qual.Nullable AsyncSaveData asyncsavedata) { | ||
| - // Paper end | ||
| + public static CompoundTag saveChunk(ServerLevel world, ChunkAccess chunk, @org.checkerframework.checker.nullness.qual.Nullable AsyncSaveData asyncsavedata, boolean unloadingChunk) { | ||
| + // Paper end - add ChunkDataEvents | ||
| // Paper start - rewrite light impl | ||
| final int minSection = io.papermc.paper.util.WorldUtil.getMinLightSection(world); | ||
| final int maxSection = io.papermc.paper.util.WorldUtil.getMaxLightSection(world); | ||
| @@ -637,6 +645,9 @@ public class ChunkSerializer { | ||
|
|
||
| nbttagcompound.put("Heightmaps", nbttagcompound3); | ||
| nbttagcompound.put("structures", ChunkSerializer.packStructureData(StructurePieceSerializationContext.fromLevel(world), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); | ||
| + // Paper start - add ChunkDataEvents | ||
| + CraftEventFactory.callChunkSaveEvent(world, chunk, chunk.persistentDataContainer, unloadingChunk); | ||
| + // Paper end - add ChunkDataEvents | ||
| // CraftBukkit start - store chunk persistent data in nbt | ||
| if (!chunk.persistentDataContainer.isEmpty()) { // SPIGOT-6814: Always save PDC to account for 1.17 to 1.18 chunk upgrading. | ||
| nbttagcompound.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); | ||
| diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java | ||
| index 5dc160b743534665c6b3efb10b10f7c36e2da5ab..039383f4a17c7ace34a2cf93b75e89bf519c1612 100644 | ||
| --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java | ||
| +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java | ||
| @@ -16,6 +16,9 @@ import java.util.Map; | ||
| import java.util.stream.Collectors; | ||
| import java.util.stream.Stream; | ||
| import javax.annotation.Nullable; | ||
| +import io.papermc.paper.event.chunk.ChunkDeserializeEvent; | ||
| +import io.papermc.paper.event.chunk.ChunkGenerateEvent; | ||
| +import io.papermc.paper.event.chunk.ChunkSerializeEvent; | ||
| import net.minecraft.core.BlockPos; | ||
| import net.minecraft.core.Direction; | ||
| import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; | ||
| @@ -56,6 +59,8 @@ import net.minecraft.world.level.Level; | ||
| import net.minecraft.world.level.LevelAccessor; | ||
| import net.minecraft.world.level.block.entity.SignBlockEntity; | ||
| import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; | ||
| +import net.minecraft.world.level.chunk.ChunkAccess; | ||
| +import net.minecraft.world.level.chunk.LevelChunk; | ||
| import net.minecraft.world.level.storage.loot.LootContext; | ||
| import net.minecraft.world.level.storage.loot.LootTable; | ||
| import net.minecraft.world.level.storage.loot.parameters.LootContextParams; | ||
| @@ -242,6 +247,7 @@ import org.bukkit.inventory.EquipmentSlot; | ||
| import org.bukkit.inventory.InventoryView; | ||
| import org.bukkit.inventory.Recipe; | ||
| import org.bukkit.inventory.meta.BookMeta; | ||
| +import org.bukkit.persistence.PersistentDataContainer; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Especially in this class it's going to be ugly, but please remove the added imports and instead fully qualify them when used in code to reduce diff |
||
| import org.bukkit.potion.PotionEffect; | ||
| import org.bukkit.util.Vector; | ||
|
|
||
| @@ -2166,4 +2172,27 @@ public class CraftEventFactory { | ||
| return event; | ||
| } | ||
| // Paper end - add EntityFertilizeEggEvent | ||
| + | ||
| + // Paper start - add ChunkDataEvents | ||
| + public static void callChunkGenerateEvent(ServerLevel serverLevel, ChunkAccess chunkAccess, PersistentDataContainer persistentDataContainer) { | ||
| + Bukkit.getPluginManager() | ||
| + .callEvent(new ChunkGenerateEvent(serverLevel.getWorld(), getCraftChunk(chunkAccess), chunkAccess.locX, chunkAccess.locZ, persistentDataContainer)); | ||
| + chunkAccess.persistentDataContainer.dirty(true); | ||
| + } | ||
| + | ||
| + public static void callChunkDeserializeEvent(ServerLevel serverLevel, ChunkAccess chunkAccess, PersistentDataContainer persistentDataContainer) { | ||
| + Bukkit.getPluginManager(). | ||
| + callEvent(new ChunkDeserializeEvent(serverLevel.getWorld(), getCraftChunk(chunkAccess), chunkAccess.locX, chunkAccess.locZ, persistentDataContainer)); | ||
| + } | ||
| + | ||
| + public static void callChunkSaveEvent(ServerLevel serverLevel, ChunkAccess chunkAccess, PersistentDataContainer persistentDataContainer, boolean unloadingChunk) { | ||
| + Bukkit.getPluginManager() | ||
| + .callEvent(new ChunkSerializeEvent(serverLevel.getWorld(), getCraftChunk(chunkAccess), chunkAccess.locX, chunkAccess.locZ, persistentDataContainer, unloadingChunk)); | ||
| + chunkAccess.persistentDataContainer.dirty(true); | ||
| + } | ||
| + | ||
| + private static CraftChunk getCraftChunk(ChunkAccess chunkAccess) { | ||
| + return chunkAccess instanceof LevelChunk chunk ? new CraftChunk(chunk) : null; | ||
| + } | ||
| + // Paper end - add ChunkDataEvents | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uppercase name for static final fields