diff options
Diffstat (limited to 'src/main')
6 files changed, 177 insertions, 18 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 index db3bbadc..dba282c1 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java @@ -2,15 +2,116 @@ package de.hysky.skyblocker.skyblock.garden; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.tabhud.widget.hud.HudFarmingWidget; +import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Location; import de.hysky.skyblocker.utils.Utils; +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.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; 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,]+) \\w+"); + 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 (!SkyblockerConfigManager.get().locations.garden.farmingHud.enableHud || Utils.getLocation() != Location.GARDEN) return; - HudFarmingWidget.INSTANCE.render(context, SkyblockerConfigManager.get().general.tabHud.enableHudBackground); + 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); + } + } + + HudFarmingWidget.INSTANCE.update(); + HudFarmingWidget.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); + } + } + } + }); + } + + 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/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java index 4fd9eeb3..df8d1e70 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java @@ -26,6 +26,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 @@ -110,7 +111,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); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java index 96ab35d5..4872435b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java @@ -53,12 +53,23 @@ public class Ico { public static final ItemStack COMPOSTER = new ItemStack(Items.COMPOSTER); public static final ItemStack SAPLING = new ItemStack(Items.OAK_SAPLING); public static final ItemStack SEEDS = new ItemStack(Items.WHEAT_SEEDS); + public static final ItemStack WHEAT = new ItemStack(Items.WHEAT); + public static final ItemStack CARROT = new ItemStack(Items.CARROT); + public static final ItemStack POTATO = new ItemStack(Items.POTATO); + public static final ItemStack SUGAR_CANE = new ItemStack(Items.SUGAR_CANE); + public static final ItemStack NETHER_WART = new ItemStack(Items.NETHER_WART); + public static final ItemStack MUSHROOM = new ItemStack(Items.RED_MUSHROOM); + public static final ItemStack CACTUS = new ItemStack(Items.CACTUS); + public static final ItemStack MELON = new ItemStack(Items.MELON); + public static final ItemStack PUMPKIN = new ItemStack(Items.PUMPKIN); + public static final ItemStack COCOA_BEANS = new ItemStack(Items.COCOA_BEANS); public static final ItemStack MILESTONE = new ItemStack(Items.LODESTONE); public static final ItemStack PICKAXE = new ItemStack(Items.IRON_PICKAXE); public static final ItemStack NETHER_STAR = new ItemStack(Items.NETHER_STAR); public static final ItemStack HEART_OF_THE_SEA = new ItemStack(Items.HEART_OF_THE_SEA); public static final ItemStack EXPERIENCE_BOTTLE = new ItemStack(Items.EXPERIENCE_BOTTLE); public static final ItemStack PINK_DYE = new ItemStack(Items.PINK_DYE); + public static final ItemStack LIME_DYE = new ItemStack(Items.LIME_DYE); public static final ItemStack ENCHANTED_BOOK = new ItemStack(Items.ENCHANTED_BOOK); public static final ItemStack SPIDER_EYE = new ItemStack(Items.SPIDER_EYE); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java index 9cff3d32..9aa4a50e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java @@ -8,8 +8,7 @@ import net.minecraft.util.Formatting; import net.minecraft.util.math.MathHelper; public class CameraPositionWidget extends Widget { - private static final MutableText TITLE = Text.literal("Camera Pos").formatted(Formatting.DARK_PURPLE, - Formatting.BOLD); + private static final MutableText TITLE = Text.literal("Camera Pos").formatted(Formatting.DARK_PURPLE, Formatting.BOLD); private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); public CameraPositionWidget() { @@ -21,17 +20,7 @@ public class CameraPositionWidget extends Widget { double yaw = CLIENT.getCameraEntity().getYaw(); double pitch = CLIENT.getCameraEntity().getPitch(); - this.addComponent( - new PlainTextComponent(Text.literal("Yaw: " + roundToDecimalPlaces(MathHelper.wrapDegrees(yaw), 3)))); - this.addComponent(new PlainTextComponent( - Text.literal("Pitch: " + roundToDecimalPlaces(MathHelper.wrapDegrees(pitch), 3)))); - - } - - // https://stackoverflow.com/a/33889423 - private static double roundToDecimalPlaces(double value, int decimalPlaces) { - double shift = Math.pow(10, decimalPlaces); - - return Math.round(value * shift) / shift; + addComponent(new PlainTextComponent(Text.literal("Yaw: " + String.format("%.3f", MathHelper.wrapDegrees(yaw))))); + addComponent(new PlainTextComponent(Text.literal("Pitch: " + String.format("%.3f", MathHelper.wrapDegrees(pitch))))); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/hud/HudFarmingWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/hud/HudFarmingWidget.java index 4099f23e..b6ac25f8 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/hud/HudFarmingWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/hud/HudFarmingWidget.java @@ -1,22 +1,65 @@ package de.hysky.skyblocker.skyblock.tabhud.widget.hud; +import de.hysky.skyblocker.skyblock.garden.FarmingHud; 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 HudFarmingWidget 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 HudFarmingWidget INSTANCE = new HudFarmingWidget(); + private final MinecraftClient client = MinecraftClient.getInstance(); public HudFarmingWidget() { super(TITLE, Formatting.YELLOW.getColorValue()); update(); } + @SuppressWarnings("DataFlowIssue") @Override public void updateContent() { - addSimpleIcoText(Ico.HOE, "Farming ", Formatting.RESET, "Farming"); + 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.HOE, Text.literal("Farming Level: "), FarmingHud.farmingXpPercentProgress(), Formatting.YELLOW.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/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java index 880ebe76..70a8c241 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java +++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java @@ -25,6 +25,7 @@ import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.Predicate; +import java.util.regex.Matcher; import java.util.regex.Pattern; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; @@ -186,6 +187,19 @@ public class ItemUtils { return null; } + @Nullable + public static Matcher getNbtTooltip(ItemStack item, Pattern pattern) { + for (Text line : getNbtTooltips(item)) { + String string = line.getString(); + Matcher matcher = pattern.matcher(string); + if (matcher.matches()) { + return matcher; + } + } + + return null; + } + public static List<Text> getNbtTooltips(ItemStack item) { NbtCompound displayNbt = item.getSubNbt("display"); if (displayNbt == null || !displayNbt.contains("Lore", NbtElement.LIST_TYPE)) { |