diff options
author | vicisacat <victor.branchu@gmail.com> | 2024-04-14 17:36:21 +0200 |
---|---|---|
committer | vicisacat <victor.branchu@gmail.com> | 2024-04-20 16:09:49 +0200 |
commit | b791e38cbd36360935164e337fa992bf514cbb36 (patch) | |
tree | f245ad744288d6f62452c26161878d59f651971d /src/main | |
parent | 3581365e654306cf08d0c4284ddfa454befd519d (diff) | |
download | Skyblocker-b791e38cbd36360935164e337fa992bf514cbb36.tar.gz Skyblocker-b791e38cbd36360935164e337fa992bf514cbb36.tar.bz2 Skyblocker-b791e38cbd36360935164e337fa992bf514cbb36.zip |
it works so cool
Diffstat (limited to 'src/main')
11 files changed, 1008 insertions, 113 deletions
diff --git a/src/main/java/de/hysky/skyblocker/mixin/WindowMixin.java b/src/main/java/de/hysky/skyblocker/mixin/WindowMixin.java new file mode 100644 index 00000000..92ca967d --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/WindowMixin.java @@ -0,0 +1,16 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.skyblock.FancyStatusBars; +import net.minecraft.client.util.Window; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Window.class) +public class WindowMixin { + @Inject(method = "setScaleFactor", at = @At("TAIL")) + public void onScaleFactorChange(double scaleFactor, CallbackInfo ci) { + FancyStatusBars.updatePositions(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java b/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java index 1a582863..6bf012ff 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/FancyStatusBars.java @@ -1,5 +1,6 @@ package de.hysky.skyblocker.skyblock; +import com.google.gson.JsonObject; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.fancybars.BarGrid; @@ -8,25 +9,37 @@ import de.hysky.skyblocker.skyblock.fancybars.StatusBarsConfigScreen; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; import de.hysky.skyblocker.utils.scheduler.Scheduler; -import jdk.jshell.EvalException; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +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.texture.Sprite; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.awt.*; -import java.util.Collection; -import java.util.HashMap; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.*; import java.util.List; -import java.util.Map; +import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; public class FancyStatusBars { private static final Identifier BARS = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/bars.png"); + private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("status_bars.json"); + private static final Logger LOGGER = LoggerFactory.getLogger(FancyStatusBars.class); private final MinecraftClient client = MinecraftClient.getInstance(); private final StatusBarTracker statusBarTracker = SkyblockerMod.getInstance().statusBarTracker; @@ -48,26 +61,138 @@ public class FancyStatusBars { public static Map<String, StatusBar> statusBars = new HashMap<>(); public static void init() { - statusBars.put("health", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/health"), new Color[]{new Color(255, 0, 0), new Color(255, 220, 0)}, true, null, "health")); - statusBars.put("intelligence", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/intelligence"), new Color[]{new Color(0, 255, 255), new Color(180, 0, 255)}, true, null, "intelligence")); - statusBars.put("defense", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/defense"), new Color[]{new Color(255, 255, 255)}, false, null, "defense")); - statusBars.put("experience", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/experience"), new Color[]{new Color(100, 220, 70)}, false, null, "experience")); - - - barGrid.addRow(1, false); + statusBars.put("health", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/health"), + new Color[]{new Color(255, 0, 0), new Color(255, 220, 0)}, + true, new Color(255, 85, 85), Text.translatable("skyblocker.bars.config.health"))); + statusBars.put("intelligence", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/intelligence"), + new Color[]{new Color(0, 255, 255), new Color(180, 0, 255)}, + true, new Color(85, 255, 255), Text.translatable("skyblocker.bars.config.intelligence"))); + statusBars.put("defense", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/defense"), + new Color[]{new Color(255, 255, 255)}, + false, new Color(185, 185, 185), Text.translatable("skyblocker.bars.config.defense"))); + statusBars.put("experience", new StatusBar(new Identifier(SkyblockerMod.NAMESPACE, "bars/icons/experience"), + new Color[]{new Color(100, 230, 70)}, + false, new Color(128, 255, 32), Text.translatable("skyblocker.bars.config.experience"))); + + // Default positions + StatusBar health = statusBars.get("health"); + health.gridX = 1; + health.gridY = 1; + StatusBar intelligence = statusBars.get("intelligence"); + intelligence.gridX = 2; + intelligence.gridY = 1; + StatusBar defense = statusBars.get("defense"); + defense.gridX = 1; + defense.gridY = -1; + StatusBar experience = statusBars.get("experience"); + experience.gridX = 1; + experience.gridY = 2; + + CompletableFuture.supplyAsync(FancyStatusBars::loadBarConfig).thenAccept(object -> { + if (object != null) { + for (String s : object.keySet()) { + if (statusBars.containsKey(s)) { + try { + statusBars.get(s).loadFromJson(object.get(s).getAsJsonObject()); + } catch (Exception e) { + LOGGER.error("[Skyblocker] Failed to load {} status bar", s, e); + } + } else { + LOGGER.warn("[Skyblocker] Unknown status bar: {}", s); + } + } + } + placeBarsInGrid(); + configLoaded = true; + }); + ClientLifecycleEvents.CLIENT_STOPPING.register((client) -> { + saveBarConfig(); + GLFW.glfwDestroyCursor(StatusBarsConfigScreen.RESIZE_CURSOR); + }); + /*barGrid.addRow(1, false); barGrid.add(1, 1, statusBars.get("health")); barGrid.add(2, 1, statusBars.get("intelligence")); barGrid.addRow(2, false); barGrid.add(1, 2, statusBars.get("experience")); barGrid.addRow(-1, true); - barGrid.add(1, -1, statusBars.get("defense")); + barGrid.add(1, -1, statusBars.get("defense"));*/ + //placeBarsInGrid(); ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register( ClientCommandManager.literal("skyblocker") .then(ClientCommandManager.literal("bar_test").executes(Scheduler.queueOpenScreenCommand(StatusBarsConfigScreen::new))))); } + private static boolean configLoaded = false; + + private static void placeBarsInGrid() { + 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; + } + barGrid.addToEndOfRow(rowNum, right, statusBar); + } + } + + public static JsonObject loadBarConfig() { + try (BufferedReader reader = Files.newBufferedReader(FILE)) { + return SkyblockerMod.GSON.fromJson(reader, JsonObject.class); + } catch (NoSuchFileException e) { + LOGGER.warn("[Skyblocker] No status bar config file found, using defaults"); + } catch (Exception e) { + LOGGER.error("[Skyblocker] Failed to load status bars config", e); + } + return null; + } + + public static void saveBarConfig() { + JsonObject output = new JsonObject(); + statusBars.forEach((s, statusBar) -> output.add(s, statusBar.toJson())); + try (BufferedWriter writer = Files.newBufferedWriter(FILE)) { + SkyblockerMod.GSON.toJson(output, writer); + LOGGER.info("[Skyblocker] Saved status bars config"); + } catch (IOException e) { + LOGGER.error("[Skyblocker] Failed to save status bars config", e); + } + } + 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(); @@ -83,6 +208,7 @@ public class FancyStatusBars { // 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) { @@ -90,10 +216,11 @@ public class FancyStatusBars { } // Fix sizing - whileLoop: while (totalSize != 12) { + whileLoop: + while (totalSize != 12) { if (totalSize > 12) { for (StatusBar bar : row) { - if (bar.size > 2) { // TODO: this can cause infinite looping if we add more than 6 bars + if (bar.size > bar.getMinimumSize()) { // TODO: this can cause infinite looping if we add more than 6 bars bar.size--; totalSize--; } @@ -101,7 +228,7 @@ public class FancyStatusBars { } } else { for (StatusBar bar : row) { - if (bar.size < 12) { + if (bar.size < bar.getMaximumSize()) { bar.size++; totalSize++; } @@ -110,52 +237,52 @@ public class FancyStatusBars { } } - int x = width/2 - 91; - int y = height - 33 - 10*i; + 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); + bar.setX(x + (int) ((size / 12.d) * hotbarSize)); bar.setY(y); - bar.setWidth((int) ((bar.size / 12.f)*hotbarSize)); - x += bar.getWidth(); - bar.gridY = i+1; - bar.gridX = j+1; + bar.setWidth((int) ((bar.size / 12.d) * hotbarSize)); + size += bar.size; + bar.gridY = i + 1; + bar.gridX = j + 1; } } - final int maxSize = 3; // 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*i; + 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 = Math.min(bar.size, maxSize); + bar.size = MathHelper.clamp(bar.size, bar.getMinimumSize(), bar.getMaximumSize()); bar.setY(y); - bar.setWidth(bar.size*25); + bar.setWidth(bar.size * 25); x -= bar.getWidth(); bar.setX(x); - bar.gridX = -j-1; - bar.gridY = -i-1; + 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*i; + 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 = Math.min(bar.size, maxSize); + bar.size = MathHelper.clamp(bar.size, bar.getMinimumSize(), bar.getMaximumSize()); bar.setX(x); bar.setY(y); - bar.setWidth(bar.size*25); + bar.setWidth(bar.size * 25); x += bar.getWidth(); - bar.gridX = j+1; - bar.gridY = -i-1; + bar.gridX = j + 1; + bar.gridY = -i - 1; } } } @@ -186,7 +313,7 @@ public class FancyStatusBars { value.render(context, -1, -1, client.getLastFrameDuration()); } for (StatusBar statusBar : barCollection) { - statusBar.renderText(context); + if (statusBar.showText()) statusBar.renderText(context); } StatusBarTracker.Resource health = statusBarTracker.getHealth(); statusBars.get("health").updateValues(health.value() / (float) health.max(), health.overflow() / (float) health.max(), health.value()); @@ -236,7 +363,7 @@ public class FancyStatusBars { MatrixStack matrices = context.getMatrices(); matrices.push(); matrices.translate(50, 50, 0); - matrices.scale(2,2,1); + matrices.scale(2, 2, 1); context.drawSprite(0, 0, 0, 60, 5, SUPPLIER.get(), 1, 0.25f, 0.25f, 1); matrices.pop(); return true; @@ -314,13 +441,13 @@ public class FancyStatusBars { context.drawTexture(BARS, anchorsX[anchorNum] + offsetX, anchorsY[anchorNum], 0, v, 9, 9); // Draw the background for the bar - context.drawGuiTexture(BAR_BACK, anchorsX[anchorNum]+ offsetX+10, anchorsY[anchorNum]+1, bar_width, 7); + context.drawGuiTexture(BAR_BACK, anchorsX[anchorNum] + offsetX + 10, anchorsY[anchorNum] + 1, bar_width, 7); // Draw the filled part of the bar for (int i = 0; i < fill.length; i++) { int fill_width = this.fill[i] * (bar_width - 2) / 100; if (fill_width >= 1) { - RenderHelper.renderNineSliceColored(context, BAR_FILL, anchorsX[anchorNum] + offsetX + 11, anchorsY[anchorNum]+2, fill_width, 5, colors[i]); + RenderHelper.renderNineSliceColored(context, BAR_FILL, anchorsX[anchorNum] + offsetX + 11, anchorsY[anchorNum] + 2, fill_width, 5, colors[i]); } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java index 6b90b86c..9d460803 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java @@ -34,18 +34,7 @@ public class EditBidPopup extends AbstractPopupScreen { super.init(); layout = DirectionalLayoutWidget.vertical(); layout.spacing(8).getMainPositioner().alignHorizontalCenter(); - textFieldWidget = new TextFieldWidget(textRenderer, 120, 15, Text.empty()) { - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (!super.keyPressed(keyCode, scanCode, modifiers)) { - if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) { - done(null); - return true; - } - } else return true; - return false; - } - }; + textFieldWidget = new EnterConfirmTextFieldWidget(textRenderer, 120, 15, Text.empty(), () -> done(null)); textFieldWidget.setTextPredicate(this::isStringGood); layout.add(new TextWidget(Text.literal("- Set Bid -").fillStyle(Style.EMPTY.withBold(true)), textRenderer)); layout.add(textFieldWidget); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java index 93219240..384250f9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java @@ -53,6 +53,28 @@ public class BarGrid { } } + public void addRowToEnd(boolean top, boolean right) { + if (top) { + this.top.add(new LinkedList<>()); + } else { + (right ? bottomRight: bottomLeft).add(new LinkedList<>()); + } + } + + public void addToEndOfRow(int row, boolean right, StatusBar bar) { + if (row>0) { + LinkedList<StatusBar> statusBars = top.get(row - 1); + statusBars.add(bar); + bar.gridY = row; + bar.gridX = statusBars.indexOf(bar)+1; + } else if (row<0) { + LinkedList<StatusBar> statusBars = (right? bottomRight: bottomLeft).get(Math.abs(row)-1); + statusBars.add(bar); + bar.gridY = row; + bar.gridX = (statusBars.indexOf(bar)+1) * (right ? 1: -1); + } + } + public void remove(int x, int y) { System.out.println("Removing x: " + x + " y: " + y); if (y > 0) { @@ -92,6 +114,21 @@ public class BarGrid { } } + public boolean coordinatesExist(int x, int y) { + if (x == 0 || y == 0) return false; + if (y > 0) { + if (y > getTopSize()) return false; + return x <= getRow(y, false).size(); + } else { + if (Math.abs(y) > (x < 0 ? getBottomLeftSize(): getBottomRightSize())) return false; + return Math.abs(x) <= getRow(y, x > 0).size(); + } + } + + public StatusBar getBar(int x, int y) { + return getRow(y, x>0).get(Math.abs(x)-1); + } + public int getTopSize() {return top.size();} public int getBottomLeftSize() {return bottomLeft.size();} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarColorPopup.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarColorPopup.java new file mode 100644 index 00000000..a3ce4e43 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarColorPopup.java @@ -0,0 +1,117 @@ +package de.hysky.skyblocker.skyblock.fancybars; + +import de.hysky.skyblocker.utils.render.gui.AbstractPopupScreen; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.widget.*; +import net.minecraft.text.Style; +import net.minecraft.text.Text; + +import java.awt.*; +import java.util.List; +import java.util.function.Consumer; + +public class EditBarColorPopup extends AbstractPopupScreen { + + private final Consumer<Color> setColor; + + private DirectionalLayoutWidget layout = DirectionalLayoutWidget.vertical(); + private BasicColorSelector colorSelector; + + protected EditBarColorPopup(Text title, Screen backgroundScreen, Consumer<Color> setColor) { + super(title, backgroundScreen); + this.setColor = setColor; + } + + @Override + protected void init() { + super.init(); + layout = DirectionalLayoutWidget.vertical(); + layout.spacing(8).getMainPositioner().alignHorizontalCenter(); + layout.add(new TextWidget(title.copy().fillStyle(Style.EMPTY.withBold(true)), MinecraftClient.getInstance().textRenderer)); + colorSelector = new BasicColorSelector(0, 0, 150, () -> done(null)); + layout.add(colorSelector); + + DirectionalLayoutWidget horizontal = DirectionalLayoutWidget.horizontal(); + ButtonWidget buttonWidget = ButtonWidget.builder(Text.literal("Cancel"), button -> close()).width(80).build(); + horizontal.add(buttonWidget); + horizontal.add(ButtonWidget.builder(Text.literal("Done"), this::done).width(80).build()); + + layout.add(horizontal); + layout.forEachChild(this::addDrawableChild); + this.layout.refreshPositions(); + SimplePositioningWidget.setPos(layout, this.getNavigationFocus()); + } + + private void done(Object object) { + if (colorSelector.validColor) setColor.accept(new Color(colorSelector.getColor())); + close(); + } + + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + super.renderBackground(context, mouseX, mouseY, delta); + drawPopupBackground(context, layout.getX(), layout.getY(), layout.getWidth(), layout.getHeight()); + } + + private static class BasicColorSelector extends ContainerWidget { + + private final EnterConfirmTextFieldWidget textFieldWidget; + + public BasicColorSelector(int x, int y, int width, Runnable onEnter) { + super(x, y, width, 15, Text.literal("edit color")); + textFieldWidget = new EnterConfirmTextFieldWidget(MinecraftClient.getInstance().textRenderer, getX() + 16, getY(), width - 16, 15, Text.empty(), onEnter); + textFieldWidget.setChangedListener(this::onTextChange); + textFieldWidget.setTextPredicate(s -> s.length() <= 6); + } + + @Override + public List<? extends Element> children() { + return List.of(textFieldWidget); + } + + public int getColor() { + return color; + } + + private int color = 0xFF000000; + private boolean validColor = false; + + private void onTextChange(String text) { + try { + color = Integer.parseInt(text, 16) | 0xFF000000; + validColor = true; + } catch (NumberFormatException e) { + color = 0; + validColor = false; + } + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + context.drawBorder(getX(), getY(), 15, 15, validColor ? -1 : 0xFFDD0000); + context.fill(getX() + 1, getY() + 1, getX() + 14, getY() + 14, color); + textFieldWidget.renderWidget(context, mouseX, mouseY, delta); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + + } + + @Override + public void setX(int x) { + super.setX(x); + textFieldWidget.setX(getX()+16); + } + + @Override + public void setY(int y) { + super.setY(y); + textFieldWidget.setY(getY()); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java new file mode 100644 index 00000000..54af7a03 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java @@ -0,0 +1,274 @@ +package de.hysky.skyblocker.skyblock.fancybars; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.tooltip.TooltipBackgroundRenderer; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.gui.widget.ContainerWidget; +import net.minecraft.client.gui.widget.TextWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Colors; +import net.minecraft.util.Formatting; + +import java.awt.*; +import java.util.List; +import java.util.function.Consumer; + +public class EditBarWidget extends ContainerWidget { + + private final EnumCyclingOption<StatusBar.IconPosition> iconOption; + private final BooleanOption booleanOption; + + private final ColorOption color1; + private final ColorOption color2; + private final ColorOption textColor; + private final TextWidget nameWidget; + + private int contentsWidth = 0; + + public EditBarWidget(int x, int y, Screen parent) { + super(x, y, 100, 66, Text.literal("Edit bar")); + + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + + nameWidget = new TextWidget(Text.empty(), textRenderer); + + MutableText translatable = Text.translatable("skyblocker.bars.config.icon"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + textRenderer.getWidth("RIGHT") + 10); + iconOption = new EnumCyclingOption<>(0, 11, getWidth(), translatable, StatusBar.IconPosition.class); + + translatable = Text.translatable("skyblocker.bars.config.showValue"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + booleanOption = new BooleanOption(0, 22, getWidth(), translatable); + + // COLO(u)RS + translatable = Text.translatable("skyblocker.bars.config.mainColor"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + color1 = new ColorOption(0, 33, getWidth(), translatable, parent); + + translatable = Text.translatable("skyblocker.bars.config.overflowColor"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + color2 = new ColorOption(0, 44, getWidth(), translatable, parent); + + translatable = Text.translatable("skyblocker.bars.config.textColor"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + textColor = new ColorOption(0, 55, getWidth(), translatable, parent); + + setWidth(contentsWidth); + } + + @Override + public List<? extends Element> children() { + return List.of(iconOption, booleanOption, color1, color2, textColor); + } + + public int insideMouseX = 0; + public int insideMouseY = 0; + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isHovered()) { + insideMouseX = mouseX; + insideMouseY = mouseY; + } else { + int i = mouseX - insideMouseX; + int j = mouseY - insideMouseY; + if (i * i + j * j > 30 * 30) visible = false; + } + TooltipBackgroundRenderer.render(context, getX(), getY(), getWidth(), getHeight(), 0); + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(getX(), getY(), 0); + nameWidget.render(context, mouseX, mouseY, delta); + iconOption.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + booleanOption.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + color1.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + color2.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + textColor.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + matrices.pop(); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (!visible) return false; + if (!isHovered()) visible = false; + return super.mouseClicked(mouseX - getX(), mouseY - getY(), button); + } + + public void setStatusBar(StatusBar statusBar) { + iconOption.setCurrent(statusBar.getIconPosition()); + iconOption.setOnChange(statusBar::setIconPosition); + booleanOption.setCurrent(statusBar.showText()); + booleanOption.setOnChange(statusBar::setShowText); + + color1.setCurrent(statusBar.getColors()[0].getRGB()); + color1.setOnChange(color -> statusBar.getColors()[0] = color); + + color2.active = statusBar.hasOverflow(); + if (color2.active) { + color2.setCurrent(statusBar.getColors()[1].getRGB()); + color2.setOnChange(color -> statusBar.getColors()[1] = color); + } + + if (statusBar.getTextColor() != null) { + textColor.setCurrent(statusBar.getTextColor().getRGB()); + } + textColor.setOnChange(statusBar::setTextColor); + + MutableText formatted = statusBar.getName().copy().formatted(Formatting.BOLD); + nameWidget.setMessage(formatted); + setWidth(Math.max(MinecraftClient.getInstance().textRenderer.getWidth(formatted), contentsWidth)); + } + + @Override + public void setWidth(int width) { + super.setWidth(width); + iconOption.setWidth(width); + booleanOption.setWidth(width); + color1.setWidth(width); + color2.setWidth(width); + textColor.setWidth(width); + nameWidget.setWidth(width); + + } + + public static class EnumCyclingOption<T extends Enum<T>> extends ClickableWidget { + + private T current; + private final T[] values; + private Consumer<T> onChange = null; + + public EnumCyclingOption(int x, int y, int width, Text message, Class<T> enumClass) { + super(x, y, width, 11, message); + values = enumClass.getEnumConstants(); + current = values[0]; + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isMouseOver(mouseX, mouseY)) { + context.fill(getX(), getY(), getRight(), getBottom(), 0x20FFFFFF); + } + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, getMessage(), getX() + 1, getY() + 1, -1, true); + String string = current.toString(); + context.drawText(textRenderer, string, getRight() - textRenderer.getWidth(string) - 1, getY() + 1, -1, true); + } + + public void setCurrent(T current) { + this.current = current; + } + + @Override + public void onClick(double mouseX, double mouseY) { + current = values[(current.ordinal() + 1) % values.length]; + if (onChange != null) onChange.accept(current); + super.onClick(mouseX, mouseY); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + } + + public void setOnChange(Consumer<T> onChange) { + this.onChange = onChange; + } + } + + public static class BooleanOption extends ClickableWidget { + + private boolean current = false; + private Consumer<Boolean> onChange = null; + + public BooleanOption(int x, int y, int width, Text message) { + super(x, y, width, 11, message); + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isMouseOver(mouseX, mouseY)) { + context.fill(getX(), getY(), getRight(), getBottom(), 0x20FFFFFF); + } + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, getMessage(), getX() + 1, getY() + 1, -1, true); + context.drawBorder(getRight() - 10, getY() + 1, 9, 9, -1); + if (current) context.fill(getRight() - 8, getY() + 3, getRight() - 3, getY() + 8, -1); + } + + @Override + public void onClick(double mouseX, double mouseY) { + current = !current; + if (onChange != null) onChange.accept(current); + super.onClick(mouseX, mouseY); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + } + + public void setCurrent(boolean current) { + this.current = current; + } + + public void setOnChange(Consumer<Boolean> onChange) { + this.onChange = onChange; + } + } + + public static class ColorOption extends ClickableWidget { + + public void setCurrent(int current) { + this.current = current; + } + + private int current = 0; + private Consumer<Color> onChange = null; + private final Screen parent; + + public ColorOption(int x, int y, int width, Text message, Screen parent) { + super(x, y, width, 11, message); + this.parent = parent; + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isMouseOver(mouseX, mouseY)) { + context.fill(getX(), getY(), getRight(), getBottom(), 0x20FFFFFF); + } + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, getMessage(), getX() + 1, getY() + 1, active ? -1 : Colors.GRAY, true); + context.drawBorder(getRight() - 10, getY() + 1, 9, 9, active ? -1 : Colors.GRAY); + context.fill(getRight() - 8, getY() + 3, getRight() - 3, getY() + 8, active ? current : Colors.GRAY); + } + + @Override + public void onClick(double mouseX, double mouseY) { + super.onClick(mouseX, mouseY); + MinecraftClient.getInstance().setScreen(new EditBarColorPopup(Text.literal("Edit ").append(getMessage()), parent, this::set)); + } + + private void set(Color color) { + current = color.getRGB(); + if (onChange != null) onChange.accept(color); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + + } + + public void setOnChange(Consumer<Color> onChange) { + this.onChange = onChange; + } + } +} 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 6d321a90..ea4a0388 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java @@ -1,5 +1,8 @@ package de.hysky.skyblocker.skyblock.fancybars; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.utils.render.RenderHelper; import net.minecraft.client.MinecraftClient; @@ -8,7 +11,7 @@ import net.minecraft.client.gui.*; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.gui.widget.Widget; -import net.minecraft.util.Colors; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.apache.commons.lang3.builder.ToStringBuilder; import org.jetbrains.annotations.Nullable; @@ -21,13 +24,66 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { private static final Identifier BAR_FILL = new Identifier(SkyblockerMod.NAMESPACE, "bars/bar_fill"); private static final Identifier BAR_BACK = new Identifier(SkyblockerMod.NAMESPACE, "bars/bar_back"); + + /* public static final Codec<StatusBar> CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.INT.fieldOf("size").forGetter(bar -> bar.size), + Codec.INT.fieldOf("x").forGetter(bar -> bar.gridX), + Codec.INT.fieldOf("y").forGetter(bar -> bar.gridY), + Codec.STRING.listOf().fieldOf("colors").xmap( + strings -> strings.stream().map(s -> Integer.parseInt(s, 16)).map(Color::new).toArray(Color[]::new), + colors -> Arrays.stream(colors).map(color -> Integer.toHexString(color.getRGB())).toList()) + .forGetter(StatusBar::getColors), + Codec.STRING.optionalFieldOf("text_color").xmap( + s -> { + if (s.isPresent()) { + return Optional.of(new Color(Integer.parseInt(s.get(), 16))); + } else return Optional.empty(); + }, + o -> o.map(object -> Integer.toHexString(((Color) object).getRGB()))) + .forGetter(bar -> { + if (bar.getTextColor() != null) { + return Optional.of(bar.getTextColor()); + } else return Optional.empty(); + }), + Codec.BOOL.optionalFieldOf("show_text", true).forGetter(StatusBar::showText), + Codec.STRING.fieldOf("icon_position").xmap( + IconPosition::valueOf, + Enum::toString + ).forGetter(bar -> bar.iconPosition) + ) + + .apply(instance, ));*/ + private final Identifier icon; - private final Color[] colors; + + public Color[] getColors() { + return colors; + } + + public boolean hasOverflow() { + return hasOverflow; + } + + public @Nullable Color getTextColor() { + return textColor; + } + + private Color[] colors; private final boolean hasOverflow; - private final @Nullable Color textColor; - private final String name; - private @Nullable Consumer<StatusBar> onClick = null; + public void setTextColor(@Nullable Color textColor) { + this.textColor = textColor; + } + + private @Nullable Color textColor; + + public Text getName() { + return name; + } + + private final Text name; + + private @Nullable OnClick onClick = null; public int gridX = 0; public int gridY = 0; @@ -37,12 +93,15 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { public float fill = 0; public float overflowFill = 0; - private Object text = ""; + private Object value = ""; private int x = 0; private int y = 0; - public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor, String name) { + private IconPosition iconPosition = IconPosition.LEFT; + private boolean showText = true; + + public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor, Text name) { this.icon = icon; this.colors = colors; this.hasOverflow = hasOverflow; @@ -50,32 +109,42 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { this.name = name; } - public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor){ - this(icon, colors, hasOverflow, textColor, "no name"); + public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor) { + this(icon, colors, hasOverflow, textColor, Text.empty()); } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (width <= 0) return; - context.drawGuiTexture(icon, x, y, 9, 9); - context.drawGuiTexture(BAR_BACK, x + 10, y + 1, width - 10, 7); - RenderHelper.renderNineSliceColored(context, BAR_FILL, x + 11, y + 2, (int) ((width - 12) * fill), 5, colors[0]); + switch (iconPosition) { + case LEFT -> context.drawGuiTexture(icon, x, y, 9, 9); + case RIGHT -> context.drawGuiTexture(icon, x + width - 9, y, 9, 9); + } + + int barWith = iconPosition.equals(IconPosition.OFF) ? width : width - 10; + int barX = iconPosition.equals(IconPosition.LEFT) ? x + 10 : x; + context.drawGuiTexture(BAR_BACK, barX, y + 1, barWith, 7); + RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, y + 2, (int) ((barWith - 2) * fill), 5, colors[0]); + + if (hasOverflow && overflowFill > 0) { - RenderHelper.renderNineSliceColored(context, BAR_FILL, x + 11, y + 2, (int) ((width - 12) * overflowFill), 5, colors[1]); + RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, y + 2, (int) ((barWith - 2) * overflowFill), 5, colors[1]); } - context.drawText(MinecraftClient.getInstance().textRenderer, gridX + " ; " + gridY , x, y-9, Colors.WHITE, true); + //context.drawText(MinecraftClient.getInstance().textRenderer, gridX + " " + gridY + " s:" + size , x, y-9, Colors.WHITE, true); } public void updateValues(float fill, float overflowFill, Object text) { - this.text = text; + this.value = text; this.fill = fill; this.overflowFill = overflowFill; } public void renderText(DrawContext context) { TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - String text = this.text.toString(); - int x = this.x + 11 + (width - textRenderer.getWidth(text) - 12) / 2; + int barWith = iconPosition.equals(IconPosition.OFF) ? width : width - 10; + int barX = iconPosition.equals(IconPosition.LEFT) ? x + 10 : x; + String text = this.value.toString(); + int x = barX + (barWith - textRenderer.getWidth(text)) / 2; int y = this.y - 3; final int[] offsets = new int[]{-1, 1}; @@ -83,7 +152,7 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { context.drawText(textRenderer, text, x + i, y, 0, false); context.drawText(textRenderer, text, x, y + i, 0, false); } - context.drawText(textRenderer, text, x, y, (textColor == null ? colors[0]: textColor).getRGB(), false); + context.drawText(textRenderer, text, x, y, (textColor == null ? colors[0] : textColor).getRGB(), false); } public void renderCursor(DrawContext context, int mouseX, int mouseY, float delta) { @@ -135,6 +204,14 @@ 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(); @@ -146,11 +223,11 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { } @Override - public void forEachChild(Consumer<ClickableWidget> consumer) {} + public void forEachChild(Consumer<ClickableWidget> consumer) { + } @Override public void setFocused(boolean focused) { - } @Override @@ -167,18 +244,17 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!isMouseOver(mouseX, mouseY)) return false; if (onClick != null) { - onClick.accept(this); + onClick.onClick(this, button, (int) mouseX, (int) mouseY); } return true; } - public void setOnClick(@Nullable Consumer<StatusBar> onClick) { + public void setOnClick(@Nullable OnClick onClick) { this.onClick = onClick; } @Override public void appendNarrations(NarrationMessageBuilder builder) { - } @Override @@ -193,4 +269,76 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { .append("width", width) .toString(); } + + public IconPosition getIconPosition() { + return iconPosition; + } + + public void setIconPosition(IconPosition iconPosition) { + this.iconPosition = iconPosition; + } + + public boolean showText() { + return showText; + } + + public void setShowText(boolean showText) { + this.showText = showText; + } + + public enum IconPosition { + LEFT, + RIGHT, + OFF + } + + @FunctionalInterface + public interface OnClick { + + void onClick(StatusBar statusBar, int button, int mouseX, int mouseY); + } + + public void loadFromJson(JsonObject object) { + // Make colors optional, so it's easy to reset to default + if (object.has("colors")) { + JsonArray colors1 = object.get("colors").getAsJsonArray(); + if (colors1.size() < 2 && hasOverflow) { + throw new IllegalStateException("Missing second color of bar that has overflow"); + } + Color[] newColors = new Color[colors1.size()]; + for (int i = 0; i < colors1.size(); i++) { + JsonElement jsonElement = colors1.get(i); + newColors[i] = new Color(Integer.parseInt(jsonElement.getAsString(), 16)); + } + this.colors = newColors; + } + + if (object.has("text_color")) this.textColor = new Color(Integer.parseInt(object.get("text_color").getAsString(), 16)); + + 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("show_text")) this.showText = object.get("show_text").getAsBoolean(); + + } + + public JsonObject toJson() { + JsonObject object = new JsonObject(); + JsonArray colors1 = new JsonArray(); + for (Color color : colors) { + colors1.add(Integer.toHexString(color.getRGB()).substring(2)); + } + object.add("colors", colors1); + if (textColor != null) { + object.addProperty("text_color", Integer.toHexString(textColor.getRGB()).substring(2)); + } + object.addProperty("size", size); + object.addProperty("x", gridX); + object.addProperty("y", gridY); + object.addProperty("icon_position", iconPosition.toString()); + object.addProperty("show_text", showText); + return object; + } } 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 8c659029..3bcc2011 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java @@ -2,7 +2,9 @@ package de.hysky.skyblocker.skyblock.fancybars; import de.hysky.skyblocker.mixin.accessor.WindowAccessor; import de.hysky.skyblocker.skyblock.FancyStatusBars; -import net.minecraft.client.MinecraftClient; +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.objects.ObjectBooleanMutablePair; +import it.unimi.dsi.fastutil.objects.ObjectObjectMutablePair; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.ScreenPos; import net.minecraft.client.gui.ScreenRect; @@ -17,16 +19,16 @@ import org.lwjgl.glfw.GLFW; import java.util.Collection; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; public class StatusBarsConfigScreen extends Screen { private static final Identifier HOTBAR_TEXTURE = new Identifier("hud/hotbar"); - private final long RESIZE_CURSOR = GLFW.glfwCreateStandardCursor(GLFW.GLFW_HRESIZE_CURSOR); + public static final long RESIZE_CURSOR = GLFW.glfwCreateStandardCursor(GLFW.GLFW_HRESIZE_CURSOR); private final Map<ScreenRect, int[]> meaningFullName = new HashMap<>(); + private static final int HOTBAR_WIDTH = 182; private @Nullable StatusBar cursorBar = null; @@ -35,7 +37,14 @@ public class StatusBarsConfigScreen extends Screen { FancyStatusBars.updatePositions(); } - private final int[] currentCoords = new int[]{0, 0}; + private final int[] currentCursorCoords = new int[]{0, 0}; + + private final Pair<int[], Boolean> resizeHover = new ObjectBooleanMutablePair<>(new int[]{0, 0}, false); + + private final Pair<int[], int[]> resizedBars = ObjectObjectMutablePair.of(new int[]{0, 0}, new int[]{0, 0}); + private boolean resizing = false; + + private EditBarWidget editBarWidget; @SuppressWarnings("UnreachableCode") // IntelliJ big stupid @Override @@ -44,45 +53,47 @@ public class StatusBarsConfigScreen extends Screen { context.fillGradient(screenRect.position().x(), screenRect.position().y(), screenRect.position().x() + screenRect.width(), screenRect.position().y() + screenRect.height(), 0xFFFF0000, 0xFF0000FF); } super.render(context, mouseX, mouseY, delta); - context.drawGuiTexture(HOTBAR_TEXTURE, width / 2 - 91, height - 22, 182, 22); + context.drawGuiTexture(HOTBAR_TEXTURE, width / 2 - HOTBAR_WIDTH / 2, height - 22, HOTBAR_WIDTH, 22); + editBarWidget.render(context, mouseX, mouseY, delta); + ScreenRect mouseRect = new ScreenRect(new ScreenPos(mouseX - 1, mouseY - 1), 3, 3); assert client != null; WindowAccessor window = (WindowAccessor) (Object) client.getWindow(); assert window != null; if (cursorBar != null) { cursorBar.renderCursor(context, mouseX, mouseY, delta); - context.drawText(textRenderer, currentCoords[0] + " " + currentCoords[1], 100, 5, Colors.WHITE, true); + context.drawText(textRenderer, currentCursorCoords[0] + " " + currentCursorCoords[1], 100, 5, Colors.WHITE, true); - if (FancyStatusBars.barGrid.getTopSize() == 0 && topBarZone.overlaps(mouseRect) && currentCoords[1] != 1) { + if (FancyStatusBars.barGrid.getTopSize() == 0 && topBarZone.overlaps(mouseRect) && currentCursorCoords[1] != 1) { FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); FancyStatusBars.barGrid.addRow(1, true); FancyStatusBars.barGrid.add(1, 1, cursorBar); - currentCoords[1] = 1; + currentCursorCoords[1] = 1; FancyStatusBars.updatePositions(); - } else if (FancyStatusBars.barGrid.getBottomLeftSize() == 0 && bottomLeftBarZone.overlaps(mouseRect) && (currentCoords[0] != -1 || currentCoords[1] != -1)) { + } else if (FancyStatusBars.barGrid.getBottomLeftSize() == 0 && bottomLeftBarZone.overlaps(mouseRect) && (currentCursorCoords[0] != -1 || currentCursorCoords[1] != -1)) { FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); FancyStatusBars.barGrid.addRow(-1, false); FancyStatusBars.barGrid.add(-1, -1, cursorBar); - currentCoords[0] = -1; - currentCoords[1] = -1; + currentCursorCoords[0] = -1; + currentCursorCoords[1] = -1; FancyStatusBars.updatePositions(); - } else if (FancyStatusBars.barGrid.getBottomRightSize() == 0 && bottomRightBarZone.overlaps(mouseRect) && (currentCoords[0] != 1 || currentCoords[1] != -1)) { + } else if (FancyStatusBars.barGrid.getBottomRightSize() == 0 && bottomRightBarZone.overlaps(mouseRect) && (currentCursorCoords[0] != 1 || currentCursorCoords[1] != -1)) { FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); FancyStatusBars.barGrid.addRow(-1, true); FancyStatusBars.barGrid.add(1, -1, cursorBar); - currentCoords[0] = 1; - currentCoords[1] = -1; + currentCursorCoords[0] = 1; + currentCursorCoords[1] = -1; FancyStatusBars.updatePositions(); } else rectLoop:for (ScreenRect screenRect : meaningFullName.keySet()) { for (NavigationDirection direction : NavigationDirection.values()) { - boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); + boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); if (overlaps) { int[] ints = meaningFullName.get(screenRect); + final boolean vertical = direction.getAxis().equals(NavigationAxis.VERTICAL); int offsetX = 0; int offsetY = 0; - final boolean vertical = direction.getAxis().equals(NavigationAxis.VERTICAL); if (vertical) { if (!direction.isPositive()) { offsetY = ints[1] > 0 ? 1 : 0; @@ -97,11 +108,9 @@ public class StatusBarsConfigScreen extends Screen { } } context.drawText(textRenderer, ints[0] + offsetX + " " + ints[1] + offsetY, 100, 15, Colors.WHITE, true); - if (ints[0] + offsetX != currentCoords[0] || ints[1] + offsetY != currentCoords[1]) { - currentCoords[0] = ints[0] + offsetX; - currentCoords[1] = ints[1] + offsetY; - System.out.println("Moving " + cursorBar); - System.out.println(ints[0] + " " + ints[1]); + if (ints[0] + offsetX != currentCursorCoords[0] || ints[1] + offsetY != currentCursorCoords[1]) { + currentCursorCoords[0] = ints[0] + offsetX; + currentCursorCoords[1] = ints[1] + offsetY; FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); @@ -114,22 +123,99 @@ public class StatusBarsConfigScreen extends Screen { FancyStatusBars.barGrid.add(ints[0] + offsetX, ints[1], cursorBar); } FancyStatusBars.updatePositions(); - System.out.println("After " + cursorBar); } break rectLoop; } } } } else { - rectLoop:for (ScreenRect screenRect : meaningFullName.keySet()) { - for (NavigationDirection direction : new NavigationDirection[]{NavigationDirection.LEFT, NavigationDirection.RIGHT}) { - boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); + // RESIZING STATE + if (resizing) { + int middleX; + boolean bottom; - if (overlaps) { - GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); - break rectLoop; - } else { - GLFW.glfwSetCursor(window.getHandle(), 0); + int[] left = resizedBars.left(); + int[] right = resizedBars.right(); + boolean hasRight = right[0] != 0; + boolean hasLeft = left[0] != 0; + if (!hasRight) { + StatusBar bar = FancyStatusBars.barGrid.getBar(left[0], left[1]); + middleX = bar.getX() + bar.getWidth(); + bottom = bar.gridY < 0; + } else { + middleX = FancyStatusBars.barGrid.getBar(right[0], right[1]).getX(); + bottom = right[1] < 0; + } + int i = bottom ? 20 : 10; + boolean doResize = true; + StatusBar rightBar = null; + StatusBar leftBar = null; + + context.drawText(textRenderer, Integer.toString(mouseX - middleX), 100, 25, -1, true); + + if (mouseX < middleX) { + if (middleX - mouseX > i) { + + if (hasRight) { + rightBar = FancyStatusBars.barGrid.getBar(right[0], right[1]); + if (rightBar.size + 1 > rightBar.getMaximumSize()) doResize = false; + } + if (hasLeft) { + leftBar = FancyStatusBars.barGrid.getBar(left[0], left[1]); + if (leftBar.size - 1 < leftBar.getMinimumSize()) doResize = false; + } + + if (doResize) { + if (hasRight) rightBar.size++; + if (hasLeft) leftBar.size--; + FancyStatusBars.updatePositions(); + } + } + } else { + if (mouseX - middleX > i) { + + if (hasRight) { + rightBar = FancyStatusBars.barGrid.getBar(right[0], right[1]); + if (rightBar.size - 1 < rightBar.getMinimumSize()) doResize = false; + } + if (hasLeft) { + leftBar = FancyStatusBars.barGrid.getBar(left[0], left[1]); + if (leftBar.size + 1 > leftBar.getMaximumSize()) doResize = false; + } + context.drawText(textRenderer, leftBar.size + " " + leftBar.getMaximumSize(), 100, 35, -1, true); + + if (doResize) { + if (hasRight) rightBar.size--; + if (hasLeft) leftBar.size++; + FancyStatusBars.updatePositions(); + } + } + } + GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); + } + // NOT RESIZING STATE + else { + rectLoop: + for (ScreenRect screenRect : meaningFullName.keySet()) { + for (NavigationDirection direction : new NavigationDirection[]{NavigationDirection.LEFT, NavigationDirection.RIGHT}) { + boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); + + if (overlaps && !editBarWidget.isMouseOver(mouseX, mouseY)) { + int[] ints = meaningFullName.get(screenRect); + boolean left = direction.equals(NavigationDirection.LEFT); + if ((ints[0] == 1 && left) || (ints[0] == -1 && !left) || (!left && ints[1] > 0 && ints[0] == FancyStatusBars.barGrid.getRow(ints[1], true).size())) { + break; + } + resizeHover.first()[0] = ints[0]; + resizeHover.first()[1] = ints[1]; + resizeHover.right(!left); + GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); + break rectLoop; + } else { + resizeHover.first()[0] = 0; + resizeHover.first()[1] = 0; + GLFW.glfwSetCursor(window.getHandle(), 0); + } } } } @@ -143,13 +229,16 @@ public class StatusBarsConfigScreen extends Screen { @Override protected void init() { super.init(); + editBarWidget = new EditBarWidget(0, 0, this); + editBarWidget.visible = false; + addSelectableChild(editBarWidget); // rendering separately to have it above hotbar Collection<StatusBar> values = FancyStatusBars.statusBars.values(); values.forEach(this::setup); checkZeroCoordinates(values); updateScreenRects(); - topBarZone = new ScreenRect(width / 2 - 91, height - 22 - 15, 182, 15); - bottomLeftBarZone = new ScreenRect(width / 2 - 91 - 20, height - 22, 20, 22); - bottomRightBarZone = new ScreenRect(width / 2 + 91, height - 22, 20, 22); + topBarZone = new ScreenRect(width / 2 - HOTBAR_WIDTH / 2, height - 22 - 15, HOTBAR_WIDTH, 15); + bottomLeftBarZone = new ScreenRect(width / 2 - HOTBAR_WIDTH / 2 - 20, height - 22, 20, 22); + bottomRightBarZone = new ScreenRect(width / 2 + HOTBAR_WIDTH / 2, height - 22, 20, 22); } private void setup(StatusBar statusBar) { @@ -175,8 +264,9 @@ public class StatusBarsConfigScreen extends Screen { super.removed(); FancyStatusBars.statusBars.values().forEach(statusBar -> statusBar.setOnClick(null)); FancyStatusBars.updatePositions(); + assert client != null; GLFW.glfwSetCursor(((WindowAccessor) (Object) client.getWindow()).getHandle(), 0); - GLFW.glfwDestroyCursor(RESIZE_CURSOR); // Does it explode if I don't do that?? idk aaaaaaaaa + FancyStatusBars.saveBarConfig(); } @Override @@ -184,11 +274,20 @@ public class StatusBarsConfigScreen extends Screen { return false; } - private void onClick(StatusBar statusBar) { - cursorBar = statusBar; - FancyStatusBars.barGrid.remove(statusBar.gridX, statusBar.gridY); - FancyStatusBars.updatePositions(); - updateScreenRects(); + private void onClick(StatusBar statusBar, int button, int mouseX, int mouseY) { + if (button == 0) { + cursorBar = statusBar; + FancyStatusBars.barGrid.remove(statusBar.gridX, statusBar.gridY); + FancyStatusBars.updatePositions(); + updateScreenRects(); + } else if (button == 1) { + int x = Math.min(mouseX - 1, width - editBarWidget.getWidth()); + int y = Math.min(mouseY - 1, height - editBarWidget.getHeight()); + editBarWidget.visible = true; + editBarWidget.setStatusBar(statusBar); + editBarWidget.setX(x); + editBarWidget.setY(y); + } } private void updateScreenRects() { @@ -206,7 +305,47 @@ public class StatusBarsConfigScreen extends Screen { checkZeroCoordinates(FancyStatusBars.statusBars.values()); updateScreenRects(); return true; + } else if (resizing) { + resizing = false; + resizedBars.left()[0] = 0; + resizedBars.left()[1] = 0; + resizedBars.right()[0] = 0; + resizedBars.right()[1] = 0; + updateScreenRects(); + return true; } return super.mouseReleased(mouseX, mouseY, button); } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + int[] first = resizeHover.first(); + // want the right click thing to have priority + if (!editBarWidget.isMouseOver(mouseX, mouseY) && button == 0 && first[0] != 0 && first[1] != 0) { + if (resizeHover.right()) { + resizedBars.left()[0] = first[0]; + resizedBars.left()[1] = first[1]; + if (FancyStatusBars.barGrid.coordinatesExist(first[0] + 1, first[1])) { + resizedBars.right()[0] = first[0] + 1; + resizedBars.right()[1] = first[1]; + } else { + resizedBars.right()[0] = 0; + resizedBars.right()[1] = 0; + } + } else { + resizedBars.right()[0] = first[0]; + resizedBars.right()[1] = first[1]; + if (FancyStatusBars.barGrid.coordinatesExist(first[0] - 1, first[1])) { + resizedBars.left()[0] = first[0] - 1; + resizedBars.left()[1] = first[1]; + } else { + resizedBars.left()[0] = 0; + resizedBars.left()[1] = 0; + } + } + resizing = true; + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } } diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractPopupScreen.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractPopupScreen.java index 2bd15955..e7a3e8b2 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractPopupScreen.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractPopupScreen.java @@ -3,10 +3,16 @@ package de.hysky.skyblocker.utils.render.gui; import com.mojang.blaze3d.platform.GlConst; import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.glfw.GLFW; + +import java.util.function.Consumer; /** * A more bare-bones version of Vanilla's Popup Screen. Meant to be extended. @@ -57,4 +63,35 @@ public class AbstractPopupScreen extends Screen { super.onDisplayed(); this.backgroundScreen.blur(); } + + public static class EnterConfirmTextFieldWidget extends TextFieldWidget { + + private final Runnable onEnter; + + public EnterConfirmTextFieldWidget(TextRenderer textRenderer, int width, int height, Text text, Runnable onEnter) { + this(textRenderer, 0, 0, width, height, text, onEnter); + } + + public EnterConfirmTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, Text text,Runnable onEnter) { + this(textRenderer, x, y, width, height, null, text, onEnter); + } + + public EnterConfirmTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, @Nullable TextFieldWidget copyFrom, Text text, Runnable onEnter) { + super(textRenderer, x, y, width, height, copyFrom, text); + this.onEnter = onEnter; + } + + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (!super.keyPressed(keyCode, scanCode, modifiers)) { + if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) { + onEnter.run(); + return true; + } + } else return true; + return false; + } + } + }
\ No newline at end of file diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index d1a5966c..5921cc95 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -496,6 +496,16 @@ "text.autoconfig.skyblocker.option.general.dontStripSkinAlphaValues": "Correct Transparent Skin Pixels", "text.autoconfig.skyblocker.option.general.dontStripSkinAlphaValues.@Tooltip": "When enabled, the alpha values of pixels in skin textures are no longer stripped while in Skyblock.\n\nThis results in the \"filler\" pixels on items using Player Heads to now be completely transparent, although this may have some side effects in odd cases.", + "skyblocker.bars.config.health": "Health", + "skyblocker.bars.config.defense": "Defense", + "skyblocker.bars.config.intelligence": "Intelligence", + "skyblocker.bars.config.experience": "Experience", + "skyblocker.bars.config.mainColor": "Main Color", + "skyblocker.bars.config.overflowColor": "Overflow Color", + "skyblocker.bars.config.textColor": "Text Color", + "skyblocker.bars.config.showValue": "Show Value", + "skyblocker.bars.config.icon": "Icon", + "skyblocker.updaterepository.failed": "§cUpdating local repository failed. Remove files manually and restart game.", "skyblocker.dungeons.secrets.physicalEntranceNotFound": "§cDungeon Entrance Room coordinates not found. Please go back to the green Entrance Room.", diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json index a483c0f0..261b7073 100644 --- a/src/main/resources/skyblocker.mixins.json +++ b/src/main/resources/skyblocker.mixins.json @@ -34,6 +34,7 @@ "RenderFishMixin", "ScoreboardMixin", "SocialInteractionsPlayerListWidgetMixin", + "WindowMixin", "WorldRendererMixin", "YggdrasilMinecraftSessionServiceMixin", "YggdrasilServicesKeyInfoMixin", |