aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk
diff options
context:
space:
mode:
authorMiniDigger | Martin <[email protected]>2024-01-14 11:04:49 +0100
committerMiniDigger | Martin <[email protected]>2024-01-14 11:04:49 +0100
commitbee74680e607c2e29b038329f62181238911cd83 (patch)
tree708fd1a4a0227d9071243adf2a42d5e9e96cde4a /patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk
parent0a44692ef6ff6e255d48eb3ba1bb114166eafda9 (diff)
downloadPaper-softspoon.tar.gz
Paper-softspoon.zip
add remapped patches as a testsoftspoon
Diffstat (limited to 'patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk')
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch77
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch104
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch1
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch26
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch1
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch235
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch35
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch117
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch110
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch1
-rw-r--r--patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch76
11 files changed, 783 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch
new file mode 100644
index 0000000000..b8de6931b4
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch
@@ -0,0 +1,77 @@
+--- a/net/minecraft/world/level/chunk/ChunkAccess.java
++++ b/net/minecraft/world/level/chunk/ChunkAccess.java
+@@ -80,15 +82,12 @@
+ protected final LevelHeightAccessor levelHeightAccessor;
+ protected final LevelChunkSection[] sections;
+
+- public ChunkAccess(
+- ChunkPos chunkPos,
+- UpgradeData upgradeData,
+- LevelHeightAccessor levelHeightAccessor,
+- Registry<Biome> biomeRegistry,
+- long inhabitedTime,
+- @Nullable LevelChunkSection[] sections,
+- @Nullable BlendingData blendingData
+- ) {
++ // CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading.
++ 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(DATA_TYPE_REGISTRY);
++ // CraftBukkit end
++
++ public ChunkAccess(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry<Biome> biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable BlendingData sections) {
+ this.chunkPos = chunkPos;
+ this.upgradeData = upgradeData;
+ this.levelHeightAccessor = levelHeightAccessor;
+@@ -106,7 +105,11 @@
+ }
+
+ replaceMissingSections(biomeRegistry, this.sections);
++ // CraftBukkit start
++ this.biomeRegistry = biomeRegistry;
+ }
++ public final Registry<Biome> biomeRegistry;
++ // CraftBukkit end
+
+ private static void replaceMissingSections(Registry<Biome> biomeRegistry, LevelChunkSection[] sections) {
+ for (int i = 0; i < sections.length; i++) {
+@@ -263,10 +272,11 @@
+
+ public void setUnsaved(boolean unsaved) {
+ this.unsaved = unsaved;
++ if (!unsaved) this.persistentDataContainer.dirty(false); // CraftBukkit - SPIGOT-6814: chunk was saved, pdc is no longer dirty
+ }
+
+ public boolean isUnsaved() {
+- return this.unsaved;
++ return this.unsaved || this.persistentDataContainer.dirty(); // CraftBukkit - SPIGOT-6814: chunk is unsaved if pdc was mutated
+ }
+
+ public abstract ChunkStatus getStatus();
+@@ -430,6 +452,27 @@
+ }
+ }
+
++ // CraftBukkit start
++ public void setBiome(int i, int j, int k, Holder<Biome> biome) {
++ try {
++ int l = QuartPos.fromBlock(this.getMinBuildHeight());
++ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1;
++ int j1 = Mth.clamp(j, l, i1);
++ int k1 = this.getSectionIndex(QuartPos.toBlock(j1));
++
++ this.sections[k1].setBiome(i & 3, j1 & 3, k & 3, biome);
++ } catch (Throwable throwable) {
++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Setting biome");
++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being set");
++
++ crashreportsystemdetails.setDetail("Location", () -> {
++ return CrashReportCategory.formatLocation(this, i, j, k);
++ });
++ throw new ReportedException(crashreport);
++ }
++ }
++ // CraftBukkit end
++
+ public void fillBiomesFromNoise(BiomeResolver resolver, Climate.Sampler sampler) {
+ ChunkPos pos = this.getPos();
+ int i = QuartPos.fromBlock(pos.getMinBlockX());
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch
new file mode 100644
index 0000000000..6e1646322f
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch
@@ -0,0 +1,104 @@
+--- a/net/minecraft/world/level/chunk/ChunkGenerator.java
++++ b/net/minecraft/world/level/chunk/ChunkGenerator.java
+@@ -314,19 +306,8 @@
+ }
+ }
+
+- public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) {
+- ChunkPos pos = chunk.getPos();
+- if (!SharedConstants.debugVoidTerrain(pos)) {
+- SectionPos sectionPos = SectionPos.of(pos, level.getMinSection());
+- BlockPos blockPos = sectionPos.origin();
+- Registry<Structure> registry = level.registryAccess().registryOrThrow(Registries.STRUCTURE);
+- Map<Integer, List<Structure>> map = registry.stream().collect(Collectors.groupingBy(structure1 -> structure1.step().ordinal()));
+- List<FeatureSorter.StepFeatureData> list = this.featuresPerStep.get();
+- WorldgenRandom worldgenRandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed()));
+- long l = worldgenRandom.setDecorationSeed(level.getSeed(), blockPos.getX(), blockPos.getZ());
+- Set<Holder<Biome>> set = new ObjectArraySet<>();
+- ChunkPos.rangeClosed(sectionPos.chunk(), 1).forEach(chunkPos -> {
+- ChunkAccess chunk1 = level.getChunk(chunkPos.x, chunkPos.z);
++ public void addVanillaDecorations(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) { // CraftBukkit
++ ChunkPos chunkcoordintpair = ichunkaccess.getPos();
+
+ for (LevelChunkSection levelChunkSection : chunk1.getSections()) {
+ levelChunkSection.getBiomes().getAll(set::add);
+@@ -410,6 +439,33 @@
+ }
+ }
+
++ // CraftBukkit start
++ public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) {
++ applyBiomeDecoration(level, chunk, structureManager, true);
++ }
++
++ public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) {
++ if (vanilla) {
++ addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager);
++ }
++
++ org.bukkit.World world = generatoraccessseed.getMinecraftWorld().getWorld();
++ // only call when a populator is present (prevents unnecessary entity conversion)
++ if (!world.getPopulators().isEmpty()) {
++ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(generatoraccessseed, ichunkaccess.getPos());
++ int x = ichunkaccess.getPos().x;
++ int z = ichunkaccess.getPos().z;
++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) {
++ WorldgenRandom seededrandom = new WorldgenRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(generatoraccessseed.getSeed()));
++ seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), x, z);
++ populator.populate(world, new org.bukkit.craftbukkit.util.RandomSourceWrapper.RandomWrapper(seededrandom), x, z, limitedRegion);
++ }
++ limitedRegion.saveEntities();
++ limitedRegion.breakLink();
++ }
++ }
++ // CraftBukkit end
++
+ private static BoundingBox getWritableArea(ChunkAccess chunk) {
+ ChunkPos pos = chunk.getPos();
+ int minBlockX = pos.getMinBlockX();
+@@ -545,26 +593,25 @@
+ );
+ }
+
+- private boolean tryGenerateStructure(
+- StructureSet.StructureSelectionEntry structureSelectionEntry,
+- StructureManager structureManager,
+- RegistryAccess registryAccess,
+- RandomState random,
+- StructureTemplateManager structureTemplateManager,
+- long seed,
+- ChunkAccess chunk,
+- ChunkPos chunkPos,
+- SectionPos sectionPos
+- ) {
+- Structure structure = structureSelectionEntry.structure().value();
+- int i = fetchReferences(structureManager, chunk, sectionPos, structure);
+- HolderSet<Biome> holderSet = structure.biomes();
+- Predicate<Holder<Biome>> predicate = holderSet::contains;
+- StructureStart structureStart = structure.generate(
+- registryAccess, this, this.biomeSource, random, structureTemplateManager, seed, chunkPos, i, chunk, predicate
+- );
+- if (structureStart.isValid()) {
+- structureManager.setStartForStructure(sectionPos, structure, structureStart, chunk);
++ private boolean tryGenerateStructure(StructureSet.a structureSelectionEntry, StructureManager structureManager, RegistryAccess registryAccess, RandomState random, StructureTemplateManager structureTemplateManager, long seed, ChunkAccess ichunkaccess, ChunkPos chunk, SectionPos chunkPos) {
++ Structure structure = (Structure) structureSelectionEntry.structure().value();
++ int j = fetchReferences(structureManager, ichunkaccess, chunkPos, structure);
++ HolderSet<Biome> holderset = structure.biomes();
++
++ Objects.requireNonNull(holderset);
++ Predicate<Holder<Biome>> predicate = holderset::contains;
++ StructureStart structurestart = structure.generate(registryAccess, this, this.biomeSource, random, structureTemplateManager, seed, chunk, j, ichunkaccess, predicate);
++
++ if (structurestart.isValid()) {
++ // CraftBukkit start
++ BoundingBox box = structurestart.getBoundingBox();
++ org.bukkit.event.world.AsyncStructureSpawnEvent event = new org.bukkit.event.world.AsyncStructureSpawnEvent(structureManager.level.getMinecraftWorld().getWorld(), org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(structure, registryAccess), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunk.x, chunk.z);
++ org.bukkit.Bukkit.getPluginManager().callEvent(event);
++ if (event.isCancelled()) {
++ return true;
++ }
++ // CraftBukkit end
++ structureManager.setStartForStructure(chunkPos, structure, structurestart, ichunkaccess);
+ return true;
+ } else {
+ return false;
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch
@@ -0,0 +1 @@
+
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch
new file mode 100644
index 0000000000..0127726c74
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch
@@ -0,0 +1,26 @@
+--- a/net/minecraft/world/level/chunk/ChunkStatus.java
++++ b/net/minecraft/world/level/chunk/ChunkStatus.java
+@@ -31,14 +32,15 @@
+ public class ChunkStatus {
+ public static final int MAX_STRUCTURE_DISTANCE = 8;
+ private static final EnumSet<Heightmap.Types> PRE_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR_WG, Heightmap.Types.WORLD_SURFACE_WG);
+- public static final EnumSet<Heightmap.Types> POST_FEATURES = EnumSet.of(
+- Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES
+- );
+- private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (status, level, structureTemplateManager, lightEngine, task, chunk) -> CompletableFuture.completedFuture(
+- Either.left(chunk)
+- );
+- public static final ChunkStatus EMPTY = registerSimple(
+- "empty", null, -1, PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (status, level, chunkGenerator, neighboringChunks, loadingChunk) -> {
++ public static final EnumSet<Heightmap.Types> POST_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES);
++ private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> {
++ return CompletableFuture.completedFuture(Either.left(ichunkaccess));
++ };
++ public static final ChunkStatus EMPTY = registerSimple("empty", (ChunkStatus) null, -1, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> {
++ });
++ public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> {
++ if (worldserver.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit
++ chunkgenerator.createStructures(worldserver.registryAccess(), worldserver.getChunkSource().getGeneratorState(), worldserver.structureManager(), ichunkaccess, structuretemplatemanager);
+ }
+ );
+ public static final ChunkStatus STRUCTURE_STARTS = register(
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch
@@ -0,0 +1 @@
+
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch
new file mode 100644
index 0000000000..5cda59a305
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch
@@ -0,0 +1,235 @@
+--- a/net/minecraft/world/level/chunk/LevelChunk.java
++++ b/net/minecraft/world/level/chunk/LevelChunk.java
+@@ -70,9 +73,9 @@
+ return "<null>";
+ }
+ };
+- private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel = Maps.newHashMap();
+- private boolean loaded;
+- final Level level;
++ private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel;
++ public boolean loaded;
++ public final ServerLevel level; // CraftBukkit - type
+ @Nullable
+ private Supplier<FullChunkStatus> fullStatus;
+ @Nullable
+@@ -85,20 +88,13 @@
+ this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, null, null, null);
+ }
+
+- public LevelChunk(
+- Level level,
+- ChunkPos pos,
+- UpgradeData data,
+- LevelChunkTicks<Block> blockTicks,
+- LevelChunkTicks<Fluid> fluidTicks,
+- long inhabitedTime,
+- @Nullable LevelChunkSection[] sections,
+- @Nullable LevelChunk.PostLoadProcessor postLoad,
+- @Nullable BlendingData blendingData
+- ) {
+- super(pos, data, level, level.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData);
+- this.level = level;
+- this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
++ public LevelChunk(Level level, ChunkPos pos, UpgradeData data, LevelChunkTicks<Block> blockTicks, LevelChunkTicks<Fluid> fluidTicks, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable LevelChunk.PostLoadProcessor sections, @Nullable BlendingData postLoad) {
++ super(pos, data, level, level.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, achunksection, postLoad);
++ this.tickersInLevel = Maps.newHashMap();
++ this.level = (ServerLevel) level; // CraftBukkit - type
++ this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap();
++ Heightmap.Types[] aheightmap_type = Heightmap.Types.values();
++ int j = aheightmap_type.length;
+
+ for (Heightmap.Types types : Heightmap.Types.values()) {
+ if (ChunkStatus.FULL.heightmapsAfter().contains(types)) {
+@@ -111,6 +109,11 @@
+ this.fluidTicks = fluidTicks;
+ }
+
++ // CraftBukkit start
++ public boolean mustNotSave;
++ public boolean needsDecoration;
++ // CraftBukkit end
++
+ public LevelChunk(ServerLevel level, ProtoChunk chunk, @Nullable LevelChunk.PostLoadProcessor postLoad) {
+ this(
+ level,
+@@ -146,6 +145,10 @@
+ this.skyLightSources = chunk.skyLightSources;
+ this.setLightCorrect(chunk.isLightCorrect());
+ this.unsaved = true;
++ this.needsDecoration = true; // CraftBukkit
++ // CraftBukkit start
++ this.persistentDataContainer = chunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading.
++ // CraftBukkit end
+ }
+
+ @Override
+@@ -231,13 +253,21 @@
+ }
+ }
+
++ // CraftBukkit start
+ @Nullable
+ @Override
+- public BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving) {
+- int y = pos.getY();
+- LevelChunkSection section = this.getSection(this.getSectionIndex(y));
+- boolean hasOnlyAir = section.hasOnlyAir();
+- if (hasOnlyAir && state.isAir()) {
++ public IBlockData setBlockState(BlockPos pos, IBlockData state, boolean isMoving) {
++ return this.setBlockState(pos, state, isMoving, true);
++ }
++
++ @Nullable
++ public IBlockData setBlockState(BlockPos blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) {
++ // CraftBukkit end
++ int i = blockposition.getY();
++ LevelChunkSection chunksection = this.getSection(this.getSectionIndex(i));
++ boolean flag1 = chunksection.hasOnlyAir();
++
++ if (flag1 && iblockdata.isAir()) {
+ return null;
+ } else {
+ int i = pos.getX() & 15;
+@@ -276,8 +311,9 @@
+ if (!section.getBlockState(i, i1, i2).is(block)) {
+ return null;
+ } else {
+- if (!this.level.isClientSide) {
+- state.onPlace(this.level, pos, blockState, isMoving);
++ // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled.
++ if (!this.level.isClientSide && doPlace && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BaseEntityBlock)) {
++ iblockdata.onPlace(this.level, blockposition, iblockdata1, flag);
+ }
+
+ if (state.hasBlockEntity()) {
+@@ -318,14 +356,22 @@
+ }
+
+ @Nullable
+- public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) {
+- BlockEntity blockEntity = this.blockEntities.get(pos);
+- if (blockEntity == null) {
+- CompoundTag compoundTag = this.pendingBlockEntities.remove(pos);
+- if (compoundTag != null) {
+- BlockEntity blockEntity1 = this.promotePendingBlockEntity(pos, compoundTag);
+- if (blockEntity1 != null) {
+- return blockEntity1;
++ public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EnumTileEntityState creationType) {
++ // CraftBukkit start
++ BlockEntity tileentity = level.capturedTileEntities.get(pos);
++ if (tileentity == null) {
++ tileentity = (BlockEntity) this.blockEntities.get(pos);
++ }
++ // CraftBukkit end
++
++ if (tileentity == null) {
++ CompoundTag nbttagcompound = (CompoundTag) this.pendingBlockEntities.remove(pos);
++
++ if (nbttagcompound != null) {
++ BlockEntity tileentity1 = this.promotePendingBlockEntity(pos, nbttagcompound);
++
++ if (tileentity1 != null) {
++ return tileentity1;
+ }
+ }
+ }
+@@ -378,6 +439,14 @@
+ if (blockEntity1 != null && blockEntity1 != blockEntity) {
+ blockEntity1.setRemoved();
+ }
++
++ // CraftBukkit start
++ } else {
++ System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ()
++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!");
++ System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16));
++ new Exception().printStackTrace();
++ // CraftBukkit end
+ }
+ }
+
+@@ -403,10 +474,21 @@
+ @Override
+ public void removeBlockEntity(BlockPos pos) {
+ if (this.isInLevel()) {
+- BlockEntity blockEntity = this.blockEntities.remove(pos);
+- if (blockEntity != null) {
+- if (this.level instanceof ServerLevel serverLevel) {
+- this.removeGameEventListener(blockEntity, serverLevel);
++ BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos);
++
++ // CraftBukkit start - SPIGOT-5561: Also remove from pending map
++ if (!pendingBlockEntities.isEmpty()) {
++ pendingBlockEntities.remove(pos);
++ }
++ // CraftBukkit end
++
++ if (tileentity != null) {
++ Level world = this.level;
++
++ if (world instanceof ServerLevel) {
++ ServerLevel worldserver = (ServerLevel) world;
++
++ this.removeGameEventListener(tileentity, worldserver);
+ }
+
+ blockEntity.setRemoved();
+@@ -446,6 +535,57 @@
+ }
+ }
+
++ // CraftBukkit start
++ public void loadCallback() {
++ org.bukkit.Server server = this.level.getCraftServer();
++ if (server != null) {
++ /*
++ * If it's a new world, the first few chunks are generated inside
++ * the World constructor. We can't reliably alter that, so we have
++ * no way of creating a CraftWorld/CraftServer at that point.
++ */
++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration));
++
++ if (this.needsDecoration) {
++ this.needsDecoration = false;
++ java.util.Random random = new java.util.Random();
++ random.setSeed(level.getSeed());
++ long xRand = random.nextLong() / 2L * 2L + 1L;
++ long zRand = random.nextLong() / 2L * 2L + 1L;
++ random.setSeed((long) this.chunkPos.x * xRand + (long) this.chunkPos.z * zRand ^ level.getSeed());
++
++ org.bukkit.World world = this.level.getWorld();
++ if (world != null) {
++ this.level.populating = true;
++ try {
++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) {
++ populator.populate(world, random, bukkitChunk);
++ }
++ } finally {
++ this.level.populating = false;
++ }
++ }
++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk));
++ }
++ }
++ }
++
++ public void unloadCallback() {
++ org.bukkit.Server server = this.level.getCraftServer();
++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
++ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(bukkitChunk, this.isUnsaved());
++ server.getPluginManager().callEvent(unloadEvent);
++ // note: saving can be prevented, but not forced if no saving is actually required
++ this.mustNotSave = !unloadEvent.isSaveChunk();
++ }
++
++ @Override
++ public boolean isUnsaved() {
++ return super.isUnsaved() && !this.mustNotSave;
++ }
++ // CraftBukkit end
++
+ public boolean isEmpty() {
+ return false;
+ }
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch
new file mode 100644
index 0000000000..704eb84a2a
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch
@@ -0,0 +1,35 @@
+--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
++++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
+@@ -21,12 +22,14 @@
+ private short nonEmptyBlockCount;
+ private short tickingBlockCount;
+ private short tickingFluidCount;
+- private final PalettedContainer<BlockState> states;
+- private PalettedContainerRO<Holder<Biome>> biomes;
++ private final PalettedContainer<IBlockData> states;
++ // CraftBukkit start - read/write
++ private PalettedContainer<Holder<Biome>> biomes;
+
+- public LevelChunkSection(PalettedContainer<BlockState> states, PalettedContainerRO<Holder<Biome>> biomes) {
+- this.states = states;
+- this.biomes = biomes;
++ public LevelChunkSection(PalettedContainer<IBlockData> datapaletteblock, PalettedContainer<Holder<Biome>> palettedcontainerro) {
++ // CraftBukkit end
++ this.states = datapaletteblock;
++ this.biomes = palettedcontainerro;
+ this.recalcBlockCounts();
+ }
+
+@@ -180,6 +190,12 @@
+ return this.biomes.get(x, y, z);
+ }
+
++ // CraftBukkit start
++ public void setBiome(int i, int j, int k, Holder<Biome> biome) {
++ this.biomes.set(i, j, k, biome);
++ }
++ // CraftBukkit end
++
+ public void fillBiomesFromNoise(BiomeResolver biomeResolver, Climate.Sampler climateSampler, int x, int y, int z) {
+ PalettedContainer<Holder<Biome>> palettedContainer = this.biomes.recreate();
+ int i = 4;
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch
new file mode 100644
index 0000000000..13e6943d3a
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch
@@ -0,0 +1,117 @@
+--- a/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
++++ b/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+@@ -86,17 +93,17 @@
+ LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkPos);
+ }
+
+- UpgradeData upgradeData = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY;
+- boolean _boolean = tag.getBoolean("isLightOn");
+- ListTag list = tag.getList("sections", 10);
+- int sectionsCount = level.getSectionsCount();
+- LevelChunkSection[] levelChunkSections = new LevelChunkSection[sectionsCount];
+- boolean hasSkyLight = level.dimensionType().hasSkyLight();
+- ChunkSource chunkSource = level.getChunkSource();
+- LevelLightEngine lightEngine = chunkSource.getLightEngine();
+- Registry<Biome> registry = level.registryAccess().registryOrThrow(Registries.BIOME);
+- Codec<PalettedContainerRO<Holder<Biome>>> codec = makeBiomeCodec(registry);
+- boolean flag = false;
++ UpgradeData chunkconverter = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY;
++ boolean flag = tag.getBoolean("isLightOn");
++ ListTag nbttaglist = tag.getList("sections", 10);
++ int i = level.getSectionsCount();
++ LevelChunkSection[] achunksection = new LevelChunkSection[i];
++ boolean flag1 = level.dimensionType().hasSkyLight();
++ ServerChunkCache chunkproviderserver = level.getChunkSource();
++ LevelLightEngine levellightengine = chunkproviderserver.getLightEngine();
++ Registry<Biome> iregistry = level.registryAccess().registryOrThrow(Registries.BIOME);
++ Codec<PalettedContainer<Holder<Biome>>> codec = makeBiomeCodecRW(iregistry); // CraftBukkit - read/write
++ boolean flag2 = false;
+
+ for (int i = 0; i < list.size(); i++) {
+ CompoundTag compound = list.getCompound(i);
+@@ -114,21 +127,27 @@
+ );
+ }
+
+- PalettedContainerRO<Holder<Biome>> palettedContainerRO;
+- if (compound.contains("biomes", 10)) {
+- palettedContainerRO = codec.parse(NbtOps.INSTANCE, compound.getCompound("biomes"))
+- .promotePartial(errorMessage -> logErrors(pos, _byte, errorMessage))
+- .getOrThrow(false, LOGGER::error);
++ PalettedContainer object; // CraftBukkit - read/write
++
++ if (nbttagcompound1.contains("biomes", 10)) {
++ dataresult = codec.parse(NbtOps.INSTANCE, nbttagcompound1.getCompound("biomes")).promotePartial((s) -> {
++ logErrors(pos, b0, s);
++ });
++ logger = ChunkSerializer.LOGGER;
++ Objects.requireNonNull(logger);
++ object = ((DataResult<PalettedContainer<Holder<Biome>>>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error
+ } else {
+ palettedContainerRO = new PalettedContainer<>(
+ registry.asHolderIdMap(), registry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES
+ );
+ }
+
+- LevelChunkSection levelChunkSection = new LevelChunkSection(palettedContainer, palettedContainerRO);
+- levelChunkSections[sectionIndexFromSectionY] = levelChunkSection;
+- SectionPos sectionPos = SectionPos.of(pos, _byte);
+- poiManager.checkConsistencyWithBlocks(sectionPos, levelChunkSection);
++ LevelChunkSection chunksection = new LevelChunkSection(datapaletteblock, (PalettedContainer) object); // CraftBukkit - read/write
++
++ achunksection[k] = chunksection;
++ SectionPos sectionposition = SectionPos.of(pos, b0);
++
++ poiManager.checkConsistencyWithBlocks(sectionposition, chunksection);
+ }
+
+ boolean flag1 = compound.contains("BlockLight", 7);
+@@ -196,9 +221,12 @@
+ }
+ }
+
+- chunkAccess.setLightCorrect(_boolean);
+- CompoundTag compound1 = tag.getCompound("Heightmaps");
+- EnumSet<Heightmap.Types> set = EnumSet.noneOf(Heightmap.Types.class);
++ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading.
++ net.minecraft.nbt.Tag persistentBase = tag.get("ChunkBukkitValues");
++ if (persistentBase instanceof CompoundTag) {
++ ((ChunkAccess) object1).persistentDataContainer.putAll((CompoundTag) persistentBase);
++ }
++ // CraftBukkit end
+
+ for (Heightmap.Types types : chunkAccess.getStatus().heightmapsAfter()) {
+ String serializationKey = types.getSerializationKey();
+@@ -268,6 +307,12 @@
+ );
+ }
+
++ // CraftBukkit start - read/write
++ private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> iregistry) {
++ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS));
++ }
++ // CraftBukkit end
++
+ public static CompoundTag write(ServerLevel level, ChunkAccess chunk) {
+ ChunkPos pos = chunk.getPos();
+ CompoundTag compoundTag = NbtUtils.addCurrentDataVersion(new CompoundTag());
+@@ -377,11 +452,14 @@
+ }
+ }
+
+- compoundTag.put("Heightmaps", compoundTag2);
+- compoundTag.put(
+- "structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), pos, chunk.getAllStarts(), chunk.getAllReferences())
+- );
+- return compoundTag;
++ nbttagcompound.put("Heightmaps", nbttagcompound3);
++ nbttagcompound.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences()));
++ // 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());
++ }
++ // CraftBukkit end
++ return nbttagcompound;
+ }
+
+ private static void saveTicks(ServerLevel level, CompoundTag tag, ChunkAccess.TicksToSave ticksToSave) {
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch
new file mode 100644
index 0000000000..71479e6a9a
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch
@@ -0,0 +1,110 @@
+--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java
++++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+@@ -16,6 +18,10 @@
+ import net.minecraft.world.level.ChunkPos;
+ import net.minecraft.world.level.Level;
+ import net.minecraft.world.level.chunk.ChunkGenerator;
++// CraftBukkit start
++import java.util.concurrent.ExecutionException;
++import net.minecraft.world.level.chunk.ChunkStatus;
++import net.minecraft.world.level.dimension.LevelStem;
+ import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler;
+ import net.minecraft.world.level.storage.DimensionDataStorage;
+
+@@ -35,18 +42,13 @@
+ return this.worker.isOldChunkAround(pos, radius);
+ }
+
+- public CompoundTag upgradeChunkTag(
+- ResourceKey<Level> levelKey,
+- Supplier<DimensionDataStorage> storage,
+- CompoundTag chunkData,
+- Optional<ResourceKey<Codec<? extends ChunkGenerator>>> chunkGeneratorKey
+- ) {
+- int version = getVersion(chunkData);
+- if (version < 1493) {
+- chunkData = DataFixTypes.CHUNK.update(this.fixerUpper, chunkData, version, 1493);
+- if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) {
+- LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage);
+- chunkData = legacyStructureHandler.updateFromLegacy(chunkData);
++ // CraftBukkit start
++ private boolean check(ServerChunkCache cps, int x, int z) {
++ ChunkPos pos = new ChunkPos(x, z);
++ if (cps != null) {
++ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread");
++ if (cps.hasChunk(x, z)) {
++ return true;
+ }
+ }
+
+@@ -60,9 +73,45 @@
+ return var7;
+ }
+
+- private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey<Level> level, Supplier<DimensionDataStorage> storage) {
+- LegacyStructureDataHandler legacyStructureDataHandler = this.legacyStructureHandler;
+- if (legacyStructureDataHandler == null) {
++ public CompoundTag upgradeChunkTag(ResourceKey<LevelStem> resourcekey, Supplier<DimensionDataStorage> supplier, CompoundTag nbttagcompound, Optional<ResourceKey<Codec<? extends ChunkGenerator>>> optional, ChunkPos pos, @Nullable LevelAccessor generatoraccess) {
++ // CraftBukkit end
++ int i = getVersion(nbttagcompound);
++
++ // CraftBukkit start
++ if (i < 1466) {
++ CompoundTag level = nbttagcompound.getCompound("Level");
++ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) {
++ ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource();
++ if (check(cps, pos.x - 1, pos.z) && check(cps, pos.x - 1, pos.z - 1) && check(cps, pos.x, pos.z - 1)) {
++ level.putBoolean("LightPopulated", true);
++ }
++ }
++ }
++ // CraftBukkit end
++
++ if (i < 1493) {
++ nbttagcompound = DataFixTypes.CHUNK.update(this.fixerUpper, nbttagcompound, i, 1493);
++ if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
++ LegacyStructureDataHandler persistentstructurelegacy = this.getLegacyStructureHandler(resourcekey, supplier);
++
++ nbttagcompound = persistentstructurelegacy.updateFromLegacy(nbttagcompound);
++ }
++ }
++
++ injectDatafixingContext(nbttagcompound, resourcekey, optional);
++ nbttagcompound = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, nbttagcompound, Math.max(1493, i));
++ if (i < SharedConstants.getCurrentVersion().getDataVersion().getVersion()) {
++ NbtUtils.addCurrentDataVersion(nbttagcompound);
++ }
++
++ nbttagcompound.remove("__context");
++ return nbttagcompound;
++ }
++
++ private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey<LevelStem> level, Supplier<DimensionDataStorage> storage) { // CraftBukkit
++ LegacyStructureDataHandler persistentstructurelegacy = this.legacyStructureHandler;
++
++ if (persistentstructurelegacy == null) {
+ synchronized (this) {
+ legacyStructureDataHandler = this.legacyStructureHandler;
+ if (legacyStructureDataHandler == null) {
+@@ -74,13 +123,14 @@
+ return legacyStructureDataHandler;
+ }
+
+- public static void injectDatafixingContext(
+- CompoundTag chunkData, ResourceKey<Level> levelKey, Optional<ResourceKey<Codec<? extends ChunkGenerator>>> chunkGeneratorKey
+- ) {
+- CompoundTag compoundTag = new CompoundTag();
+- compoundTag.putString("dimension", levelKey.location().toString());
+- chunkGeneratorKey.ifPresent(generator -> compoundTag.putString("generator", generator.location().toString()));
+- chunkData.put("__context", compoundTag);
++ public static void injectDatafixingContext(CompoundTag chunkData, ResourceKey<LevelStem> levelKey, Optional<ResourceKey<Codec<? extends ChunkGenerator>>> chunkGeneratorKey) { // CraftBukkit
++ CompoundTag nbttagcompound1 = new CompoundTag();
++
++ nbttagcompound1.putString("dimension", levelKey.location().toString());
++ chunkGeneratorKey.ifPresent((resourcekey1) -> {
++ nbttagcompound1.putString("generator", resourcekey1.location().toString());
++ });
++ chunkData.put("__context", nbttagcompound1);
+ }
+
+ public static int getVersion(CompoundTag chunkData) {
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch
@@ -0,0 +1 @@
+
diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch
new file mode 100644
index 0000000000..637d17ecdc
--- /dev/null
+++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch
@@ -0,0 +1,76 @@
+--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
++++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+@@ -26,27 +30,38 @@
+ this.sync = sync;
+ }
+
+- private RegionFile getRegionFile(ChunkPos chunkPos) throws IOException {
+- long _long = ChunkPos.asLong(chunkPos.getRegionX(), chunkPos.getRegionZ());
+- RegionFile regionFile = this.regionCache.getAndMoveToFirst(_long);
+- if (regionFile != null) {
+- return regionFile;
++ private RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
++ long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
++ RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i);
++
++ if (regionfile != null) {
++ return regionfile;
+ } else {
+ if (this.regionCache.size() >= 256) {
+ this.regionCache.removeLast().close();
+ }
+
+ FileUtil.createDirectoriesSafe(this.folder);
+- Path path = this.folder.resolve("r." + chunkPos.getRegionX() + "." + chunkPos.getRegionZ() + ".mca");
+- RegionFile regionFile1 = new RegionFile(path, this.folder, this.sync);
+- this.regionCache.putAndMoveToFirst(_long, regionFile1);
+- return regionFile1;
++ Path path = this.folder;
++ int j = chunkcoordintpair.getRegionX();
++ Path path1 = path.resolve("r." + j + "." + chunkcoordintpair.getRegionZ() + ".mca");
++ if (existingOnly && !java.nio.file.Files.exists(path1)) return null; // CraftBukkit
++ RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync);
++
++ this.regionCache.putAndMoveToFirst(i, regionfile1);
++ return regionfile1;
+ }
+ }
+
+ @Nullable
+ public CompoundTag read(ChunkPos chunkPos) throws IOException {
+- RegionFile regionFile = this.getRegionFile(chunkPos);
++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
++ RegionFile regionfile = this.getRegionFile(chunkPos, true);
++ if (regionfile == null) {
++ return null;
++ }
++ // CraftBukkit end
++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos);
+
+ CompoundTag var4;
+ try (DataInputStream chunkDataInputStream = regionFile.getChunkDataInputStream(chunkPos)) {
+@@ -61,7 +100,13 @@
+ }
+
+ public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException {
+- RegionFile regionFile = this.getRegionFile(chunkPos);
++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
++ RegionFile regionfile = this.getRegionFile(chunkPos, true);
++ if (regionfile == null) {
++ return;
++ }
++ // CraftBukkit end
++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos);
+
+ try (DataInputStream chunkDataInputStream = regionFile.getChunkDataInputStream(chunkPos)) {
+ if (chunkDataInputStream != null) {
+@@ -71,7 +131,8 @@
+ }
+
+ protected void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException {
+- RegionFile regionFile = this.getRegionFile(chunkPos);
++ RegionFile regionfile = this.getRegionFile(chunkPos, false); // CraftBukkit
++
+ if (chunkData == null) {
+ regionFile.clear(chunkPos);
+ } else {