Do not read tile entities in chunks that are positioned outside of the chunk

The tile entities are not accessible and so should not be loaded.
This can happen as a result of users moving regionfiles around,
which would cause a crash on Folia but would appear to function
fine on Paper.
This commit is contained in:
Spottedleaf 2023-06-18 23:04:46 -07:00
parent 183683ecc5
commit 65466558be

View file

@ -109,20 +109,35 @@
} }
} }
@@ -289,6 +317,12 @@ @@ -287,7 +315,13 @@
if (this.chunkStatus.isOrAfter(ChunkStatus.INITIALIZE_LIGHT)) {
protochunk.setLightEngine(levellightengine);
} }
} + }
+
+ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading. + // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading.
+ if (this.persistentDataContainer instanceof CompoundTag) { + if (this.persistentDataContainer instanceof CompoundTag) {
+ ((ChunkAccess) object).persistentDataContainer.putAll((CompoundTag) this.persistentDataContainer); + ((ChunkAccess) object).persistentDataContainer.putAll((CompoundTag) this.persistentDataContainer);
+ } }
+ // CraftBukkit end + // CraftBukkit end
+
((ChunkAccess) object).setLightCorrect(this.lightCorrect); ((ChunkAccess) object).setLightCorrect(this.lightCorrect);
EnumSet<Heightmap.Types> enumset = EnumSet.noneOf(Heightmap.Types.class); EnumSet<Heightmap.Types> enumset = EnumSet.noneOf(Heightmap.Types.class);
Iterator iterator1 = ((ChunkAccess) object).getPersistedStatus().heightmapsAfter().iterator(); @@ -329,6 +363,13 @@
@@ -348,6 +382,12 @@
while (iterator2.hasNext()) {
nbttagcompound = (CompoundTag) iterator2.next();
+ // Paper start - do not read tile entities positioned outside the chunk
+ final BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound);
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
+ LOGGER.warn("Tile entity serialized in chunk {} in world '{}' positioned at {} is located outside of the chunk", chunkPos, world.getWorld().getName(), blockposition);
+ continue;
+ }
+ // Paper end - do not read tile entities positioned outside the chunk
protochunk1.setBlockEntityNbt(nbttagcompound);
}
@@ -348,6 +389,12 @@
return PalettedContainer.codecRO(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS)); return PalettedContainer.codecRO(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS));
} }
@ -135,7 +150,7 @@
public static SerializableChunkData copyOf(ServerLevel world, ChunkAccess chunk) { public static SerializableChunkData copyOf(ServerLevel world, ChunkAccess chunk) {
if (!chunk.canBeSerialized()) { if (!chunk.canBeSerialized()) {
throw new IllegalArgumentException("Chunk can't be serialized: " + String.valueOf(chunk)); throw new IllegalArgumentException("Chunk can't be serialized: " + String.valueOf(chunk));
@@ -419,7 +459,14 @@ @@ -419,7 +466,14 @@
}); });
CompoundTag nbttagcompound1 = packStructureData(StructurePieceSerializationContext.fromLevel(world), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences()); CompoundTag nbttagcompound1 = packStructureData(StructurePieceSerializationContext.fromLevel(world), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences());
@ -151,7 +166,7 @@
} }
} }
@@ -432,7 +479,7 @@ @@ -432,7 +486,7 @@
nbttagcompound.putLong("LastUpdate", this.lastUpdateTime); nbttagcompound.putLong("LastUpdate", this.lastUpdateTime);
nbttagcompound.putLong("InhabitedTime", this.inhabitedTime); nbttagcompound.putLong("InhabitedTime", this.inhabitedTime);
nbttagcompound.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(this.chunkStatus).toString()); nbttagcompound.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(this.chunkStatus).toString());
@ -160,7 +175,7 @@
Logger logger; Logger logger;
if (this.blendingData != null) { if (this.blendingData != null) {
@@ -513,6 +560,11 @@ @@ -513,6 +567,11 @@
}); });
nbttagcompound.put("Heightmaps", nbttagcompound2); nbttagcompound.put("Heightmaps", nbttagcompound2);
nbttagcompound.put("structures", this.structureData); nbttagcompound.put("structures", this.structureData);
@ -172,7 +187,21 @@
return nbttagcompound; return nbttagcompound;
} }
@@ -623,6 +675,12 @@ @@ -564,6 +623,13 @@
chunk.setBlockEntityNbt(nbttagcompound);
} else {
BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound);
+ // Paper start - do not read tile entities positioned outside the chunk
+ ChunkPos chunkPos = chunk.getPos();
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
+ LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk");
+ continue;
+ }
+ // Paper end - do not read tile entities positioned outside the chunk
BlockEntity tileentity = BlockEntity.loadStatic(blockposition, chunk.getBlockState(blockposition), nbttagcompound, world.registryAccess());
if (tileentity != null) {
@@ -623,6 +689,12 @@
StructureStart structurestart = StructureStart.loadStaticStart(context, nbttagcompound1.getCompound(s), worldSeed); StructureStart structurestart = StructureStart.loadStaticStart(context, nbttagcompound1.getCompound(s), worldSeed);
if (structurestart != null) { if (structurestart != null) {