aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2023-07-22 15:17:11 -0400
committerGitHub <noreply@github.com>2023-07-22 15:17:11 -0400
commit1aa006198fe987dae999486c6668f4f6e071ddf4 (patch)
treec850f150efdda3b940d74f60695cbcc880b143ce
parentbac0f8f4aff96c5c6707bbb750f37de92e000da4 (diff)
parent14ec65e7639758972f44a9097c44b8eb53c45c15 (diff)
downloadSkyblocker-1aa006198fe987dae999486c6668f4f6e071ddf4.tar.gz
Skyblocker-1aa006198fe987dae999486c6668f4f6e071ddf4.tar.bz2
Skyblocker-1aa006198fe987dae999486c6668f4f6e071ddf4.zip
Merge branch 'SkyblockerMod:master' into dark-auction-tabhud
-rw-r--r--build.gradle13
-rw-r--r--gradle.properties4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java23
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/FrustumInvoker.java7
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMap.java40
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java28
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java56
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java6
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/Shortcuts.java206
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigListWidget.java232
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/shortcut/ShortcutsConfigScreen.java107
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/FrustumUtils.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Scheduler.java15
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java37
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainer.java7
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/title/TitleContainerConfigScreen.java4
-rw-r--r--src/main/resources/assets/skyblocker/lang/en_us.json22
-rw-r--r--src/main/resources/fabric.mod.json2
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"
},