diff options
Diffstat (limited to 'src/main/java')
23 files changed, 427 insertions, 207 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java index 8d0406cb..8ddcd60e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java @@ -133,13 +133,14 @@ public class PetCache { return CACHED_PETS.containsKey(uuid) && CACHED_PETS.get(uuid).containsKey(profileId) ? CACHED_PETS.get(uuid).get(profileId) : null; } - public record PetInfo(String type, double exp, String tier, Optional<String> uuid, Optional<String> item) { + public record PetInfo(String type, double exp, String tier, Optional<String> uuid, Optional<String> item, Optional<String> skin) { public static final Codec<PetInfo> CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.STRING.fieldOf("type").forGetter(PetInfo::type), Codec.DOUBLE.fieldOf("exp").forGetter(PetInfo::exp), Codec.STRING.fieldOf("tier").forGetter(PetInfo::tier), Codec.STRING.optionalFieldOf("uuid").forGetter(PetInfo::uuid), - Codec.STRING.optionalFieldOf("heldItem").forGetter(PetInfo::item)) + Codec.STRING.optionalFieldOf("heldItem").forGetter(PetInfo::item), + Codec.STRING.optionalFieldOf("skin").forGetter(PetInfo::skin)) .apply(instance, PetInfo::new)); private static final Codec<Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, PetInfo>>> SERIALIZATION_CODEC = Codec.unboundedMap(Codec.STRING, Codec.unboundedMap(Codec.STRING, CODEC).xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java index d867a0e6..16f7eb28 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.skyblock.profileviewer; import com.mojang.blaze3d.systems.RenderSystem; -import de.hysky.skyblocker.skyblock.profileviewer.utils.SkullCreator; +import de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils; import de.hysky.skyblocker.skyblock.tabhud.util.Ico; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; @@ -22,9 +22,9 @@ public class ProfileViewerNavButton extends ClickableWidget { private static final Map<String, ItemStack> HEAD_ICON = Map.ofEntries( Map.entry("Skills", Ico.IRON_SWORD), - Map.entry("Slayers", SkullCreator.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzkzMzZkN2NjOTVjYmY2Njg5ZjVlOGM5NTQyOTRlYzhkMWVmYzQ5NGE0MDMxMzI1YmI0MjdiYzgxZDU2YTQ4NGQifX19")), + Map.entry("Slayers", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzkzMzZkN2NjOTVjYmY2Njg5ZjVlOGM5NTQyOTRlYzhkMWVmYzQ5NGE0MDMxMzI1YmI0MjdiYzgxZDU2YTQ4NGQifX19")), Map.entry("Pets", Ico.BONE), - Map.entry("Dungeons", SkullCreator.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzliNTY4OTViOTY1OTg5NmFkNjQ3ZjU4NTk5MjM4YWY1MzJkNDZkYjljMWIwMzg5YjhiYmViNzA5OTlkYWIzM2QifX19")), + Map.entry("Dungeons", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzliNTY4OTViOTY1OTg5NmFkNjQ3ZjU4NTk5MjM4YWY1MzJkNDZkYjljMWIwMzg5YjhiYmViNzA5OTlkYWIzM2QifX19")), Map.entry("Inventories", Ico.E_CHEST), Map.entry("Collections", Ico.PAINTING) ); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java index 1d0b21ca..f74526a4 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java @@ -27,6 +27,7 @@ import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.network.OtherClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.util.SkinTextures; +import net.minecraft.command.CommandSource; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerModelPart; import net.minecraft.text.Text; @@ -55,6 +56,7 @@ public class ProfileViewerScreen extends Screen { private String playerName; private JsonObject hypixelProfile; private JsonObject playerProfile; + private boolean profileNotFound = false; private int activePage = 0; private static final String[] PAGE_NAMES = {"Skills", "Slayers", "Dungeons", "Inventories", "Collections"}; @@ -73,6 +75,8 @@ public class ProfileViewerScreen extends Screen { } private void initialisePagesAndWidgets() { + if (profileNotFound) return; + textWidget = new ProfileViewerTextWidget(hypixelProfile, playerProfile); CompletableFuture<Void> skillsFuture = CompletableFuture.runAsync(() -> profileViewerPages[0] = new SkillsPage(hypixelProfile, playerProfile)); @@ -105,6 +109,7 @@ public class ProfileViewerScreen extends Screen { button.render(context, mouseX, mouseY, delta); } + if (textWidget != null) textWidget.render(context, textRenderer, rootX + 8, rootY + 120); drawPlayerEntity(context, playerName != null ? playerName : "Loading...", rootX, rootY, mouseX, mouseY); @@ -112,7 +117,7 @@ public class ProfileViewerScreen extends Screen { profileViewerPages[activePage].markWidgetsAsVisible(); profileViewerPages[activePage].render(context, mouseX, mouseY, delta, rootX + 93, rootY + 7); } else { - context.drawText(textRenderer, "Loading...", rootX + 180, rootY + 80, Color.WHITE.getRGB(), true); + context.drawText(textRenderer, profileNotFound ? "No Profile" : "Loading...", rootX + 180, rootY + 80, Color.WHITE.getRGB(), true); } } @@ -120,18 +125,24 @@ public class ProfileViewerScreen extends Screen { if (entity != null) drawEntity(context, rootX + 9, rootY + 16, rootX + 89, rootY + 124, 42, 0.0625F, mouseX, mouseY, entity); context.drawCenteredTextWithShadow(textRenderer, username.length() > 15 ? username.substring(0, 15) : username, rootX + 47, rootY + 14, Color.WHITE.getRGB()); - } private CompletableFuture<Void> fetchPlayerData(String username) { CompletableFuture<Void> profileFuture = ProfileUtils.fetchFullProfile(username).thenAccept(profiles -> { - this.hypixelProfile = profiles.getAsJsonArray("profiles").asList().stream() - .map(JsonElement::getAsJsonObject) - .filter(profile -> profile.getAsJsonPrimitive("selected").getAsBoolean()) - .findFirst() - .orElseThrow(() -> new IllegalStateException("No selected profile found!")); - - this.playerProfile = hypixelProfile.getAsJsonObject("members").get(ApiUtils.name2Uuid(username)).getAsJsonObject(); + try { + Optional<JsonObject> selectedProfile = profiles.getAsJsonArray("profiles").asList().stream() + .map(JsonElement::getAsJsonObject) + .filter(profile -> profile.getAsJsonPrimitive("selected").getAsBoolean()) + .findFirst(); + + if (selectedProfile.isPresent()) { + this.hypixelProfile = selectedProfile.get(); + this.playerProfile = hypixelProfile.getAsJsonObject("members").get(ApiUtils.name2Uuid(username)).getAsJsonObject(); + } + } catch (Exception e) { + this.profileNotFound = true; + LOGGER.warn("[Skyblocker Profile Viewer] Error while looking for profile", e); + } }); CompletableFuture<Void> minecraftProfileFuture = SkullBlockEntityAccessor.invokeFetchProfileByName(username).thenAccept(profile -> { @@ -156,12 +167,14 @@ public class ProfileViewerScreen extends Screen { entity.setCustomNameVisible(false); }).exceptionally(ex -> { this.playerName = "User not found"; + this.profileNotFound = true; return null; }); return CompletableFuture.allOf(profileFuture, minecraftProfileFuture); } + public void onNavButtonClick(ProfileViewerNavButton clickedButton) { if (profileViewerPages[activePage] != null) profileViewerPages[activePage].markWidgetsAsInvisible(); for (ProfileViewerNavButton button : profileViewerNavButtons) { @@ -188,10 +201,11 @@ public class ProfileViewerScreen extends Screen { ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { LiteralArgumentBuilder<FabricClientCommandSource> literalArgumentBuilder = ClientCommandManager.literal("pv") - .then(ClientCommandManager.argument("username", StringArgumentType.string()) - .executes(Scheduler.queueOpenScreenFactoryCommand(context -> new ProfileViewerScreen(StringArgumentType.getString(context, "username")))) - ) - .executes(Scheduler.queueOpenScreenCommand(() -> new ProfileViewerScreen(MinecraftClient.getInstance().getSession().getUsername()))); + .then(ClientCommandManager.argument("username", StringArgumentType.string()) + .suggests((source, builder) -> CommandSource.suggestMatching(getPlayerSuggestions(source.getSource()), builder)) + .executes(Scheduler.queueOpenScreenFactoryCommand(context -> new ProfileViewerScreen(StringArgumentType.getString(context, "username")))) + ) + .executes(Scheduler.queueOpenScreenCommand(() -> new ProfileViewerScreen(MinecraftClient.getInstance().getSession().getUsername()))); dispatcher.register(literalArgumentBuilder); dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE).then(literalArgumentBuilder)); }); @@ -227,4 +241,11 @@ public class ProfileViewerScreen extends Screen { } return Collections.emptyMap(); } + + /** + * Ensures that "dummy" players aren't included in command suggestions + */ + private static String[] getPlayerSuggestions(FabricClientCommandSource source) { + return source.getPlayerNames().stream().filter(playerName -> playerName.matches("[A-Za-z0-9_]+")).toArray(String[]::new); + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerTextWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerTextWidget.java index 4ee2dbba..58c238f8 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerTextWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerTextWidget.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.skyblock.profileviewer; import com.google.gson.JsonObject; +import de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils; import de.hysky.skyblocker.skyblock.tabhud.util.Ico; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -36,20 +37,8 @@ public class ProfileViewerTextWidget { context.drawText(textRenderer, "§n"+PROFILE_NAME, root_x + 14, root_y + 3, Colors.WHITE, true); context.drawText(textRenderer, "§aLevel:§r " + SKYBLOCK_LEVEL, root_x + 2, root_y + 6 + ROW_GAP, Colors.WHITE, true); - context.drawText(textRenderer, "§6Purse:§r " + formatCoins(PURSE), root_x + 2, root_y + 6 + ROW_GAP * 2, Colors.WHITE, true); - context.drawText(textRenderer, "§6Bank:§r " + formatCoins(BANK), root_x + 2, root_y + 6 + ROW_GAP * 3, Colors.WHITE, true); + context.drawText(textRenderer, "§6Purse:§r " + ProfileViewerUtils.numLetterFormat(PURSE), root_x + 2, root_y + 6 + ROW_GAP * 2, Colors.WHITE, true); + context.drawText(textRenderer, "§6Bank:§r " + ProfileViewerUtils.numLetterFormat(BANK), root_x + 2, root_y + 6 + ROW_GAP * 3, Colors.WHITE, true); context.drawText(textRenderer, "§6NW:§r " + "Soon™", root_x + 2, root_y + 6 + ROW_GAP * 4, Colors.WHITE, true ); } - - private String formatCoins(double amount) { - if (amount >= 1_000_000_000) { - return String.format("%.4gB", amount / 1_000_000_000); - } else if (amount >= 1_000_000) { - return String.format("%.4gM", amount / 1_000_000); - } else if (amount >= 1_000) { - return String.format("%.4gK", amount / 1_000); - } else { - return String.valueOf((int)(amount)); - } - } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/collections/GenericCategory.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/collections/GenericCategory.java index ef26332e..306fe279 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/collections/GenericCategory.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/collections/GenericCategory.java @@ -5,13 +5,12 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerPage; import de.hysky.skyblocker.skyblock.tabhud.util.Ico; -import de.hysky.skyblocker.utils.NEURepoManager; -import io.github.moulberry.repo.data.NEUItem; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LoreComponent; +import net.minecraft.component.type.NbtComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.tooltip.TooltipType; @@ -21,17 +20,18 @@ import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import java.awt.*; -import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; -import java.util.*; +import java.util.Map; import static de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerScreen.fetchCollectionsData; +import static de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils.COMMA_FORMATTER; public class GenericCategory implements ProfileViewerPage { private final String category; private final LinkedList<ItemStack> collections = new LinkedList<>(); private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - private static final NumberFormat FORMATTER = NumberFormat.getInstance(Locale.US); private static final Identifier BUTTON_TEXTURE = Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/profile_viewer/button_icon_toggled.png"); private static final int COLUMN_GAP = 26; private static final int ROW_GAP = 34; @@ -61,40 +61,50 @@ public class GenericCategory implements ProfileViewerPage { JsonObject playerCollection = pProfile.getAsJsonObject("collection"); for (String collection : collectionsMap.get(this.category)) { - Map<String, NEUItem> items = NEURepoManager.NEU_REPO.getItems().getItems(); - ItemStack itemStack = items.values().stream() - .filter(i -> Formatting.strip(i.getSkyblockItemId()).equals(ICON_TRANSLATION.getOrDefault(collection, collection).replace(':', '-'))) - .findFirst() - .map(NEUItem::getSkyblockItemId) - .map(ItemRepository::getItemStack) - .map(ItemStack::copy) - .orElse(Ico.BARRIER.copy()); + ItemStack itemStack = ItemRepository.getItemStack(ICON_TRANSLATION.getOrDefault(collection, collection).replace(':', '-')); + itemStack = itemStack == null ? Ico.BARRIER.copy() : itemStack.copy(); + + if (itemStack.getItem().getName().getString().equals("Barrier")) { + itemStack.set(DataComponentTypes.CUSTOM_NAME, Text.of(collection)); + System.out.println(collection); + System.out.println(this.category); + } + + Style style = Style.EMPTY.withColor(Formatting.WHITE).withItalic(false); + itemStack.set(DataComponentTypes.CUSTOM_NAME, Text.literal(Formatting.strip(itemStack.getComponents().get(DataComponentTypes.CUSTOM_NAME).getString())).setStyle(style)); - if (itemStack.getItem().getName().getString().equals("Barrier")) itemStack.set(DataComponentTypes.ITEM_NAME, Text.of(collection)); int personalColl = playerCollection != null && playerCollection.has(collection) ? playerCollection.get(collection).getAsInt() : 0; - int coopColl = 0; + int totalCollection = 0; for (String member : hProfile.get("members").getAsJsonObject().keySet()) { if (!hProfile.getAsJsonObject("members").getAsJsonObject(member).has("collection")) continue; JsonObject memberColl = hProfile.getAsJsonObject("members").getAsJsonObject(member).getAsJsonObject("collection"); - coopColl += memberColl.has(collection) ? memberColl.get(collection).getAsInt() : 0; + totalCollection += memberColl.has(collection) ? memberColl.get(collection).getAsInt() : 0; } - int collectionTier = calculateTier(coopColl, tierRequirementsMap.get(collection)); + int collectionTier = calculateTier(totalCollection, tierRequirementsMap.get(collection)); List<Integer> tierRequirements = tierRequirementsMap.get(collection); List<Text> lore = new ArrayList<>(); - Style style = Style.EMPTY.withItalic(false); - lore.add(Text.literal("Collection: " + FORMATTER.format(personalColl)).setStyle(style).formatted(Formatting.YELLOW)); + lore.add(Text.literal("Collection Item").setStyle(style).formatted(Formatting.DARK_GRAY)); + lore.add(Text.empty()); + if (hProfile.get("members").getAsJsonObject().keySet().size() > 1) { - lore.add(Text.literal("Co-op Collection: " + FORMATTER.format(coopColl)).setStyle(style).formatted(Formatting.AQUA)); + lore.add(Text.literal("Personal: " + COMMA_FORMATTER.format(personalColl)).setStyle(style).formatted(Formatting.GOLD)); + lore.add(Text.literal("Co-op Collection: " + COMMA_FORMATTER.format(totalCollection-personalColl)).setStyle(style).formatted(Formatting.AQUA)); } - lore.add(Text.literal("Collection Tier: " + collectionTier).setStyle(style).formatted(Formatting.LIGHT_PURPLE)); - itemStack.set(DataComponentTypes.LORE, new LoreComponent(lore)); + lore.add(Text.literal("Collection: " + COMMA_FORMATTER.format(totalCollection)).setStyle(style).formatted(Formatting.YELLOW)); + + lore.add(Text.empty()); + lore.add(Text.literal("Collection Tier: " + collectionTier + "/" + tierRequirements.size()).setStyle(style).formatted(Formatting.LIGHT_PURPLE)); if (collectionTier == tierRequirements.size()) itemStack.set(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true); + itemStack.set(DataComponentTypes.LORE, new LoreComponent(lore)); + + itemStack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT); + collections.add(itemStack); } } @@ -116,11 +126,16 @@ public class GenericCategory implements ProfileViewerPage { ItemStack itemStack = collections.get(i); List<Text> lore = itemStack.getOrDefault(DataComponentTypes.LORE, LoreComponent.DEFAULT).lines(); for (Text text : lore) { - if (!text.getString().startsWith("Collection Tier: ")) continue; - int cTier = Integer.parseInt(text.getString().substring("Collection Tier: ".length())); - Color colour = Boolean.TRUE.equals(itemStack.get(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE)) ? Color.MAGENTA : Color.darkGray; - context.drawText(textRenderer, Text.literal(toRomanNumerals(cTier)), x + 9 - (textRenderer.getWidth(toRomanNumerals(cTier)) / 2), y + 21, colour.getRGB(), false); - break; + if (text.getString().startsWith("Collection Tier: ")) { + String tierText = text.getString().substring("Collection Tier: ".length()); + if (tierText.contains("/")) { + String[] parts = tierText.split("/"); + int cTier = Integer.parseInt(parts[0].trim()); + Color colour = itemStack.hasGlint() ? Color.MAGENTA : Color.darkGray; + context.drawText(textRenderer, Text.literal(toRomanNumerals(cTier)), x + 9 - (textRenderer.getWidth(toRomanNumerals(cTier)) / 2), y + 21, colour.getRGB(), false); + } + break; + } } if (mouseX > x && mouseX < x + 16 && mouseY > y && mouseY < y + 16) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonClassWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonClassWidget.java index 3b847b1b..37953a2b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonClassWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonClassWidget.java @@ -3,15 +3,20 @@ package de.hysky.skyblocker.skyblock.profileviewer.dungeons; import com.google.gson.JsonObject; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.profileviewer.utils.LevelFinder; +import de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils; import de.hysky.skyblocker.skyblock.tabhud.util.Ico; import de.hysky.skyblocker.utils.render.RenderHelper; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import java.awt.*; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public class DungeonClassWidget { @@ -48,7 +53,7 @@ public class DungeonClassWidget { } } - public void render(DrawContext context, int x, int y) { + public void render(DrawContext context, int mouseX, int mouseY, int x, int y) { context.drawTexture(TEXTURE, x, y, 0, 0, 109, 26, 109, 26); context.drawItem(stack, x + 3, y + 5); if (active) context.drawTexture(ACTIVE_TEXTURE, x + 3, y + 5, 0, 0, 16, 16, 16, 16); @@ -57,6 +62,12 @@ public class DungeonClassWidget { Color fillColor = classLevel.level >= CLASS_CAP ? Color.MAGENTA : Color.GREEN; context.drawGuiTexture(BAR_BACK, x + 30, y + 15, 75, 6); RenderHelper.renderNineSliceColored(context, BAR_FILL, x + 30, y + 15, (int) (75 * classLevel.fill), 6, fillColor); - } + if (mouseX > x + 30 && mouseX < x + 105 && mouseY > y + 12 && mouseY < y + 22){ + List<Text> tooltipText = new ArrayList<>(); + tooltipText.add(Text.literal(this.className).formatted(Formatting.GREEN)); + tooltipText.add(Text.literal("XP: " + ProfileViewerUtils.COMMA_FORMATTER.format(this.classLevel.xp)).formatted(Formatting.GOLD)); + context.drawTooltip(textRenderer, tooltipText, mouseX, mouseY); + } + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonFloorRunsWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonFloorRunsWidget.java index 7c9206c0..b592266a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonFloorRunsWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonFloorRunsWidget.java @@ -11,6 +11,8 @@ import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import java.awt.*; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public class DungeonFloorRunsWidget { @@ -26,8 +28,7 @@ public class DungeonFloorRunsWidget { } catch (Exception ignored) {} } - // TODO: Hovering on each floor should probably showcase best run times in a tooltip - public void render(DrawContext context, int x, int y) { + public void render(DrawContext context, int mouseX ,int mouseY, int x, int y) { context.drawTexture(TEXTURE, x, y, 0, 0, 109, 110, 109, 110); context.drawText(textRenderer, Text.literal("Floor Runs").formatted(Formatting.BOLD), x + 6, y + 4, Color.WHITE.getRGB(), true); @@ -36,12 +37,33 @@ public class DungeonFloorRunsWidget { for (String dungeon : DUNGEONS) { JsonObject dungeonData; try { - dungeonData = dungeonsStats.getAsJsonObject(dungeon).getAsJsonObject(dungeon.equals("catacombs") ? "times_played" : "tier_completions"); + dungeonData = dungeonsStats.getAsJsonObject(dungeon).getAsJsonObject("tier_completions"); for (Map.Entry<String, JsonElement> entry : dungeonData.entrySet()) { if (entry.getKey().equals("total")) continue; String textToRender = String.format((dungeon.equals("catacombs") ? "§aF" : "§cM") + "%s§r %s", entry.getKey(), entry.getValue().getAsInt()); context.drawText(textRenderer, textToRender, columnX + 2, elementY + 2, Color.WHITE.getRGB(), true); + if (!entry.getKey().equals("0") && mouseX >= columnX && mouseX <= columnX + 40 && mouseY >= elementY && mouseY <= elementY + 9) { + List<Text> tooltipText = new ArrayList<>(); + tooltipText.add(Text.literal("Personal Bests").formatted(Formatting.BOLD, Formatting.LIGHT_PURPLE)); + + JsonObject fastestTimes = dungeonsStats.getAsJsonObject(dungeon).getAsJsonObject("fastest_time_s"); + if (fastestTimes != null && fastestTimes.has(entry.getKey())) { + tooltipText.add(Text.literal("S Run: " + formatTime(fastestTimes.get(entry.getKey()).getAsLong())).formatted(Formatting.GOLD)); + } + + fastestTimes = dungeonsStats.getAsJsonObject(dungeon).getAsJsonObject("fastest_time_s_plus"); + if (fastestTimes != null && fastestTimes.has(entry.getKey())) { + tooltipText.add(Text.literal("S+ Run: " + formatTime(fastestTimes.get(entry.getKey()).getAsLong())).formatted(Formatting.GOLD)); + } + + fastestTimes = dungeonsStats.getAsJsonObject(dungeon).getAsJsonObject("fastest_time"); + if (fastestTimes != null && fastestTimes.has(entry.getKey()) && tooltipText.size() == 1) { + tooltipText.add(Text.literal("Completion: " + formatTime(fastestTimes.get(entry.getKey()).getAsLong())).formatted(Formatting.GOLD)); + } + + context.drawTooltip(textRenderer, tooltipText, mouseX, mouseY); + } elementY += 11; } @@ -52,4 +74,11 @@ public class DungeonFloorRunsWidget { } } } + + private String formatTime(long milliseconds) { + long seconds = milliseconds / 1000; + long minutes = seconds / 60; + seconds %= 60; + return String.format("%2d:%02d", minutes, seconds); + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonMiscStatsWidgets.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonMiscStatsWidgets.java index 679cc575..780eec24 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonMiscStatsWidgets.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonMiscStatsWidgets.java @@ -31,7 +31,7 @@ public class DungeonMiscStatsWidgets { secrets = DUNGEONS_DATA.get("secrets").getAsInt(); for (String dungeon : DUNGEONS) { - JsonObject dungeonData = DUNGEONS_DATA.getAsJsonObject("dungeon_types").getAsJsonObject(dungeon).getAsJsonObject(dungeon.equals("catacombs") ? "times_played" : "tier_completions"); + JsonObject dungeonData = DUNGEONS_DATA.getAsJsonObject("dungeon_types").getAsJsonObject(dungeon).getAsJsonObject("tier_completions"); int runs = 0; for (Map.Entry<String, JsonElement> entry : dungeonData.entrySet()) { String key = entry.getKey(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonsPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonsPage.java index b1398661..e0051c88 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonsPage.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonsPage.java @@ -30,10 +30,10 @@ public class DungeonsPage implements ProfileViewerPage { public void render(DrawContext context, int mouseX, int mouseY, float delta, int rootX, int rootY) { dungeonHeaderWidget.render(context, rootX, rootY); - dungeonFloorRunsWidget.render(context, rootX + 113, rootY + 56); + dungeonFloorRunsWidget.render(context, mouseX, mouseY, rootX + 113, rootY + 56); dungeonMiscStatsWidgets.render(context, rootX + 113, rootY); for (int i = 0; i < dungeonClassWidgetsList.size(); i++) { - dungeonClassWidgetsList.get(i).render(context, rootX, rootY + 28 + i * 28); + dungeonClassWidgetsList.get(i).render(context, mouseX, mouseY, rootX, rootY + 28 + i * 28); } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java index a2f7d9d6..126c55ec 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java @@ -1,6 +1,8 @@ package de.hysky.skyblocker.skyblock.profileviewer.inventory; import com.google.gson.JsonObject; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; import de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerPage; import de.hysky.skyblocker.skyblock.profileviewer.inventory.itemLoaders.ItemLoader; import it.unimi.dsi.fastutil.ints.IntIntPair; @@ -8,6 +10,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.resource.language.I18n; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.tooltip.TooltipType; @@ -16,6 +19,7 @@ import net.minecraft.util.Identifier; import java.awt.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class Inventory implements ProfileViewerPage { @@ -49,7 +53,7 @@ public class Inventory implements ProfileViewerPage { context.drawTexture(TEXTURE, rootX, rootYAdjusted + dimensions.leftInt() * 18 + 17, 0, 215, dimensions.rightInt() * 18 + 7, 7); context.drawTexture(TEXTURE, rootX + dimensions.rightInt() * 18 + 7, rootYAdjusted + dimensions.leftInt() * 18 + 17, 169, 215, 7, 7); - context.drawText(textRenderer, containerName, rootX + 7, rootYAdjusted + 7, Color.DARK_GRAY.getRGB(), false); + context.drawText(textRenderer, I18n.translate("skyblocker.profileviewer.inventory." + containerName), rootX + 7, rootYAdjusted + 7, Color.DARK_GRAY.getRGB(), false); if (containerList.size() > itemsPerPage) { previousPage.setX(rootX + 44); @@ -65,6 +69,7 @@ public class Inventory implements ProfileViewerPage { int startIndex = activePage * itemsPerPage; int endIndex = Math.min(startIndex + itemsPerPage, containerList.size()); + List<Text> tooltip = Collections.emptyList(); for (int i = 0; i < endIndex - startIndex; i++) { if (containerList.get(startIndex + i) == ItemStack.EMPTY) continue; int column = i % dimensions.rightInt(); @@ -72,14 +77,20 @@ public class Inventory implements ProfileViewerPage { |
