Skip to content

Commit 5728c66

Browse files
committed
Performance Improvements
1 parent 58f388c commit 5728c66

12 files changed

Lines changed: 253 additions & 32 deletions

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,13 @@ Examples:
995995
- Notify users once per toggle/enable so they know performance/behavior is adjusted.
996996
- Currently only in these higher risk hacks: Search, CaveFinder, PlayerESP and Excavator as well as in BlockVertexCompiler.
997997

998+
### Performance Improvements
999+
- Improved chunk-scan responsiveness across Search, X-ray and other ESP hacks while moving quickly.
1000+
- Added Chunk Scan Mode to GlobalToggle which allows for incremental updates rather than full.
1001+
- Added search thread priority slider for tuning background scan speed vs CPU usage.
1002+
- Optimized Search when using corners only ESP to avoid unnecessary heavy mesh work making detection faster.
1003+
- Reduced lag spikes on large scans by using cheaper nearest-result selection paths.
1004+
9981005
### Notes
9991006
- Scanning only includes server-loaded chunks. Larger radii work best in single-player or on high view distance servers.
10001007

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,10 @@ public void onUpdate()
190190
if(didFiltersChange())
191191
groupsUpToDate = false;
192192

193-
if(!groupsUpToDate && coordinator.isDone())
193+
boolean partialScan =
194+
WURST.getHax().globalToggleHack.usePartialChunkScan();
195+
if(!groupsUpToDate && (partialScan ? coordinator.hasReadyMatches()
196+
: coordinator.isDone()))
194197
updateGroupBoxes();
195198
}
196199

@@ -251,7 +254,7 @@ private void renderTracers(PoseStack matrixStack, float partialTicks)
251254
private void updateGroupBoxes()
252255
{
253256
groups.forEach(BedEspBlockGroup::clear);
254-
java.util.List<Result> results = coordinator.getMatches().toList();
257+
java.util.List<Result> results = coordinator.getReadyMatches().toList();
255258
refreshEnvironmentalCaches();
256259
results.forEach(this::addToGroupBoxes);
257260
groupsUpToDate = true;

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
import net.wurstclient.hack.CheckboxOverrideManager;
1717
import net.wurstclient.hack.Hack;
1818
import net.wurstclient.settings.CheckboxSetting;
19+
import net.wurstclient.settings.EnumSetting;
1920
import net.wurstclient.settings.SliderSetting;
2021
import net.wurstclient.settings.SliderSetting.ValueDisplay;
2122
import net.wurstclient.util.ChatUtils;
23+
import net.wurstclient.util.chunk.ChunkSearcher;
2224

2325
@SearchTags({"global toggle", "render global toggle"})
2426
public final class GlobalToggleHack extends Hack implements UpdateListener
@@ -38,13 +40,25 @@ public final class GlobalToggleHack extends Hack implements UpdateListener
3840
"Forces the above-ground filter off for all supported hacks.", false);
3941
private final SliderSetting yLimitValue = new SliderSetting(
4042
"Global Y limit", 62, 0, 255, 1, ValueDisplay.INTEGER);
43+
private final SliderSetting searchThreadPriority = new SliderSetting(
44+
"Search thread priority",
45+
"Global background thread priority for Search/ESP/X-Ray chunk scanning.",
46+
ChunkSearcher.getBackgroundThreadPriority(), Thread.MIN_PRIORITY,
47+
Thread.MAX_PRIORITY, 1, ValueDisplay.INTEGER);
48+
private final EnumSetting<ChunkScanMode> chunkScanMode = new EnumSetting<>(
49+
"Chunk scan mode",
50+
"FULL: Update only when full area scan is done (old behavior).\n"
51+
+ "PARTIAL: Update from ready chunks immediately (faster detection).",
52+
ChunkScanMode.values(), ChunkScanMode.FULL);
4153

4254
private Map<CheckboxSetting, Boolean> stickySnapshot = Map.of();
4355
private Map<CheckboxSetting, Boolean> yLimitSnapshot = Map.of();
4456

4557
private OverrideState lastStickyState = OverrideState.NONE;
4658
private OverrideState lastYState = OverrideState.NONE;
4759
private int lastYLimitValue = 62;
60+
private int lastSearchThreadPriority =
61+
ChunkSearcher.getBackgroundThreadPriority();
4862
private boolean stickyAnnouncementsReady;
4963
private boolean yLimitAnnouncementsReady;
5064

@@ -58,8 +72,11 @@ public GlobalToggleHack()
5872
addSetting(yLimitForceOn);
5973
addSetting(yLimitForceOff);
6074
addSetting(yLimitValue);
75+
addSetting(searchThreadPriority);
76+
addSetting(chunkScanMode);
6177

6278
lastYLimitValue = yLimitValue.getValueI();
79+
lastSearchThreadPriority = searchThreadPriority.getValueI();
6380

6481
EVENTS.add(UpdateListener.class, this);
6582
}
@@ -170,6 +187,13 @@ public void onUpdate()
170187
stickyAnnouncementsReady = true;
171188
if(!yLimitAnnouncementsReady)
172189
yLimitAnnouncementsReady = true;
190+
191+
int priority = searchThreadPriority.getValueI();
192+
if(priority != lastSearchThreadPriority)
193+
{
194+
ChunkSearcher.setBackgroundThreadPriority(priority);
195+
lastSearchThreadPriority = priority;
196+
}
173197
}
174198

175199
private void announceSticky(boolean forcingOn)
@@ -198,10 +222,21 @@ private OverrideState getOverrideState(CheckboxSetting forceOn,
198222
return OverrideState.NONE;
199223
}
200224

225+
public boolean usePartialChunkScan()
226+
{
227+
return chunkScanMode.getSelected() == ChunkScanMode.PARTIAL;
228+
}
229+
201230
private enum OverrideState
202231
{
203232
NONE,
204233
FORCE_ON,
205234
FORCE_OFF;
206235
}
236+
237+
private enum ChunkScanMode
238+
{
239+
FULL,
240+
PARTIAL;
241+
}
207242
}

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

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
import com.mojang.blaze3d.vertex.PoseStack;
1111
import java.awt.Color;
1212
import java.util.Arrays;
13-
import java.util.Comparator;
1413
import java.util.List;
14+
import java.util.PriorityQueue;
1515
import java.util.function.BiPredicate;
16-
import java.util.stream.Collectors;
1716
import net.minecraft.core.BlockPos;
1817
import net.minecraft.world.level.ChunkPos;
1918
import net.minecraft.world.level.block.Block;
@@ -169,7 +168,10 @@ public void onUpdate()
169168
lastMatchesVersion = matchesVersion;
170169
groupsUpToDate = false;
171170
}
172-
if(!groupsUpToDate && coordinator.isDone())
171+
boolean partialScan =
172+
WURST.getHax().globalToggleHack.usePartialChunkScan();
173+
if(!groupsUpToDate && (partialScan ? coordinator.hasReadyMatches()
174+
: coordinator.isDone()))
173175
updateGroupBoxes();
174176
}
175177

@@ -227,11 +229,21 @@ private void updateGroupBoxes()
227229
{
228230
groups.forEach(LiquidEspBlockGroup::clear);
229231
int limit = renderAmount.getValueI();
230-
java.util.List<Result> matches = coordinator.getMatches()
231-
.sorted(Comparator.comparingDouble(
232-
r -> r.pos().distToCenterSqr(RotationUtils.getEyesPos())))
233-
.limit(limit).collect(Collectors.toList());
234-
matches.forEach(this::addToGroupBoxes);
232+
var eyesPos = RotationUtils.getEyesPos();
233+
PriorityQueue<Result> heap = new PriorityQueue<>((limit + 1),
234+
(a, b) -> Double.compare(b.pos().distToCenterSqr(eyesPos),
235+
a.pos().distToCenterSqr(eyesPos)));
236+
coordinator.getReadyMatches().forEach(result -> {
237+
if(heap.size() < limit)
238+
heap.offer(result);
239+
else if(result.pos().distToCenterSqr(eyesPos) < heap.peek().pos()
240+
.distToCenterSqr(eyesPos))
241+
{
242+
heap.poll();
243+
heap.offer(result);
244+
}
245+
});
246+
heap.forEach(this::addToGroupBoxes);
235247
groupsUpToDate = true;
236248
}
237249

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public final class PortalEspHack extends Hack implements UpdateListener,
128128
private boolean groupsUpToDate;
129129
private ChunkAreaSetting.ChunkArea lastAreaSelection;
130130
private ChunkPos lastPlayerChunk;
131+
private int lastMatchesVersion;
131132
private final HashSet<BlockPos> discoveredPositions = new HashSet<>();
132133

133134
public PortalEspHack()
@@ -156,6 +157,7 @@ protected void onEnable()
156157
discoveredPositions.clear();
157158
lastAreaSelection = area.getSelected();
158159
lastPlayerChunk = new ChunkPos(MC.player.blockPosition());
160+
lastMatchesVersion = coordinator.getMatchesVersion();
159161
EVENTS.add(UpdateListener.class, this);
160162
EVENTS.add(CameraTransformViewBobbingListener.class, this);
161163
EVENTS.add(RenderListener.class, this);
@@ -172,6 +174,7 @@ protected void onDisable()
172174
EVENTS.remove(RenderListener.class, this);
173175

174176
coordinator.reset();
177+
lastMatchesVersion = coordinator.getMatchesVersion();
175178
groups.forEach(PortalEspBlockGroup::clear);
176179
discoveredPositions.clear();
177180
}
@@ -205,7 +208,16 @@ public void onUpdate()
205208
boolean searchersChanged = coordinator.update();
206209
if(searchersChanged)
207210
groupsUpToDate = false;
208-
if(!groupsUpToDate && coordinator.isDone())
211+
int matchesVersion = coordinator.getMatchesVersion();
212+
if(matchesVersion != lastMatchesVersion)
213+
{
214+
lastMatchesVersion = matchesVersion;
215+
groupsUpToDate = false;
216+
}
217+
boolean partialScan =
218+
WURST.getHax().globalToggleHack.usePartialChunkScan();
219+
if(!groupsUpToDate && (partialScan ? coordinator.hasReadyMatches()
220+
: coordinator.isDone()))
209221
updateGroupBoxes();
210222
}
211223

@@ -262,7 +274,7 @@ private void updateGroupBoxes()
262274
groups.forEach(PortalEspBlockGroup::clear);
263275
HashMap<PortalEspBlockGroup, ArrayList<BlockPos>> newBlocksByGroup =
264276
new HashMap<>();
265-
coordinator.getMatches()
277+
coordinator.getReadyMatches()
266278
.forEach(result -> addToGroupBoxes(result, newBlocksByGroup));
267279

268280
ArrayList<DiscoveryHit> discoveries =

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,10 @@ public void onUpdate()
303303
lastMatchesVersion = matchesVersion;
304304
groupsUpToDate = false;
305305
}
306-
if(!groupsUpToDate && coordinator.isDone())
306+
boolean partialScan =
307+
WURST.getHax().globalToggleHack.usePartialChunkScan();
308+
if(!groupsUpToDate && (partialScan ? coordinator.hasReadyMatches()
309+
: coordinator.isDone()))
307310
updateGroupBoxes();
308311
}
309312

@@ -359,7 +362,7 @@ private void renderTracers(PoseStack matrixStack, float partialTicks)
359362
private void updateGroupBoxes()
360363
{
361364
renderGroups.forEach(RenderGroup::clear);
362-
coordinator.getMatches().forEach(this::addToGroupBoxes);
365+
coordinator.getReadyMatches().forEach(this::addToGroupBoxes);
363366
groupsUpToDate = true;
364367
int total =
365368
renderGroups.stream().mapToInt(g -> g.getBoxes().size()).sum();

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

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ private enum SearchMode
145145
private java.util.List<net.minecraft.world.phys.Vec3> tracerEnds;
146146
private ChunkPos lastPlayerChunk;
147147
private int lastMatchesVersion;
148+
private boolean lastNeedsVertexBuffer;
148149

149150
private SearchMode lastMode;
150151
private int lastListHash;
@@ -221,6 +222,7 @@ protected void onEnable()
221222
lastPlayerChunk = new ChunkPos(MC.player.blockPosition());
222223
lastMode = mode.getSelected();
223224
lastListHash = blockList.getBlockNames().hashCode();
225+
lastNeedsVertexBuffer = needsVertexBuffer();
224226
applySearchCriteria(block.getBlock(), "");
225227
lastMatchesVersion = coordinator.getMatchesVersion();
226228
if(shaderSafeMode)
@@ -336,6 +338,13 @@ public void onUpdate()
336338
notify = true;
337339
}
338340

341+
boolean needsVertexBuffer = needsVertexBuffer();
342+
if(needsVertexBuffer != lastNeedsVertexBuffer)
343+
{
344+
lastNeedsVertexBuffer = needsVertexBuffer;
345+
stopBuildingBuffer(true);
346+
}
347+
339348
if(!coordinator.hasReadyMatches())
340349
return;
341350

@@ -351,6 +360,13 @@ public void onUpdate()
351360
if(!getMatchingBlocksTask.isDone())
352361
return;
353362

363+
if(!needsVertexBuffer)
364+
{
365+
if(!bufferUpToDate)
366+
setSimpleBufferFromTask();
367+
return;
368+
}
369+
354370
if(compileVerticesTask == null)
355371
startCompileVerticesTask();
356372

@@ -377,8 +393,10 @@ public void onRender(PoseStack matrixStack, float partialTicks)
377393
style.hasBoxes() && vertexBuffer != null && bufferRegion != null;
378394
boolean drawTracers =
379395
style.hasLines() && tracerEnds != null && !tracerEnds.isEmpty();
396+
boolean drawHighlights =
397+
highlightBoxes != null && !highlightBoxes.isEmpty();
380398

381-
if(!drawBoxes && !drawTracers)
399+
if(!drawBoxes && !drawTracers && !drawHighlights)
382400
return;
383401

384402
float[] rgb = useFixedColor.isChecked() ? fixedColor.getColorF()
@@ -400,7 +418,7 @@ public void onRender(PoseStack matrixStack, float partialTicks)
400418
tracerColor, false);
401419
}
402420

403-
if(highlightBoxes != null && !highlightBoxes.isEmpty())
421+
if(drawHighlights)
404422
{
405423
float alpha = getHighlightAlphaFloat();
406424
int color = RenderUtils.toIntColor(rgb, alpha);
@@ -641,6 +659,12 @@ else if(notify)
641659
notify = false;
642660
}
643661

662+
if(!needsVertexBuffer())
663+
{
664+
setSimpleBufferFromMatches(matchingBlocks);
665+
return;
666+
}
667+
644668
ArrayList<int[]> vertices = BlockVertexCompiler.compile(matchingBlocks);
645669
setBufferFromVertices(vertices, matchingBlocks);
646670
}
@@ -657,6 +681,44 @@ private void setBufferFromTask()
657681
setBufferFromVertices(vertices, lastMatchingBlocks);
658682
}
659683

684+
private void setSimpleBufferFromTask()
685+
{
686+
HashSet<BlockPos> matchingBlocks = getMatchingBlocksTask.join();
687+
lastMatchingBlocks = matchingBlocks;
688+
setSimpleBufferFromMatches(matchingBlocks);
689+
}
690+
691+
private void setSimpleBufferFromMatches(HashSet<BlockPos> matchingBlocks)
692+
{
693+
if(vertexBuffer != null)
694+
{
695+
vertexBuffer.close();
696+
vertexBuffer = null;
697+
}
698+
699+
bufferRegion = null;
700+
bufferUpToDate = true;
701+
702+
if(matchingBlocks != null)
703+
{
704+
highlightBoxes = matchingBlocks.stream().map(AABB::new)
705+
.collect(java.util.stream.Collectors.toList());
706+
tracerEnds = matchingBlocks.stream().map(pos -> {
707+
if(net.wurstclient.util.BlockUtils.canBeClicked(pos))
708+
return net.wurstclient.util.BlockUtils.getBoundingBox(pos)
709+
.getCenter();
710+
return pos.getCenter();
711+
}).collect(java.util.stream.Collectors.toList());
712+
foundCount = Math.min(matchingBlocks.size(), 999);
713+
714+
}else
715+
{
716+
highlightBoxes = null;
717+
tracerEnds = null;
718+
foundCount = 0;
719+
}
720+
}
721+
660722
private void setBufferFromVertices(ArrayList<int[]> vertices,
661723
HashSet<BlockPos> matchingBlocks)
662724
{
@@ -716,6 +778,11 @@ private void stopBuildingBuffer(boolean discardCurrent)
716778
}
717779
}
718780

781+
private boolean needsVertexBuffer()
782+
{
783+
return highlightFill.isChecked();
784+
}
785+
719786
private float getHighlightAlphaFloat()
720787
{
721788
int v = (int)Math.round(highlightAlpha.getValue());

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ public void onUpdate()
166166
lastMatchesVersion = matchesVersion;
167167
groupsUpToDate = false;
168168
}
169-
if(!groupsUpToDate && coordinator.isDone())
169+
boolean partialScan =
170+
WURST.getHax().globalToggleHack.usePartialChunkScan();
171+
if(!groupsUpToDate && (partialScan ? coordinator.hasReadyMatches()
172+
: coordinator.isDone()))
170173
updateGroupBoxes();
171174
}
172175

@@ -245,7 +248,7 @@ private void renderTracers(PoseStack matrixStack, float partialTicks)
245248
private void updateGroupBoxes()
246249
{
247250
groups.forEach(SignEspGroup::clear);
248-
coordinator.getMatches().forEach(this::addToGroupBoxes);
251+
coordinator.getReadyMatches().forEach(this::addToGroupBoxes);
249252
groupsUpToDate = true;
250253
// compute count from both sign boxes and frame boxes
251254
int signs = groups.stream().mapToInt(g -> g.getBoxes().size()).sum();

0 commit comments

Comments
 (0)