Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the powder widget to also display the diff #1103

Merged
merged 1 commit into from
Dec 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,39 +1,119 @@
package de.hysky.skyblocker.skyblock.tabhud.widget;


import de.hysky.skyblocker.annotations.RegisterWidget;
import de.hysky.skyblocker.skyblock.tabhud.util.Ico;
import de.hysky.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent;
import de.hysky.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Util;
import org.apache.commons.lang3.math.NumberUtils;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

// this widget shows how much mithril and gemstone powder you have
// (dwarven mines and crystal hollows)
@RegisterWidget
public class PowderWidget extends TabHudWidget {
private static final MutableText TITLE = Text.literal("Powders").formatted(Formatting.DARK_AQUA, Formatting.BOLD);
private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
private static final short UPDATE_INTERVAL = 2000;

static {
DECIMAL_FORMAT.setPositivePrefix("+"); // Causes the positive sign to be displayed for positive numbers, while the negative sign is always displayed for negative numbers. This removes the need to prepend a + if positive.
}

private static final MutableText TITLE = Text.literal("Powders").formatted(Formatting.DARK_AQUA,
Formatting.BOLD);
// Patterns to match the playerlist lines against
private static final Pattern MITHRIL_PATTERN = Pattern.compile("Mithril: ([\\d,]+)");
private static final Pattern GEMSTONE_PATTERN = Pattern.compile("Gemstone: ([\\d,]+)");
private static final Pattern GLACITE_PATTERN = Pattern.compile("Glacite: ([\\d,]+)");
// Amounts from last update
private int lastMithril = 0;
private int lastGemstone = 0;
private int lastGlacite = 0;
// The amount difference between the 2nd last and last update
private int lastMithrilDiff = 0;
private int lastGemstoneDiff = 0;
private int lastGlaciteDiff = 0;
// A bitfield to keep track of which powders have been updated.
// First 3 bits represent mithril, gemstone and glacite respectively, with 1 being found and 0 being not found.
// The 4th bit is for whether the current tick caused an update, which will change the value of lastUpdate when 1.
private byte updated = 0b0000;
private long lastUpdate = 0;

public PowderWidget() {
super("Powders", TITLE, Formatting.DARK_AQUA.getColorValue());
}

@Override
public void updateContent(List<Text> lines) {
Matcher matcher = Pattern.compile("").matcher(""); // Placeholder pattern and input to construct a matcher that can be reused
long msAfterLastUpdate = Util.getMeasuringTimeMs() - lastUpdate;

for (Text line : lines) {
switch (line.getString().toLowerCase()) {
case String s when s.contains("mithril") -> this.addComponent(new IcoTextComponent(Ico.MITHRIL, line));
case String s when s.contains("gemstone") -> this.addComponent(new IcoTextComponent(Ico.AMETHYST_SHARD, line));
case String s when s.contains("glacite") -> this.addComponent(new IcoTextComponent(Ico.BLUE_ICE, line));
default -> this.addComponent(new PlainTextComponent(line));
switch (matcher.reset(line.getString())) {
case Matcher m when m.usePattern(MITHRIL_PATTERN).matches() -> {
int mithril = parseAmount(m);
// Generally this will only work if the update interval has passed, but we also don't want to stall the update if the amount has changed
if (mithril != lastMithril || msAfterLastUpdate > UPDATE_INTERVAL) {
lastMithrilDiff = mithril - lastMithril;
updated |= 0b1000;
addComponent(new IcoTextComponent(Ico.MITHRIL, getTextToDisplay(lastMithrilDiff, line, Formatting.DARK_GREEN)));
lastMithril = mithril;
} else {
addComponent(new IcoTextComponent(Ico.MITHRIL, getTextToDisplay(lastMithrilDiff, line, Formatting.DARK_GREEN)));
}
updated |= 0b001;
}
case Matcher m when m.usePattern(GEMSTONE_PATTERN).matches() -> {
int gemstone = parseAmount(m);
// Generally this will only work if the update interval has passed, but we also don't want to stall the update if the amount has changed
if (gemstone != lastGemstone || msAfterLastUpdate > UPDATE_INTERVAL) {
lastGemstoneDiff = gemstone - lastGemstone;
updated |= 0b1000;
addComponent(new IcoTextComponent(Ico.AMETHYST_SHARD, getTextToDisplay(lastGemstoneDiff, line, Formatting.LIGHT_PURPLE)));
lastGemstone = gemstone;
} else {
addComponent(new IcoTextComponent(Ico.AMETHYST_SHARD, getTextToDisplay(lastGemstoneDiff, line, Formatting.LIGHT_PURPLE)));
}
updated |= 0b010;
}
case Matcher m when m.usePattern(GLACITE_PATTERN).matches() -> {
int glacite = parseAmount(m);
// Generally this will only work if the update interval has passed, but we also don't want to stall the update if the amount has changed
if (glacite != lastGlacite || msAfterLastUpdate > UPDATE_INTERVAL) {
lastGlaciteDiff = glacite - lastGlacite;
updated |= 0b1000;
addComponent(new IcoTextComponent(Ico.BLUE_ICE, getTextToDisplay(lastGlaciteDiff, line, Formatting.AQUA)));
lastGlacite = glacite;
} else {
addComponent(new IcoTextComponent(Ico.BLUE_ICE, getTextToDisplay(lastGlaciteDiff, line, Formatting.AQUA)));
}
updated |= 0b100;
}
default -> {}
}
if ((updated & 0b111) == 0b111) break; // All powder counts have been updated, no need to continue
}
if ((updated & 0b1000) == 0b1000) lastUpdate = Util.getMeasuringTimeMs();
updated = 0b0000; // Reset the bitfield for the next tick
}

private int parseAmount(Matcher matcher) {
return NumberUtils.toInt(matcher.group(1).replace(",", ""));
}

private MutableText getAppendix(int diff, Formatting formatting) {
return Text.literal(" (" + DECIMAL_FORMAT.format(diff) + ")").formatted(formatting);
}

// Decides whether the appendix should be appended to the line
private Text getTextToDisplay(int diff, Text line, Formatting formatting) {
return diff != 0 ? line.copy().append(getAppendix(diff, formatting)) : line;
}
}
Loading