Skip to content

Commit 2f0143c

Browse files
authored
Usage Stats HUD update, thanks Jookly123!
+ Added Usage Stats Tracker to monitor macro runtime over various timeframes. + Introduced a new Usage Stats HUD, configurable in the HUD settings menu. Shows runtime for the past 24 hours, 7 days, 30 days, and lifetime. Requires enabling long-term usage data storage in the settings (may increase file size slightly on slower systems).
2 parents 43f58a1 + b6008d4 commit 2f0143c

File tree

7 files changed

+258
-3
lines changed

7 files changed

+258
-3
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ baseGroup=com.jelly.farmhelperv2
44
mcVersion=1.8.9
55
modid=farmhelperv2
66
modName=FarmHelper
7-
version=2.9.4-pre1
7+
version=2.9.4-pre2
88
shouldRelease=true

src/main/java/com/jelly/farmhelperv2/config/FarmHelperConfig.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.jelly.farmhelperv2.hud.DebugHUD;
2424
import com.jelly.farmhelperv2.hud.ProfitCalculatorHUD;
2525
import com.jelly.farmhelperv2.hud.StatusHUD;
26+
import com.jelly.farmhelperv2.hud.UsageStatsHUD;
2627
import com.jelly.farmhelperv2.util.BlockUtils;
2728
import com.jelly.farmhelperv2.util.LogUtils;
2829
import com.jelly.farmhelperv2.util.PlayerUtils;
@@ -2161,6 +2162,63 @@ public static void triggerManuallyAutoComposter() {
21612162
name = "Profit Calculator HUD - Visual Settings", category = HUD, subcategory = " "
21622163
)
21632164
public static ProfitCalculatorHUD profitHUD = new ProfitCalculatorHUD();
2165+
@Switch(
2166+
name = "Colour-code 24-hour total",
2167+
description = "Green < 3.5 h, 3.5 h < Orange < 7 h, Red ≥ 7 h",
2168+
category = HUD,
2169+
subcategory = "Usage Stats"
2170+
)
2171+
public static boolean colourCode24H = true;
2172+
@Switch(
2173+
name = "Show 24-hour total",
2174+
category = HUD,
2175+
subcategory = "Usage Stats"
2176+
)
2177+
public static boolean showStats24H = true;
2178+
@Switch(
2179+
name = "Show 7-day total",
2180+
category = HUD,
2181+
subcategory = "Usage Stats"
2182+
)
2183+
public static boolean showStats7D = false;
2184+
@Switch(
2185+
name = "Enable Long Term Data Storage",
2186+
category = HUD,
2187+
subcategory = "Usage Stats"
2188+
)
2189+
public static boolean longTermUserStats = false;
2190+
@Info(
2191+
text = "Enabling long term storage of user stats could potentially lead to large files (< 1mb), which may cause lag, in time, on slow systems",
2192+
type = InfoType.WARNING,
2193+
category = HUD,
2194+
subcategory = "Usage Stats",
2195+
size = 2
2196+
)
2197+
public static boolean usageStatsInfo;
2198+
@Switch(
2199+
name = "Show 30-day total",
2200+
category = HUD,
2201+
subcategory = "Usage Stats"
2202+
)
2203+
public static boolean showStats30D = false;
2204+
@Switch(
2205+
name = "Show lifetime total",
2206+
category = HUD,
2207+
subcategory = "Usage Stats"
2208+
)
2209+
public static boolean showStatsLifetime = true;
2210+
@Switch(
2211+
name = "Show FH Usage Stats Title",
2212+
category = HUD,
2213+
subcategory = "Usage Stats"
2214+
)
2215+
public static boolean showStatsTitle = false;
2216+
@HUD(
2217+
name = "Usage Stats HUD - Visual Settings",
2218+
category = HUD,
2219+
subcategory = "Usage Stats"
2220+
)
2221+
public static UsageStatsHUD UsageStatsHUD = new UsageStatsHUD();
21642222
//</editor-fold>
21652223

21662224
//<editor-fold desc="DEBUG">
@@ -2437,6 +2495,9 @@ public FarmHelperConfig() {
24372495

24382496
this.addDependency("leaveTime", "leaveTimer");
24392497

2498+
this.addDependency("showStats30D", "longTermUserStats");
2499+
this.addDependency("showStatsLifetime", "longTermUserStats");
2500+
24402501
this.hideIf("shownWelcomeGUI", () -> true);
24412502

24422503
this.hideIf("configVersion", () -> true);

src/main/java/com/jelly/farmhelperv2/feature/FeatureManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public List<IFeature> fillFeatures() {
4949
Scheduler.getInstance(),
5050
UngrabMouse.getInstance(),
5151
VisitorsMacro.getInstance(),
52+
UsageStatsTracker.getInstance(),
5253
PiPMode.getInstance()
5354
);
5455
features.addAll(featuresList);

src/main/java/com/jelly/farmhelperv2/feature/impl/BanInfoWS.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,24 @@ public void saveStats() {
470470
}
471471

472472
public long getLongestSessionLast7D() {
473+
if (FarmHelperConfig.longTermUserStats) {
474+
long sevenDaysAgo = System.currentTimeMillis() - 604800000L; // 7 days in milliseconds
475+
JsonArray jsonArray = readJsonArrayFromFile();
476+
long longestSessionLength = 0L;
477+
478+
for (JsonElement element : jsonArray) {
479+
JsonObject session = element.getAsJsonObject();
480+
long sessionTimestamp = session.get("timestamp").getAsLong();
481+
if (sessionTimestamp >= sevenDaysAgo) {
482+
long sessionLength = session.get("timeMacroing").getAsLong();
483+
if (sessionLength > longestSessionLength) {
484+
longestSessionLength = sessionLength;
485+
}
486+
}
487+
}
488+
return longestSessionLength;
489+
}
490+
473491
long sevenDaysAgo = System.currentTimeMillis() - 604800000L; // 7 days in milliseconds
474492
JsonArray jsonArray = readJsonArrayFromFile();
475493
JsonArray updatedJsonArray = new JsonArray();
@@ -486,9 +504,10 @@ public long getLongestSessionLast7D() {
486504
updatedJsonArray.add(session);
487505
}
488506
}
489-
490-
writeJsonArrayToFile(updatedJsonArray); // Optimize by writing only if needed
507+
// every time a user gets banned this function will run. it will delete entries in the json that are older than 7d
508+
writeJsonArrayToFile(updatedJsonArray);
491509
return longestSessionLength;
510+
492511
}
493512

494513
private JsonArray readJsonArrayFromFile() {
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package com.jelly.farmhelperv2.feature.impl;
2+
3+
import com.google.gson.*;
4+
import com.jelly.farmhelperv2.feature.IFeature;
5+
import com.jelly.farmhelperv2.util.LogUtils;
6+
import net.minecraft.client.Minecraft;
7+
8+
import java.io.*;
9+
import java.nio.charset.StandardCharsets;
10+
import java.time.*;
11+
import java.util.concurrent.TimeUnit;
12+
import java.util.zip.GZIPInputStream;
13+
14+
import static com.jelly.farmhelperv2.feature.impl.BanInfoWS.fileNamePrefix;
15+
import static com.jelly.farmhelperv2.feature.impl.BanInfoWS.statsDirectory;
16+
17+
18+
public class UsageStatsTracker implements IFeature {
19+
private static UsageStatsTracker instance;
20+
public static UsageStatsTracker getInstance() {
21+
return instance == null ? (instance = new UsageStatsTracker()) : instance;
22+
}
23+
24+
private long baseTodayMillis = 0;
25+
private long baseTotalMillis = 0;
26+
private LocalDate todayDate = LocalDate.now();
27+
private long sessionMillis = 0;
28+
private long lastTickMillis = System.currentTimeMillis();
29+
private boolean running = false;
30+
31+
private UsageStatsTracker() { loadFromFile(); }
32+
33+
public String getTodayString() {
34+
return fmt(baseTodayMillis + sessionMillis);
35+
}
36+
public String getTotalString() {
37+
return fmt(baseTotalMillis + sessionMillis);
38+
}
39+
40+
public long getTodayMillis() { return baseTodayMillis + sessionMillis; }
41+
42+
private long rollingMillis(int days) {
43+
long cutoff = System.currentTimeMillis() - days * 86_400_000L;
44+
long sum = 0;
45+
for (JsonElement e : readArray()) {
46+
JsonObject o = e.getAsJsonObject();
47+
if (o.get("timestamp").getAsLong() >= cutoff)
48+
sum += o.get("timeMacroing").getAsLong();
49+
}
50+
return sum + sessionMillis;
51+
}
52+
53+
public long get7dMillis() { return rollingMillis(7); }
54+
public long get30dMillis() { return rollingMillis(30); }
55+
public String get7dString() { return fmt(get7dMillis()); }
56+
public String get30dString() { return fmt(get30dMillis()); }
57+
58+
@Override public String getName() { return "User Stats Tracker"; }
59+
@Override public boolean isRunning() { return running; }
60+
@Override public boolean shouldPauseMacroExecution() { return false; }
61+
@Override public boolean shouldStartAtMacroStart() { return false; }
62+
@Override public boolean isToggled() { return true; }
63+
@Override public boolean shouldCheckForFailsafes() { return false; }
64+
@Override public void resetStatesAfterMacroDisabled() {}
65+
@Override public void start() { running = true; lastTickMillis = System.currentTimeMillis(); }
66+
@Override public void resume() { start(); }
67+
@Override public void stop() { running = false ;}
68+
69+
public void tick(boolean macroRunning) {
70+
long now = System.currentTimeMillis();
71+
long delta = now - lastTickMillis;
72+
lastTickMillis = now;
73+
if (!todayDate.equals(LocalDate.now())) {
74+
todayDate = LocalDate.now();
75+
baseTodayMillis = 0;
76+
}
77+
if (macroRunning && delta > 0 && delta < 5000) {
78+
sessionMillis += delta;
79+
}
80+
}
81+
82+
private void loadFromFile() {
83+
JsonArray arr = readArray();
84+
LocalDate today = LocalDate.now();
85+
for (JsonElement e : arr) {
86+
JsonObject o = e.getAsJsonObject();
87+
long ms = o.get("timeMacroing").getAsLong();
88+
baseTotalMillis += ms;
89+
long ts = o.get("timestamp").getAsLong();
90+
LocalDate d = Instant.ofEpochMilli(ts).atZone(ZoneId.systemDefault()).toLocalDate();
91+
if (d.equals(today)) baseTodayMillis += ms;
92+
}
93+
}
94+
95+
private String fmt(long ms) {
96+
long h = TimeUnit.MILLISECONDS.toHours(ms);
97+
long m = TimeUnit.MILLISECONDS.toMinutes(ms) % 60;
98+
return String.format("%dh %02dm", h, m);
99+
}
100+
101+
private File statsFile() {
102+
String uuid = Minecraft.getMinecraft().getSession().getPlayerID().replace("-", "");
103+
return new File(statsDirectory, fileNamePrefix + uuid + ".dat");
104+
}
105+
106+
private JsonArray readArray() {
107+
File f = statsFile();
108+
if (!f.exists()) return new JsonArray();
109+
try (GZIPInputStream gzis = new GZIPInputStream(new FileInputStream(f));
110+
InputStreamReader isr = new InputStreamReader(gzis, StandardCharsets.UTF_8)) {
111+
JsonElement el = new JsonParser().parse(isr);
112+
return el.isJsonArray() ? el.getAsJsonArray() : new JsonArray();
113+
} catch (Exception e) {
114+
LogUtils.sendDebug("Error Reading Usage Stats Array");
115+
// e.printStackTrace();
116+
}
117+
return new JsonArray();
118+
}
119+
}

src/main/java/com/jelly/farmhelperv2/handler/MacroHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ public void onTick(TickEvent.ClientTickEvent event) {
334334
if (!cm.isEnabledAndNoFeature()) return;
335335
cm.onTick();
336336
});
337+
UsageStatsTracker.getInstance().tick(!isCurrentMacroPaused());
337338
}
338339

339340
@SubscribeEvent
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.jelly.farmhelperv2.hud;
2+
3+
import cc.polyfrost.oneconfig.config.core.OneColor;
4+
import cc.polyfrost.oneconfig.hud.TextHud;
5+
import com.jelly.farmhelperv2.config.FarmHelperConfig;
6+
import com.jelly.farmhelperv2.feature.impl.UsageStatsTracker;
7+
import com.jelly.farmhelperv2.handler.GameStateHandler;
8+
9+
import java.util.List;
10+
11+
public class UsageStatsHUD extends TextHud {
12+
13+
public UsageStatsHUD() {
14+
super(true, 1f, 10f, 0.9f, true, true,
15+
4, 5, 5, new OneColor(0,0,0,150),
16+
false, 2, new OneColor(0,0,0,127));
17+
}
18+
19+
@Override
20+
protected void getLines(List<String> lines, boolean example) {
21+
if (FarmHelperConfig.showStatsTitle) {
22+
lines.add("§lFH Usage Stats");
23+
}
24+
if (FarmHelperConfig.showStats24H) {
25+
String colour = "";
26+
if (FarmHelperConfig.colourCode24H) {
27+
double hrs = UsageStatsTracker.getInstance().getTodayMillis() / 3_600_000.0;
28+
if (hrs < 3.5) colour = "§a";
29+
else if (hrs < 7.0) colour = "§6";
30+
else colour = "§c";
31+
}
32+
lines.add("24 hour: " + colour + UsageStatsTracker.getInstance().getTodayString());
33+
}
34+
if (FarmHelperConfig.showStats7D) {
35+
lines.add("7 day: §a" + UsageStatsTracker.getInstance().get7dString());
36+
}
37+
if (FarmHelperConfig.showStats30D) {
38+
lines.add("30 day: §a" + UsageStatsTracker.getInstance().get30dString());
39+
}
40+
if (FarmHelperConfig.showStatsLifetime) {
41+
lines.add("lifetime: §a" + UsageStatsTracker.getInstance().getTotalString());
42+
}
43+
if (!FarmHelperConfig.showStatsTitle &&!FarmHelperConfig.showStats24H && !FarmHelperConfig.showStats7D && !FarmHelperConfig.showStats30D && !FarmHelperConfig.showStatsLifetime) {
44+
lines.add("§cEnable usage stats in the HUD config menu");
45+
}
46+
}
47+
48+
@Override
49+
protected boolean shouldShow() {
50+
return super.shouldShow()
51+
&& !FarmHelperConfig.streamerMode
52+
&& GameStateHandler.getInstance().inGarden();
53+
}
54+
}

0 commit comments

Comments
 (0)