aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNassim Jahnke <[email protected]>2024-10-27 10:26:44 +0100
committerNassim Jahnke <[email protected]>2024-10-27 10:40:53 +0100
commitb6305644f91fbbd78b648b47740a10194bda6916 (patch)
tree84193ee51a4d1dd7231bf297e4dcde6946bcdb7d
parent348c8550967380d9843e365e769f67eee8a8e474 (diff)
downloadPaper-b6305644f91fbbd78b648b47740a10194bda6916.tar.gz
Paper-b6305644f91fbbd78b648b47740a10194bda6916.zip
More patches
-rw-r--r--patches/server/1049-Incremental-chunk-and-player-saving.patch (renamed from patches/unapplied/server/1030-Incremental-chunk-and-player-saving.patch)44
-rw-r--r--patches/server/1050-Optimise-general-POI-access.patch (renamed from patches/unapplied/server/1011-Optimise-general-POI-access.patch)32
-rw-r--r--patches/server/1051-Fix-entity-tracker-desync-when-new-players-are-added.patch (renamed from patches/unapplied/server/1025-Fix-entity-tracker-desync-when-new-players-are-added.patch)36
-rw-r--r--patches/server/1052-Lag-compensation-ticks.patch (renamed from patches/unapplied/server/1026-Lag-compensation-ticks.patch)38
-rw-r--r--patches/server/1053-Optimise-collision-checking-in-player-move-packet-ha.patch (renamed from patches/unapplied/server/1039-Optimise-collision-checking-in-player-move-packet-ha.patch)20
-rw-r--r--patches/unapplied/server/1028-Write-SavedData-IO-async.patch164
6 files changed, 82 insertions, 252 deletions
diff --git a/patches/unapplied/server/1030-Incremental-chunk-and-player-saving.patch b/patches/server/1049-Incremental-chunk-and-player-saving.patch
index 92967eb763..9a12860c6a 100644
--- a/patches/unapplied/server/1030-Incremental-chunk-and-player-saving.patch
+++ b/patches/server/1049-Incremental-chunk-and-player-saving.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index b64c3e29e2b8e890073fee0b45c8b8dfc2b642fd..aa38e3b297209cc121e7dc7a6ac9588c18bf9357 100644
+index de80ac827c8ac3630d68b73cb425d4b56f7d2cd7..f422cbcb69d6fda2b4e229cbdbf10abd0d36d6f9 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -992,7 +992,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -1009,7 +1009,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try {
this.isSaving = true;
@@ -17,32 +17,26 @@ index b64c3e29e2b8e890073fee0b45c8b8dfc2b642fd..aa38e3b297209cc121e7dc7a6ac9588c
flag3 = this.saveAllChunks(suppressLogs, flush, force);
} finally {
this.isSaving = false;
-@@ -1595,16 +1595,28 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -1676,9 +1676,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
--this.ticksUntilAutosave;
-- // CraftBukkit start
-- if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) {
-- this.ticksUntilAutosave = this.autosavePeriod;
-- // CraftBukkit end
-- MinecraftServer.LOGGER.debug("Autosave started");
-- this.profiler.push("save");
-- this.saveEverything(true, false, false);
-- this.profiler.pop();
-- MinecraftServer.LOGGER.debug("Autosave finished");
+- if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { // CraftBukkit
+- this.autoSave();
+ // Paper start - Incremental chunk and player saving
++ final ProfilerFiller profiler = Profiler.get();
+ int playerSaveInterval = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.rate;
+ if (playerSaveInterval < 0) {
+ playerSaveInterval = autosavePeriod;
+ }
-+ this.profiler.push("save");
++ profiler.push("save");
+ final boolean fullSave = autosavePeriod > 0 && this.tickCount % autosavePeriod == 0;
+ try {
+ this.isSaving = true;
+ if (playerSaveInterval > 0) {
+ this.playerList.saveAll(playerSaveInterval);
+ }
-+ for (ServerLevel level : this.getAllLevels()) {
++ for (final ServerLevel level : this.getAllLevels()) {
+ if (level.paperConfig().chunks.autoSaveInterval.value() > 0) {
+ level.saveIncrementally(fullSave);
+ }
@@ -50,16 +44,16 @@ index b64c3e29e2b8e890073fee0b45c8b8dfc2b642fd..aa38e3b297209cc121e7dc7a6ac9588c
+ } finally {
+ this.isSaving = false;
}
-+ this.profiler.pop();
++ profiler.pop();
+ // Paper end - Incremental chunk and player saving
- // Paper start - move executeAll() into full server tick timing
- try (co.aikar.timings.Timing ignored = MinecraftTimings.processTasksTimer.startTiming()) {
- this.runAllTasks();
+
+ ProfilerFiller gameprofilerfiller = Profiler.get();
+
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 202975cf97ae143622a0c19826b0d63ad2afa0ce..f9abf63e12ea930275121b470e4e4906cff0fc12 100644
+index a7420e4522e0dff72ce7f8a791b9cd4bfa270106..fd07824ff6a928ca6e2f56477a63bac7aaeb8c15 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -1315,6 +1315,35 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -1371,6 +1371,35 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos);
}
@@ -96,10 +90,10 @@ index 202975cf97ae143622a0c19826b0d63ad2afa0ce..f9abf63e12ea930275121b470e4e4906
// Paper start - add close param
this.save(progressListener, flush, savingDisabled, false);
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 8dc3ba983fd4c61e463867be8d224aa90424215a..6c280abdef5f80b668d6090f9d35283a33e21e0c 100644
+index 8ceeebb561046933cba0725e15732fa074226884..8c9148426f23cbbdfaf7ae66657d1a620f8bd853 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -203,6 +203,7 @@ import org.bukkit.inventory.MainHand;
+@@ -221,6 +221,7 @@ import org.bukkit.inventory.MainHand;
public class ServerPlayer extends net.minecraft.world.entity.player.Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
private static final Logger LOGGER = LogUtils.getLogger();
@@ -108,10 +102,10 @@ index 8dc3ba983fd4c61e463867be8d224aa90424215a..6c280abdef5f80b668d6090f9d35283a
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
-index 30b6f5d4af1dc799d5ffee6a345bcf92528df7cd..5e2c4969e77c669acbb4a13c07033cb267c3d586 100644
+index 3642444d45038fd1a07768ff96bfbd8678b02e04..f8f8e8f602f416fe97fc23ef6efeee7af2749292 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
-@@ -569,6 +569,7 @@ public abstract class PlayerList {
+@@ -519,6 +519,7 @@ public abstract class PlayerList {
protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
@@ -119,7 +113,7 @@ index 30b6f5d4af1dc799d5ffee6a345bcf92528df7cd..5e2c4969e77c669acbb4a13c07033cb2
this.playerIo.save(player);
ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit
-@@ -1193,10 +1194,22 @@ public abstract class PlayerList {
+@@ -1153,10 +1154,22 @@ public abstract class PlayerList {
}
public void saveAll() {
diff --git a/patches/unapplied/server/1011-Optimise-general-POI-access.patch b/patches/server/1050-Optimise-general-POI-access.patch
index b3636fe591..0e3d18cfa4 100644
--- a/patches/unapplied/server/1011-Optimise-general-POI-access.patch
+++ b/patches/server/1050-Optimise-general-POI-access.patch
@@ -886,10 +886,10 @@ index d5a549f08b98c80a5cf0eef02cb8a389c32dfecb..92731b6b593289e9f583c9b705b219e8
BlockPos blockPos = path.getTarget();
Optional<Holder<PoiType>> optional = poiManager.getType(blockPos);
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
-index d7a6eab60bf26916f78f858e224573560e581fef..a908bf1dc5e821dcf6981a8c21076fb0bdc6516d 100644
+index 5930a430983061afddf20e3208ff2462ca1b78cd..63a94b6068fdaef8bb26675c2927cb729ced1dac 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
-@@ -268,36 +268,45 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
+@@ -254,36 +254,45 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> im
public Optional<BlockPos> find(
Predicate<Holder<PoiType>> typePredicate, Predicate<BlockPos> posPredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus
) {
@@ -903,10 +903,10 @@ index d7a6eab60bf26916f78f858e224573560e581fef..a908bf1dc5e821dcf6981a8c21076fb0
public Optional<BlockPos> findClosest(Predicate<Holder<PoiType>> typePredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus) {
- return this.getInRange(typePredicate, pos, radius, occupationStatus)
- .map(PoiRecord::getPos)
-- .min(Comparator.comparingDouble(blockPos2 -> blockPos2.distSqr(pos)));
+- .min(Comparator.comparingDouble(poiPos -> poiPos.distSqr(pos)));
+ // Paper start - re-route to faster logic
-+ BlockPos ret = io.papermc.paper.util.PoiAccess.findClosestPoiDataPosition(this, typePredicate, null, pos, radius, radius * radius, occupationStatus, false);
-+ return Optional.ofNullable(ret);
++ BlockPos closestPos = io.papermc.paper.util.PoiAccess.findClosestPoiDataPosition(this, typePredicate, null, pos, radius, radius * radius, occupationStatus, false);
++ return Optional.ofNullable(closestPos);
+ // Paper end - re-route to faster logic
}
@@ -929,27 +929,27 @@ index d7a6eab60bf26916f78f858e224573560e581fef..a908bf1dc5e821dcf6981a8c21076fb0
- return this.getInRange(typePredicate, pos, radius, occupationStatus)
- .map(PoiRecord::getPos)
- .filter(posPredicate)
-- .min(Comparator.comparingDouble(blockPos2 -> blockPos2.distSqr(pos)));
+- .min(Comparator.comparingDouble(poiPos -> poiPos.distSqr(pos)));
+ // Paper start - re-route to faster logic
-+ BlockPos ret = io.papermc.paper.util.PoiAccess.findClosestPoiDataPosition(this, typePredicate, posPredicate, pos, radius, radius * radius, occupationStatus, false);
-+ return Optional.ofNullable(ret);
++ BlockPos closestPos = io.papermc.paper.util.PoiAccess.findClosestPoiDataPosition(this, typePredicate, posPredicate, pos, radius, radius * radius, occupationStatus, false);
++ return Optional.ofNullable(closestPos);
+ // Paper end - re-route to faster logic
}
- public Optional<BlockPos> take(Predicate<Holder<PoiType>> typePredicate, BiPredicate<Holder<PoiType>, BlockPos> biPredicate, BlockPos pos, int radius) {
+ public Optional<BlockPos> take(Predicate<Holder<PoiType>> typePredicate, BiPredicate<Holder<PoiType>, BlockPos> posPredicate, BlockPos pos, int radius) {
- return this.getInRange(typePredicate, pos, radius, PoiManager.Occupancy.HAS_SPACE)
-- .filter(poi -> biPredicate.test(poi.getPoiType(), poi.getPos()))
+- .filter(poi -> posPredicate.test(poi.getPoiType(), poi.getPos()))
- .findFirst()
+ // Paper start - re-route to faster logic
+ final @javax.annotation.Nullable PoiRecord closest = io.papermc.paper.util.PoiAccess.findClosestPoiDataRecord(
-+ this, typePredicate, biPredicate, pos, radius, radius * radius, Occupancy.HAS_SPACE, false
++ this, typePredicate, posPredicate, pos, radius, radius * radius, Occupancy.HAS_SPACE, false
+ );
+ return Optional.ofNullable(closest)
+ // Paper end - re-route to faster logic
.map(poi -> {
poi.acquireTicket();
return poi.getPos();
-@@ -312,8 +321,21 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
+@@ -298,8 +307,21 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> im
int radius,
RandomSource random
) {
@@ -974,7 +974,7 @@ index d7a6eab60bf26916f78f858e224573560e581fef..a908bf1dc5e821dcf6981a8c21076fb0
public boolean release(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
-index a6c0e89cb645693034f8e90ac2de8f2da457453c..11e895d837794d79a76303b912092096bd7d07a8 100644
+index 712cbfc100e8aaf612d1d651dae64f57f892a768..827991ee61406bcda3f4794dcc735c0e2e0e09af 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
@@ -26,7 +26,7 @@ import org.slf4j.Logger;
@@ -987,10 +987,10 @@ index a6c0e89cb645693034f8e90ac2de8f2da457453c..11e895d837794d79a76303b912092096
private boolean isValid;
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
-index c7ed3eb80f6e8b918434153093644776866aa220..21de1b95f2a5d136149447472e871f675760ba1a 100644
+index c3beb7fcad46a917d2b61bd0a0e98e5106056728..9b97fb2d125df4df715599aab27e074707731466 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
-@@ -81,11 +81,11 @@ public abstract class SectionStorage<R> implements AutoCloseable, ca.spottedleaf
+@@ -131,11 +131,11 @@ public class SectionStorage<R, P> implements AutoCloseable, ca.spottedleaf.moonr
}
@Nullable
@@ -1005,7 +1005,7 @@ index c7ed3eb80f6e8b918434153093644776866aa220..21de1b95f2a5d136149447472e871f67
return Optional.empty();
} else {
diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
-index fd04a50183ccb1f21fc6efa70256e1bb4db2d6d4..49f7ba292b82bac1643cc07aa576f3c37b8e8ab3 100644
+index 83d294f6f48b867d09ea0d339c779011bf4138a5..9204bb0538297f233442a86733a33e6d0eea8114 100644
--- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
+++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
@@ -53,17 +53,39 @@ public class PortalForcer {
diff --git a/patches/unapplied/server/1025-Fix-entity-tracker-desync-when-new-players-are-added.patch b/patches/server/1051-Fix-entity-tracker-desync-when-new-players-are-added.patch
index f767b9ab91..6aecc462a4 100644
--- a/patches/unapplied/server/1025-Fix-entity-tracker-desync-when-new-players-are-added.patch
+++ b/patches/server/1051-Fix-entity-tracker-desync-when-new-players-are-added.patch
@@ -29,7 +29,7 @@ client will not tick the entity and thus not lerp the entity
from its old position to its new position.
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java
-index 854baa554da2215a656f976ae2973341c3b2d61c..792b9a72a610cc512a8920d61013b6ba02f71e47 100644
+index f6e1deb2f849d8b01b15cfa69e2f6cd5f2b1512b..f66e40326c510aa3267542b1a24ed75d1ed6d3f1 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java
@@ -42,9 +42,11 @@ public class ClientboundAddEntityPacket implements Packet<ClientGamePacketListen
@@ -48,10 +48,10 @@ index 854baa554da2215a656f976ae2973341c3b2d61c..792b9a72a610cc512a8920d61013b6ba
entityTrackerEntry.getLastSentYRot(),
entity.getType(),
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index 21370ed6c7d98d3f3546f0365ac50e5c26ba3bde..af8cb316ac169aa8d98a88765b85bb013b9ba961 100644
+index d692af061ded8cd5bcf1d268e6bd521d84f99c39..bf43bdb43c5301c0e0954729bc531fb6a5045075 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -1269,6 +1269,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1277,6 +1277,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.serverEntity.addPairing(player);
}
// Paper end - entity tracking events
@@ -60,10 +60,10 @@ index 21370ed6c7d98d3f3546f0365ac50e5c26ba3bde..af8cb316ac169aa8d98a88765b85bb01
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
-index 12d86f27d04bffed8c3844e36b42fbc2f84dacff..8ea2f24695f5dad55e21f238b69442513e7a90c6 100644
+index 5bbc7ceaafc163f12344e5d5d355ad2ff30ddca2..90eb4927fa51ce3df86aa7b6c71f49150a03e337 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
-@@ -96,6 +96,13 @@ public class ServerEntity {
+@@ -100,6 +100,13 @@ public class ServerEntity {
this.trackedDataValues = entity.getEntityData().getNonDefaultValues();
}
@@ -77,25 +77,25 @@ index 12d86f27d04bffed8c3844e36b42fbc2f84dacff..8ea2f24695f5dad55e21f238b6944251
public void sendChanges() {
// Paper start - optimise collisions
if (((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity)this.entity).moonrise$isHardColliding()) {
-@@ -145,7 +152,7 @@ public class ServerEntity {
+@@ -149,7 +156,7 @@ public class ServerEntity {
}
}
- if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) {
+ if (this.forceStateResync || this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) { // Paper - fix desync when a player is added to the tracker
- int i;
- int j;
+ byte b0 = Mth.packDegrees(this.entity.getYRot());
+ byte b1 = Mth.packDegrees(this.entity.getXRot());
+ boolean flag = Math.abs(b0 - this.lastSentYRot) >= 1 || Math.abs(b1 - this.lastSentXRot) >= 1;
+@@ -199,7 +206,7 @@ public class ServerEntity {
+ long k = this.positionCodec.encodeZ(vec3d);
+ boolean flag5 = i < -32768L || i > 32767L || j < -32768L || j > 32767L || k < -32768L || k > 32767L;
-@@ -185,7 +192,7 @@ public class ServerEntity {
- long i1 = this.positionCodec.encodeZ(vec3d);
- boolean flag6 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L;
-
-- if (!flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) {
-+ if (!this.forceStateResync && !flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) { // Paper - fix desync when a player is added to the tracker
- if ((!flag2 || !flag3) && !(this.entity instanceof AbstractArrow)) {
- if (flag2) {
- packet1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), this.entity.onGround());
-@@ -249,6 +256,7 @@ public class ServerEntity {
+- if (!flag5 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) {
++ if (!this.forceStateResync && !flag5 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) { // Paper - fix desync when a player is added to the tracker
+ if ((!flag2 || !flag) && !(this.entity instanceof AbstractArrow)) {
+ if (flag2) {
+ packet1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) i), (short) ((int) j), (short) ((int) k), this.entity.onGround());
+@@ -265,6 +272,7 @@ public class ServerEntity {
}
this.entity.hasImpulse = false;
diff --git a/patches/unapplied/server/1026-Lag-compensation-ticks.patch b/patches/server/1052-Lag-compensation-ticks.patch
index aa8b7f2d46..2643c943aa 100644
--- a/patches/unapplied/server/1026-Lag-compensation-ticks.patch
+++ b/patches/server/1052-Lag-compensation-ticks.patch
@@ -8,10 +8,10 @@ Areas affected by lag comepnsation:
- Eating food items
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index d25d500a2206d4f7e821de3766e8a523df4370e3..b64c3e29e2b8e890073fee0b45c8b8dfc2b642fd 100644
+index f422cbcb69d6fda2b4e229cbdbf10abd0d36d6f9..73855f4555f781741f70267be65dec1ebb98b46a 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -321,6 +321,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -332,6 +332,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public volatile Thread shutdownThread; // Paper
public volatile boolean abnormalExit = false; // Paper
@@ -19,22 +19,22 @@ index d25d500a2206d4f7e821de3766e8a523df4370e3..b64c3e29e2b8e890073fee0b45c8b8df
public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) {
AtomicReference<S> atomicreference = new AtomicReference();
-@@ -1763,6 +1764,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -1874,6 +1875,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers
+ worldserver.updateLagCompensationTick(); // Paper - lag compensation
- this.profiler.push(() -> {
+ gameprofilerfiller.push(() -> {
String s = String.valueOf(worldserver);
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index d223ecfbb0b8986507ce8b6728edbf7c8d818b7d..9e1af229f52a8ac09833901ad53bd154fed34a4f 100644
+index fd07824ff6a928ca6e2f56477a63bac7aaeb8c15..b2bbc9f3efbb7c949cc862eeee5d5f47be5d804f 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -485,6 +485,17 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
- return this.entityTickingChunks;
+@@ -577,6 +577,17 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ );
}
- // Paper end - rewrite chunk system
+ // Paper end - chunk tick iteration
+ // Paper start - lag compensation
+ private long lagCompensationTick = net.minecraft.server.MinecraftServer.SERVER_INIT;
+
@@ -50,10 +50,10 @@ index d223ecfbb0b8986507ce8b6728edbf7c8d818b7d..9e1af229f52a8ac09833901ad53bd154
// Add env and gen to constructor, IWorldDataServer -> WorldDataServer
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
-index 24b1715397ba8e6f5e9841a030d0e3d964356f89..cc01ead133cc6859ca5d7a1d0ac3c12955e590da 100644
+index 504c996220b278c194c93e001a3b326d549868ec..a96f859a5d0c6ec692d4627a69f3c9ee49199dbc 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
-@@ -129,7 +129,7 @@ public class ServerPlayerGameMode {
+@@ -127,7 +127,7 @@ public class ServerPlayerGameMode {
}
public void tick() {
@@ -63,10 +63,10 @@ index 24b1715397ba8e6f5e9841a030d0e3d964356f89..cc01ead133cc6859ca5d7a1d0ac3c129
if (this.hasDelayedDestroy) {
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-index 5079775ce8f86fb061e616190513f56ff086e409..13c93281f6b81e88f2f54befb8e6a3e4bdabf53d 100644
+index 22b3d3d945cbddae25abfca7d900324c79d32293..a68ca22d5f8909d2ad37feded448f777736bf7db 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-@@ -3900,6 +3900,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -4052,6 +4052,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer);
}
// Paper end - Properly cancel usable items
@@ -77,21 +77,21 @@ index 5079775ce8f86fb061e616190513f56ff086e409..13c93281f6b81e88f2f54befb8e6a3e4
private void updatingUsingItem() {
if (this.isUsingItem()) {
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
-@@ -3918,7 +3922,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
- this.triggerItemUseEffects(stack, 5);
- }
+@@ -4066,7 +4070,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
+ protected void updateUsingItem(ItemStack stack) {
+ stack.onUseTick(this.level(), this, this.getUseItemRemainingTicks());
- if (--this.useItemRemaining == 0 && !this.level().isClientSide && !stack.useOnRelease()) {
+ // Paper start - lag compensate eating
+ // we add 1 to the expected time to avoid lag compensating when we should not
-+ boolean shouldLagCompensate = this.useItem.has(DataComponents.FOOD) && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1L + this.totalEatTimeTicks) * 50L * (1000L * 1000L));
++ final boolean shouldLagCompensate = this.useItem.has(DataComponents.FOOD) && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1L + this.totalEatTimeTicks) * 50L * (1000L * 1000L));
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide && !stack.useOnRelease()) {
+ this.useItemRemaining = 0;
+ // Paper end - lag compensate eating
this.completeUsingItem();
}
-@@ -3964,7 +3973,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -4104,7 +4113,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper - Prevent consuming the wrong itemstack
this.useItem = itemstack;
@@ -103,7 +103,7 @@ index 5079775ce8f86fb061e616190513f56ff086e409..13c93281f6b81e88f2f54befb8e6a3e4
if (!this.level().isClientSide) {
this.setLivingEntityFlag(1, true);
this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND);
-@@ -3989,7 +4001,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -4129,7 +4141,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
} else if (!this.isUsingItem() && !this.useItem.isEmpty()) {
this.useItem = ItemStack.EMPTY;
@@ -115,7 +115,7 @@ index 5079775ce8f86fb061e616190513f56ff086e409..13c93281f6b81e88f2f54befb8e6a3e4
}
}
-@@ -4132,7 +4147,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -4260,7 +4275,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
this.useItem = ItemStack.EMPTY;
diff --git a/patches/unapplied/server/1039-Optimise-collision-checking-in-player-move-packet-ha.patch b/patches/server/1053-Optimise-collision-checking-in-player-move-packet-ha.patch
index 2caf83aaca..a75038dc8a 100644
--- a/patches/unapplied/server/1039-Optimise-collision-checking-in-player-move-packet-ha.patch
+++ b/patches/server/1053-Optimise-collision-checking-in-player-move-packet-ha.patch
@@ -6,10 +6,10 @@ Subject: [PATCH] Optimise collision checking in player move packet handling
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d6aeb69a0 100644
+index eef96e946b80064fe211039a65db4192ea7a52d3..c4b016a2fb5c79fb3f191e243712bee7cbe5cd2c 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-@@ -572,7 +572,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -577,7 +577,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
return;
}
@@ -18,7 +18,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
-@@ -588,6 +588,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -593,6 +593,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
@@ -26,7 +26,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
double d11 = d7;
d6 = d3 - entity.getX();
-@@ -601,15 +602,23 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -606,15 +607,23 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
boolean flag2 = false;
if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
@@ -53,7 +53,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
entity.absMoveTo(d0, d1, d2, f, f1);
this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
this.send(new ClientboundMoveVehiclePacket(entity));
-@@ -691,7 +700,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -697,7 +706,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
private boolean noBlocksAround(Entity entity) {
@@ -87,7 +87,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
}
@Override
-@@ -1386,7 +1420,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1398,7 +1432,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
}
@@ -96,7 +96,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
-@@ -1428,6 +1462,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1440,6 +1474,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
@@ -104,7 +104,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
// Paper start - prevent position desync
if (this.awaitingPositionFromClient != null) {
return; // ... thanks Mojang for letting move calls teleport across dimensions.
-@@ -1458,7 +1493,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1470,7 +1505,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
// Paper start - Add fail move event
@@ -123,7 +123,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
if (teleportBack) {
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
toX, toY, toZ, toYaw, toPitch, false);
-@@ -1569,7 +1614,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1594,7 +1639,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private boolean updateAwaitingTeleport() {
if (this.awaitingPositionFromClient != null) {
@@ -132,7 +132,7 @@ index 62d5ca25104e10ca16c2005ef9272bf8329ce145..f93edc8a6ed7c51ec6e9335f66ab146d
this.awaitingTeleportTime = this.tickCount;
this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
}
-@@ -1582,6 +1627,33 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1607,6 +1652,33 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
}
diff --git a/patches/unapplied/server/1028-Write-SavedData-IO-async.patch b/patches/unapplied/server/1028-Write-SavedData-IO-async.patch
deleted file mode 100644
index cceb676e45..0000000000
--- a/patches/unapplied/server/1028-Write-SavedData-IO-async.patch
+++ /dev/null
@@ -1,164 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Cryptite <[email protected]>
-Date: Tue, 27 Jun 2023 11:35:52 -0500
-Subject: [PATCH] Write SavedData IO async
-
-Co-Authored-By: Shane Freeder <[email protected]>
-
-diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-index 4a5dc7fd4eb1a7ab1ec371f0f107de882f88149c..dcb5651d1d9b10b40430fb2f713beedf68336704 100644
---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -369,6 +369,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
-
- public void close(boolean save) throws IOException {
- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.close(save, true); // Paper - rewrite chunk system
-+ // Paper start - Write SavedData IO async
-+ try {
-+ this.dataStorage.close();
-+ } catch (final IOException e) {
-+ LOGGER.error("Failed to close persistent world data", e);
-+ }
-+ // Paper end - Write SavedData IO async
- }
-
- // CraftBukkit start - modelled on below
-diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index c5698b05cc3ea4cb1bc6789c30f2aab76748d491..2931e1dd0c8ae5ac1c9ec42f90dd5ab57595bf60 100644
---- a/src/main/java/net/minecraft/server/level/ServerLevel.java
-+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -1330,7 +1330,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
- progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel"));
- }
-
-- this.saveLevelData();
-+ this.saveLevelData(!close); // Paper - Write SavedData IO async
- if (progressListener != null) {
- progressListener.progressStage(Component.translatable("menu.savingChunks"));
- }
-@@ -1361,12 +1361,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
- // CraftBukkit end
- }
-
-- private void saveLevelData() {
-+ private void saveLevelData(boolean async) { // Paper - Write SavedData IO async
- if (this.dragonFight != null) {
- this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit
- }
-
-- this.getChunkSource().getDataStorage().save();
-+ this.getChunkSource().getDataStorage().save(async); // Paper - Write SavedData IO async
- }
-
- public <T extends Entity> List<? extends T> getEntities(EntityTypeTest<Entity, T> filter, Predicate<? super T> predicate) {
-diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
-index 0382b6597a130d746f8954a93a756a9d1ac81d50..cb39c629af1827078f35904a373d35a63fea17ff 100644
---- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
-+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
-@@ -116,7 +116,13 @@ public class WorldUpgrader {
- (new WorldUpgrader.PoiUpgrader(this)).upgrade();
- WorldUpgrader.LOGGER.info("Upgrading blocks");
- (new WorldUpgrader.ChunkUpgrader()).upgrade();
-- this.overworldDataStorage.save();
-+ // Paper start - Write SavedData IO async
-+ try {
-+ this.overworldDataStorage.close();
-+ } catch (final IOException e) {
-+ LOGGER.error("Failed to close persistent world data", e);
-+ }
-+ // Paper end - Write SavedData IO async
- i = Util.getMillis() - i;
- WorldUpgrader.LOGGER.info("World optimizaton finished after {} seconds", i / 1000L);
- this.finished = true;
-diff --git a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
-index 9cc3850bb70dfbcf342651360314a19fd9ea3ecc..4cbb943b702baaeb8bfd2b558cc848e719cf095d 100644
---- a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
-+++ b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
-@@ -30,20 +30,36 @@ public abstract class SavedData {
- return this.dirty;
- }
-
-+ // Paper start - Write SavedData IO async - joining is evil, but we assume the old blocking behavior here just for safety
-+ @io.papermc.paper.annotation.DoNotUse
- public void save(File file, HolderLookup.Provider registryLookup) {
-+ save(file, registryLookup, null).join();
-+ }
-+
-+ public java.util.concurrent.CompletableFuture<Void> save(File file, HolderLookup.Provider registryLookup, @org.jetbrains.annotations.Nullable java.util.concurrent.ExecutorService ioExecutor) {
-+ // Paper end - Write SavedData IO async
- if (this.isDirty()) {
- CompoundTag compoundTag = new CompoundTag();
- compoundTag.put("data", this.save(new CompoundTag(), registryLookup));
- NbtUtils.addCurrentDataVersion(compoundTag);
-
-+ Runnable writeRunnable = () -> { // Paper - Write SavedData IO async
- try {
- NbtIo.writeCompressed(compoundTag, file.toPath());
- } catch (IOException var5) {
- LOGGER.error("Could not save data {}", this, var5);
- }
-+ }; // Paper - Write SavedData IO async
-
- this.setDirty(false);
-+ // Paper start - Write SavedData IO async
-+ if (ioExecutor == null) {
-+ return java.util.concurrent.CompletableFuture.runAsync(writeRunnable); // No executor, just use common pool
-+ }
-+ return java.util.concurrent.CompletableFuture.runAsync(writeRunnable, ioExecutor);
- }
-+ return java.util.concurrent.CompletableFuture.completedFuture(null);
-+ // Paper end - Write SavedData IO async
- }
-
- public static record Factory<T extends SavedData>(
-diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
-index 7d98d2911e9d6ec429ce7df1f1f2650c7ea32325..6e23e69abd56eeda3b52a22019e1b74ae10682e7 100644
---- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
-+++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
-@@ -23,17 +23,19 @@ import net.minecraft.util.datafix.DataFixTypes;
- import net.minecraft.world.level.saveddata.SavedData;
- import org.slf4j.Logger;
-
--public class DimensionDataStorage {
-+public class DimensionDataStorage implements java.io.Closeable { // Paper - Write SavedData IO async
- private static final Logger LOGGER = LogUtils.getLogger();
- public final Map<String, SavedData> cache = Maps.newHashMap();
- private final DataFixer fixerUpper;
- private final HolderLookup.Provider registries;
- private final File dataFolder;
-+ protected final java.util.concurrent.ExecutorService ioExecutor; // Paper - Write SavedData IO async
-
- public DimensionDataStorage(File directory, DataFixer dataFixer, HolderLookup.Provider registryLookup) {
- this.fixerUpper = dataFixer;
- this.dataFolder = directory;
- this.registries = registryLookup;
-+ this.ioExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("DimensionDataIO - " + dataFolder.getParent() + " - %d").setDaemon(true).build()); // Paper - Write SavedData IO async
- }
-
- private File getDataFile(String id) {
-@@ -123,10 +125,23 @@ public class DimensionDataStorage {
- return bl;
- }
-
-- public void save() {
-+ // Paper start - Write SavedData IO async
-+ @Override
-+ public void close() throws IOException {
-+ save(false);
-+ this.ioExecutor.shutdown();
-+ }
-+ // Paper end - Write SavedData IO async
-+
-+ public void save(boolean async) { // Paper - Write SavedData IO async
- this.cache.forEach((id, state) -> {
- if (state != null) {
-- state.save(this.getDataFile(id), this.registries);
-+ // Paper start - Write SavedData IO async
-+ final java.util.concurrent.CompletableFuture<Void> save = state.save(this.getDataFile(id), this.registries, this.ioExecutor);
-+ if (!async) {
-+ save.join();
-+ }
-+ // Paper end - Write SavedData IO async
- }
- });
- }