Update ticklist saving
This commit is contained in:
		
					parent
					
						
							
								44ee55cf7a
							
						
					
				
			
			
				commit
				
					
						cbb86f2753
					
				
			
		
					 1 changed files with 75 additions and 96 deletions
				
			
		|  | @ -2377,53 +2377,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 | ||||||
|          } |          } | ||||||
|          activityAccountant.endActivity(); // Spigot |          activityAccountant.endActivity(); // Spigot | ||||||
| @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
 | @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
 | ||||||
|   |  | ||||||
|      } |  | ||||||
|   |  | ||||||
| +    // Paper start - async chunk save for unload
 |  | ||||||
| +    // Note: This is very unsafe to call if the chunk is still in use.
 |  | ||||||
| +    // This is also modeled after PlayerChunkMap#save(IChunkAccess, boolean), with the intentional difference being
 |  | ||||||
| +    // serializing the chunk is left to a worker thread.
 |  | ||||||
| +    private void asyncSave(ChunkAccess chunk) {
 |  | ||||||
| +        ChunkPos chunkPos = chunk.getPos();
 |  | ||||||
| +        CompoundTag poiData;
 |  | ||||||
| +        try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) {
 |  | ||||||
| +            poiData = this.poiManager.getData(chunk.getPos());
 |  | ||||||
| +        }
 |  | ||||||
| +
 |  | ||||||
| +        com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z,
 |  | ||||||
| +            poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY);
 |  | ||||||
| +
 |  | ||||||
| +        if (!chunk.isUnsaved()) {
 |  | ||||||
| +            return;
 |  | ||||||
| +        }
 |  | ||||||
| +
 |  | ||||||
| +        ChunkStatus chunkstatus = chunk.getStatus();
 |  | ||||||
| +
 |  | ||||||
| +        // Copied from PlayerChunkMap#save(IChunkAccess, boolean)
 |  | ||||||
| +        if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) {
 |  | ||||||
| +            // Paper start - Optimize save by using status cache
 |  | ||||||
| +            if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) {
 |  | ||||||
| +                return;
 |  | ||||||
| +            }
 |  | ||||||
| +        }
 |  | ||||||
| +
 |  | ||||||
| +        ChunkSerializer.AsyncSaveData asyncSaveData;
 |  | ||||||
| +        try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) {
 |  | ||||||
| +            asyncSaveData = ChunkSerializer.getAsyncSaveData(this.level, chunk);
 |  | ||||||
| +        }
 |  | ||||||
| +
 |  | ||||||
| +        this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY,
 |  | ||||||
| +            asyncSaveData, chunk);
 |  | ||||||
| +
 |  | ||||||
| +        chunk.setUnsaved(false);
 |  | ||||||
| +    }
 |  | ||||||
| +    // Paper end
 |  | ||||||
| +
 |  | ||||||
|      private void scheduleUnload(long pos, ChunkHolder holder) { |  | ||||||
|          CompletableFuture<ChunkAccess> completablefuture = holder.getChunkToSave(); |  | ||||||
|          Consumer<ChunkAccess> consumer = (ichunkaccess) -> { // CraftBukkit - decompile error |  | ||||||
| @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
 |  | ||||||
|                          ((LevelChunk) ichunkaccess).setLoaded(false); |                          ((LevelChunk) ichunkaccess).setLoaded(false); | ||||||
|                      } |                      } | ||||||
|   |   | ||||||
|  | @ -2509,8 +2462,49 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 | ||||||
|   |   | ||||||
|      private void markPositionReplaceable(ChunkPos pos) { |      private void markPositionReplaceable(ChunkPos pos) { | ||||||
| @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
 | @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
 | ||||||
|  |          return this.tickingGenerated.get(); | ||||||
|      } |      } | ||||||
|   |   | ||||||
|  | +    // Paper start - async chunk save for unload
 | ||||||
|  | +    // Note: This is very unsafe to call if the chunk is still in use.
 | ||||||
|  | +    // This is also modeled after PlayerChunkMap#save(IChunkAccess, boolean), with the intentional difference being
 | ||||||
|  | +    // serializing the chunk is left to a worker thread.
 | ||||||
|  | +    private void asyncSave(ChunkAccess chunk) {
 | ||||||
|  | +        ChunkPos chunkPos = chunk.getPos();
 | ||||||
|  | +        CompoundTag poiData;
 | ||||||
|  | +        try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) {
 | ||||||
|  | +            poiData = this.poiManager.getData(chunk.getPos());
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z,
 | ||||||
|  | +            poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY);
 | ||||||
|  | +
 | ||||||
|  | +        if (!chunk.isUnsaved()) {
 | ||||||
|  | +            return;
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        ChunkStatus chunkstatus = chunk.getStatus();
 | ||||||
|  | +
 | ||||||
|  | +        // Copied from PlayerChunkMap#save(IChunkAccess, boolean)
 | ||||||
|  | +        if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) {
 | ||||||
|  | +            // Paper start - Optimize save by using status cache
 | ||||||
|  | +            if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) {
 | ||||||
|  | +                return;
 | ||||||
|  | +            }
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        ChunkSerializer.AsyncSaveData asyncSaveData;
 | ||||||
|  | +        try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) {
 | ||||||
|  | +            asyncSaveData = ChunkSerializer.getAsyncSaveData(this.level, chunk);
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY,
 | ||||||
|  | +            asyncSaveData, chunk);
 | ||||||
|  | +
 | ||||||
|  | +        chunk.setUnsaved(false);
 | ||||||
|  | +    }
 | ||||||
|  | +    // Paper end
 | ||||||
|  | +
 | ||||||
|      public boolean save(ChunkAccess chunk) { |      public boolean save(ChunkAccess chunk) { | ||||||
| +        try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper
 | +        try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper
 | ||||||
|          this.poiManager.flush(chunk.getPos()); |          this.poiManager.flush(chunk.getPos()); | ||||||
|  | @ -3035,31 +3029,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 | ||||||
|   |   | ||||||
| -            return protochunk1;
 | -            return protochunk1;
 | ||||||
| +            return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
 | +            return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
 | ||||||
| +        }
 |  | ||||||
| +    }
 |  | ||||||
| +
 |  | ||||||
| +    // Paper start - async chunk save for unload
 |  | ||||||
| +    public static final class AsyncSaveData {
 |  | ||||||
| +        public final DataLayer[] blockLight;
 |  | ||||||
| +        public final DataLayer[] skyLight;
 |  | ||||||
| +
 |  | ||||||
| +        public final ListTag blockTickList; // non-null if we had to go to the server's tick list
 |  | ||||||
| +        public final ListTag fluidTickList; // non-null if we had to go to the server's tick list
 |  | ||||||
| +        public final ListTag blockEntities;
 |  | ||||||
| +
 |  | ||||||
| +        public final long worldTime;
 |  | ||||||
| +
 |  | ||||||
| +        public AsyncSaveData(DataLayer[] blockLight, DataLayer[] skyLight,
 |  | ||||||
| +                             ListTag blockTickList, ListTag fluidTickList, ListTag blockEntities, long worldTime) {
 |  | ||||||
| +            this.blockLight = blockLight;
 |  | ||||||
| +            this.skyLight = skyLight;
 |  | ||||||
| +            this.blockTickList = blockTickList;
 |  | ||||||
| +            this.fluidTickList = fluidTickList;
 |  | ||||||
| +            this.blockEntities = blockEntities;
 |  | ||||||
| +            this.worldTime = worldTime;
 |  | ||||||
|          } |          } | ||||||
|      } |      } | ||||||
|   |   | ||||||
|  | +    // Paper start - async chunk save for unload
 | ||||||
|  | +    public record AsyncSaveData(
 | ||||||
|  | +        DataLayer[] blockLight,
 | ||||||
|  | +        DataLayer[] skyLight,
 | ||||||
|  | +        Tag blockTickList, // non-null if we had to go to the server's tick list
 | ||||||
|  | +        Tag fluidTickList, // non-null if we had to go to the server's tick list
 | ||||||
|  | +        ListTag blockEntities,
 | ||||||
|  | +        long worldTime
 | ||||||
|  | +    ) {}
 | ||||||
|  | +
 | ||||||
| +    // must be called sync
 | +    // must be called sync
 | ||||||
| +    public static AsyncSaveData getAsyncSaveData(ServerLevel world, ChunkAccess chunk) {
 | +    public static AsyncSaveData getAsyncSaveData(ServerLevel world, ChunkAccess chunk) {
 | ||||||
| +        org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save");
 | +        org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save");
 | ||||||
|  | @ -3086,25 +3068,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 | ||||||
| +            skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray;
 | +            skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray;
 | ||||||
| +        }
 | +        }
 | ||||||
| +
 | +
 | ||||||
| +        net.minecraft.world.ticks.TickContainerAccess<Block> blockTickList = chunk.getBlockTicks();
 | +        final CompoundTag tickLists = new CompoundTag();
 | ||||||
| +
 | +        ChunkSerializer.saveTicks(world, tickLists, chunk.getTicksForSerialization());
 | ||||||
| +        //TODO check ChunkSerializer "block_ticks"
 |  | ||||||
| +        ListTag blockTickListSerialized = null; // Paper - remove null
 |  | ||||||
| +        // if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) {
 |  | ||||||
| +        //     blockTickListSerialized = null;
 |  | ||||||
| +        // } else {
 |  | ||||||
| +        //     blockTickListSerialized = world.getBlockTicks().save(chunkPos);
 |  | ||||||
| +        // }
 |  | ||||||
| +
 |  | ||||||
| +        net.minecraft.world.ticks.TickContainerAccess<Fluid> fluidTickList = chunk.getFluidTicks();
 |  | ||||||
| +
 |  | ||||||
| +        //TODO
 |  | ||||||
| +        ListTag fluidTickListSerialized = null; // Paper - remove null
 |  | ||||||
| +        // if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) {
 |  | ||||||
| +        //     fluidTickListSerialized = null;
 |  | ||||||
| +        // } else {
 |  | ||||||
| +        //     fluidTickListSerialized = world.getFluidTicks().save(chunkPos);
 |  | ||||||
| +        // }
 |  | ||||||
| +
 | +
 | ||||||
| +        ListTag blockEntitiesSerialized = new ListTag();
 | +        ListTag blockEntitiesSerialized = new ListTag();
 | ||||||
| +        for (final BlockPos blockPos : chunk.getBlockEntitiesPos()) {
 | +        for (final BlockPos blockPos : chunk.getBlockEntitiesPos()) {
 | ||||||
|  | @ -3114,7 +3079,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 | ||||||
| +            }
 | +            }
 | ||||||
| +         }
 | +         }
 | ||||||
| +
 | +
 | ||||||
| +        return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime());
 | +        return new AsyncSaveData(
 | ||||||
|  | +            blockLight,
 | ||||||
|  | +            skyLight,
 | ||||||
|  | +            tickLists.get(BLOCK_TICKS_TAG),
 | ||||||
|  | +            tickLists.get(FLUID_TICKS_TAG),
 | ||||||
|  | +            blockEntitiesSerialized,
 | ||||||
|  | +            world.getGameTime()
 | ||||||
|  | +        );
 | ||||||
| +     }
 | +     }
 | ||||||
| +
 | +
 | ||||||
|      private static void logErrors(ChunkPos chunkPos, int y, String message) { |      private static void logErrors(ChunkPos chunkPos, int y, String message) { | ||||||
|  | @ -3126,7 +3098,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 | ||||||
|      public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { |      public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { | ||||||
| +        return saveChunk(world, chunk, null);
 | +        return saveChunk(world, chunk, null);
 | ||||||
| +    }
 | +    }
 | ||||||
| +    public static CompoundTag saveChunk(ServerLevel world, ChunkAccess chunk, AsyncSaveData asyncsavedata) {
 | +    public static CompoundTag saveChunk(ServerLevel world, ChunkAccess chunk, @org.checkerframework.checker.nullness.qual.Nullable AsyncSaveData asyncsavedata) {
 | ||||||
| +        // Paper end
 | +        // Paper end
 | ||||||
|          ChunkPos chunkcoordintpair = chunk.getPos(); |          ChunkPos chunkcoordintpair = chunk.getPos(); | ||||||
|          CompoundTag nbttagcompound = new CompoundTag(); |          CompoundTag nbttagcompound = new CompoundTag(); | ||||||
|  | @ -3181,13 +3153,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 | ||||||
|          CompoundTag nbttagcompound2; |          CompoundTag nbttagcompound2; | ||||||
|   |   | ||||||
| @@ -0,0 +0,0 @@ public class ChunkSerializer {
 | @@ -0,0 +0,0 @@ public class ChunkSerializer {
 | ||||||
|      private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) { |              nbttagcompound.put("CarvingMasks", nbttagcompound2); | ||||||
|          long i = world.getLevelData().getGameTime(); |          } | ||||||
|   |   | ||||||
| +        //TODO original patch line 3259
 | +        // Paper start
 | ||||||
|          nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> { | +        if (asyncsavedata != null) {
 | ||||||
|              return Registry.BLOCK.getKey(block).toString(); | +            nbttagcompound.put(BLOCK_TICKS_TAG, asyncsavedata.blockTickList);
 | ||||||
|          })); | +            nbttagcompound.put(FLUID_TICKS_TAG, asyncsavedata.fluidTickList);
 | ||||||
|  | +        } else {
 | ||||||
|  |          ChunkSerializer.saveTicks(world, nbttagcompound, chunk.getTicksForSerialization()); | ||||||
|  | +        }
 | ||||||
|  | +        // Paper end
 | ||||||
|  |          nbttagcompound.put("PostProcessing", ChunkSerializer.packOffsets(chunk.getPostProcessing())); | ||||||
|  |          CompoundTag nbttagcompound3 = new CompoundTag(); | ||||||
|  |          Iterator iterator1 = chunk.getHeightmaps().iterator(); | ||||||
| diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
 | diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
 | ||||||
| index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | ||||||
| --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
 | --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jason Penilla
				Jason Penilla