SPIGOT-6814: (Chunk) PersistentData is lost after restart

By: DerFrZocker <derrieple@gmail.com>
This commit is contained in:
CraftBukkit/Spigot 2021-11-29 09:28:19 +11:00
parent 95ab0e27a8
commit 6b0484122e
4 changed files with 71 additions and 34 deletions

View File

@ -18,7 +18,7 @@
this.gameEventDispatcherSections = new Int2ObjectOpenHashMap();
HeightMap.Type[] aheightmap_type = HeightMap.Type.values();
int j = aheightmap_type.length;
@@ -110,8 +110,22 @@
@@ -110,8 +110,20 @@
this.postLoad = chunk_c;
this.blockTicks = levelchunkticks;
this.fluidTicks = levelchunkticks1;
@ -34,22 +34,24 @@
+ public boolean mustNotSave;
+ public boolean needsDecoration;
+
+ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
+ public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
+ // CraftBukkit end
+
public Chunk(WorldServer worldserver, ProtoChunk protochunk, @Nullable Chunk.c chunk_c) {
this(worldserver, protochunk.getPos(), protochunk.getUpgradeData(), protochunk.unpackBlockTicks(), protochunk.unpackFluidTicks(), protochunk.getInhabitedTime(), protochunk.getSections(), chunk_c, protochunk.getBlendingData());
Iterator iterator = protochunk.getBlockEntities().values().iterator();
@@ -142,6 +156,7 @@
@@ -142,6 +154,11 @@
this.setLightCorrect(protochunk.isLightCorrect());
this.unsaved = true;
+ this.needsDecoration = true; // CraftBukkit
+ // CraftBukkit start
+ this.persistentDataContainer = protochunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading.
+ this.persistentDataContainer.setCallback(() -> setUnsaved(true)); // SPIGOT-6814: Handle cases were only persistentData is saved
+ // CraftBukkit end
}
@Override
@@ -238,9 +253,16 @@
@@ -238,9 +255,16 @@
}
}
@ -66,7 +68,7 @@
int i = blockposition.getY();
ChunkSection chunksection = this.getSection(this.getSectionIndex(i));
boolean flag1 = chunksection.hasOnlyAir();
@@ -279,7 +301,8 @@
@@ -279,7 +303,8 @@
if (!chunksection.getBlockState(j, k, l).is(block)) {
return null;
} else {
@ -76,7 +78,7 @@
iblockdata.onPlace(this.level, blockposition, iblockdata1, flag);
}
@@ -324,7 +347,12 @@
@@ -324,7 +349,12 @@
@Nullable
public TileEntity getBlockEntity(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) {
@ -90,7 +92,7 @@
if (tileentity == null) {
NBTTagCompound nbttagcompound = (NBTTagCompound) this.pendingBlockEntities.remove(blockposition);
@@ -395,6 +423,13 @@
@@ -395,6 +425,13 @@
tileentity1.setRemoved();
}
@ -104,7 +106,7 @@
}
}
@@ -424,6 +459,12 @@
@@ -424,6 +461,12 @@
if (this.isInLevel()) {
TileEntity tileentity = (TileEntity) this.blockEntities.remove(blockposition);
@ -117,7 +119,7 @@
if (tileentity != null) {
this.removeGameEventListener(tileentity);
tileentity.setRemoved();
@@ -471,6 +512,55 @@
@@ -471,6 +514,55 @@
}
@ -173,7 +175,7 @@
public boolean isEmpty() {
return false;
}
@@ -659,7 +749,7 @@
@@ -659,7 +751,7 @@
private <T extends TileEntity> void updateBlockEntityTicker(T t0) {
IBlockData iblockdata = t0.getBlockState();
@ -182,7 +184,7 @@
if (blockentityticker == null) {
this.removeBlockEntityTicker(t0.getBlockPos());
@@ -752,7 +842,7 @@
@@ -752,7 +844,7 @@
private boolean loggedInvalidBlockState;
a(TileEntity tileentity, BlockEntityTicker blockentityticker) {
@ -191,7 +193,7 @@
this.ticker = blockentityticker;
}
@@ -775,7 +865,7 @@
@@ -775,7 +867,7 @@
this.loggedInvalidBlockState = true;
Chunk.LOGGER.warn("Block entity {} @ {} state {} invalid for ticking:", new org.apache.logging.log4j.util.Supplier[]{this::getType, this::getPos, () -> {
return iblockdata;

View File

@ -1,18 +1,31 @@
--- a/net/minecraft/world/level/chunk/IChunkAccess.java
+++ b/net/minecraft/world/level/chunk/IChunkAccess.java
@@ -94,7 +94,11 @@
@@ -77,6 +77,11 @@
protected final LevelHeightAccessor levelHeightAccessor;
protected final ChunkSection[] sections;
+ // 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.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
+ // CraftBukkit end
+
public IChunkAccess(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, LevelHeightAccessor levelheightaccessor, IRegistry<BiomeBase> iregistry, long i, @Nullable ChunkSection[] achunksection, @Nullable BlendingData blendingdata) {
this.chunkPos = chunkcoordintpair;
this.upgradeData = chunkconverter;
@@ -94,7 +99,12 @@
}
replaceMissingSections(levelheightaccessor, iregistry, this.sections);
+ // CraftBukkit start
+ this.biomeRegistry = iregistry;
+ this.persistentDataContainer.setCallback(() -> setUnsaved(true)); // CraftBukkit - SPIGOT-6814: Handle cases were only persistentData is saved
}
+ public final IRegistry<BiomeBase> biomeRegistry;
+ // CraftBukkit end
private static void replaceMissingSections(LevelHeightAccessor levelheightaccessor, IRegistry<BiomeBase> iregistry, ChunkSection[] achunksection) {
for (int i = 0; i < achunksection.length; ++i) {
@@ -394,6 +398,27 @@
@@ -394,6 +404,27 @@
}
}
@ -40,7 +53,7 @@
public void fillBiomesFromNoise(BiomeResolver biomeresolver, Climate.Sampler climate_sampler) {
ChunkCoordIntPair chunkcoordintpair = this.getPos();
int i = QuartPos.fromBlock(chunkcoordintpair.getMinBlockX());
@@ -425,8 +450,10 @@
@@ -425,8 +456,10 @@
return this;
}
@ -52,7 +65,7 @@
private final SerializableTickContainer<Block> blocks;
private final SerializableTickContainer<FluidType> fluids;
@@ -442,5 +469,7 @@
@@ -442,5 +475,7 @@
public SerializableTickContainer<FluidType> fluids() {
return this.fluids;
}

View File

@ -9,7 +9,21 @@
Objects.requireNonNull(protochunk);
optional.ifPresent(protochunk::setBelowZeroRetrogen);
@@ -321,7 +321,7 @@
@@ -219,6 +219,13 @@
}
}
+ // 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.NBTBase persistentBase = nbttagcompound.get("ChunkBukkitValues");
+ if (persistentBase instanceof NBTTagCompound) {
+ ((IChunkAccess) object).persistentDataContainer.putAll((NBTTagCompound) persistentBase);
+ }
+ // CraftBukkit end
+
((IChunkAccess) object).setLightCorrect(flag);
NBTTagCompound nbttagcompound2 = nbttagcompound.getCompound("Heightmaps");
EnumSet<HeightMap.Type> enumset = EnumSet.noneOf(HeightMap.Type.class);
@@ -321,7 +328,7 @@
nbttagcompound.putLong("InhabitedTime", ichunkaccess.getInhabitedTime());
nbttagcompound.putString("Status", ichunkaccess.getStatus().getName());
BlendingData blendingdata = ichunkaccess.getBlendingData();
@ -18,28 +32,15 @@
Logger logger;
if (blendingdata != null) {
@@ -452,6 +452,11 @@
@@ -452,6 +459,11 @@
nbttagcompound.put("Heightmaps", nbttagcompound3);
nbttagcompound.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(worldserver), chunkcoordintpair, ichunkaccess.getAllStarts(), ichunkaccess.getAllReferences()));
+ // CraftBukkit start - store chunk persistent data in nbt
+ if (ichunkaccess instanceof Chunk && !((Chunk) ichunkaccess).persistentDataContainer.isEmpty()) {
+ nbttagcompound.put("ChunkBukkitValues", ((Chunk) ichunkaccess).persistentDataContainer.toTagCompound());
+ if (!ichunkaccess.persistentDataContainer.isEmpty()) { // SPIGOT-6814: Always save PDC to account for 1.17 to 1.18 chunk upgrading.
+ nbttagcompound.put("ChunkBukkitValues", ichunkaccess.persistentDataContainer.toTagCompound());
+ }
+ // CraftBukkit end
return nbttagcompound;
}
@@ -498,6 +503,12 @@
}
}
+ // CraftBukkit start - load chunk persistent data from nbt
+ net.minecraft.nbt.NBTBase persistentBase = nbttagcompound.get("ChunkBukkitValues");
+ if (persistentBase instanceof NBTTagCompound) {
+ chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase);
+ }
+ // CraftBukkit end
};
}

View File

@ -17,9 +17,11 @@ import org.bukkit.persistence.PersistentDataType;
public final class CraftPersistentDataContainer implements PersistentDataContainer {
private static final Callback EMPTY = () -> { };
private final Map<String, NBTBase> customDataTags = new HashMap<>();
private final CraftPersistentDataTypeRegistry registry;
private final CraftPersistentDataAdapterContext adapterContext;
private Callback callback = EMPTY;
public CraftPersistentDataContainer(Map<String, NBTBase> customTags, CraftPersistentDataTypeRegistry registry) {
this(registry);
@ -31,6 +33,15 @@ public final class CraftPersistentDataContainer implements PersistentDataContain
this.adapterContext = new CraftPersistentDataAdapterContext(this.registry);
}
public void setCallback(Callback callback) {
if (callback == null) {
this.callback = EMPTY;
return;
}
this.callback = callback;
}
@Override
public <T, Z> void set(NamespacedKey key, PersistentDataType<T, Z> type, Z value) {
Validate.notNull(key, "The provided key for the custom value was null");
@ -38,6 +49,7 @@ public final class CraftPersistentDataContainer implements PersistentDataContain
Validate.notNull(value, "The provided value for the custom value was null");
this.customDataTags.put(key.toString(), registry.wrap(type.getPrimitiveType(), type.toPrimitive(value, adapterContext)));
callback.onValueChange();
}
@Override
@ -91,6 +103,7 @@ public final class CraftPersistentDataContainer implements PersistentDataContain
Validate.notNull(key, "The provided key for the custom value was null");
this.customDataTags.remove(key.toString());
callback.onValueChange();
}
@Override
@ -125,16 +138,19 @@ public final class CraftPersistentDataContainer implements PersistentDataContain
public void put(String key, NBTBase base) {
this.customDataTags.put(key, base);
callback.onValueChange();
}
public void putAll(Map<String, NBTBase> map) {
this.customDataTags.putAll(map);
callback.onValueChange();
}
public void putAll(NBTTagCompound compound) {
for (String key : compound.getAllKeys()) {
this.customDataTags.put(key, compound.get(key));
}
callback.onValueChange();
}
public Map<String, NBTBase> getRaw() {
@ -155,4 +171,9 @@ public final class CraftPersistentDataContainer implements PersistentDataContain
public Map<String, Object> serialize() {
return (Map<String, Object>) CraftNBTTagConfigSerializer.serialize(toTagCompound());
}
@FunctionalInterface
public interface Callback {
void onValueChange();
}
}