diff options
| author | vicisacat <victor.branchu@gmail.com> | 2024-04-17 23:07:49 +0200 |
|---|---|---|
| committer | vicisacat <victor.branchu@gmail.com> | 2024-04-20 16:09:49 +0200 |
| commit | f0ff0b555621f2d7f240bc72ccc1c7667badab6f (patch) | |
| tree | 76feeb4c44483a364cce571eecc4809022c13411 /src | |
| parent | b791e38cbd36360935164e337fa992bf514cbb36 (diff) | |
| download | Skyblocker-f0ff0b555621f2d7f240bc72ccc1c7667badab6f.tar.gz Skyblocker-f0ff0b555621f2d7f240bc72ccc1c7667badab6f.tar.bz2 Skyblocker-f0ff0b555621f2d7f240bc72ccc1c7667badab6f.zip | |
things happened yea
rewrote the entire thing to use semi data-driven BarAnchors
help button in the config screen
Diffstat (limited to 'src')
10 files changed, 611 insertions, 286 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index 0c6a3d75..37faaf25 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -2,6 +2,7 @@ package de.hysky.skyblocker.config.categories; import de.hysky.skyblocker.config.ConfigUtils; import de.hysky.skyblocker.config.SkyblockerConfig; +import de.hysky.skyblocker.skyblock.fancybars.StatusBarsConfigScreen; import de.hysky.skyblocker.skyblock.shortcut.ShortcutsConfigScreen; import de.hysky.skyblocker.utils.render.title.TitleContainerConfigScreen; import de.hysky.skyblocker.utils.waypoint.Waypoint; @@ -156,6 +157,11 @@ public class GeneralCategory { //Fancy Bars .group(OptionGroup.createBuilder() + .option(ButtonOption.createBuilder() + .name(Text.translatable("skyblocker.bars.config.openScreen")) + .text(Text.translatable("text.skyblocker.open")) + .action((screen, opt) -> MinecraftClient.getInstance().setScreen(new StatusBarsConfigScreen())) + .build()) .name(Text.translatable("text.autoconfig.skyblocker.option.general.bars")) .collapsed(true) .option(Option.<Boolean>createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java b/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java index 6bf012ff..306c2456 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java @@ -4,6 +4,7 @@ import com.google.gson.JsonObject; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.fancybars.BarGrid; +import de.hysky.skyblocker.skyblock.fancybars.BarPositioner; import de.hysky.skyblocker.skyblock.fancybars.StatusBar; import de.hysky.skyblocker.skyblock.fancybars.StatusBarsConfigScreen; import de.hysky.skyblocker.utils.Utils; @@ -15,6 +16,7 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.ScreenPos; import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; @@ -57,6 +59,8 @@ public class FancyStatusBars { private final int[] anchorsX = new int[3]; private final int[] anchorsY = new int[3]; + public static BarPositioner barPositioner = new BarPositioner(); + @Deprecated(forRemoval = true) public static BarGrid barGrid = new BarGrid(); public static Map<String, StatusBar> statusBars = new HashMap<>(); @@ -76,17 +80,21 @@ public class FancyStatusBars { // Default positions StatusBar health = statusBars.get("health"); - health.gridX = 1; - health.gridY = 1; + health.anchor = BarPositioner.BarAnchor.HOTBAR_TOP; + health.gridX = 0; + health.gridY = 0; StatusBar intelligence = statusBars.get("intelligence"); - intelligence.gridX = 2; - intelligence.gridY = 1; + intelligence.anchor = BarPositioner.BarAnchor.HOTBAR_TOP; + intelligence.gridX = 1; + intelligence.gridY = 0; StatusBar defense = statusBars.get("defense"); - defense.gridX = 1; - defense.gridY = -1; + defense.anchor = BarPositioner.BarAnchor.HOTBAR_RIGHT; + defense.gridX = 0; + defense.gridY = 0; StatusBar experience = statusBars.get("experience"); - experience.gridX = 1; - experience.gridY = 2; + experience.anchor = BarPositioner.BarAnchor.HOTBAR_TOP; + experience.gridX = 0; + experience.gridY = 1; CompletableFuture.supplyAsync(FancyStatusBars::loadBarConfig).thenAccept(object -> { if (object != null) { @@ -102,8 +110,11 @@ public class FancyStatusBars { } } } - placeBarsInGrid(); + placeBarsInPositioner(); configLoaded = true; + }).exceptionally(throwable -> { + LOGGER.error("[Skyblocker] Failed reading status bars config", throwable); + return null; }); ClientLifecycleEvents.CLIENT_STOPPING.register((client) -> { saveBarConfig(); @@ -119,53 +130,30 @@ public class FancyStatusBars { //placeBarsInGrid(); ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register( - ClientCommandManager.literal("skyblocker") - .then(ClientCommandManager.literal("bar_test").executes(Scheduler.queueOpenScreenCommand(StatusBarsConfigScreen::new))))); + ClientCommandManager.literal(SkyblockerMod.NAMESPACE) + .then(ClientCommandManager.literal("bars").executes(Scheduler.queueOpenScreenCommand(StatusBarsConfigScreen::new))))); } private static boolean configLoaded = false; - private static void placeBarsInGrid() { + private static void placeBarsInPositioner() { List<StatusBar> original = statusBars.values().stream().toList(); - // TOP - List<StatusBar> barList = new ArrayList<>(original.stream().filter(statusBar -> statusBar.gridY > 0).toList()); - barList.sort((a, b) -> a.gridY == b.gridY ? Integer.compare(a.gridX, b.gridX) : Integer.compare(a.gridY, b.gridY)); - - int y = 0; - int rowNum = 0; - for (StatusBar statusBar : barList) { - if (statusBar.gridY > y) { - barGrid.addRowToEnd(true, false); - rowNum++; - y = statusBar.gridY; - } - barGrid.addToEndOfRow(rowNum, false, statusBar); - } - - // BOTTOM LEFT - barList.clear(); - barList.addAll(original.stream().filter(statusBar -> statusBar.gridY < 0 && statusBar.gridX < 0).toList()); - barList.sort((a, b) -> a.gridY == b.gridY ? -Integer.compare(a.gridX, b.gridX) : -Integer.compare(a.gridY, b.gridY)); - doBottom(false, barList); - - // BOTTOM RIGHT - barList.clear(); - barList.addAll(original.stream().filter(statusBar -> statusBar.gridY < 0 && statusBar.gridX > 0).toList()); - barList.sort((a, b) -> a.gridY == b.gridY ? Integer.compare(a.gridX, b.gridX) : -Integer.compare(a.gridY, b.gridY)); - doBottom(true, barList); - } - - private static void doBottom(boolean right, List<StatusBar> barList) { - int y = 0; - int rowNum = 0; - for (StatusBar statusBar : barList) { - if (statusBar.gridY < y) { - barGrid.addRowToEnd(false, right); - rowNum--; - y = statusBar.gridY; + for (BarPositioner.BarAnchor barAnchor : BarPositioner.BarAnchor.allAnchors()) { + List<StatusBar> barList = new ArrayList<>(original.stream().filter(bar -> bar.anchor == barAnchor).toList()); + if (barList.isEmpty()) continue; + barList.sort((a, b) -> a.gridY == b.gridY ? Integer.compare(a.gridX, b.gridX) : Integer.compare(a.gridY, b.gridY)); + + int y = -1; + int rowNum = -1; + for (StatusBar statusBar : barList) { + if (statusBar.gridY > y) { + barPositioner.addRow(barAnchor); + rowNum++; + y = statusBar.gridY; + } + barPositioner.addBar(barAnchor, rowNum, statusBar); } - barGrid.addToEndOfRow(rowNum, right, statusBar); } } @@ -193,97 +181,82 @@ public class FancyStatusBars { public static void updatePositions() { if (!configLoaded) return; - final float hotbarSize = 182; final int width = MinecraftClient.getInstance().getWindow().getScaledWidth(); final int height = MinecraftClient.getInstance().getWindow().getScaledHeight(); - for (StatusBar value : statusBars.values()) { - if (value.gridX == 0 || value.gridY == 0) { - value.setX(-1); - value.setY(-1); - value.setWidth(0); - } - } - - // THE TOP - for (int i = 0; i < barGrid.getTopSize(); i++) { - List<StatusBar> row = barGrid.getRow(i + 1, false); - System.out.println(row); - if (row.isEmpty()) continue; - int totalSize = 0; - for (StatusBar bar : row) { - totalSize += bar.size; - } - - // Fix sizing - whileLoop: - while (totalSize != 12) { - if (totalSize > 12) { - for (StatusBar bar : row) { - if (bar.size > bar.getMinimumSize()) { // TODO: this can cause infinite looping if we add more than 6 bars - bar.size--; - totalSize--; - } - if (totalSize == 12) break whileLoop; - } - } else { - for (StatusBar bar : row) { - if (bar.size < bar.getMaximumSize()) { - bar.size++; - totalSize++; + for (BarPositioner.BarAnchor barAnchor : BarPositioner.BarAnchor.allAnchors()) { + ScreenPos anchorPosition = barAnchor.getAnchorPosition(width, height); + BarPositioner.SizeRule sizeRule = barAnchor.getSizeRule(); + + if (sizeRule.isTargetSize()) { + for (int row = 0; row < barPositioner.getRowCount(barAnchor); row++) { + LinkedList<StatusBar> barRow = barPositioner.getRow(barAnchor, row); + if (barRow.isEmpty()) continue; + + // FIX SIZES + int totalSize = 0; + for (StatusBar statusBar : barRow) + totalSize += (statusBar.size = MathHelper.clamp(statusBar.size, sizeRule.minSize(), sizeRule.maxSize())); + + whileLoop: + while (totalSize != sizeRule.targetSize()) { + if (totalSize > sizeRule.targetSize()) { + for (StatusBar statusBar : barRow) { + if (statusBar.size > sizeRule.minSize()) { + statusBar.size--; + totalSize--; + if (totalSize == sizeRule.targetSize()) break whileLoop; + } + } + } else { + for (StatusBar statusBar : barRow) { + if (statusBar.size < sizeRule.maxSize()) { + statusBar.size++; + totalSize++; + if (totalSize == sizeRule.targetSize()) break whileLoop; + } + } } - if (totalSize == 12) break whileLoop; } + } } - int x = width / 2 - 91; - int y = height - 33 - 10 * i; - int size = 0; - for (int j = 0; j < row.size(); j++) { - StatusBar bar = row.get(j); - bar.setX(x + (int) ((size / 12.d) * hotbarSize)); - bar.setY(y); - bar.setWidth((int) ((bar.size / 12.d) * hotbarSize)); - size += bar.size; - bar.gridY = i + 1; - bar.gridX = j + 1; - } - } + for (int row = 0; row < barPositioner.getRowCount(barAnchor); row++) { + List<StatusBar> barRow = barPositioner.getRow(barAnchor, row); + if (barRow.isEmpty()) continue; - // BOTTOM LEFT - for (int i = 0; i < barGrid.getBottomLeftSize(); i++) { - List<StatusBar> row = barGrid.getRow(-(i + 1), false); - if (row.isEmpty()) continue; - int x = width / 2 - 91 - 2; - int y = height - 15 - 10 * (barGrid.getBottomLeftSize() - i - 1); - for (int j = 0; j < row.size(); j++) { - StatusBar bar = row.get(j); - bar.size = MathHelper.clamp(bar.size, bar.getMinimumSize(), bar.getMaximumSize()); - bar.setY(y); - bar.setWidth(bar.size * 25); - x -= bar.getWidth(); - bar.setX(x); - bar.gridX = -j - 1; - bar.gridY = -i - 1; - } - } - // BOTTOM RIGHT - for (int i = 0; i < barGrid.getBottomRightSize(); i++) { - List<StatusBar> row = barGrid.getRow(-(i + 1), true); - if (row.isEmpty()) continue; - int x = width / 2 + 91 + 2; - int y = height - 15 - 10 * (barGrid.getBottomRightSize() - i - 1); - for (int j = 0; j < row.size(); j++) { - StatusBar bar = row.get(j); - bar.size = MathHelper.clamp(bar.size, bar.getMinimumSize(), bar.getMaximumSize()); - bar.setX(x); - bar.setY(y); - bar.setWidth(bar.size * 25); - x += bar.getWidth(); - bar.gridX = j + 1; - bar.gridY = -i - 1; + + // Update the positions + float widthPerSize; + if (sizeRule.isTargetSize()) + widthPerSize = (float) sizeRule.totalWidth() / sizeRule.targetSize(); + else + widthPerSize = sizeRule.widthPerSize(); + + int currSize = 0; + for (int i = 0; i < barRow.size(); i++) { + StatusBar statusBar = barRow.get(i); + statusBar.size = MathHelper.clamp(statusBar.size, sizeRule.minSize(), sizeRule.maxSize()); + + float x = barAnchor.isRight() ? + anchorPosition.x() + currSize * widthPerSize : + anchorPosition.x() - currSize * widthPerSize - statusBar.size * widthPerSize; + statusBar.setX((int) x); + + int y = barAnchor.isUp() ? + anchorPosition.y() - (row + 1) * (statusBar.getHeight() + 1) : + anchorPosition.y() + row * (statusBar.getHeight() + 1); + statusBar.setY(y); + + statusBar.setWidth((int) (statusBar.size * widthPerSize)); + currSize += statusBar.size; + statusBar.gridX = i; + statusBar.gridY = row; + + } } + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java index c8bc1f13..d6111f1b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java @@ -352,7 +352,7 @@ public class AuctionBrowserScreen extends AbstractCustomHypixelGUI<AuctionHouseS List<Text> tooltip = ItemUtils.getNbtTooltips(stack); String str = tooltip.get(0).getString().trim(); str = str.substring(1, str.length() - 1); // remove parentheses - String[] parts = str.split("/"); // split the string + String[] parts = str.split("/"); // targetSize the string currentPage = Integer.parseInt(parts[0].replace(",", "")); // parse current page totalPages = Integer.parseInt(parts[1].replace(",", "")); // parse total } catch (Exception e) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java index 34cc6352..65cbde5b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java @@ -235,7 +235,7 @@ public class ChatRule { String rawLocation = Utils.getLocationRaw(); Boolean isLocationValid = null; - for (String validLocation : validLocations.replace(" ", "").toLowerCase().split(",")) {//the locations are raw locations split by "," and start with ! if not locations + for (String validLocation : validLocations.replace(" ", "").toLowerCase().split(",")) {//the locations are raw locations targetSize by "," and start with ! if not locations String rawValidLocation = ChatRulesHandler.locations.get(validLocation.replace("!","")); if (rawValidLocation == null) continue; if (validLocation.startsWith("!")) {//not location diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java index 8e0073f7..3d373025 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java @@ -117,7 +117,7 @@ public class DungeonMapUtils { * @param mapEntrancePos the map position of the top left corner of the entrance * @param mapRoomSize the size of a room on the map * @return the map position of the top left corner of the room the player is in - * @implNote {@code mapPos} is shifted by 2 so room borders are evenly split. + * @implNote {@code mapPos} is shifted by 2 so room borders are evenly targetSize. * {@code mapPos} is then shifted by {@code offset} to align the top left most room at (0, 0) * so subtracting the modulo will give the top left corner of the room shifted by {@code offset}. * Finally, {@code mapPos} is shifted back by {@code offset} to its intended position. @@ -168,7 +168,7 @@ public class DungeonMapUtils { * @param x the x position of the coordinate to calculate * @param z the z position of the coordinate to calculate * @return the physical position of the northwest corner of the room the player is in - * @implNote {@code physicalPos} is shifted by 0.5 so room borders are evenly split. + * @implNote {@code physicalPos} is shifted by 0.5 so room borders are evenly targetSize. * {@code physicalPos} is further shifted by 8 because Hypixel offset dungeons by 8 blocks in Skyblock 0.12.3. * Subtracting the modulo gives the northwest corner of the room shifted by 8. Finally, {@code physicalPos} is shifted back by 8 to its intended position. */ diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarPositioner.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarPositioner.java new file mode 100644 index 00000000..7fde9117 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarPositioner.java @@ -0,0 +1,319 @@ +package de.hysky.skyblocker.skyblock.fancybars; + +import net.minecraft.client.gui.ScreenPos; +import net.minecraft.client.gui.ScreenRect; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class BarPositioner { + + private final Map<BarAnchor, LinkedList<LinkedList<StatusBar>>> map = new HashMap<>(BarAnchor.values().length); + + public BarPositioner() { + for (BarAnchor value : BarAnchor.values()) { + map.put(value, new LinkedList<>()); + } + } + + + public int getRowCount(@NotNull BarAnchor barAnchor) { + return map.get(barAnchor).size(); + } + + /** + * Adds a row to the end of an anchor + * + * @param barAnchor the anchor + */ + public void addRow(@NotNull BarAnchor barAnchor) { + map.get(barAnchor).add(new LinkedList<>()); + } + + /** + * Adds a row at the specified index + * + * @param barAnchor the anchor + * @param row row index + */ + public void addRow(@NotNull BarAnchor barAnchor, int row) { + map.get(barAnchor).add(row, new LinkedList<>()); + } + + /** + * adds a bar to the end of a row + * + * @param barAnchor the anchor + * @param row the row + * @param bar the bar to add + */ + public void addBar(@NotNull BarAnchor barAnchor, int row, StatusBar bar) { + LinkedList<StatusBar> statusBars = map.get(barAnchor).get(row); + statusBars.add(bar); + bar.gridY = row; + bar.gridX = statusBars.lastIndexOf(bar); // optimization baby, start with the end! + bar.anchor = barAnchor; + } + + /** + * adds a bar to the specified x in a row + * + * @param barAnchor the anchor + * @param row the row + * @param x the index in the row + * @param bar the bar to add + */ + public void addBar(@NotNull BarAnchor barAnchor, int row, int x, StatusBar bar) { + LinkedList<StatusBar> statusBars = map.get(barAnchor).get(row); + statusBars.add(x, bar); + bar.gridY = row; + bar.gridX = statusBars.indexOf(bar); + bar.anchor = barAnchor; + } + + /** + * removes the specified bar at x on the row. If it's row is empty after being removed, the row will be auto removed + * + * @param barAnchor the anchor + * @param row dah row + * @param x dah x + */ + public void removeBar(@NotNull BarAnchor barAnchor, int row, int x) { + LinkedList<StatusBar> statusBars = map.get(barAnchor).get(row); + StatusBar remove = statusBars.remove(x); + remove.anchor = null; + for (int i = x; i < statusBars.size(); i++) { + statusBars.get(i).gridX--; + } + if (statusBars.isEmpty()) removeRow(barAnchor, row); + } + + /** + * removes the specified bar on the row. If it's row is empty after being removed, the row will be auto removed + * + * @param barAnchor the anchor + * @param row dah row + * @param bar dah bar + */ + public void removeBar(@NotNull BarAnchor barAnchor, int row, StatusBar bar) { + LinkedList<StatusBar> barRow = map.get(barAnchor).get(row); + int x = barRow.indexOf(bar); + if (x < 0) return; // probably a bad idea + + barRow.remove(bar); + bar.anchor = null; + for (int i = x; i < barRow.size(); i++) { + barRow.get(i).gridX--; + } + if (barRow.isEmpty()) removeRow(barAnchor, row); + } + + /** + * row must be empty + * + * @param barAnchor the anchor + * @param row the row to remove + */ + public void removeRow(@NotNull BarAnchor barAnchor, int row) { + LinkedList<StatusBar> barRow = map.get(barAnchor).get(row); + if (!barRow.isEmpty()) + throw new IllegalStateException("Can't remove a non-empty row (" + barAnchor + "," + row + ")"); + map.get(barAnchor).remove(row); + for (int i = row; i < map.get(barAnchor).size(); i++) { + for (StatusBar statusBar : map.get(barAnchor).get(i)) { + statusBar.gridY--; + } + } + } + + + public LinkedList<StatusBar> getRow(@NotNull BarAnchor barAnchor, int row) { + return map.get(barAnchor).get(row); + } + + public StatusBar getBar(@NotNull BarAnchor barAnchor, int row, int x) { + return map.get(barAnchor).get(row).get(x); + } + + public boolean hasNeighbor(@NotNull BarAnchor barAnchor, int row, int x, boolean right) { + LinkedList<StatusBar> statusBars = map.get(barAnchor).get(row); + if (barAnchor.isRight()) { + return (right && x < statusBars.size() - 1) || (!right && x > 0); + } else { + return (right && x > 0) || (!right && x < statusBars.size() - 1); + } + } + + + public enum BarAnchor { + HOTBAR_LEFT(true, false, + (scaledWidth, scaledHeight) -> new ScreenPos(scaledWidth / 2 - 91 - 2, scaledHeight - 5), + SizeRule.freeSize(25, 2, 6)), + + HOTBAR_RIGHT(true, true, + (scaledWidth, scaledHeight) -> new ScreenPos(scaledWidth / 2 + 91 + 2, scaledHeight - 5), + SizeRule.freeSize(25, 2, 6)), + + HOTBAR_TOP(true, true, + (scaledWidth, scaledHeight) -> new ScreenPos(scaledWidth / 2 - 91, scaledHeight - 23), + SizeRule.targetSize(12, 182, 2), + anchorPosition -> new ScreenRect(anchorPosition.x(), anchorPosition.y() - 20, 182, 20)), + + SCREEN_TOP_LEFT(false, true, + ((scaledWidth, scaledHeight) -> new ScreenPos(5, 5)), + SizeRule.freeSize(25, 2, 6) + ), + SCREEN_TOP_RIGHT(false, false, + ((scaledWidth, scaledHeight) -> new ScreenPos(scaledWidth - 5, 5)), + SizeRule.freeSize(25, 2, 6) + ), + SCREEN_BOTTOM_LEFT(true, true, + ((scaledWidth, scaledHeight) -> new ScreenPos(5, scaledHeight - 5)), + SizeRule.freeSize(25, 2, 6) + ), + SCREEN_BOTTOM_RIGHT(true, false, + ((scaledWidth, scaledHeight) -> new ScreenPos(scaledWidth - 5, scaledHeight - 5)), + SizeRule.freeSize(25, 2, 6) + ), + ; + + private final AnchorPositionProvider positionProvider; + private final AnchorHitboxProvider hitboxProvider; + private final boolean up; + private final boolean right; + private final SizeRule sizeRule; + + /** + * @param up whether the rows stack towards the top of the screen from the anchor (false is bottom) + * @param right whether the bars are line up towards the right of the screen from the anchor (false is left) + * @param positionProvider provides the position of the anchor for a give screen size + * @param sizeRule the rule the bars should follow. See {@link SizeRule} + * @param hitboxProvider provides the hitbox for when the anchor has no bars for the config screen + */ + BarAnchor(boolean up, boolean right, AnchorPositionProvider positionProvider, SizeRule sizeRule, AnchorHitboxProvider hitboxProvider) { + this.positionProvider = positionProvider; + this.up = up; + this.right = right; + this.hitboxProvider = hitboxProvider; + this.sizeRule = sizeRule; + } + + BarAnchor(boolean up, boolean right, AnchorPositionProvider positionProvider, SizeRule sizeRule) { + this(up, right, positionProvider, sizeRule, + anchorPosition -> new ScreenRect(anchorPosition.x() - (right ? 0 : 20), anchorPosition.y() - (up ? 20 : 0), 20, 20)); + } + + public ScreenPos getAnchorPosition(int scaledWidth, int scaledHeight) { + return positionProvider.getPosition(scaledWidth, scaledHeight); + } + + public ScreenRect getAnchorHitbox(ScreenPos anchorPosition) { + return hitboxProvider.getHitbox(anchorPosition); + } + + /** + * whether the rows stack towards the top of the screen from the anchor (false is bottom) + * + * @return true if towards the top, false otherwise + */ + public boolean isUp() { + return up; + } + + /** + * whether the bars are line up towards the right of the screen from the anchor (false is left) + * + * @return true if towards the right, false otherwise + */ + public boolean isRight() { + return right; + } + + public SizeRule getSizeRule() { + return sizeRule; + } + + private static final List<BarAnchor> cached = List.of(values()); + + /** + * cached version of {@link BarAnchor#values()} + * + * @return the list of anchors + */ + public static List<BarAnchor> allAnchors() { + return cached; + } + } + + /** + * The rules the bars on an anchor should follow + * + * @param isTargetSize whether the bars went to fit to a target width + * @param targetSize the size of all the bars on a row should add up to this (target size) + * @param totalWidth the total width taken by all the bars on the row (target size) + * @param widthPerSize the width of each size "unit" (free size) + * @param minSize the minimum (free and target size) + * @param maxSize the maximum (free and target size, THIS SHOULD BE THE SAME AS {@code targetSize} FOR {@code isTargetSize = true}) + */ + public record SizeRule(boolean isTargetSize, int targetSize, int totalWidth, int widthPerSize, int minSize, + int maxSize) { + public static SizeRule freeSize(int widthPerSize, int minSize, int maxSize) { + return new SizeRule(false, -1, -1, widthPerSize, minSize, maxSize); + } + + public static SizeRule targetSize(int targetSize, int totalWidth, int minSize) { + return new SizeRule(true, targetSize, totalWidth, -1, minSize, targetSize); + } + } + + /** + * A record representing a snapshot of a bar's position + * + * @param barAnchor + * @param x + * @param y the row + */ + public record BarLocation(@Nullable BarAnchor barAnchor, int x, int y) { + + public static final BarLocation NULL = new BarLocation(null, -1, -1); + + public static BarLocation of(StatusBar bar) { + return new BarLocation(bar.anchor, bar.gridX, bar.gridY); + } + + @Override + public boolean equals(Object object) { + if (this == object) return true; + if (object == null || getClass() != object.getClass()) return false; + + BarLocation that = (BarLocation) object; + return x == that.x && y == that.y && barAnchor == that.barAnchor; + } + + public boolean equals(BarAnchor barAnchor, int x, int y) { + return x == this.x && y == this.y && barAnchor == this.barAnchor; + } + } + + /** + * provides the position of the anchor for a give screen size + */ + @FunctionalInterface + interface AnchorPositionProvider { + + ScreenPos getPosition(int scaledWidth, int scaledHeight); + } + + @FunctionalInterface + interface AnchorHitboxProvider { + + /** + * The hitbox, as in how large the area of "snapping" is if there are no bars on this anchor + * + * @param anchorPosition the position of the anchor + * @return the rectangle that represents the hitbox + */ + ScreenRect getHitbox(ScreenPos anchorPosition); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java index ea4a0388..5ece1934 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java @@ -86,12 +86,14 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { private @Nullable OnClick onClick = null; public int gridX = 0; public int gridY = 0; + public @Nullable BarPositioner.BarAnchor anchor = null; public int size = 1; private int width = 0; public float fill = 0; public float overflowFill = 0; + public boolean ghost = false; private Object value = ""; @@ -116,6 +118,8 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (width <= 0) return; + // half works lol. only puts transparency on the filler of the bar + if (ghost) context.setShaderColor(1f,1f,1f,0.25f); switch (iconPosition) { case LEFT -> context.drawGuiTexture(icon, x, y, 9, 9); case RIGHT -> context.drawGuiTexture(icon, x + width - 9, y, 9, 9); @@ -130,6 +134,7 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { if (hasOverflow && overflowFill > 0) { RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, y + 2, (int) ((barWith - 2) * overflowFill), 5, colors[1]); } + if (ghost) context.setShaderColor(1f,1f,1f,1f); //context.drawText(MinecraftClient.getInstance().textRenderer, gridX + " " + gridY + " s:" + size , x, y-9, Colors.WHITE, true); } @@ -159,13 +164,19 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { int temp_x = x; int temp_y = y; int temp_width = width; + boolean temp_ghost = ghost; + x = mouseX; y = mouseY; width = 100; + ghost = false; + render(context, mouseX, mouseY, delta); + x = temp_x; y = temp_y; width = temp_width; + ghost = temp_ghost; } // GUI shenanigans @@ -204,14 +215,6 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { return 9; } - public int getMinimumSize() { - return 2; - } - - public int getMaximumSize() { - return gridY < 0 ? 6 : 12; - } - @Override public ScreenRect getNavigationFocus() { return Widget.super.getNavigationFocus(); @@ -267,6 +270,7 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { .append("x", x) .append("y", y) .append("width", width) + .append("anchor", anchor) .toString(); } @@ -315,11 +319,13 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { if (object.has("text_color")) this.textColor = new Color(Integer.parseInt(object.get("text_color").getAsString(), 16)); + String maybeAnchor = object.get("anchor").getAsString().trim(); |
