diff options
author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2023-07-22 15:17:11 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-22 15:17:11 -0400 |
commit | 1aa006198fe987dae999486c6668f4f6e071ddf4 (patch) | |
tree | c850f150efdda3b940d74f60695cbcc880b143ce | |
parent | bac0f8f4aff96c5c6707bbb750f37de92e000da4 (diff) | |
parent | 14ec65e7639758972f44a9097c44b8eb53c45c15 (diff) | |
download | Skyblocker-1aa006198fe987dae999486c6668f4f6e071ddf4.tar.gz Skyblocker-1aa006198fe987dae999486c6668f4f6e071ddf4.tar.bz2 Skyblocker-1aa006198fe987dae999486c6668f4f6e071ddf4.zip |
Merge branch 'SkyblockerMod:master' into dark-auction-tabhud
20 files changed, 694 insertions, 123 deletions
diff --git a/build.gradle b/build.gradle index b5eaa09f..44d47adc 100644 --- a/build.gradle +++ b/build.gradle @@ -41,11 +41,10 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" // Cloth config - modImplementation("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") { + include modImplementation("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") { exclude group: "net.fabricmc.fabric-api" exclude module: "modmenu" } - include "me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}" // Mod Menu modImplementation "com.terraformersmc:modmenu:${project.mod_menu_version}" @@ -58,13 +57,15 @@ dependencies { modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" // https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit used pull data from the NEU item repo - include(implementation("org.eclipse.jgit:org.eclipse.jgit:6.4.0.202211300538-r")) + include implementation("org.eclipse.jgit:org.eclipse.jgit:6.4.0.202211300538-r") // Renderer (https://github.com/0x3C50/Renderer) - include modImplementation("com.github.0x3C50:Renderer:${project.renderer_version}") + include modImplementation("com.github.0x3C50:Renderer:${project.renderer_version}"){ + exclude group: "io.github.ladysnake" exclude module: "satin" + } + + include modImplementation("meteordevelopment:discord-ipc:1.1") - include(modImplementation ("meteordevelopment:discord-ipc:1.1")) - // Occlusion Culling (https://github.com/LogisticsCraft/OcclusionCulling) include implementation("com.logisticscraft:occlusionculling:${project.occlusionculling_version}") } diff --git a/gradle.properties b/gradle.properties index ce4f22c0..a97ef816 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ loader_version=0.14.21 #Fabric api ## 1.20 -fabric_api_version=0.83.0+1.20 +fabric_api_version=0.86.0+1.20.1 # Dependencies ## Cloth Api (https://www.curseforge.com/minecraft/mc-mods/cloth-config/files) @@ -18,7 +18,7 @@ mod_menu_version=7.0.1 ## REI (https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items/files) rei_version=12.0.625 ## Renderer (https://github.com/0x3C50/Renderer) -renderer_version = d687aced4c +renderer_version = master-SNAPSHOT ## Occlusion Culling (https://github.com/LogisticsCraft/OcclusionCulling) occlusionculling_version = 0.0.7-SNAPSHOT diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java index 3692db1b..0263f20c 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java @@ -16,6 +16,7 @@ import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup; import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; import me.xmrvizzy.skyblocker.skyblock.quicknav.QuickNav; import me.xmrvizzy.skyblocker.skyblock.rift.TheRift; +import me.xmrvizzy.skyblocker.skyblock.shortcut.Shortcuts; import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud; import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; import me.xmrvizzy.skyblocker.utils.*; @@ -76,6 +77,7 @@ public class SkyblockerMod implements ClientModInitializer { QuickNav.init(); DwarvenHud.init(); ChatMessageListener.init(); + Shortcuts.init(); DiscordRPCManager.init(); LividColor.init(); FishingHelper.init(); diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java index 04cfaea3..c4eeb090 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java @@ -1,6 +1,5 @@ package me.xmrvizzy.skyblocker.config; -import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.shedaniel.autoconfig.AutoConfig; import me.shedaniel.autoconfig.ConfigData; @@ -161,6 +160,10 @@ public class SkyblockerConfig implements ConfigData { @ConfigEntry.Gui.CollapsibleObject() public FairySouls fairySouls = new FairySouls(); + @ConfigEntry.Category("shortcuts") + @ConfigEntry.Gui.CollapsibleObject() + public Shortcuts shortcuts = new Shortcuts(); + @ConfigEntry.Category("itemList") @ConfigEntry.Gui.CollapsibleObject() public ItemList itemList = new ItemList(); @@ -264,6 +267,15 @@ public class SkyblockerConfig implements ConfigData { public boolean enableFairySoulsHelper = false; } + public static class Shortcuts { + @ConfigEntry.Gui.Tooltip() + public boolean enableShortcuts = true; + @ConfigEntry.Gui.Tooltip() + public boolean enableCommandShortcuts = true; + @ConfigEntry.Gui.Tooltip() + public boolean enableCommandArgShortcuts = true; + } + public static class Hitbox { public boolean oldFarmlandHitbox = true; public boolean oldLeverHitbox = false; @@ -505,7 +517,7 @@ public class SkyblockerConfig implements ConfigData { */ public static void init() { AutoConfig.register(SkyblockerConfig.class, GsonConfigSerializer::new); - ClientCommandRegistrationCallback.EVENT.register(((dispatcher, registryAccess) -> dispatcher.register(literal("skyblocker").then(optionsLiteral("config")).then(optionsLiteral("options"))))); + ClientCommandRegistrationCallback.EVENT.register(((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(optionsLiteral("config")).then(optionsLiteral("options"))))); } /** @@ -515,11 +527,8 @@ public class SkyblockerConfig implements ConfigData { * @return the command builder */ private static LiteralArgumentBuilder<FabricClientCommandSource> optionsLiteral(String name) { - return literal(name).executes(context -> { - // Don't immediately open the next screen as it will be closed by ChatScreen right after this command is executed - SkyblockerMod.getInstance().scheduler.queueOpenScreen(AutoConfig.getConfigScreen(SkyblockerConfig.class, null)); - return Command.SINGLE_SUCCESS; - }); + // Don't immediately open the next screen as it will be closed by ChatScreen right after this command is executed + return literal(name).executes(context -> SkyblockerMod.getInstance().scheduler.queueOpenScreen(AutoConfig.getConfigScreen(SkyblockerConfig.class, null))); } public static SkyblockerConfig get() { diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index 903d3992..13272323 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -30,6 +30,8 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Map; + @Mixin(HandledScreen.class) public abstract class HandledScreenMixin extends Screen { protected HandledScreenMixin(Text title) { @@ -96,7 +98,7 @@ public abstract class HandledScreenMixin extends Screen { superpairsSolver.setSuperpairsCurrentSlot(ItemStack.EMPTY); } else if (experimentSolver instanceof UltrasequencerSolver ultrasequencerSolver && slot.getIndex() == ultrasequencerSolver.getUltrasequencerNextSlot()) { int count = ultrasequencerSolver.getSlots().get(ultrasequencerSolver.getUltrasequencerNextSlot()).getCount() + 1; - ultrasequencerSolver.getSlots().entrySet().stream().filter(entry -> entry.getValue().getCount() == count).findAny().ifPresentOrElse((entry) -> ultrasequencerSolver.setUltrasequencerNextSlot(entry.getKey()), () -> ultrasequencerSolver.setState(ExperimentSolver.State.END)); + ultrasequencerSolver.getSlots().entrySet().stream().filter(entry -> entry.getValue().getCount() == count).findAny().map(Map.Entry::getKey).ifPresentOrElse(ultrasequencerSolver::setUltrasequencerNextSlot, () -> ultrasequencerSolver.setState(ExperimentSolver.State.END)); } } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java index 108a7344..3cde115e 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java @@ -1,15 +1,14 @@ package me.xmrvizzy.skyblocker.mixin.accessor; -import me.xmrvizzy.skyblocker.utils.FrustumUtils; import net.minecraft.client.render.Frustum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; /** - * Use {@link FrustumUtils#isVisible(double, double, double, double, double, double) FrustumUtils#isVisible} which is shorter. For the purpose of avoiding object allocations! + * Use {@link me.xmrvizzy.skyblocker.utils.FrustumUtils#isVisible(double, double, double, double, double, double) FrustumUtils#isVisible} which is shorter. For the purpose of avoiding object allocations! */ @Mixin(Frustum.class) public interface FrustumInvoker { - @Invoker("isVisible") - boolean isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ); + @Invoker + boolean invokeIsVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ); } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMap.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMap.java index 2a97d0ee..29a6e687 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMap.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMap.java @@ -1,9 +1,6 @@ package me.xmrvizzy.skyblocker.skyblock.dungeon; -import org.apache.commons.lang3.StringUtils; - -import com.mojang.brigadier.Command; - +import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; @@ -16,11 +13,11 @@ import net.minecraft.item.FilledMapItem; import net.minecraft.item.ItemStack; import net.minecraft.item.map.MapState; import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.apache.commons.lang3.StringUtils; public class DungeonMap { - private static final Identifier MAP_BACKGROUND = new Identifier("textures/map/map_background.png"); + private static final Identifier MAP_BACKGROUND = new Identifier("textures/map/map_background.png"); public static void render(MatrixStack matrices) { MinecraftClient client = MinecraftClient.getInstance(); @@ -36,36 +33,29 @@ public class DungeonMap { MapRenderer map = client.gameRenderer.getMapRenderer(); MapState state = FilledMapItem.getMapState(mapid, client.world); float scaling = SkyblockerConfig.get().locations.dungeons.mapScaling; - int x = SkyblockerConfig.get().locations.dungeons.mapX; - int y = SkyblockerConfig.get().locations.dungeons.mapY; + int x = SkyblockerConfig.get().locations.dungeons.mapX; + int y = SkyblockerConfig.get().locations.dungeons.mapY; if (state == null) return; matrices.push(); matrices.translate(x, y, 0); matrices.scale(scaling, scaling, 0f); - map.draw( matrices, vertices, mapid, state, false, 15728880); + map.draw(matrices, vertices, mapid, state, false, 15728880); vertices.draw(); matrices.pop(); } } - + public static void renderHUDMap(DrawContext context, int x, int y) { - float scaling = SkyblockerConfig.get().locations.dungeons.mapScaling; - int size = (int) (128 * scaling); - context.drawTexture(MAP_BACKGROUND, x, y, 0, 0, size, size, size, size); + float scaling = SkyblockerConfig.get().locations.dungeons.mapScaling; + int size = (int) (128 * scaling); + context.drawTexture(MAP_BACKGROUND, x, y, 0, 0, size, size, size, size); } - + public static void init() { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { - dispatcher.register(ClientCommandManager.literal("skyblocker") - .then(ClientCommandManager.literal("hud") - .then(ClientCommandManager.literal("dungeonmap") - .executes(context -> { - MinecraftClient client = context.getSource().getClient(); - client.send(() -> client.setScreen(new DungeonMapConfigScreen(Text.literal("Dungeon Map Config")))); - - return Command.SINGLE_SUCCESS; - })))); - }); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") + .then(ClientCommandManager.literal("hud") + .then(ClientCommandManager.literal("dungeonmap") + .executes(context -> SkyblockerMod.getInstance().scheduler.queueOpenScreen(DungeonMapConfigScreen::new)))))); } }
\ No newline at end of file diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java index ffd7a8b6..ef782c3b 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java @@ -10,43 +10,43 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; public class DungeonMapConfigScreen extends Screen { - + private int hudX = SkyblockerConfig.get().locations.dungeons.mapX; private int hudY = SkyblockerConfig.get().locations.dungeons.mapY; - - protected DungeonMapConfigScreen(Text title) { - super(title); + + protected DungeonMapConfigScreen() { + super(Text.literal("Dungeon Map Config")); } - + @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); renderBackground(context); DungeonMap.renderHUDMap(context, hudX, hudY); - context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); + context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width >> 1, height >> 1, Color.GRAY.getRGB()); } - + @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { float scaling = SkyblockerConfig.get().locations.dungeons.mapScaling; int size = (int) (128 * scaling); - if(RenderUtils.pointExistsInArea((int) mouseX, (int) mouseY, hudX, hudY, hudX + size, hudY + size) && button == 0) { - hudX = (int) Math.max(Math.min(mouseX - (size / 2), this.width - size), 0); - hudY = (int) Math.max(Math.min(mouseY - (size / 2), this.height - size), 0); + if (RenderUtils.pointExistsInArea((int) mouseX, (int) mouseY, hudX, hudY, hudX + size, hudY + size) && button == 0) { + hudX = (int) Math.max(Math.min(mouseX - (size >> 1), this.width - size), 0); + hudY = (int) Math.max(Math.min(mouseY - (size >> 1), this.height - size), 0); } return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } - + @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if(button == 1) { + if (button == 1) { hudX = 2; hudY = 2; } - + return super.mouseClicked(mouseX, mouseY, button); } - + @Override public void close() { SkyblockerConfig.get().locations.dungeons.mapX = hudX; diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java index 122f6c6c..7316577e 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java @@ -1,5 +1,6 @@ package me.xmrvizzy.skyblocker.skyblock.dwarven; +import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.CommsWidget; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; @@ -7,7 +8,6 @@ import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallba import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; 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; @@ -26,34 +26,32 @@ public class DwarvenHud { public static final List<Pattern> COMMISSIONS = Stream.of( - "(?:Titanium|Mithril|Hard Stone) Miner", - "(?:Ice Walker|Goblin|Goblin Raid|Automaton|Sludge|Team Treasurite Member|Yog|Boss Corleone|Thyst) Slayer", - "(?:Lava Springs|Cliffside Veins|Rampart's Quarry|Upper Mines|Royal Mines) Mithril", - "(?:Lava Springs|Cliffside Veins|Rampart's Quarry|Upper Mines|Royal Mines) Titanium", - "Goblin Raid", - "(?:Powder Ghast|Star Sentry) Puncher", - "(?<!Lucky )Raffle", - "Lucky Raffle", - "2x Mithril Powder Collector", - "(?:Ruby|Amber|Sapphire|Jade|Amethyst|Topaz) Gemstone Collector", - "(?:Amber|Sapphire|Jade|Amethyst|Topaz) Crystal Hunter", - "Chest Looter" + "(?:Titanium|Mithril|Hard Stone) Miner", + "(?:Ice Walker|Goblin|Goblin Raid|Automaton|Sludge|Team Treasurite Member|Yog|Boss Corleone|Thyst) Slayer", + "(?:Lava Springs|Cliffside Veins|Rampart's Quarry|Upper Mines|Royal Mines) Mithril", + "(?:Lava Springs|Cliffside Veins|Rampart's Quarry|Upper Mines|Royal Mines) Titanium", + "Goblin Raid", + "(?:Powder Ghast|Star Sentry) Puncher", + "(?<!Lucky )Raffle", + "Lucky Raffle", + "2x Mithril Powder Collector", + "(?:Ruby|Amber|Sapphire|Jade|Amethyst|Topaz) Gemstone Collector", + "(?:Amber|Sapphire|Jade|Amethyst|Topaz) Crystal Hunter", + "Chest Looter" ).map(s -> Pattern.compile("^.*(" + s + "): (\\d+\\.?\\d*%|DONE)")) .collect(Collectors.toList()); + public static void init() { ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") .then(ClientCommandManager.literal("hud") .then(ClientCommandManager.literal("dwarven") - .executes(context -> { - client.send(() -> client.setScreen(new DwarvenHudConfigScreen(Text.of("Dwarven HUD Config")))); - return 1; - }))))); + .executes(context -> SkyblockerMod.getInstance().scheduler.queueOpenScreen(DwarvenHudConfigScreen::new)))))); HudRenderCallback.EVENT.register((context, tickDelta) -> { if (!SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enabled - || client.options.playerListKey.isPressed() - || client.player == null - || commissionList.isEmpty()) { + || client.options.playerListKey.isPressed() + || client.player == null + || commissionList.isEmpty()) { return; } render(context, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.x, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.y, commissionList); @@ -62,7 +60,7 @@ public class DwarvenHud { public static void render(DrawContext context, int hudX, int hudY, List<Commission> commissions) { - switch(SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.style) { + switch (SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.style) { case SIMPLE -> renderSimple(context, hudX, hudY, commissions); case FANCY -> renderFancy(context, hudX, hudY, commissions); case CLASSIC -> renderClassic(context, hudX, hudY, commissions); @@ -77,12 +75,12 @@ public class DwarvenHud { int y = 0; for (Commission commission : commissions) { context - .drawTextWithShadow(client.textRenderer, - Text.literal(commission.commission + ": ") - .styled(style -> style.withColor(Formatting.AQUA)) - .append(Text.literal(commission.progression) - .styled(style -> style.withColor(Formatting.GREEN))), - hudX + 5, hudY + y + 5, 0xFFFFFFFF); + .drawTextWithShadow(client.textRenderer, + Text.literal(commission.commission + ": ") + .styled(style -> style.withColor(Formatting.AQUA)) + .append(Text.literal(commission.progression) + .styled(style -> style.withColor(Formatting.GREEN))), + hudX + 5, hudY + y + 5, 0xFFFFFFFF); y += 20; } } @@ -119,6 +117,6 @@ public class DwarvenHud { } // steamroller tactics to get visibility from outside classes (CommsWidget) - public static record Commission(String commission, String progression){} - + public record Commission(String commission, String progression) { + } }
\ No newline at end of file diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java index f91ed921..10e62d88 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java @@ -5,7 +5,6 @@ import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.utils.RenderUtils; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import java.awt.*; @@ -15,8 +14,9 @@ public class DwarvenHudConfigScreen extends Screen { private int hudX = SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.x; private int hudY = SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.y; - protected DwarvenHudConfigScreen(Text title) { - super(title); + + protected DwarvenHudConfigScreen() { + super(Text.of("Dwarven HUD Config")); } @Override diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java new file mode 100644 index 00000000..44077b3e --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java @@ -0,0 +1,206 @@ +package me.xmrvizzy.skyblocker.skyblock.shortcut; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import me.xmrvizzy.skyblocker.SkyblockerMod; +import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; + +public class Shortcuts { + private static final Logger LOGGER = LoggerFactory.getLogger(Shortcuts.class); + private static final File SHORTCUTS_FILE = SkyblockerMod.CONFIG_DIR.resolve("shortcuts.json").toFile(); + @Nullable + private static CompletableFuture<Void> shortcutsLoaded; + public static final Map<String, String> commands = new HashMap<>(); + public static final Map<String, String> commandArgs = new HashMap<>(); + + public static boolean isShortcutsLoaded() { + return shortcutsLoaded != null && shortcutsLoaded.isDone(); + } + + public static void init() { + loadShortcuts(); + ClientLifecycleEvents.CLIENT_STOPPING.register(Shortcuts::saveShortcuts); + ClientCommandRegistrationCallback.EVENT.register(Shortcuts::registerCommands); + ClientSendMessageEvents.MODIFY_COMMAND.register(Shortcuts::modifyCommand); + } + + protected static void loadShortcuts() { + if (shortcutsLoaded != null && !isShortcutsLoaded()) { + return; + } + shortcutsLoaded = CompletableFuture.runAsync(() -> { + try (BufferedReader reader = new BufferedReader(new FileReader(SHORTCUTS_FILE))) { + Type shortcutsType = new TypeToken<Map<String, Map<String, String>>>() { + }.getType(); + Map<String, Map<String, String>> shortcuts = SkyblockerMod.GSON.fromJson(reader, shortcutsType); + commands.clear(); + commandArgs.clear(); + commands.putAll(shortcuts.get("commands")); + commandArgs.putAll(shortcuts.get("commandArgs")); + LOGGER.info("[Skyblocker] Loaded {} command shortcuts and {} command argument shortcuts", commands.size(), commandArgs.size()); + } catch (FileNotFoundException e) { + registerDefaultShortcuts(); + LOGGER.warn("[Skyblocker] Shortcuts file not found, using default shortcuts. This is normal when using for the first time.", e); + } catch (IOException e) { + LOGGER.error("[Skyblocker] Failed to load shortcuts file", e); + } + }); + } + + private static void registerDefaultShortcuts() { + commands.clear(); + commandArgs.clear(); + + // Skyblock + commands.put("/s", "/skyblock"); + commands.put("/i", "/is"); + commands.put("/h", "/hub"); + + // Dungeon + commands.put("/d", "/warp dungeon_hub"); + + // Chat channels + commands.put("/ca", "/chat all"); + commands.put("/cp", "/chat party"); + commands.put("/cg", "/chat guild"); + commands.put("/co", "/chat officer"); + commands.put("/cc", "/chat coop"); + + // Message + commandArgs.put("/m", "/msg"); + + // Party + commandArgs.put("/pa", "/p accept"); + commands.put("/pv", "/p leave"); + commands.put("/pd", "/p disband"); + commands.put("/rp", "/reparty"); + + // Visit + commandArgs.put("/v", "/visit"); + commands.put("/vp", "/visit portalhub"); + } + + private static void registerMoreDefaultShortcuts() { + // Combat + commands.put("/spider", "/warp spider"); + commands.put("/crimson", "/warp nether"); + commands.put("/end", "/warp end"); + + // Mining + commands.put("/gold", "/warp gold"); + commands.put("/cavern", "/warp deep"); + commands.put("/dwarven", "/warp mines"); + commands.put("/fo", "/warp forge"); + commands.put("/ch", "/warp crystals"); + + // Foraging & Farming + commands.put("/park", "/warp park"); + commands.put("/barn", "/warp barn"); + commands.put("/desert", "/warp desert"); + commands.put("/ga", "/warp garden"); + + // Other warps + commands.put("/castle", "/warp castle"); + commands.put("/museum", "/warp museum"); + commands.put("/da", "/warp da"); + commands.put("/crypt", "/warp crypt"); + commands.put("/nest", "/warp nest"); + commands.put("/magma", "/warp magma"); + commands.put("/void", "/warp void"); + commands.put("/drag", "/warp drag"); + commands.put("/jungle", "/warp jungle"); + commands.put("/howl", "/warp howl"); + } + + protected static void saveShortcuts(MinecraftClient client) { + JsonObject shortcutsJson = new JsonObject(); + shortcutsJson.add("commands", SkyblockerMod.GSON.toJsonTree(commands)); + shortcutsJson.add("commandArgs", SkyblockerMod.GSON.toJsonTree(commandArgs)); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(SHORTCUTS_FILE))) { + SkyblockerMod.GSON.toJson(shortcutsJson, writer); + LOGGER.info("[Skyblocker] Saved {} command shortcuts and {} command argument shortcuts", commands.size(), commandArgs.size()); + } catch (IOException e) { + LOGGER.error("[Skyblocker] Failed to save shortcuts file", e); + } + } + + private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) { + for (String key : commands.keySet()) { + if (key.startsWith("/")) { + dispatcher.register(literal(key.substring(1))); + } + } + for (String key : commandArgs.keySet()) { + if (key.startsWith("/")) { + dispatcher.register(literal(key.substring(1)).then(argument("args", StringArgumentType.greedyString()))); + } + } + dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("help").executes(context -> { + FabricClientCommandSource source = context.getSource(); + String status = SkyblockerConfig.get().general.shortcuts.enableShortcuts && SkyblockerConfig.get().general.shortcuts.enableCommandShortcuts ? "§a§l (Enabled)" : "§c§l (Disabled)"; + source.sendFeedback(Text.of("§e§lSkyblocker §fCommand Shortcuts" + status)); + if (!isShortcutsLoaded()) { + source.sendFeedback(Text.translatable("skyblocker.shortcuts.notLoaded")); + } else for (Map.Entry<String, String> command : commands.entrySet()) { + source.sendFeedback(Text.of("§7" + command.getKey() + " §f→ §7" + command.getValue())); + } + status = SkyblockerConfig.get().general.shortcuts.enableShortcuts && SkyblockerConfig.get().general.shortcuts.enableCommandArgShortcuts ? "§a§l (Enabled)" : "§c§l (Disabled)"; + source.sendFeedback(Text.of("§e§lSkyblocker §fCommand Argument Shortcuts" + status)); + if (!isShortcutsLoaded()) { + source.sendFeedback(Text.translatable("skyblocker.shortcuts.notLoaded")); + } else for (Map.Entry<String, String> commandArg : commandArgs.entrySet()) { + source.sendFeedback(Text.of("§7" + commandArg.getKey() + " §f→ §7" + commandArg.getValue())); + } + source.sendFeedback(Text.of("§e§lSkyblocker §fCommands")); + for (String command : dispatcher.getSmartUsage(dispatcher.getRoot().getChild(SkyblockerMod.NAMESPACE), source).values()) { + source.sendFeedback(Text.of("§7/" + SkyblockerMod.NAMESPACE + " " + command)); + } + return Command.SINGLE_SUCCESS; + // Queue the screen or else the screen will be immediately closed after executing this command + })).then(literal("shortcuts").executes(context -> SkyblockerMod.getInstance().scheduler.queueOpenScreen(ShortcutsConfigScreen::new)))); + } + + private static String modifyCommand(String command) { + if (SkyblockerConfig.get().general.shortcuts.enableShortcuts) { + if (!isShortcutsLoaded()) { + LOGGER.warn("[Skyblocker] Shortcuts not loaded yet, skipping shortcut for command: {}", command); + return command; + } + command = '/' + command; + if (SkyblockerConfig.get().general.shortcuts.enableCommandShortcuts) { + command = commands.getOrDefault(command, command); + } + if (SkyblockerConfig.get().general.shortcuts.enableCommandArgShortcuts) { + String[] messageArgs = command.split(" "); + for (int i = 0; i < messageArgs.length; i++) { + messageArgs[i] = commandArgs.getOrDefault(messageArgs[i], messageArgs[i]); + } + command = String.join(" ", messageArgs); + } + return command.substring(1); + } + return command; + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java new file mode 100644 index 00000000..f29470bf --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java @@ -0,0 +1,232 @@ +package me.xmrvizzy.skyblocker.skyblock.shortcut; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.Selectable; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.stream.Stream; + +public class ShortcutsConfigListWidget extends ElementListWidget<ShortcutsConfigListWidget.AbstractShortcutEntry> { + private final ShortcutsConfigScreen screen; + private final List<Map<String, String>> shortcutMaps = new ArrayList<>(); + + public ShortcutsConfigListWidget(MinecraftClient minecraftClient, ShortcutsConfigScreen screen, int width, int height, int top, int bottom, int itemHeight) { + super(minecraftClient, width, height, top, bottom, itemHeight); + this.screen = screen; + ShortcutCategoryEntry commandCategory = new ShortcutCategoryEntry(Shortcuts.commands, "skyblocker.shortcuts.command.target", "skyblocker.shortcuts.command.replacement"); + if (Shortcuts.isShortcutsLoaded()) { + commandCategory.shortcutsMap.keySet().stream().sorted().forEach(commandTarget -> addEntry(new ShortcutEntry(commandCategory, commandTarget))); + } else { + addEntry(new ShortcutLoadingEntry()); + } + ShortcutCategoryEntry commandArgCategory = new ShortcutCategoryEntry(Shortcuts.commandArgs, "skyblocker.shortcuts.commandArg.target", "skyblocker.shortcuts.commandArg.replacement", "skyblocker.shortcuts.commandArg.tooltip"); + if (Shortcuts.isShortcutsLoaded()) { + commandArgCategory.shortcutsMap.keySet().stream().sorted().forEach(commandArgTarget -> addEntry(new ShortcutEntry(commandArgCategory, commandArgTarget))); + } else { + addEntry(new ShortcutLoadingEntry()); + } + } + + @Override + public int getRowWidth() { + return super.getRowWidth() + 100; + } + + @Override + protected int getScrollbarPositionX() { + return super.getScrollbarPositionX() + 50; + } + + protected Optional<ShortcutCategoryEntry> getCategory() { + if (getSelectedOrNull() instanceof ShortcutCategoryEntry category) { + return Optional.of(category); + } else if (getSelectedOrNull() instanceof ShortcutEntry shortcutEntry) { + return Optional.of(shortcutEntry.category); + } + return Optional.empty(); + } + + @Override + public void setSelected(@Nullable ShortcutsConfigListWidget.AbstractShortcutEntry entry) { + super.setSelected(entry); + screen.updateButtons(); + } + + protected void addShortcutAfterSelected() { + getCategory().ifPresent(category -> children().add(children().indexOf(getSelectedOrNull()) + 1, new ShortcutEntry(category))); + } + + @Override + protected boolean removeEntry(AbstractShortcutEntry entry) { + return super.removeEntry(entry); + } + + protected boolean hasChanges() { + ShortcutEntry[] notEmptyShortcuts = getNotEmptyShortcuts().toArray(ShortcutEntry[]::new); + return notEmptyShortcuts.length != shortcutMaps.stream().mapToInt(Map::size).sum() || Arrays.stream(notEmptyShortcuts).anyMatch(ShortcutEntry::isChanged); + } + + protected void saveShortcuts() { + shortcutMaps.forEach(Map::clear); + getNotEmptyShortcuts().forEach(ShortcutEntry::save); + Shortcuts.saveShortcuts(MinecraftClient.getInstance()); // Save shortcuts to disk + } + + private Stream<ShortcutEntry> getNotEmptyShortcuts() { + return children().stream().filter(ShortcutEntry.class::isInstance).map(ShortcutEntry.class::cast).filter(ShortcutEntry::isNotEmpty); + } + + protected static abstract class AbstractShortcutEntry extends ElementListWidget.Entry<AbstractShortcutEntry> { + } + + private class ShortcutCategoryEntry extends AbstractShortcutEntry { + private final Map<String, String> shortcutsMap; + private final Text targetName; + private final Text replacementName; + @Nullable + private final Text tooltip; + + private ShortcutCategoryEntry(Map<String, String> shortcutsMap, String targetName, String replacementName) { + this(shortcutsMap, targetName, replacementName, (Text) null); + } + + private ShortcutCategoryEntry(Map<String, String> shortcutsMap, String targetName, String replacementName, String tooltip) { + this(shortcutsMap, targetName, replacementName, Text.translatable(tooltip)); + } + + private ShortcutCategoryEntry(Map<String, String> shortcutsMap, String targetName, String replacementName, @Nullable Text tooltip) { + this.shortcutsMap = shortcutsMap; + this.targetName = Text.translatable(targetName); + this.replacementName = Text.translatable(replacementName); + this.tooltip = tooltip; + shortcutMaps.add(shortcutsMap); + addEntry(this); + } + + @Override + public List<? extends Element> children() { + return List.of(); + } + + @Override + public List<? extends Selectable> selectableChildren() { + return List.of(new Selectable() { + @Override + public SelectionType getType() { + return SelectionType.HOVERED; + } + + @Override + public void appendNarrations(NarrationMessageBuilder builder) { + builder.put(NarrationPart.TITLE, targetName, replacementName); + } + }); + } + + @Override + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + context.drawCenteredTextWithShadow(client.textRenderer, targetName, width / 2 - 85, y + 5, 0xFFFFFF); + context.drawCenteredTextWithShadow(client.textRenderer, replacementName, width / 2 + 85, y + 5, 0xFFFFFF); + if (tooltip != null && isMouseOver(mouseX, mouseY)) { + screen.setTooltip(tooltip); + } + } + } + + private class ShortcutLoadingEntry extends AbstractShortcutEntry { + private final Text text; + + private ShortcutLoadingEntry() { + this.text = Text.translatable("skyblocker.shortcuts.notLoaded"); + } + + @Override + public List<? extends Element> children() { + return List.of(); + } + + @Override + public List<? extends Selectable> selectableChildren() { + return List.of(new Selectable() { + @Override + public SelectionType getType() { + return SelectionType.HOVERED; + } + + @Override + public void appendNarrations(NarrationMessageBuilder builder) { + builder.put(NarrationPart.TITLE, text); + } + }); + } + + @Override + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + context.drawCenteredTextWithShadow(client.textRenderer, text, width / 2, y + 5, 0xFFFFFF); + } + } + + protected class ShortcutEntry extends AbstractShortcutEntry { + private final List<TextFieldWidget> children; + private final ShortcutCategoryEntry category; + private final TextFieldWidget target; + private final TextFieldWidget replacement; + + private ShortcutEntry(ShortcutCategoryEntry category) { + this(category, ""); + } + + private ShortcutEntry(ShortcutCategoryEntry category, String targetString) { + this.category = category; + target = new TextFieldWidget(MinecraftClient.getInstance().textRenderer, width / 2 - 160, 5, 150, 20, category.targetName); + replacement = new TextFieldWidget(MinecraftClient.getInstance().textRenderer, width / 2 + 10, 5, 150, 20, category.replacementName); + target.setText(targetString); + replacement.setText(category.shortcutsMap.getOrDefault(targetString, "")); + children = List.of(target, replacement); + } + + @Override + public String toString() { + return target.getText() + " → " + replacement.getText(); + } + + @Override + public List<? extends Element> children() { + return children; + } + + @Override + public List<? extends Selectable> selectableChildren() { + return children; + } + + private boolean isNotEmpty() { + return !target.getText().isEmpty() && !replacement.getText().isEmpty(); + } + + private boolean isChanged() { + return !category.shortcutsMap.containsKey(target.getText()) || !category.shortcutsMap.get(target.getText()).equals(replacement.getText()); + } + + private void save() { + category.shortcutsMap.put(target.getText(), replacement.getText()); + } + + @Override + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + target.setY(y); + replacement.setY(y); + target.render(context, mouseX, mouseY, tickDelta); + replacement.render(context, mouseX, mouseY, tickDelta); + context.drawCenteredTextWithShadow(client.textRenderer, "→", width / 2, y + 5, 0xFFFFFF); + } + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java new file mode 100644 index 00000000..dec23d36 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java @@ -0,0 +1,107 @@ +package me.xmrvizzy.skyblocker.skyblock.shortcut; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ConfirmScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.GridWidget; +import net.minecraft.client.gui.widget.SimplePositioningWidget; +import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.Text; + +public class ShortcutsConfigScreen extends Screen { + + private ShortcutsConfigListWidget shortcutsConfigListWidget; + private ButtonWidget buttonDelete; + private ButtonWidget buttonNew; + private ButtonWidget buttonDone; + private boolean initialized; + private double scrollAmount; + + public ShortcutsConfigScreen() { + super(Text.translatable("skyblocker.shortcuts.config")); + } + + @Override + public void setTooltip(Text tooltip) { + super.setTooltip(tooltip); + } + + @Override + protected void init() { + super.init(); + if (initialized) { + shortcutsConfigListWidget.updateSize(width, height, 32, height - 64); + } else { + shortcutsConfigListWidget = new ShortcutsConfigListWidget(client, this, width, height, 32, height - 64, 25); + initialized = true; + } + addDrawableChild(shortcutsConfigListWidget); + GridWidget gridWidget = new GridWidget(); + gridWidget.getMainPositioner().marginX(5).marginY(2); + GridWidget.Adder adder = gridWidget.createAdder(2); + buttonDelete = ButtonWidget.builder(Text.translatable("selectServer.delete"), button -> { + if (client != null && shortcutsConfigListWidget.getSelectedOrNull() instanceof ShortcutsConfigListWidget.ShortcutEntry shortcutEntry) { + scrollAmount = shortcutsConfigListWidget.getScrollAmount(); + client.setScreen(new ConfirmScreen(this::deleteEntry, Text.translatable("skyblocker.shortcuts.deleteQuestion"), Text.translatable("skyblocker.shortcuts.deleteWarning", shortcutEntry), Text.translatable("selectServer.deleteButton"), ScreenTexts.CANCEL)); + } + }).build(); + adder.add(buttonDelete); + buttonNew = ButtonWidget.builder(Text.translatable("skyblocker.shortcuts.new"), buttonNew -> shortcutsConfigListWidget.addShortcutAfterSelected()).build(); + adder.add(buttonNew); + adder.add(ButtonWidget.builder(ScreenTexts.CANCEL, button -> { + if (client != null) { + close(); + } + }).build()); + buttonDone = ButtonWidget.builder(ScreenTexts.DONE, button -> { + shortcutsConfigListWidget.saveShortcuts(); + if (client != null) { + close(); + } + }).tooltip(Tooltip.of(Text.translatable("skyblocker.shortcuts.commandSuggestionTooltip"))).build(); + adder.add(buttonDone); + gridWidget.refreshPositions(); + SimplePositioningWidget.setPos(gridWidget, 0, this.height - 64, this.width, 64); + gridWidget.forEachChild(this::addDrawableChild); + updateButtons(); + } + + private void deleteEntry(boolean confirmedAction) { + if (client != null) { + if (confirmedAction && shortcutsConfigListWidget.getSelectedOrNull() instanceof ShortcutsConfigListWidget.ShortcutEntry shortcutEntry) { + shortcutsConfigListWidget.removeEntry(shortcutEntry); + } + client.setScreen(this); // Re-inits the screen and keeps the old instance of ShortcutsConfigListWidget + shortcutsConfigListWidget.setScrollAmount(scrollAmount); + } + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + super.render(context, mouseX, mouseY, delta); + context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 16, 0xFFFFFF); + } + + @Override + public void close() { + if (client != null && shortcutsConfigListWidget.hasChanges()) { + client.setScreen(new ConfirmScreen(confirmedAction -> { + if (confirmedAction) { + super.close(); + } else { + client.setScreen(this); + } + }, Text.translatable("text.cloth-config.quit_config"), Text.translatable("text.cloth-config.quit_config_sure"), Text.translatable("text.cloth-config.quit_discard"), ScreenTexts.CANCEL)); + } else { + super.close(); + } + } + + protected void updateButtons() { + buttonDelete.active = Shortcuts.isShortcutsLoaded() && shortcutsConfigListWidget.getSelectedOrNull() instanceof ShortcutsConfigListWidget.ShortcutEntry; + buttonNew.active = Shortcuts.isShortcutsLoaded() && shortcutsConfigListWidget.getCategory().isPresent(); + buttonDone.active = Shortcuts.isShortcutsLoaded(); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java index 9ea90c16..565bd7a8 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java @@ -17,6 +17,6 @@ public class FrustumUtils { } public static boolean isVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - return ((FrustumInvoker) getFrustum()).isVisible(minX, minY, minZ, maxX, maxY, maxZ); + return ((FrustumInvoker) getFrustum()).invokeIsVisible(minX, minY, minZ, maxX, maxY, maxZ); } }
\ No newline at end of file diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java index 7b19e284..fbe79ade 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java @@ -1,5 +1,6 @@ package me.xmrvizzy.skyblocker.utils; +import com.mojang.brigadier.Command; import me.xmrvizzy.skyblocker.SkyblockerMod; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; @@ -58,17 +59,9 @@ public class Scheduler { * * @param screenSupplier the supplier of the screen to open */ - public void queueOpenScreen(Supplier<Screen> screenSupplier) { - queueOpenScreen(screenSupplier.get()); - } - - /** - * Schedules a screen to open in the next tick. Used in commands to avoid screen immediately closing after the command is executed. - * - * @param screen the supplier of the screen to open - */ - public void queueOpenScreen(Screen screen) { - MinecraftClient.getInstance().send(() -> MinecraftClient.getInstance().setScreen(screen)); + public int queueOpenScreen(Supplier<Screen> screenSupplier) { + MinecraftClient.getInstance().send(() -> MinecraftClient.getInstance().setScreen(screenSupplier.get())); + return Command.SINGLE_SUCCESS; } public void tick() { diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java index 35dfd368..71e3b44f 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java @@ -29,6 +29,7 @@ import java.util.List; */ public class Utils { private static final String PROFILE_PREFIX = "Profile: "; + private static boolean isOnHypixel = false; private static boolean isOnSkyblock = false; private static boolean isInDungeons = false; private static boolean isInjected = false; @@ -45,6 +46,10 @@ public class Utils { private static boolean sentLocRaw = false; private static long lastLocRaw = 0; + public static boolean isOnHypixel() { + return isOnHypixel; + } + public static boolean isOnSkyblock() { return isOnSkyblock; } @@ -126,21 +131,35 @@ public class Utils { String string = sidebar.toString(); if (sidebar.isEmpty()) return; - if (sidebar.get(0).contains("SKYBLOCK") || sidebar.get(0).contains("SKIBLOCK")) { - if (!isOnSkyblock) { - if (!isInjected) { - isInjected = true; - ItemTooltipCallback.EVENT.register(PriceInfoTooltip::onInjectTooltip); + if (sidebar.get(sidebar.size() - 1).equals("www.hypixel.net")) { + if (!isOnHypixel) { + isOnHypixel = true; + } + if (sidebar.get(0).contains("SKYBLOCK") || sidebar.get(0).contains("SKIBLOCK")) { + if (!isOnSkyblock) { + if (!isInjected) { + isInjected = true; + ItemTooltipCallback.EVENT.register(PriceInfoTooltip::onInjectTooltip); + } + isOnSkyblock = true; + SkyblockEvents.JOIN.invoker().onSkyblockJoin(); } - isOnSkyblock = true; - SkyblockEvents.JOIN.invoker().onSkyblockJoin(); + } else { + leaveSkyblock(); } - } else if (isOnSkyblock) { + isInDungeons = isOnSkyblock && string.contains("The Catacombs"); + } else if (isOnHypixel) { + isOnHypixel = false; + leaveSkyblock(); + } + } + + private static void leaveSkyblock() { + if (isOnSkyblock) { isOnSkyblock = false; isInDungeons = false; SkyblockEvents.LEAVE.invoker().onSkyblockLeave(); } - isInDungeons = isOnSkyblock && string.contains("The Catacombs"); } public static String getLocation() { diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainer.java b/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainer.java index a4e445ee..7b92fff6 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainer.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainer.java @@ -1,6 +1,5 @@ package me.xmrvizzy.skyblocker.utils.title; -import com.mojang.brigadier.Command; import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; @@ -9,7 +8,6 @@ import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; import java.util.LinkedHashSet; @@ -31,10 +29,7 @@ public class TitleContainer { ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") .then(ClientCommandManager.literal("hud") .then(ClientCommandManager.literal("titleContainer") - .executes(context -> { - SkyblockerMod.getInstance().scheduler.queueOpenScreen(new TitleContainerConfigScreen(Text.of("Title Container HUD Config"))); - return Command.SINGLE_SUCCESS; - }))))); + .executes(context -> SkyblockerMod.getInstance().scheduler.queueOpenScreen(TitleContainerConfigScreen::new)))))); } /** diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainerConfigScreen.java b/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainerConfigScreen.java index e729ea15..c0c4d63c 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainerConfigScreen.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainerConfigScreen.java @@ -21,8 +21,8 @@ public class TitleContainerConfigScreen extends Screen { private float hudX = SkyblockerConfig.get().general.titleContainer.x; private float hudY = SkyblockerConfig.get().general.titleContainer.y; - protected TitleContainerConfigScreen(Text title) { - super(title); + protected TitleContainerConfigScreen() { + super(Text.of("Title Container HUD Config")); } @Override diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index 0cf9933c..b907cf1b 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -29,6 +29,13 @@ "text.autoconfig.skyblocker.option.general.fishing.enableFishingHelper": "Enable Fishing Helper", "text.autoconfig.skyblocker.option.general.fairySouls": "Fairy Souls Helper", "text.autoconfig.skyblocker.option.general.fairySouls.enableFairySoulsHelper": "Enable Fairy Souls Helper", + "text.autoconfig.skyblocker.option.general.shortcuts": "Shortcuts", + "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts": "Enable Shortcuts", + "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts.@Tooltip": "Only works on Hypixel. Edit shortcuts with \"/skyblocker shortcuts\". At least one of the following options must be enabled for this to take effect.", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts": "Enable Command Shortcuts", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts.@Tooltip": "Shortcuts for commands consisting of only one word. Edit shortcuts with \"/skyblocker shortcuts\". Shortcuts must be enabled for this to take effect.", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts": "Enable Command Argument Shortcuts", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts.@Tooltip": "Shortcuts that replace one or more word(s)/argument(s) of a command which has multiple words/arguments. Edit shortcuts with \"/skyblocker shortcuts\". Shortcuts must be enabled for this to take effect.", "text.autoconfig.skyblocker.option.general.quicknav": "Quicknav", "text.autoconfig.skyblocker.option.general.quicknav.enableQuicknav": "Enable Quicknav", "text.autoconfig.skyblocker.option.general.backpackPreviewWithoutShift": "View backpack preview without holding Shift", @@ -214,7 +221,7 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Enable Background", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.x": "X", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.y": "Y", - + "text.autoconfig.skyblocker.option.locations.rift": "The Rift", "text.autoconfig.skyblocker.option.locations.rift.mirrorverseWaypoints": "Enable Mirrorverse Waypoints", "text.autoconfig.skyblocker.option.locations.rift.mcGrubberStacks": "McGrubber Stacks", @@ -265,5 +272,16 @@ "skyblocker.rift.mania": "Mania!", "skyblocker.rift.stakeNow": "Stake now!", "skyblocker.fairySouls.markAllFound": "Marked all fairy souls in the current island as found", - "skyblocker.fairySouls.markAllMissing": "Marked all fairy souls in the current island as missing" + "skyblocker.fairySouls.markAllMissing": "Marked all fairy souls in the current island as missing", + "skyblocker.shortcuts.config": "Shortcuts Config", + "skyblocker.shortcuts.notLoaded": "§c§lShortcuts not loaded yet", + "skyblocker.shortcuts.command.target": "Target Command", + "skyblocker.shortcuts.command.replacement": "Replacement Command", + "skyblocker.shortcuts.commandArg.target": "Target Command Argument", + "skyblocker.shortcuts.commandArg.replacement": "Replacement Command Argument", + "skyblocker.shortcuts.commandArg.tooltip": "Replace one or more word(s)/argument(s) of a command which has multiple words/arguments instead of matching the entire command.", + "skyblocker.shortcuts.deleteQuestion": "Are you sure you want to remove this shortcut?", + "skyblocker.shortcuts.deleteWarning": "Shortcut '%s' will be lost forever! (A long time!)", + "skyblocker.shortcuts.new": "New Shortcut", + "skyblocker.shortcuts.commandSuggestionTooltip": "Due to limitations of Minecraft, command suggestions will only work after a restart of the game." } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ead46adc..5b383fe7 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -30,7 +30,7 @@ ], "depends": { "fabricloader": ">=0.14.21", - "fabric-api": ">=0.83.0+1.20", + "fabric-api": ">=0.86.0", "cloth-config2": "*", "minecraft": "~1.20" }, |