Skip to content

Commit 7ab6d19

Browse files
committed
Version 1.1: also cancel attribute updates
1 parent cd059f5 commit 7ab6d19

File tree

7 files changed

+82
-5
lines changed

7 files changed

+82
-5
lines changed

.idea/gradle.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Doing this fix should make hit slowdown **less latency** dependant.
2626

2727
**Warning:** This plugin will make hit slowdown happen completely different to most servers (To compare: minemen.club has fixed this issue partly by not doing setSprinting(false) internally, it still has the other issue, of when the client sends START_SPRINTING / STOP_SPRINTING)
2828

29+
## Attribute
30+
Since version 1.1 BetterSlowdown also cancels "useless" attribute packets which apply / remove the sprint modifier, this is handled client side and the server should not try to override this.
31+
2932
## Dependencies
3033

3134
This plugin uses, and depends on [PacketEvents](https://github.com/retrooper/packetevents)
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package me.beanes.betterslowdown;
22

33
import com.github.retrooper.packetevents.PacketEvents;
4+
import com.github.retrooper.packetevents.event.PacketListenerCommon;
45
import com.github.retrooper.packetevents.event.PacketListenerPriority;
56
import me.beanes.betterslowdown.listener.FilterListener;
67
import org.bukkit.plugin.java.JavaPlugin;
78

89
public class BetterSlowdown extends JavaPlugin {
910
private FallbackMode mode = FallbackMode.SPRINT;
11+
private boolean alwaysAddSprint = false;
12+
private PacketListenerCommon listener;
1013

1114
public FallbackMode getMode() {
1215
return mode;
1316
}
1417

18+
public boolean isAlwaysAddSprint() {
19+
return alwaysAddSprint;
20+
}
21+
1522
@Override
1623
public void onLoad() {
17-
PacketEvents.getAPI().getEventManager().registerListener(new FilterListener(this), PacketListenerPriority.LOWEST);
24+
listener = PacketEvents.getAPI().getEventManager().registerListener(new FilterListener(this), PacketListenerPriority.LOWEST);
1825
}
1926

2027
@Override
@@ -23,11 +30,18 @@ public void onEnable() {
2330

2431
try {
2532
mode = FallbackMode.valueOf(getConfig().getString("mode").toUpperCase());
33+
alwaysAddSprint = getConfig().getBoolean("always-add-sprint");
2634
} catch (Exception ex) {
2735
mode = FallbackMode.SERVER;
2836
getLogger().info("Failed to load config due to error");
2937
}
3038

3139
getLogger().info("Slowdown fallback mode is set to " + mode);
40+
getLogger().info("Always add sprint is set to " + alwaysAddSprint);
41+
}
42+
43+
@Override
44+
public void onDisable() {
45+
PacketEvents.getAPI().getEventManager().unregisterListener(listener);
3246
}
3347
}

src/main/java/me/beanes/betterslowdown/listener/FilterListener.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,26 @@
77
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
88
import com.github.retrooper.packetevents.protocol.player.User;
99
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
10+
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
1011
import me.beanes.betterslowdown.BetterSlowdown;
1112
import me.beanes.betterslowdown.FallbackMode;
1213

1314
import java.util.HashMap;
1415
import java.util.Iterator;
1516
import java.util.Map;
17+
import java.util.UUID;
1618

1719
public class FilterListener implements PacketListener {
20+
private static final UUID SPRINT_MODIFIER_UUID = UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D");
21+
private static final WrapperPlayServerUpdateAttributes.PropertyModifier SPRINT_MODIFIER = new WrapperPlayServerUpdateAttributes.PropertyModifier(SPRINT_MODIFIER_UUID, 0.30000001192092896D, WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_TOTAL);
1822
private final BetterSlowdown plugin;
1923
private final ThreadLocal<Map<User, Byte>> lastUsefulBitmaskThreadLocal;
24+
private final ThreadLocal<Map<User, Double>> lastSpeedThreadLocal;
2025

2126
public FilterListener(BetterSlowdown plugin) {
2227
this.plugin = plugin;
2328
this.lastUsefulBitmaskThreadLocal = ThreadLocal.withInitial(HashMap::new);
29+
this.lastSpeedThreadLocal = ThreadLocal.withInitial(HashMap::new);
2430
}
2531

2632

@@ -53,7 +59,7 @@ public void onPacketSend(PacketSendEvent event) {
5359

5460
if (plugin.getMode() != FallbackMode.SERVER) {
5561
if (plugin.getMode() == FallbackMode.SPRINT) {
56-
data.setValue((byte) ((byte) data.getValue() | 0x08)); // Rewrite with sprinting=true
62+
data.setValue((byte) ((byte) data.getValue() | 0x08)); // Rewrite with sprinting = true
5763
} else if (plugin.getMode() == FallbackMode.NO_SPRINT) {
5864
data.setValue((byte) ((byte) data.getValue() & ~0x08)); // Rewrite with sprinting = false
5965
}
@@ -75,11 +81,53 @@ public void onPacketSend(PacketSendEvent event) {
7581
}
7682
}
7783
}
84+
} else if (event.getPacketType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) {
85+
WrapperPlayServerUpdateAttributes wrapper = new WrapperPlayServerUpdateAttributes(event);
86+
User user = event.getUser();
87+
88+
if (wrapper.getEntityId() == user.getEntityId()) {
89+
for (WrapperPlayServerUpdateAttributes.Property snapshot : wrapper.getProperties()) {
90+
if (snapshot.getAttribute().getName().getKey().equals("movement_speed")) {
91+
// Calculate the movement speed without sprint
92+
boolean exists = snapshot.getModifiers().removeIf(modifier -> modifier.getUUID().equals(SPRINT_MODIFIER_UUID));
93+
if (exists) {
94+
snapshot.setDirty();
95+
}
96+
97+
double speed = snapshot.calcValue();
98+
99+
Map<User, Double> lastSpeed = lastSpeedThreadLocal.get();
100+
101+
if (lastSpeed.getOrDefault(user, -1.0D) == speed) {
102+
// Cancel this attribute packet as it only changes the sprint attribute
103+
event.setCancelled(true);
104+
} else {
105+
// Update the speed
106+
lastSpeed.put(user, speed);
107+
108+
if (exists) {
109+
snapshot.addModifier(SPRINT_MODIFIER); // Re-add the modifier if packetevents is on default re-encode
110+
} else if (plugin.isAlwaysAddSprint()) {
111+
// TODO: check if the player is "allowed" to sprint, keep food value, and check START_SPRINTING and STOP_SPRINTING to prevent omnisprint?
112+
snapshot.addModifier(SPRINT_MODIFIER);
113+
event.markForReEncode(true);
114+
}
115+
}
116+
}
117+
}
118+
}
119+
} else if (event.getPacketType() == PacketType.Play.Server.RESPAWN) {
120+
User user = event.getUser();
121+
122+
// Reset last as the entity is recreated
123+
this.lastUsefulBitmaskThreadLocal.get().remove(user);
124+
this.lastSpeedThreadLocal.get().remove(user);
78125
}
79126
}
80127

81128
@Override
82129
public void onUserDisconnect(UserDisconnectEvent event) {
83130
this.lastUsefulBitmaskThreadLocal.get().remove(event.getUser());
131+
this.lastSpeedThreadLocal.get().remove(event.getUser());
84132
}
85133
}

src/main/resources/config.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,9 @@
1414
# SERVER - this mode will just use the server sent value
1515
# SPRINT - always set sprinting true, causes the client to force the hit slowdown (if the client hit) for a single tick when it receives the updated metadata
1616
# NO_SPRINT - always set sprinting false, causes the client to not do the hit slowdown (if the client hit) even when its sprinting when it receives the updated metadata
17-
mode: NO_SPRINT
17+
mode: SPRINT
18+
19+
# Should the server always apply the sprint attribute when attributes are being overridden by server (and the plugin can't cancel it due to speed change)
20+
# This is useful for HCF servers when you get speed 3 / speed 2, and your sprint suddenly disappears
21+
# This is still in beta as this can cause the player to sprint while not having the food for it and it can cause omnisprint
22+
always-add-sprint: false

src/main/resources/plugin.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: BetterSlowdown
2-
version: '${version}'
2+
version: 1.1
33
main: me.beanes.betterslowdown.BetterSlowdown
44
author: Beanes
55
description: Fixes server/network issues related to hit slowdown
66
depend:
7-
- packetevents
7+
- packetevents

0 commit comments

Comments
 (0)