aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/1057-Remove-wall-time-unused-skip-tick-protection.patch
blob: e2d5d9dcabe69eefb2231850a16b82f5b4c8ec24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bjarne Koll <lynxplay101@gmail.com>
Date: Mon, 16 Sep 2024 23:07:29 +0200
Subject: [PATCH] Remove wall-time / unused skip tick protection

Spigot still maintains some partial implementation of "tick skipping", a
practice in which the MinecraftServer.currentTick field is updated not
by an increment of one per actual tick, but instead set to
System.currentTimeMillis() / 50. This behaviour means that the tracked
tick may "skip" a tick value in case a previous tick took more than the
expected 50ms.

To compensate for this in important paths, spigot/craftbukkit
implements "wall-time". Instead of incrementing/decrementing ticks on
block entities/entities by one for each call to their tick() method,
they instead increment/decrement important values, like
an ItemEntity's age or pickupDelay, by the difference of
`currentTick - lastTick`, where `lastTick` is the value of
`currentTick` during the last tick() call.

These "fixes" however do not play nicely with minecraft's simulation
distance as entities/block entities implementing the above behaviour
would "catch up" their values when moving from a non-ticking chunk to a
ticking one as their `lastTick` value remains stuck on the last tick in
a ticking chunk and hence lead to a large "catch up" once ticked again.

Paper completely removes the "tick skipping" behaviour (See patch
"Further-improve-server-tick-loop"), making the above precautions
completely unnecessary, which also rids paper of the previous described
incompatibility with non-ticking chunks.

diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
index 03cfa29bdb426a9fb6b1b6be6e897da48d4f2f3e..4423973d4d9a2c3879d98d1d4c8b8c117c677ac5 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
@@ -60,7 +60,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
     @Nullable
     public UUID target;
     public final float bobOffs;
-    private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit
+    // private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
     public boolean canMobPickup = true; // Paper - Item#canEntityPickup
     private int despawnRate = -1; // Paper - Alternative item-despawn-rate
     public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
@@ -153,12 +153,11 @@ public class ItemEntity extends Entity implements TraceableEntity {
             this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
         } else {
             super.tick();
-            // CraftBukkit start - Use wall time for pickup and despawn timers
-            int elapsedTicks = MinecraftServer.currentTick - this.lastTick;
-            if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks;
-            if (this.age != -32768) this.age += elapsedTicks;
-            this.lastTick = MinecraftServer.currentTick;
-            // CraftBukkit end
+            // Paper start - remove anti tick skipping measures / wall time - revert to vanilla
+            if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
+                --this.pickupDelay;
+            }
+            // Paper end - remove anti tick skipping measures / wall time - revert to vanilla
 
             this.xo = this.getX();
             this.yo = this.getY();
@@ -211,7 +210,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
                 this.mergeWithNeighbours();
             }
 
-            /* CraftBukkit start - moved up
+            // Paper - remove anti tick skipping measures / wall time - revert to vanilla /* CraftBukkit start - moved up
             if (this.age != -32768) {
                 ++this.age;
             }
@@ -242,12 +241,14 @@ public class ItemEntity extends Entity implements TraceableEntity {
     // Spigot start - copied from above
     @Override
     public void inactiveTick() {
-        // CraftBukkit start - Use wall time for pickup and despawn timers
-        int elapsedTicks = MinecraftServer.currentTick - this.lastTick;
-        if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks;
-        if (this.age != -32768) this.age += elapsedTicks;
-        this.lastTick = MinecraftServer.currentTick;
-        // CraftBukkit end
+        // Paper start - remove anti tick skipping measures / wall time - copied from above
+        if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
+            --this.pickupDelay;
+        }
+        if (this.age != -32768) {
+            ++this.age;
+        }
+        // Paper end - remove anti tick skipping measures / wall time - copied from above
 
         if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate
             // CraftBukkit start - fire ItemDespawnEvent
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index 2280004638fd19ed018cb3e77d53a018b34ec516..2b43337ac63d051718a2074fcc46e128a1d65129 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -96,7 +96,7 @@ public class Zombie extends Monster {
     private boolean canBreakDoors;
     private int inWaterTime;
     public int conversionTime;
-    private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field
+    // private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field // Paper - remove anti tick skipping measures / wall time
     private boolean shouldBurnInDay = true; // Paper - Add more Zombie API
 
     public Zombie(EntityType<? extends Zombie> type, Level world) {
@@ -219,10 +219,7 @@ public class Zombie extends Monster {
     public void tick() {
         if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) {
             if (this.isUnderWaterConverting()) {
-                // CraftBukkit start - Use wall time instead of ticks for conversion
-                int elapsedTicks = MinecraftServer.currentTick - this.lastTick;
-                this.conversionTime -= elapsedTicks;
-                // CraftBukkit end
+                --this.conversionTime; // Paper - remove anti tick skipping measures / wall time
                 if (this.conversionTime < 0) {
                     this.doUnderWaterConversion();
                 }
@@ -239,7 +236,7 @@ public class Zombie extends Monster {
         }
 
         super.tick();
-        this.lastTick = MinecraftServer.currentTick; // CraftBukkit
+        // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
     }
 
     @Override
@@ -280,7 +277,7 @@ public class Zombie extends Monster {
     }
     // Paper end - Add more Zombie API
     public void startUnderWaterConversion(int ticksUntilWaterConversion) {
-        this.lastTick = MinecraftServer.currentTick; // CraftBukkit
+        // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
         this.conversionTime = ticksUntilWaterConversion;
         this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true);
     }
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
index a2fafef89d5354e2cb02f5672810909950a57777..bf2c303a314205590a2839e0f729af3a9ff40a86 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
@@ -54,7 +54,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
     public int fuel;
     protected final ContainerData dataAccess;
     // CraftBukkit start - add fields and methods
-    private int lastTick = MinecraftServer.currentTick;
+    // private int lastTick = MinecraftServer.currentTick; // Paper - remove anti tick skipping measures / wall time
     public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
     private int maxStack = MAX_STACK;
 
@@ -169,12 +169,10 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
         boolean flag1 = blockEntity.brewTime > 0;
         ItemStack itemstack1 = (ItemStack) blockEntity.items.get(3);
 
-        // CraftBukkit start - Use wall time instead of ticks for brewing
-        int elapsedTicks = MinecraftServer.currentTick - blockEntity.lastTick;
-        blockEntity.lastTick = MinecraftServer.currentTick;
+        // Paper - remove anti tick skipping measures / wall time
 
         if (flag1) {
-            blockEntity.brewTime -= elapsedTicks;
+            --blockEntity.brewTime; // Paper - remove anti tick skipping measures / wall time - revert to vanilla
             boolean flag2 = blockEntity.brewTime <= 0; // == -> <=
             // CraftBukkit end