diff options
Diffstat (limited to 'src/main')
21 files changed, 404 insertions, 245 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java index b60ae4d1..e9af52f6 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerInitializer.java @@ -4,6 +4,7 @@ import me.xmrvizzy.skyblocker.chat.ChatMessageListener; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.skyblock.HotbarSlotLock; import me.xmrvizzy.skyblocker.skyblock.api.StatsCommand; +import me.xmrvizzy.skyblocker.skyblock.dwarven.DwarvenHud; import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip; import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup; import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; @@ -19,6 +20,7 @@ public class SkyblockerInitializer implements ClientModInitializer { WikiLookup.init(); ItemRegistry.init(); StatsCommand.init(); + DwarvenHud.init(); ChatMessageListener.init(); UpdateChecker.init(); SkyblockerMod.getInstance().discordRPCManager.init(); diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java index f3c851f1..f729019f 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java @@ -3,6 +3,7 @@ package me.xmrvizzy.skyblocker; import me.xmrvizzy.skyblocker.container.ContainerSolverManager; import me.xmrvizzy.skyblocker.discord.DiscordRPCManager; import me.xmrvizzy.skyblocker.skyblock.BackpackPreview; +import me.xmrvizzy.skyblocker.skyblock.StatusBarTracker; import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonBlaze; import me.xmrvizzy.skyblocker.utils.Scheduler; import me.xmrvizzy.skyblocker.utils.Utils; @@ -14,6 +15,7 @@ public class SkyblockerMod { public final Scheduler scheduler = new Scheduler(); public final ContainerSolverManager containerSolverManager = new ContainerSolverManager(); public final DiscordRPCManager discordRPCManager = new DiscordRPCManager(); + public final StatusBarTracker statusBarTracker = new StatusBarTracker(); private SkyblockerMod() { scheduler.scheduleCyclic(Utils::sbChecker, 20); diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java index 1862313b..93e1d8e9 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java @@ -131,6 +131,17 @@ public class SkyblockerConfig implements ConfigData { public boolean enableDrillFuel = true; public boolean solveFetchur = true; public boolean solvePuzzler = true; + @ConfigEntry.Gui.CollapsibleObject(startExpanded = true) + public DwarvenHud dwarvenHud = new DwarvenHud(); + } + + public static class DwarvenHud { + public boolean enabled = true; + public boolean enableBackground = true; + @ConfigEntry.BoundedDiscrete(min = 3, max = 2000) + public int x = 10; + @ConfigEntry.BoundedDiscrete(min = 3, max = 2000) + public int y = 10; } public static class Messages { diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/ChatHudListenerMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/ChatHudListenerMixin.java index 2a9984b3..7e5411aa 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/ChatHudListenerMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/ChatHudListenerMixin.java @@ -33,9 +33,8 @@ public class ChatHudListenerMixin { switch (result) { case ACTION_BAR: ClientPlayerEntity player = client.player; - // Couldn't have received original message if client was null - assert player != null; - player.sendMessage(message, true); + if (player != null) + player.sendMessage(message, true); case FILTER: ci.cancel(); } diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java index b9e80bd6..9ceebf9f 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java @@ -5,6 +5,7 @@ import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.skyblock.FancyStatusBars; import me.xmrvizzy.skyblocker.skyblock.HotbarSlotLock; +import me.xmrvizzy.skyblocker.skyblock.StatusBarTracker; import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonMap; import me.xmrvizzy.skyblocker.utils.Utils; import net.fabricmc.api.EnvType; @@ -24,14 +25,12 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - @Environment(EnvType.CLIENT) @Mixin(InGameHud.class) public abstract class InGameHudMixin extends DrawableHelper { private static final Identifier SLOT_LOCK = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/slot_lock.png"); + private final StatusBarTracker statusBarTracker = SkyblockerMod.getInstance().statusBarTracker; private final FancyStatusBars statusBars = new FancyStatusBars(); private MatrixStack hotbarMatrices; private int hotbarSlotIndex; @@ -44,13 +43,21 @@ public abstract class InGameHudMixin extends DrawableHelper { @Shadow private int scaledWidth; + @Shadow + private void setOverlayMessage(Text message, boolean tinted) { + } + @Inject(method = "setOverlayMessage(Lnet/minecraft/text/Text;Z)V", at = @At("HEAD"), cancellable = true) private void onSetOverlayMessage(Text message, boolean tinted, CallbackInfo ci) { - if(!Utils.isOnSkyblock) + if (!Utils.isOnSkyblock || !SkyblockerConfig.get().general.bars.enableBars) return; String msg = message.getString(); - if(statusBars.update(msg)) + String res = statusBarTracker.update(msg, SkyblockerConfig.get().messages.hideMana); + if (msg != res) { + if (res != null) + setOverlayMessage(Text.of(res), tinted); ci.cancel(); + } } @Inject(method = "renderHotbar", at = @At("HEAD")) diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java index 75d232e9..c463ecb5 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FancyStatusBars.java @@ -7,164 +7,93 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - public class FancyStatusBars extends DrawableHelper { - private static final MinecraftClient client = MinecraftClient.getInstance(); private static final Identifier BARS = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/bars.png"); - private static final Pattern ACTION_BAR_MANA = Pattern.compile("§b-\\d+ Mana \\(.*\\) +"); - private static final Pattern ACTION_BAR_STATUS = Pattern.compile("^§[6c](\\d+)/(\\d+)❤(\\+§c\\d+.)?(?: +§a(\\d+)§a❈ Defense)?(?: +(\\S+(?:\\s\\S+)*))??(?: +§b(\\d+)/(\\d+)✎ +(?:Mana|§3(\\d+)ʬ))?(?: +(§[27].*))?$"); - - private final Resource[] resources = new Resource[]{ - // Health - new Resource(16733525), - // Mana - new Resource(5636095), - // Defense - new Resource(12106180), - // Experience - new Resource(8453920), - }; - - public boolean update(String actionBar) { - if (!SkyblockerConfig.get().general.bars.enableBars) { - if (SkyblockerConfig.get().messages.hideMana) { - Matcher mana = ACTION_BAR_MANA.matcher(actionBar); - if (mana.find()) { - assert client.player != null; - client.player.sendMessage(Text.of(actionBar.replace(mana.group(), "")), true); - return true; - } - } - return false; - } - - Matcher matcher = ACTION_BAR_STATUS.matcher(actionBar); - if (!matcher.matches()) - return false; - - resources[0].setMax(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2))); - if (matcher.group(4) != null) { - int def = Integer.parseInt(matcher.group(4)); - resources[2].setFillLevel(def, (double) def / ((double) def + 100D)); - } - if (matcher.group(6) != null) { - int m = Integer.parseInt(matcher.group(6)); - if (matcher.group(8) != null) - m += Integer.parseInt(matcher.group(8)); - resources[1].setMax(m, Integer.parseInt(matcher.group(7))); - } - assert client.player != null; - resources[3].setFillLevel(client.player.experienceLevel, client.player.experienceProgress); - StringBuilder sb = new StringBuilder(); - if (matcher.group(3) != null) { - sb.append("§c").append(matcher.group(3)); - } - if (SkyblockerConfig.get().messages.hideMana) { - Matcher mana = ACTION_BAR_MANA.matcher(actionBar); - if (!mana.find()) - appendIfNotNull(sb, matcher.group(5)); - } else { - appendIfNotNull(sb, matcher.group(5)); - } - appendIfNotNull(sb, matcher.group(9)); + private final MinecraftClient client = MinecraftClient.getInstance(); + private final StatusBarTracker statusBarTracker = SkyblockerMod.getInstance().statusBarTracker; - if (!sb.isEmpty()) { - assert client.player != null; - client.player.sendMessage(Text.of(sb.toString()), true); - } + private final StatusBar[] bars = new StatusBar[]{ + new StatusBar(0, 16733525, 2), + new StatusBar(1, 5636095, 2), + new StatusBar(2, 12106180, 1), + new StatusBar(3, 8453920, 1), + }; - return true; - } + private int left; + private int top; - private void appendIfNotNull(StringBuilder sb, String str) { - if (str == null) - return; - if (!sb.isEmpty()) - sb.append(" "); - sb.append(str); + private int fill(int value, int max) { + return (32 * value - 1) / max; } - private static final int BAR_SPACING = 46; - public boolean render(MatrixStack matrices, int scaledWidth, int scaledHeight) { - if (!SkyblockerConfig.get().general.bars.enableBars) + var player = client.player; + if (!SkyblockerConfig.get().general.bars.enableBars || player == null) return false; - int left = scaledWidth / 2 - 91; - int top = scaledHeight - 35; - RenderSystem.setShaderTexture(0, BARS); - for (int i = 0; i < 4; i++) { - this.drawTexture(matrices, left + i * BAR_SPACING, top, 0, 9 * i, 43, 9); - int fillCount = resources[i].getFillCount(); - for (int j = 0; j < fillCount; j++) { - this.drawTexture(matrices, left + 11 + i * BAR_SPACING, top, 43 + 31 * j, 9 * i, Resource.INNER_WIDTH, 9); - } - int fillLevel = resources[i].getFillLevel(); - if (0 < fillLevel) - this.drawTexture(matrices, left + 11 + i * BAR_SPACING, top, 43 + 31 * fillCount, 9 * i, fillLevel, 9); - } - for (int i = 0; i < 4; i++) { - renderText(matrices, resources[i].getValue(), left + 11 + i * BAR_SPACING, top, resources[i].getTextColor()); - } - return true; - } + left = scaledWidth / 2 - 91; + top = scaledHeight - 35; - private void renderText(MatrixStack matrices, int value, int left, int top, int color) { - TextRenderer textRenderer = client.textRenderer; - String text = Integer.toString(value); - int x = left + (33 - textRenderer.getWidth(text)) / 2; - int y = top - 3; + bars[0].update(statusBarTracker.getHealth()); + bars[1].update(statusBarTracker.getMana()); + int def = statusBarTracker.getDefense(); + bars[2].fill[0] = fill(def, def + 100); + bars[2].text = def; + bars[3].fill[0] = (int) (32 * player.experienceProgress); + bars[3].text = player.experienceLevel; - // for i in [-1, 1] - for (int i = -1; i < 2; i += 2) { - textRenderer.draw(matrices, text, (float) (x + i), (float) y, 0); - textRenderer.draw(matrices, text, (float) x, (float) (y + i), 0); - } - - textRenderer.draw(matrices, text, (float) x, (float) y, color); + RenderSystem.setShaderTexture(0, BARS); + for (var bar : bars) + bar.draw(matrices); + for (var bar : bars) + bar.drawText(matrices); + return true; } - private static class Resource { - static final int INNER_WIDTH = 31; - private int value; - private int fillLevel; - private final int textColor; - - public Resource(int textColor) { - this.value = 0; - this.fillLevel = INNER_WIDTH; - this.textColor = textColor; - } - - public void setMax(int value, int max) { - this.value = value; - this.fillLevel = value * INNER_WIDTH / max; - } - - public void setFillLevel(int value, double fillLevel) { - this.value = value; - this.fillLevel = (int) (INNER_WIDTH * fillLevel); - } - - public int getValue() { - return value; - } - - public int getFillCount() { - return fillLevel / INNER_WIDTH; - } - - public int getFillLevel() { - return fillLevel % INNER_WIDTH; - } - - public int getTextColor() { - return textColor; + private class StatusBar { + public final int[] fill; + private final int offsetX; + private final int v; + private final int text_color; + public Object text; + + private StatusBar(int i, int textColor, int fillNum) { + this.offsetX = i * 46; + this.v = i * 9; + this.text_color = textColor; + this.fill = new int[fillNum]; + this.fill[0] = 33; + this.text = ""; + } + + public void update(StatusBarTracker.Resource resource) { + int max = resource.max(); + int val = resource.value(); + this.fill[0] = fill(val, max); + this.fill[1] = fill(resource.overflow(), max); + this.text = val; + } + + public void draw(MatrixStack matrices) { + drawTexture(matrices, left + offsetX, top, 0, v, 43, 9); + for (int i = 0; i < fill.length; i++) + drawTexture(matrices, left + offsetX + 11, top, 43 + i * 31, v, fill[i], 9); + } + + public void drawText(MatrixStack matrices) { + TextRenderer textRenderer = client.textRenderer; + String text = this.text.toString(); + int x = left + this.offsetX + 11 + (33 - textRenderer.getWidth(text)) / 2; + int y = top - 3; + + final int[] offsets = new int[]{-1, 1}; + for (int i : offsets) { + textRenderer.draw(matrices, text, (float) (x + i), (float) y, 0); + textRenderer.draw(matrices, text, (float) x, (float) (y + i), 0); + } + textRenderer.draw(matrices, text, (float) x, (float) y, text_color); } } -}
\ No newline at end of file +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/StatusBarTracker.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/StatusBarTracker.java new file mode 100644 index 00000000..0111f75a --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/StatusBarTracker.java @@ -0,0 +1,110 @@ +package me.xmrvizzy.skyblocker.skyblock; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StatusBarTracker { + private static final Pattern STATUS_HEALTH = Pattern.compile("§[6c](\\d+)/(\\d+)❤(?:(\\+§c\\d+. *)| *)"); + private static final Pattern DEFENSE_STATUS = Pattern.compile("§a(\\d+)§a❈ Defense *"); + private static final Pattern MANA_USE = Pattern.compile("§b-\\d+ Mana \\(§\\S+(?:\\s\\S+)* *"); + private static final Pattern MANA_STATUS = Pattern.compile("§b(\\d+)/(\\d+)✎ (?:Mana|§3(\\d+)ʬ) *"); + + private Resource health = new Resource(100, 100, 0); + private Resource mana = new Resource(100, 100, 0); + private int defense = 0; + + public Resource getHealth() { + return this.health; + } + + public Resource getMana() { + return this.mana; + } + + public int getDefense() { + return this.defense; + } + + private int parseInt(Matcher m, int group) { + return Integer.parseInt(m.group(group)); + } + + private void updateMana(Matcher m) { + int value = parseInt(m, 1); + int max = parseInt(m, 2); + int overflow = m.group(3) == null ? 0 : parseInt(m, 3); + this.mana = new Resource(value, max, overflow); + } + + private void updateHealth(Matcher m) { + int value = parseInt(m, 1); + int max = parseInt(m, 2); + int overflow = 0; + ClientPlayerEntity player = null; + try { + player = MinecraftClient.getInstance().player; + } + // Is triggered by tests. Couldn't come up with a better solution. + catch (NullPointerException ignored) { + } + if (player != null) { + int hp = (int) (player.getHealth() * max / player.getMaxHealth()); + overflow = value - hp; + value = hp; + } else if (value > max) { + overflow = value - max; + value = max; + } + if (overflow > max) + overflow = max; + this.health = new Resource(value, max, overflow); + } + + private String reset(String str, Matcher m) { + str = str.substring(m.end()); + m.reset(str); + return str; + } + + public String update(String actionBar, boolean filterManaUse) { + var sb = new StringBuilder(); + Matcher matcher = STATUS_HEALTH.matcher(actionBar); + if (!matcher.lookingAt()) + return actionBar; + updateHealth(matcher); + if (matcher.group(3) != null) { + sb.append("§c❤"); + sb.append(matcher.group(3)); + } + actionBar = reset(actionBar, matcher); + if (matcher.usePattern(MANA_STATUS).lookingAt()) { + defense = 0; + updateMana(matcher); + actionBar = reset(actionBar, matcher); + } else { + if (matcher.usePattern(DEFENSE_STATUS).lookingAt()) { + defense = parseInt(matcher, 1); + actionBar = reset(actionBar, matcher); + } else if (filterManaUse && matcher.usePattern(MANA_USE).lookingAt()) { + actionBar = reset(actionBar, matcher); + } + if (matcher.usePattern(MANA_STATUS).find()) { + updateMana(matcher); + matcher.appendReplacement(sb, ""); + } + } + matcher.appendTail(sb); + String res = sb.toString().trim(); + return res.isEmpty() ? null : res; + } + + public record Resource( + int value, + int max, + int overflow + ) { + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java index 1b87925c..4554372b 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonBlaze.java @@ -7,6 +7,7 @@ import me.xmrvizzy.skyblocker.utils.RenderUtils; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.util.math.Box; import org.slf4j.Logger; @@ -19,15 +20,14 @@ public class DungeonBlaze { static boolean renderHooked = false; public static void update() { - if (!Utils.isInDungeons) return; - MinecraftClient client = MinecraftClient.getInstance(); + ClientWorld world = MinecraftClient.getInstance().world; + if (world == null || !Utils.isInDungeons) return; if(!renderHooked){ WorldRenderEvents.END.register(DungeonBlaze::blazeRenderer); renderHooked = true; } - assert client.world != null; - Iterable<Entity> entities = client.world.getEntities(); + Iterable<Entity> entities = world.getEntities(); int highestHealth = 0; int lowestHealth = 99999999; diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Reparty.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Reparty.java index f5fd1151..c3da7c18 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Reparty.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Reparty.java @@ -27,9 +27,8 @@ public class Reparty extends ChatPatternListener { repartying = false; ClientCommandManager.DISPATCHER.register( ClientCommandManager.literal("rp").executes(context -> { - if (!Utils.isOnSkyblock || repartying) + if (!Utils.isOnSkyblock || repartying || client.player == null) return 0; - assert client.player != null; repartying = true; client.player.sendChatMessage("/p list"); return 0; @@ -63,7 +62,10 @@ public class Reparty extends ChatPatternListener { private void reparty() { ClientPlayerEntity playerEntity = client.player; - assert playerEntity != null; + if (playerEntity == null) { + repartying = false; + return; + } sendCommand(playerEntity, "/p disband", 1); StringBuilder sb = new StringBuilder(); int invites = (players.length - 1) / 5 + 1; diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/ThreeWeirdos.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/ThreeWeirdos.java index 8f1f3711..da964f07 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/ThreeWeirdos.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/ThreeWeirdos.java @@ -23,17 +23,13 @@ public class ThreeWeirdos extends ChatPatternListener { @Override public boolean onMatch(Text message, Matcher matcher) { MinecraftClient client = MinecraftClient.getInstance(); - assert client.world != null; - assert client.player != null; + if (client.player == null || client.world == null) return false; client.world.getEntitiesByClass( ArmorStandEntity.class, client.player.getBoundingBox().expand(3), entity -> { Text customName = entity.getCustomName(); - if (customName != null && customName.getString().equals(matcher.group(1))) { - return true; - } - return false; + return customName != null && customName.getString().equals(matcher.group(1)); } ).forEach( entity -> entity.setCustomName(Text.of(Formatting.GREEN + matcher.group(1))) diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java index 51ff1c6a..673797d4 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/Trivia.java @@ -31,9 +31,9 @@ public class Trivia extends ChatPatternListener { if (riddle != null) { if (!solutions.contains(riddle)) { ClientPlayerEntity player = MinecraftClient.getInstance().player; - assert player != null; - MinecraftClient.getInstance().player.sendMessage(new LiteralText(" " + Formatting.GOLD + matcher.group(2) + Formatting.RED + " " + riddle), false); - return true; + if (player != null) + MinecraftClient.getInstance().player.sendMessage(new LiteralText(" " + Formatting.GOLD + matcher.group(2) + Formatting.RED + " " + riddle), false); + return player != null; } } else updateSolutions(matcher.group(0)); diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java new file mode 100644 index 00000000..0c614641 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java @@ -0,0 +1,75 @@ +package me.xmrvizzy.skyblocker.skyblock.dwarven; + +import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class DwarvenHud { + + + public static MinecraftClient client = MinecraftClient.getInstance(); + + public static final List<Pattern> COMMISSIONS = List.of( + "(?:Titanium|Mithril|Hard Stone) Miner", + "(?:Ice Walker|Goblin|Goblin Raid|Automaton|Sludge|Team Treasuite Member|Yog|Boss Corleone|Thyst) Slayer", + "(?:Lava Springs|Cliffside Veins|Rampart's Quarry|Upper Mines|Royal Mines) Mithril", + "(?:Lava Springs|Cliffside Veins|Rampart's Quarry|Upper Mines|Royal Mines) Titanium", + "Goblin Raid", + "(?:Powder Ghast|Star Sentry) Puncher", + "(?<!Lucky )Raffle", + "Lucky Raffle", + "2x Mithril Powder Collector", + "(?:Ruby|Amber|Sapphire|Jade|Amethyst|Topaz) Gemstone Collector", + "(?:Amber|Sapphire|Jade|Amethyst|Topaz) Crystal Hunter", + "Chest Looter" + ).stream().map(s -> Pattern.compile("^.*(" + s + "): (\\d+\\.?\\d*%|DONE)")) + .collect(Collectors.toList()); + public static void init(){ + HudRenderCallback.EVENT.register((matrixStack, tickDelta) -> { + if (SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enabled) { + int hudX = SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.x; + int hudY = SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.y; + List<Commission> commissions = new ArrayList<>(); + client.getNetworkHandler().getPlayerList().forEach(playerListEntry -> { + if (playerListEntry.getDisplayName() != null) { + for (Pattern pattern : COMMISSIONS) { + Matcher matcher = pattern.matcher(playerListEntry.getDisplayName().getString()); + if (matcher.find()) { + commissions.add(new Commission(matcher.group(1), matcher.group(2))); + } + + } + } + }); + if (commissions.size() > 0){ + if (SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enableBackground) + DrawableHelper.fill(matrixStack, hudX, hudY, hudX + 200, hudY + (20 * commissions.size()), 0x64000000); + int y = 0; + for (Commission commission : commissions) { + client.textRenderer.drawWithShadow(matrixStack, new LiteralText(commission.commission).styled(style -> style.withColor(Formatting.AQUA)).append(new LiteralText(": " + commission.progression).styled(style -> style.withColor(Formatting.GREEN))), hudX + 5, hudY + y + 5, 0xFFFFFFFF); + y += 20; + } + } + } + }); + } + + public static class Commission{ + String commission; + String progression; + + public Commission(String commission, String progression){ + this.commission = commission; + this.progression = progression; + } + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Fetchur.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Fetchur.java index ce1dde11..ccd47c5a 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Fetchur.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Fetchur.java @@ -26,7 +26,7 @@ public class Fetchur extends ChatPatternListener { @Override public boolean onMatch(Text message, Matcher matcher) { MinecraftClient client = MinecraftClient.getInstance(); - assert client.player != null; + if (client.player == null) return false; String riddle = matcher.group(1); String answer = answers.getOrDefault(riddle, riddle); client.player.sendMessage(Text.of("§e[NPC] Fetchur§f: " + answer), false); diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Puzzler.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Puzzler.java index f61e007e..06395898 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Puzzler.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/Puzzler.java @@ -32,8 +32,8 @@ public class Puzzler extends ChatPatternListener { else if (c == '▶') x--; } ClientWorld world = MinecraftClient.getInstance().world; - assert world != null; - world.setBlockStateWithoutNeighborUpdates(new BlockPos(x, 195, z), Blocks.CRIMSON_PLANKS.getDefaultState()); + if (world != null) + world.setBlockStateWithoutNeighborUpdates(new BlockPos(x, 195, z), Blocks.CRIMSON_PLANKS.getDefaultState()); return false; } }
\ No newline at end of file diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/PriceInfoTooltip.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/PriceInfoTooltip.java index 290bd0ae..3a5980f0 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/PriceInfoTooltip.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/PriceInfoTooltip.java @@ -49,6 +49,7 @@ public class PriceInfoTooltip { int count = stack.getCount(); String timestamp = getTimestamp(stack); + boolean bazaarOpened = lines.stream().anyMatch(each -> each.getString().contains("Buy price:") || each.getString().contains("Sell price:")); if (SkyblockerConfig.get().general.itemTooltip.enableNPCPrice) { if (npcPricesJson == null) { @@ -63,7 +64,31 @@ public class PriceInfoTooltip { } } - if (SkyblockerConfig.get().general.itemTooltip.enableLowestBIN) { + boolean bazaarExist = false; + if (SkyblockerConfig.get().general.itemTooltip.enableBazaarPrice && !bazaarOpened) { + if (bazaarPricesJson == null) { + if (!nullMsgSend) { + client.player.sendMessage(new TranslatableText("skyblocker.itemTooltip.nullMessage"), false); + nullMsgSend = true; + } + } else if (bazaarPricesJson.has(name)) { + JsonObject getItem = bazaarPricesJson.getAsJsonObject(name); + lines.add(new LiteralText(String.format("%-18s", "Bazaar buy Price:")) + .formatted(Formatting.GOLD) + .append(getItem.get("buyPrice").isJsonNull() + ? new LiteralText("No data").formatted(Formatting.RED) + : getCoinsMessage(getItem.get("buyPrice").getAsDouble(), count))); + lines.add(new LiteralText(String.format("%-19s", "Bazaar sell Price:")) + .formatted(Formatting.GOLD) + .append(getItem.get("sellPrice").isJsonNull() + ? new LiteralText("No data").formatted(Formatting.RED) + : getCoinsMessage(getItem.get("sellPrice").getAsDouble(), count))); + bazaarExist = true; + } + } + + // bazaarOpened & bazaarExist check for lbin, because Skytils keeps some bazaar item data in lbin api + if (SkyblockerConfig.get().general.itemTooltip.enableLowestBIN && !bazaarOpened && !bazaarExist) { if (lowestPricesJson == null) { if (!nullMsgSend) { client.player.sendMessage(new TranslatableText("skyblocker.itemTooltip.nullMessage"), false); @@ -110,49 +135,23 @@ public class PriceInfoTooltip { // "No data" line because of API not keeping old data, it causes NullPointerException if (!name.isEmpty() && (type == SkyblockerConfig.Average.ONE_DAY || type == SkyblockerConfig.Average.BOTH)) { - if (oneDayAvgPricesJson.get(name) != null) { - lines.add(new LiteralText(String.format("%-19s", "1 Day Avg. Price:")) - .formatted(Formatting.GOLD) - .append(getCoinsMessage(oneDayAvgPricesJson.get(name).getAsDouble(), count))); - } else { - lines.add(new LiteralText(String.format("%-19s", "1 Day Avg. Price:")) - .formatted(Formatting.GOLD) - .append(new LiteralText("No data").formatted(Formatting.RED))); - } + lines.add(new LiteralText(String.format("%-19s", "1 Day Avg. Price:")) + .formatted(Formatting.GOLD) + .append(oneDayAvgPricesJson.get(name) == null + ? new LiteralText("No data").formatted(Formatting.RED) + : getCoinsMessage(oneDayAvgPricesJson.get(name).getAsDouble(), count))); } if (!name.isEmpty() && (type == SkyblockerConfig.Average.THREE_DAY || type == SkyblockerConfig.Average.BOTH)) { - if (threeDayAvgPricesJson.get(name) != null) { - lines.add(new LiteralText(String.format("%-19s", "3 Day Avg. Price:")) - .formatted(Formatting.GOLD) - .append(getCoinsMessage(threeDayAvgPricesJson.get(name).getAsDouble(), count))); - } else { - lines.add(new LiteralText(String.format("%-19s", "3 Day Avg. Price:")) - .formatted(Formatting.GOLD) - .append(new LiteralText("No data").formatted(Formatting.RED))); - } + lines.add(new LiteralText(String.format("%-19s", "3 Day Avg. Price:")) + .formatted(Formatting.GOLD) + .append(threeDayAvgPricesJson.get(name) == null + ? new LiteralText("No data").formatted(Formatting.RED) + : getCoinsMessage(threeDayAvgPricesJson.get(name).getAsDouble(), count))); } } } - if (SkyblockerConfig.get().general.itemTooltip.enableBazaarPrice - && lines.stream().noneMatch(each -> each.getString().contains("Buy price:") || each.getString().contains("Sell price:"))) { - if (bazaarPricesJson == null) { - if (!nullMsgSend) { - client.player.sendMessage(new TranslatableText("skyblocker.itemTooltip.nullMessage"), false); - nullMsgSend = true; - } - } else if (bazaarPricesJson.has(name)) { - JsonObject getItem = bazaarPricesJson.getAsJsonObject(name); - lines.add(new LiteralText(String.format("%-18s", "Bazaar buy Price:")) - .formatted(Formatting.GOLD) - .append(getCoinsMessage(getItem.get("buyPrice").getAsDouble(), count))); - lines.add(new LiteralText(String.format("%-19s", "Bazaar sell Price:")) - .formatted(Formatting.GOLD) - .append(getCoinsMessage(getItem.get("sellPrice").getAsDouble(), count))); - } - } - - if (SkyblockerConfig.get().general.itemTooltip.enableMuseumDate) { + if (SkyblockerConfig.get().general.itemTooltip.enableMuseumDate && !bazaarOpened) { if (isMuseumJson == null) { if (!nullMsgSend) { client.player.sendMessage(new TranslatableText("skyblocker.itemTooltip.nullMessage"), false); @@ -252,9 +251,16 @@ public class PriceInfoTooltip { } } - public static int minute = 0; + // If these options is true beforehand, the client will get first data of these options while loading. + // After then, it will only fetch the data if it is on Skyblock. + public static int minute = -1; public static void init() { skyblocker.scheduler.scheduleCyclic(() -> { + if (!Utils.isOnSkyblock && 0 < minute++) { + nullMsgSend = false; + return; + } + List<CompletableFuture<Void>> futureList = new ArrayList<>(); if ((SkyblockerConfig.get().general.itemTooltip.enableAvgBIN) && (oneDayAvgPricesJson == null || threeDayAvgPricesJson == null || minute % 5 == 0)) { SkyblockerConfig.Average type = SkyblockerConfig.get().general.itemTooltip.avg; diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java index c664bb9e..17e9aebc 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java @@ -2,22 +2,24 @@ package me.xmrvizzy.skyblocker.skyblock.itemlist; import com.google.gson.JsonObject; import com.google.gson.JsonParser; + +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.errors.GitAPIException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; -import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.*; public class ItemRegistry { - protected static final String REMOTE_ITEM_REPO_DIR = "https://github.com/KonaeAkira/NotEnoughUpdates-REPO.git"; - protected static final String LOCAL_ITEM_REPO_DIR = "./config/skyblocker/items-repo/"; + protected static final String REMOTE_ITEM_REPO = "https://github.com/KonaeAkira/NotEnoughUpdates-REPO.git"; + protected static final Path LOCAL_ITEM_REPO_DIR = FabricLoader.getInstance().getConfigDir().resolve("skyblocker/item-repo"); - private static final String ITEM_LIST_DIR = LOCAL_ITEM_REPO_DIR + "items/"; + private static final Path ITEM_LIST_DIR = LOCAL_ITEM_REPO_DIR.resolve("items"); protected static List<ItemStack> items = new ArrayList<>(); protected static Map<String, ItemStack> itemsMap = new HashMap<>(); @@ -31,21 +33,21 @@ public class ItemRegistry { } private static void updateItemRepo() { - if (!Files.isDirectory(Paths.get(LOCAL_ITEM_REPO_DIR))) { + if (!Files.isDirectory(LOCAL_ITEM_REPO_DIR)) { try { Git.cloneRepository() - .setURI(REMOTE_ITEM_REPO_DIR) - .setDirectory(new File(LOCAL_ITEM_REPO_DIR)) + .setURI(REMOTE_ITEM_REPO) + .setDirectory(LOCAL_ITEM_REPO_DIR.toFile()) .setBranchesToClone(List.of("refs/heads/master")) .setBranch("refs/heads/master") .call(); - } catch (GitAPIException e) { + } catch (Exception e) { e.printStackTrace(); } } else { try { - Git.open(new File(LOCAL_ITEM_REPO_DIR)).pull().call(); - } catch (GitAPIException | IOException e) { + Git.open(LOCAL_ITEM_REPO_DIR.toFile()).pull().call(); + } catch (Exception e) { e.printStackTrace(); } } @@ -54,16 +56,15 @@ public class ItemRegistry { private static void importItemFiles() { List<JsonObject> jsonObjs = new ArrayList<>(); - File dir = new File(ITEM_LIST_DIR); + File dir = ITEM_LIST_DIR.toFile(); File[] files = dir.listFiles(); assert files != null; for (File file : files) { - String path = ITEM_LIST_DIR + "/" + file.getName(); + Path path = ITEM_LIST_DIR.resolve(file.getName()); try { - String fileContent = Files.readString(Paths.get(path)); + String fileContent = Files.readString(path); jsonObjs.add(JsonParser.parseString(fileContent).getAsJsonObject()); - } catch (IOException e) { - System.err.println("Couldn't import " + path); + } catch (Exception e) { e.printStackTrace(); } } @@ -110,6 +111,7 @@ public class ItemRegistry { } class Recipe { + private static final Logger LOGGER = LoggerFactory.getLogger(Recipe.class); String text = ""; List<ItemStack> grid = new ArrayList<>(9); ItemStack result; @@ -131,12 +133,17 @@ class Recipe { } private static ItemStack getItemStack(String internalName) { - if (internalName.length() > 0) { - int count = Integer.parseInt(internalName.split(":")[1]); - internalName = internalName.split(":")[0]; - ItemStack itemStack = ItemRegistry.itemsMap.get(internalName).copy(); - itemStack.setCount(count); - return itemStack; + try { + if (internalName.length() > 0) { + int count = Integer.parseInt(internalName.split(":")[1]); + internalName = internalName.split(":")[0]; + ItemStack itemStack = ItemRegistry.itemsMap.get(internalName).copy(); + itemStack.setCount(count); + return itemStack; + } + } + catch(Exception e) { + LOGGER.error("[Skyblocker-Recipe] "+internalName,e); } return Items.AIR.getDefaultStack(); } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemStackBuilder.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemStackBuilder.java index b7a6e919..f21c7ccb 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemStackBuilder.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemStackBuilder.java @@ -9,21 +9,20 @@ import net.minecraft.nbt.*; import net.minecraft.text.Text; import net.minecraft.util.Pair; -import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ItemStackBuilder { - private final static String PETNUMS_PATH = ItemRegistry.LOCAL_ITEM_REPO_DIR + "constants/petnums.json"; + private final static Path PETNUMS_PATH = ItemRegistry.LOCAL_ITEM_REPO_DIR.resolve("constants/petnums.json"); private static JsonObject petNums; public static void init() { try { - petNums = JsonParser.parseString(Files.readString(Paths.get(PETNUMS_PATH))).getAsJsonObject(); - } catch (IOException e) { + petNums = JsonParser.parseString(Files.readString(PETNUMS_PATH)).getAsJsonObject(); + } catch (Exception e) { e.printStackTrace(); } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java index 0fdf4892..16e5b023 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java @@ -1,8 +1,12 @@ package me.xmrvizzy.skyblocker.utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.PriorityQueue; public class Scheduler { + private static final Logger LOGGER = LoggerFactory.getLogger(Scheduler.class); private int currentTick; private final PriorityQueue<ScheduledTask> tasks; @@ -12,21 +16,25 @@ public class Scheduler { } public void schedule(Runnable task, int delay) { - assert delay > 0; + if (delay < 0) + LOGGER.warn("Scheduled a task with negative delay"); ScheduledTask tmp = new ScheduledTask(currentTick + delay, task); tasks.add(tmp); } public void scheduleCyclic(Runnable task, int period) { - new CyclicTask(task, period).run(); + if (period <= 0) + LOGGER.error("Attempted to schedule a cyclic task with period lower than 1"); + else + new CyclicTask(task, period).run(); } public void tick() { currentTick += 1; ScheduledTask task; while ((task = tasks.peek()) != null && task.schedule <= currentTick) { - task.run(); tasks.poll(); + task.run(); } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java index 4551564d..46f3a7e1 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java @@ -3,6 +3,7 @@ package me.xmrvizzy.skyblocker.utils; import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip; import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.ScoreboardObjective; import net.minecraft.scoreboard.ScoreboardPlayerScore; @@ -106,7 +107,8 @@ public class Utils { public static List<String> getSidebar() { try { - assert MinecraftClient.getInstance().player != null; + ClientPlayerEntity client = MinecraftClient.getInstance().player; + if (client == null) return Collections.emptyList(); Scoreboard scoreboard = MinecraftClient.getInstance().player.getScoreboard(); ScoreboardObjective objective = scoreboard.getObjectiveForSlot(1); List<String> lines = new ArrayList<>(); diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index 91b2cf28..0b148a91 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -46,6 +46,11 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.enableDrillFuel": "Enable Drill Fuel", "text.autoconfig.skyblocker.option.locations.dwarvenMines.solveFetchur": "Solve Fetchur", "text.autoconfig.skyblocker.option.locations.dwarvenMines.solvePuzzler": "Solve Puzzler Puzzle", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud": "Dwarven HUD", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enabled": "Enabled", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Enable Background", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.x": "X", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.y": "Y", "text.autoconfig.skyblocker.category.messages": "Messages", "text.autoconfig.skyblocker.option.messages.hideAbility": "Hide Ability Cooldown", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index c5d30d73..6358a234 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -5,12 +5,11 @@ "name": "Skyblocker", "description": "Hypixel Skyblock Mod", "authors": ["xMrVizzy", "d3dx9", "LifeIsAParadox"], - "contributors": ["ExternalTime", "Zailer43", "TacoMonkey", "KonaeAkira", "Fix3dll"], - "translators" : ["null2264", "HyperSoop", "edgarogh"], + "contributors": ["ExternalTime", "Zailer43", "TacoMonkey", "KonaeAkira", "Fix3dll", "null2264", "HyperSoop", "edgarogh"], "contact": { "homepage": "https://hysky.de", - "sources": "https://github.com/LifeIsAParadox/Skyblocker", - "issues": "https://github.com/LifeIsAParadox/Skyblocker/issues" + "sources": "https://github.com/SkyblockerMod/Skyblocker", + "issues": "https://github.com/SkyblockerMod/Skyblocker/issues" }, "license": "GNU LGPLv3", "icon": "assets/skyblocker/icon.png", |