More patches

This commit is contained in:
Nassim Jahnke 2024-10-27 10:26:44 +01:00
parent ba24f1b59d
commit 88aa8528c9
6 changed files with 39 additions and 209 deletions

View file

@ -83,18 +83,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- 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;
@@ -0,0 +0,0 @@ public class ServerEntity {
long i1 = this.positionCodec.encodeZ(vec3d);
boolean flag6 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L;
long k = this.positionCodec.encodeZ(vec3d);
boolean flag5 = i < -32768L || i > 32767L || j < -32768L || j > 32767L || k < -32768L || k > 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());
- 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());
@@ -0,0 +0,0 @@ public class ServerEntity {
}

View file

@ -21,28 +21,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
--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 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos);
}

View file

@ -25,16 +25,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
return this.entityTickingChunks;
@@ -0,0 +0,0 @@ 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;
+
@ -78,13 +78,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (this.isUsingItem()) {
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.triggerItemUseEffects(stack, 5);
}
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

View file

@ -889,7 +889,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..00000000000000000000000000000000
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 0000000000000000000000000000000000000000..00000000000000000000000000000000
- 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();
@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> im
int radius,
RandomSource random
) {
@ -990,7 +990,7 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorag
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
@@ -0,0 +0,0 @@ public abstract class SectionStorage<R> implements AutoCloseable, ca.spottedleaf
@@ -0,0 +0,0 @@ public class SectionStorage<R, P> implements AutoCloseable, ca.spottedleaf.moonr
}
@Nullable

View file

@ -1,164 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Tue, 27 Jun 2023 11:35:52 -0500
Subject: [PATCH] Write SavedData IO async
Co-Authored-By: Shane Freeder <theboyetronic@gmail.com>
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ 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"));
}
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
+++ b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
+++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
@@ -0,0 +0,0 @@ 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) {
@@ -0,0 +0,0 @@ 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
}
});
}