From 047149f394359ed957a6b9c050d00c8953ed0198 Mon Sep 17 00:00:00 2001 From: Kevin <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 2 Mar 2025 23:22:16 -0500 Subject: Fabric updates (#1172) * Update fabric deps * Migrate client game test to loom * Migrate to new hud api * Fix fancy tab hud * Rename ScreenMaster to WidgetManager * No server game tests * Update deps * Separate fmj for game test * Run production client game test in CI and move template image * Run client game test * Update screenshots dir --- .../de/hysky/skyblocker/SkyblockerGameTest.java | 60 ----- .../config/categories/UIAndVisualsCategory.java | 4 +- .../hysky/skyblocker/events/HudRenderEvents.java | 12 +- .../de/hysky/skyblocker/mixins/InGameHudMixin.java | 73 +----- .../skyblocker/skyblock/dungeon/DungeonMap.java | 8 +- .../skyblock/dungeon/DungeonScoreHUD.java | 8 +- .../skyblock/dungeon/FireFreezeStaffTimer.java | 7 +- .../skyblock/dwarven/GlaciteColdOverlay.java | 4 + .../profittrackers/PowderMiningTracker.java | 7 +- .../skyblocker/skyblock/garden/FarmingHud.java | 9 +- .../tabhud/config/WidgetsConfigurationScreen.java | 16 +- .../skyblock/tabhud/config/preview/PreviewTab.java | 40 ++-- .../tabhud/config/preview/PreviewWidget.java | 12 +- .../tabhud/screenbuilder/ScreenBuilder.java | 8 +- .../tabhud/screenbuilder/ScreenMaster.java | 218 ------------------ .../tabhud/screenbuilder/WidgetManager.java | 244 +++++++++++++++++++++ .../screenbuilder/pipeline/PositionRule.java | 8 +- .../screenbuilder/pipeline/WidgetPositioner.java | 6 +- .../skyblock/tabhud/util/PlayerListManager.java | 4 +- .../utils/render/title/TitleContainer.java | 8 +- 20 files changed, 340 insertions(+), 416 deletions(-) delete mode 100644 src/main/java/de/hysky/skyblocker/SkyblockerGameTest.java delete mode 100644 src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenMaster.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/WidgetManager.java (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerGameTest.java b/src/main/java/de/hysky/skyblocker/SkyblockerGameTest.java deleted file mode 100644 index d3da8969..00000000 --- a/src/main/java/de/hysky/skyblocker/SkyblockerGameTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package de.hysky.skyblocker; - -import de.hysky.skyblocker.debug.SnapshotDebug; -import de.hysky.skyblocker.skyblock.fancybars.FancyStatusBars; -import it.unimi.dsi.fastutil.Pair; -import net.fabricmc.fabric.api.client.gametest.v1.ClientGameTestContext; -import net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest; -import net.fabricmc.fabric.api.client.gametest.v1.TestScreenshotComparisonOptions; -import net.fabricmc.fabric.api.client.gametest.v1.TestSingleplayerContext; -import net.minecraft.client.gui.screen.world.WorldCreator; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.world.gen.WorldPresets; - -@SuppressWarnings("UnstableApiUsage") -public class SkyblockerGameTest implements FabricClientGameTest { - @Override - public void runTest(ClientGameTestContext context) { - try (TestSingleplayerContext singleplayer = context.worldBuilder().adjustSettings(worldCreator -> { - worldCreator.setWorldType(new WorldCreator.WorldType(worldCreator.getGeneratorOptionsHolder().getCombinedRegistryManager().getOrThrow(RegistryKeys.WORLD_PRESET).getOrThrow(WorldPresets.DEFAULT))); - worldCreator.setSeed(String.valueOf(SnapshotDebug.AARON_WORLD_SEED)); - }).create()) { - // Set up the world - singleplayer.getServer().runCommand("/fill 180 63 -13 184 67 -17 air"); - singleplayer.getServer().runCommand("/setblock 175 66 -4 minecraft:barrier"); - singleplayer.getServer().runCommand("/tp @a 175 67 -4"); - - context.runOnClient(client -> { - assert client.player != null; - client.player.setYaw(180); - client.player.setPitch(20); - }); - - // Save the current fancy status bars config and reset it to default - var config = context.computeOnClient(client -> { - var curConfig = FancyStatusBars.statusBars.entrySet().stream().map(e -> Pair.of(e.getKey(), e.getValue().toJson())).toList(); - - int[] counts = new int[7]; - FancyStatusBars.statusBars.forEach((type, bar) -> { - bar.anchor = type.getDefaultAnchor(); - bar.gridY = type.getDefaultGridY(); - bar.gridX = counts[type.getDefaultAnchor().ordinal()]++; - }); - FancyStatusBars.placeBarsInPositioner(); - FancyStatusBars.updatePositions(); - return curConfig; - }); - - // Take a screenshot and compare it - singleplayer.getClientWorld().waitForChunksRender(); - context.assertScreenshotEquals(TestScreenshotComparisonOptions.of("skyblocker_render").saveWithFileName("skyblocker_render")); - - // Restore the fancy status bars config - context.runOnClient(client -> { - config.forEach(pair -> FancyStatusBars.statusBars.get(pair.key()).loadFromJson(pair.value())); - FancyStatusBars.placeBarsInPositioner(); - FancyStatusBars.updatePositions(); - }); - } - } -} diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java index d076b7fd..14372b8c 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java @@ -8,7 +8,7 @@ import de.hysky.skyblocker.skyblock.item.slottext.SlotTextManager; import de.hysky.skyblocker.skyblock.item.slottext.SlotTextMode; import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen; import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder; -import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster; +import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.WidgetManager; import de.hysky.skyblocker.skyblock.waypoint.WaypointsScreen; import de.hysky.skyblocker.utils.Location; import de.hysky.skyblocker.utils.Utils; @@ -236,7 +236,7 @@ public class UIAndVisualsCategory { if (Utils.isOnSkyblock()) { MessageScheduler.INSTANCE.sendMessageAfterCooldown("/widgets", true); } else { - MinecraftClient.getInstance().setScreen(new WidgetsConfigurationScreen(Location.HUB, ScreenMaster.ScreenLayer.MAIN_TAB, screen)); + MinecraftClient.getInstance().setScreen(new WidgetsConfigurationScreen(Location.HUB, WidgetManager.ScreenLayer.MAIN_TAB, screen)); } }) .build()) diff --git a/src/main/java/de/hysky/skyblocker/events/HudRenderEvents.java b/src/main/java/de/hysky/skyblocker/events/HudRenderEvents.java index f6ee1ff5..db4db58b 100644 --- a/src/main/java/de/hysky/skyblocker/events/HudRenderEvents.java +++ b/src/main/java/de/hysky/skyblocker/events/HudRenderEvents.java @@ -7,24 +7,27 @@ import net.minecraft.client.render.RenderTickCounter; /** * HUD render events that allow for proper layering between different HUD elements. - * This should always be preferred over Fabric's {@link net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback}. - * - * Perhaps in the future this system could be PR'd to Fabric. + * + * @deprecated Use {@link net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback}. */ +@Deprecated(forRemoval = true) public class HudRenderEvents { /** * Called after the hotbar, status bars, and experience bar have been rendered. */ + @Deprecated(forRemoval = true) public static final Event AFTER_MAIN_HUD = createEventForStage(); /** * Called before the {@link net.minecraft.client.gui.hud.ChatHud} is rendered. */ + @Deprecated(forRemoval = true) public static final Event BEFORE_CHAT = createEventForStage(); /** * Called after the entire HUD is rendered. */ + @Deprecated(forRemoval = true) public static final Event LAST = createEventForStage(); private static Event createEventForStage() { @@ -38,12 +41,13 @@ public class HudRenderEvents { /** * @implNote Similar to Fabric's {@link net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback} */ + @Deprecated(forRemoval = true) @FunctionalInterface public interface HudRenderStage { /** * Called sometime during a specific HUD render stage. * - * @param drawContext The {@link DrawContext} instance + * @param context The {@link DrawContext} instance * @param tickCounter The {@link RenderTickCounter} instance */ void onRender(DrawContext context, RenderTickCounter tickCounter); diff --git a/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java b/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java index 21fc5ab7..1b55ed94 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java @@ -5,8 +5,6 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.systems.RenderSystem; import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.events.HudRenderEvents; -import de.hysky.skyblocker.skyblock.dwarven.GlaciteColdOverlay; import de.hysky.skyblocker.skyblock.fancybars.FancyStatusBars; import de.hysky.skyblocker.skyblock.item.HotbarSlotLock; import de.hysky.skyblocker.skyblock.item.ItemCooldowns; @@ -14,18 +12,14 @@ import de.hysky.skyblocker.skyblock.item.ItemProtection; import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; import de.hysky.skyblocker.skyblock.tabhud.TabHud; import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen; -import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster; import de.hysky.skyblocker.utils.Utils; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.LayeredDrawer; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.gui.hud.PlayerListHud; import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.util.Window; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.scoreboard.Scoreboard; @@ -38,8 +32,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.function.Supplier; @@ -60,11 +52,7 @@ public abstract class InGameHudMixin { @Final private MinecraftClient client; - @Shadow - @Final - private LayeredDrawer layeredDrawer; - - @Inject(method = "renderHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IILnet/minecraft/client/render/RenderTickCounter;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V", ordinal = 0)) + @Inject(method = "renderHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IILnet/minecraft/client/render/RenderTickCounter;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V", ordinal = 0)) public void skyblocker$renderHotbarItemLockOrRarityBg(CallbackInfo ci, @Local(argsOnly = true) DrawContext context, @Local(ordinal = 4, name = "m") int index, @Local(ordinal = 5, name = "n") int x, @Local(ordinal = 6, name = "o") int y, @Local PlayerEntity player) { if (Utils.isOnSkyblock()) { // slot lock @@ -121,12 +109,6 @@ public abstract class InGameHudMixin { if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.hideStatusEffectOverlay) ci.cancel(); } - // TODO switch to fabric event when available - @Inject(method = "renderMiscOverlays", at = @At("TAIL")) - private void skyblocker$afterMiscOverlays(CallbackInfo ci, @Local(argsOnly = true) DrawContext context) { - GlaciteColdOverlay.render(context); - } - @ModifyExpressionValue(method = "renderCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getAttackCooldownProgress(F)F")) private float skyblocker$modifyAttackIndicatorCooldown(float cooldownProgress) { if (Utils.isOnSkyblock() && client.player != null) { @@ -146,59 +128,6 @@ public abstract class InGameHudMixin { } } - @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/LayeredDrawer;addLayer(Lnet/minecraft/client/gui/LayeredDrawer$Layer;)Lnet/minecraft/client/gui/LayeredDrawer;", ordinal = 2)) - private LayeredDrawer.Layer skyblocker$afterMainHud(LayeredDrawer.Layer mainHudLayer) { - return (context, tickCounter) -> { - mainHudLayer.render(context, tickCounter); - HudRenderEvents.AFTER_MAIN_HUD.invoker().onRender(context, tickCounter); - }; - } - - @ModifyArg(method = "", slice = @Slice(from = @At(value = "NEW", target = "Lnet/minecraft/client/gui/LayeredDrawer;", ordinal = 2)), at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/LayeredDrawer;addLayer(Lnet/minecraft/client/gui/LayeredDrawer$Layer;)Lnet/minecraft/client/gui/LayeredDrawer;", ordinal = 5)) - private LayeredDrawer.Layer skyblocker$beforeChat(LayeredDrawer.Layer beforeChatLayer) { - return (context, tickCounter) -> { - HudRenderEvents.BEFORE_CHAT.invoker().onRender(context, tickCounter); - beforeChatLayer.render(context, tickCounter); - }; - } - - @Inject(method = "", at = @At("TAIL")) - private void skyblocker$afterDrawersInitialized(CallbackInfo ci) { - this.layeredDrawer.addLayer(HudRenderEvents.LAST.invoker()::onRender); - } - - // Renders the hud (always on screen) widgets. - // Inject before the debug hud, this injection point is identical to the after main hud event - // z = 200 - // TODO: Switch to fabric event when available - // TODO: The after sleep/before demo timer injection point gives z = 1600, - // and due to the z offset that comes with item rendering, it still renders above the debug hud - @Inject(method = "renderMainHud", at = @At("RETURN")) - private void skyblocker$renderHud(CallbackInfo ci, @Local(argsOnly = true) DrawContext context) { - skyblocker$renderTabHudInternal(context, true); - } - - // Renders the tab widgets - // TODO: Switch to fabric event when available - @Inject(method = "renderPlayerList", at = @At("HEAD")) - private void skyblocker$renderTabHud(CallbackInfo ci, @Local(argsOnly = true) DrawContext context) { - skyblocker$renderTabHudInternal(context, false); - } - - private void skyblocker$renderTabHudInternal(DrawContext context, boolean hud) { - if (!Utils.isOnSkyblock()) return; - MinecraftClient client = MinecraftClient.getInstance(); - - if (client.currentScreen instanceof WidgetsConfigurationScreen) return; - Window window = client.getWindow(); - float scale = SkyblockerConfigManager.get().uiAndVisuals.tabHud.tabHudScale / 100f; - MatrixStack matrices = context.getMatrices(); - matrices.push(); - matrices.scale(scale, scale, 1.F); - ScreenMaster.render(context, (int) (window.getScaledWidth() / scale), (int) (window.getScaledHeight() / scale), hud); - matrices.pop(); - } - @WrapWithCondition(method = "renderPlayerList", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/PlayerListHud;render(Lnet/minecraft/client/gui/DrawContext;ILnet/minecraft/scoreboard/Scoreboard;Lnet/minecraft/scoreboard/ScoreboardObjective;)V")) private boolean skyblocker$shouldRenderHud(PlayerListHud playerListHud, DrawContext context, int scaledWindowWidth, Scoreboard scoreboard, ScoreboardObjective objective) { return !Utils.isOnSkyblock() || !SkyblockerConfigManager.get().uiAndVisuals.tabHud.tabHudEnabled || TabHud.shouldRenderVanilla() || MinecraftClient.getInstance().currentScreen instanceof WidgetsConfigurationScreen; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java index 32fd1afe..471dc753 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java @@ -1,14 +1,16 @@ package de.hysky.skyblocker.skyblock.dungeon; +import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.events.HudRenderEvents; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.LightmapTextureManager; @@ -22,15 +24,17 @@ import net.minecraft.item.FilledMapItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.item.map.MapState; +import net.minecraft.util.Identifier; public class DungeonMap { + private static final Identifier DUNGEON_MAP = Identifier.of(SkyblockerMod.NAMESPACE, "dungeon_map"); private static final MapIdComponent DEFAULT_MAP_ID_COMPONENT = new MapIdComponent(1024); private static final MapRenderState MAP_RENDER_STATE = new MapRenderState(); private static MapIdComponent cachedMapIdComponent = null; @Init public static void init() { - HudRenderEvents.AFTER_MAIN_HUD.register((context, tickCounter) -> render(context)); + HudLayerRegistrationCallback.EVENT.register(d -> d.attachLayerAfter(IdentifiedLayer.STATUS_EFFECTS, DUNGEON_MAP, (context, tickCounter) -> render(context))); ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") .then(ClientCommandManager.literal("hud") .then(ClientCommandManager.literal("dungeon") diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java index 1e0bfb98..85c2afab 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java @@ -2,21 +2,25 @@ package de.hysky.skyblocker.skyblock.dungeon; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.events.HudRenderEvents; import de.hysky.skyblocker.utils.Utils; +import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; public class DungeonScoreHUD { + private static final Identifier DUNGEON_SCORE = Identifier.of("skyblocker", "dungeon_score"); + private DungeonScoreHUD() { } @Init public static void init() { - HudRenderEvents.AFTER_MAIN_HUD.register((context, tickCounter) -> render(context)); + HudLayerRegistrationCallback.EVENT.register(d -> d.attachLayerAfter(IdentifiedLayer.OVERLAY_MESSAGE, DUNGEON_SCORE, (context, tickCounter) -> render(context))); } //This is 4+5 wide, needed to offset the extra width from bold numbers (3×1 wide) in S+ and the "+" (6 wide) so that it doesn't go off the screen if the score is S+ and the hud element is at the right edge of the screen diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java index f5edb4dd..14706ccd 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java @@ -2,22 +2,25 @@ package de.hysky.skyblocker.skyblock.dungeon; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.events.HudRenderEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.RenderTickCounter; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; public class FireFreezeStaffTimer { + private static final Identifier FIRE_FREEZE_STAFF_TIMER = Identifier.of("skyblocker", "fire_freeze_staff_timer"); private static long fireFreezeTimer; @Init public static void init() { - HudRenderEvents.BEFORE_CHAT.register(FireFreezeStaffTimer::onDraw); + HudLayerRegistrationCallback.EVENT.register(d -> d.attachLayerAfter(IdentifiedLayer.OVERLAY_MESSAGE, FIRE_FREEZE_STAFF_TIMER, FireFreezeStaffTimer::onDraw)); ClientReceiveMessageEvents.GAME.register(FireFreezeStaffTimer::onChatMessage); ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> FireFreezeStaffTimer.reset()); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/GlaciteColdOverlay.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/GlaciteColdOverlay.java index 9e6516b6..2e3c89a7 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/GlaciteColdOverlay.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/GlaciteColdOverlay.java @@ -5,7 +5,10 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.render.RenderLayer; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -24,6 +27,7 @@ public class GlaciteColdOverlay { public static void init() { Scheduler.INSTANCE.scheduleCyclic(GlaciteColdOverlay::update, 20); ClientReceiveMessageEvents.GAME.register(GlaciteColdOverlay::coldReset); + HudLayerRegistrationCallback.EVENT.register(d -> d.attachLayerAfter(IdentifiedLayer.MISC_OVERLAYS, POWDER_SNOW_OUTLINE, (context, tickCounter) -> render(context))); } private static void coldReset(Text text, boolean b) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/profittrackers/PowderMiningTracker.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/profittrackers/PowderMiningTracker.java index 10b9d776..8b49ee5c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/profittrackers/PowderMiningTracker.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/profittrackers/PowderMiningTracker.java @@ -6,7 +6,6 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.events.ChatEvents; -import de.hysky.skyblocker.events.HudRenderEvents; import de.hysky.skyblocker.events.ItemPriceUpdateEvent; import de.hysky.skyblocker.events.SkyblockEvents; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; @@ -16,6 +15,8 @@ import it.unimi.dsi.fastutil.doubles.DoubleBooleanPair; import it.unimi.dsi.fastutil.objects.*; import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.ChatHud; @@ -23,6 +24,7 @@ import net.minecraft.client.render.RenderTickCounter; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; import org.apache.commons.lang3.math.NumberUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -39,6 +41,7 @@ import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.lit public final class PowderMiningTracker extends AbstractProfitTracker { public static final PowderMiningTracker INSTANCE = new PowderMiningTracker(); private static final Logger LOGGER = LoggerFactory.getLogger("Skyblocker Powder Mining Tracker"); + private static final Identifier POWDER_MINING_TRACKER = Identifier.of(SkyblockerMod.NAMESPACE, "powder_mining_tracker"); private static final Codec> REWARDS_CODEC = CodecUtils.object2IntMapCodec(Codec.STRING); private static final Object2ObjectArrayMap NAME2ID_MAP = new Object2ObjectArrayMap<>(50); @@ -76,7 +79,7 @@ public final class PowderMiningTracker extends AbstractProfitTracker { @Init public static void init() { ChatEvents.RECEIVE_STRING.register(INSTANCE::onChatMessage); - HudRenderEvents.AFTER_MAIN_HUD.register(PowderMiningTracker::render); + HudLayerRegistrationCallback.EVENT.register(d -> d.attachLayerAfter(IdentifiedLayer.STATUS_EFFECTS, POWDER_MINING_TRACKER, PowderMiningTracker::render)); ItemPriceUpdateEvent.ON_PRICE_UPDATE.register(INSTANCE::onPriceUpdate); INSTANCE.allRewards.init(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java index ab1cfe2d..6b39fb0a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java @@ -3,7 +3,6 @@ package de.hysky.skyblocker.skyblock.garden; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.events.HudRenderEvents; import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Location; @@ -15,12 +14,15 @@ import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; import it.unimi.dsi.fastutil.longs.LongPriorityQueue; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer; import net.fabricmc.fabric.api.event.client.player.ClientPlayerBlockBreakEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,6 +39,7 @@ import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.lit public class FarmingHud { private static final Logger LOGGER = LoggerFactory.getLogger(FarmingHud.class); + private static final Identifier FARMING_HUD = Identifier.of(SkyblockerMod.NAMESPACE, "farming_hud"); public static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(Locale.US); private static final Pattern FARMING_XP = Pattern.compile("\\+(?\\d+(?:\\.\\d+)?) Farming \\((?[\\d,]+(?:\\.\\d+)?%|[\\d,]+/[\\d,]+)\\)"); private static final MinecraftClient client = MinecraftClient.getInstance(); @@ -48,7 +51,7 @@ public class FarmingHud { @Init public static void init() { - HudRenderEvents.AFTER_MAIN_HUD.register((context, tickCounter) -> { + HudLayerRegistrationCallback.EVENT.register(d -> d.attachLayerAfter(IdentifiedLayer.STATUS_EFFECTS, FARMING_HUD, (context, tickCounter) -> { if (shouldRender()) { if (!counter.isEmpty() && counter.peek().rightLong() + 5000 < System.currentTimeMillis()) { counter.poll(); @@ -66,7 +69,7 @@ public class FarmingHud { counterType = CounterType.NONE; } } - }); + })); ClientPlayerBlockBreakEvents.AFTER.register((world, player, pos, state) -> { if (shouldRender()) { blockBreaks.enqueue(System.currentTimeMillis()); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/WidgetsConfigurationScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/WidgetsConfigurationScreen.java index 8a0e0509..39da9d6e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/WidgetsConfigurationScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/WidgetsConfigurationScreen.java @@ -4,7 +4,7 @@ import com.mojang.logging.LogUtils; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.tabhud.config.entries.WidgetEntry; import de.hysky.skyblocker.skyblock.tabhud.config.preview.PreviewTab; -import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster; +import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.WidgetManager; import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListManager; import de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget; import de.hysky.skyblocker.utils.ItemUtils; @@ -39,7 +39,7 @@ public class WidgetsConfigurationScreen extends Screen implements ScreenHandlerL private @Nullable GenericContainerScreenHandler handler; private String titleLowercase; public final boolean noHandler; - private ScreenMaster.ScreenLayer widgetsLayer = null; + private WidgetManager.ScreenLayer widgetsLayer = null; private Screen parent = null; private boolean tabPreview = false; @@ -87,7 +87,7 @@ public class WidgetsConfigurationScreen extends Screen implements ScreenHandlerL * @param handler the container handler * @param titleLowercase the title in lowercase */ - private WidgetsConfigurationScreen(@Nullable GenericContainerScreenHandler handler, String titleLowercase, Location targetLocation, @Nullable ScreenMaster.ScreenLayer widgetLayerToGoTo) { + private WidgetsConfigurationScreen(@Nullable GenericContainerScreenHandler handler, String titleLowercase, Location targetLocation, @Nullable WidgetManager.ScreenLayer widgetLayerToGoTo) { super(Text.literal("Widgets Configuration")); this.handler = handler; this.titleLowercase = titleLowercase; @@ -99,7 +99,7 @@ public class WidgetsConfigurationScreen extends Screen implements ScreenHandlerL currentLocation = targetLocation; widgetsLayer = widgetLayerToGoTo; } - ScreenMaster.getScreenBuilder(currentLocation).backupPositioning(); + WidgetManager.getScreenBuilder(currentLocation).backupPositioning(); } /** @@ -119,7 +119,7 @@ public class WidgetsConfigurationScreen extends Screen implements ScreenHandlerL * @param widgetLayerToGoTo go to this widget's layer */ public WidgetsConfigurationScreen(Location targetLocation, String widgetLayerToGoTo, Screen parent) { - this(null, "", targetLocation, ScreenMaster.getScreenBuilder(targetLocation).getPositionRuleOrDefault(widgetLayerToGoTo).screenLayer()); + this(null, "", targetLocation, WidgetManager.getScreenBuilder(targetLocation).getPositionRuleOrDefault(widgetLayerToGoTo).screenLayer()); this.parent = parent; } @@ -129,7 +129,7 @@ public class WidgetsConfigurationScreen extends Screen implements ScreenHandlerL * @param targetLocation open the preview to this location * @param layerToGo go to this layer */ - public WidgetsConfigurationScreen(Location targetLocation, ScreenMaster.ScreenLayer layerToGo, Screen parent) { + public WidgetsConfigurationScreen(Location targetLocation, WidgetManager.ScreenLayer layerToGo, Screen parent) { this(null, "", targetLocation, layerToGo); this.parent = parent; } @@ -177,7 +177,7 @@ public class WidgetsConfigurationScreen extends Screen implements ScreenHandlerL public void updateCustomWidgets() { List entries = new ArrayList<>(); - for (HudWidget value : ScreenMaster.widgetInstances.values()) { + for (HudWidget value : WidgetManager.widgetInstances.values()) { if (!value.availableLocations().contains(currentLocation)) continue; entries.add(new WidgetEntry(value, currentLocation)); } @@ -188,7 +188,7 @@ public class WidgetsConfigurationScreen extends Screen implements ScreenHandlerL Location old = this.currentLocation; currentLocation = location; if (old != currentLocation) { - ScreenMaster.getScreenBuilder(currentLocation).backupPositioning(); + WidgetManager.getScreenBuilder(currentLocation).backupPositioning(); updateCustomWidgets(); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java index 18d608ed..4b34230e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewTab.java @@ -5,7 +5,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.tabhud.config.DungeonsTabPlaceholder; import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen; import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder; -import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster; +import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.WidgetManager; import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.pipeline.PositionRule; import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.pipeline.WidgetPositioner; import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListManager; @@ -57,7 +57,7 @@ public class PreviewTab implements Tab { private final WidgetOptionsScrollable widgetOptions; private final Mode mode; private final ButtonWidget restorePositioning; - private ScreenMaster.ScreenLayer currentScreenLayer = ScreenMaster.ScreenLayer.MAIN_TAB; + private WidgetManager.ScreenLayer currentScreenLayer = WidgetManager.ScreenLayer.MAIN_TAB; private final ButtonWidget[] layerButtons; private final TextWidget textWidget; final ScoreboardObjective placeHolderObjective; @@ -76,10 +76,10 @@ public class PreviewTab implements Tab { widgetOptions = new WidgetOptionsScrollable(); widgetOptions.setWidth(RIGHT_SIDE_WIDTH - 10); - ScreenMaster.ScreenLayer[] values = ScreenMaster.ScreenLayer.values(); + WidgetManager.ScreenLayer[] values = WidgetManager.ScreenLayer.values(); layerButtons = new ButtonWidget[3]; for (int i = 0; i < 3; i++) { - ScreenMaster.ScreenLayer screenLayer = values[i]; + WidgetManager.ScreenLayer screenLayer = values[i]; layerButtons[i] = ButtonWidget.builder(Text.literal(screenLayer.toString()), button -> { this.currentScreenLayer = screenLayer; for (ButtonWidget layerButton : this.layerButtons) { @@ -92,7 +92,7 @@ public class PreviewTab implements Tab { } restorePositioning = ButtonWidget.builder(Text.literal("Restore Positioning"), button -> { - ScreenMaster.getScreenBuilder(getCurrentLocation()).restorePositioningFromBackup(); + WidgetManager.getScreenBuilder(getCurrentLocation()).restorePositioningFromBackup(); updateWidgets(); onHudWidgetSelected(previewWidget.selectedWidget); }) @@ -122,7 +122,7 @@ public class PreviewTab implements Tab { scoreboard.getOrCreateScore(createHolder(Text.literal("enough lines bye")), placeHolderObjective).setScore(-9); scoreboard.getOrCreateScore(createHolder(Text.literal("NEVER GONNA GIVE Y-")), placeHolderObjective).setScore(-10); - ScreenMaster.getScreenBuilder(getCurrentLocation()).positionWidgets(client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight(), true); + WidgetManager.getScreenBuilder(getCurrentLocation()).positionWidgets(client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight(), true); locationDropdown = parent.createLocationDropdown(location -> updateWidgets()); } @@ -141,8 +141,8 @@ public class PreviewTab implements Tab { }; } - public void goToLayer(ScreenMaster.ScreenLayer layer) { - if (layer == ScreenMaster.ScreenLayer.DEFAULT) layer = ScreenMaster.ScreenLayer.HUD; + public void goToLayer(WidgetManager.ScreenLayer layer) { + if (layer == WidgetManager.ScreenLayer.DEFAULT) layer = WidgetManager.ScreenLayer.HUD; layerButtons[layer.ordinal()].onPress(); } @@ -248,7 +248,7 @@ public class PreviewTab implements Tab { } void updateWidgets() { - ScreenBuilder screenBuilder = ScreenMaster.getScreenBuilder(getCurrentLocation()); + ScreenBuilder screenBuilder = WidgetManager.getScreenBuilder(getCurrentLocation()); updatePlayerListFromPreview(); float scale = SkyblockerConfigManager.get().uiAndVisuals.tabHud.tabHudScale / 100.f; screenBuilder.positionWidgets((int) (parent.width / scale), (int) (parent.height / scale), true); @@ -263,7 +263,7 @@ public class PreviewTab implements Tab { void onHudWidgetSelected(@Nullable HudWidget hudWidget) { widgetOptions.clearWidgets(); if (hudWidget == null) return; - ScreenBuilder screenBuilder = ScreenMaster.getScreenBuilder(getCurrentLocation()); + ScreenBuilder screenBuilder = WidgetManager.getScreenBuilder(getCurrentLocation()); PositionRule positionRule = screenBuilder.getPositionRule(hudWidget.getInternalID()); int width = widgetOptions.getWidth() - 6; @@ -284,7 +284,7 @@ public class PreviewTab implements Tab { PositionRule.Point.DEFAULT, hudWidget.getX() - 5, hudWidget.getY() - 5, - ScreenMaster.ScreenLayer.DEFAULT); + WidgetManager.ScreenLayer.DEFAULT); screenBuilder.setPositionRule(hudWidget.getInternalID(), rule); updateWidgets(); onHudWidgetSelected(hudWidget); @@ -306,9 +306,9 @@ public class PreviewTab implements Tab { String ye = "Layer: " + positionRule.screenLayer().toString(); widgetOptions.addWidget(ButtonWidget.builder(Text.literal(ye), button -> { - ScreenBuilder builder = ScreenMaster.getScreenBuilder(getCurrentLocation()); + ScreenBuilder builder = WidgetManager.getScreenBuilder(getCurrentLocation()); PositionRule rule = builder.getPositionRuleOrDefault(hudWidget.getInternalID()); - ScreenMaster.ScreenLayer newLayer = EnumUtils.cycle(rule.screenLayer()); + WidgetManager.ScreenLayer newLayer = EnumUtils.cycle(rule.screenLayer()); PositionRule newRule = new PositionRule( rule.parent(), @@ -321,7 +321,7 @@ public class PreviewTab implements Tab { builder.setPositionRule(hudWidget.getInternalID(), newRule); button.setMessage(Text.literal("Layer: " + newRule.screenLayer().toString())); updateWidgets(); - if (newLayer != ScreenMaster.ScreenLayer.DEFAULT) { + if (newLayer != WidgetManager.ScreenLayer.DEFAULT) { layerButtons[newLayer.ordinal()].onPress(); } @@ -331,7 +331,7 @@ public class PreviewTab implements Tab { HudWidget parent; if (positionRule.parent().equals("screen")) { parentName = Text.literal("Screen"); - } else if ((parent = ScreenMaster.widgetInstances.get(positionRule.parent())) == null) { + } else if ((parent = WidgetManager.widgetInstances.get(positionRule.parent())) == null) { parentName = Text.literal("Unloaded Widget"); } else { parentName = parent.getDisplayName(); @@ -361,11 +361,11 @@ public class PreviewTab implements Tab { widgetOptions.addWidget(ButtonWidget.builder(Text.literal("Apply Everywhere"), button -> { if (this.previewWidget.selectedWidget == null) return; - PositionRule toCopy = ScreenMaster.getScreenBuilder(getCurrentLocation()).getPositionRule(this.previewWidget.selectedWidget.getInternalID()); + PositionRule toCopy = WidgetManager.getScreenBuilder(getCurrentLocation()).getPositionRule(this.previewWidget.selectedWidget.getInternalID()); if (toCopy == null && !(this.previewWidget.selectedWidget instanceof TabHudWidget)) return; for (Location value : Location.values()) { if (value == getCurrentLocation() || value == Location.DUNGEON || value == Location.UNKNOWN) continue; - ScreenMaster.getScreenBuilder(value).setPositionRule( + WidgetManager.getScreenBuilder(value).setPositionRule( this.previewWidget.selectedWidget.getInternalID(), toCopy ); @@ -380,7 +380,7 @@ public class PreviewTab implements Tab { return mode == Mode.DUNGEON ? Location.DUNGEON : parent.getCurrentLocation(); } - public ScreenMaster.ScreenLayer getCurrentScreenLayer() { + public WidgetManager.ScreenLayer getCurrentScreenLayer() { return currentScreenLayer; } @@ -472,7 +472,7 @@ public class PreviewTab implements Tab { boolean selectedAnchor = false; if (previewWidget.selectedWidget != null) { String internalID = previewWidget.selectedWidget.getInternalID(); - PositionRule positionRule = ScreenMaster.getScreenBuilder(getCurrentLocation()).getPositionRule(internalID); + PositionRule positionRule = WidgetManager.getScreenBuilder(getCurrentLocation()).getPositionRule(internalID); if (positionRule != null) { PositionRule.Point point = other ? positionRule.parentPoint() : positionRule.thisPoint(); selectedAnchor = point.horizontalPoint().ordinal() == i && point.verticalPoint().ordinal() == j; @@ -500,7 +500,7 @@ public class PreviewTab implements Tab { public void onClick(double mouseX, double mouseY) { HudWidget affectedWidget = previewWidget.selectedWidget; if (hoveredPoint != null && affectedWidget != null) { - ScreenBuilder screenBuilder = ScreenMaster.getScreenBuilder(getCurrentLocation()); + ScreenBuilder screenBuilder = WidgetManager.getScreenBuilder(getCurrentLocation()); String internalID = affectedWidget.getInternalID(); PositionRule oldRule = screenBuilder.getPositionRuleOrDefault(internalID); // Get the x, y of the parent's point diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewWidget.java index be217958..0fdab758 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/config/preview/PreviewWidget.java @@ -3,7 +3,7 @@ package de.hysky.skyblocker.skyblock.tabhud.config.preview; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.mixins.accessors.InGameHudInvoker; import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder; -import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster; +import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.WidgetManager; import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.pipeline.PositionRule; import de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget; import net.minecraft.client.MinecraftClient; @@ -61,7 +61,7 @@ public class PreviewWidget extends ClickableWidget { scaledScreenWidth = tab.parent.width / scale; scaledScreenHeight = tab.parent.height / scale; - ScreenBuilder screenBuilder = ScreenMaster.getScreenBuilder(tab.getCurrentLocation()); + ScreenBuilder screenBuilder = WidgetManager.getScreenBuilder(tab.getCurrentLocation()); context.drawBorder(getX() - 1, getY() - 1, getWidth() + 2, getHeight() + 2, -1); context.enableScissor(getX(), getY(), getRight(), getBottom()); MatrixStack matrices = context.getMatrices(); @@ -199,7 +199,7 @@ public class PreviewWidget extends ClickableWidget { // TODO releasing a widget outside of the area causes weird behavior, might wanna look into that // Update positioning real if (selectedWidget != null && selectedOriginalPos != null) { - ScreenBuilder screenBuilder = ScreenMaster.getScreenBuilder(tab.getCurrentLocation()); + ScreenBuilder screenBuilder = WidgetManager.getScreenBuilder(tab.getCurrentLocation()); PositionRule oldRule = screenBuilder.getPositionRule(selectedWidget.getInternalID()); if (oldRule == null) oldRule = PositionRule.DEFAULT; int relativeX = selectedWidget.getX() - selectedOriginalPos.x(); @@ -226,7 +226,7 @@ public class PreviewWidget extends ClickableWidget { double localMouseY = (mouseY - getY()) / scaledRatio; if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { List hoveredThingies = new ArrayList<>(); - for (HudWidget hudWidget : ScreenMaster.getScreenBuilder(tab.getCurrentLocation()).getHudWidgets(tab.getCurrentScreenLayer())) { + for (HudWidget hudWidget : WidgetManager.getScreenBuilder(tab.getCurrentLocation()).getHudWidgets(tab.getCurrentScreenLayer())) { if (hudWidget.isMouseOver(localMouseX, localMouseY)) hoveredThingies.add(hudWidget); } if (hoveredThingies.size() == 1) selectedWidget = hoveredThingies.getFirst(); @@ -239,7 +239,7 @@ public class PreviewWidget extends ClickableWidget { } return true; } - ScreenBuilder screenBuilder = ScreenMaster.getScreenBuilder(tab.getCurrentLocation()); + ScreenBuilder screenBuilder = WidgetManager.getScreenBuilder(tab.getCurrentLocation()); if (pickParent && selectedWidget != null && !selectedWidget.equals(hoveredWidget)) { PositionRule oldRule = screenBuilder.getPositionRule(selectedWidget.getInternalID()); if (oldRule == null) oldRule = PositionRule.DEFAULT; @@ -283,7 +283,7 @@ public class PreviewWidget extends ClickableWidget { case GLFW.GLFW_KEY_LEFT -> x = -multiplier; case GLFW.GLFW_KEY_RIGHT -> x = multiplier; } - ScreenBuilder screenBuilder = ScreenMaster.getScreenBuilder(tab.getCurrentLocation()); + ScreenBuilder screenBuilder = WidgetManager.getScreenBuilder(tab.getCurrentLocation()); PositionRule oldRule = screenBuilder.getPositionRuleOrDefault(selectedWidget.getInternalID()); screenBuilder.setPositionRule(selectedWidget.getInternalID(), new PositionRule( diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenBuilder.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenBuilder.java index 24c42d7a..78b765ed 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenBuilder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenBuilder.java @@ -74,7 +74,7 @@ public class ScreenBuilder { WidgetPositioner newPositioner = SkyblockerConfigManager.get().uiAndVisuals.tabHud.defaultPositioning.getNewPositioner(screenW, screenH); - for (HudWidget widget : ScreenMaster.widgetInstances.values()) { + for (HudWidget widget : WidgetManager.widgetInstances.values()) { widget.setVisible(false); if (config ? widget.isEnabledIn(location) : widget.shouldRender(location)) { // TabHudWidget has this at false // TODO maybe behavior to change? (having no position rule on a normal hud widget shouldn't quite be possible) @@ -142,7 +142,7 @@ public class ScreenBuilder { /** * Renders the widgets present on the specified layer. Doesn't scale with the config option. */ - public void renderWidgets(DrawContext context, ScreenMaster.ScreenLayer screenLayer) { + public void renderWidgets(DrawContext context, WidgetManager.ScreenLayer screenLayer) { List widgetsToRender = getHudWidgets(screenLayer); for (HudWidget widget : widgetsToRender) { @@ -150,7 +150,7 @@ public class ScreenBuilder { } } - public List getHudWidgets(ScreenMaster.ScreenLayer screenLayer) { + public List getHudWidgets(WidgetManager.ScreenLayer screenLayer) { return switch (screenLayer) { case MAIN_TAB -> mainTabScreen; case SECONDARY_TAB -> secondaryTabScreen; @@ -162,7 +162,7 @@ public class ScreenBuilder { /** * Run the pipeline to build a Screen */ - public void run(DrawContext context, int screenW, int screenH, ScreenMaster.ScreenLayer screenLayer) { + public void run(DrawContext context, int screenW, int screenH, WidgetManager.ScreenLayer screenLayer) { /*int i = 0; for (TabHudWidget value : PlayerListMgr.tabWidgetInstances.values()) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenMaster.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenMaster.java deleted file mode 100644 index 2517b2e2..00000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenMaster.java +++ /dev/null @@ -1,218 +0,0 @@ -package de.hysky.skyblocker.skyblock.tabhud.screenbuilder; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.logging.LogUtils; -import com.mojang.serialization.Codec; -import com.mojang.serialization.JsonOps; -import de.hysky.skyblocker.SkyblockerMod; -import de.hysky.skyblocker.annotations.Init; -import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.events.SkyblockEvents; -import de.hysky.skyblocker.skyblock.tabhud.TabHud; -import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.pipeline.PositionRule; -import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListManager; -import de.hysky.skyblocker.skyblock.tabhud.widget.CommsWidget; -import de.hysky.skyblocker.skyblock.tabhud.widget.DungeonPlayerWidget; -import de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget; -import de.hysky.skyblocker.skyblock.tabhud.widget.TabHudWidget; -import de.hysky.skyblocker.utils.Location; -import de.hysky.skyblocker.utils.Utils; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.util.StringIdentifiable; -import org.slf4j.Logger; - -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.Arrays; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class ScreenMaster { - private static final Logger LOGGER = LogUtils.getLogger(); - - private static final int VERSION = 2; - private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("hud_widgets.json"); - - private static final Map BUILDER_MAP = new EnumMap<>(Arrays.stream(Location.values()).collect(Collectors.toMap(Function.identity(), ScreenBuilder::new))); - - public static final Map widgetInstances = new HashMap<>(); - - public static ScreenBuilder getScreenBuilder(Location location) { - return BUILDER_MAP.get(location); - } - - /** - * Top level render method. - * Calls the appropriate ScreenBuilder with the screen's dimensions - * Called in PlayerListHudMixin - * - * @param hud true to only render the hud (always on screen) widgets, false to only render the tab widgets. - */ - public static void render(DrawContext context, int w, int h, boolean hud) { - MinecraftClient client = MinecraftClient.getInstance(); - ScreenBuilder screenBuilder = getScreenBuilder(Utils.getLocation()); - if (client.options.playerListKey.isPressed()) { - if (hud || TabHud.shouldRenderVanilla()) return; - if (TabHud.toggleSecondary.isPressed()) { - screenBuilder.run(context, w, h, ScreenLayer.SECONDARY_TAB); - } else { - screenBuilder.run(context, w, h, ScreenLayer.MAIN_TAB); - } - } else if (hud) { - screenBuilder.run(context, w, h, ScreenLayer.HUD); - } - } - - public static void loadConfig() { - try (BufferedReader reader = Files.newBufferedReader(FILE)) { - JsonObject object = SkyblockerMod.GSON.fromJson(reader, JsonObject.class); - JsonObject positions = object.getAsJsonObject("positions"); - for (Map.Entry builderEntry : BUILDER_MAP.entrySet()) { - Location location = builderEntry.getKey(); - ScreenBuilder screenBuilder = builderEntry.getValue(); - if (positions.has(location.id())) { - JsonObject locationObject = positions.getAsJsonObject(location.id()); - for (Map.Entry entry : locationObject.entrySet()) { - PositionRule.CODEC.decode(JsonOps.INSTANCE, entry.getValue()) - .ifSuccess(pair -> screenBuilder.setPositionRule(entry.getKey(), pair.getFirst())) - .ifError(pairError -> LOGGER.error("[Skyblocker] Failed to parse position rule: {}", pairError.messageSupplier().get())); - } - } - } - } catch (NoSuchFileException e) { - LOGGER.warn("[Skyblocker] No hud widget config file found, using defaults"); - } catch (Exception e) { - LOGGER.error("[Skyblocker] Failed to load hud widgets config", e); - } - } - - public static void saveConfig() { - JsonObject output = new JsonObject(); - JsonObject positions = new JsonObject(); - for (Map.Entry builderEntry : BUILDER_MAP.entrySet()) { - Location location = builderEntry.getKey(); - ScreenBuilder screenBuilder = builderEntry.getValue(); - JsonObject locationObject = new JsonObject(); - screenBuilder.forEachPositionRuleEntry((s, positionRule) -> locationObject.add(s, PositionRule.CODEC.encodeStart(JsonOps.INSTANCE, positionRule).getOrThrow())); - if (locationObject.isEmpty()) continue; - positions.add(location.id(), locationObject); - } - output.add("positions", positions); - try (BufferedWriter writer = Files.newBufferedWriter(FILE)) { - SkyblockerMod.GSON.toJson(output, writer); - LOGGER.info("[Skyblocker] Saved hud widget config"); - } catch (IOException e) { - LOGGER.error("[Skyblocker] Failed to save hud widget config", e); - } - } - - // All non-tab HUDs should have a position rule initialised here, because they don't have an auto positioning - private static void fillDefaultConfig() { - ScreenBuilder screenBuilder = getScreenBuilder(Location.THE_END); - screenBuilder.setPositionRule( - "hud_end", - new PositionRule("screen", PositionRule.Point.DEFAULT, PositionRule.Point.DEFAULT, SkyblockerConfigManager.get().otherLocations.end.x, SkyblockerConfigManager.get().otherLocations.end.y, ScreenMaster.ScreenLayer.HUD) - ); - - screenBuilder = getScreenBuilder(Location.GARDEN); - screenBuilder.setPositionRule( - "hud_farming", - new PositionRule("screen", PositionRule.Point.DEFAULT, PositionRule.Point.DEFAULT, SkyblockerConfigManager.get().farming.garden.farmingHud.x, SkyblockerConfigManager.get().farming.garden.farmingHud.y, ScreenMaster.ScreenLayer.HUD) - ); - - for (Location loc : new Location[]{Location.CRYSTAL_HOLLOWS, Location.DWARVEN_MINES}) { - screenBuilder = getScreenBuilder(loc); - screenBuilder.setPositionRule( - CommsWidget.ID, - new PositionRule("screen", PositionRule.Point.DEFAULT, PositionRule.Point.DEFAULT, 5, 5, ScreenMaster.ScreenLayer.HUD) - ); - screenBuilder.setPositionRule( - "powders", - new PositionRule(CommsWidget.ID, new PositionRule.Point(PositionRule.VerticalPoint.BOTTOM, PositionRule.HorizontalPoint.LEFT), PositionRule.Point.DEFAULT, 0, 2, ScreenMaster.ScreenLayer.HUD) - ); - - } - - } - - // we probably want this to run pretty early? - @Init(priority = -1) - public static void init() { - SkyblockEvents.LOCATION_CHANGE.register(location -> ScreenBuilder.positionsNeedsUpdating = true); - - ClientLifecycleEvents.CLIENT_STARTED.register(client -> { - - instantiateWidgets(); - for (int i = 1; i < 6; i++) { - DungeonPlayerWidget widget = new DungeonPlayerWidget(i); - addWidgetInstance(widget); - } - - fillDefaultConfig(); - loadConfig(); - - }); - - ClientLifecycleEvents.CLIENT_STOPPING.register(client -> saveConfig()); - } - - - /** - * Filled at compile item with ASM. - * Do not fill this method or change the signature unless you know what you're doing - */ - private static void instantiateWidgets() {} - - /** - * Called by the ASM generated code to add a widget instance to the map. - * Do not change the signature unless you know what you're doing. - */ - public static void addWidgetInstance(HudWidget widget) { - HudWidget put = widgetInstances.put(widget.getInternalID(), widget); - if (widget instanceof TabHudWidget tabHudWidget) { - PlayerListManager.tabWidgetInstances.put(tabHudWidget.getHypixelWidgetName(), tabHudWidget); - } - if (put != null) LOGGER.warn("[Skyblocker] Duplicate hud widget found: {}", widget); - } - - /** - * @implNote !! The 3 first ones shouldn't be moved, ordinal is used in some places - */ - public enum ScreenLayer implements StringIdentifiable { - MAIN_TAB, - SECONDARY_TAB, - HUD, - /** - * Default is only present for config and isn't used anywhere else - */ - DEFAULT; - - public static final Codec CODEC = StringIdentifiable.createCodec(ScreenLayer::values); - - @Override - public String toString() { - return switch (this) { - case MAIN_TAB -> "Main Tab"; - case SECONDARY_TAB -> "Secondary Tab"; - case HUD -> "HUD"; - case DEFAULT -> "Default"; - }; - } - - @Override - public String asString() { - return name(); - } - } - -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/WidgetManager.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/WidgetManager.java new file mode 100644 index 00000000..f2040975 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/WidgetManager.java @@ -0,0 +1,244 @@ +package de.hysky.skyblocker.skyblock.tabhud.screenbuilder; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.logging.LogUtils; +import com.mojang.serialization.Codec; +import com.mojang.serialization.JsonOps; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.annotations.Init; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.events.SkyblockEvents; +import de.hysky.skyblocker.skyblock.tabhud.TabHud; +import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen; +import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.pipeline.PositionRule; +import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListManager; +import de.hysky.skyblocker.skyblock.tabhud.widget.CommsWidget; +import de.hysky.skyblocker.skyblock.tabhud.widget.DungeonPlayerWidget; +import de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget; +import de.hysky.skyblocker.skyblock.tabhud.widget.TabHudWidget; +import de.hysky.skyblocker.utils.Location; +import de.hysky.skyblocker.utils.Utils; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.Window; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.StringIdentifiable; +import org.slf4j.Logger; + +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.Arrays; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class WidgetManager { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final Identifier FANCY_TAB_HUD = Identifier.of(SkyblockerMod.NAMESPACE, "fancy_tab_hud"); + private static final Identifier FANCY_TAB = Identifier.of(SkyblockerMod.NAMESPACE, "fancy_tab"); + + private static final int VERSION = 2; + private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("hud_widgets.json"); + + private static final Map BUILDER_MAP = new EnumMap<>(Arrays.stream(Location.values()).collect(Collectors.toMap(Function.identity(), ScreenBuilder::new))); + + public static final Map widgetInstances = new HashMap<>(); + + public static ScreenBuilder getScreenBuilder(Location location) { + return BUILDER_MAP.get(location); + } + + // we probably want this to run pretty early? + @Init(priority = -1) + public static void init() { + SkyblockEvents.LOCATION_CHANGE.register(location -> ScreenBuilder.positionsNeedsUpdating = true); + + ClientLifecycleEvents.CLIENT_STARTED.register(client -> { + + instantiateWidgets(); + for (int i = 1; i < 6; i++) { + DungeonPlayerWidget widget = new DungeonPlayerWidget(i); + addWidgetInstance(widget); + } + + fillDefaultConfig(); + loadConfig(); + + }); + + ClientLifecycleEvents.CLIENT_STOPPING.register(client -> saveConfig()); + + HudLayerRegistrationCallback.EVENT.register(layeredDrawer -> layeredDrawer + // Renders the hud (always on screen) widgets. + // Since each layer has a z offset of 200 automatically added, attaching fancy tab hud before the demo timer is just enough for items to render below the debug hud + .attachLayerBefore(IdentifiedLayer.DEMO_TIMER, FANCY_TAB_HUD, (context, tickCounter) -> render(context, true)) + // Renders the tab widgets + .attachLayerBefore(IdentifiedLayer.PLAYER_LIST, FANCY_TAB, (context, tickCounter) -> render(context, false)) + ); + } + + private static void render(DrawContext context, boolean hud) { + if (!Utils.isOnSkyblock()) return; + MinecraftClient client = MinecraftClient.getInstance(); + + if (client.currentScreen instanceof WidgetsConfigurationScreen) return; + Window window = client.getWindow(); + float scale = SkyblockerConfigManager.get().uiAndVisuals.tabHud.tabHudScale / 100f; + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.scale(scale, scale, 1.F); + WidgetManager.render(context, (int) (window.getScaledWidth() / scale), (int) (window.getScaledHeight() / scale), hud); + matrices.pop(); + } + + /** + * Top level render method. + * Calls the appropriate ScreenBuilder with the screen's dimensions + * + * @param hud true to only render the hud (always on screen) widgets, false to only render the tab widgets. + */ + private static void render(DrawContext context, int w, int h, boolean hud) { + MinecraftClient client = MinecraftClient.getInstance(); + ScreenBuilder screenBuilder = getScreenBuilder(Utils.getLocation()); + if (client.options.playerListKey.isPressed()) { + if (hud || TabHud.shouldRenderVanilla()) return; + if (TabHud.toggleSecondary.isPressed()) { + screenBuilder.run(context, w, h, ScreenLayer.SECONDARY_TAB); + } else { + screenBuilder.run(context, w, h, ScreenLayer.MAIN_TAB); + } + } else if (hud) { + screenBuilder.run(context, w, h, ScreenLayer.HUD); + } + } + + public static void loadConfig() { + try (BufferedReader reader = Files.newBufferedReader(FILE)) { + JsonObject object = SkyblockerMod.GSON.fromJson(reader, JsonObject.class); + JsonObject positions = object.getAsJsonObject("positions"); + for (Map.Entry builderEntry : BUILDER_MAP.entrySet()) { + Location location = builderEntry.getKey(); + ScreenBuilder screenBuilder = builderEntry.getValue(); + if (positions.has(location.id())) { + JsonObject locationObject = positions.getAsJsonObject(location.id()); + for (Map.Entry