aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/PetCache.java5
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java63
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerNavButton.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java47
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerTextWidget.java17
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/collections/GenericCategory.java69
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonClassWidget.java15
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonFloorRunsWidget.java35
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonMiscStatsWidgets.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/dungeons/DungeonsPage.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java19
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/InventoryPage.java16
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java275
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java27
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/BackpackItemLoader.java13
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/itemLoaders/ItemLoader.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillWidget.java17
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/skills/SkillsPage.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayerWidget.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/slayers/SlayersPage.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/LevelFinder.java17
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/ProfileViewerUtils.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/SkullCreator.java)18
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/utils/SubPageSelectButton.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java1
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java49
25 files changed, 492 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