77
88import meteordevelopment .meteorclient .events .game .OpenScreenEvent ;
99import meteordevelopment .meteorclient .events .packets .PacketEvent ;
10+ import meteordevelopment .meteorclient .events .world .TickEvent ;
1011import meteordevelopment .meteorclient .mixin .AbstractSignEditScreenAccessor ;
12+ import meteordevelopment .meteorclient .settings .IntSetting ;
13+ import meteordevelopment .meteorclient .settings .Setting ;
14+ import meteordevelopment .meteorclient .settings .SettingGroup ;
1115import meteordevelopment .meteorclient .systems .modules .Categories ;
1216import meteordevelopment .meteorclient .systems .modules .Module ;
1317import meteordevelopment .orbit .EventHandler ;
1418import net .minecraft .block .entity .SignBlockEntity ;
1519import net .minecraft .client .gui .screen .ingame .AbstractSignEditScreen ;
1620import net .minecraft .network .packet .c2s .play .UpdateSignC2SPacket ;
1721
22+ import java .util .ArrayDeque ;
23+ import java .util .Queue ;
24+
1825public class AutoSign extends Module {
26+ private final SettingGroup sgGeneral = settings .getDefaultGroup ();
27+
28+ private final Setting <Integer > delay = sgGeneral .add (new IntSetting .Builder ()
29+ .name ("delay" )
30+ .description ("The tick delay between sign update packets." )
31+ .defaultValue (10 )
32+ .range (0 , 100 )
33+ .sliderRange (0 , 100 )
34+ .build ()
35+ );
36+
1937 private String [] text ;
2038
39+ // Some servers (e.g., 2b2t) don't like the sign packet being sent too soon after the swing or block click packets, so queue them.
40+ // Delaying by sleeping in the event handler may be fine for a single sign, but would visibly lag the UI at a larger scale.
41+ private final Queue <UpdateSignC2SPacket > queue = new ArrayDeque <>();
42+ private int timer = 0 ;
43+
2144 public AutoSign () {
2245 super (Categories .World , "auto-sign" , "Automatically writes signs. The first sign's text will be used." );
2346 }
@@ -27,6 +50,26 @@ public void onDeactivate() {
2750 text = null ;
2851 }
2952
53+ @ EventHandler
54+ private void onTick (TickEvent .Post event ) {
55+ // Adding a new packet with the timer close to the threshold could lead to it being sent too fast relative to
56+ // the swing/click packets, but only if there isn't another packet ahead of it to reset the timer, so always
57+ // keep it reset if the queue is empty.
58+ if (mc .player == null || queue .peek () == null ) {
59+ timer = 0 ;
60+ return ;
61+ }
62+
63+ if (timer < delay .get ()) {
64+ timer ++;
65+ return ;
66+ }
67+
68+ mc .player .networkHandler .sendPacket (queue .poll ());
69+
70+ timer = 0 ;
71+ }
72+
3073 @ EventHandler
3174 private void onSendPacket (PacketEvent .Send event ) {
3275 if (!(event .packet instanceof UpdateSignC2SPacket )) return ;
@@ -40,7 +83,7 @@ private void onOpenScreen(OpenScreenEvent event) {
4083
4184 SignBlockEntity sign = ((AbstractSignEditScreenAccessor ) event .screen ).meteor$getSign ();
4285
43- mc . player . networkHandler . sendPacket (new UpdateSignC2SPacket (sign .getPos (), true , text [0 ], text [1 ], text [2 ], text [3 ]));
86+ queue . add (new UpdateSignC2SPacket (sign .getPos (), true , text [0 ], text [1 ], text [2 ], text [3 ]));
4487
4588 event .cancel ();
4689 }
0 commit comments