2023-09-24 07:10:40 +02:00
|
|
|
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
|
|
|
|
|
2024-11-09 21:44:55 +01:00
|
|
|
Feature patch
|
|
|
|
|
2023-09-24 07:10:40 +02:00
|
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
2024-11-29 17:07:35 +01:00
|
|
|
index be6e64d5c858961b19eb7b1b028530c1eb4c68d7..11a0bf52d891d79e3520de91d270b876871510f7 100644
|
2023-09-24 07:10:40 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
2024-10-27 18:11:15 +01:00
|
|
|
@@ -331,6 +331,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
2024-01-23 12:06:27 +01:00
|
|
|
|
2023-09-24 07:10:40 +02:00
|
|
|
public volatile Thread shutdownThread; // Paper
|
|
|
|
public volatile boolean abnormalExit = false; // Paper
|
2024-01-23 12:06:27 +01:00
|
|
|
+ public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation
|
2023-09-24 07:10:40 +02:00
|
|
|
|
|
|
|
public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) {
|
|
|
|
AtomicReference<S> atomicreference = new AtomicReference();
|
2024-10-31 22:30:18 +01:00
|
|
|
@@ -1841,6 +1842,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
2024-02-01 10:15:57 +01:00
|
|
|
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
2024-01-19 22:13:42 +01:00
|
|
|
worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
2024-02-01 10:15:57 +01:00
|
|
|
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
|
|
|
|
|
2024-10-27 10:26:44 +01:00
|
|
|
gameprofilerfiller.push(() -> {
|
2024-04-25 14:23:55 +02:00
|
|
|
String s = String.valueOf(worldserver);
|
2023-09-24 07:10:40 +02:00
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
2024-11-29 02:39:40 +01:00
|
|
|
index dc523c3017939d4a206f28617e5aacd83e5d2334..5979e8d25eaddf990ded79bcf6485cc0612faa63 100644
|
2023-09-24 07:10:40 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
|
|
|
@@ -582,6 +582,17 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
2024-10-27 10:26:44 +01:00
|
|
|
);
|
2023-09-24 07:10:40 +02:00
|
|
|
}
|
2024-10-27 10:26:44 +01:00
|
|
|
// Paper end - chunk tick iteration
|
2023-09-24 07:10:40 +02:00
|
|
|
+ // 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
|
2024-10-27 10:26:44 +01:00
|
|
|
index 504c996220b278c194c93e001a3b326d549868ec..a96f859a5d0c6ec692d4627a69f3c9ee49199dbc 100644
|
2023-09-24 07:10:40 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
2024-10-27 10:26:44 +01:00
|
|
|
@@ -127,7 +127,7 @@ public class ServerPlayerGameMode {
|
2023-09-24 07:10:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2024-11-18 21:09:44 +01:00
|
|
|
index 59c992173fda6153c58722caae061b0e6bee86a1..6a3a8f0466998409a01223bc0c16d92b96e50118 100644
|
2023-09-24 07:10:40 +02:00
|
|
|
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
2024-11-04 18:42:38 +01:00
|
|
|
@@ -4051,6 +4051,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
2024-04-25 21:40:53 +02:00
|
|
|
this.resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer);
|
2023-09-24 07:10:40 +02:00
|
|
|
}
|
2024-01-15 12:38:39 +01:00
|
|
|
// Paper end - Properly cancel usable items
|
2023-09-24 07:10:40 +02:00
|
|
|
+ // 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)) {
|
2024-11-04 18:42:38 +01:00
|
|
|
@@ -4065,7 +4069,12 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
2023-09-24 07:10:40 +02:00
|
|
|
|
2024-10-27 10:26:44 +01:00
|
|
|
protected void updateUsingItem(ItemStack stack) {
|
|
|
|
stack.onUseTick(this.level(), this, this.getUseItemRemainingTicks());
|
2023-09-24 07:10:40 +02:00
|
|
|
- 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
|
2024-10-27 10:26:44 +01:00
|
|
|
+ final boolean shouldLagCompensate = this.useItem.has(DataComponents.FOOD) && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1L + this.totalEatTimeTicks) * 50L * (1000L * 1000L));
|
2023-09-24 07:10:40 +02:00
|
|
|
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide && !stack.useOnRelease()) {
|
|
|
|
+ this.useItemRemaining = 0;
|
2024-01-13 18:34:33 +01:00
|
|
|
+ // Paper end - lag compensate eating
|
2023-09-24 07:10:40 +02:00
|
|
|
this.completeUsingItem();
|
|
|
|
}
|
|
|
|
|
2024-11-04 18:42:38 +01:00
|
|
|
@@ -4103,7 +4112,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
2023-09-24 07:10:40 +02:00
|
|
|
|
2024-01-21 12:53:04 +01:00
|
|
|
if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper - Prevent consuming the wrong itemstack
|
2023-09-24 07:10:40 +02:00
|
|
|
this.useItem = itemstack;
|
2024-07-11 21:22:59 +02:00
|
|
|
- this.useItemRemaining = itemstack.getUseDuration(this);
|
2023-09-24 07:10:40 +02:00
|
|
|
+ // Paper start - lag compensate eating
|
2024-07-11 21:22:59 +02:00
|
|
|
+ this.useItemRemaining = this.totalEatTimeTicks = itemstack.getUseDuration(this);
|
2023-09-24 07:10:40 +02:00
|
|
|
+ this.eatStartTime = System.nanoTime();
|
2024-01-13 18:34:33 +01:00
|
|
|
+ // Paper end - lag compensate eating
|
2023-09-24 07:10:40 +02:00
|
|
|
if (!this.level().isClientSide) {
|
|
|
|
this.setLivingEntityFlag(1, true);
|
|
|
|
this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND);
|
2024-11-04 18:42:38 +01:00
|
|
|
@@ -4128,7 +4140,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
2023-09-24 07:10:40 +02:00
|
|
|
}
|
|
|
|
} 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;
|
2024-01-13 18:34:33 +01:00
|
|
|
+ // Paper end - lag compensate eating
|
2023-09-24 07:10:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-04 18:42:38 +01:00
|
|
|
@@ -4259,7 +4274,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
2023-09-24 07:10:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.useItem = ItemStack.EMPTY;
|
|
|
|
- this.useItemRemaining = 0;
|
|
|
|
+ // Paper start - lag compensate eating
|
|
|
|
+ this.useItemRemaining = this.totalEatTimeTicks = 0;
|
|
|
|
+ this.eatStartTime = -1L;
|
2024-01-13 18:34:33 +01:00
|
|
|
+ // Paper end - lag compensate eating
|
2023-09-24 07:10:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isBlocking() {
|