/* * Copyright (C) 2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates is free software: you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * NotEnoughUpdates is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.profileviewer; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.JsonUtils; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.JsonToNBT; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumChatFormatting; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Base64; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; public class ProfileViewerUtils { static Map playerSkullCache = new HashMap<>(); static Map lastSoopyRequestTime = new HashMap<>(); static Map soopyDataCache = new HashMap<>(); public static JsonArray readInventoryInfo(JsonObject profileInfo, String bagName) { String bytes = Utils.getElementAsString( Utils.getElement(profileInfo, "inventory.bag_contents." + bagName + ".data"), "H4sIAAAAAAAAAONiYOBkYMzkYmBg0GUgCQAA4gDYkzoAAAA=" ); NBTTagCompound nbt; try { nbt = CompressedStreamTools.readCompressed( new ByteArrayInputStream(Base64.getDecoder().decode(bytes)) ); } catch (IOException e) { e.printStackTrace(); return null; } NBTTagList items = nbt.getTagList("i", 10); JsonArray contents = new JsonArray(); NEUManager manager = NotEnoughUpdates.INSTANCE.manager; for (int j = 0; j < items.tagCount(); j++) { contents.add(manager.getJsonFromNBTEntry(items.getCompoundTagAt(j))); } return contents; } public static int getMagicalPower(JsonArray talismanBag, JsonObject profileInfo) { Map accessories = JsonUtils.getJsonArrayAsStream(talismanBag).map(o -> { try { return JsonToNBT.getTagFromJson(o.getAsJsonObject().get("nbttag").getAsString()); } catch (Exception ignored) { return null; } }).filter(Objects::nonNull).map(tag -> { NBTTagList loreTagList = tag.getCompoundTag("display").getTagList("Lore", 8); String lastElement = loreTagList.getStringTagAt(loreTagList.tagCount() - 1); if (lastElement.contains(EnumChatFormatting.OBFUSCATED.toString())) { lastElement = lastElement.substring(lastElement.indexOf(' ')).trim().substring(4); } JsonArray lastElementJsonArray = new JsonArray(); lastElementJsonArray.add(new JsonPrimitive(lastElement)); return new AbstractMap.SimpleEntry<>( tag.getCompoundTag("ExtraAttributes").getString("id"), Utils.getRarityFromLore(lastElementJsonArray) ); }).sorted(Comparator.comparingInt(e -> -e.getValue())).collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new )); Set ignoredTalismans = new HashSet<>(); // While there are several crab hats, only one of them counts towards the magical power boolean countedCrabHat = false; int powerAmount = 0; if (profileInfo.has("rift") && profileInfo.getAsJsonObject("rift").has("access") && profileInfo.getAsJsonObject( "rift").getAsJsonObject("access").has("consumed_prism")) { // should be true when existing ? powerAmount += 11; } HashSet duplicates = new HashSet<>(); for (Map.Entry entry : accessories.entrySet()) { if (duplicates.contains(entry.getKey())) continue; JsonObject misc = Constants.MISC; JsonElement talisman_upgrades_element = misc.get("talisman_upgrades"); if (talisman_upgrades_element == null) { break; } String internalName = entry.getKey(); JsonObject talisman_upgrades = talisman_upgrades_element.getAsJsonObject(); if (talisman_upgrades.has(internalName)) { JsonArray upgrades = talisman_upgrades.get(internalName).getAsJsonArray(); for (Map.Entry entry2 : accessories.entrySet()) { if (entry2 != entry) { String internalname2 = entry2.getKey(); ArrayList upgradeIDs = new ArrayList<>(); for (int j = 0; j < upgrades.size(); j++) { String upgrade = upgrades.get(j).getAsString(); upgradeIDs.add(upgrade); if (internalname2.equals(upgrade)) { duplicates.add(internalname2); } } } } } } for (Map.Entry entry : accessories.entrySet()) { if (ignoredTalismans.contains(entry.getKey())) continue; if (duplicates.contains(entry.getKey())) continue; JsonArray children = Utils .getElementOrDefault(Constants.PARENTS, entry.getKey(), new JsonArray()) .getAsJsonArray(); for (JsonElement child : children) { ignoredTalismans.add(child.getAsString()); } if (entry.getKey().equals("HEGEMONY_ARTIFACT")) { switch (entry.getValue()) { case 4: powerAmount += 16; break; case 5: powerAmount += 22; break; } } if (entry.getKey().equals("ABICASE")) { if (profileInfo != null && profileInfo.has("nether_island_player_data")) { JsonObject data = profileInfo.get("nether_island_player_data").getAsJsonObject(); if (data.has("abiphone") && data.get("abiphone").getAsJsonObject().has("active_contacts")) { // BatChest int contact = data.get("abiphone").getAsJsonObject().get("active_contacts").getAsJsonArray().size(); powerAmount += Math.floor(contact / 2); } } } if (entry.getKey().startsWith("PARTY_HAT") || entry.getKey().startsWith("BALLOON_HAT")) { if (countedCrabHat) continue; countedCrabHat = true; } switch (entry.getValue()) { case 0: case 6: powerAmount += 3; break; case 1: case 7: powerAmount += 5; break; case 2: powerAmount += 8; break; case 3: powerAmount += 12; break; case 4: powerAmount += 16; break; case 5: powerAmount += 22; break; } } return powerAmount; } public static int getLevelingCap(JsonObject leveling, String skillName) { JsonElement capsElement = Utils.getElement(leveling, "leveling_caps"); return capsElement != null && capsElement.isJsonObject() && capsElement.getAsJsonObject().has(skillName) ? capsElement.getAsJsonObject().get(skillName).getAsInt() : 50; } public static ProfileViewer.Level getLevel(JsonArray levelingArray, float xp, int levelCap, boolean cumulative) { ProfileViewer.Level levelObj = new ProfileViewer.Level(); levelObj.totalXp = xp; levelObj.maxLevel = levelCap; for (int level = 0; level < levelingArray.size(); level++) { float levelXp = levelingArray.get(level).getAsFloat(); if (levelXp > xp) { if (cumulative) { float previous = level > 0 ? levelingArray.get(level - 1).getAsFloat() : 0; levelObj.maxXpForLevel = (levelXp - previous); levelObj.level = 1 + level + (xp - levelXp) / levelObj.maxXpForLevel; } else { levelObj.maxXpForLevel = levelXp; levelObj.level = level + xp / levelXp; } if (levelObj.level > levelCap) { levelObj.level = levelCap; levelObj.maxed = true; } return levelObj; } else { if (!cumulative) { xp -= levelXp; } } } levelObj.level = Math.min(levelingArray.size(), levelCap); levelObj.maxed = true; return levelObj; } public static void saveSearch(String username) { if (username == null) return; String nameLower = username.toLowerCase(Locale.ROOT); if (nameLower.equals(Minecraft.getMinecraft().thePlayer.getName().toLowerCase(Locale.ROOT))) return; List previousProfileSearches = NotEnoughUpdates.INSTANCE.config.hidden.previousProfileSearches; previousProfileSearches.remove(nameLower); previousProfileSearches.add(0, nameLower); while (previousProfileSearches.size() > 6) { previousProfileSearches.remove(previousProfileSearches.size() - 1); } } private static ItemStack fallBackSkull() { return Utils.createSkull( "Simon", "f3c4dfb91c7b40ac81fd462538538523", "ewogICJ0aW1lc3RhbXAiIDogMTY4NzQwMTM4MjY4MywKICAicHJvZmlsZUlkIiA6ICJmM2M0ZGZiOTFjN2I0MGFjODFmZDQ2MjUzODUzODUyMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJTaW1vbiIsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9kN2ViYThhZWU0ZmQxMTUxMmI3ZTFhMjc5YTE0YWM2NDhlNDQzNDgxYjlmMzcxMzZhNzEwMThkMzg3Mjk0Y2YzIgogICAgfQogIH0KfQ" ); } public static ItemStack getPlayerData(String username) { if (username == null) return new ItemStack(Blocks.stone); String nameLower = username.toLowerCase(Locale.ROOT); if (!playerSkullCache.containsKey(nameLower)) { playerSkullCache.put(nameLower, fallBackSkull()); getPlayerSkull(nameLower, skull -> { if (skull == null) { skull = fallBackSkull(); } playerSkullCache.put(nameLower, skull); }); } return playerSkullCache.get(nameLower); } private static void getPlayerSkull(String username, Consumer callback) { if (NotEnoughUpdates.profileViewer.nameToUuid.containsKey(username) && NotEnoughUpdates.profileViewer.nameToUuid.get(username) == null) { callback.accept(null); return; } NotEnoughUpdates.profileViewer.getPlayerUUID(username, uuid -> { if (uuid == null) { callback.accept(null); } else { NotEnoughUpdates.INSTANCE.manager.apiUtils .request() .url("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false") .requestJson() .thenAcceptAsync(jsonObject -> { if (jsonObject.has("properties") && jsonObject.get("properties").isJsonArray()) { JsonArray propertiesArray = jsonObject.getAsJsonArray("properties"); if (propertiesArray.size() > 0) { JsonObject textureObject = propertiesArray.get(0).getAsJsonObject(); if (textureObject.has("value") && textureObject.get("value").isJsonPrimitive() && textureObject.get("value").getAsJsonPrimitive().isString()) { ItemStack skull = Utils.createSkull( username, uuid, textureObject.get("value").getAsString() ); callback.accept(skull); } } } }); } }); } public static int onSlotToChangePage(int mouseX, int mouseY, int guiLeft, int guiTop) { if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) { if (mouseY >= guiTop && mouseY <= guiTop + 28) { return 1; } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) { return 2; } } return 0; } }