aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0754-Lag-compensate-block-breaking.patch
blob: 985f81e2402ef2345184e803d63e3147671a283f (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
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Fri, 14 Feb 2020 22:16:34 -0800
Subject: [PATCH] Lag compensate block breaking

Use time instead of ticks if ticks fall behind

diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index cd601be6604fd81be8d58f6a46d39008fa8ecc20..cff9872882f9057ec2bfd44c15c1d66d8cefa721 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -619,4 +619,10 @@ public class PaperConfig {
             }
         }
     }
+
+    public static boolean lagCompensateBlockBreaking;
+
+    private static void lagCompensateBlockBreaking() {
+        lagCompensateBlockBreaking = getBoolean("settings.lag-compensate-block-breaking", true);
+    }
 }
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index b6eef41079120fffd63f06f681378b1b628b95e0..891199d02539fa46454cd0aa7c133637e5dc8235 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -56,14 +56,28 @@ public class ServerPlayerGameMode {
     @Nullable
     private GameType previousGameModeForPlayer;
     private boolean isDestroyingBlock;
-    private int destroyProgressStart;
+    private int destroyProgressStart; private long lastDigTime; // Paper - lag compensate block breaking
     private BlockPos destroyPos;
     private int gameTicks;
     private boolean hasDelayedDestroy;
     private BlockPos delayedDestroyPos;
-    private int delayedTickStart;
+    private int delayedTickStart; private long hasDestroyedTooFastStartTime; // Paper - lag compensate block breaking
     private int lastSentState;
 
+    // Paper start - lag compensate block breaking
+    private int getTimeDiggingLagCompensate() {
+        int lagCompensated = (int)((System.nanoTime() - this.lastDigTime) / (50L * 1000L * 1000L));
+        int tickDiff = this.gameTicks - this.destroyProgressStart;
+        return (com.destroystokyo.paper.PaperConfig.lagCompensateBlockBreaking && lagCompensated > (tickDiff + 1)) ? lagCompensated : tickDiff; // add one to ensure we don't lag compensate unless we need to
+    }
+
+    private int getTimeDiggingTooFastLagCompensate() {
+        int lagCompensated = (int)((System.nanoTime() - this.hasDestroyedTooFastStartTime) / (50L * 1000L * 1000L));
+        int tickDiff = this.gameTicks - this.delayedTickStart;
+        return (com.destroystokyo.paper.PaperConfig.lagCompensateBlockBreaking && lagCompensated > (tickDiff + 1)) ? lagCompensated : tickDiff; // add one to ensure we don't lag compensate unless we need to
+    }
+    // Paper end
+
     public ServerPlayerGameMode(ServerPlayer player) {
         this.gameModeForPlayer = GameType.DEFAULT_MODE;
         this.destroyPos = BlockPos.ZERO;
@@ -130,7 +144,7 @@ public class ServerPlayerGameMode {
             if (iblockdata == null || iblockdata.isAir()) { // Paper
                 this.hasDelayedDestroy = false;
             } else {
-                float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart);
+                float f = this.updateBlockBreakAnimation(iblockdata, this.delayedDestroyPos, this.getTimeDiggingTooFastLagCompensate()); // Paper - lag compensate destroying blocks
 
                 if (f >= 1.0F) {
                     this.hasDelayedDestroy = false;
@@ -150,7 +164,7 @@ public class ServerPlayerGameMode {
                 this.lastSentState = -1;
                 this.isDestroyingBlock = false;
             } else {
-                this.incrementDestroyProgress(iblockdata, this.destroyPos, this.destroyProgressStart);
+                this.updateBlockBreakAnimation(iblockdata, this.destroyPos, this.getTimeDiggingLagCompensate()); // Paper - lag compensate destroying
             }
         }
 
@@ -158,6 +172,12 @@ public class ServerPlayerGameMode {
 
     private float incrementDestroyProgress(BlockState state, BlockPos pos, int i) {
         int j = this.gameTicks - i;
+        // Paper start - change i (startTime) to totalTime
+        return this.updateBlockBreakAnimation(state, pos, j);
+    }
+    private float updateBlockBreakAnimation(BlockState state, BlockPos pos, int totalTime) {
+        int j = totalTime;
+        // Paper end
         float f = state.getDestroyProgress(this.player, this.player.level, pos) * (float) (j + 1);
         int k = (int) (f * 10.0F);
 
@@ -234,7 +254,7 @@ public class ServerPlayerGameMode {
                     return;
                 }
 
-                this.destroyProgressStart = this.gameTicks;
+                this.destroyProgressStart = this.gameTicks; this.lastDigTime = System.nanoTime(); // Paper - lag compensate block breaking
                 float f = 1.0F;
 
                 iblockdata1 = this.level.getBlockState(pos);
@@ -287,12 +307,12 @@ public class ServerPlayerGameMode {
                     int j = (int) (f * 10.0F);
 
                     this.level.destroyBlockProgress(this.player.getId(), pos, j);
-                    this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "actual start of destroying"));
+                    if (!com.destroystokyo.paper.PaperConfig.lagCompensateBlockBreaking) this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "actual start of destroying"));
                     this.lastSentState = j;
                 }
             } else if (action == ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK) {
                 if (pos.equals(this.destroyPos)) {
-                    int k = this.gameTicks - this.destroyProgressStart;
+                    int k = this.getTimeDiggingLagCompensate(); // Paper - lag compensate block breaking
 
                     iblockdata1 = this.level.getBlockState(pos);
                     if (!iblockdata1.isAir()) {
@@ -309,12 +329,18 @@ public class ServerPlayerGameMode {
                             this.isDestroyingBlock = false;
                             this.hasDelayedDestroy = true;
                             this.delayedDestroyPos = pos;
-                            this.delayedTickStart = this.destroyProgressStart;
+                            this.delayedTickStart = this.destroyProgressStart; this.hasDestroyedTooFastStartTime = this.lastDigTime; // Paper - lag compensate block breaking
                         }
                     }
                 }
 
+                // Paper start - this can cause clients on a lagging server to think they're not currently destroying a block
+                if (com.destroystokyo.paper.PaperConfig.lagCompensateBlockBreaking) {
+                    this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
+                } else {
                 this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying"));
+                }
+                // Paper end - this can cause clients on a lagging server to think they're not currently destroying a block
             } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) {
                 this.isDestroyingBlock = false;
                 if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) {
@@ -326,7 +352,7 @@ public class ServerPlayerGameMode {
                 }
 
                 this.level.destroyBlockProgress(this.player.getId(), pos, -1);
-                this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "aborted destroying"));
+                if (!com.destroystokyo.paper.PaperConfig.lagCompensateBlockBreaking) this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "aborted destroying")); // Paper - this can cause clients on a lagging server to think they stopped destroying a block they're currently destroying
 
                 CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit
             }
@@ -338,7 +364,13 @@ public class ServerPlayerGameMode {
 
     public void destroyAndAck(BlockPos pos, ServerboundPlayerActionPacket.Action action, String reason) {
         if (this.destroyBlock(pos)) {
+            // Paper start - this can cause clients on a lagging server to think they're not currently destroying a block
+            if (com.destroystokyo.paper.PaperConfig.lagCompensateBlockBreaking) {
+                this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos));
+            } else {
             this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, reason));
+            }
+            // Paper end - this can cause clients on a lagging server to think they're not currently destroying a block
         } else {
             this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); // CraftBukkit - SPIGOT-5196
         }