Skip to content

Commit ea022a3

Browse files
committed
FPS & TPS Graph
1 parent 701afc2 commit ea022a3

File tree

4 files changed

+558
-15
lines changed

4 files changed

+558
-15
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ A ready-to-publish starter project is included here: [https://github.com/cev-api
284284
- Adjustable Tri-state Beacon Mode on waypoints (On/Off/ESP) that matches the waypoint's color.
285285
- Toggleable automatic portal logging, logs numerically each portal you enter and matches it in the opposite dimension with the same number.
286286
- Optional distance based label scaling
287+
- Optional dimming or hiding of on-screen waypoints unless looking directly at them
287288

288289

289290
#### Waypoint Commands
@@ -863,6 +864,10 @@ Purpose: helps you avoid and debug anticheat flags by cleaning risky movement pa
863864
- FPS/TPS/Ping show running averages in brackets (e.g. `Ping: 30 (21)`)
864865
- Style settings: font size, font opacity, font color, font stroke, background box toggle, background color, and background opacity
865866
- Per-stat visibility toggles plus a universal `Show Prefixes` and `Show Averages` toggle for labels
867+
- FPS and TPS graph
868+
- Can be embedded into GameStats or detached
869+
- When detached can be resizable via settings or dragging bottom right corner
870+
- Adjustable colors
866871

867872
![FPS](https://i.imgur.com/MhmAno5.png)
868873

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

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,30 @@ public final class GameStatsHack extends Hack implements PacketInputListener,
102102
private final CheckboxSetting showAverages =
103103
new CheckboxSetting("Show Averages", true);
104104

105+
private final CheckboxSetting showGraph =
106+
new CheckboxSetting("Show graph", false);
107+
108+
private final CheckboxSetting separateGraphWindow =
109+
new CheckboxSetting("Separate graph window", false);
110+
111+
private final ColorSetting fpsGraphColor =
112+
new ColorSetting("FPS graph color", new Color(0x53, 0xC7, 0xFF, 0xFF));
113+
114+
private final ColorSetting tpsGraphColor =
115+
new ColorSetting("TPS graph color", new Color(0xFF, 0xB3, 0x47, 0xFF));
116+
117+
private final SliderSetting graphWindowWidth = new SliderSetting(
118+
"Graph width", 220, 120, 1000, 1, ValueDisplay.INTEGER);
119+
120+
private final SliderSetting graphWindowHeight = new SliderSetting(
121+
"Graph height", 120, 70, 800, 1, ValueDisplay.INTEGER);
122+
123+
private final SliderSetting graphWindowOffsetX = new SliderSetting(
124+
"Graph X offset", 180, -2000, 2000, 1, ValueDisplay.INTEGER);
125+
126+
private final SliderSetting graphWindowOffsetY = new SliderSetting(
127+
"Graph Y offset", 0, -2000, 2000, 1, ValueDisplay.INTEGER);
128+
105129
private final ArrayDeque<Long> incomingPacketTimes = new ArrayDeque<>();
106130
private final ArrayDeque<Long> outgoingPacketTimes = new ArrayDeque<>();
107131
private final Object packetTimesLock = new Object();
@@ -135,6 +159,14 @@ public GameStatsHack()
135159
addSetting(hudOffsetY);
136160
addSetting(showPrefixes);
137161
addSetting(showAverages);
162+
addSetting(showGraph);
163+
addSetting(separateGraphWindow);
164+
addSetting(fpsGraphColor);
165+
addSetting(tpsGraphColor);
166+
addSetting(graphWindowWidth);
167+
addSetting(graphWindowHeight);
168+
addSetting(graphWindowOffsetX);
169+
addSetting(graphWindowOffsetY);
138170
}
139171

140172
@Override
@@ -343,6 +375,98 @@ public boolean showAverages()
343375
return showAverages.isChecked();
344376
}
345377

378+
public boolean showGraph()
379+
{
380+
return showGraph.isChecked();
381+
}
382+
383+
public boolean separateGraphWindow()
384+
{
385+
return separateGraphWindow.isChecked();
386+
}
387+
388+
public int getFpsGraphColorI()
389+
{
390+
return fpsGraphColor.getColorI();
391+
}
392+
393+
public int getTpsGraphColorI()
394+
{
395+
return tpsGraphColor.getColorI();
396+
}
397+
398+
public int getGraphWindowWidth()
399+
{
400+
return graphWindowWidth.getValueI();
401+
}
402+
403+
public int getGraphWindowHeight()
404+
{
405+
return graphWindowHeight.getValueI();
406+
}
407+
408+
public int getGraphWindowOffsetX()
409+
{
410+
return graphWindowOffsetX.getValueI();
411+
}
412+
413+
public int getGraphWindowOffsetY()
414+
{
415+
return graphWindowOffsetY.getValueI();
416+
}
417+
418+
public int getGraphWindowMinWidth()
419+
{
420+
return (int)graphWindowWidth.getMinimum();
421+
}
422+
423+
public int getGraphWindowMaxWidth()
424+
{
425+
return (int)graphWindowWidth.getMaximum();
426+
}
427+
428+
public int getGraphWindowMinHeight()
429+
{
430+
return (int)graphWindowHeight.getMinimum();
431+
}
432+
433+
public int getGraphWindowMaxHeight()
434+
{
435+
return (int)graphWindowHeight.getMaximum();
436+
}
437+
438+
public int getGraphWindowMinOffsetX()
439+
{
440+
return (int)graphWindowOffsetX.getMinimum();
441+
}
442+
443+
public int getGraphWindowMaxOffsetX()
444+
{
445+
return (int)graphWindowOffsetX.getMaximum();
446+
}
447+
448+
public int getGraphWindowMinOffsetY()
449+
{
450+
return (int)graphWindowOffsetY.getMinimum();
451+
}
452+
453+
public int getGraphWindowMaxOffsetY()
454+
{
455+
return (int)graphWindowOffsetY.getMaximum();
456+
}
457+
458+
public void setGraphWindowOffsets(int x, int y)
459+
{
460+
graphWindowOffsetX.setValue(x);
461+
graphWindowOffsetY.setValue(y);
462+
}
463+
464+
public void setGraphWindowSize(int width, int height)
465+
{
466+
graphWindowWidth.setValue(width);
467+
graphWindowHeight.setValue(height);
468+
}
469+
346470
public int getHudOffsetX()
347471
{
348472
return hudOffsetX.getValueI();

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

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import net.wurstclient.settings.SliderSetting;
4444
import net.wurstclient.settings.ColorSetting;
4545
import net.wurstclient.settings.SliderSetting.ValueDisplay;
46+
import net.wurstclient.util.BlockUtils;
4647
import net.wurstclient.util.RenderUtils;
4748
import net.wurstclient.waypoints.Waypoint;
4849
import net.wurstclient.waypoints.WaypointDimension;
@@ -141,6 +142,14 @@ public void update()
141142
new CheckboxSetting("Compass text outline", true);
142143
private final SliderSetting compassOutlineOpacity = new SliderSetting(
143144
"Compass outline opacity", 100, 0, 100, 1, ValueDisplay.INTEGER);
145+
private final CheckboxSetting dimObscuredOnScreenWaypoints =
146+
new CheckboxSetting("Dim obscured on-screen waypoints",
147+
"When a waypoint is hidden behind blocks, greatly dim its on-screen compass marker unless you're looking directly at it.",
148+
false);
149+
private final CheckboxSetting iconOnlyForObscuredOnScreenWaypoints =
150+
new CheckboxSetting("Icon-only when obscured",
151+
"When a waypoint is hidden behind blocks, only show its icon on the on-screen compass unless you're looking directly at it.",
152+
false);
144153

145154
// Waypoint world-label outline settings
146155
private final CheckboxSetting waypointOutline =
@@ -196,6 +205,8 @@ public WaypointsHack()
196205
addSetting(compassOpacity);
197206
addSetting(compassOutline);
198207
addSetting(compassOutlineOpacity);
208+
addSetting(dimObscuredOnScreenWaypoints);
209+
addSetting(iconOnlyForObscuredOnScreenWaypoints);
199210
addSetting(waypointOutline);
200211
addSetting(waypointOutlineOpacity);
201212
addSetting(compassBackgroundOpacity);
@@ -781,6 +792,20 @@ public void onRender(PoseStack matrices, float partialTicks)
781792

782793
double distSq = MC.player.distanceToSqr(wp.getX() + 0.5,
783794
wp.getY() + 0.5, wp.getZ() + 0.5);
795+
boolean applyObscuredRules =
796+
dimObscuredOnScreenWaypoints.isChecked()
797+
|| iconOnlyForObscuredOnScreenWaypoints.isChecked();
798+
boolean obscured = applyObscuredRules && isWaypointObscured(wp);
799+
boolean directlyLooked =
800+
obscured && isDirectlyLookingAtWaypoint(wp, 5.0);
801+
boolean suppressDetails = obscured && !directlyLooked
802+
&& iconOnlyForObscuredOnScreenWaypoints.isChecked();
803+
int waypointColor = applyFade(w.getColor(), distSq);
804+
if(obscured && !directlyLooked
805+
&& dimObscuredOnScreenWaypoints.isChecked())
806+
{
807+
waypointColor = dimForObscured(waypointColor);
808+
}
784809
double dist = Math.sqrt(distSq);
785810
double trd = waypointRenderDistance.getValue();
786811
boolean infiniteLabels = trd >= DISTANCE_SLIDER_INFINITE;
@@ -800,12 +825,10 @@ public void onRender(PoseStack matrices, float partialTicks)
800825
{
801826
RenderUtils.drawTracer(matrices, partialTicks,
802827
new Vec3(wp.getX() + 0.5, wp.getY() + 0.5, wp.getZ() + 0.5),
803-
applyFade(w.getColor(), distSq), false);
804-
RenderUtils
805-
.drawOutlinedBoxes(matrices,
806-
java.util.List.of(new RenderUtils.ColoredBox(
807-
new AABB(wp), applyFade(w.getColor(), distSq))),
808-
false);
828+
waypointColor, false);
829+
RenderUtils.drawOutlinedBoxes(matrices, java.util.List.of(
830+
new RenderUtils.ColoredBox(new AABB(wp), waypointColor)),
831+
false);
809832
}
810833

811834
if(!beyondMaxVisible)
@@ -829,16 +852,18 @@ public void onRender(PoseStack matrices, float partialTicks)
829852
if(beaconsEnabled && beaconMode != Waypoint.BeaconMode.OFF)
830853
{
831854
if(beaconInfinite || distSq <= beaconRangeSq)
832-
drawBeaconBeam(matrices, wp,
833-
applyFade(w.getColor(), distSq), beaconMode);
855+
drawBeaconBeam(matrices, wp, waypointColor, beaconMode);
834856
}
835857
}
836858

837859
if(renderLabel)
838860
{
839861
String title = w.getName() == null ? "" : w.getName();
840862
String icon = iconChar(w.getIcon());
841-
if(!icon.isEmpty())
863+
if(suppressDetails)
864+
{
865+
title = icon.isEmpty() ? "●" : icon;
866+
}else if(!icon.isEmpty())
842867
title = icon + (title.isEmpty() ? "" : " " + title);
843868
String distanceText = (int)dist + " blocks";
844869
double baseY = wp.getY() + 1.2;
@@ -919,10 +944,11 @@ public void onRender(PoseStack matrices, float partialTicks)
919944
}
920945
// Keep a constant 10px separation using local pixel offset
921946
float sepPx = 10.0f;
922-
drawWorldLabel(matrices, title, lx, ly, lz,
923-
applyFade(w.getColor(), distSq), scale, -sepPx);
924-
drawWorldLabel(matrices, distanceText, lx, ly, lz,
925-
applyFade(w.getColor(), distSq), (float)(scale * 0.9f), 0f);
947+
drawWorldLabel(matrices, title, lx, ly, lz, waypointColor,
948+
scale, -sepPx);
949+
if(!suppressDetails)
950+
drawWorldLabel(matrices, distanceText, lx, ly, lz,
951+
waypointColor, (float)(scale * 0.9f), 0f);
926952
}
927953
}
928954
}
@@ -1476,7 +1502,9 @@ public void onRenderGUI(GuiGraphicsExtractor context, float partialTicks)
14761502
for(WaypointEntry e : entries)
14771503
{
14781504
int ix = (int)Math.round(e.x);
1479-
if(selected != null && e.w.getUuid().equals(selected.w.getUuid()))
1505+
boolean directlyLooked =
1506+
selected != null && e.w.getUuid().equals(selected.w.getUuid());
1507+
if(directlyLooked)
14801508
ix = centerX; // center selected
14811509
String icon = iconChar(e.w.getIcon());
14821510
if(icon == null)
@@ -1618,6 +1646,48 @@ private static String cardinalFromYaw(double yaw)
16181646
}
16191647
}
16201648

1649+
private boolean isWaypointObscured(BlockPos waypointPos)
1650+
{
1651+
if(MC.player == null || MC.level == null || waypointPos == null)
1652+
return false;
1653+
1654+
Vec3 eyes = MC.player.getEyePosition(1.0F);
1655+
Vec3 target = new Vec3(waypointPos.getX() + 0.5,
1656+
waypointPos.getY() + 1.2, waypointPos.getZ() + 0.5);
1657+
return !BlockUtils.hasLineOfSight(eyes, target);
1658+
}
1659+
1660+
private boolean isDirectlyLookingAtWaypoint(BlockPos waypointPos,
1661+
double maxAngleDeg)
1662+
{
1663+
if(MC.player == null || waypointPos == null)
1664+
return false;
1665+
1666+
Vec3 eyes = MC.player.getEyePosition(1.0F);
1667+
Vec3 target = new Vec3(waypointPos.getX() + 0.5,
1668+
waypointPos.getY() + 1.2, waypointPos.getZ() + 0.5);
1669+
Vec3 toWp = target.subtract(eyes);
1670+
double len = toWp.length();
1671+
if(len < 1.0E-6)
1672+
return true;
1673+
1674+
Vec3 dir = toWp.scale(1.0 / len);
1675+
Vec3 look = MC.player.getLookAngle();
1676+
double dot = look.dot(dir);
1677+
dot = Math.max(-1.0, Math.min(1.0, dot));
1678+
double angle = Math.toDegrees(Math.acos(dot));
1679+
return angle <= maxAngleDeg;
1680+
}
1681+
1682+
private int dimForObscured(int argb)
1683+
{
1684+
int a = (argb >>> 24) & 0xFF;
1685+
if(a <= 0)
1686+
a = 0xFF;
1687+
int dimmedAlpha = Math.max(14, (int)Math.round(a * 0.2));
1688+
return withAlpha(argb, dimmedAlpha);
1689+
}
1690+
16211691
private static final class WaypointEntry
16221692
{
16231693
final Waypoint w;

0 commit comments

Comments
 (0)