PaperMC/patches/server/1013-Lag-compensation-ticks.patch
Spottedleaf 1281f4f552 Make region/lock shift accessors per world
This has been done to ensure that the shifts are not used
until the world object is being constructed, which is before
the global configuration is initialised. There also isn't any
reason for these shifts to be global anyways.
2023-12-30 15:45:24 -08:00

131 lines
7.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 23 Sep 2023 22:05:35 -0700
Subject: [PATCH] Lag compensation ticks
Areas affected by lag comepnsation:
- Block breaking and destroying
- Eating food items
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index a8f9f4e23575cb58045f9d8efe011a60a51dbd7a..34f19ac897a30c0c4e3ab406013fcca1c8b7db93 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -311,6 +311,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public volatile Thread shutdownThread; // Paper
public volatile boolean abnormalExit = false; // Paper
public boolean isIteratingOverLevels = false; // Paper
+ // Paper start - lag compensation
+ public static final long SERVER_INIT = System.nanoTime();
+ // Paper end - lag compensation
public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) {
AtomicReference<S> atomicreference = new AtomicReference();
@@ -1691,6 +1694,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
Iterator iterator = this.getAllLevels().iterator(); // Paper - move down
while (iterator.hasNext()) {
ServerLevel worldserver = (ServerLevel) iterator.next();
+ worldserver.updateLagCompensationTick(); // Paper - lag compensation
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index c17d8e00cd43f2f969c81be2ee65fab2b8578eae..15dc5af10041f71b5d377353302fb09a34bcda82 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -571,6 +571,17 @@ public class ServerLevel extends Level implements WorldGenLevel {
return player != null && player.level() == this ? player : null;
}
// Paper end
+ // Paper start - lag compensation
+ private long lagCompensationTick = net.minecraft.server.MinecraftServer.SERVER_INIT;
+
+ public long getLagCompensationTick() {
+ return this.lagCompensationTick;
+ }
+
+ public void updateLagCompensationTick() {
+ this.lagCompensationTick = (System.nanoTime() - net.minecraft.server.MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L));
+ }
+ // Paper end - lag compensation
// 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 899439e0af639e8d9124522b3cb6a10601b17fe2..b214c934b9a537f52cef142c519c2b9b55a89ae3 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -124,7 +124,7 @@ public class ServerPlayerGameMode {
}
public void tick() {
- this.gameTicks = MinecraftServer.currentTick; // CraftBukkit;
+ this.gameTicks = (int)this.level.getLagCompensationTick(); // CraftBukkit; // Paper - lag compensation
BlockState iblockdata;
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 3ce5c06a6c154c0b8c9f2aaaa0a2f9d092cc4551..12d4ab6aa349e3f465cc88a2717243ff5064df02 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3818,6 +3818,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.getEntityData().resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer);
}
// Paper end
+ // Paper start - lag compensate eating
+ protected long eatStartTime;
+ protected int totalEatTimeTicks;
+ // Paper end - lag compensate eating
private void updatingUsingItem() {
if (this.isUsingItem()) {
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
@@ -3836,7 +3840,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.triggerItemUseEffects(stack, 5);
}
- 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.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000));
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide && !stack.useOnRelease()) {
+ this.useItemRemaining = 0;
+ // Paper end
this.completeUsingItem();
}
@@ -3884,7 +3893,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag
this.useItem = itemstack;
- this.useItemRemaining = itemstack.getUseDuration();
+ // Paper start - lag compensate eating
+ this.useItemRemaining = this.totalEatTimeTicks = itemstack.getUseDuration();
+ this.eatStartTime = System.nanoTime();
+ // Paper end
if (!this.level().isClientSide) {
this.setLivingEntityFlag(1, true);
this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND);
@@ -3909,7 +3921,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
} else if (!this.isUsingItem() && !this.useItem.isEmpty()) {
this.useItem = ItemStack.EMPTY;
- this.useItemRemaining = 0;
+ // Paper start - lag compensate eating
+ this.useItemRemaining = this.totalEatTimeTicks = 0;
+ this.eatStartTime = -1L;
+ // Paper end
}
}
@@ -4044,7 +4059,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
this.useItem = ItemStack.EMPTY;
- this.useItemRemaining = 0;
+ // Paper start - lag compensate eating
+ this.useItemRemaining = this.totalEatTimeTicks = 0;
+ this.eatStartTime = -1L;
+ // Paper end
}
public boolean isBlocking() {