aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/skyblock/garden
diff options
context:
space:
mode:
authorKevin <92656833+kevinthegreat1@users.noreply.github.com>2024-03-18 00:41:11 -0400
committerGitHub <noreply@github.com>2024-03-18 00:41:11 -0400
commit02a7ecc471c3a24a0ef4c9a58b70ebf2510ed55f (patch)
treedb7ec1bc6e5142cd1853c49e3f08148544d16b8e /src/main/java/de/hysky/skyblocker/skyblock/garden
parent40fc0550c7441ed6966d8a0222b60485180f93e0 (diff)
parent5cf396aa564ba3b93762f914cc2334d48596ab2e (diff)
downloadSkyblocker-02a7ecc471c3a24a0ef4c9a58b70ebf2510ed55f.tar.gz
Skyblocker-02a7ecc471c3a24a0ef4c9a58b70ebf2510ed55f.tar.bz2
Skyblocker-02a7ecc471c3a24a0ef4c9a58b70ebf2510ed55f.zip
Merge pull request #589 from kevinthegreat1/farming-hud
Farming HUD & HUD Refactor
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock/garden')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java123
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudConfigScreen.java30
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudWidget.java67
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java3
4 files changed, 222 insertions, 1 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java
new file mode 100644
index 00000000..95c72241
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java
@@ -0,0 +1,123 @@
+package de.hysky.skyblocker.skyblock.garden;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.ItemUtils;
+import de.hysky.skyblocker.utils.Location;
+import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.scheduler.Scheduler;
+import it.unimi.dsi.fastutil.floats.FloatLongPair;
+import it.unimi.dsi.fastutil.ints.IntLongPair;
+import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue;
+import it.unimi.dsi.fastutil.longs.LongPriorityQueue;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
+import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
+import net.fabricmc.fabric.api.event.client.player.ClientPlayerBlockBreakEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.item.ItemStack;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Locale;
+import java.util.Queue;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
+public class FarmingHud {
+ private static final Logger LOGGER = LoggerFactory.getLogger(FarmingHud.class);
+ public static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(Locale.US);
+ private static final Pattern COUNTER = Pattern.compile("Counter: (?<count>[\\d,]+) .+");
+ private static final Pattern FARMING_XP = Pattern.compile("ยง3\\+(?<xp>\\d+.?\\d*) Farming \\((?<percent>\\d+.?\\d*)%\\)");
+ private static final Deque<IntLongPair> counter = new ArrayDeque<>();
+ private static final LongPriorityQueue blockBreaks = new LongArrayFIFOQueue();
+ private static final Queue<FloatLongPair> farmingXp = new ArrayDeque<>();
+ private static float farmingXpPercentProgress;
+
+ public static void init() {
+ HudRenderCallback.EVENT.register((context, tickDelta) -> {
+ if (shouldRender()) {
+ if (!counter.isEmpty() && counter.peek().rightLong() + 10_000 < System.currentTimeMillis()) {
+ counter.poll();
+ }
+ if (!blockBreaks.isEmpty() && blockBreaks.firstLong() + 1000 < System.currentTimeMillis()) {
+ blockBreaks.dequeueLong();
+ }
+ if (!farmingXp.isEmpty() && farmingXp.peek().rightLong() + 1000 < System.currentTimeMillis()) {
+ farmingXp.poll();
+ }
+
+ ItemStack stack = MinecraftClient.getInstance().player.getMainHandStack();
+ Matcher matcher = ItemUtils.getNbtTooltip(stack, FarmingHud.COUNTER);
+ if (matcher != null) {
+ try {
+ int count = NUMBER_FORMAT.parse(matcher.group("count")).intValue();
+ if (counter.isEmpty() || counter.peekLast().leftInt() != count) {
+ counter.offer(IntLongPair.of(count, System.currentTimeMillis()));
+ }
+ } catch (ParseException e) {
+ LOGGER.error("[Skyblocker Farming HUD] Failed to parse counter", e);
+ }
+ }
+
+ FarmingHudWidget.INSTANCE.update();
+ FarmingHudWidget.INSTANCE.render(context, SkyblockerConfigManager.get().general.tabHud.enableHudBackground);
+ }
+ });
+ ClientPlayerBlockBreakEvents.AFTER.register((world, player, pos, state) -> {
+ if (shouldRender()) {
+ blockBreaks.enqueue(System.currentTimeMillis());
+ }
+ });
+ ClientReceiveMessageEvents.GAME.register((message, overlay) -> {
+ if (shouldRender() && overlay) {
+ Matcher matcher = FARMING_XP.matcher(message.getString());
+ if (matcher.matches()) {
+ try {
+ farmingXp.offer(FloatLongPair.of(NUMBER_FORMAT.parse(matcher.group("xp")).floatValue(), System.currentTimeMillis()));
+ farmingXpPercentProgress = NUMBER_FORMAT.parse(matcher.group("percent")).floatValue();
+ } catch (ParseException e) {
+ LOGGER.error("[Skyblocker Farming HUD] Failed to parse farming xp", e);
+ }
+ }
+ }
+ });
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("hud").then(literal("farming")
+ .executes(Scheduler.queueOpenScreenCommand(() -> new FarmingHudConfigScreen(null)))))));
+ }
+
+ private static boolean shouldRender() {
+ return SkyblockerConfigManager.get().locations.garden.farmingHud.enableHud && Utils.getLocation() == Location.GARDEN;
+ }
+
+ public static int counter() {
+ return counter.isEmpty() ? 0 : counter.peekLast().leftInt();
+ }
+
+ public static float cropsPerMinute() {
+ if (counter.isEmpty()) {
+ return 0;
+ }
+ IntLongPair first = counter.peek();
+ IntLongPair last = counter.peekLast();
+ return (float) (last.leftInt() - first.leftInt()) / (last.rightLong() - first.rightLong()) * 60_000f;
+ }
+
+ public static int blockBreaks() {
+ return blockBreaks.size();
+ }
+
+ public static float farmingXpPercentProgress() {
+ return farmingXpPercentProgress;
+ }
+
+ public static double farmingXpPerHour() {
+ return farmingXp.stream().mapToDouble(FloatLongPair::leftFloat).sum() * 3600;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudConfigScreen.java
new file mode 100644
index 00000000..5384d47a
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudConfigScreen.java
@@ -0,0 +1,30 @@
+package de.hysky.skyblocker.skyblock.garden;
+
+import de.hysky.skyblocker.config.HudConfigScreen;
+import de.hysky.skyblocker.config.SkyblockerConfig;
+import de.hysky.skyblocker.skyblock.tabhud.widget.Widget;
+import it.unimi.dsi.fastutil.ints.IntIntMutablePair;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.text.Text;
+
+import java.util.List;
+
+public class FarmingHudConfigScreen extends HudConfigScreen {
+ public FarmingHudConfigScreen(Screen parent) {
+ super(Text.literal("Farming HUD Config"), parent, FarmingHudWidget.INSTANCE);
+ }
+
+ @SuppressWarnings("SuspiciousNameCombination")
+ @Override
+ protected List<IntIntMutablePair> getConfigPos(SkyblockerConfig config) {
+ return List.of(
+ IntIntMutablePair.of(config.locations.garden.farmingHud.x, config.locations.garden.farmingHud.y)
+ );
+ }
+
+ @Override
+ protected void savePos(SkyblockerConfig configManager, List<Widget> widgets) {
+ configManager.locations.garden.farmingHud.x = widgets.get(0).getX();
+ configManager.locations.garden.farmingHud.y = widgets.get(0).getY();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudWidget.java
new file mode 100644
index 00000000..6ddb0e05
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudWidget.java
@@ -0,0 +1,67 @@
+package de.hysky.skyblocker.skyblock.garden;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.tabhud.util.Ico;
+import de.hysky.skyblocker.skyblock.tabhud.widget.Widget;
+import de.hysky.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent;
+import de.hysky.skyblocker.skyblock.tabhud.widget.component.ProgressComponent;
+import de.hysky.skyblocker.utils.ItemUtils;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.item.ItemStack;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+import net.minecraft.util.math.MathHelper;
+
+import java.util.Map;
+
+public class FarmingHudWidget extends Widget {
+ private static final MutableText TITLE = Text.literal("Farming").formatted(Formatting.YELLOW, Formatting.BOLD);
+ private static final Map<String, ItemStack> FARMING_TOOLS = Map.ofEntries(
+ Map.entry("THEORETICAL_HOE_WHEAT_1", Ico.WHEAT),
+ Map.entry("THEORETICAL_HOE_WHEAT_2", Ico.WHEAT),
+ Map.entry("THEORETICAL_HOE_WHEAT_3", Ico.WHEAT),
+ Map.entry("THEORETICAL_HOE_CARROT_1", Ico.CARROT),
+ Map.entry("THEORETICAL_HOE_CARROT_2", Ico.CARROT),
+ Map.entry("THEORETICAL_HOE_CARROT_3", Ico.CARROT),
+ Map.entry("THEORETICAL_HOE_POTATO_1", Ico.POTATO),
+ Map.entry("THEORETICAL_HOE_POTATO_2", Ico.POTATO),
+ Map.entry("THEORETICAL_HOE_POTATO_3", Ico.POTATO),
+ Map.entry("THEORETICAL_HOE_CANE_1", Ico.SUGAR_CANE),
+ Map.entry("THEORETICAL_HOE_CANE_2", Ico.SUGAR_CANE),
+ Map.entry("THEORETICAL_HOE_CANE_3", Ico.SUGAR_CANE),
+ Map.entry("THEORETICAL_HOE_WARTs_1", Ico.NETHER_WART),
+ Map.entry("THEORETICAL_HOE_WARTs_2", Ico.NETHER_WART),
+ Map.entry("THEORETICAL_HOE_WARTs_3", Ico.NETHER_WART),
+ Map.entry("FUNGI_CUTTER", Ico.MUSHROOM),
+ Map.entry("CACTUS_KNIFE", Ico.CACTUS),
+ Map.entry("MELON_DICER", Ico.MELON),
+ Map.entry("PUMPKIN_DICER", Ico.PUMPKIN),
+ Map.entry("COCO_CHOPPER", Ico.COCOA_BEANS)
+ );
+ public static final FarmingHudWidget INSTANCE = new FarmingHudWidget();
+ private final MinecraftClient client = MinecraftClient.getInstance();
+
+ public FarmingHudWidget() {
+ super(TITLE, Formatting.YELLOW.getColorValue());
+ setX(SkyblockerConfigManager.get().locations.garden.farmingHud.x);
+ setY(SkyblockerConfigManager.get().locations.garden.farmingHud.y);
+ update();
+ }
+
+ @SuppressWarnings("DataFlowIssue")
+ @Override
+ public void updateContent() {
+ ItemStack icon = FARMING_TOOLS.getOrDefault(ItemUtils.getItemId(client.player.getMainHandStack()), Ico.HOE);
+ addSimpleIcoText(icon, "Counter: ", Formatting.YELLOW, FarmingHud.NUMBER_FORMAT.format(FarmingHud.counter()));
+ addSimpleIcoText(icon, "Crops/min: ", Formatting.YELLOW, FarmingHud.NUMBER_FORMAT.format((int) FarmingHud.cropsPerMinute() / 100 * 100));
+ addSimpleIcoText(icon, "Blocks/s: ", Formatting.YELLOW, Integer.toString(FarmingHud.blockBreaks()));
+ addComponent(new ProgressComponent(Ico.LANTERN, Text.literal("Farming Level: "), FarmingHud.farmingXpPercentProgress(), Formatting.GOLD.getColorValue()));
+ addSimpleIcoText(Ico.LIME_DYE, "Farming XP/h: ", Formatting.YELLOW, FarmingHud.NUMBER_FORMAT.format((int) FarmingHud.farmingXpPerHour()));
+
+ double yaw = client.getCameraEntity().getYaw();
+ double pitch = client.getCameraEntity().getPitch();
+ addComponent(new PlainTextComponent(Text.literal("Yaw: " + String.format("%.3f", MathHelper.wrapDegrees(yaw))).formatted(Formatting.YELLOW)));
+ addComponent(new PlainTextComponent(Text.literal("Pitch: " + String.format("%.3f", MathHelper.wrapDegrees(pitch))).formatted(Formatting.YELLOW)));
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
index 92e7e258..bde8b3ea 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
import java.text.NumberFormat;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
//TODO: check inventory items, sum all repeated items into one
@@ -111,7 +112,7 @@ public class VisitorHelper {
String itemName = splitItemText[0].trim();
if (itemName.isEmpty()) return;
try {
- int amount = splitItemText.length == 2 ? NumberFormat.getInstance().parse(splitItemText[1].trim()).intValue() : 1;
+ int amount = splitItemText.length == 2 ? NumberFormat.getInstance(Locale.US).parse(splitItemText[1].trim()).intValue() : 1;
Object2IntMap<String> visitorMap = itemMap.getOrDefault(visitorName, new Object2IntOpenHashMap<>());
visitorMap.putIfAbsent(itemName, amount);
itemMap.putIfAbsent(visitorName, visitorMap);