diff options
author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2023-06-09 16:08:04 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-09 16:08:04 -0400 |
commit | 2adaeb8c54ddffd4cdd6b5a58497a876ed0d97dd (patch) | |
tree | f3f30d0543c6ae18ed110bd934aa54458a315dd1 /src/main/java/me | |
parent | cf15ad24aa5a2c766589ad9fc3a118b3bf1f6cb1 (diff) | |
parent | 9b93e87859276cd7e37de0b6b02ca27c27228b87 (diff) | |
download | Skyblocker-2adaeb8c54ddffd4cdd6b5a58497a876ed0d97dd.tar.gz Skyblocker-2adaeb8c54ddffd4cdd6b5a58497a876ed0d97dd.tar.bz2 Skyblocker-2adaeb8c54ddffd4cdd6b5a58497a876ed0d97dd.zip |
Merge pull request #137 from msg-programs/skyhytab
Replace tab/playerlist HUD with a more fancy version
Diffstat (limited to 'src/main/java/me')
73 files changed, 3644 insertions, 20 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java index 2ab1b45e..e0f950d0 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java @@ -17,6 +17,8 @@ import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip; import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup; import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; import me.xmrvizzy.skyblocker.skyblock.quicknav.QuickNav; +import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; import me.xmrvizzy.skyblocker.utils.MessageScheduler; import me.xmrvizzy.skyblocker.utils.Scheduler; import me.xmrvizzy.skyblocker.utils.UpdateChecker; @@ -26,7 +28,9 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.MinecraftClient; /** - * Main class for Skyblocker which initializes features, registers events, and manages ticks. This class will be instantiated by Fabric. Do not instantiate this class. + * Main class for Skyblocker which initializes features, registers events, and + * manages ticks. This class will be instantiated by Fabric. Do not instantiate + * this class. */ public class SkyblockerMod implements ClientModInitializer { public static final String NAMESPACE = "skyblocker"; @@ -51,7 +55,9 @@ public class SkyblockerMod implements ClientModInitializer { } /** - * Register {@link #tick(MinecraftClient)} to {@link ClientTickEvents#END_CLIENT_TICK}, initialize all features, and schedule tick events. + * Register {@link #tick(MinecraftClient)} to + * {@link ClientTickEvents#END_CLIENT_TICK}, initialize all features, and + * schedule tick events. */ @Override public void onInitializeClient() { @@ -71,6 +77,7 @@ public class SkyblockerMod implements ClientModInitializer { DiscordRPCManager.init(); LividColor.init(); FishingHelper.init(); + TabHud.init(); containerSolverManager.init(); scheduler.scheduleCyclic(Utils::sbChecker, 20); scheduler.scheduleCyclic(DiscordRPCManager::update, 100); @@ -78,10 +85,12 @@ public class SkyblockerMod implements ClientModInitializer { scheduler.scheduleCyclic(LividColor::update, 10); scheduler.scheduleCyclic(BackpackPreview::tick, 50); scheduler.scheduleCyclic(DwarvenHud::update, 40); + scheduler.scheduleCyclic(PlayerListMgr::updateList, 20); } /** - * Ticks the scheduler. Called once at the end of every client tick through {@link ClientTickEvents#END_CLIENT_TICK}. + * Ticks the scheduler. Called once at the end of every client tick through + * {@link ClientTickEvents#END_CLIENT_TICK}. * * @param client the Minecraft client. */ diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java index c87f0ad9..7fdd7254 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java @@ -135,6 +135,10 @@ public class SkyblockerConfig implements ConfigData { public boolean backpackPreviewWithoutShift = false; public boolean hideEmptyTooltips = true; + @ConfigEntry.Category("tabHud") + @ConfigEntry.Gui.CollapsibleObject() + public TabHudConf tabHud = new TabHudConf(); + @ConfigEntry.Gui.Excluded public String apiKey; @@ -162,6 +166,14 @@ public class SkyblockerConfig implements ConfigData { public List<Integer> lockedSlots = new ArrayList<>(); } + public static class TabHudConf { + public boolean tabHudEnabled = true; + + @ConfigEntry.BoundedDiscrete(min=10, max=200) + @ConfigEntry.Gui.Tooltip() + public int tabHudScale = 100; + } + public static class Bars { public boolean enableBars = true; @@ -298,11 +310,29 @@ public class SkyblockerConfig implements ConfigData { public static class DwarvenHud { public boolean enabled = true; + @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) + @ConfigEntry.Gui.Tooltip(count = 3) + public Style style = Style.SIMPLE; public boolean enableBackground = true; public int x = 10; public int y = 10; } + public enum Style { + SIMPLE, + FANCY, + CLASSIC; + + @Override + public String toString() { + return switch (this) { + case SIMPLE -> "Simple"; + case FANCY -> "Fancy"; + case CLASSIC -> "Classic"; + }; + } + } + public static class Barn { public boolean solveHungryHiker = true; public boolean solveTreasureHunter = true; diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudAccessor.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudAccessor.java new file mode 100644 index 00000000..db329775 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudAccessor.java @@ -0,0 +1,18 @@ +package me.xmrvizzy.skyblocker.mixin; + +import java.util.Comparator; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.PlayerListEntry; + +@Mixin(PlayerListHud.class) +public interface PlayerListHudAccessor { + + @Accessor("ENTRY_ORDERING") + public static Comparator<PlayerListEntry> getOrdering() { + throw new AssertionError(); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java new file mode 100644 index 00000000..b5403ae2 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java @@ -0,0 +1,57 @@ +package me.xmrvizzy.skyblocker.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.utils.Utils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.scoreboard.Scoreboard; +import net.minecraft.scoreboard.ScoreboardObjective; +import net.minecraft.text.Text; + +@Environment(EnvType.CLIENT) +@Mixin(PlayerListHud.class) +public class PlayerListHudMixin { + + @Shadow + private Text footer; + + @Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/client/util/math/MatrixStack;ILnet/minecraft/scoreboard/Scoreboard;Lnet/minecraft/scoreboard/ScoreboardObjective;)V", cancellable = true) + public void skyblocker$renderTabHud(MatrixStack ms, int scaledW, Scoreboard sb, ScoreboardObjective sbo, + CallbackInfo info) { + + if (!Utils.isOnSkyblock() + || !SkyblockerConfig.get().general.tabHud.tabHudEnabled + || TabHud.defaultTgl.isPressed()) { + return; + } + + MinecraftClient client = MinecraftClient.getInstance(); + ClientPlayNetworkHandler nwH = client.getNetworkHandler(); + if (nwH == null) { + return; + } + + int w = scaledW; + int h = MinecraftClient.getInstance().getWindow().getScaledHeight(); + try { + Screen screen = Screen.getCorrect(w, h, footer); + screen.render(ms); + info.cancel(); + } catch (Exception e) { + TabHud.LOGGER.error("Drawing default hud. Reason: Screen exception {}", e); + } + } + +}
\ No newline at end of file diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java index 86fe58fe..15f9e58b 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java @@ -1,6 +1,7 @@ package me.xmrvizzy.skyblocker.skyblock.dwarven; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.CommsWidget; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; @@ -49,23 +50,57 @@ public class DwarvenHud { }))))); HudRenderCallback.EVENT.register((matrixStack, tickDelta) -> { - if (!SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enabled || client.player == null || commissionList.isEmpty()) return; + if (!SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enabled + || client.options.playerListKey.isPressed() + || client.player == null + || commissionList.isEmpty()) { + return; + } render(matrixStack, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.x, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.y, commissionList); }); } public static void render(MatrixStack matrixStack, int hudX, int hudY, List<Commission> commissions) { - 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, Text.literal(commission.commission).styled(style -> style.withColor(Formatting.AQUA)).append(Text.literal(": " + commission.progression).styled(style -> style.withColor(Formatting.GREEN))), hudX + 5, hudY + y + 5, 0xFFFFFFFF); - y += 20; - } + + switch(SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.style) { + case SIMPLE -> renderSimple(matrixStack, hudX, hudY, commissions); + case FANCY -> renderFancy(matrixStack, hudX, hudY, commissions); + case CLASSIC -> renderClassic(matrixStack, hudX, hudY, commissions); + } + } + + public static void renderClassic(MatrixStack matrixStack, int hudX, int hudY, List<Commission> commissions) { + 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, + Text.literal(commission.commission + ": ") + .styled(style -> style.withColor(Formatting.AQUA)) + .append(Text.literal(commission.progression) + .styled(style -> style.withColor(Formatting.GREEN))), + hudX + 5, hudY + y + 5, 0xFFFFFFFF); + y += 20; } } + public static void renderSimple(MatrixStack matrixStack, int hudX, int hudY, List<Commission> commissions) { + CommsWidget cw = new CommsWidget(commissions, false); + cw.setX(hudX); + cw.setY(hudY); + cw.render(matrixStack, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enableBackground); + } + + public static void renderFancy(MatrixStack matrixStack, int hudX, int hudY, List<Commission> commissions) { + CommsWidget cw = new CommsWidget(commissions, true); + cw.setX(hudX); + cw.setY(hudY); + cw.render(matrixStack, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enableBackground); + } + public static void update() { commissionList = new ArrayList<>(); if (client.player == null || !SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enabled) return; @@ -83,13 +118,7 @@ public class DwarvenHud { }); } - public static class Commission{ - final String commission; - final String progression; + // steamroller tactics to get visibility from outside classes (CommsWidget) + public static record 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/tabhud/TabHud.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/TabHud.java new file mode 100644 index 00000000..6d90b269 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/TabHud.java @@ -0,0 +1,44 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud; + +import org.lwjgl.glfw.GLFW; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; + +public class TabHud { + + public static KeyBinding playerTgl; + public static KeyBinding genericTgl; + // public static KeyBinding mapTgl; + public static KeyBinding defaultTgl; + + public static final Logger LOGGER = LoggerFactory.getLogger("Skyblocker Tab HUD"); + + public static void init() { + + playerTgl = KeyBindingHelper.registerKeyBinding( + new KeyBinding("key.skyblocker.playerTgl", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_B, + "key.categories.skyblocker")); + genericTgl = KeyBindingHelper.registerKeyBinding( + new KeyBinding("key.skyblocker.genericTgl", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_N, + "key.categories.skyblocker")); + // mapTgl = KeyBindingHelper.registerKeyBinding( + // new KeyBinding("key.tabhud.mapTgl", + // InputUtil.Type.KEYSYM, + // GLFW.GLFW_KEY_LEFT_ALT, + // "key.categories.skyblocker")); + defaultTgl = KeyBindingHelper.registerKeyBinding( + new KeyBinding("key.skyblocker.defaultTgl", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_M, + "key.categories.skyblocker")); + + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/EmptyScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/EmptyScreen.java new file mode 100644 index 00000000..5c302eb3 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/EmptyScreen.java @@ -0,0 +1,16 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EmptyWidget; + +import net.minecraft.text.Text; + +public class EmptyScreen extends Screen { + + public EmptyScreen(int w, int h, Text footer) { + super(w, h); + EmptyWidget ew = new EmptyWidget(); + this.center(ew); + this.addWidget(ew); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java new file mode 100644 index 00000000..43b7f956 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java @@ -0,0 +1,225 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens; + +import java.util.ArrayList; + +import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.genericInfo.GardenInfoScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.genericInfo.GenericInfoScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.CrimsonIsleScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.DungeonHubScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.DungeonScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.FarmingServerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.GardenScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.GenericServerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.GuestServerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.HomeServerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.HubServerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.MineServerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main.ParkServerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList.DungeonPlayerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList.GuestPlayerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList.HomePlayerScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList.PlayerListScreen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerLocator; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; + +public class Screen { + + private ArrayList<Widget> widgets = new ArrayList<>(); + private int w, h; + + public Screen(int w, int h) { + float scale = SkyblockerConfig.get().general.tabHud.tabHudScale / 100f; + this.w = (int) (w / scale); + this.h = (int) (h / scale); + } + + public static Screen getCorrect(int w, int h, Text footer) { + if (TabHud.genericTgl.isPressed()) { + return Screen.correctGenericScrn(w, h, footer); + } else if (TabHud.playerTgl.isPressed()) { + return Screen.correctPlayerScrn(w, h, footer); + } else { + return Screen.correctMainScrn(w, h, footer); + } + } + + private static Screen correctGenericScrn(int w, int h, Text footer) { + return switch (PlayerLocator.getPlayerLocation()) { + case GARDEN -> new GardenInfoScreen(w, h, footer); // ok + case UNKNOWN -> new EmptyScreen(w, h, footer); // ok + default -> new GenericInfoScreen(w, h, footer); // ok + }; + } + + private static Screen correctPlayerScrn(int w, int h, Text footer) { + return switch (PlayerLocator.getPlayerLocation()) { + case GUEST_ISLAND -> new GuestPlayerScreen(w, h, footer); // ok + case HOME_ISLAND, GARDEN -> new HomePlayerScreen(w, h, footer); // ok for 1 player + case DUNGEON -> new DungeonPlayerScreen(w, h, footer); + case UNKNOWN -> new EmptyScreen(w, h, footer); // ok + default -> new PlayerListScreen(w, h, footer); // ok + }; + } + + private static Screen correctMainScrn(int w, int h, Text footer) { + return switch (PlayerLocator.getPlayerLocation()) { + case PARK -> new ParkServerScreen(w, h, footer); // ok + case HUB -> new HubServerScreen(w, h, footer); // ok when fire sale incoming + case HOME_ISLAND -> new HomeServerScreen(w, h, footer); // ok + case GUEST_ISLAND -> new GuestServerScreen(w, h, footer); // ok + case CRYSTAL_HOLLOWS, DWARVEN_MINES -> new MineServerScreen(w, h, footer); // ok, TODO active forge + case FARMING_ISLAND -> new FarmingServerScreen(w, h, footer); + case DUNGEON_HUB -> new DungeonHubScreen(w, h, footer); // ok + case DUNGEON -> new DungeonScreen(w, h, footer); // ok + case CRIMSON_ISLE -> new CrimsonIsleScreen(w, h, footer); + case GARDEN -> new GardenScreen(w, h, footer); // ok + case UNKNOWN -> new EmptyScreen(w, h, footer); // ok + default -> new GenericServerScreen(w, h, footer); // ok + }; + } + + /** + * Add a widget to this screen + */ + public void addWidget(Widget w) { + widgets.add(w); + } + + /** + * Add many widgets to this screen + */ + public void addWidgets(Widget... ws) { + for (Widget w : ws) { + widgets.add(w); + } + } + + public void render(MatrixStack ms) { + for (Widget w : widgets) { + w.render(ms); + } + } + + /** + * Stack these widgets on top of each other as determined by the lists's order + */ + public void stackWidgetsH(Widget... list) { + int compHeight = -5; + for (Widget wid : list) { + compHeight += wid.getHeight() + 5; + } + + int y = (h - compHeight) / 2; + for (Widget wid : list) { + wid.setY(y); + y += wid.getHeight() + 5; + } + } + + /** + * Arrange these widgets next to each other as determined by the lists's order + */ + public void stackWidgetsW(Widget... list) { + // TODO not centered + int compWidth = -5; + for (Widget wid : list) { + compWidth += wid.getWidth() + 5; + } + + int x = (w - compWidth) / 2; + for (Widget wid : list) { + wid.setX(x); + x += wid.getWidth() + 5; + } + } + + /** + * Center a widget vertically, keeping X pos + */ + public void centerH(Widget wid) { + wid.setY((h - wid.getHeight()) / 2); + } + + /** + * Center a widget horizontally, keeping Y pos + */ + public void centerW(Widget wid) { + wid.setX((w - wid.getWidth()) / 2); + } + + /** + * Center a widget vertically and horizontally + */ + public void center(Widget wid) { + this.centerH(wid); + this.centerW(wid); + } + + /** + * Let a widget's left border be on the screen's center, keeping Y pos + */ + public void offCenterL(Widget wid) { + int wHalf = this.w / 2; + wid.setX(wHalf - 3 - wid.getWidth()); + } + + /** + * Let a widget's right border be on the screen's center, keeping Y pos + */ + public void offCenterR(Widget wid) { + int wHalf = this.w / 2; + wid.setX(wHalf + 3); + } + + public void collideAgainstL(Widget w, Widget... others) { + int yMin = w.getY(); + int yMax = w.getY() + w.getHeight(); + + int xCor = this.w / 2; + + // assume others to be sorted top-bottom. + for (Widget other : others) { + if (other.getY() + other.getHeight() + 5 < yMin) { + // too high, next one + continue; + } + + if (other.getY() - 5 > yMax) { + // too low, no more collisions possible + break; + } + + int xPos = other.getX() - 5 - w.getWidth(); + xCor = Math.min(xCor, xPos); + } + w.setX(xCor); + } + + public void collideAgainstR(Widget w, Widget... others) { + int yMin = w.getY(); + int yMax = w.getY() + w.getHeight(); + + int xCor = this.w / 2; + + // assume others to be sorted top-bottom. + for (Widget other : others) { + if (other.getY() + other.getHeight() + 5 < yMin) { + // too high, next one + continue; + } + + if (other.getY() - 5 > yMax) { + // too low, no more collisions possible + break; + } + + int xPos = other.getX() + other.getWidth() + 5; + xCor = Math.max(xCor, xPos); + } + w.setX(xCor); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/genericInfo/GardenInfoScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/genericInfo/GardenInfoScreen.java new file mode 100644 index 00000000..0bb12c8e --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/genericInfo/GardenInfoScreen.java @@ -0,0 +1,51 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.genericInfo; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.CookieWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EffectWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EventWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.GardenSkillsWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.JacobsContestWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ProfileWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.UpgradeWidget; + +import net.minecraft.text.Text; + +public class GardenInfoScreen extends Screen { + + public GardenInfoScreen(int w, int h, Text footer) { + super(w, h); + + String f = footer.getString(); + + GardenSkillsWidget gsw = new GardenSkillsWidget(); + EventWidget evw = new EventWidget(true); + UpgradeWidget uw = new UpgradeWidget(f); + + ProfileWidget pw = new ProfileWidget(); + EffectWidget efw = new EffectWidget(f); + + JacobsContestWidget jcw = new JacobsContestWidget(); + CookieWidget cw = new CookieWidget(f); + + // layout code incoming + this.stackWidgetsH(gsw, evw, uw); + this.stackWidgetsH(pw, efw); + this.stackWidgetsH(jcw, cw); + + this.centerW(gsw); + this.centerW(evw); + this.centerW(uw); + + this.collideAgainstL(pw, gsw, evw, uw); + this.collideAgainstL(efw, gsw, evw, uw); + + this.collideAgainstR(jcw, gsw, evw, uw); + this.collideAgainstR(cw, gsw, evw, uw); + + this.addWidgets(gsw, evw, uw, pw, efw, jcw, cw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/genericInfo/GenericInfoScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/genericInfo/GenericInfoScreen.java new file mode 100644 index 00000000..046a9313 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/genericInfo/GenericInfoScreen.java @@ -0,0 +1,48 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.genericInfo; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.CookieWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EffectWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ElectionWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EventWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ProfileWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.SkillsWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.UpgradeWidget; + +import net.minecraft.text.Text; + +public class GenericInfoScreen extends Screen { + + public GenericInfoScreen(int w, int h, Text footer) { + super(w, h); + + String f = footer.getString(); + + SkillsWidget sw = new SkillsWidget(); + EventWidget evw = new EventWidget(false); + UpgradeWidget uw = new UpgradeWidget(f); + + ProfileWidget pw = new ProfileWidget(); + EffectWidget efw = new EffectWidget(f); + + ElectionWidget elw = new ElectionWidget(); + CookieWidget cw = new CookieWidget(f); + + this.stackWidgetsH(sw, evw, uw); + this.stackWidgetsH(pw, efw); + this.stackWidgetsH(elw, cw); + + this.centerW(sw); + this.centerW(evw); + this.centerW(uw); + + this.collideAgainstL(pw, sw, evw, uw); + this.collideAgainstL(efw, sw, evw, uw); + + this.collideAgainstR(elw, sw, evw, uw); + this.collideAgainstR(cw, sw, evw, uw); + + this.addWidgets(sw, evw, uw, pw, efw, elw, cw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/CrimsonIsleScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/CrimsonIsleScreen.java new file mode 100644 index 00000000..6e6f563b --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/CrimsonIsleScreen.java @@ -0,0 +1,32 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.QuestWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ReputationWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ServerWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.VolcanoWidget; + +import net.minecraft.text.Text; + +public class CrimsonIsleScreen extends Screen { + + public CrimsonIsleScreen(int w, int h, Text footer) { + super(w, h); + + ServerWidget sw = new ServerWidget(); + ReputationWidget rw = new ReputationWidget(); + QuestWidget qw = new QuestWidget(); + VolcanoWidget vw = new VolcanoWidget(); + + this.stackWidgetsH(sw, rw); + this.stackWidgetsH(qw, vw); + this.offCenterL(sw); + this.offCenterL(rw); + this.offCenterR(vw); + this.offCenterR(qw); + this.addWidgets(sw, rw, qw, vw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/DungeonHubScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/DungeonHubScreen.java new file mode 100644 index 00000000..5db461af --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/DungeonHubScreen.java @@ -0,0 +1,25 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EssenceWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ServerWidget; + +import net.minecraft.text.Text; + +public class DungeonHubScreen extends Screen{ + + public DungeonHubScreen(int w, int h, Text footer) { + super(w, h); + + ServerWidget sw = new ServerWidget(); + EssenceWidget ew = new EssenceWidget(); + + this.centerW(sw); + this.centerW(ew); + this.stackWidgetsH(sw, ew); + this.addWidget(ew); + this.addWidget(sw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/DungeonScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/DungeonScreen.java new file mode 100644 index 00000000..852ee876 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/DungeonScreen.java @@ -0,0 +1,40 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.DungeonBuffWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.DungeonDeathWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.DungeonDownedWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.DungeonPuzzleWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.DungeonSecretWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.DungeonServerWidget; +import net.minecraft.text.Text; + +public class DungeonScreen extends Screen { + + public DungeonScreen(int w, int h, Text footer) { + super(w, h); + + String f = footer.getString(); + + DungeonDownedWidget ddow = new DungeonDownedWidget(); + DungeonDeathWidget ddew = new DungeonDeathWidget(); + DungeonSecretWidget dscw = new DungeonSecretWidget(); + DungeonServerWidget dsrw = new DungeonServerWidget(); + DungeonPuzzleWidget dpuw = new DungeonPuzzleWidget(); + DungeonBuffWidget dbw = new DungeonBuffWidget(f); + + this.offCenterL(ddow); + this.offCenterL(ddew); + this.offCenterL(dbw); + this.offCenterR(dsrw); + this.offCenterR(dpuw); + this.offCenterR(dscw); + + this.stackWidgetsH(ddow, ddew, dbw); + this.stackWidgetsH(dsrw, dpuw, dscw); + + this.addWidgets(ddow, ddew, dscw, dsrw, dpuw, dbw); + + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/FarmingServerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/FarmingServerScreen.java new file mode 100644 index 00000000..02c81f23 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/FarmingServerScreen.java @@ -0,0 +1,26 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ServerWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.TrapperWidget; + + +import net.minecraft.text.Text; + +public class FarmingServerScreen extends Screen{ + + public FarmingServerScreen(int w, int h, Text footer) { + super(w, h); + + ServerWidget sw = new ServerWidget(); + TrapperWidget tw = new TrapperWidget(); + + this.centerW(sw); + this.centerW(tw); + this.stackWidgetsH(sw, tw); + this.addWidgets(tw, sw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GardenScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GardenScreen.java new file mode 100644 index 00000000..ae5b642f --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GardenScreen.java @@ -0,0 +1,23 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ComposterWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.GardenServerWidget; +import net.minecraft.text.Text; + +public class GardenScreen extends Screen{ + + public GardenScreen(int w, int h, Text footer) { + super(w, h); + + GardenServerWidget gsw = new GardenServerWidget(); + ComposterWidget cw = new ComposterWidget(); + + this.stackWidgetsH(gsw, cw); + this.centerW(gsw); + this.centerW(cw); + this.addWidgets(gsw, cw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GenericServerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GenericServerScreen.java new file mode 100644 index 00000000..a89563db --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GenericServerScreen.java @@ -0,0 +1,21 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ServerWidget; + +import net.minecraft.text.Text; + +public class GenericServerScreen extends Screen { + + public GenericServerScreen(int w, int h, Text footer) { + super(w, h); + + ServerWidget sw = new ServerWidget(); + + this.center(sw); + this.addWidget(sw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GuestServerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GuestServerScreen.java new file mode 100644 index 00000000..57d7a199 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/GuestServerScreen.java @@ -0,0 +1,22 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.GuestServerWidget; + + +import net.minecraft.text.Text; + +public class GuestServerScreen extends Screen{ + + public GuestServerScreen(int w, int h, Text footer) { + super(w, h); + + GuestServerWidget gsw = new GuestServerWidget(); + + this.center(gsw); + this.addWidget(gsw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/HomeServerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/HomeServerScreen.java new file mode 100644 index 00000000..e61ba4b0 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/HomeServerScreen.java @@ -0,0 +1,26 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.IslandServerWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.MinionWidget; + + +import net.minecraft.text.Text; + +public class HomeServerScreen extends Screen { + + public HomeServerScreen(int w, int h, Text footer) { + super(w, h); + + IslandServerWidget isw = new IslandServerWidget(); + MinionWidget mw = new MinionWidget(); + + this.centerH(isw); + this.centerH(mw); + this.stackWidgetsW(isw, mw); + this.addWidgets(isw, mw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/HubServerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/HubServerScreen.java new file mode 100644 index 00000000..e2857f7e --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/HubServerScreen.java @@ -0,0 +1,26 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.FireSaleWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ServerWidget; + + +import net.minecraft.text.Text; + +public class HubServerScreen extends Screen { + + public HubServerScreen(int w, int h, Text footer) { + super(w, h); + + ServerWidget sw = new ServerWidget(); + FireSaleWidget fsw = new FireSaleWidget(); + + this.centerW(sw); + this.centerW(fsw); + this.stackWidgetsH(sw, fsw); + this.addWidgets(sw, fsw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/MineServerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/MineServerScreen.java new file mode 100644 index 00000000..616c3e82 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/MineServerScreen.java @@ -0,0 +1,30 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.CommsWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ForgeWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.PowderWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ServerWidget; + +import net.minecraft.text.Text; + +public class MineServerScreen extends Screen { + + public MineServerScreen(int w, int h, Text footer) { + super(w, h); + + ServerWidget sw = new ServerWidget(); + PowderWidget pw = new PowderWidget(); + CommsWidget cw = new CommsWidget(); + ForgeWidget fw = new ForgeWidget(); + + this.stackWidgetsH(sw, cw); + this.stackWidgetsH(fw, pw); + this.offCenterL(sw); + this.offCenterL(cw); + this.offCenterR(pw); + this.offCenterR(fw); + this.addWidgets(fw, cw, pw, sw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/ParkServerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/ParkServerScreen.java new file mode 100644 index 00000000..aa65d946 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/main/ParkServerScreen.java @@ -0,0 +1,19 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.main; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.ParkServerWidget; + +import net.minecraft.text.Text; + +public class ParkServerScreen extends Screen{ + + public ParkServerScreen(int w, int h, Text footer) { + super(w, h); + + ParkServerWidget sw = new ParkServerWidget(); + + this.center(sw); + this.addWidget(sw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/DungeonPlayerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/DungeonPlayerScreen.java new file mode 100644 index 00000000..2567da13 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/DungeonPlayerScreen.java @@ -0,0 +1,29 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.DungeonPlayerWidget; +import net.minecraft.text.Text; + +public class DungeonPlayerScreen extends Screen { + + public DungeonPlayerScreen(int w, int h, Text footer) { + + super(w, h); + + DungeonPlayerWidget dpw1 = new DungeonPlayerWidget(1); + DungeonPlayerWidget dpw2 = new DungeonPlayerWidget(2); + DungeonPlayerWidget dpw3 = new DungeonPlayerWidget(3); + DungeonPlayerWidget dpw4 = new DungeonPlayerWidget(4); + DungeonPlayerWidget dpw5 = new DungeonPlayerWidget(5); + + this.offCenterL(dpw1); + this.offCenterL(dpw2); + this.offCenterL(dpw3); + this.offCenterR(dpw4); + this.offCenterR(dpw5); + this.stackWidgetsH(dpw1, dpw2, dpw3); + this.stackWidgetsH(dpw4, dpw5); + this.addWidgets(dpw1, dpw2, dpw3, dpw4, dpw5); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/GuestPlayerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/GuestPlayerScreen.java new file mode 100644 index 00000000..5a9733cc --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/GuestPlayerScreen.java @@ -0,0 +1,26 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.IslandGuestsWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.IslandOwnersWidget; + + +import net.minecraft.text.Text; + +public class GuestPlayerScreen extends Screen{ + + public GuestPlayerScreen(int w, int h, Text footer) { + super(w, h); + + IslandGuestsWidget igw = new IslandGuestsWidget(); + IslandOwnersWidget iow = new IslandOwnersWidget(); + + this.centerH(iow); + this.centerH(igw); + this.stackWidgetsW(igw, iow); + this.addWidgets(iow, igw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/HomePlayerScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/HomePlayerScreen.java new file mode 100644 index 00000000..2a159ecc --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/HomePlayerScreen.java @@ -0,0 +1,25 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList; + + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.IslandGuestsWidget; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.IslandSelfWidget; + + +import net.minecraft.text.Text; + +public class HomePlayerScreen extends Screen { + + public HomePlayerScreen(int w, int h, Text footer) { + super(w, h); + + IslandSelfWidget isw = new IslandSelfWidget(); + IslandGuestsWidget igw = new IslandGuestsWidget(); + + this.centerH(isw); + this.centerH(igw); + this.stackWidgetsW(isw, igw); + this.addWidgets(isw, igw); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/PlayerListScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/PlayerListScreen.java new file mode 100644 index 00000000..5db01512 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/playerList/PlayerListScreen.java @@ -0,0 +1,20 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.PlayerListWidget; + +import net.minecraft.text.Text; + +public class PlayerListScreen extends Screen { + + public PlayerListScreen(int w, int h, Text footer) { + super(w, h); + + PlayerListWidget plw = new PlayerListWidget(); + + this.center(plw); + this.addWidget(plw); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/Ico.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/Ico.java new file mode 100644 index 00000000..ca767617 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/Ico.java @@ -0,0 +1,55 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.util; + +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; + +/** + * Stores convenient shorthands for common ItemStack definitions + */ +public class Ico { + public static final ItemStack MAP = new ItemStack(Items.FILLED_MAP); + public static final ItemStack NTAG = new ItemStack(Items.NAME_TAG); + public static final ItemStack EMERALD = new ItemStack(Items.EMERALD); + public static final ItemStack CLOCK = new ItemStack(Items.CLOCK); + public static final ItemStack DIASWORD = new ItemStack(Items.DIAMOND_SWORD); + public static final ItemStack DBUSH = new ItemStack(Items.DEAD_BUSH); + public static final ItemStack VILLAGER = new ItemStack(Items.VILLAGER_SPAWN_EGG); + public static final ItemStack MOREGOLD = new ItemStack(Items.GOLDEN_APPLE); + public static final ItemStack COMPASS = new ItemStack(Items.COMPASS); + public static final ItemStack SUGAR = new ItemStack(Items.SUGAR); + public static final ItemStack HOE = new ItemStack(Items.IRON_HOE); + public static final ItemStack GOLD = new ItemStack(Items.GOLD_INGOT); + public static final ItemStack BONE = new ItemStack(Items.BONE); + public static final ItemStack SIGN = new ItemStack(Items.OAK_SIGN); + public static final ItemStack FISH_ROD = new ItemStack(Items.FISHING_ROD); + public static final ItemStack SWORD = new ItemStack(Items.IRON_SWORD); + public static final ItemStack LANTERN = new ItemStack(Items.LANTERN); + public static final ItemStack COOKIE = new ItemStack(Items.COOKIE); + public static final ItemStack POTION = new ItemStack(Items.POTION); + public static final ItemStack BARRIER = new ItemStack(Items.BARRIER); + public static final ItemStack PLAYER = new ItemStack(Items.PLAYER_HEAD); + public static final ItemStack WATER = new ItemStack(Items.WATER_BUCKET); + public static final ItemStack LEATHER = new ItemStack(Items.LEATHER); + public static final ItemStack MITHRIL = new ItemStack(Items.PRISMARINE_CRYSTALS); + public static final ItemStack REDSTONE = new ItemStack(Items.REDSTONE); + public static final ItemStack FIRE = new ItemStack(Items.CAMPFIRE); + public static final ItemStack STRING = new ItemStack(Items.STRING); + public static final ItemStack WITHER = new ItemStack(Items.WITHER_SKELETON_SKULL); + public static final ItemStack FLESH = new ItemStack(Items.ROTTEN_FLESH); + public static final ItemStack DRAGON = new ItemStack(Items.DRAGON_HEAD); + public static final ItemStack DIAMOND = new ItemStack(Items.DIAMOND); + public static final ItemStack ICE = new ItemStack(Items.ICE); + public static final ItemStack CHEST = new ItemStack(Items.CHEST); + public static final ItemStack COMMAND = new ItemStack(Items.COMMAND_BLOCK); + public static final ItemStack SKULL = new ItemStack(Items.SKELETON_SKULL); + public static final ItemStack BOOK = new ItemStack(Items.WRITABLE_BOOK); + public static final ItemStack FURNACE = new ItemStack(Items.FURNACE); + public static final ItemStack CHESTPLATE = new ItemStack(Items.IRON_CHESTPLATE); + public static final ItemStack B_ROD = new ItemStack(Items.BLAZE_ROD); + public static final ItemStack BOW = new ItemStack(Items.BOW); + public static final ItemStack COPPER = new ItemStack(Items.COPPER_INGOT); + public static final ItemStack COMPOSTER = new ItemStack(Items.COMPOSTER); + public static final ItemStack SAPLING = new ItemStack(Items.OAK_SAPLING); + public static final ItemStack MILESTONE = new ItemStack(Items.LODESTONE); + public static final ItemStack PICKAXE = new ItemStack(Items.IRON_PICKAXE); +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerListMgr.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerListMgr.java new file mode 100644 index 00000000..60915bc1 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerListMgr.java @@ -0,0 +1,111 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.util; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import me.xmrvizzy.skyblocker.mixin.PlayerListHudAccessor; + +import me.xmrvizzy.skyblocker.utils.Utils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.text.Text; + +/** + * This class may be used to get data from the player list. + * It doesn't get its data every frame, instead, a scheduler is used to + * update the data this class is holding periodically. + * The list is sorted like in the vanilla game. + */ +public class PlayerListMgr { + + public static final Logger LOGGER = LoggerFactory.getLogger("Skyblocker Regex"); + + private static List<PlayerListEntry> playerList; + + public static void updateList() { + + if (!Utils.isOnSkyblock()) { + return; + } + + ClientPlayNetworkHandler cpnwh = MinecraftClient.getInstance().getNetworkHandler(); + + // check is needed, else game crash on server leave + if (cpnwh != null) { + playerList = cpnwh.getPlayerList() + .stream() + .sorted(PlayerListHudAccessor.getOrdering()) + .toList(); + } + } + + /** + * Get the display name at some index of the player list and apply a pattern to + * it + * + * @return the matcher if p fully matches, else null + */ + public static Matcher regexAt(int idx, Pattern p) { + + String str = PlayerListMgr.strAt(idx); + + if (str == null) { + return null; + } + + Matcher m = p.matcher(str); + if (!m.matches()) { + LOGGER.error("no match: \"{}\" against \"{}\"", str, p); + return null; + } else { + return m; + } + } + + /** + * Get the display name at some index of the player list as string + * + * @return the string or null, if the display name is null, empty or whitespace + * only + */ + public static String strAt(int idx) { + + if (playerList == null) { + return null; + } + + if (playerList.size() <= idx) { + return null; + } + + Text txt = playerList.get(idx).getDisplayName(); + if (txt == null) { + return null; + } + String str = txt.getString().trim(); + if (str.length() == 0) { + return null; + } + return str; + } + + /** + * Get the display name at some index of the player list as Text as seen in the + * game + * + * @return the PlayerListEntry at that index + */ + public static PlayerListEntry getRaw(int idx) { + return playerList.get(idx); + } + + public static int getSize() { + return playerList.size(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerLocator.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerLocator.java new file mode 100644 index 00000000..d7abdfc2 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerLocator.java @@ -0,0 +1,89 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.util; + +import me.xmrvizzy.skyblocker.utils.Utils; + +/** + * Uses data from the player list to determine the area the player is in. + */ +public class PlayerLocator { + + public static enum Location { + DUNGEON, + GUEST_ISLAND, + HOME_ISLAND, + CRIMSON_ISLE, + DUNGEON_HUB, + FARMING_ISLAND, + PARK, + DWARVEN_MINES, + CRYSTAL_HOLLOWS, + END, + GOLD_MINE, + DEEP_CAVERNS, + HUB, + SPIDER_DEN, + JERRY, + GARDEN, + INSTANCED, + UNKNOWN + } + + public static Location getPlayerLocation() { + + if (!Utils.isOnSkyblock()) { + return Location.UNKNOWN; + } + + String areaDesciptor = PlayerListMgr.strAt(41); + + if (areaDesciptor == null || areaDesciptor.length() < 6) { + return Location.UNKNOWN; + } + + if (areaDesciptor.startsWith("Dungeon")) { + return Location.DUNGEON; + } + + switch (areaDesciptor.substring(6)) { + case "Private Island": + String islandType = PlayerListMgr.strAt(44); + if (islandType == null) { + return Location.UNKNOWN; + } else if (islandType.endsWith("Guest")) { + return Location.GUEST_ISLAND; + } else { + return Location.HOME_ISLAND; + } + case "Crimson Isle": + return Location.CRIMSON_ISLE; + case "Dungeon Hub": + return Location.DUNGEON_HUB; + case "The Farming Islands": + return Location.FARMING_ISLAND; + case "The Park": + return Location.PARK; + case "Dwarven Mines": + return Location.DWARVEN_MINES; + case "Crystal Hollows": + return Location.CRYSTAL_HOLLOWS; + case "The End": + return Location.END; + case "Gold Mine": + return Location.GOLD_MINE; + case "Deep Caverns": + return Location.DEEP_CAVERNS; + case "Hub": + return Location.HUB; + case "Spider's Den": + return Location.SPIDER_DEN; + case "Jerry's Workshop": + return Location.JERRY; + case "Garden": + return Location.GARDEN; + case "Instanced": + return Location.INSTANCED; + default: + return Location.UNKNOWN; + } + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CommsWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CommsWidget.java new file mode 100644 index 00000000..de90cf30 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CommsWidget.java @@ -0,0 +1,91 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.dwarven.DwarvenHud.Commission; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.Component; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.MathHelper; + +// this widget shows the status of the king's commissions. +// (dwarven mines and crystal hollows) + +public class CommsWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Commissions").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + // match a comm + // group 1: comm name + // group 2: comm progress (without "%" for comms that show a percentage) + private static final Pattern COMM_PATTERN = Pattern.compile("(?<name>.*): (?<progress>.*)%?"); + + public CommsWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + for (int i = 50; i <= 53; i++) { + Matcher m = PlayerListMgr.regexAt(i, COMM_PATTERN); + // end of comms found? + if (m == null) { + if (i == 50) { + this.addComponent(new IcoTextComponent()); + } + break; + } + + ProgressComponent pc; + + String name = m.group("name"); + String progress = m.group("progress"); + + if (progress.equals("DONE")) { + pc = new ProgressComponent(Ico.BOOK, Text.of(name), Text.of(progress), 100f, pcntToCol(100)); + } else { + float pcnt = Float.parseFloat(progress.substring(0, progress.length() - 1)); + pc = new ProgressComponent(Ico.BOOK, Text.of(name), pcnt, pcntToCol(pcnt)); + } + this.addComponent(pc); + } + this.pack(); + } + + // for the dwarven hud + public CommsWidget(List<Commission> commissions, boolean isFancy) { + super(TITLE, Formatting.AQUA.getColorValue()); + for (Commission comm : commissions) { + + Text c = Text.literal(comm.commission()); + + float p = 100f; + if (!comm.progression().contains("DONE")) { + p = Float.parseFloat(comm.progression().substring(0, comm.progression().length() - 1)); + } + + Component comp; + if (isFancy) { + comp = new ProgressComponent(Ico.BOOK, c, p, pcntToCol(p)); + } else { + comp = new PlainTextComponent( + Text.literal(comm.commission() + ": ") + .append(Text.literal(comm.progression()).formatted(Formatting.GREEN))); + } + this.addComponent(comp); + } + this.pack(); + + } + + private int pcntToCol(float pcnt) { + return MathHelper.hsvToRgb(pcnt / 300f, 0.9f, 0.9f); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ComposterWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ComposterWidget.java new file mode 100644 index 00000000..5922fcbc --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ComposterWidget.java @@ -0,0 +1,28 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about the garden's composter + +public class ComposterWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Composter").formatted(Formatting.GREEN, + Formatting.BOLD); + + public ComposterWidget() { + super(TITLE, Formatting.GREEN.getColorValue()); + + this.addSimpleIcoText(Ico.SAPLING, "Organic Matter:", Formatting.YELLOW, 48); + this.addSimpleIcoText(Ico.FURNACE, "Fuel:", Formatting.BLUE, 49); + this.addSimpleIcoText(Ico.CLOCK, "Time Left:", Formatting.RED, 50); + this.addSimpleIcoText(Ico.COMPOSTER, "Stored Compost:", Formatting.DARK_GREEN, 51); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CookieWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CookieWidget.java new file mode 100644 index 00000000..48cb90bd --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CookieWidget.java @@ -0,0 +1,48 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about active super cookies +// or not, if you're unwilling to buy one + +public class CookieWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Cookie Info").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + private static final Pattern COOKIE_PATTERN = Pattern.compile(".*\\nCookie Buff\\n(?<buff>.*)\\n"); + + public CookieWidget(String footertext) { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + if (footertext == null || !footertext.contains("Cookie Buff")) { + this.addComponent(new IcoTextComponent()); + this.pack(); + return; + } + + Matcher m = COOKIE_PATTERN.matcher(footertext); + if (!m.find() || m.group("buff") == null) { + this.addComponent(new IcoTextComponent()); + this.pack(); + return; + } + + String buff = m.group("buff"); + if (buff.startsWith("Not")) { + this.addComponent(new IcoTextComponent(Ico.COOKIE, Text.of("Not active"))); + } else { + Text cookie = Text.literal("Time Left: ").append(buff); + this.addComponent(new IcoTextComponent(Ico.COOKIE, cookie)); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonBuffWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonBuffWidget.java new file mode 100644 index 00000000..6ad5268e --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonBuffWidget.java @@ -0,0 +1,44 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows a list of obtained dungeon buffs +// TODO: could be more pretty, can't be arsed atm + +public class DungeonBuffWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Dungeon Buffs").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + public DungeonBuffWidget(String footertext) { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + if (footertext == null || !footertext.contains("Dungeon Buffs")) { + this.addComponent(new PlainTextComponent(Text.literal("No data").formatted(Formatting.GRAY))); + this.pack(); + return; + } + + String interesting = footertext.split("Dungeon Buffs")[1]; + String[] lines = interesting.split("\n"); + + if (!lines[1].startsWith("Blessing")) { + this.addComponent(new PlainTextComponent(Text.literal("No buffs found!").formatted(Formatting.GRAY))); + this.pack(); + return; + } + + for (int i = 1; i < lines.length; i++) { + if (lines[i].length() < 3) { // empty line is §s + break; + } + this.addComponent(new PlainTextComponent(Text.of(lines[i]))); + } + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonDeathWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonDeathWidget.java new file mode 100644 index 00000000..78e1aeae --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonDeathWidget.java @@ -0,0 +1,45 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows various dungeon info +// deaths, healing, dmg taken, milestones + +public class DungeonDeathWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Death").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + // match the deaths entry + // group 1: amount of deaths + private static final Pattern DEATH_PATTERN = Pattern.compile("\\S*: \\((?<deathnum>\\d+)\\).*"); + + public DungeonDeathWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + Matcher m = PlayerListMgr.regexAt(25, DEATH_PATTERN); + if (m == null) { + this.addComponent(new IcoTextComponent()); + } else { + Formatting f = (m.group("deathnum").equals("0")) ? Formatting.GREEN : Formatting.RED; + Text d = Widget.simpleEntryText(m.group("deathnum"), "Deaths: ", f); + IcoTextComponent deaths = new IcoTextComponent(Ico.SKULL, d); + this.addComponent(deaths); + } + + this.addSimpleIcoText(Ico.SWORD, "Damage Dealt:", Formatting.RED, 26); + this.addSimpleIcoText(Ico.POTION, "Healing Done:", Formatting.RED, 27); + this.addSimpleIcoText(Ico.NTAG, "Milestone:", Formatting.YELLOW, 28); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonDownedWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonDownedWidget.java new file mode 100644 index 00000000..9bb250f7 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonDownedWidget.java @@ -0,0 +1,42 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about... something? +// related to downed people in dungeons, not sure what this is supposed to show + +public class DungeonDownedWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Downed").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + public DungeonDownedWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + String down = PlayerListMgr.strAt(21); + if (down == null) { + this.addComponent(new IcoTextComponent()); + } else { + + Formatting format = Formatting.RED; + if (down.endsWith("NONE")) { + format = Formatting.GRAY; + } + int idx = down.indexOf(": "); + Text downed = (idx == -1) ? null + : Widget.simpleEntryText(down.substring(idx + 2), "Downed: ", format); + IcoTextComponent d = new IcoTextComponent(Ico.SKULL, downed); + this.addComponent(d); + } + + this.addSimpleIcoText(Ico.CLOCK, "Time:", Formatting.GRAY, 22); + this.addSimpleIcoText(Ico.POTION, "Revive:", Formatting.GRAY, 23); + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonPlayerWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonPlayerWidget.java new file mode 100644 index 00000000..c1f9e235 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonPlayerWidget.java @@ -0,0 +1,99 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about a player in the current dungeon group + +public class DungeonPlayerWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Player").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + // match a player entry + // group 1: name + // group 2: class (or literal "EMPTY" pre dungeon start) + // group 3: level (or nothing, if pre dungeon start) + // as a side effect, this regex keeps the iron man icon in the name + // not sure if that should be + private static final Pattern PLAYER_PATTERN = Pattern + .compile("\\[\\d*\\] (?<name>.*) \\((?<class>\\S*) ?(?<level>[LXVI]*)\\)"); + + private static final HashMap<String, ItemStack> ICOS = new HashMap<>(); + private static final ArrayList<String> MSGS = new ArrayList<>(); + static { + ICOS.put("Tank", Ico.CHESTPLATE); + ICOS.put("Mage", Ico.B_ROD); + ICOS.put("Berserk", Ico.DIASWORD); + ICOS.put("Archer", Ico.BOW); + ICOS.put("Healer", Ico.POTION); + + MSGS.add("PRESS A TO JOIN"); + MSGS.add("Invite a friend!"); + MSGS.add("But nobody came."); + MSGS.add("More is better!"); + } + + // title needs to be changeable here + public DungeonPlayerWidget(int player) { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + int start = 1 + (player - 1) * 4; + + if (PlayerListMgr.strAt(start) == null) { + int idx = player - 2; + IcoTextComponent noplayer = new IcoTextComponent(Ico.SIGN, + Text.literal(MSGS.get(idx)).formatted(Formatting.GRAY)); + this.addComponent(noplayer); + this.pack(); + return; + } + Matcher m = PlayerListMgr.regexAt(start, PLAYER_PATTERN); + if (m == null) { + this.addComponent(new IcoTextComponent()); + this.addComponent(new IcoTextComponent()); + } else { + + Text name = Text.literal("Name: ").append(Text.literal(m.group("name")).formatted(Formatting.YELLOW)); + this.addComponent(new IcoTextComponent(Ico.PLAYER, name)); + + String cl = m.group("class"); + String level = m.group("level"); + + if (level == null) { + PlainTextComponent ptc = new PlainTextComponent( + Text.literal("Player is dead").formatted(Formatting.RED)); + this.addComponent(ptc); + } else { + + Formatting clf = Formatting.GRAY; + ItemStack cli = Ico.BARRIER; + if (!cl.equals("EMPTY")) { + cli = ICOS.get(cl); + clf = Formatting.LIGHT_PURPLE; + cl += " " + m.group("level"); + } + + Text clazz = Text.literal("Class: ").append(Text.literal(cl).formatted(clf)); + IcoTextComponent itclass = new IcoTextComponent(cli, clazz); + this.addComponent(itclass); + } + } + + this.addSimpleIcoText(Ico.CLOCK, "Ult Cooldown:", Formatting.GOLD, start + 1); + this.addSimpleIcoText(Ico.POTION, "Revives:", Formatting.DARK_PURPLE, start + 2); + + this.pack(); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonPuzzleWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonPuzzleWidget.java new file mode 100644 index 00000000..2529e876 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonPuzzleWidget.java @@ -0,0 +1,55 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about all puzzeles in the dungeon (name and status) + +public class DungeonPuzzleWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Puzzles").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + // match a puzzle entry + // group 1: name + // group 2: status + // " ?.*" to diescard the solver's name if present + // the teleport maze has a trailing whitespace that messes with the regex + private static final Pattern PUZZLE_PATTERN = Pattern.compile("(?<name>.*): \\[(?<status>.*)\\] ?.*"); + + public DungeonPuzzleWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + int pos = 48; + + while (pos < 60) { + Matcher m = PlayerListMgr.regexAt(pos, PUZZLE_PATTERN); + if (m == null) { + break; + } + Text t = Text.literal(m.group("name") + ": ") + .append(Text.literal("[").formatted(Formatting.GRAY)) + .append(m.group("status")) + .append(Text.literal("]").formatted(Formatting.GRAY)); + IcoTextComponent itc = new IcoTextComponent(Ico.SIGN, t); + this.addComponent(itc); + pos++; + // code points for puzzle status chars unsolved and solved: 10022, 10004 + // not sure which one is which + // still need to find out codepoint for the puzzle failed char + } + if (pos == 48) { + this.addComponent( + new IcoTextComponent(Ico.BARRIER, Text.literal("No puzzles!").formatted(Formatting.GRAY))); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonSecretWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonSecretWidget.java new file mode 100644 index 00000000..93eb69de --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonSecretWidget.java @@ -0,0 +1,24 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about the secrets of the dungeon + +public class DungeonSecretWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Discoveries").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + public DungeonSecretWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + this.addSimpleIcoText(Ico.CHEST, "Secrets:", Formatting.YELLOW, 31); + this.addSimpleIcoText(Ico.SKULL, "Crypts:", Formatting.YELLOW, 32); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonServerWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonServerWidget.java new file mode 100644 index 00000000..81b8f907 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/DungeonServerWidget.java @@ -0,0 +1,47 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows broad info about the current dungeon +// opened/completed rooms, % of secrets found and time taken + +public class DungeonServerWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Dungeon Info").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + // match the secrets text + // group 1: % of secrets found (without "%") + private static final Pattern SECRET_PATTERN = Pattern.compile("Secrets Found: (?<secnum>.*)%"); + + public DungeonServerWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + this.addSimpleIcoText(Ico.NTAG, "Name:", Formatting.AQUA, 41); + this.addSimpleIcoText(Ico.SIGN, "Rooms Visited:", Formatting.DARK_PURPLE, 42); + this.addSimpleIcoText(Ico.SIGN, "Rooms Completed:", Formatting.LIGHT_PURPLE, 43); + + Matcher m = PlayerListMgr.regexAt(44, SECRET_PATTERN); + if (m == null) { + this.addComponent(new ProgressComponent()); + } else { + ProgressComponent scp = new ProgressComponent(Ico.CHEST, Text.of("Secrets found:"), + Float.parseFloat(m.group("secnum")), + Formatting.DARK_PURPLE.getColorValue()); + this.addComponent(scp); + } + + this.addSimpleIcoText(Ico.CLOCK, "Time:", Formatting.GOLD, 45); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EffectWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EffectWidget.java new file mode 100644 index 00000000..cd39a25a --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EffectWidget.java @@ -0,0 +1,64 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoFatTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widgte shows, how many active effects you have. +// it also shows one of those in detail. +// the parsing is super suspect and should be replaced by some regexes sometime later + +public class EffectWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Effect Info").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + public EffectWidget(String footertext) { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + + if (footertext == null || !footertext.contains("Active Effects")) { + this.addComponent(new IcoTextComponent()); + this.pack(); + return; + + } + + String[] lines = footertext.split("Active Effects")[1].split("\n"); + if (lines.length < 2) { + this.addComponent(new IcoTextComponent()); + this.pack(); + return; + } + + if (lines[1].startsWith("No")) { + Text txt = Text.literal("No effects active").formatted(Formatting.GRAY); + this.addComponent(new IcoTextComponent(Ico.POTION, txt)); + } else if (lines[1].contains("God")) { + String timeleft = lines[1].split("! ")[1]; + Text godpot = Text.literal("God potion!").formatted(Formatting.RED); + Text txttleft = Text.literal(timeleft).formatted(Formatting.LIGHT_PURPLE); + IcoFatTextComponent iftc = new IcoFatTextComponent(Ico.POTION, godpot, txttleft); + this.addComponent(iftc); + } else { + String number = lines[1].substring("You have ".length()); + int idx = number.indexOf(' '); + if (idx == -1 || lines.length < 4) { + this.addComponent(new IcoFatTextComponent()); + this.pack(); + return; + } + number = number.substring(0, idx); + Text active = Text.literal("Active Effects: ") + .append(Text.literal(number).formatted(Formatting.YELLOW)); + + IcoFatTextComponent iftc = new IcoFatTextComponent(Ico.POTION, active, + Text.literal(lines[3]).formatted(Formatting.AQUA)); + this.addComponent(iftc); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ElectionWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ElectionWidget.java new file mode 100644 index 00000000..ed07982c --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ElectionWidget.java @@ -0,0 +1,103 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows the status or results of the current election + +public class ElectionWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Election Info").formatted(Formatting.YELLOW, + Formatting.BOLD); + + private static final HashMap<String, ItemStack> MAYOR_DATA = new HashMap<>(); + + private static final Text EL_OVER = Text.literal("Election ") + .append(Text.literal("over!").formatted(Formatting.RED)); + + // pattern matching a candidate while people are voting + // group 1: name + // group 2: % of votes + private static final Pattern VOTE_PATTERN = Pattern.compile("(?<mayor>\\S*): \\|+ \\((?<pcnt>\\d*)%\\)"); + + static { + MAYOR_DATA.put("Aatrox", Ico.DIASWORD); + MAYOR_DATA.put("Cole", Ico.PICKAXE); + MAYOR_DATA.put("Diana", Ico.BONE); + MAYOR_DATA.put("Diaz", Ico.GOLD); + MAYOR_DATA.put("Finnegan", Ico.HOE); + MAYOR_DATA.put("Foxy", Ico.SUGAR); + MAYOR_DATA.put("Paul", Ico.COMPASS); + MAYOR_DATA.put("Scorpius", Ico.MOREGOLD); + MAYOR_DATA.put("Jerry", Ico.VILLAGER); + MAYOR_DATA.put("Derpy", Ico.DBUSH); + MAYOR_DATA.put("Marina", Ico.FISH_ROD); + } + + private static final Formatting[] COLS = { Formatting.GOLD, Formatting.RED, Formatting.LIGHT_PURPLE }; + + public ElectionWidget() { + super(TITLE, Formatting.YELLOW.getColorValue()); + + String status = PlayerListMgr.strAt(76); + if (status == null) { + this.addComponent(new IcoTextComponent()); + this.addComponent(new IcoTextComponent()); + this.addComponent(new IcoTextComponent()); + this.addComponent(new IcoTextComponent()); + this.pack(); + return; + } + + if (status.contains("Over!")) { + // election is over + IcoTextComponent over = new IcoTextComponent(Ico.BARRIER, EL_OVER); + this.addComponent(over); + + String win = PlayerListMgr.strAt(77); + if (win == null || !win.contains(": ")) { + this.addComponent(new IcoTextComponent()); + } else { + String winnername = win.split(": ")[1]; + Text winnertext = Widget.simpleEntryText(winnername, "Winner: ", Formatting.GREEN); + IcoTextComponent winner = new IcoTextComponent(MAYOR_DATA.get(winnername), winnertext); + this.addComponent(winner); + } + + this.addSimpleIcoText(Ico.PLAYER, "Participants:", Formatting.AQUA, 78); + this.addSimpleIcoText(Ico.SIGN, "Year:", Formatting.LIGHT_PURPLE, 79); + + } else { + // election is going on + this.addSimpleIcoText(Ico.CLOCK, "End in:", Formatting.GOLD, 76); + + for (int i = 77; i <= 79; i++) { + Matcher m = PlayerListMgr.regexAt(i, VOTE_PATTERN); + if (m == null) { + this.addComponent(new ProgressComponent()); + } else { + + String mayorname = m.group("mayor"); + String pcntstr = m.group("pcnt"); + float pcnt = Float.parseFloat(pcntstr); + Text candidate = Text.literal(mayorname).formatted(COLS[i - 77]); + ProgressComponent pc = new ProgressComponent(MAYOR_DATA.get(mayorname), candidate, pcnt, + COLS[i - 77].getColorValue()); + this.addComponent(pc); + } + } + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java new file mode 100644 index 00000000..52d6cfbd --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java @@ -0,0 +1,24 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// empty widget for when nothing can be shown + +public class EmptyWidget extends Widget { + private static final MutableText TITLE = Text.literal("Empty").formatted(Formatting.RED, + Formatting.BOLD); + + public EmptyWidget() { + super(TITLE, Formatting.RED.getColorValue()); + + Text info = Text.of("No info for this area!"); + PlainTextComponent inf = new PlainTextComponent(info); + this.addComponent(inf); + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EssenceWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EssenceWidget.java new file mode 100644 index 00000000..fc0780e1 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EssenceWidget.java @@ -0,0 +1,44 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.TableComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows your dungeon essences (dungeon hub only) + +public class EssenceWidget extends Widget { + + private Text undead, wither, diamond, gold, dragon, spider, ice, crimson; + + private static final MutableText TITLE = Text.literal("Essences").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public EssenceWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + wither = Widget.simpleEntryText(46, "Wither:", Formatting.DARK_PURPLE); + spider = Widget.simpleEntryText(47, "Spider:", Formatting.DARK_PURPLE); + undead = Widget.simpleEntryText(48, "Undead:", Formatting.DARK_PURPLE); + dragon = Widget.simpleEntryText(49, "Dragon:", Formatting.DARK_PURPLE); + gold = Widget.simpleEntryText(50, "Gold:", Formatting.DARK_PURPLE); + diamond = Widget.simpleEntryText(51, "Diamond:", Formatting.DARK_PURPLE); + ice = Widget.simpleEntryText(52, "Ice:", Formatting.DARK_PURPLE); + crimson = Widget.simpleEntryText(53, "Crimson:", Formatting.DARK_PURPLE); + + TableComponent tc = new TableComponent(2, 4, Formatting.DARK_AQUA.getColorValue()); + + tc.addToCell(0, 0, new IcoTextComponent(Ico.WITHER, wither)); + tc.addToCell(0, 1, new IcoTextComponent(Ico.STRING, spider)); + tc.addToCell(0, 2, new IcoTextComponent(Ico.FLESH, undead)); + tc.addToCell(0, 3, new IcoTextComponent(Ico.DRAGON, dragon)); + tc.addToCell(1, 0, new IcoTextComponent(Ico.GOLD, gold)); + tc.addToCell(1, 1, new IcoTextComponent(Ico.DIAMOND, diamond)); + tc.addToCell(1, 2, new IcoTextComponent(Ico.ICE, ice)); + tc.addToCell(1, 3, new IcoTextComponent(Ico.REDSTONE, crimson)); + this.addComponent(tc); + this.pack(); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EventWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EventWidget.java new file mode 100644 index 00000000..1b46e621 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EventWidget.java @@ -0,0 +1,30 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about ongoing events (e.g. election) + +public class EventWidget extends Widget { + private static final MutableText TITLE = Text.literal("Event Info").formatted(Formatting.YELLOW, Formatting.BOLD); + + public EventWidget(boolean isInGarden) { + super(TITLE, Formatting.YELLOW.getColorValue()); + + // hypixel devs carefully inserting the most random edge cases #317: + // the event info is placed a bit differently when in the garden. + int offset = (isInGarden) ? -1 : 0; + + this.addSimpleIcoText(Ico.NTAG, "Name:", Formatting.YELLOW, 73 + offset); + + // this could look better + Text time = Widget.plainEntryText(74 + offset); + IcoTextComponent t = new IcoTextComponent(Ico.CLOCK, time); + this.addComponent(t); + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/FireSaleWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/FireSaleWidget.java new file mode 100644 index 00000000..ddf51f32 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/FireSaleWidget.java @@ -0,0 +1,68 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.Formatting; + +// this widget shows info about fire sales when in the hub. +// or not, if there isn't one going on + +public class FireSaleWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Fire Sale").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + // matches a fire sale item + // group 1: item name + // group 2: # items available + // group 3: # items available in total (1 digit + "k") + private static final Pattern FIRE_PATTERN = Pattern.compile("(?<item>.*): (?<avail>\\d*)/(?<total>[0-9.]*)k"); + + public FireSaleWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + String event = PlayerListMgr.strAt(46); + + if (event == null) { + this.addComponent(new PlainTextComponent(Text.literal("No Fire Sale!").formatted(Formatting.GRAY))); + this.pack(); + return; + } + + if (event.contains("Starts In")) { + this.addSimpleIcoText(Ico.CLOCK, "Starts in:", Formatting.DARK_AQUA, 46); + this.pack(); + return; + } + + for (int i = 46;; i++) { + Matcher m = PlayerListMgr.regexAt( i, FIRE_PATTERN); + if (m == null) { + break; + } + String avail = m.group("avail"); + Text itemTxt = Text.literal(m.group("item")); + float total = Float.parseFloat(m.group("total")) * 1000; + Text prgressTxt = Text.literal(String.format("%s/%.0f", avail, total)); + float pcnt = (Float.parseFloat(avail) / (total)) * 100f; + ProgressComponent pc = new ProgressComponent(Ico.GOLD, itemTxt, prgressTxt, pcnt, pcntToCol(pcnt)); + this.addComponent(pc); + } + this.pack(); + + } + + private int pcntToCol(float pcnt) { + return MathHelper.hsvToRgb( pcnt / 300f, 0.9f, 0.9f); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ForgeWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ForgeWidget.java new file mode 100644 index 00000000..da1ba6c5 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ForgeWidget.java @@ -0,0 +1,79 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.Component; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoFatTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows what you're forging right now. +// for locked slots, the unlock requirement is shown + +public class ForgeWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Forge Status").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public ForgeWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + int forgestart = 54; + // why is it forges and not looms >:( + String pos = PlayerListMgr.strAt(53); + if (pos == null) { + this.addComponent(new IcoTextComponent()); + this.pack(); + return; + } + + if (!pos.startsWith("Forges")) { + forgestart += 2; + } + + for (int i = forgestart, slot = 1; i < forgestart + 5 && i < 60; i++, slot++) { + String fstr = PlayerListMgr.strAt(i); + if (fstr == null || fstr.length() < 3) { + if (i == forgestart) { + this.addComponent(new IcoTextComponent()); + } + break; + } + Component c; + Text l1, l2; + + switch (fstr.substring(3)) { + case "LOCKED": + l1 = Text.literal("Locked").formatted(Formatting.RED); + l2 = switch (slot) { + case 3 -> Text.literal("Needs HotM 3").formatted(Formatting.GRAY); + case 4 -> Text.literal("Needs HotM 4").formatted(Formatting.GRAY); + case 5 -> Text.literal("Needs PotM 2").formatted(Formatting.GRAY); + default -> + Text.literal("This message should not appear").formatted(Formatting.RED, Formatting.BOLD); + }; + c = new IcoFatTextComponent(Ico.BARRIER, l1, l2); + break; + case "EMPTY": + l1 = Text.literal("Empty").formatted(Formatting.GRAY); + c = new IcoTextComponent(Ico.FURNACE, l1); + break; + default: + String[] parts = fstr.split(": "); + if (parts.length != 2) { + c = new IcoFatTextComponent(); + } else { + l1 = Text.literal(parts[0].substring(3)).formatted(Formatting.YELLOW); + l2 = Text.literal("Done in: ").formatted(Formatting.GRAY).append(Text.literal(parts[1]).formatted(Formatting.WHITE)); + c = new IcoFatTextComponent(Ico.FIRE, l1, l2); + } + break; + } + this.addComponent(c); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenServerWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenServerWidget.java new file mode 100644 index 00000000..b0fc160f --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenServerWidget.java @@ -0,0 +1,53 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about the garden server + +public class GardenServerWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Server Info").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + // match the next visitor in the garden + // group 1: visitor name + private static final Pattern VISITOR_PATTERN = Pattern.compile("Next Visitor: (?<vis>.*)"); + + public GardenServerWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + this.addSimpleIcoText(Ico.MAP, "Area:", Formatting.DARK_AQUA, 41); + this.addSimpleIcoText(Ico.NTAG, "Server ID:", Formatting.GRAY, 42); + this.addSimpleIcoText(Ico.EMERALD, "Gems:", Formatting.GREEN, 43); + this.addSimpleIcoText(Ico.COPPER, "Copper:", Formatting.GOLD, 44); + + Matcher m = PlayerListMgr.regexAt(45, VISITOR_PATTERN); + if (m == null ) { + this.addComponent(new IcoTextComponent()); + this.pack(); + return; + } + + String vis = m.group("vis"); + Formatting col; + if (vis.equals("Not Unlocked!")) { + col = Formatting.RED; + } else { + col = Formatting.GREEN; + } + Text visitor = Widget.simpleEntryText(vis, "Next Visitor: ", col); + IcoTextComponent v = new IcoTextComponent(Ico.PLAYER, visitor); + this.addComponent(v); + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenSkillsWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenSkillsWidget.java new file mode 100644 index 00000000..26e29ce2 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenSkillsWidget.java @@ -0,0 +1,78 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.TableComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about your skills while in the garden + +public class GardenSkillsWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Skill Info").formatted(Formatting.YELLOW, + Formatting.BOLD); + + // match the skill entry + // group 1: skill name and level + // group 2: progress to next level (without "%") + private static final Pattern SKILL_PATTERN = Pattern + .compile("\\S*: (?<skill>[A-Za-z]* [0-9]*): (?<progress>\\S*)%"); + // same, but with leading space + private static final Pattern MS_PATTERN = Pattern.compile("\\S*: (?<skill>[A-Za-z]* [0-9]*): (?<progress>\\S*)%"); + + public GardenSkillsWidget() { + super(TITLE, Formatting.YELLOW.getColorValue()); + + ProgressComponent pc; + Matcher m = PlayerListMgr.regexAt(66, SKILL_PATTERN); + if (m == null) { + pc = new ProgressComponent(); + } else { + + String strpcnt = m.group("progress"); + String skill = m.group("skill"); + + float pcnt = Float.parseFloat(strpcnt); + pc = new ProgressComponent(Ico.LANTERN, Text.of(skill), pcnt, + Formatting.GOLD.getColorValue()); + } + + this.addComponent(pc); + + Text speed = Widget.simpleEntryText(67, "SPD", Formatting.WHITE); + IcoTextComponent spd = new IcoTextComponent(Ico.SUGAR, speed); + Text farmfort = Widget.simpleEntryText(68, "FFO", Formatting.GOLD); + IcoTextComponent ffo = new IcoTextComponent(Ico.HOE, farmfort); + + TableComponent tc = new TableComponent(2, 1, Formatting.YELLOW.getColorValue()); + tc.addToCell(0, 0, spd); + tc.addToCell(1, 0, ffo); + this.addComponent(tc); + + ProgressComponent pc2; + m = PlayerListMgr.regexAt(69, MS_PATTERN); + if (m == null) { + pc2 = new ProgressComponent(); + } else { + String strpcnt = m.group("progress"); + String skill = m.group("skill"); + + float pcnt = Float.parseFloat(strpcnt); + pc2 = new ProgressComponent(Ico.MILESTONE, Text.of(skill), pcnt, + Formatting.GREEN.getColorValue()); + + } + this.addComponent(pc2); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GuestServerWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GuestServerWidget.java new file mode 100644 index 00000000..cb208e92 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GuestServerWidget.java @@ -0,0 +1,28 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about the private island you're visiting + +public class GuestServerWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Island Info").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public GuestServerWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + this.addSimpleIcoText(Ico.MAP, "Area:", Formatting.DARK_AQUA, 41); + this.addSimpleIcoText(Ico.NTAG, "Server ID:", Formatting.GRAY, 42); + this.addSimpleIcoText(Ico.SIGN, "Owner:", Formatting.GREEN, 43); + this.addSimpleIcoText(Ico.SIGN, "Status:", Formatting.BLUE, 44); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandGuestsWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandGuestsWidget.java new file mode 100644 index 00000000..e0f5f1a3 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandGuestsWidget.java @@ -0,0 +1,44 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows a list of all people visiting the same private island as you + +public class IslandGuestsWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Guests").formatted(Formatting.AQUA, + Formatting.BOLD); + + // matches a player entry, removing their level and the hand icon + // group 1: player name + private static final Pattern GUEST_PATTERN = Pattern.compile("\\[\\d*\\] (.*) \\[.\\]"); + + public IslandGuestsWidget() { + super(TITLE, Formatting.AQUA.getColorValue()); + for (int i = 21; i < 40; i++) { + String str = PlayerListMgr.strAt(i); + if (str == null) { + if (i == 21) { + this.addComponent(new PlainTextComponent(Text.literal("No Visitors!").formatted(Formatting.GRAY))); + } + break; + } + Matcher m = PlayerListMgr.regexAt( i, GUEST_PATTERN); + if (m == null) { + this.addComponent(new PlainTextComponent(Text.of("???"))); + } else { + this.addComponent(new PlainTextComponent(Text.of(m.group(1)))); + } + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandOwnersWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandOwnersWidget.java new file mode 100644 index 00000000..6c2d6b47 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandOwnersWidget.java @@ -0,0 +1,60 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows a list of the owners of a home island while guesting + +public class IslandOwnersWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Owners").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + // matches an owner + // group 1: player name + // group 2: last seen, if owner not online + private static final Pattern OWNER_PATTERN = Pattern + .compile("^(?<nameA>.*) \\((?<lastseen>.*)\\)$|^\\[\\d*\\] (?<nameB>.*)$|^(?<nameC>.*)$"); + + public IslandOwnersWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + for (int i = 1; i < 20; i++) { + Matcher m = PlayerListMgr.regexAt(i, OWNER_PATTERN); + if (m == null) { + break; + } + + String name = null, lastseen = null; + Formatting format = null; + if (m.group("nameA") != null) { + name = m.group("nameA"); + lastseen = m.group("lastseen"); + format = Formatting.GRAY; + } else if (m.group("nameB")!=null){ + name = m.group("nameB"); + lastseen = "Online"; + format = Formatting.WHITE; + } else { + name = m.group("nameC"); + lastseen = "Online"; + format = Formatting.WHITE; + } + + Text entry = Text.literal(name) + .append( + Text.literal(" (" + lastseen + ")") + .formatted(format)); + PlainTextComponent ptc = new PlainTextComponent(entry); + this.addComponent(ptc); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandSelfWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandSelfWidget.java new file mode 100644 index 00000000..4324dad9 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandSelfWidget.java @@ -0,0 +1,37 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows a list of the owners while on your home island + +public class IslandSelfWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Owners").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + + // matches an owner + // group 1: player name, optionally offline time + private static final Pattern OWNER_PATTERN = Pattern.compile("^\\[\\d*\\] (.*)$|^(.*)$"); + + public IslandSelfWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + for (int i = 1; i < 20; i++) { + Matcher m = PlayerListMgr.regexAt( i, OWNER_PATTERN); + if (m == null) { + break; + } + PlainTextComponent ptc = new PlainTextComponent(Text.of(m.group(1))); + this.addComponent(ptc); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandServerWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandServerWidget.java new file mode 100644 index 00000000..2b02c514 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/IslandServerWidget.java @@ -0,0 +1,30 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about your home island + +public class IslandServerWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Island Info").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public IslandServerWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + this.addSimpleIcoText(Ico.MAP, "Area:", Formatting.DARK_AQUA, 41); + this.addSimpleIcoText(Ico.NTAG, "Server ID:", Formatting.GRAY, 42); + this.addSimpleIcoText(Ico.EMERALD, "Crystals:", Formatting.DARK_PURPLE, 43); + this.addSimpleIcoText(Ico.CHEST, "Stash:", Formatting.GREEN, 44); + this.addSimpleIcoText(Ico.COMMAND, "Minions:", Formatting.BLUE, 45); + + this.pack(); + + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/JacobsContestWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/JacobsContestWidget.java new file mode 100644 index 00000000..8d49efaa --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/JacobsContestWidget.java @@ -0,0 +1,60 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.HashMap; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.TableComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about the current jacob's contest (garden only) + +public class JacobsContestWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Jacob's Contest").formatted(Formatting.YELLOW, + Formatting.BOLD); + + private static final HashMap<String, ItemStack> FARM_DATA = new HashMap<>(); + + // again, there HAS to be a better way to do this + static { + FARM_DATA.put("Wheat", new ItemStack(Items.WHEAT)); + FARM_DATA.put("Sugar Cane", new ItemStack(Items.SUGAR_CANE)); + FARM_DATA.put("Carrot", new ItemStack(Items.CARROT)); + FARM_DATA.put("Potato", new ItemStack(Items.POTATO)); + FARM_DATA.put("Melon", new ItemStack(Items.MELON_SLICE)); + FARM_DATA.put("Pumpkin", new ItemStack(Items.PUMPKIN)); + FARM_DATA.put("Cocoa Beans", new ItemStack(Items.COCOA_BEANS)); + FARM_DATA.put("Nether Wart", new ItemStack(Items.NETHER_WART)); + FARM_DATA.put("Cactus", new ItemStack(Items.CACTUS)); + FARM_DATA.put("Mushroom", new ItemStack(Items.RED_MUSHROOM)); + } + + public JacobsContestWidget() { + super(TITLE, Formatting.YELLOW.getColorValue()); + + this.addSimpleIcoText(Ico.CLOCK, "Starts in:", Formatting.GOLD, 76); + + TableComponent tc = new TableComponent(1, 3, Formatting.YELLOW .getColorValue()); + + for (int i = 77; i < 80; i++) { + String item = PlayerListMgr.strAt(i); + IcoTextComponent itc; + if (item == null) { + itc = new IcoTextComponent(); + } else { + itc = new IcoTextComponent(FARM_DATA.get(item), Text.of(item)); + } + tc.addToCell(0, i - 77, itc); + } + this.addComponent(tc); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/MinionWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/MinionWidget.java new file mode 100644 index 00000000..22082202 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/MinionWidget.java @@ -0,0 +1,133 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; + +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about minions placed on the home island + +public class MinionWidget extends Widget { + private static final MutableText TITLE = Text.literal("Minions").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + private static final HashMap<String, ItemStack> MIN_ICOS = new HashMap<>(); + + // hmm... + static { + MIN_ICOS.put("Blaze", new ItemStack(Items.BLAZE_ROD)); + MIN_ICOS.put("Cave Spider", new ItemStack(Items.SPIDER_EYE)); + MIN_ICOS.put("Creeper", new ItemStack(Items.GUNPOWDER)); + MIN_ICOS.put("Enderman", new ItemStack(Items.ENDER_PEARL)); + MIN_ICOS.put("Ghast", new ItemStack(Items.GHAST_TEAR)); + MIN_ICOS.put("Magma Cube", new ItemStack(Items.MAGMA_CREAM)); + MIN_ICOS.put("Skeleton", new ItemStack(Items.BONE)); + MIN_ICOS.put("Slime", new ItemStack(Items.SLIME_BALL)); + MIN_ICOS.put("Spider", new ItemStack(Items.STRING)); + MIN_ICOS.put("Zombie", new ItemStack(Items.ROTTEN_FLESH)); + MIN_ICOS.put("Cactus", new ItemStack(Items.CACTUS)); + MIN_ICOS.put("Carrot", new ItemStack(Items.CARROT)); + MIN_ICOS.put("Chicken", new ItemStack(Items.CHICKEN)); + MIN_ICOS.put("Cocoa Beans", new ItemStack(Items.COCOA_BEANS)); + MIN_ICOS.put("Cow", new ItemStack(Items.BEEF)); + MIN_ICOS.put("Melon", new ItemStack(Items.MELON_SLICE)); + MIN_ICOS.put("Mushroom", new ItemStack(Items.RED_MUSHROOM)); + MIN_ICOS.put("Nether Wart", new ItemStack(Items.NETHER_WART)); + MIN_ICOS.put("Pig", new ItemStack(Items.PORKCHOP)); + MIN_ICOS.put("Potato", new ItemStack(Items.POTATO)); + MIN_ICOS.put("Pumpkin", new ItemStack(Items.PUMPKIN)); + MIN_ICOS.put("Rabbit", new ItemStack(Items.RABBIT)); + MIN_ICOS.put("Sheep", new ItemStack(Items.WHITE_WOOL)); + MIN_ICOS.put("Sugar Cane", new ItemStack(Items.SUGAR_CANE)); + MIN_ICOS.put("Wheat", new ItemStack(Items.WHEAT)); + MIN_ICOS.put("Clay", new ItemStack(Items.CLAY)); + MIN_ICOS.put("Fishing", new ItemStack(Items.FISHING_ROD)); + MIN_ICOS.put("Coal", new ItemStack(Items.COAL)); + MIN_ICOS.put("Cobblestone", new ItemStack(Items.COBBLESTONE)); + MIN_ICOS.put("Diamond", new ItemStack(Items.DIAMOND)); + MIN_ICOS.put("Emerald", new ItemStack(Items.EMERALD)); + MIN_ICOS.put("End Stone", new ItemStack(Items.END_STONE)); + MIN_ICOS.put("Glowstone", new ItemStack(Items.GLOWSTONE_DUST)); + MIN_ICOS.put("Gold", new ItemStack(Items.GOLD_INGOT)); + MIN_ICOS.put("Gravel", new ItemStack(Items.GRAVEL)); + MIN_ICOS.put("Hard Stone", new ItemStack(Items.STONE)); + MIN_ICOS.put("Ice", new ItemStack(Items.ICE)); + MIN_ICOS.put("Iron", new ItemStack(Items.IRON_INGOT)); + MIN_ICOS.put("Lapis", new ItemStack(Items.LAPIS_LAZULI)); + MIN_ICOS.put("Mithril", new ItemStack(Items.PRISMARINE_CRYSTALS)); + MIN_ICOS.put("Mycelium", new ItemStack(Items.MYCELIUM)); + MIN_ICOS.put("Obsidian", new ItemStack(Items.OBSIDIAN)); + MIN_ICOS.put("Quartz", new ItemStack(Items.QUARTZ)); + MIN_ICOS.put("Red Sand", new ItemStack(Items.RED_SAND)); + MIN_ICOS.put("Redstone", new ItemStack(Items.REDSTONE)); + MIN_ICOS.put("Sand", new ItemStack(Items.SAND)); + MIN_ICOS.put("Snow", new ItemStack(Items.SNOWBALL)); + MIN_ICOS.put("Inferno", new ItemStack(Items.BLAZE_SPAWN_EGG)); + MIN_ICOS.put("Revenant", new ItemStack(Items.ZOMBIE_SPAWN_EGG)); + MIN_ICOS.put("Tarantula", new ItemStack(Items.SPIDER_SPAWN_EGG)); + MIN_ICOS.put("Voidling", new ItemStack(Items.ENDERMAN_SPAWN_EGG)); + MIN_ICOS.put("Acacia", new ItemStack(Items.ACACIA_LOG)); + MIN_ICOS.put("Birch", new ItemStack(Items.BIRCH_LOG)); + MIN_ICOS.put("Dark Oak", new ItemStack(Items.DARK_OAK_LOG)); + MIN_ICOS.put("Flower", new ItemStack(Items.POPPY)); + MIN_ICOS.put("Jungle", new ItemStack(Items.JUNGLE_LOG)); + MIN_ICOS.put("Oak", new ItemStack(Items.OAK_LOG)); + MIN_ICOS.put("Spruce", new ItemStack(Items.SPRUCE_LOG)); + } + + // matches a minion entry + // group 1: name + // group 2: level + // group 3: status + public static final Pattern MINION_PATTERN = Pattern.compile("(?<name>.*) (?<level>[XVI]*) \\[(?<status>.*)\\]"); + + public MinionWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + for (int i = 48; i < 59; i++) { + Matcher m = PlayerListMgr.regexAt(i, MINION_PATTERN); + if (m != null) { + + String min = m.group("name"); + String lvl = m.group("level"); + String stat = m.group("status"); + + MutableText mt = Text.literal(min + " " + lvl).append(Text.literal(": ")); + + Formatting format = Formatting.RED; + if (stat.equals("ACTIVE")) { + format = Formatting.GREEN; + } else if (stat.equals("SLOW")) { + format = Formatting.YELLOW; + } + // makes "BLOCKED" also red. in reality, it's some kind of crimson + mt.append(Text.literal(stat).formatted(format)); + + IcoTextComponent itc = new IcoTextComponent(MIN_ICOS.get(min), mt); + this.addComponent(itc); + + } else { + break; + } + } + + // if more minions are placed than the tab menu can display, + // a "And X more..." text is shown + // look for that and add it to the widget + String more = PlayerListMgr.strAt(59); + if (more != null) { + this.addComponent(new PlainTextComponent(Text.of(more))); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ParkServerWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ParkServerWidget.java new file mode 100644 index 00000000..4148ed77 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ParkServerWidget.java @@ -0,0 +1,28 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about the park server + +public class ParkServerWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Server Info").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public ParkServerWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + this.addSimpleIcoText(Ico.MAP, "Area:", Formatting.DARK_AQUA, 41); + this.addSimpleIcoText(Ico.NTAG, "Server ID:", Formatting.GRAY, 42); + this.addSimpleIcoText(Ico.EMERALD, "Gems:", Formatting.GREEN, 43); + this.addSimpleIcoText(Ico.WATER, "Rain:", Formatting.BLUE, 44); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/PlayerListWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/PlayerListWidget.java new file mode 100644 index 00000000..2cd710eb --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/PlayerListWidget.java @@ -0,0 +1,73 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlayerComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.TableComponent; + +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows a list of players with their skins. +// responsible for non-private-island areas + +public class PlayerListWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Players").formatted(Formatting.GREEN, + Formatting.BOLD); + + private ArrayList<PlayerListEntry> list = new ArrayList<>(); + + public PlayerListWidget() { + super(TITLE, Formatting.GREEN.getColorValue()); + + // hard cap to 4x20 entries. + // 5x20 is too wide (and not possible in theory. in reality however...) + int listlen = Math.min(PlayerListMgr.getSize(), 160); + + // list isn't fully loaded, so our hack won't work... + if (listlen < 80) { + this.addComponent(new PlainTextComponent(Text.literal("List loading...").formatted(Formatting.GRAY))); + this.pack(); + return; + } + + // unintuitive int ceil division stolen from + // https://stackoverflow.com/questions/7139382/java-rounding-up-to-an-int-using-math-ceil#21830188 + int tblW = ((listlen - 80) - 1) / 20 + 1; + + TableComponent tc = new TableComponent(tblW, (listlen - 80 >= 20) ? 20 : listlen - 80, + Formatting.GREEN.getColorValue()); + + for (int i = 80; i < listlen; i++) { + list.add(PlayerListMgr.getRaw(i)); + } + + Collections.sort(list, new Comparator<PlayerListEntry>() { + @Override + public int compare(PlayerListEntry o1, PlayerListEntry o2) { + return o1.getProfile().getName().toLowerCase().compareTo(o2.getProfile().getName().toLowerCase()); + } + }); + + int x = 0, y = 0; + + for (PlayerListEntry ple : list) { + tc.addToCell(x, y, new PlayerComponent(ple)); + y++; + if (y >= 20) { + y = 0; + x++; + } + } + + this.addComponent(tc); + this.pack(); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/PowderWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/PowderWidget.java new file mode 100644 index 00000000..459e3de2 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/PowderWidget.java @@ -0,0 +1,28 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows how much mithril and gemstone powder you have +// (dwarven mines and crystal hollows) + +public class PowderWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Powders").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public PowderWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + this.addSimpleIcoText(Ico.MITHRIL, "Mithril:", Formatting.AQUA, 46); + this.addSimpleIcoText(Ico.EMERALD, "Gemstone:", Formatting.DARK_PURPLE, 47); + + this.pack(); + + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ProfileWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ProfileWidget.java new file mode 100644 index 00000000..a6d9e82d --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ProfileWidget.java @@ -0,0 +1,25 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about your profile and bank + +public class ProfileWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Profile").formatted(Formatting.YELLOW, Formatting.BOLD); + + public ProfileWidget() { + super(TITLE, Formatting.YELLOW.getColorValue()); + + this.addSimpleIcoText(Ico.SIGN, "Profile:", Formatting.GREEN, 61); + this.addSimpleIcoText(Ico.BONE, "Pet Sitter:", Formatting.AQUA, 62); + this.addSimpleIcoText(Ico.EMERALD, "Balance:", Formatting.GOLD, 63); + this.addSimpleIcoText(Ico.CLOCK, "Interest in:", Formatting.GOLD, 64); + + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/QuestWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/QuestWidget.java new file mode 100644 index 00000000..5c89964e --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/QuestWidget.java @@ -0,0 +1,29 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows your crimson isle faction quests + +public class QuestWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Faction Quests").formatted(Formatting.AQUA, + Formatting.BOLD); + + public QuestWidget() { + super(TITLE, Formatting.AQUA.getColorValue()); + + for (int i = 51; i < 56; i++) { + Text q = Widget.plainEntryText(i); + IcoTextComponent itc = new IcoTextComponent(Ico.BOOK, q); + this.addComponent(itc); + } + this.pack(); + + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ReputationWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ReputationWidget.java new file mode 100644 index 00000000..c0379623 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ReputationWidget.java @@ -0,0 +1,67 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows your faction status (crimson isle) + +public class ReputationWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Faction Status").formatted(Formatting.AQUA, + Formatting.BOLD); + + // matches your faction alignment progress + // group 1: percentage to next alignment level + private static final Pattern PROGRESS_PATTERN = Pattern.compile("\\|+ \\((?<prog>[0-9.]*)%\\)"); + + // matches alignment level names + // group 1: left level name + // group 2: right level name + private static final Pattern STATE_PATTERN = Pattern.compile("(?<from>\\S*) *(?<to>\\S*)"); + + public ReputationWidget() { + super(TITLE, Formatting.AQUA.getColorValue()); + + String fracstr = PlayerListMgr.strAt(45); + + int spaceidx; + IcoTextComponent faction; + if (fracstr == null || (spaceidx = fracstr.indexOf(' ')) == -1) { + faction = new IcoTextComponent(); + } else { + String fname = fracstr.substring(0, spaceidx); + if (fname.equals("Mage")) { + faction = new IcoTextComponent(Ico.POTION, Text.literal(fname).formatted(Formatting.DARK_AQUA)); + } else { + faction = new IcoTextComponent(Ico.SWORD, Text.literal(fname).formatted(Formatting.RED)); + } + } + this.addComponent(faction); + + Text rep = Widget.plainEntryText(46); + Matcher prog = PlayerListMgr.regexAt(47, PROGRESS_PATTERN); + Matcher state = PlayerListMgr.regexAt(48, STATE_PATTERN); + + if (prog == null || state == null) { + this.addComponent(new ProgressComponent()); + } else { + float pcnt = Float.parseFloat(prog.group("prog")); + ProgressComponent pc = new ProgressComponent(Ico.LANTERN, + Text.of(state.group("from") + " -> " + state.group("to")), rep, pcnt, + Formatting.AQUA.getColorValue()); + this.addComponent(pc); + } + + this.pack(); + + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ServerWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ServerWidget.java new file mode 100644 index 00000000..2d8d1c63 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/ServerWidget.java @@ -0,0 +1,28 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about "generic" servers. +// a server is "generic", when only name, server ID and gems are shown +// in the third column of the tab HUD + +public class ServerWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Server Info").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public ServerWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + this.addSimpleIcoText(Ico.MAP, "Area:", Formatting.DARK_AQUA, 41); + this.addSimpleIcoText(Ico.NTAG, "Server ID:", Formatting.GRAY, 42); + this.addSimpleIcoText(Ico.EMERALD, "Gems:", Formatting.GREEN, 43); + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/SkillsWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/SkillsWidget.java new file mode 100644 index 00000000..88ba8022 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/SkillsWidget.java @@ -0,0 +1,75 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.Component; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoFatTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.TableComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about a skill and some stats, +// as seen in the rightmost column of the default HUD + +public class SkillsWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Skill Info").formatted(Formatting.YELLOW, + Formatting.BOLD); + + // match the skill entry + // group 1: skill name and level + // group 2: progress to next level (without "%") + private static final Pattern SKILL_PATTERN = Pattern.compile("\\S*: ([A-Za-z]* [0-9]*): ([0-9.MAX]*)%?"); + + public SkillsWidget() { + super(TITLE, Formatting.YELLOW.getColorValue()); + + Matcher m = PlayerListMgr.regexAt(66, SKILL_PATTERN); + Component progress; + if (m == null) { + progress = new ProgressComponent(); + } else { + + String skill = m.group(1); + String pcntStr = m.group(2); + + if (!pcntStr.equals("MAX")) { + float pcnt = Float.parseFloat(pcntStr); + progress = new ProgressComponent(Ico.LANTERN, Text.of(skill), + Text.of(pcntStr + "%"), pcnt, Formatting.GOLD.getColorValue()); + } else { + progress = new IcoFatTextComponent(Ico.LANTERN, Text.of(skill), + Text.literal(pcntStr).formatted(Formatting.RED)); + } + } + + this.addComponent(progress); + + Text speed = Widget.simpleEntryText(67, "SPD", Formatting.WHITE); + IcoTextComponent spd = new IcoTextComponent(Ico.SUGAR, speed); + Text strength = Widget.simpleEntryText(68, "STR", Formatting.RED); + IcoTextComponent str = new IcoTextComponent(Ico.SWORD, strength); + Text critDmg = Widget.simpleEntryText(69, "CCH", Formatting.BLUE); + IcoTextComponent cdg = new IcoTextComponent(Ico.SWORD, critDmg); + Text critCh = Widget.simpleEntryText(70, "CDG", Formatting.BLUE); + IcoTextComponent cch = new IcoTextComponent(Ico.SWORD, critCh); + Text aSpeed = Widget.simpleEntryText(71, "ASP", Formatting.YELLOW); + IcoTextComponent asp = new IcoTextComponent(Ico.HOE, aSpeed); + + TableComponent tc = new TableComponent(2, 3, Formatting.YELLOW.getColorValue()); + tc.addToCell(0, 0, spd); + tc.addToCell(0, 1, str); + tc.addToCell(0, 2, asp); + tc.addToCell(1, 0, cdg); + tc.addToCell(1, 1, cch); + this.addComponent(tc); + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/TrapperWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/TrapperWidget.java new file mode 100644 index 00000000..d47849c3 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/TrapperWidget.java @@ -0,0 +1,22 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows how meny pelts you have (farming island) + +public class TrapperWidget extends Widget { + private static final MutableText TITLE = Text.literal("Trapper").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + public TrapperWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + + this.addSimpleIcoText(Ico.LEATHER, "Pelts:", Formatting.AQUA, 46); + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/UpgradeWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/UpgradeWidget.java new file mode 100644 index 00000000..ef7c21d0 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/UpgradeWidget.java @@ -0,0 +1,47 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; + +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows info about ongoing profile/account upgrades +// or not, if there aren't any +// TODO: not very pretty atm + +public class UpgradeWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Upgrade Info").formatted(Formatting.GOLD, + Formatting.BOLD); + + public UpgradeWidget(String footertext) { + super(TITLE, Formatting.GOLD.getColorValue()); + if (footertext == null) { + this.addComponent(new PlainTextComponent(Text.literal("No data").formatted(Formatting.GRAY))); + this.pack(); + return; + } + + if (!footertext.contains("Upgrades")) { + this.addComponent(new PlainTextComponent(Text.of("Currently no upgrades..."))); + this.pack(); + return; + } + + String interesting = footertext.split("Upgrades")[1]; + String[] lines = interesting.split("\n"); + + for (int i = 1; i < lines.length; i++) { + if (lines[i].trim().length() < 3) { // empty line is §s + break; + } + IcoTextComponent itc = new IcoTextComponent(Ico.SIGN, Text.of(lines[i])); + this.addComponent(itc); + } + this.pack(); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/VolcanoWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/VolcanoWidget.java new file mode 100644 index 00000000..ec6a35fb --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/VolcanoWidget.java @@ -0,0 +1,57 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.HashMap; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Pair; + +// shows the volcano status (crimson isle) + +public class VolcanoWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Volcano Status").formatted(Formatting.AQUA, + Formatting.BOLD); + + private static final HashMap<String, Pair<ItemStack, Formatting>> BOOM_TYPE = new HashMap<>(); + + static { + BOOM_TYPE.put("INACTIVE", + new Pair<ItemStack, Formatting>(new ItemStack(Items.BARRIER), Formatting.DARK_GRAY)); + BOOM_TYPE.put("CHILL", + new Pair<ItemStack, Formatting>(new ItemStack(Items.ICE), Formatting.AQUA)); + BOOM_TYPE.put("LOW", + new Pair<ItemStack, Formatting>(new ItemStack(Items.FLINT_AND_STEEL), Formatting.GRAY)); + BOOM_TYPE.put("DISRUPTIVE", + new Pair<ItemStack, Formatting>(new ItemStack(Items.CAMPFIRE), Formatting.WHITE)); + BOOM_TYPE.put("MEDIUM", + new Pair<ItemStack, Formatting>(new ItemStack(Items.LAVA_BUCKET), Formatting.YELLOW)); + BOOM_TYPE.put("HIGH", + new Pair<ItemStack, Formatting>(new ItemStack(Items.FIRE_CHARGE), Formatting.GOLD)); + BOOM_TYPE.put("EXPLOSIVE", + new Pair<ItemStack, Formatting>(new ItemStack(Items.TNT), Formatting.RED)); + BOOM_TYPE.put("CATACLYSMIC", + new Pair<ItemStack, Formatting>(new ItemStack(Items.SKELETON_SKULL), Formatting.DARK_RED)); + } + + public VolcanoWidget() { + super(TITLE, Formatting.AQUA.getColorValue()); + + String s = PlayerListMgr.strAt(58); + if (s == null) { + this.addComponent(new IcoTextComponent()); + } else { + Pair<ItemStack, Formatting> p = BOOM_TYPE.get(s); + this.addComponent(new IcoTextComponent(p.getLeft(), Text.literal(s).formatted(p.getRight()))); + } + + this.pack(); + + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java new file mode 100644 index 00000000..6b96c151 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java @@ -0,0 +1,202 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import java.util.ArrayList; + +import com.mojang.blaze3d.systems.RenderSystem; + +import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.Component; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.IcoTextComponent; +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.item.ItemStack; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +/** + * Abstract base class for a Widget. + * Widgets are containers for components with a border and a title. + * Their size is dependent on the components inside, + * the position may be changed after construction. + */ +public abstract class Widget { + + private ArrayList<Component> components = new ArrayList<>(); + private int w = 0, h = 0; + private int x = 0, y = 0; + private int color; + private Text title; + + private static TextRenderer txtRend = MinecraftClient.getInstance().textRenderer; + + static final int BORDER_SZE_N = txtRend.fontHeight + 4; + static final int BORDER_SZE_S = 4; + static final int BORDER_SZE_W = 4; + static final int BORDER_SZE_E = 4; + static final int COL_BG_BOX = 0xc00c0c0c; + + public Widget(MutableText title, Integer colorValue) { + this.title = title; + this.color = 0xff000000 | colorValue; + } + + public final void addComponent(Component c) { + components.add(c); + } + + /** + * Shorthand function for simple components. + * If the entry at idx has the format "<textA>: <textB>", an IcoTextComponent is added as such: + * [ico] [string] [textB.formatted(fmt)] + */ + public final void addSimpleIcoText(ItemStack ico, String string, Formatting fmt, int idx) { + Text txt = Widget.simpleEntryText(idx, string, fmt); + this.addComponent(new IcoTextComponent(ico, txt)); + } + + /** + * Calculate the size of this widget. + * <b>Must be called before returning from the widget constructor and after all components are added!</b> + */ + public final void pack() { + for (Component c : components) { + h += c.getHeight() + Component.PAD_L; + w = Math.max(w, c.getWidth() + Component.PAD_S); + } + + h -= Component.PAD_L / 2; // less padding after lowest/last component + h += BORDER_SZE_N + BORDER_SZE_S - 2; + w += BORDER_SZE_E + BORDER_SZE_W; + + // min width is dependent on title + w = Math.max(w, BORDER_SZE_W + BORDER_SZE_E + Widget.txtRend.getWidth(title) + 4 + 4 + 1); + } + + public final void setX(int x) { + this.x = x; + } + + public final int getY() { + return this.y; + } + + public final int getX() { + return this.x; + } + + public final void setY(int y) { + this.y = y; + } + + public final int getWidth() { + return this.w; + } + + public final int getHeight() { + return this.h; + } + + /** + * Draw this widget with a background + */ + public final void render(MatrixStack ms) { + this.render(ms, true); + } + + /** + * Draw this widget, possibly with a background + */ + public final void render(MatrixStack ms, boolean hasBG) { + + // not sure if this is the way to go, but it fixes Z-layer issues + // like blocks being rendered behind the BG and the hotbar clipping into things + RenderSystem.enableDepthTest(); + ms.push(); + + float scale = SkyblockerConfig.get().general.tabHud.tabHudScale / 100f; + ms.scale(scale, scale, 1); + + // move above other UI elements + ms.translate(0, 0, 200); + if (hasBG) { + DrawableHelper.fill(ms, x + 1, y, x + w - 1, y + h, COL_BG_BOX); + DrawableHelper.fill(ms, x, y + 1, x + 1, y + h - 1, COL_BG_BOX); + DrawableHelper.fill(ms, x + w - 1, y + 1, x + w, y + h - 1, COL_BG_BOX); + } + // move above background (if exists) + ms.translate(0, 0, 100); + + int strHeightHalf = Widget.txtRend.fontHeight / 2; + int strAreaWidth = Widget.txtRend.getWidth(title) + 4; + + txtRend.draw(ms, title, x + 8, y + 2, this.color); + + this.drawHLine(ms, x + 2, y + 1 + strHeightHalf, 4); + this.drawHLine(ms, x + 2 + strAreaWidth + 4, y + 1 + strHeightHalf, w - 4 - 4 - strAreaWidth); + this.drawHLine(ms, x + 2, y + h - 2, w - 4); + + this.drawVLine(ms, x + 1, y + 2 + strHeightHalf, h - 4 - strHeightHalf); + this.drawVLine(ms, x + w - 2, y + 2 + strHeightHalf, h - 4 - strHeightHalf); + + int yOffs = y + BORDER_SZE_N; + + for (Component c : components) { + c.render(ms, x + BORDER_SZE_W, yOffs); + yOffs += c.getHeight() + Component.PAD_L; + } + // pop manipulations above + ms.pop(); + RenderSystem.disableDepthTest(); + } + + private void drawHLine(MatrixStack ms, int xpos, int ypos, int width) { + DrawableHelper.fill(ms, xpos, ypos, xpos + width, ypos + 1, this.color); + } + + private void drawVLine(MatrixStack ms, int xpos, int ypos, int height) { + DrawableHelper.fill(ms, xpos, ypos, xpos + 1, ypos + height, this.color); + } + + /** + * If the entry at idx has the format "[textA]: [textB]", the following is returned: + * [entryName] [textB.formatted(contentFmt)] + */ + public static Text simpleEntryText(int idx, String entryName, Formatting contentFmt) { + + String src = PlayerListMgr.strAt(idx); + + if (src == null) { + return null; + } + + int cidx = src.indexOf(':'); + if (cidx == -1) { + return null; + } + + src = src.substring(src.indexOf(':') + 1); + return Widget.simpleEntryText(src, entryName, contentFmt); + } + + /** + * @return [entryName] [entryContent.formatted(contentFmt)] + */ + public static Text simpleEntryText(String entryContent, String entryName, Formatting contentFmt) { + return Text.literal(entryName).append(Text.literal(entryContent).formatted(contentFmt)); + } + + /** + * @return the entry at idx as unformatted Text + */ + public static Text plainEntryText(int idx) { + String str = PlayerListMgr.strAt(idx); + if (str == null) { + return null; + } + return Text.of(str); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/Component.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/Component.java new file mode 100644 index 00000000..671b1f41 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/Component.java @@ -0,0 +1,33 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.util.math.MatrixStack; + +/** + * Abstract base class for a component that may be added to a Widget. + */ +public abstract class Component { + + static final int ICO_DIM = 16; + public static final int PAD_S = 2; + public static final int PAD_L = 4; + + static TextRenderer txtRend = MinecraftClient.getInstance().textRenderer; + static ItemRenderer itmRend = MinecraftClient.getInstance().getItemRenderer(); + + // these should always be the content dimensions without any padding. + int width, height; + + public abstract void render(MatrixStack ms, int x, int y); + + public int getWidth() { + return this.width; + } + + public int getHeight() { + return this.height; + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/IcoFatTextComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/IcoFatTextComponent.java new file mode 100644 index 00000000..f845eba5 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/IcoFatTextComponent.java @@ -0,0 +1,45 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +/** + * Component that consists of an icon and two lines of text + */ +public class IcoFatTextComponent extends Component { + + private static final int ICO_OFFS = 1; + + private ItemStack ico; + private Text line1, line2; + + public IcoFatTextComponent(ItemStack ico, Text l1, Text l2) { + this.ico = (ico == null) ? Ico.BARRIER : ico; + this.line1 = l1; + this.line2 = l2; + + if (l1 == null || l2 == null) { + this.ico = Ico.BARRIER; + this.line1 = Text.literal("No data").formatted(Formatting.GRAY); + this.line2 = Text.literal("No data").formatted(Formatting.GRAY); + } + + this.width = ICO_DIM + PAD_L + Math.max(txtRend.getWidth(this.line1), txtRend.getWidth(this.line2)); + this.height = txtRend.fontHeight + PAD_S + txtRend.fontHeight; + } + + public IcoFatTextComponent() { + this(null, null, null); + } + + @Override + public void render(MatrixStack ms, int x, int y) { + itmRend.renderGuiItemIcon(ms, ico, x, y + ICO_OFFS); + txtRend.draw(ms, line1, x + ICO_DIM + PAD_L, y, 0xffffffff); + txtRend.draw(ms, line2, x + ICO_DIM + PAD_L, y + txtRend.fontHeight + PAD_S, 0xffffffff); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/IcoTextComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/IcoTextComponent.java new file mode 100644 index 00000000..7a495a13 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/IcoTextComponent.java @@ -0,0 +1,40 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +/** + * Component that consists of an icon and a line of text. + */ +public class IcoTextComponent extends Component { + + private ItemStack ico; + private Text text; + + public IcoTextComponent(ItemStack ico, Text txt) { + this.ico = (ico == null) ? Ico.BARRIER : ico; + this.text = txt; + + if (txt == null) { + this.ico = Ico.BARRIER; + this.text = Text.literal("No data").formatted(Formatting.GRAY); + } + + this.width = ICO_DIM + PAD_L + txtRend.getWidth(this.text); + this.height = ICO_DIM; + } + + public IcoTextComponent() { + this(null, null); + } + + @Override + public void render(MatrixStack ms, int x, int y) { + itmRend.renderGuiItemIcon(ms, ico, x, y); + txtRend.draw(ms, text, x + ICO_DIM + PAD_L, y + 5, 0xffffffff); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/PlainTextComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/PlainTextComponent.java new file mode 100644 index 00000000..265d11f1 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/PlainTextComponent.java @@ -0,0 +1,30 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component; + +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +/** + * Component that consists of a line of text. + */ +public class PlainTextComponent extends Component { + + private Text text; + + public PlainTextComponent(Text txt) { + this.text = txt; + + if (txt == null) { + this.text = Text.literal("No data").formatted(Formatting.GRAY); + } + + this.width = PAD_S + txtRend.getWidth(this.text); // looks off without padding + this.height = txtRend.fontHeight; + } + + @Override + public void render(MatrixStack ms, int x, int y) { + txtRend.draw(ms, text, x + PAD_S, y, 0xffffffff); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/PlayerComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/PlayerComponent.java new file mode 100644 index 00000000..18859080 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/PlayerComponent.java @@ -0,0 +1,36 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.gui.PlayerSkinDrawer; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; + +/** + * Component that consists of a player's skin icon and their name + */ +public class PlayerComponent extends Component { + + private static final int SKIN_ICO_DIM = 8; + + private String name; + private Identifier tex; + + public PlayerComponent(PlayerListEntry ple) { + + name = ple.getProfile().getName(); + tex = ple.getSkinTexture(); + + this.width = SKIN_ICO_DIM + PAD_S + txtRend.getWidth(name); + this.height = txtRend.fontHeight; + } + + @Override + public void render(MatrixStack ms, int x, int y) { + RenderSystem.setShaderTexture(0, tex); + PlayerSkinDrawer.draw(ms, x, y, SKIN_ICO_DIM); + txtRend.draw(ms, name, x + SKIN_ICO_DIM + PAD_S, y, 0xffffffff); + } + +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/ProgressComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/ProgressComponent.java new file mode 100644 index 00000000..b9ebc0e9 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/ProgressComponent.java @@ -0,0 +1,70 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + + +/** + * Component that consists of an icon, some text and a progress bar. + * The progress bar either shows the fill percentage or custom text. + * NOTICE: pcnt is 0-100, not 0-1! + */ +public class ProgressComponent extends Component { + + private static final int BAR_WIDTH = 100; + private static final int BAR_HEIGHT = txtRend.fontHeight + 3; + private static final int ICO_OFFS = 4; + private static final int COL_BG_BAR = 0xf0101010; + + private ItemStack ico; + private Text desc, bar; + private float pcnt; + private int color; + private int barW; + + public ProgressComponent(ItemStack ico, Text d, Text b, float pcnt, int color) { + this.ico = (ico == null) ? Ico.BARRIER : ico; + this.desc = d; + this.bar = b; + this.color = 0xff000000 | color; + this.pcnt = pcnt; + + if (d == null || b == null) { + this.ico = Ico.BARRIER; + this.desc = Text.literal("No data").formatted(Formatting.GRAY); + this.bar = Text.literal("---").formatted(Formatting.GRAY); + this.pcnt = 100f; + this.color = 0xff000000 | Formatting.DARK_GRAY.getColorValue(); + } + + this.barW = BAR_WIDTH; + this.width = ICO_DIM + PAD_L + Math.max(this.barW, txtRend.getWidth(this.desc)); + this.height = txtRend.fontHeight + PAD_S + 2 + txtRend.fontHeight + 2; + } + + public ProgressComponent(ItemStack ico, Text text, float pcnt, int color) { + this(ico, text, Text.of(pcnt + "%"), pcnt, color); + } + + public ProgressComponent() { + this(null, null, null, 100, 0); + } + + @Override + public void render(MatrixStack ms, int x, int y) { + itmRend.renderGuiItemIcon(ms, ico, x, y + ICO_OFFS); + txtRend.draw(ms, desc, x + ICO_DIM + PAD_L, y, 0xffffffff); + + int barX = x + ICO_DIM + PAD_L; + int barY = y + txtRend.fontHeight + PAD_S; + int endOffsX = ((int) (this.barW * (this.pcnt / 100f))); + DrawableHelper.fill(ms, barX + endOffsX, barY, barX + this.barW, barY + BAR_HEIGHT, COL_BG_BAR); + DrawableHelper.fill(ms, barX, barY, barX + endOffsX, barY + BAR_HEIGHT, + this.color); + txtRend.drawWithShadow(ms, bar, barX + 3, barY + 2, 0xffffffff); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/TableComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/TableComponent.java new file mode 100644 index 00000000..5d49be2c --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/component/TableComponent.java @@ -0,0 +1,59 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component; + +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.util.math.MatrixStack; + +/** + * Meta-Component that consists of a grid of other components + * Grid cols are separated by lines. + */ +public class TableComponent extends Component { + + private Component[][] comps; + private int color; + private int cols, rows; + private int cellW, cellH; + + public TableComponent(int w, int h, int col) { + comps = new Component[w][h]; + color = 0xff000000 | col; + cols = w; + rows = h; + } + + public void addToCell(int x, int y, Component c) { + this.comps[x][y] = c; + + // pad extra to add a vertical line later + this.cellW = Math.max(this.cellW, c.width + PAD_S + PAD_L); + + // assume all rows are equally high so overwriting doesn't matter + // if this wasn't the case, drawing would need more math + // not doing any of that if it's not needed + this.cellH = c.height + PAD_S; + + this.width = this.cellW * this.cols; + this.height = (this.cellH * this.rows) - PAD_S / 2; + + } + + @Override + public void render(MatrixStack ms, int xpos, int ypos) { + for (int x = 0; x < cols; x++) { + for (int y = 0; y < rows; y++) { + if (comps[x][y] != null) { + comps[x][y].render(ms, xpos + (x * cellW), ypos + y * cellH); + } + } + // add a line before the col if we're not drawing the first one + if (x != 0) { + int lineX1 = xpos + (x * cellW) - PAD_S - 1; + int lineX2 = xpos + (x * cellW) - PAD_S; + int lineY1 = ypos + 1; + int lineY2 = ypos + this.height - PAD_S - 1; // not sure why but it looks correct + DrawableHelper.fill(ms, lineX1, lineY1, lineX2, lineY2, this.color); + } + } + } + +} |