diff options
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker/skyblock')
19 files changed, 1083 insertions, 274 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java index 8dee3fcb..b53157c5 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FishingHelper.java @@ -44,10 +44,10 @@ public class FishingHelper { startTime = 0; } - public static void onSound(MinecraftClient client, PlaySoundS2CPacket packet) { + public static void onSound(PlaySoundS2CPacket packet) { String path = packet.getSound().value().getId().getPath(); if (SkyblockerConfig.get().general.fishing.enableFishingHelper && startTime != 0 && System.currentTimeMillis() >= startTime + 2000 && ("entity.generic.splash".equals(path) || "entity.player.splash".equals(path))) { - ClientPlayerEntity player = client.player; + ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player != null && player.fishHook != null) { Vec3d soundToFishHook = player.fishHook.getPos().subtract(packet.getX(), 0, packet.getZ()); if (Math.abs(normalYawVector.x * soundToFishHook.z - normalYawVector.z * soundToFishHook.x) < 0.2D && Math.abs(normalYawVector.dotProduct(soundToFishHook)) < 4D && player.getPos().squaredDistanceTo(packet.getX(), packet.getY(), packet.getZ()) > 1D) { diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/TeleportOverlay.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/TeleportOverlay.java new file mode 100644 index 00000000..e7c76160 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/TeleportOverlay.java @@ -0,0 +1,112 @@ +package me.xmrvizzy.skyblocker.skyblock; + +import com.mojang.blaze3d.systems.RenderSystem; +import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip; +import me.xmrvizzy.skyblocker.utils.RenderHelper; +import me.xmrvizzy.skyblocker.utils.Utils; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; + +public class TeleportOverlay { + private static final float[] COLOR_COMPONENTS = {118f / 255f, 21f / 255f, 148f / 255f}; + private static final MinecraftClient client = MinecraftClient.getInstance(); + + public static void init() { + WorldRenderEvents.AFTER_TRANSLUCENT.register(TeleportOverlay::render); + } + + private static void render(WorldRenderContext wrc) { + if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.teleportOverlay.enableTeleportOverlays && client.player != null && client.world != null) { + ItemStack heldItem = client.player.getMainHandStack(); + String itemId = PriceInfoTooltip.getInternalNameFromNBT(heldItem); + NbtCompound nbt = heldItem.getNbt(); + + if (itemId != null) { + switch (itemId) { + case "ASPECT_OF_THE_LEECH_1" -> { + if (SkyblockerConfig.get().general.teleportOverlay.enableWeirdTransmission) { + render(wrc, 3); + } + } + case "ASPECT_OF_THE_LEECH_2" -> { + if (SkyblockerConfig.get().general.teleportOverlay.enableWeirdTransmission) { + render(wrc, 4); + } + } + case "ASPECT_OF_THE_END", "ASPECT_OF_THE_VOID" -> { + if (SkyblockerConfig.get().general.teleportOverlay.enableEtherTransmission && client.options.sneakKey.isPressed() && nbt != null && nbt.getCompound("ExtraAttributes").getInt("ethermerge") == 1) { + render(wrc, nbt, 57); + } else if (SkyblockerConfig.get().general.teleportOverlay.enableInstantTransmission) { + render(wrc, nbt, 8); + } + } + case "ETHERWARP_CONDUIT" -> { + if (SkyblockerConfig.get().general.teleportOverlay.enableEtherTransmission) { + render(wrc, nbt, 57); + } + } + case "SINSEEKER_SCYTHE" -> { + if (SkyblockerConfig.get().general.teleportOverlay.enableSinrecallTransmission) { + render(wrc, nbt, 4); + } + } + case "NECRON_BLADE", "ASTRAEA", "HYPERION", "SCYLLA", "VALKYRIE" -> { + if (SkyblockerConfig.get().general.teleportOverlay.enableWitherImpact) { + render(wrc, 10); + } + } + } + } + } + } + + /** + * Renders the teleport overlay with a given base range and the tuned transmission stat. + */ + private static void render(WorldRenderContext wrc, NbtCompound nbt, int baseRange) { + render(wrc, nbt != null && nbt.getCompound("ExtraAttributes").contains("tuned_transmission") ? baseRange + nbt.getCompound("ExtraAttributes").getInt("tuned_transmission") : baseRange); + } + + /** + * Renders the teleport overlay with a given range. Uses {@link MinecraftClient#crosshairTarget} if it is a block and within range. Otherwise, raycasts from the player with the given range. + * @implNote {@link MinecraftClient#player} and {@link MinecraftClient#world} must not be null when calling this method. + */ + private static void render(WorldRenderContext wrc, int range) { + if (client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.BLOCK && client.crosshairTarget instanceof BlockHitResult blockHitResult && client.crosshairTarget.squaredDistanceTo(client.player) < range * range) { + render(wrc, blockHitResult); + } else if (client.interactionManager != null && range > client.interactionManager.getReachDistance()) { + @SuppressWarnings("DataFlowIssue") + HitResult result = client.player.raycast(range, wrc.tickDelta(), false); + if (result.getType() == HitResult.Type.BLOCK && result instanceof BlockHitResult blockHitResult) { + render(wrc, blockHitResult); + } + } + } + + /** + * Renders the teleport overlay at the given {@link BlockHitResult}. + * @implNote {@link MinecraftClient#world} must not be null when calling this method. + */ + private static void render(WorldRenderContext wrc, BlockHitResult blockHitResult) { + BlockPos pos = blockHitResult.getBlockPos(); + @SuppressWarnings("DataFlowIssue") + BlockState state = client.world.getBlockState(pos); + if (!state.isAir() && client.world.getBlockState(pos.up()).isAir() && client.world.getBlockState(pos.up(2)).isAir()) { + RenderSystem.polygonOffset(-1f, -10f); + RenderSystem.enablePolygonOffset(); + + RenderHelper.renderFilledIfVisible(wrc, pos, COLOR_COMPONENTS, 0.5f); + + RenderSystem.polygonOffset(0f, 0f); + RenderSystem.disablePolygonOffset(); + } + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java index 2d868782..44c8803f 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java @@ -25,7 +25,7 @@ public class CroesusHelper extends ContainerSolver { List<ColorHighlight> highlights = new ArrayList<>(); for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) { ItemStack stack = entry.getValue(); - if (stack != null && stack.getNbt() != null && stack.getNbt().toString().contains("opened")) { + if (stack != null && stack.getNbt() != null && stack.getNbt().toString().contains("No more Chests to open!")) { highlights.add(ColorHighlight.gray(entry.getKey())); } } 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/dungeon/OldLever.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/OldLever.java index 37320c92..13789fe1 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/OldLever.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/OldLever.java @@ -7,11 +7,11 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; public class OldLever { - protected static final VoxelShape FLOOR_SHAPE; - protected static final VoxelShape NORTH_SHAPE; - protected static final VoxelShape SOUTH_SHAPE; - protected static final VoxelShape EAST_SHAPE; - protected static final VoxelShape WEST_SHAPE; + protected static final VoxelShape FLOOR_SHAPE = Block.createCuboidShape(4.0D, 0.0D, 4.0D, 12.0D, 10.0D, 12.0D); + protected static final VoxelShape NORTH_SHAPE = Block.createCuboidShape(5.0D, 3.0D, 10.0D, 11.0D, 13.0D, 16.0D); + protected static final VoxelShape SOUTH_SHAPE = Block.createCuboidShape(5.0D, 3.0D, 0.0D, 11.0D, 13.0D, 6.0D); + protected static final VoxelShape EAST_SHAPE = Block.createCuboidShape(0.0D, 3.0D, 5.0D, 6.0D, 13.0D, 11.0D); + protected static final VoxelShape WEST_SHAPE = Block.createCuboidShape(10.0D, 3.0D, 5.0D, 16.0D, 13.0D, 11.0D); public static VoxelShape getShape(WallMountLocation wallMountLocation, Direction direction) { if (!SkyblockerConfig.get().general.hitbox.oldLeverHitbox) @@ -37,12 +37,4 @@ public class OldLever { } return null; } - - static { - FLOOR_SHAPE = Block.createCuboidShape(4, 0, 4, 12, 10, 12); - NORTH_SHAPE = Block.createCuboidShape(5.0D, 3.0D, 10.0D, 11.0D, 13.0D, 16.0D); - SOUTH_SHAPE = Block.createCuboidShape(5.0D, 3.0D, 0.0D, 11.0D, 13.0D, 6.0D); - WEST_SHAPE = Block.createCuboidShape(10.0D, 3.0D, 5.0D, 16.0D, 13.0D, 11.0D); - EAST_SHAPE = Block.createCuboidShape(0.0D, 3.0D, 5.0D, 6.0D, 13.0D, 11.0D); - } } 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 21a1b2d0..999a3163 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dwarven/DwarvenHud.java @@ -1,12 +1,6 @@ package me.xmrvizzy.skyblocker.skyblock.dwarven; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - +import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.hud.HudCommsWidget; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; @@ -17,8 +11,14 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -public class DwarvenHud { +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +public class DwarvenHud { public static final MinecraftClient client = MinecraftClient.getInstance(); public static List<Commission> commissionList = new ArrayList<>(); @@ -35,33 +35,32 @@ public class DwarvenHud { "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)")) + "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; - }))))); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, + registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") + .then(ClientCommandManager.literal("hud") + .then(ClientCommandManager.literal("dwarven") + .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); + render(context, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.x, + SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.y, commissionList); }); } 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); @@ -76,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; } } @@ -91,7 +90,8 @@ public class DwarvenHud { HudCommsWidget.INSTANCE.update(); HudCommsWidget.INSTANCE.setX(hudX); HudCommsWidget.INSTANCE.setY(hudY); - HudCommsWidget.INSTANCE.render(context, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enableBackground); + HudCommsWidget.INSTANCE.render(context, + SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enableBackground); } public static void renderFancy(DrawContext context, int hudX, int hudY, List<Commission> commissions) { @@ -99,12 +99,14 @@ public class DwarvenHud { HudCommsWidget.INSTANCE.update(); HudCommsWidget.INSTANCE.setX(hudX); HudCommsWidget.INSTANCE.setY(hudY); - HudCommsWidget.INSTANCE.render(context, SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enableBackground); + HudCommsWidget.INSTANCE.render(context, + SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enableBackground); } public static void update() { commissionList = new ArrayList<>(); - if (client.player == null || !SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enabled) return; + if (client.player == null || !SkyblockerConfig.get().locations.dwarvenMines.dwarvenHud.enabled) + return; client.getNetworkHandler().getPlayerList().forEach(playerListEntry -> { if (playerListEntry.getDisplayName() != null) { @@ -120,6 +122,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/itemlist/ItemFixerUpper.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemFixerUpper.java index d8ad3a89..cc7b216c 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemFixerUpper.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemFixerUpper.java @@ -1,39 +1,45 @@ package me.xmrvizzy.skyblocker.skyblock.itemlist; -import net.minecraft.item.Items; -// import net.minecraft.registry.Registry; -import net.minecraft.registry.Registries; -import net.minecraft.util.Identifier; import java.util.Map; public class ItemFixerUpper { - private final static Map<String, String> MAPPING = Map.ofEntries( - Map.entry("minecraft:golden_rail", "minecraft:powered_rail"), - Map.entry("minecraft:lit_pumpkin", "minecraft:jack_o_lantern"), - Map.entry("minecraft:snow_layer", "minecraft:snow"), - Map.entry("minecraft:hardened_clay", "minecraft:terracotta"), - Map.entry("minecraft:speckled_melon", "minecraft:glistering_melon_slice"), - Map.entry("minecraft:mob_spawner", "minecraft:spawner"), - Map.entry("minecraft:brick_block", "minecraft:bricks"), - Map.entry("minecraft:deadbush", "minecraft:dead_bush"), - Map.entry("minecraft:slime", "minecraft:slime_block"), - Map.entry("minecraft:melon_block", "minecraft:melon"), - Map.entry("minecraft:reeds", "minecraft:sugar_cane"), - Map.entry("minecraft:yellow_flower", "minecraft:dandelion"), - Map.entry("minecraft:firework_charge", "minecraft:firework_star"), - Map.entry("minecraft:noteblock", "minecraft:note_block"), - Map.entry("minecraft:web", "minecraft:cobweb"), - Map.entry("minecraft:fireworks", "minecraft:firework_rocket"), - Map.entry("minecraft:netherbrick", "minecraft:nether_brick"), - Map.entry("minecraft:stained_hardened_clay", "minecraft:terracotta"), - Map.entry("minecraft:quartz_ore", "minecraft:nether_quartz_ore"), - Map.entry("minecraft:tallgrass", "minecraft:grass"), - Map.entry("minecraft:stone_slab2", "minecraft:red_sandstone_slab"), - Map.entry("minecraft:waterlily", "minecraft:lily_pad"), - Map.entry("minecraft:stone_stairs", "minecraft:cobblestone_stairs") - ); + private final static String[] ANVIL_VARIANTS = { + "minecraft:anvil", + "minecraft:chipped_anvil", + "minecraft:damaged_anvil" + }; + + private final static String[] COAL_VARIANTS = { + "minecraft:coal", + "minecraft:charcoal" + }; - private final static String[] DYE_COLORS = { + private final static String[] COBBLESTONE_WALL_VARIANTS = { + "minecraft:cobblestone_wall", + "minecraft:mossy_cobblestone_wall" + }; + + private final static String[] COOKED_FISH_VARIANTS = { + "minecraft:cooked_cod", + "minecraft:cooked_salmon" + }; + + private final static String[] DIRT_VARIANTS = { + "minecraft:dirt", + "minecraft:coarse_dirt", + "minecraft:podzol" + }; + + private final static String[] DOUBLE_PLANT_VARIANTS = { + "minecraft:sunflower", + "minecraft:lilac", + "minecraft:tall_grass", + "minecraft:large_fern", + "minecraft:rose_bush", + "minecraft:peony" + }; + + private final static String[] DYE_VARIANTS = { "minecraft:ink_sac", "minecraft:red_dye", "minecraft:green_dye", @@ -52,39 +58,55 @@ public class ItemFixerUpper { "minecraft:bone_meal" }; - private final static String[] BLOCK_COLORS = { - "white_", - "orange_", - "magenta_", - "light_blue_", - "yellow_", - "lime_", - "pink_", - "gray_", - "light_gray_", - "cyan_", - "purple_", - "blue_", - "brown_", - "green_", - "red_", - "black_" - }; - - private final static String[] TREE_VARIANTS = { - "oak_", - "spruce_", - "birch_", - "jungle_", - "acacia_", - "dark_oak_" - }; - - private final static String[] STONE_BRICK_VARIANTS = { - "minecraft:stone_bricks", - "minecraft:mossy_stone_bricks", - "minecraft:cracked_stone_bricks", - "minecraft:chiseled_stone_bricks" + private final static String[] FISH_VARIANTS = { + "minecraft:cod", + "minecraft:salmon", + "minecraft:tropical_fish", + "minecraft:pufferfish" + }; + + private final static String[] GOLDEN_APPLE_VARIANTS = { + "minecraft:golden_apple", + "minecraft:enchanted_golden_apple" + }; + + private final static String[] LOG_VARIANTS = { + "minecraft:oak_log", + "minecraft:spruce_log", + "minecraft:birch_log", + "minecraft:jungle_log", + "minecraft:oak_wood", + "minecraft:spruce_wood", + "minecraft:birch_wood", + "minecraft:jungle_wood", + }; + + private final static String[] LOG2_VARIANTS = { + "minecraft:acacia_log", + "minecraft:dark_oak_log", + "minecraft:acacia_wood", + "minecraft:dark_oak_wood" + }; + + private final static String[] MONSTER_EGG_VARIANTS = { + "minecraft:infested_stone", + "minecraft:infested_cobblestone", + "minecraft:infested_stone_bricks", + "minecraft:infested_mossy_stone_bricks", + "minecraft:infested_cracked_stone_bricks", + "minecraft:infested_chiseled_stone_bricks" + }; + + private final static String[] PRISMARINE_VARIANTS = { + "minecraft:prismarine", + "minecraft:prismarine_bricks", + "minecraft:dark_prismarine" + }; + + private final static String[] QUARTZ_BLOCK_VARIANTS = { + "minecraft:quartz_block", + "minecraft:chiseled_quartz_block", + "minecraft:quartz_pillar" }; private final static String[] RED_FLOWER_VARIANTS = { @@ -99,45 +121,11 @@ public class ItemFixerUpper { "minecraft:oxeye_daisy" }; - private final static String[] DOUBLE_PLANT_VARIANTS = { - "minecraft:sunflower", - "minecraft:lilac", - "minecraft:tall_grass", - "minecraft:large_fern", - "minecraft:rose_bush", - "minecraft:peony" + private final static String[] SAND_VARIANTS = { + "minecraft:sand", + "minecraft:red_sand" }; - private final static Map<Integer, String> SPAWN_EGG_VARIANTS = Map.ofEntries( - Map.entry(50, "minecraft:creeper_spawn_egg"), - Map.entry(51, "minecraft:skeleton_spawn_egg"), - Map.entry(52, "minecraft:spider_spawn_egg"), - Map.entry(54, "minecraft:zombie_spawn_egg"), - Map.entry(55, "minecraft:slime_spawn_egg"), - Map.entry(56, "minecraft:ghast_spawn_egg"), - Map.entry(57, "minecraft:zombified_piglin_spawn_egg"), - Map.entry(58, "minecraft:enderman_spawn_egg"), - Map.entry(59, "minecraft:cave_spider_spawn_egg"), - Map.entry(60, "minecraft:silverfish_spawn_egg"), - Map.entry(61, "minecraft:blaze_spawn_egg"), - Map.entry(62, "minecraft:magma_cube_spawn_egg"), - Map.entry(65, "minecraft:bat_spawn_egg"), - Map.entry(66, "minecraft:witch_spawn_egg"), - Map.entry(67, "minecraft:endermite_spawn_egg"), - Map.entry(68, "minecraft:guardian_spawn_egg"), - Map.entry(90, "minecraft:pig_spawn_egg"), - Map.entry(91, "minecraft:sheep_spawn_egg"), - Map.entry(92, "minecraft:cow_spawn_egg"), - Map.entry(93, "minecraft:chicken_spawn_egg"), - Map.entry(94, "minecraft:squid_spawn_egg"), - Map.entry(95, "minecraft:wolf_spawn_egg"), - Map.entry(96, "minecraft:mooshroom_spawn_egg"), - Map.entry(98, "minecraft:ocelot_spawn_egg"), - Map.entry(100, "minecraft:horse_spawn_egg"), - Map.entry(101, "minecraft:rabbit_spawn_egg"), - Map.entry(120, "minecraft:villager_spawn_egg") - ); - private final static String[] SKULL_VARIANTS = { "minecraft:skeleton_skull", "minecraft:wither_skeleton_skull", @@ -146,16 +134,9 @@ public class ItemFixerUpper { "minecraft:creeper_head" }; - private final static String[] FISH_VARIANTS = { - "minecraft:cod", - "minecraft:salmon", - "minecraft:tropical_fish", - "minecraft:pufferfish" - }; - - private final static String[] COOKED_FISH_VARIANTS = { - "minecraft:cooked_cod", - "minecraft:cooked_salmon" + private final static String[] SPONGE_VARIANTS = { + "minecraft:sponge", + "minecraft:wet_sponge" }; private final static String[] STONE_VARIANTS = { @@ -171,7 +152,7 @@ public class ItemFixerUpper { private final static String[] STONE_SLAB_VARIANTS = { "minecraft:smooth_stone_slab", "minecraft:sandstone_slab", - "minecraft:barrier", // doesn't exist + "minecraft:petrified_oak_slab", "minecraft:cobblestone_slab", "minecraft:brick_slab", "minecraft:stone_brick_slab", @@ -179,63 +160,182 @@ public class ItemFixerUpper { "minecraft:quartz_slab" }; - private final static String[] COBBLESTONE_WALL_VARIANTS = { - "minecraft:cobblestone_wall", - "minecraft:mossy_cobblestone_wall" + private final static String[] STONEBRICK_VARIANTS = { + "minecraft:stone_bricks", + "minecraft:mossy_stone_bricks", + "minecraft:cracked_stone_bricks", + "minecraft:chiseled_stone_bricks" }; - private final static String[] DIRT_VARIANTS = { - "minecraft:dirt", - "minecraft:coarse_dirt", - "minecraft:podzol" + private final static String[] TALLGRASS_VARIANTS = { + "minecraft:dead_bush", + "minecraft:grass", + "minecraft:fern" }; - private final static String[] SPONGE_VARIANTS = { - "minecraft:sponge", - "minecraft:wet_sponge" + private final static Map<Integer, String> SPAWN_EGG_VARIANTS = Map.ofEntries( + //This entry 0 is technically not right but Hypixel decided to make it polar bear so well we use that + Map.entry(0, "minecraft:polar_bear_spawn_egg"), + Map.entry(50, "minecraft:creeper_spawn_egg"), + Map.entry(51, "minecraft:skeleton_spawn_egg"), + Map.entry(52, "minecraft:spider_spawn_egg"), + Map.entry(54, "minecraft:zombie_spawn_egg"), + Map.entry(55, "minecraft:slime_spawn_egg"), + Map.entry(56, "minecraft:ghast_spawn_egg"), + Map.entry(57, "minecraft:zombified_piglin_spawn_egg"), + Map.entry(58, "minecraft:enderman_spawn_egg"), + Map.entry(59, "minecraft:cave_spider_spawn_egg"), + Map.entry(60, "minecraft:silverfish_spawn_egg"), + Map.entry(61, "minecraft:blaze_spawn_egg"), + Map.entry(62, "minecraft:magma_cube_spawn_egg"), + Map.entry(65, "minecraft:bat_spawn_egg"), + Map.entry(66, "minecraft:witch_spawn_egg"), + Map.entry(67, "minecraft:endermite_spawn_egg"), + Map.entry(68, "minecraft:guardian_spawn_egg"), + Map.entry(90, "minecraft:pig_spawn_egg"), + Map.entry(91, "minecraft:sheep_spawn_egg"), + Map.entry(92, "minecraft:cow_spawn_egg"), + Map.entry(93, "minecraft:chicken_spawn_egg"), + Map.entry(94, "minecraft:squid_spawn_egg"), + Map.entry(95, "minecraft:wolf_spawn_egg"), + Map.entry(96, "minecraft:mooshroom_spawn_egg"), + Map.entry(98, "minecraft:ocelot_spawn_egg"), + Map.entry(100, "minecraft:horse_spawn_egg"), + Map.entry(101, "minecraft:rabbit_spawn_egg"), + Map.entry(120, "minecraft:villager_spawn_egg") + ); + + private final static String[] SANDSTONE_VARIANTS = { + ":", + ":chiseled_", + ":cut_" }; - private final static String[] PRISMARINE_VARIANTS = { - "minecraft:prismarine", - "minecraft:prismarine_bricks", - "minecraft:dark_prismarine" + private final static String[] COLOR_VARIANTS = { + ":white_", + ":orange_", + ":magenta_", + ":light_blue_", + ":yellow_", + ":lime_", + ":pink_", + ":gray_", + ":light_gray_", + ":cyan_", + ":purple_", + ":blue_", + ":brown_", + ":green_", + ":red_", + ":black_" + }; + + private final static String[] WOOD_VARIANTS = { + ":oak_", + ":spruce_", + ":birch_", + ":jungle_", + ":acacia_", + ":dark_oak_" }; - // TODO: map potions to their correct colors + //this is the map of all renames + private final static Map<String, String> RENAMED = Map.ofEntries( + Map.entry("minecraft:bed", "minecraft:red_bed"), + Map.entry("minecraft:boat", "minecraft:oak_boat"), + Map.entry("minecraft:brick_block", "minecraft:bricks"), + Map.entry("minecraft:deadbush", "minecraft:dead_bush"), + Map.entry("minecraft:fence_gate", "minecraft:oak_fence_gate"), + Map.entry("minecraft:fence", "minecraft:oak_fence"), + Map.entry("minecraft:firework_charge", "minecraft:firework_star"), + Map.entry("minecraft:fireworks", "minecraft:firework_rocket"), + Map.entry("minecraft:golden_rail", "minecraft:powered_rail"), + Map.entry("minecraft:grass", "minecraft:grass_block"), + Map.entry("minecraft:hardened_clay", "minecraft:terracotta"), + Map.entry("minecraft:lit_pumpkin", "minecraft:jack_o_lantern"), + Map.entry("minecraft:melon_block", "minecraft:melon"), + Map.entry("minecraft:melon", "minecraft:melon_slice"), + Map.entry("minecraft:mob_spawner", "minecraft:spawner"), + Map.entry("minecraft:nether_brick", "minecraft:nether_bricks"), + Map.entry("minecraft:netherbrick", "minecraft:nether_brick"), + Map.entry("minecraft:noteblock", "minecraft:note_block"), + Map.entry("minecraft:piston_extension", "minecraft:moving_piston"), + Map.entry("minecraft:portal", "minecraft:nether_portal"), + Map.entry("minecraft:pumpkin", "minecraft:carved_pumpkin"), + Map.entry("minecraft:quartz_ore", "minecraft:nether_quartz_ore"), + Map.entry("minecraft:record_11", "minecraft:music_disc_11"), + Map.entry("minecraft:record_13", "minecraft:music_disc_13"), + Map.entry("minecraft:record_blocks", "minecraft:music_disc_blocks"), + Map.entry("minecraft:record_cat", "minecraft:music_disc_cat"), + Map.entry("minecraft:record_chirp", "minecraft:music_disc_chirp"), + Map.entry("minecraft:record_far", "minecraft:music_disc_far"), + Map.entry("minecraft:record_mall", "minecraft:music_disc_mall"), + Map.entry("minecraft:record_mellohi", "minecraft:music_disc_mellohi"), + Map.entry("minecraft:record_stal", "minecraft:music_disc_stal"), + Map.entry("minecraft:record_strad", "minecraft:music_disc_strad"), + Map.entry("minecraft:record_wait", "minecraft:music_disc_wait"), + Map.entry("minecraft:record_ward", "minecraft:music_disc_ward"), + Map.entry("minecraft:red_nether_brick", "minecraft:red_nether_bricks"), + Map.entry("minecraft:reeds", "minecraft:sugar_cane"), + Map.entry("minecraft:sign", "minecraft:oak_sign"), + Map.entry("minecraft:slime", "minecraft:slime_block"), + Map.entry("minecraft:snow_layer", "minecraft:snow"), + Map.entry("minecraft:snow", "minecraft:snow_block"), + Map.entry("minecraft:speckled_melon", "minecraft:glistering_melon_slice"), + Map.entry("minecraft:stone_slab2", "minecraft:red_sandstone_slab"), + Map.entry("minecraft:stone_stairs", "minecraft:cobblestone_stairs"), + Map.entry("minecraft:trapdoor", "minecraft:oak_trapdoor"), + Map.entry("minecraft:waterlily", "minecraft:lily_pad"), + Map.entry("minecraft:web", "minecraft:cobweb"), + Map.entry("minecraft:wooden_button", "minecraft:oak_button"), + Map.entry("minecraft:wooden_door", "minecraft:oak_door"), + Map.entry("minecraft:wooden_pressure_plate", "minecraft:oak_pressure_plate"), + Map.entry("minecraft:yellow_flower", "minecraft:dandelion") + ); + + //TODO : Add mushroom block variants + //i'll do it later because it isn't used and unlike the other, it's not just a rename or a separate, it's a separate and a merge public static String convertItemId(String id, int damage) { - if (id.equals("minecraft:dye")) return DYE_COLORS[damage]; - if (id.equals("minecraft:log2")) return "minecraft:" + TREE_VARIANTS[damage + 4] + "log"; - if (id.equals("minecraft:leaves2")) return "minecraft:" + TREE_VARIANTS[damage + 4] + "leaves"; - if (id.equals("minecraft:stonebrick")) return STONE_BRICK_VARIANTS[damage]; - if (id.equals("minecraft:red_flower")) return RED_FLOWER_VARIANTS[damage]; - if (id.equals("minecraft:double_plant")) return DOUBLE_PLANT_VARIANTS[damage]; - if (id.equals("minecraft:spawn_egg")) return SPAWN_EGG_VARIANTS.getOrDefault(damage, "minecraft:ghast_spawn_egg"); - if (id.equals("minecraft:banner")) return "minecraft:" + BLOCK_COLORS[15 - damage] + "banner"; - if (id.equals("minecraft:skull")) return SKULL_VARIANTS[damage]; - if (id.equals("minecraft:fish")) return FISH_VARIANTS[damage]; - if (id.equals("minecraft:cooked_fish")) return COOKED_FISH_VARIANTS[damage]; - if (id.equals("minecraft:stone")) return STONE_VARIANTS[damage]; - if (id.equals("minecraft:stone_slab")) return STONE_SLAB_VARIANTS[damage]; - if (id.equals("minecraft:cobblestone_wall")) return COBBLESTONE_WALL_VARIANTS[damage]; - if (id.equals("minecraft:dirt")) return DIRT_VARIANTS[damage]; - if (id.equals("minecraft:sponge")) return SPONGE_VARIANTS[damage]; - if (id.equals("minecraft:prismarine")) return PRISMARINE_VARIANTS[damage]; - - id = MAPPING.getOrDefault(id, id); - // if (Registry.ITEM.get(new Identifier(id)).equals(Items.AIR)) { - if (Registries.ITEM.get(new Identifier(id)).equals(Items.AIR)) { - String shortId = id.split(":")[1]; - // if (damage < BLOCK_COLORS.length && !Registry.ITEM.get(new Identifier("minecraft:" + BLOCK_COLORS[damage] + shortId)).equals(Items.AIR)) - if (damage < BLOCK_COLORS.length && !Registries.ITEM.get(new Identifier("minecraft:" + BLOCK_COLORS[damage] + shortId)).equals(Items.AIR)) - return "minecraft:" + BLOCK_COLORS[damage] + shortId; - // if (damage < TREE_VARIANTS.length && !Registry.ITEM.get(new Identifier("minecraft:" + TREE_VARIANTS[damage] + shortId)).equals(Items.AIR)) - if (damage < TREE_VARIANTS.length && !Registries.ITEM.get(new Identifier("minecraft:" + TREE_VARIANTS[damage] + shortId)).equals(Items.AIR)) - return "minecraft:" + TREE_VARIANTS[damage] + shortId; - - if (id.contains("wooden_")) return id.replaceFirst("wooden_", TREE_VARIANTS[damage]); - if (id.contains("minecraft:record")) return id.replaceFirst("minecraft:record", "minecraft:music_disc"); - } - return id; + return switch (id) { + //all the case are simple separate + case "minecraft:anvil" -> ANVIL_VARIANTS[damage]; + case "minecraft:coal" -> COAL_VARIANTS[damage]; + case "minecraft:cobblestone_wall" -> COBBLESTONE_WALL_VARIANTS[damage]; + case "minecraft:cooked_fish" -> COOKED_FISH_VARIANTS[damage]; + case "minecraft:dirt" -> DIRT_VARIANTS[damage]; + case "minecraft:double_plant" -> DOUBLE_PLANT_VARIANTS[damage]; + case "minecraft:dye" -> DYE_VARIANTS[damage]; + case "minecraft:fish" -> FISH_VARIANTS[damage]; + case "minecraft:golden_apple" -> GOLDEN_APPLE_VARIANTS[damage]; + case "minecraft:log" -> LOG_VARIANTS[damage]; + case "minecraft:log2" -> LOG2_VARIANTS[damage]; + case "minecraft:monster_egg" -> MONSTER_EGG_VARIANTS[damage]; + case "minecraft:prismarine" -> PRISMARINE_VARIANTS[damage]; + case "minecraft:quartz_block" -> QUARTZ_BLOCK_VARIANTS[damage]; + case "minecraft:red_flower" -> RED_FLOWER_VARIANTS[damage]; + case "minecraft:sand" -> SAND_VARIANTS[damage]; + case "minecraft:skull" -> SKULL_VARIANTS[damage]; + case "minecraft:sponge" -> SPONGE_VARIANTS[damage]; + case "minecraft:stone" -> STONE_VARIANTS[damage]; + case "minecraft:stone_slab" -> STONE_SLAB_VARIANTS[damage]; + case "minecraft:stonebrick" -> STONEBRICK_VARIANTS[damage]; + case "minecraft:tallgrass" -> TALLGRASS_VARIANTS[damage]; + //we use a Map from int to str instead of an array because numbers are not consecutive + case "minecraft:spawn_egg" -> SPAWN_EGG_VARIANTS.get(damage); + //when we use the generalized variant we need to replaceFirst + case "minecraft:sandstone", "minecraft:red_sandstone" -> id.replaceFirst(":", SANDSTONE_VARIANTS[damage]); + //to use the general color variants we need to reverse the order because Minecraft decided so for some reason + case "minecraft:banner" -> id.replaceFirst(":", COLOR_VARIANTS[15 - damage]); + case "minecraft:carpet", "minecraft:stained_glass", "minecraft:stained_glass_pane", "minecraft:wool" -> id.replaceFirst(":", COLOR_VARIANTS[damage]); + //for the terracotta we replace the whole name by the color and append "terracotta" at the end + case "minecraft:stained_hardened_clay" -> id.replaceFirst(":stained_hardened_clay", COLOR_VARIANTS[damage]) + "terracotta"; + //for the wooden slab we need to remove the "wooden_" prefix, but otherwise it's the same, so I just combined them anyway + case "minecraft:leaves", "minecraft:planks", "minecraft:sapling", "minecraft:wooden_slab" -> id.replaceFirst(":(?:wooden_)?", WOOD_VARIANTS[damage]); + //here we replace the 2 by nothing to remove it as it's not needed anymore + case "minecraft:leaves2" -> id.replaceFirst(":", WOOD_VARIANTS[damage + 4]).replaceFirst("2", ""); + //the default case is just a rename or no change + default -> RENAMED.getOrDefault(id, id); + }; } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java index 3a1f91d3..04dc6820 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemListWidget.java @@ -1,7 +1,7 @@ package me.xmrvizzy.skyblocker.skyblock.itemlist; import com.mojang.blaze3d.systems.RenderSystem; -import me.xmrvizzy.skyblocker.mixin.RecipeBookWidgetAccessor; +import me.xmrvizzy.skyblocker.mixin.accessor.RecipeBookWidgetAccessor; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; @@ -15,7 +15,7 @@ import net.minecraft.screen.AbstractRecipeScreenHandler; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -@Environment(value= EnvType.CLIENT) +@Environment(value = EnvType.CLIENT) public class ItemListWidget extends RecipeBookWidget implements Drawable, Selectable { private int parentWidth; private int parentHeight; @@ -23,10 +23,12 @@ public class ItemListWidget extends RecipeBookWidget implements Drawable, Select private TextFieldWidget searchField; private SearchResultsWidget results; - public ItemListWidget() { super(); } + public ItemListWidget() { + super(); + } public void updateSearchResult() { - this.results.updateSearchResult(((RecipeBookWidgetAccessor)this).getSearchText()); + this.results.updateSearchResult(((RecipeBookWidgetAccessor) this).getSearchText()); } @Override @@ -35,7 +37,7 @@ public class ItemListWidget extends RecipeBookWidget implements Drawable, Select this.parentWidth = parentWidth; this.parentHeight = parentHeight; this.leftOffset = narrow ? 0 : 86; - this.searchField = ((RecipeBookWidgetAccessor)this).getSearchField(); + this.searchField = ((RecipeBookWidgetAccessor) this).getSearchField(); int x = (this.parentWidth - 147) / 2 - this.leftOffset; int y = (this.parentHeight - 166) / 2; if (ItemRegistry.filesImported) { @@ -48,14 +50,14 @@ public class ItemListWidget extends RecipeBookWidget implements Drawable, Select public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (this.isOpen()) { MatrixStack matrices = context.getMatrices(); - matrices.push(); + matrices.push(); matrices.translate(0.0D, 0.0D, 100.0D); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - this.searchField = ((RecipeBookWidgetAccessor)this).getSearchField(); + this.searchField = ((RecipeBookWidgetAccessor) this).getSearchField(); int i = (this.parentWidth - 147) / 2 - this.leftOffset; int j = (this.parentHeight - 166) / 2; context.drawTexture(TEXTURE, i, j, 1, 1, 147, 166); - this.searchField = ((RecipeBookWidgetAccessor)this).getSearchField(); + this.searchField = ((RecipeBookWidgetAccessor) this).getSearchField(); if (!ItemRegistry.filesImported && !this.searchField.isFocused() && this.searchField.getText().isEmpty()) { Text hintText = (Text.literal("Loading...")).formatted(Formatting.ITALIC).formatted(Formatting.GRAY); @@ -66,7 +68,7 @@ public class ItemListWidget extends RecipeBookWidget implements Drawable, Select } else { this.searchField.render(context, mouseX, mouseY, delta); } - if (ItemRegistry.filesImported){ + if (ItemRegistry.filesImported) { if (results == null) { int x = (this.parentWidth - 147) / 2 - this.leftOffset; int y = (this.parentHeight - 166) / 2; @@ -88,15 +90,15 @@ public class ItemListWidget extends RecipeBookWidget implements Drawable, Select @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (this.isOpen() && !this.client.player.isSpectator() && ItemRegistry.filesImported && results != null) { - if (this.searchField != null && this.searchField.mouseClicked(mouseX, mouseY, button)) { + if (this.isOpen() && this.client.player != null && !this.client.player.isSpectator() && ItemRegistry.filesImported && this.searchField != null && results != null) { + if (this.searchField.mouseClicked(mouseX, mouseY, button)) { this.results.closeRecipeView(); this.searchField.setFocused(true); return true; - } else - this.searchField.setFocused(false); + } else { + this.searchField.setFocused(false); return this.results.mouseClicked(mouseX, mouseY, button); - } else - return false; + } + } else return false; } }
\ No newline at end of file diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNavButton.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNavButton.java index c02463a3..d9e97976 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNavButton.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/quicknav/QuickNavButton.java @@ -3,7 +3,7 @@ package me.xmrvizzy.skyblocker.skyblock.quicknav; import com.mojang.blaze3d.systems.RenderSystem; import me.xmrvizzy.skyblocker.SkyblockerMod; -import me.xmrvizzy.skyblocker.mixin.HandledScreenAccessor; +import me.xmrvizzy.skyblocker.mixin.accessor.HandledScreenAccessor; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; @@ -19,7 +19,6 @@ import net.minecraft.util.Identifier; @Environment(value=EnvType.CLIENT) public class QuickNavButton extends ClickableWidget { - private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); private static final Identifier BUTTON_TEXTURE = new Identifier("textures/gui/container/creative_inventory/tabs.png"); private final int index; @@ -42,12 +41,9 @@ public class QuickNavButton extends ClickableWidget { if (screen instanceof HandledScreen<?> handledScreen) { int x = ((HandledScreenAccessor)handledScreen).getX(); int y = ((HandledScreenAccessor)handledScreen).getY(); - int w = ((HandledScreenAccessor)handledScreen).getBackgroundWidth(); int h = ((HandledScreenAccessor)handledScreen).getBackgroundHeight(); if (h > 166) --h; // why is this even a thing - // this.x = x + this.index % 6 * 28 + 4; this.setX(x + this.index % 6 * 26 + 4); - // this.y = this.index < 6 ? y - 28 : y + h - 4; this.setY(this.index < 6 ? y - 26 : y + h - 4); this.u = 26; this.v = (index < 6 ? 0 : 64) + (toggled ? 32 : 0); diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java index fed34796..aa730c31 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/rift/HealingMelonIndicator.java @@ -12,12 +12,12 @@ import net.minecraft.util.Formatting; public class HealingMelonIndicator { private static final Title title = new Title("skyblocker.rift.healNow", Formatting.DARK_RED); - public static void updateHealth(MinecraftClient client) { + public static void updateHealth() { if (!SkyblockerConfig.get().slayer.vampireSlayer.enableHealingMelonIndicator || !Utils.isOnSkyblock() || !Utils.isInTheRift() || !Utils.getLocation().contains("Stillgore Château")) { TitleContainer.removeTitle(title); return; } - ClientPlayerEntity player = client.player; + ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player != null && player.getHealth() <= SkyblockerConfig.get().slayer.vampireSlayer.healingMelonHealthThreshold * 2F) { RenderHelper.displayInTitleContainerAndPlaySound(title); } else { 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/skyblock/tabhud/util/PlayerListMgr.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerListMgr.java index 5caa190c..30cc242e 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerListMgr.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerListMgr.java @@ -7,7 +7,7 @@ import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import me.xmrvizzy.skyblocker.mixin.PlayerListHudAccessor; +import me.xmrvizzy.skyblocker.mixin.accessor.PlayerListHudAccessor; import me.xmrvizzy.skyblocker.utils.Utils; import net.minecraft.client.MinecraftClient; diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerLocator.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerLocator.java index 9b24171a..deadaa7d 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerLocator.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/util/PlayerLocator.java @@ -26,6 +26,7 @@ public class PlayerLocator { GARDEN("garden"), INSTANCED("kuudra"), THE_RIFT("rift"), + DARK_AUCTION("dark_auction"), UNKNOWN("unknown"); public String internal; @@ -92,7 +93,9 @@ public class PlayerLocator { case "Instanced": return Location.INSTANCED; case "The Rift": - return Location.THE_RIFT; + return Location.THE_RIFT; + case "Dark Auction": + return Location.DARK_AUCTION; default: return Location.UNKNOWN; } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java new file mode 100644 index 00000000..7e44bc44 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java @@ -0,0 +1,37 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.MathHelper; + +public class CameraPositionWidget extends Widget { + private static final MutableText TITLE = Text.literal("Camera Pos").formatted(Formatting.DARK_PURPLE, + Formatting.BOLD); + private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); + + public CameraPositionWidget() { + super(TITLE, Formatting.DARK_PURPLE.getColorValue()); + } + + @Override + public void updateContent() { + double yaw = CLIENT.getCameraEntity().getYaw(); + double pitch = CLIENT.getCameraEntity().getPitch(); + + this.addComponent( + new PlainTextComponent(Text.literal("Yaw: " + roundToDecimalPlaces(MathHelper.wrapDegrees(yaw), 3)))); + this.addComponent(new PlainTextComponent( + Text.literal("Pitch: " + roundToDecimalPlaces(MathHelper.wrapDegrees(pitch), 3)))); + + } + + // https://stackoverflow.com/a/33889423 + private static double roundToDecimalPlaces(double value, int decimalPlaces) { + double shift = Math.pow(10, decimalPlaces); + + return Math.round(value * shift) / shift; + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenVisitorsWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenVisitorsWidget.java new file mode 100644 index 00000000..945fb17c --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/GardenVisitorsWidget.java @@ -0,0 +1,30 @@ +package me.xmrvizzy.skyblocker.skyblock.tabhud.widget; + +import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +public class GardenVisitorsWidget extends Widget { + private static final MutableText TITLE = Text.literal("Visitors").formatted(Formatting.DARK_GREEN, Formatting.BOLD); + + public GardenVisitorsWidget() { + super(TITLE, Formatting.DARK_GREEN.getColorValue()); + } + + @Override + public void updateContent() { + if (PlayerListMgr.textAt(54) == null) { + this.addComponent(new PlainTextComponent(Text.literal("No visitors!").formatted(Formatting.GRAY))); + return; + } + + for (int i = 54; i < 59; i++) { + String text = PlayerListMgr.strAt(i); + if (text != null) + this.addComponent(new PlainTextComponent(Text.literal(text))); + } + + } +} |