diff options
Diffstat (limited to 'src/main')
26 files changed, 504 insertions, 254 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/chocolatefactory/EggFinder.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java index 42883c4f..620da37c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java @@ -24,7 +24,6 @@ import net.minecraft.text.ClickEvent; import net.minecraft.text.HoverEvent; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import org.apache.commons.lang3.mutable.MutableObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,6 +33,7 @@ import java.util.regex.Pattern; public class EggFinder { private static final Pattern eggFoundPattern = Pattern.compile("^(?:HOPPITY'S HUNT You found a Chocolate|You have already collected this Chocolate) (Breakfast|Lunch|Dinner)"); + private static final Pattern newEggPattern = Pattern.compile("^HOPPITY'S HUNT A Chocolate (Breakfast|Lunch|Dinner) Egg has appeared!$"); private static final Logger logger = LoggerFactory.getLogger("Skyblocker Egg Finder"); private static final LinkedList<ArmorStandEntity> armorStandQueue = new LinkedList<>(); private static final Location[] possibleLocations = {Location.CRIMSON_ISLE, Location.CRYSTAL_HOLLOWS, Location.DUNGEON_HUB, Location.DWARVEN_MINES, Location.HUB, Location.THE_END, Location.THE_PARK, Location.GOLD_MINE, Location.DEEP_CAVERNS, Location.SPIDERS_DEN, Location.THE_FARMING_ISLAND}; @@ -96,7 +96,7 @@ public class EggFinder { for (ItemStack itemStack : armorStand.getArmorItems()) { ItemUtils.getHeadTextureOptional(itemStack).ifPresent(texture -> { for (EggType type : EggType.entries) { //Compare blockPos rather than entity to avoid incorrect matches when the entity just moves rather than a new one being spawned elsewhere - if (texture.equals(type.texture) && (type.egg.getValue() == null || !type.egg.getValue().entity.getBlockPos().equals(armorStand.getBlockPos()))) { + if (texture.equals(type.texture) && (type.egg == null || !type.egg.entity.getBlockPos().equals(armorStand.getBlockPos()))) { handleFoundEgg(armorStand, type); return; } @@ -109,27 +109,29 @@ public class EggFinder { if (!SkyblockerConfigManager.get().helpers.chocolateFactory.enableEggFinder) return; isLocationCorrect = false; for (EggType type : EggType.entries) { - type.egg.setValue(null); + type.egg = null; } } private static void handleFoundEgg(ArmorStandEntity entity, EggType eggType) { - eggType.egg.setValue(new Egg(entity, new Waypoint(entity.getBlockPos().up(2), SkyblockerConfigManager.get().helpers.chocolateFactory.waypointType, ColorUtils.getFloatComponents(eggType.color)))); - - if (!SkyblockerConfigManager.get().helpers.chocolateFactory.sendEggFoundMessages) return; - MinecraftClient.getInstance().player.sendMessage(Constants.PREFIX.get() - .append("Found a ") - .append(Text.literal("Chocolate " + eggType + " Egg") - .withColor(eggType.color)) - .append(" at " + entity.getBlockPos().up(2).toShortString() + "!") - .styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/skyblocker eggFinder shareLocation " + entity.getBlockX() + " " + (entity.getBlockY() + 2) + " " + entity.getBlockZ() + " " + eggType)) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to share the location in chat!").formatted(Formatting.GREEN))))); + eggType.egg = new Egg(entity, new Waypoint(entity.getBlockPos().up(2), SkyblockerConfigManager.get().helpers.chocolateFactory.waypointType, ColorUtils.getFloatComponents(eggType.color))); + + if (!SkyblockerConfigManager.get().helpers.chocolateFactory.sendEggFoundMessages || System.currentTimeMillis() - eggType.messageLastSent < 1000) return; + eggType.messageLastSent = System.currentTimeMillis(); + MinecraftClient.getInstance().player.sendMessage( + Constants.PREFIX.get() + .append("Found a ") + .append(Text.literal("Chocolate " + eggType + " Egg") + .withColor(eggType.color)) + .append(" at " + entity.getBlockPos().up(2).toShortString() + "!") + .styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/skyblocker eggFinder shareLocation " + entity.getBlockX() + " " + (entity.getBlockY() + 2) + " " + entity.getBlockZ() + " " + eggType)) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to share the location in chat!").formatted(Formatting.GREEN))))); } private static void renderWaypoints(WorldRenderContext context) { if (!SkyblockerConfigManager.get().helpers.chocolateFactory.enableEggFinder) return; for (EggType type : EggType.entries) { - Egg egg = type.egg.getValue(); + Egg egg = type.egg; if (egg != null && egg.waypoint.shouldRender()) egg.waypoint.render(context); } } @@ -139,30 +141,47 @@ public class EggFinder { Matcher matcher = eggFoundPattern.matcher(text.getString()); if (matcher.find()) { try { - Egg egg = EggType.valueOf(matcher.group(1).toUpperCase()).egg.getValue(); + Egg egg = EggType.valueOf(matcher.group(1).toUpperCase()).egg; if (egg != null) egg.waypoint.setFound(); } catch (IllegalArgumentException e) { logger.error("[Skyblocker Egg Finder] Failed to find egg type for egg found message. Tried to match against: " + matcher.group(0), e); } } + + matcher.usePattern(newEggPattern); + if (matcher.find()) { + try { + EggType.valueOf(matcher.group(1).toUpperCase()).egg = null; + } catch (IllegalArgumentException e) { + logger.error("[Skyblocker Egg Finder] Failed to find egg type for egg spawn message. Tried to match against: " + matcher.group(0), e); + } + } } - record Egg(ArmorStandEntity entity, Waypoint waypoint) { } + record Egg(ArmorStandEntity entity, Waypoint waypoint) {} + @SuppressWarnings("DataFlowIssue") //Removes that pesky "unboxing of Integer might cause NPE" warning when we already know it's not null enum EggType { - LUNCH(new MutableObject<>(), Formatting.BLUE.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjU2ODExMiwKICAicHJvZmlsZUlkIiA6ICI3NzUwYzFhNTM5M2Q0ZWQ0Yjc2NmQ4ZGUwOWY4MjU0NiIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWVkcmVsIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdhZTZkMmQzMWQ4MTY3YmNhZjk1MjkzYjY4YTRhY2Q4NzJkNjZlNzUxZGI1YTM0ZjJjYmM2NzY2YTAzNTZkMGEiCiAgICB9CiAgfQp9"), - DINNER(new MutableObject<>(), Formatting.GREEN.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY0OTcwMSwKICAicHJvZmlsZUlkIiA6ICI3NGEwMzQxNWY1OTI0ZTA4YjMyMGM2MmU1NGE3ZjJhYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZXp6aXIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTVlMzYxNjU4MTlmZDI4NTBmOTg1NTJlZGNkNzYzZmY5ODYzMTMxMTkyODNjMTI2YWNlMGM0Y2M0OTVlNzZhOCIKICAgIH0KICB9Cn0"), - BREAKFAST(new MutableObject<>(), Formatting.GOLD.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY3MzE0OSwKICAicHJvZmlsZUlkIiA6ICJiN2I4ZTlhZjEwZGE0NjFmOTY2YTQxM2RmOWJiM2U4OCIsCiAgInByb2ZpbGVOYW1lIiA6ICJBbmFiYW5hbmFZZzciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQ5MzMzZDg1YjhhMzE1ZDAzMzZlYjJkZjM3ZDhhNzE0Y2EyNGM1MWI4YzYwNzRmMWI1YjkyN2RlYjUxNmMyNCIKICAgIH0KICB9Cn0"); + LUNCH(Formatting.BLUE.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjU2ODExMiwKICAicHJvZmlsZUlkIiA6ICI3NzUwYzFhNTM5M2Q0ZWQ0Yjc2NmQ4ZGUwOWY4MjU0NiIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWVkcmVsIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdhZTZkMmQzMWQ4MTY3YmNhZjk1MjkzYjY4YTRhY2Q4NzJkNjZlNzUxZGI1YTM0ZjJjYmM2NzY2YTAzNTZkMGEiCiAgICB9CiAgfQp9"), + DINNER(Formatting.GREEN.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY0OTcwMSwKICAicHJvZmlsZUlkIiA6ICI3NGEwMzQxNWY1OTI0ZTA4YjMyMGM2MmU1NGE3ZjJhYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZXp6aXIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTVlMzYxNjU4MTlmZDI4NTBmOTg1NTJlZGNkNzYzZmY5ODYzMTMxMTkyODNjMTI2YWNlMGM0Y2M0OTVlNzZhOCIKICAgIH0KICB9Cn0"), + BREAKFAST(Formatting.GOLD.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY3MzE0OSwKICAicHJvZmlsZUlkIiA6ICJiN2I4ZTlhZjEwZGE0NjFmOTY2YTQxM2RmOWJiM2U4OCIsCiAgInByb2ZpbGVOYW1lIiA6ICJBbmFiYW5hbmFZZzciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQ5MzMzZDg1YjhhMzE1ZDAzMzZlYjJkZjM3ZDhhNzE0Y2EyNGM1MWI4YzYwNzRmMWI1YjkyN2RlYjUxNmMyNCIKICAgIH0KICB9Cn0"); - public final MutableObject<Egg> egg; + private Egg egg = null; public final int color; public final String texture; + /* + When a new egg spawns in the player's range, the order of packets/messages goes like this: + set_equipment -> new egg message -> set_entity_data + We have to set the egg to null to prevent the highlight from staying where it was before the new egg spawned, + and doing so causes the found message to get sent twice. This is the reason for the existence of this field, so that we can not send the 2nd message. + This doesn't fix the field being set twice, but that's not an issue anyway. It'd be much harder to fix the highlight issue mentioned above if it wasn't being set twice. + */ + private long messageLastSent = 0; //This is to not create an array each time we iterate over the values public static final ObjectImmutableList<EggType> entries = ObjectImmutableList.of(BREAKFAST, LUNCH, DINNER); - EggType(MutableObject<Egg> egg, int color, String texture) { - this.egg = egg; + EggType(int color, String texture) { this.color = color; this.texture = texture; } 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 { int x = rootX + 8 + column * 18; int y = rootYAdjusted + 18 + row * 18; + + if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) { + ItemRarityBackgrounds.tryDraw(containerList.get(startIndex + i), context, x, y); + } + context.drawItem(containerList.get(startIndex + i), x, y); context.drawItemInSlot(textRenderer, containerList.get(startIndex + i), x, y); - if (mouseX > x && mouseX < x + 16 && mouseY > y && mouseY < y + 16) { - List<Text> tooltip = containerList.get(startIndex + i).getTooltip(Item.TooltipContext.DEFAULT, MinecraftClient.getInstance().player, TooltipType.BASIC); - context.drawTooltip(textRenderer, tooltip, mouseX, mouseY); + if (mouseX > x -1 && mouseX < x + 16 && mouseY > y - 1 && mouseY < y + 16) { + tooltip = containerList.get(startIndex + i).getTooltip(Item.TooltipContext.DEFAULT, MinecraftClient.getInstance().player, TooltipType.BASIC); } } + + if (!tooltip.isEmpty()) context.drawTooltip(textRenderer, tooltip, mouseX, mouseY); } public void nextPage() { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/InventoryPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/InventoryPage.java index 8b0cbefc..6aa92ef6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/InventoryPage.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/InventoryPage.java @@ -6,7 +6,7 @@ import de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerScreen; import de.hysky.skyblocker.skyblock.profileviewer.inventory.itemLoaders.BackpackItemLoader; import de.hysky.skyblocker.skyblock.profileviewer.inventory.itemLoaders.PetsInventoryItemLoader; import de.hysky.skyblocker.skyblock.profileviewer.inventory.itemLoaders.WardrobeInventoryItemLoader; -import de.hysky.skyblocker.skyblock.profileviewer.utils.SkullCreator; +import de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils; import de.hysky.skyblocker.skyblock.profileviewer.utils.SubPageSelectButton; import de.hysky.skyblocker.skyblock.tabhud.util.Ico; import it.unimi.dsi.fastutil.ints.IntIntPair; @@ -22,15 +22,15 @@ import java.util.List; import java.util.Map; public class InventoryPage implements ProfileViewerPage { - private static final String[] INVENTORY_PAGES = {"Inventory", "Enderchest", "Backpack", "Wardrobe", "Pets", "Accessory Bag"}; + private static final String[] INVENTORY_PAGES = {"inventory", "enderchest", "backpack", "wardrobe", "pets", "accessoryBag"}; private static final int TOTAL_HEIGHT = 165; private static final Map<String, ItemStack> ICON_MAP = Map.ofEntries( - Map.entry("Wardrobe", Ico.L_CHESTPLATE), - Map.entry("Inventory", Ico.CHEST), - Map.entry("Backpack", SkullCreator.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzYyZjNiM2EwNTQ4MWNkZTc3MjQwMDA1YzBkZGNlZTFjMDY5ZTU1MDRhNjJjZTA5Nzc4NzlmNTVhMzkzOTYxNDYifX19")), - Map.entry("Pets", Ico.BONE), - Map.entry("Enderchest", Ico.E_CHEST), - Map.entry("Accessory Bag", SkullCreator.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTYxYTkxOGMwYzQ5YmE4ZDA1M2U1MjJjYjkxYWJjNzQ2ODkzNjdiNGQ4YWEwNmJmYzFiYTkxNTQ3MzA5ODVmZiJ9fX0=")) + Map.entry("wardrobe", Ico.L_CHESTPLATE), + Map.entry("inventory", Ico.CHEST), + Map.entry("backpack", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzYyZjNiM2EwNTQ4MWNkZTc3MjQwMDA1YzBkZGNlZTFjMDY5ZTU1MDRhNjJjZTA5Nzc4NzlmNTVhMzkzOTYxNDYifX19")), + Map.entry("pets", Ico.BONE), + Map.entry("enderchest", Ico.E_CHEST), + Map.entry("accessoryBag", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTYxYTkxOGMwYzQ5YmE4ZDA1M2U1MjJjYjkxYWJjNzQ2ODkzNjdiNGQ4YWEwNmJmYzFiYTkxNTQ3MzA5ODVmZiJ9fX0=")) ); private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java index b3389d39..857198e1 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java @@ -4,71 +4,107 @@ import de.hysky.skyblocker.skyblock.PetCache; import de.hysky.skyblocker.skyblock.itemlist.ItemFixerUpper; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; 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.ItemUtils; import de.hysky.skyblocker.utils.NEURepoManager; import io.github.moulberry.repo.constants.PetNumbers; import io.github.moulberry.repo.data.NEUItem; import io.github.moulberry.repo.data.Rarity; -import io.github.moulberry.repo.util.PetId; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LoreComponent; import net.minecraft.component.type.ProfileComponent; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtString; import net.minecraft.registry.Registries; +import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; -import net.minecraft.util.Pair; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.regex.Matcher; -import java.util.stream.Collectors; +import java.util.regex.Pattern; import static de.hysky.skyblocker.skyblock.itemlist.ItemStackBuilder.SKULL_TEXTURE_PATTERN; -import static de.hysky.skyblocker.skyblock.itemlist.ItemStackBuilder.SKULL_UUID_PATTERN; +import static de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils.numLetterFormat; public class Pet { private final String name; private final double xp; private final String tier; private final Optional<String> heldItem; + private final Optional<String> skin; + private final Optional<String> skinTexture; private final int level; + private final double perecentageToLevel; + private final long levelXP; + private final long nextLevelXP; private final ItemStack icon; + private final Pattern statsMatcher = Pattern.compile("\\{[A-Za-z_]+}"); + private final Pattern numberMatcher = Pattern.compile("\\{\\d+}"); + + + private static final Map<String, Integer> TIER_MAP = Map.of( "COMMON", 0, "UNCOMMON", 1, "RARE", 2, "EPIC", 3, "LEGENDARY", 4, "MYTHIC", 5 ); + private static final Int2ObjectMap<Formatting> RARITY_COLOR_MAP = Int2ObjectMaps.unmodifiable(new Int2ObjectOpenHashMap<>(Map.of( + 0, Formatting.WHITE, // COMMON + 1, Formatting.GREEN, // UNCOMMON + 2, Formatting.BLUE, // RARE + 3, Formatting.DARK_PURPLE, // EPIC + 4, Formatting.GOLD, // LEGENDARY + 5, Formatting.LIGHT_PURPLE, // MYTHIC + 6, Formatting.AQUA // DIVINE (future proofing, because why not) + ))); + public Pet(PetCache.PetInfo petData) { + LevelFinder.LevelInfo info = LevelFinder.getLevelInfo(petData.type().equals("GOLDEN_DRAGON") ? "PET_GREG" : "PET_" + petData.tier(), (long) petData.exp()); this.name = petData.type(); this.xp = petData.exp(); this.heldItem = petData.item(); - if ((heldItem.isPresent() && heldItem.get().equals("PET_ITEM_TIER_BOOST"))) { - this.tier = switch (petData.tier()) { - case "COMMON" -> "UNCOMMON"; - case "UNCOMMON" -> "RARE"; - case "RARE" -> "EPIC"; - case "EPIC" -> "LEGENDARY"; - case "LEGENDARY" -> "MYTHIC"; - default -> petData.tier(); - }; - } else { - this.tier = petData.tier(); - } - this.level = LevelFinder.getLevelInfo(this.name.equals("GOLDEN_DRAGON") ? "PET_GREG" : "PET_" + this.tier, (long) xp).level; + this.skin = petData.skin(); + this.skinTexture = calculateSkinTexture(); + this.tier = petData.tier(); + this.level = info.level; + this.perecentageToLevel = info.fill; + this.levelXP = info.levelXP; + this.nextLevelXP = info.nextLevelXP; this.icon = createIcon(); } - public String getName() { return name; } - public long getXP() { return (long) xp; } - public int getTier() { return TIER_MAP.getOrDefault(tier, 0); } - public String getTierAsString() { return tier; } - public String getSkin() { return null; } + private String getName() { + return name; + } + + public long getXP() { + return (long) xp; + } + + private int getTier() { + return TIER_MAP.getOrDefault(tier, 0); + } + + public String getTierAsString() { + return tier; + } + + private Optional<String> calculateSkinTexture() { + if (this.skin.isPresent()) { + NEUItem item = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId("PET_SKIN_" + this.skin.get()); + if (item == null) return Optional.empty(); + Matcher skullTexture = SKULL_TEXTURE_PATTERN.matcher(item.getNbttag()); + if (skullTexture.find()) return Optional.of(skullTexture.group(1)); + } + return Optional.empty(); + } public int getLevel() { return level; } public ItemStack getIcon() { return icon; } @@ -78,19 +114,15 @@ public class Pet { Map<String, NEUItem> items = NEURepoManager.NEU_REPO.getItems().getItems(); if (items == null) return Ico.BARRIER; - String targetItemId = this.getName() + ";" + this.getTier(); - NEUItem item = items.values().stream() - .filter(i -> Formatting.strip(i.getSkyblockItemId()).equals(targetItemId)) - .findFirst().orElse(null); + String targetItemId = this.getName() + ";" + (this.getTier() + (heldItem.isPresent() && heldItem.get().equals("PET_ITEM_TIER_BOOST") ? 1 : 0)); + NEUItem item = NEURepoManager.NEU_REPO.getItems().getItems().get(targetItemId); - NEUItem petItem = null; - if (this.heldItem.isPresent()) { - petItem = items.values().stream() - .filter(i -> Formatting.strip(i.getSkyblockItemId()).equals(this.heldItem.get())) - .findFirst().orElse(null); + // For cases life RIFT_FERRET Where it can be tier boosted into a pet that otherwise can't exist + if (item == null && heldItem.isPresent() && heldItem.get().equals("PET_ITEM_TIER_BOOST")) { + item = NEURepoManager.NEU_REPO.getItems().getItems().get(getName() + ";" + getTier()); } - return fromNEUItem(item, petItem); + return fromNEUItem(item, this.heldItem.map(ItemRepository::getItemStack).orElse(null)); } /** @@ -100,87 +132,134 @@ public class Pet { * the NBT Data into modern DataComponentTypes before returning the final ItemStack </p * * @param item The NEUItem representing the pet. - * @param helditem The NEUItem representing the held item, if any. + * @param heldItem The ItemStack of the pet's held item, if any. * @return The ItemStack representing the pet with all its properties set. */ - private ItemStack fromNEUItem(NEUItem item, NEUItem helditem) { - if (item == null) return Ico.BARRIER; - List<Pair<String, String>> injectors = new ArrayList<>(createLoreReplacers(item.getSkyblockItemId(), helditem)); + private ItemStack fromNEUItem(NEUItem item, ItemStack heldItem) { + if (item == null) { + ItemStack errIcon = Ico.BARRIER.copy(); + errIcon.set(DataComponentTypes.CUSTOM_NAME, Text.of(this.getName())); + return errIcon; + } + Identifier itemId = Identifier.of(ItemFixerUpper.convertItemId(item.getMinecraftItemId(), item.getDamage())); - ItemStack stack = new ItemStack(Registries.ITEM.get(itemId)); - - NbtCompound customData = new NbtCompound(); - customData.put(ItemUtils.ID, NbtString.of(item.getSkyblockItemId())); - stack.set(DataComponentTypes.CUSTOM_NAME, Text.of(injectData(item.getDisplayName(), injectors))); - - stack.set(DataComponentTypes.LORE, new LoreComponent( - item.getLore().stream().map(line -> injectData(line, injectors)) - .filter(line -> !line.contains("SKIP")).map(Text::of) - .collect(Collectors.toList()))); - - Matcher skullUuid = SKULL_UUID_PATTERN.matcher(item.getNbttag()); - Matcher skullTexture = SKULL_TEXTURE_PATTERN.matcher(item.getNbttag()); - if (skullUuid.find() && skullTexture.find()) { - UUID uuid = UUID.fromString(skullUuid.group(1)); - String textureValue = this.getSkin() == null ? skullTexture.group(1) : this.getSkin(); - stack.set(DataComponentTypes.PROFILE, new ProfileComponent( - Optional.of(item.getSkyblockItemId()), Optional.of(uuid), - ItemUtils.propertyMapWithTexture(textureValue))); + ItemStack petStack = new ItemStack(Registries.ITEM.get(itemId)).copy(); + + List<Text> formattedLore = !(name.equals("GOLDEN_DRAGON") && level < 101) ? processLore(item.getLore(), heldItem) : buildGoldenDragonEggLore(item.getLore()); + + // Calculate and display XP for level + Style style = Style.EMPTY.withItalic(false); + if (level != 100 && level != 200) { + String progress = "Progress to Level " + this.level + ": §e" + fixDecimals(this.perecentageToLevel * 100, true) + "%"; + formattedLore.add(formattedLore.size() - 1, Text.literal(progress).setStyle(style).formatted(Formatting.GRAY)); + String string = "§2§m ".repeat((int) Math.round(perecentageToLevel * 30)) + "§f§m ".repeat(30 - (int) Math.round(perecentageToLevel * 30)); + formattedLore.add(formattedLore.size() - 1, Text.literal(string + "§r§e " + numLetterFormat(levelXP) + "§6/§e" + numLetterFormat(nextLevelXP)).setStyle(style)); + formattedLore.add(formattedLore.size() - 1, Text.empty()); + } else { + formattedLore.add(formattedLore.size() - 1, Text.literal("MAX LEVEL").setStyle(style).formatted(Formatting.AQUA, Formatting.BOLD)); + formattedLore.add(formattedLore.size() - 1, Text.literal("▸ " + ProfileViewerUtils.COMMA_FORMATTER.format((long) xp) + " XP").setStyle(style).formatted(Formatting.DARK_GRAY)); + formattedLore.add(formattedLore.size() - 1, Text.empty()); } - return stack; + + // Skin Head Texture + if (skinTexture.isPresent()) { + formattedLore.set(0, Text.of(formattedLore.getFirst().getString() + ", " + Formatting.strip(NEURepoManager.NEU_REPO.getItems().getItems().get("PET_SKIN_" + skin.get()).getDisplayName()))); + petStack.set(DataComponentTypes.PROFILE, new ProfileComponent( + Optional.of(item.getSkyblockItemId()), Optional.of(UUID.randomUUID()), + ItemUtils.propertyMapWithTexture(this.skinTexture.get()))); + } else { + Matcher skullTexture = SKULL_TEXTURE_PATTERN.matcher(item.getNbttag()); + if (skullTexture.find()) { + petStack.set(DataComponentTypes.PROFILE, new ProfileComponent( + Optional.of(item.getSkyblockItemId()), Optional.of(UUID.randomUUID()), + ItemUtils.propertyMapWithTexture(skullTexture.group(1)))); + } + } + + if ((boosted())) formattedLore.set(formattedLore.size() - 1, Text.literal(Rarity.values()[getTier() + 1].toString()).setStyle(style).formatted(Formatting.BOLD, RARITY_COLOR_MAP.get(getTier() + 1))); + + // Update the lore and name + petStack.set(DataComponentTypes.LORE, new LoreComponent(formattedLore)); + String displayName = Formatting.strip(item.getDisplayName()).replace("[Lvl {LVL}]", "§7[Lvl " + this.level + "]§r"); + petStack.set(DataComponentTypes.CUSTOM_NAME, Text.literal(displayName).setStyle(style).formatted(RARITY_COLOR_MAP.get(this.getTier() + (boosted() ? 1 : 0)))); + return petStack; } /** - * Generates a list of placeholder-replacement pairs for the itemName of a pet item. - * <p> This method uses the pet's data from the NEU repository and uses PetInfo to generate replacers, and optionally - * includes data about a held item. </p> + * Iterates through a Pet's lore injecting interpolated stat numbers based on pet level * - * @param itemSkyblockID The initial itemName string containing the pet's name and tier separated by a semicolon. - * @param helditem The NEUItem representing the held item, if any. - * @return A list of placeholder-replacement pairs to be used for injecting data into the pet item's itemName. + * @param lore the raw lore data stored in NEU Repo + * @param heldItem the pet's held item, if any + * @return Formatted lore with injected stats inserted into the tooltip */ - private List<Pair<String, String>> createLoreReplacers(String itemSkyblockID, NEUItem helditem) { - List<Pair<String, String>> list = new ArrayList<>(); - Map<@PetId String, Map<Rarity, PetNumbers>> petNums = NEURepoManager.NEU_REPO.getConstants().getPetNumbers(); - String petName = itemSkyblockID.split(";")[0]; - if (!itemSkyblockID.contains(";") || !petNums.containsKey(petName)) return list; - - Rarity rarity = Rarity.values()[Integer.parseInt(itemSkyblockID.split(";")[1])]; - try { - PetNumbers data = petNums.get(petName).get(rarity); - list.add(new Pair<>("\\{LVL\\}", String.valueOf(this.level))); - data.interpolatedStatsAtLevel(this.level).getStatNumbers().forEach((key, value) -> - list.add(new Pair<>("\\{" + key + "\\}", fixDecimals(value, true)))); - - List<Double> otherNumsMin = data.interpolatedStatsAtLevel(this.level).getOtherNumbers(); - for (int i = 0; i < otherNumsMin.size(); ++i) { - list.add(new Pair<>("\\{" + i + "\\}", fixDecimals(otherNumsMin.get(i), false))); + private List<Text> processLore(List<String> lore, ItemStack heldItem) { + Map<String, Map<Rarity, PetNumbers>> petNums = NEURepoManager.NEU_REPO.getConstants().getPetNumbers(); + Rarity rarity = Rarity.values()[getTier()]; + PetNumbers data = petNums.get(getName()).get(rarity); + List<Text> formattedLore = new ArrayList<>(); + + for (String line : lore) { + if (line.contains("Right-click to add this") || line.contains("pet menu!")) continue; + + String formattedLine = line; + + Matcher stats = statsMatcher.matcher(formattedLine); + Matcher other = numberMatcher.matcher(formattedLine); + + while (stats.find()) { + String placeholder = stats.group(); + String statKey = placeholder.substring(1, placeholder.length() - 1); + String statValue = String.valueOf(fixDecimals(data.interpolatedStatsAtLevel(this.level).getStatNumbers().get(statKey), true)); + formattedLine = formattedLine.replace(placeholder, statValue); } - list.add(new Pair<>("Right-click to add this pet to", - helditem != null ? "§r§6Held Item: " + helditem.getDisplayName() : "SKIP")); - list.add(new Pair<>("pet menu!", "SKIP")); - } catch (Exception e) { - if (petName.equals("GOLDEN_DRAGON")) { - list.add(new Pair<>("Golden Dragon", - "§r§7[Lvl " + this.level + "] " + "§6Golden Dragon Egg §c[Not Supported by NEU-Repo]")); + while (other.find()) { + String placeholder = other.group(); + int numberKey = Integer.parseInt(placeholder.substring(1, placeholder.length() - 1)); + String statValue = String.valueOf(fixDecimals(data.interpolatedStatsAtLevel(this.level).getOtherNumbers().get(numberKey), false)); + formattedLine = formattedLine.replace(placeholder, statValue); } + + formattedLore.add(Text.of(formattedLine)); } - return list; - } - private String injectData(String string, List<Pair<String, String>> injectors) { - for (Pair<String, String> injector : injectors) { - if (string.contains(injector.getLeft())) return injector.getRight(); - string = string.replaceAll(injector.getLeft(), injector.getRight()); + + if (heldItem != null) { + formattedLore.set(formattedLore.size() - 2, Text.of("§r§6Held Item: " + heldItem.getName().getString())); + formattedLore.add(formattedLore.size() - 1, Text.empty()); } - return string; + + return formattedLore; + } + + /** + * NEU Repo doesn't distinguish between the Egg and the hatched GoldenDragon pet so hardcoded lore :eues: + * @param lore the existing lore + * @return Fully formatted GoldenDragonEgg Lore + */ + private List<Text> buildGoldenDragonEggLore(List<String> lore) { + List<Text> formattedLore = new ArrayList<>(); + Style style = Style.EMPTY.withItalic(false); + + formattedLore.add(Text.of(lore.getFirst())); + formattedLore.add(Text.empty()); + formattedLore.add(Text.literal("Perks:").setStyle(style).formatted(Formatting.GRAY)); + formattedLore.add(Text.literal("???").setStyle(style).formatted(Formatting.RED, Formatting.BOLD)); + formattedLore.add(Text.empty()); + formattedLore.add(Text.literal("Hatches at level §b100").setStyle(style).formatted(Formatting.GRAY)); + formattedLore.add(Text.empty()); + formattedLore.add(Text.of(lore.getLast())); + + return formattedLore; } private String fixDecimals(double num, boolean truncate) { - if (num % 1 == 0) return String.valueOf((int) num); - BigDecimal roundedNum = new BigDecimal(num).setScale(3, RoundingMode.HALF_UP); - return truncate && num > 1 ? String.valueOf(roundedNum.intValue()) - : roundedNum.stripTrailingZeros().toPlainString(); + if (num % 1 == 0) return String.valueOf((int) (num)); + BigDecimal roundedNum = new BigDecimal(num).setScale(truncate ? 1 : 3, RoundingMode.HALF_UP); + return roundedNum.stripTrailingZeros().toPlainString(); + } + + private boolean boosted() { + return this.heldItem.isPresent() && this.heldItem.get().equals("PET_ITEM_TIER_BOOST"); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java index 26673693..e210ca9a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java @@ -1,12 +1,15 @@ 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.InventoryItemLoader; import it.unimi.dsi.fastutil.ints.IntIntPair; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.resource.language.I18n; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.tooltip.TooltipType; @@ -14,12 +17,14 @@ import net.minecraft.text.Text; import net.minecraft.util.Identifier; import java.awt.*; +import java.util.Collections; import java.util.List; public class PlayerInventory implements ProfileViewerPage { private static final Identifier TEXTURE = Identifier.of("textures/gui/container/generic_54.png"); private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; private final List<ItemStack> containerList; + private List<Text> tooltip = Collections.emptyList(); public PlayerInventory(JsonObject inventory) { this.containerList = new InventoryItemLoader().loadItems(inventory); @@ -27,17 +32,19 @@ public class PlayerInventory implements ProfileViewerPage { // Z-STACKING forces this nonsense of separating the Background texture and Item Drawing :( public void render(DrawContext context, int mouseX, int mouseY, float delta, int rootX, int rootY) { - drawContainerTextures(context, "Armour", rootX, rootY + 108, IntIntPair.of(1, 4)); - drawContainerTextures(context, "Inventory", rootX, rootY + 2, IntIntPair.of(4, 9)); - drawContainerTextures(context, "Equipment", rootX + 90, rootY + 108, IntIntPair.of(1, 4)); + drawContainerTextures(context, "armor", rootX, rootY + 108, IntIntPair.of(1, 4)); + drawContainerTextures(context, "inventory", rootX, rootY + 2, IntIntPair.of(4, 9)); + drawContainerTextures(context, "equipment", rootX + 90, rootY + 108, IntIntPair.of(1, 4)); + tooltip.clear(); drawContainerItems(context, rootX, rootY + 108, IntIntPair.of(1, 4), 36, 40, mouseX, mouseY); drawContainerItems(context, rootX, rootY + 2, IntIntPair.of(4, 9), 0, 36, mouseX, mouseY); drawContainerItems(context, rootX + 90, rootY + 108, IntIntPair.of(1, 4), 40, containerList.size(), mouseX, mouseY); + if (!tooltip.isEmpty()) context.drawTooltip(textRenderer, tooltip, mouseX, mouseY); } private void drawContainerTextures(DrawContext context, String containerName, int rootX, int rootY, IntIntPair dimensions) { - if (containerName.equals("Inventory")) { + if (containerName.equals("inventory")) { context.drawTexture(TEXTURE, rootX, rootY + dimensions.leftInt() + 10, 0, 136, dimensions.rightInt() * 18 + 7, dimensions.leftInt() * 18 + 17); context.drawTexture(TEXTURE, rootX + dimensions.rightInt() * 18 + 7, rootY, 169, 0, 7, dimensions.leftInt() * 18 + 21); context.drawTexture(TEXTURE, rootX, rootY, 0, 0, dimensions.rightInt() * 18 + 7, 14); @@ -48,8 +55,7 @@ public class PlayerInventory implements ProfileViewerPage { context.drawTexture(TEXTURE, rootX, rootY + dimensions.leftInt() * 18 + 17, 0, 215, dimensions.rightInt() * 18 + 7, 7); context.drawTexture(TEXTURE, rootX + dimensions.rightInt() * 18 + 7, rootY + dimensions.leftInt() * 18 + 17, 169, 215, 7, 7); } - - context.drawText(textRenderer, containerName, rootX + 7, rootY + 7, Color.DARK_GRAY.getRGB(), false); + context.drawText(textRenderer, I18n.translate("skyblocker.profileviewer.inventory." + containerName), rootX + 7, rootY + 7, Color.DARK_GRAY.getRGB(), false); } private void drawContainerItems(DrawContext context, int rootX, int rootY, IntIntPair dimensions, int startIndex, int endIndex, int mouseX, int mouseY) { @@ -61,12 +67,15 @@ public class PlayerInventory implements ProfileViewerPage { int x = rootX + 8 + column * 18; int y = (rootY + 18 + row * 18) + (dimensions.leftInt() > 1 && row + 1 == dimensions.leftInt() ? 4 : 0); + if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) { + ItemRarityBackgrounds.tryDraw(containerList.get(startIndex + i), context, x, y); + } + context.drawItem(containerList.get(startIndex + i), x, y); context.drawItemInSlot(textRenderer, containerList.get(startIndex + i), x, y); - if (mouseX > x && mouseX < x + 16 && mouseY > y && mouseY < y + 16) { - List<Text> tooltip = containerList.get(startIndex + i).getTooltip(Item.TooltipContext.DEFAULT, MinecraftClient.getInstance().player, TooltipType.BASIC); - context.drawTooltip(textRenderer, tooltip, mouseX, mouseY); + if (mouseX > x -1 && mouseX < x + 16 && mouseY > y - 1 && mouseY < y + 16) { + tooltip = containerList.get(startIndex + i).getTooltip(Item.TooltipContext.DEFAULT, MinecraftClient.getInstance().player, TooltipType.BASIC); } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/BackpackItemLoader.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/BackpackItemLoader.java index 99e728be..dee2bfaf 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/BackpackItemLoader.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/BackpackItemLoader.java @@ -2,7 +2,11 @@ package de.hysky.skyblocker.skyblock.profileviewer.inventory.itemLoaders; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; import java.util.ArrayList; import java.util.List; @@ -23,9 +27,12 @@ public class BackpackItemLoader extends ItemLoader { for (int i = 0; i < sortedEntries.size(); i++) { backpackItems.addAll(super.loadItems(sortedEntries.get(i).getValue().getAsJsonObject())); - int padding = (i + 1) * 45 % (backpackItems.isEmpty() ? 1 : backpackItems.size()); - for (int j = 0; j < padding; j++) { - backpackItems.add(ItemStack.EMPTY); + int paddingNeeded = (45 - (backpackItems.size() % 45)) % 45; + for (int j = 0; j < paddingNeeded; j++) { + ItemStack paddingItem = Ico.GRAY_DYE.copy(); + paddingItem.set(DataComponentTypes.CUSTOM_NAME, Text.translatable("skyblocker.profileviewer.inventory.inactive")); + paddingItem.set(DataComponentTypes.LORE, new LoreComponent(List.of(Text.translatable("skyblocker.profileviewer.inventory.inactive.description.backpack"),Text.translatable("skyblocker.profileviewer.inventory.inactive.description.general")))); + backpackItems.add(paddingItem); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/ItemLoader.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/ItemLoader.java index 9d9b1b07..f3045c11 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/ItemLoader.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/ItemLoader.java @@ -12,10 +12,7 @@ import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.NEURepoManager; import io.github.moulberry.repo.data.NEUItem; import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.AttributeModifiersComponent; -import net.minecraft.component.type.DyedColorComponent; -import net.minecraft.component.type.LoreComponent; -import net.minecraft.component.type.ProfileComponent; +import net.minecraft.component.type.*; import net.minecraft.datafixer.fix.ItemIdFix; import net.minecraft.datafixer.fix.ItemInstanceTheFlatteningFix; import net.minecraft.item.ItemStack; @@ -44,9 +41,9 @@ public class ItemLoader { } NbtCompound nbttag = containerContent.getCompound(i).getCompound("tag"); - String internalName = nbttag.getCompound("ExtraAttributes").getString("id"); + NbtCompound extraAttributes = nbttag.getCompound("ExtraAttributes"); + String internalName = extraAttributes.getString("id"); if (internalName.equals("PET")) { - NbtCompound extraAttributes = nbttag .getCompound("ExtraAttributes"); PetCache.PetInfo petInfo = PetCache.PetInfo.CODEC.parse(JsonOps.INSTANCE, JsonParser.parseString(extraAttributes.getString("petInfo"))).getOrThrow(); Pet pet = new Pet(petInfo); itemList.add(pet.getIcon()); @@ -114,6 +111,8 @@ public class ItemLoader { // Set Count stack.setCount(containerContent.getCompound(i).getInt("Count")); + stack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes)); + itemList.add(stack); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillWidget.java index 3a3870f3..51f5e5f4 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillWidget.java @@ -2,16 +2,20 @@ package de.hysky.skyblocker.skyblock.profileviewer.skills; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.profileviewer.utils.LevelFinder; -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 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 SkillWidget { @@ -33,7 +37,7 @@ public class SkillWidget { Map.entry("Alchemy", Ico.BREWING_STAND), Map.entry("Taming", Ico.SPAWN_EGG), Map.entry("Carpentry", Ico.CRAFTING_TABLE), - Map.entry("Catacombs", SkullCreator.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzliNTY4OTViOTY1OTg5NmFkNjQ3ZjU4NTk5MjM4YWY1MzJkNDZkYjljMWIwMzg5YjhiYmViNzA5OTlkYWIzM2QifX19")), + Map.entry("Catacombs", ProfileViewerUtils.createSkull("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzliNTY4OTViOTY1OTg5NmFkNjQ3ZjU4NTk5MjM4YWY1MzJkNDZkYjljMWIwMzg5YjhiYmViNzA5OTlkYWIzM2QifX19")), Map.entry("Runecraft", Ico.MAGMA_CREAM), Map.entry("Social", Ico.EMERALD) ); @@ -75,7 +79,7 @@ public class SkillWidget { } - public void render(DrawContext context, int x, int y) { + public void render(DrawContext context, int mouseX, int mouseY, int x, int y) { context.drawItem(this.stack, x + 3, y + 2); context.drawText(textRenderer, SKILL_NAME + " " + SKILL_LEVEL.level, x + 31, y + 2, Color.white.hashCode(), false); @@ -91,5 +95,12 @@ public class SkillWidget { context.drawGuiTexture(BAR_BACK, x + 30, y + 12, 75, 6); RenderHelper.renderNineSliceColored(context, BAR_FILL, x + 30, y + 12, (int) (75 * SKILL_LEVEL.fill), 6, fillColor); + + if (mouseX > x + 30 && mouseX < x + 105 && mouseY > y + 10 && mouseY < y + 19){ + List<Text> tooltipText = new ArrayList<>(); + tooltipText.add(Text.literal(this.SKILL_NAME).formatted(Formatting.GREEN)); + tooltipText.add(Text.literal("XP: " + ProfileViewerUtils.COMMA_FORMATTER.format(this.SKILL_LEVEL.xp)).formatted(Formatting.GOLD)); + context.drawTooltip(textRenderer, tooltipText, mouseX, mouseY); + } } }
\ No newline at end of file diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillsPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillsPage.java index c331bbdd..952e5620 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillsPage.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillsPage.java @@ -41,7 +41,7 @@ public class SkillsPage implements ProfileViewerPage { int x = (i < 6) ? rootX : column2; int y = rootY + (i % 6) * ROW_GAP; context.drawTexture(TEXTURE, x, y, 0, 0, 109, 26, 109, 26); - skillWidgets.get(i).render(context, x, y + 3); + skillWidgets.get(i).render(context, mouseX, mouseY, x, y + 3); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayerWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayerWidget.java index a9c05c11..978c58c4 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayerWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayerWidget.java @@ -3,15 +3,20 @@ package de.hysky.skyblocker.skyblock.profileviewer.slayers; 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 SlayerWidget { @@ -53,7 +58,7 @@ public class SlayerWidget { } catch (Exception ignored) {} } - 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.drawTexture(this.item, x + 1, y + 3, 0, 0, 20, 20, 20, 20); context.drawText(textRenderer, slayerName + " " + slayerLevel.level, x + 31, y + 5, Color.white.hashCode(), false); @@ -67,6 +72,13 @@ public class SlayerWidget { context.drawGuiTexture(BAR_BACK, x + 30, y + 15, 75, 6); Color fillColor = slayerLevel.fill == 1 ? Color.MAGENTA : Color.green; RenderHelper.renderNineSliceColored(context, BAR_FILL, x + 30, y + 15, (int) (75 * slayerLevel.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.slayerName).formatted(Formatting.GREEN)); + tooltipText.add(Text.literal("XP: " + ProfileViewerUtils.COMMA_FORMATTER.format(this.slayerLevel.xp)).formatted(Formatting.GOLD)); + context.drawTooltip(textRenderer, tooltipText, mouseX, mouseY); + } } private int findTotalKills() { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayersPage.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayersPage.java index 08e2ca06..528bd3ac 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayersPage.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayersPage.java @@ -26,7 +26,7 @@ public class SlayersPage implements ProfileViewerPage { public void render(DrawContext context, int mouseX, int mouseY, float delta, int rootX, int rootY) { for (int i = 0; i < slayerWidgets.size(); i++) { - slayerWidgets.get(i).render(context, rootX, rootY + i * ROW_GAP); + slayerWidgets.get(i).render(context, mouseX, mouseY, rootX, rootY + i * ROW_GAP); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/LevelFinder.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/LevelFinder.java index b52fd579..f53df0f5 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/LevelFinder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/LevelFinder.java @@ -8,15 +8,20 @@ public class LevelFinder { public long xp; public int level; public double fill; + public long levelXP; + public long nextLevelXP; public LevelInfo(long xp, int level) { this.xp = xp; this.level = level; } - public LevelInfo(int level, double fill) { + public LevelInfo(long xp, int level, double fill, double levelXP, double nextLevelXP) { + this.xp = xp; this.level = level; this.fill = fill; + this.levelXP = (long) levelXP; + this.nextLevelXP = (long) nextLevelXP; } } @@ -255,16 +260,20 @@ public class LevelFinder { for (int i = boundaries.size() - 1; i >= 0 ; i--) { if (xp >= boundaries.get(i).xp) { double fill; + double xpInCurrentLevel; + double levelXPRange; if (i < boundaries.getLast().level) { double currentLevelXP = boundaries.get(i).xp; double nextLevelXP = boundaries.get(i + 1).xp; - double levelXPRange = nextLevelXP - currentLevelXP; - double xpInCurrentLevel = xp - currentLevelXP; + levelXPRange = nextLevelXP - currentLevelXP; + xpInCurrentLevel = xp - currentLevelXP; fill = xpInCurrentLevel / levelXPRange; } else { fill = 1.0; + xpInCurrentLevel = xp - boundaries.getLast().xp; + levelXPRange = boundaries.getLast().xp - boundaries.get(boundaries.size()-2).xp; } - return new LevelInfo(boundaries.get(i).level, fill); + return new LevelInfo(xp, boundaries.get(i).level, fill, xpInCurrentLevel, levelXPRange); } } return new LevelInfo(0L, 0); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/SkullCreator.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/ProfileViewerUtils.java index b074952c..8dadedaf 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/SkullCreator.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/ProfileViewerUtils.java @@ -8,10 +8,14 @@ import net.minecraft.component.type.ProfileComponent; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import java.text.NumberFormat; +import java.util.Locale; import java.util.Optional; import java.util.UUID; -public class SkullCreator { +public class ProfileViewerUtils { + public static final NumberFormat COMMA_FORMATTER = NumberFormat.getNumberInstance(Locale.US); + public static ItemStack createSkull(String textureB64) { ItemStack skull = new ItemStack(Items.PLAYER_HEAD); try { @@ -24,4 +28,16 @@ public class SkullCreator { } return skull; } + + public static String numLetterFormat(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/utils/SubPageSelectButton.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/SubPageSelectButton.java index 4c9dcda4..8398747d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/SubPageSelectButton.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/SubPageSelectButton.java @@ -34,7 +34,7 @@ public class SubPageSelectButton extends ClickableWidget { @Override protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { context.fill(this.getX(), this.getY(), this.getX() + 20, this.getY() + 20, Color.BLACK.getRGB()); - context.drawTexture(TEXTURES.get(toggled, isHovered()), this.getX() + 1, this.getY() + 1,0, 0, 18, 18, 18, 18); + context.drawTexture(TEXTURES.get(toggled, (mouseX > getX() && mouseX < getX() + 19 && mouseY > getY() && mouseY < getY() + 19)), this.getX() + 1, this.getY() + 1,0, 0, 18, 18, 18, 18); context.drawItem(ICON, this.getX() + 2, this.getY() + 2); if ((mouseX > getX() + 1 && mouseX < getX() + 19 && mouseY > getY() + 1 && mouseY < getY() + 19)) { LoreComponent lore = ICON.get(DataComponentTypes.LORE); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java index b37a3883..f182a949 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java @@ -73,6 +73,7 @@ public class Ico { public static final ItemStack EXPERIENCE_BOTTLE = new ItemStack(Items.EXPERIENCE_BOTTLE); public static final ItemStack PINK_DYE = new ItemStack(Items.PINK_DYE); public static final ItemStack LIME_DYE = new ItemStack(Items.LIME_DYE); + public static final ItemStack GRAY_DYE = new ItemStack(Items.GRAY_DYE); public static final ItemStack ENCHANTED_BOOK = new ItemStack(Items.ENCHANTED_BOOK); public static final ItemStack SPIDER_EYE = new ItemStack(Items.SPIDER_EYE); public static final ItemStack BLUE_ICE = new ItemStack(Items.BLUE_ICE); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java index f8930882..11ec1b8d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java @@ -1,28 +1,5 @@ package de.hysky.skyblocker.skyblock.waypoint; -import static com.mojang.brigadier.arguments.StringArgumentType.getString; -import static com.mojang.brigadier.arguments.StringArgumentType.word; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Semaphore; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import org.slf4j.Logger; - import com.google.common.primitives.Floats; import com.google.gson.Gson; import com.google.gson.JsonParser; @@ -33,8 +10,8 @@ import com.mojang.logging.LogUtils; import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; import com.mojang.serialization.codecs.RecordCodecBuilder; - import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.item.CustomArmorDyeColors; import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.Utils; @@ -59,6 +36,28 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import org.slf4j.Logger; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Semaphore; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; public class OrderedWaypoints { private static final Logger LOGGER = LogUtils.getLogger(); @@ -400,7 +399,7 @@ public class OrderedWaypoints { private int waypointIndex; OrderedWaypoint(BlockPos pos, float[] colorComponents) { - super(pos, Type.WAYPOINT, colorComponents); + super(pos, () -> SkyblockerConfigManager.get().uiAndVisuals.waypoints.waypointType, colorComponents); } private BlockPos getPos() { diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index ff88814d..bf154048 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -945,5 +945,17 @@ "skyblocker.waypoints.ordered.import.coleWeight.success": "Successfully imported waypoints from the Cole Weight format.", "skyblocker.waypoints.ordered.import.coleWeight.fail": "§cFailed to import waypoints from the Cole Weight format. Make sure to have the waypoint data copied to your clipboard!", + "skyblocker.profileviewer.inventory.inventory": "Inventory", + "skyblocker.profileviewer.inventory.armor": "Armor", + "skyblocker.profileviewer.inventory.equipment": "Equipment", + "skyblocker.profileviewer.inventory.enderchest": "Enderchest", + "skyblocker.profileviewer.inventory.backpack": "Backpack", + "skyblocker.profileviewer.inventory.wardrobe": "Wardrobe", + "skyblocker.profileviewer.inventory.pets": "Pets", + "skyblocker.profileviewer.inventory.accessoryBag": "Accessory Bag", + "skyblocker.profileviewer.inventory.inactive": "Locked Slot", + "skyblocker.profileviewer.inventory.inactive.description.backpack": "The selected backpack", + "skyblocker.profileviewer.inventory.inactive.description.general": "does not contain this slot", + "emi.category.skyblocker.skyblock": "Skyblock" } |