aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java233
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonMapUtils.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarPositioner.java319
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java27
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java299
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/searchoverlay/SearchOverManager.java2
9 files changed, 608 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();
+ this.anchor = maybeAnchor.equals("null") ? null : BarPositioner.BarAnchor.valueOf(maybeAnchor);
this.size = object.get("size").getAsInt();
this.gridX = object.get("x").getAsInt();
this.gridY = object.get("y").getAsInt();
// these are optional too, why not
- if (object.has("icon_position")) this.iconPosition = IconPosition.valueOf(object.get("icon_position").getAsString());
+ if (object.has("icon_position")) this.iconPosition = IconPosition.valueOf(object.get("icon_position").getAsString().trim());
if (object.has("show_text")) this.showText = object.get("show_text").getAsBoolean();
}
@@ -335,6 +341,9 @@ public class StatusBar implements Widget, Drawable, Element, Selectable {
object.addProperty("text_color", Integer.toHexString(textColor.getRGB()).substring(2));
}
object.addProperty("size", size);
+ if (anchor != null) {
+ object.addProperty("anchor", anchor.toString());
+ } else object.addProperty("anchor", "null");
object.addProperty("x", gridX);
object.addProperty("y", gridY);
object.addProperty("icon_position", iconPosition.toString());
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java
index 3bcc2011..7c1aa71b 100644
--- a/