Skip to content

Commit e8b711b

Browse files
committed
Update AttributeSwap, ChatSpam, CreativeFlight, StaffMonitor, Untouchable
1 parent ebe0821 commit e8b711b

6 files changed

Lines changed: 286 additions & 35 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
### Download
1212
Pre-compiled copies are available on the [Release Page](https://github.com/cev-api/Wurst7-CevAPI/releases).
1313

14-
[![](https://i.imgur.com/OUs86yu.png)](https://github.com/cev-api/Wurst7-CevAPI/releases)
14+
[![](https://i.imgur.com/b44bIdV.png)](https://github.com/cev-api/Wurst7-CevAPI/releases)
1515

1616
I have versions for [1.21.1](https://github.com/cev-api/Wurst7-CevAPI/tree/1.21.1), [1.21.8](https://github.com/cev-api/Wurst7-CevAPI/tree/1.21.8), [1.21.10](https://github.com/cev-api/Wurst7-CevAPI/tree/1.21.10), [1.21.11](https://github.com/cev-api/Wurst7-CevAPI/tree/1.21.11), [26.1.2](https://github.com/cev-api/Wurst7-CevAPI/tree/26.1.2) but I only update and maintain the latest; [26.2.x](https://github.com/cev-api/Wurst7-CevAPI/tree/master)
1717

src/main/java/net/wurstclient/hacks/AttributeSwapHack.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public final class AttributeSwapHack extends Hack
5151

5252
private final CheckboxSetting reserveTargetSlot = new CheckboxSetting(
5353
"Reserve target slot",
54-
"Prevents you from selecting the target slot yourself. AttributeSwap can still use it temporarily.",
54+
"Prevents you from selecting the target slot yourself. If \"Only with Mace\" is on and the slot doesn't hold a mace, the reservation is lifted.",
5555
false);
5656

5757
private final CheckboxSetting swapBack = new CheckboxSetting("Swap back",
@@ -94,7 +94,9 @@ public final class AttributeSwapHack extends Hack
9494
"Only activate when MultiAura is enabled.", false);
9595

9696
private final CheckboxSetting onlyWithMace = new CheckboxSetting(
97-
"Only with Mace", "Only swap when holding a Mace.", false);
97+
"Only with Mace",
98+
"Only swap when the target slot already contains a Mace. If the slot doesn't hold a mace, AttributeSwap stays off and won't reserve the slot.",
99+
false);
98100

99101
private int backTimer;
100102
private boolean awaitingBack;
@@ -391,7 +393,21 @@ public boolean canPlayerSelectHotbarSlot(int slot)
391393

392394
private boolean isTargetSlotReserved()
393395
{
394-
return isEnabled() && reserveTargetSlot.isChecked();
396+
return isEnabled() && reserveTargetSlot.isChecked()
397+
&& isTargetSlotUsable();
398+
}
399+
400+
private boolean isTargetSlotUsable()
401+
{
402+
if(!onlyWithMace.isChecked())
403+
return true;
404+
405+
int target = getTargetHotbarSlot();
406+
if(target < 0 || target > 8 || MC.player == null)
407+
return false;
408+
409+
return MC.player.getInventory().getItem(target)
410+
.getItem() instanceof MaceItem;
395411
}
396412

397413
public int getTargetHotbarSlot()

src/main/java/net/wurstclient/hacks/ChatSpamHack.java

Lines changed: 141 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
import java.nio.charset.StandardCharsets;
1212
import java.nio.file.Files;
1313
import java.nio.file.Path;
14+
import java.text.BreakIterator;
1415
import java.util.ArrayList;
1516
import java.util.List;
17+
import java.util.Locale;
1618

1719
import net.wurstclient.Category;
1820
import net.wurstclient.SearchTags;
@@ -31,6 +33,7 @@
3133
public final class ChatSpamHack extends Hack implements UpdateListener
3234
{
3335
private static final int CHAT_LIMIT = 256;
36+
private static final char FORMAT_CHAR = '\u00A7';
3437

3538
private final TextFieldSetting message = new TextFieldSetting("Message",
3639
"Chat message to send repeatedly when file mode is disabled.", "",
@@ -218,9 +221,7 @@ private boolean loadMessagesFromFile()
218221

219222
for(String line : lines)
220223
{
221-
String normalized = normalizeMessage(line);
222-
if(!normalized.isEmpty())
223-
pendingMessages.add(normalized);
224+
addMessageChunks(line);
224225
}
225226

226227
if(pendingMessages.isEmpty())
@@ -237,10 +238,143 @@ private static String normalizeMessage(String message)
237238
if(message == null)
238239
return "";
239240

240-
String trimmed = message.replace("\r", "");
241-
if(trimmed.length() > CHAT_LIMIT)
242-
trimmed = trimmed.substring(0, CHAT_LIMIT);
241+
return message.replace("\r", "");
242+
}
243+
244+
private void addMessageChunks(String message)
245+
{
246+
String remaining = normalizeMessage(message);
247+
if(remaining.isEmpty())
248+
return;
243249

244-
return trimmed;
250+
String formattingPrefix = "";
251+
while(!remaining.isEmpty())
252+
{
253+
int budget = CHAT_LIMIT - formattingPrefix.length();
254+
if(budget <= 0)
255+
{
256+
formattingPrefix = "";
257+
budget = CHAT_LIMIT;
258+
}
259+
260+
if(remaining.length() <= budget)
261+
{
262+
pendingMessages.add(formattingPrefix + remaining);
263+
return;
264+
}
265+
266+
int breakPos = findPreferredBreakPosition(remaining, budget);
267+
if(breakPos <= 0)
268+
breakPos = findSafeHardBreak(remaining, budget);
269+
270+
String chunk = remaining.substring(0, breakPos).stripTrailing();
271+
if(!chunk.isEmpty())
272+
{
273+
pendingMessages.add(formattingPrefix + chunk);
274+
formattingPrefix =
275+
getActiveFormatting(formattingPrefix + chunk);
276+
}
277+
278+
remaining = remaining.substring(breakPos).stripLeading();
279+
}
280+
}
281+
282+
private static int findPreferredBreakPosition(String text, int budget)
283+
{
284+
int sentenceBreak = findSentenceBreakPosition(text, budget);
285+
if(sentenceBreak > 0)
286+
return sentenceBreak;
287+
288+
int wordBreak = findWhitespaceBreakPosition(text, budget);
289+
if(wordBreak > 0)
290+
return wordBreak;
291+
292+
return -1;
293+
}
294+
295+
private static int findSentenceBreakPosition(String text, int budget)
296+
{
297+
BreakIterator iterator = BreakIterator.getSentenceInstance(Locale.ROOT);
298+
iterator.setText(text);
299+
300+
int best = -1;
301+
for(int end = iterator.first(); end != BreakIterator.DONE; end =
302+
iterator.next())
303+
{
304+
if(end > 0 && end <= budget)
305+
best = end;
306+
}
307+
308+
return best;
309+
}
310+
311+
private static int findWhitespaceBreakPosition(String text, int budget)
312+
{
313+
int limit = Math.min(budget, text.length());
314+
for(int i = limit; i > 0; i--)
315+
{
316+
if(Character.isWhitespace(text.charAt(i - 1)))
317+
return i;
318+
}
319+
320+
return -1;
321+
}
322+
323+
private static int findSafeHardBreak(String text, int budget)
324+
{
325+
int end = Math.min(budget, text.length());
326+
if(end <= 0)
327+
return Math.min(1, text.length());
328+
329+
if(text.charAt(end - 1) == FORMAT_CHAR)
330+
end--;
331+
332+
if(end <= 0)
333+
end = Math.min(1, text.length());
334+
335+
return end;
336+
}
337+
338+
private static String getActiveFormatting(String text)
339+
{
340+
String color = "";
341+
StringBuilder styles = new StringBuilder();
342+
343+
for(int i = 0; i < text.length() - 1; i++)
344+
{
345+
if(text.charAt(i) != FORMAT_CHAR)
346+
continue;
347+
348+
char code = Character.toLowerCase(text.charAt(++i));
349+
if(code == 'r')
350+
{
351+
color = "";
352+
styles.setLength(0);
353+
continue;
354+
}
355+
356+
if(isColorCode(code))
357+
{
358+
color = "" + FORMAT_CHAR + code;
359+
styles.setLength(0);
360+
continue;
361+
}
362+
363+
if(isStyleCode(code) && styles.indexOf("" + FORMAT_CHAR + code) < 0)
364+
styles.append(FORMAT_CHAR).append(code);
365+
}
366+
367+
return color + styles;
368+
}
369+
370+
private static boolean isColorCode(char code)
371+
{
372+
return code >= '0' && code <= '9' || code >= 'a' && code <= 'f';
373+
}
374+
375+
private static boolean isStyleCode(char code)
376+
{
377+
return code == 'k' || code == 'l' || code == 'm' || code == 'n'
378+
|| code == 'o';
245379
}
246380
}

src/main/java/net/wurstclient/hacks/CreativeFlightHack.java

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88
package net.wurstclient.hacks;
99

10-
import net.minecraft.client.KeyMapping;
1110
import net.minecraft.client.player.LocalPlayer;
1211
import net.minecraft.world.entity.player.Abilities;
1312
import net.minecraft.world.phys.Vec3;
@@ -23,6 +22,8 @@
2322
@SearchTags({"creative flight", "CreativeFly", "creative fly"})
2423
public final class CreativeFlightHack extends Hack implements UpdateListener
2524
{
25+
private static final double DESCENT_SPEED = -0.15;
26+
2627
private final CheckboxSetting antiKick = new CheckboxSetting("Anti-Kick",
2728
"Makes you fall a little bit every now and then to prevent you from getting kicked.",
2829
false);
@@ -31,16 +32,22 @@ public final class CreativeFlightHack extends Hack implements UpdateListener
3132
new SliderSetting("Anti-Kick Interval",
3233
"How often Anti-Kick should prevent you from getting kicked.\n"
3334
+ "Most servers will kick you after 80 ticks.",
34-
30, 5, 80, 1, SliderSetting.ValueDisplay.INTEGER
35+
70, 5, 80, 1, SliderSetting.ValueDisplay.INTEGER
3536
.withSuffix(" ticks").withLabel(1, "1 tick"));
3637

3738
private final SliderSetting antiKickDistance = new SliderSetting(
3839
"Anti-Kick Distance",
3940
"How far Anti-Kick should make you fall.\n"
4041
+ "Most servers require at least 0.032m to stop you from getting kicked.",
41-
0.07, 0.01, 0.2, 0.001, ValueDisplay.DECIMAL.withSuffix("m"));
42+
0.035, 0.01, 0.2, 0.001, ValueDisplay.DECIMAL.withSuffix("m"));
43+
44+
private final CheckboxSetting startFlyingImmediately = new CheckboxSetting(
45+
"Start flying immediately",
46+
"Automatically enables CreativeFlight as soon as the hack is turned on, instead of waiting for the usual double-jump.",
47+
true);
4248

4349
private int tickCounter = 0;
50+
private boolean suppressedSneakKey;
4451

4552
public CreativeFlightHack()
4653
{
@@ -49,16 +56,23 @@ public CreativeFlightHack()
4956
addSetting(antiKick);
5057
addSetting(antiKickInterval);
5158
addSetting(antiKickDistance);
59+
addSetting(startFlyingImmediately);
5260
}
5361

5462
@Override
5563
protected void onEnable()
5664
{
5765
tickCounter = 0;
66+
suppressedSneakKey = false;
5867

5968
WURST.getHax().jetpackHack.setEnabled(false);
6069
WURST.getHax().flightHack.setEnabled(false);
6170

71+
Abilities abilities = MC.player.getAbilities();
72+
abilities.mayfly = true;
73+
if(startFlyingImmediately.isChecked())
74+
abilities.flying = true;
75+
6276
EVENTS.add(UpdateListener.class, this);
6377
}
6478

@@ -74,7 +88,7 @@ protected void onDisable()
7488
abilities.flying = creative && !player.onGround();
7589
abilities.mayfly = creative;
7690

77-
restoreKeyPresses();
91+
restoreSneakKey();
7892
}
7993

8094
@Override
@@ -83,49 +97,71 @@ public void onUpdate()
8397
Abilities abilities = MC.player.getAbilities();
8498
abilities.mayfly = true;
8599

100+
handleSmoothDescent(abilities);
101+
86102
if(antiKick.isChecked() && abilities.flying)
87103
doAntiKick();
88104
}
89105

106+
private void handleSmoothDescent(Abilities abilities)
107+
{
108+
IKeyMapping sneakKey = IKeyMapping.get(MC.options.keyShift);
109+
boolean sneakDown = sneakKey.isActuallyDown();
110+
111+
if(!abilities.flying || !sneakDown)
112+
{
113+
if(suppressedSneakKey)
114+
restoreSneakKey();
115+
116+
return;
117+
}
118+
119+
sneakKey.setDown(false);
120+
suppressedSneakKey = true;
121+
122+
if(IKeyMapping.get(MC.options.keyJump).isActuallyDown())
123+
return;
124+
125+
Vec3 velocity = MC.player.getDeltaMovement();
126+
MC.player.setDeltaMovement(velocity.x, DESCENT_SPEED, velocity.z);
127+
}
128+
90129
private void doAntiKick()
91130
{
92-
if(tickCounter > antiKickInterval.getValueI() + 2)
131+
if(IKeyMapping.get(MC.options.keyJump).isActuallyDown()
132+
|| IKeyMapping.get(MC.options.keyShift).isActuallyDown())
133+
return;
134+
135+
if(tickCounter > antiKickInterval.getValueI() + 1)
93136
tickCounter = 0;
94137

95138
switch(tickCounter)
96139
{
97140
case 0 ->
98141
{
99-
if(MC.options.keyShift.isDown() && !MC.options.keyJump.isDown())
100-
tickCounter = 3;
142+
Vec3 velocity = MC.player.getDeltaMovement();
143+
if(velocity.y <= -antiKickDistance.getValue())
144+
tickCounter = 2;
101145
else
102-
setMotionY(-antiKickDistance.getValue());
146+
addMotionY(-antiKickDistance.getValue());
103147
}
104148

105-
case 1 -> setMotionY(antiKickDistance.getValue());
106-
107-
case 2 -> setMotionY(0);
108-
109-
case 3 -> restoreKeyPresses();
149+
case 1 -> addMotionY(antiKickDistance.getValue());
110150
}
111151

112152
tickCounter++;
113153
}
114154

115-
private void setMotionY(double motionY)
155+
private void addMotionY(double motionY)
116156
{
117-
MC.options.keyShift.setDown(false);
118-
MC.options.keyJump.setDown(false);
119-
120157
Vec3 velocity = MC.player.getDeltaMovement();
121-
MC.player.setDeltaMovement(velocity.x, motionY, velocity.z);
158+
MC.player.setDeltaMovement(velocity.x, velocity.y + motionY,
159+
velocity.z);
122160
}
123161

124-
private void restoreKeyPresses()
162+
private void restoreSneakKey()
125163
{
126-
KeyMapping[] keys = {MC.options.keyJump, MC.options.keyShift};
127-
128-
for(KeyMapping key : keys)
129-
IKeyMapping.get(key).resetPressedState();
164+
IKeyMapping.get(MC.options.keyShift).resetPressedState();
165+
suppressedSneakKey = false;
130166
}
131167
}

0 commit comments

Comments
 (0)