diff options
Diffstat (limited to 'src/main')
11 files changed, 1455 insertions, 90 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 8d625c14..edf1d31c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -112,10 +112,12 @@ public class NEUManager { public void setCurrentProfile(String currentProfile) { this.currentProfile = currentProfile; + this.auctionManager.incPlayerInfoVersion(); } public void setCurrentProfileBackup(String currentProfile) { this.currentProfileBackup = currentProfile; + this.auctionManager.incPlayerInfoVersion(); } public String getCurrentProfile() { @@ -227,7 +229,7 @@ public class NEUManager { public void updatePrices() { if(System.currentTimeMillis() - auctionLastUpdate > 1000*60*120) { //2 hours craftCost.clear(); - System.out.println("UPDATING PRICE INFORMATION"); + System.out.println("[NEU] UPDATING PRICE INFORMATION"); auctionLastUpdate = System.currentTimeMillis(); try(Reader inReader = new InputStreamReader(new GZIPInputStream(new URL(AUCTIONS_PRICE_URL).openStream()))) { auctionPricesJson = gson.fromJson(inReader, JsonObject.class); @@ -349,7 +351,7 @@ public class NEUManager { BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); JsonObject json = gson.fromJson(reader, JsonObject.class); return json; - } catch(Exception e) { return null; } + } catch(Exception e) { e.printStackTrace(); return null; } } /** @@ -389,7 +391,6 @@ public class NEUManager { if (Display.isActive()) dialog.toFront(); if (changedFiles != null && changedFiles.size() <= 20) { - String startMessage = "NotEnoughUpdates: Syncing with remote repository ("; int downloaded = 0; @@ -403,6 +404,7 @@ public class NEUManager { File item = new File(repoLocation, name); try { + item.getParentFile().mkdirs(); item.createNewFile(); } catch (IOException e) { } @@ -810,6 +812,7 @@ public class NEUManager { public JsonObject getJsonFromItemBytes(String item_bytes) { try { NBTTagCompound tag = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes))); + //System.out.println(tag.toString()); return getJsonFromNBT(tag); } catch(IOException e) { return null; @@ -873,7 +876,12 @@ public class NEUManager { } public JsonObject getJsonFromNBT(NBTTagCompound tag) { - tag = tag.getTagList("i", 10).getCompoundTagAt(0); + return getJsonFromNBTEntry(tag.getTagList("i", 10).getCompoundTagAt(0)); + } + + public JsonObject getJsonFromNBTEntry(NBTTagCompound tag) { + if(tag.getKeySet().size() == 0) return null; + int id = tag.getShort("id"); int damage = tag.getShort("Damage"); int count = tag.getShort("Count"); @@ -882,6 +890,7 @@ public class NEUManager { if(id == 141) id = 391; //for some reason hypixel thinks carrots have id 141 String internalname = getInternalnameFromNBT(tag); + if(internalname == null) return null; NBTTagCompound display = tag.getCompoundTag("display"); String[] lore = getLoreFromNBT(tag); @@ -896,15 +905,25 @@ public class NEUManager { String clickcommand = ""; - //public JsonObject createItemJson(String internalname, String itemid, String displayname, String[] lore, - // String crafttext, String infoType, String[] info, - // String clickcommand, int damage, NBTTagCompound nbttag) { JsonObject item = new JsonObject(); item.addProperty("internalname", internalname); item.addProperty("itemid", itemid); item.addProperty("displayname", displayname); + if(tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + if (ea.hasKey("new_year_cake_bag_data", 7)) { + byte[] bytes = ea.getByteArray("new_year_cake_bag_data"); + JsonArray bytesArr = new JsonArray(); + for(byte b : bytes) { + bytesArr.add(new JsonPrimitive(b)); + } + item.add("item_contents", bytesArr); + } + } + if(lore != null && lore.length > 0) { JsonArray jsonLore = new JsonArray(); for (String line : lore) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 23def271..a33c13b3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -1097,6 +1097,9 @@ public class NEUOverlay extends Gui { case "ducttapedigger": searchedItems.add(CustomItems.DUCTTAPE); break; + case "thirtyvirus": + searchedItems.add(manager.getItemInformation().get("SPIKED_BAIT")); + break; } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index a589fe2b..a7a30233 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -11,6 +11,8 @@ import io.github.moulberry.notenoughupdates.commands.SimpleCommand; import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.infopanes.CollectionLogInfoPane; import io.github.moulberry.notenoughupdates.infopanes.CosmeticsInfoPane; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.questing.GuiQuestLine; import io.github.moulberry.notenoughupdates.questing.NEUQuesting; import io.github.moulberry.notenoughupdates.util.Utils; @@ -29,6 +31,7 @@ import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.scoreboard.ScoreObjective; @@ -129,6 +132,37 @@ public class NotEnoughUpdates { } }); + private static ProfileViewer profileViewer; + + SimpleCommand viewProfileCommand = new SimpleCommand("neuprofile", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + if(args.length != 1) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "idiot.")); + } + profileViewer.getProfileByName(args[0], profile -> { + openGui = new GuiProfileViewer(profile); + }); + } + }); + + SimpleCommand linksCommand = new SimpleCommand("neulinks", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + File repo = manager.repoLocation; + if(repo.exists()) { + File updateJson = new File(repo, "update.json"); + try { + JsonObject update = manager.getJsonFromFile(updateJson); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + displayLinks(update); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } catch (Exception ignored) { + } + } + } + }); + SimpleCommand overlayPlacementsCommand = new SimpleCommand("neuoverlay", new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { openGui = new NEUOverlayPlacements(); @@ -175,6 +209,8 @@ public class NotEnoughUpdates { f.mkdirs(); ClientCommandHandler.instance.registerCommand(collectionLogCommand); ClientCommandHandler.instance.registerCommand(cosmeticsCommand); + ClientCommandHandler.instance.registerCommand(linksCommand); + ClientCommandHandler.instance.registerCommand(viewProfileCommand); ClientCommandHandler.instance.registerCommand(overlayPlacementsCommand); //ClientCommandHandler.instance.registerCommand(questingCommand); ClientCommandHandler.instance.registerCommand(neuAhCommand); @@ -183,6 +219,7 @@ public class NotEnoughUpdates { manager = new NEUManager(this, neuio, f); manager.loadItemInformation(); overlay = new NEUOverlay(manager); + profileViewer = new ProfileViewer(manager); for(KeyBinding kb : manager.keybinds) { ClientRegistry.registerKeyBinding(kb); @@ -203,7 +240,7 @@ public class NotEnoughUpdates { })); //TODO: login code. Ignore this, used for testing. - /*try { + try { Field field = Minecraft.class.getDeclaredField("session"); YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString()) @@ -232,7 +269,7 @@ public class NotEnoughUpdates { field.setAccessible(true); field.set(Minecraft.getMinecraft(), session); } catch (NoSuchFieldException | AuthenticationException | IllegalAccessException e) { - }*/ + } } /** @@ -250,6 +287,98 @@ public class NotEnoughUpdates { } } + private void displayLinks(JsonObject update) { + String discord_link = update.get("discord_link").getAsString(); + String youtube_link = update.get("youtube_link").getAsString(); + String update_link = update.get("update_link").getAsString(); + String github_link = update.get("github_link").getAsString(); + String other_text = update.get("other_text").getAsString(); + String other_link = update.get("other_link").getAsString(); + + ChatComponentText other = null; + if(other_text.length() > 0) { + other = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+other_text+EnumChatFormatting.GRAY+"]"); + other.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, other_link)); + } + ChatComponentText links = new ChatComponentText(""); + ChatComponentText separator = new ChatComponentText( + EnumChatFormatting.GRAY+EnumChatFormatting.BOLD.toString()+EnumChatFormatting.STRIKETHROUGH+(other==null?"---":"--")); + ChatComponentText discord = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+"Discord"+EnumChatFormatting.GRAY+"]"); + discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link)); + ChatComponentText youtube = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.RED+"YouTube"+EnumChatFormatting.GRAY+"]"); + youtube.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, youtube_link)); + ChatComponentText release = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.GREEN+"Release"+EnumChatFormatting.GRAY+"]"); + release.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, update_link)); + ChatComponentText github = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.DARK_PURPLE+"GitHub"+EnumChatFormatting.GRAY+"]"); + github.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, github_link)); + + + links.appendSibling(separator); + links.appendSibling(discord); + links.appendSibling(separator); + links.appendSibling(youtube); + links.appendSibling(separator); + links.appendSibling(release); + links.appendSibling(separator); + links.appendSibling(github); + links.appendSibling(separator); + if(other != null) { + links.appendSibling(other); + links.appendSibling(separator); + } + + Minecraft.getMinecraft().thePlayer.addChatMessage(links); + } + + private boolean displayUpdateMessageIfOutOfDate() { + File repo = manager.repoLocation; + if(repo.exists()) { + File updateJson = new File(repo, "update.json"); + try { + JsonObject o = manager.getJsonFromFile(updateJson); + + String version = o.get("version").getAsString(); + + if(!VERSION.equalsIgnoreCase(version)) { + String update_msg = o.get("update_msg").getAsString(); + String discord_link = o.get("discord_link").getAsString(); + String youtube_link = o.get("youtube_link").getAsString(); + String update_link = o.get("update_link").getAsString(); + String github_link = o.get("github_link").getAsString(); + String other_text = o.get("other_text").getAsString(); + String other_link = o.get("other_link").getAsString(); + + int first_len = -1; + for(String line : update_msg.split("\n")) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int len = fr.getStringWidth(line); + if(first_len == -1) { + first_len = len; + } + int missing_len = first_len-len; + if(missing_len > 0) { + StringBuilder sb = new StringBuilder(line); + for(int i=0; i<missing_len/8; i++) { + sb.insert(0, " "); + } + line = sb.toString(); + } + line = line.replaceAll("\\{version}", version); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); + } + + displayLinks(o); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + + } + + return true; + } catch(Exception ignored) {} + } + return false; + } + /** * 1)Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message. * This is used in order to prevent the mod spamming messages. @@ -265,80 +394,8 @@ public class NotEnoughUpdates { if(hasSkyblockScoreboard()) { manager.auctionManager.tick(); if(!joinedSB && manager.config.showUpdateMsg.value) { - File repo = manager.repoLocation; - if(repo.exists()) { - File updateJson = new File(repo, "update.json"); - try { - JsonObject o = manager.getJsonFromFile(updateJson); - - String version = o.get("version").getAsString(); - - if(!VERSION.equalsIgnoreCase(version)) { - String update_msg = o.get("update_msg").getAsString(); - String discord_link = o.get("discord_link").getAsString(); - String youtube_link = o.get("youtube_link").getAsString(); - String update_link = o.get("update_link").getAsString(); - String github_link = o.get("github_link").getAsString(); - String other_text = o.get("other_text").getAsString(); - String other_link = o.get("other_link").getAsString(); - - int first_len = -1; - for(String line : update_msg.split("\n")) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int len = fr.getStringWidth(line); - if(first_len == -1) { - first_len = len; - } - int missing_len = first_len-len; - if(missing_len > 0) { - StringBuilder sb = new StringBuilder(line); - for(int i=0; i<missing_len/8; i++) { - sb.insert(0, " "); - } - line = sb.toString(); - } - line = line.replaceAll("\\{version}", version); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); - } - ChatComponentText other = null; - if(other_text.length() > 0) { - other = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+other_text+EnumChatFormatting.GRAY+"]"); - other.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, other_link)); - } - ChatComponentText links = new ChatComponentText(""); - ChatComponentText separator = new ChatComponentText( - EnumChatFormatting.GRAY+EnumChatFormatting.BOLD.toString()+EnumChatFormatting.STRIKETHROUGH+(other==null?"---":"--")); - ChatComponentText discord = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+"Discord"+EnumChatFormatting.GRAY+"]"); - discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link)); - ChatComponentText youtube = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.RED+"YouTube"+EnumChatFormatting.GRAY+"]"); - youtube.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, youtube_link)); - ChatComponentText release = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.GREEN+"Release"+EnumChatFormatting.GRAY+"]"); - release.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, update_link)); - ChatComponentText github = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.DARK_PURPLE+"GitHub"+EnumChatFormatting.GRAY+"]"); - github.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, github_link)); - - - links.appendSibling(separator); - links.appendSibling(discord); - links.appendSibling(separator); - links.appendSibling(youtube); - links.appendSibling(separator); - links.appendSibling(release); - links.appendSibling(separator); - links.appendSibling(github); - links.appendSibling(separator); - if(other != null) { - links.appendSibling(other); - links.appendSibling(separator); - } - - Minecraft.getMinecraft().thePlayer.addChatMessage(links); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - - } - - joinedSB = true; - } catch(Exception ignored) {} + if(displayUpdateMessageIfOutOfDate()) { + joinedSB = false; } } //NEUQuesting.getInstance().tick(); @@ -387,7 +444,6 @@ public class NotEnoughUpdates { } } } else { - for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { processUniqueStack(stack, newItem); } @@ -407,6 +463,7 @@ public class NotEnoughUpdates { if(newItemAddMap.containsKey(internalname)) { if(System.currentTimeMillis() - newItemAddMap.get(internalname) > 1000) { log.add(internalname); + try { manager.saveConfig(); } catch(IOException ignored) {} } } else { newItemAddMap.put(internalname, System.currentTimeMillis()); @@ -732,7 +789,10 @@ public class NotEnoughUpdates { ItemStack item = lower.getStackInSlot(11+i); String internal = manager.getInternalNameForItem(item); if(internal != null) { - int worth = manager.auctionManager.getLowestBin(internal); + float worth = manager.auctionManager.getLowestBin(internal); + + if(worth == -1) worth = manager.getCraftCost(internal).craftCost; + if(worth > 0) { totalValue += worth; } else { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index 20ac86ba..65f6545e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -19,6 +19,7 @@ import net.minecraft.util.EnumChatFormatting; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; public class APIManager { @@ -60,6 +61,8 @@ public class APIManager { customAH = new CustomAH(manager); } + private AtomicInteger playerInfoVersion = new AtomicInteger(0); + public JsonObject getPlayerInformation() { if(playerInformation == null) return null; for(int i=0; i<playerInformation.size(); i++) { @@ -75,6 +78,14 @@ public class APIManager { return null; } + public int getPlayerInfoVersion() { + return playerInfoVersion.get(); + } + + public void incPlayerInfoVersion() { + playerInfoVersion.incrementAndGet(); + } + public TreeMap<String, Auction> getAuctionItems() { return auctionMap; } @@ -158,6 +169,7 @@ public class APIManager { manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles", args, jsonObject -> { if(jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + incPlayerInfoVersion(); playerInformation = jsonObject.get("profiles").getAsJsonArray(); if(playerInformation == null) return; String backup = null; @@ -332,6 +344,8 @@ public class APIManager { if(contains) { if(line.trim().contains(rarity + " " + typeMatches[j])) { return j; + } else if(line.trim().contains(rarity + " DUNGEON " + typeMatches[j])) { + return j; } } else { if(line.trim().endsWith(rarity + " " + typeMatches[j])) { @@ -464,7 +478,7 @@ public class APIManager { //Categories String category = sbCategory; - int itemType = checkItemType(item_lore, false,"SWORD", "FISHING ROD", "PICKAXE", + int itemType = checkItemType(item_lore, true,"SWORD", "FISHING ROD", "PICKAXE", "AXE", "SHOVEL", "PET ITEM", "TRAVEL SCROLL", "REFORGE STONE", "BOW"); if(itemType >= 0 && itemType < categoryItemType.length) { category = categoryItemType[itemType]; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java new file mode 100644 index 00000000..81ecc9b4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java @@ -0,0 +1,315 @@ +package io.github.moulberry.notenoughupdates.profileviewer; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.mojang.authlib.properties.Property; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.TexLoc; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.client.resources.SkinManager; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.Charsets; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + +public class GuiProfileViewer extends GuiScreen { + + public static final ResourceLocation pv_basic = new ResourceLocation("notenoughupdates:pv_basic.png"); + + private final ProfileViewer.Profile profile; + private ProfileViewerPage currentPage = ProfileViewerPage.BASIC; + private int sizeX; + private int sizeY; + private int guiLeft; + private int guiTop; + + public enum ProfileViewerPage { + BASIC + } + + public GuiProfileViewer(ProfileViewer.Profile profile) { + this.profile = profile; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + drawDefaultBackground(); + + switch (currentPage) { + case BASIC: + drawBasicPage(mouseX, mouseY, partialTicks); + break; + } + + } + + private String niceUuid(String uuidStr) { + if(uuidStr.length()!=32) return uuidStr; + + StringBuilder niceAucId = new StringBuilder(); + niceAucId.append(uuidStr, 0, 8); + niceAucId.append("-"); + niceAucId.append(uuidStr, 8, 12); + niceAucId.append("-"); + niceAucId.append(uuidStr, 12, 16); + niceAucId.append("-"); + niceAucId.append(uuidStr, 16, 20); + niceAucId.append("-"); + niceAucId.append(uuidStr, 20, 32); + return niceAucId.toString(); + } + + private EntityOtherPlayerMP entityPlayer = null; + private ResourceLocation playerLocationSkin = null; + private ResourceLocation playerLocationCape = null; + private String skinType = null; + + TexLoc tl = new TexLoc(0, 0, Keyboard.KEY_M); + TexLoc tl2 = new TexLoc(0, 0, Keyboard.KEY_B); + TexLoc tl3 = new TexLoc(0, 0, Keyboard.KEY_J); + private void drawBasicPage(int mouseX, int mouseY, float partialTicks) { + this.sizeX = 431; + this.sizeY = 202; + this.guiLeft = (this.width-this.sizeX)/2; + this.guiTop = (this.height-this.sizeY)/2; + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_basic); + Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); + + tl.handleKeyboardInput(); + tl2.handleKeyboardInput(); + tl3.handleKeyboardInput(); + + if(entityPlayer == null) { + UUID playerUUID = UUID.fromString(niceUuid(profile.getUuid())); + GameProfile fakeProfile = Minecraft.getMinecraft().getSessionService().fillProfileProperties(new GameProfile(playerUUID, "CoolGuy123"), false); + for(Property prop : fakeProfile.getProperties().get("textures")) { + System.out.println(new String(Base64.decodeBase64(prop.getValue()), Charsets.UTF_8)); + } + entityPlayer = new EntityOtherPlayerMP(Minecraft.getMinecraft().theWorld, fakeProfile) { + public ResourceLocation getLocationSkin() { + return playerLocationSkin == null ? DefaultPlayerSkin.getDefaultSkin(this.getUniqueID()) : playerLocationSkin; + } + + public ResourceLocation getLocationCape() { + return playerLocationCape; + } + + public String getSkinType() { + return skinType == null ? DefaultPlayerSkin.getSkinType(this.getUniqueID()) : skinType; + } + }; + } + + JsonObject profileInfo = profile.getProfileInformation(null); + if(profileInfo == null) return; + + JsonObject skillInfo = profile.getSkillInfo(null); + JsonObject inventoryInfo = profile.getInventoryInfo(null); + JsonObject collectionInfo =profile. getCollectionInfo(null); + + if(inventoryInfo != null && inventoryInfo.has("inv_armor")) { + JsonArray items = inventoryInfo.get("inv_armor").getAsJsonArray(); + for(int i=0; i<entityPlayer.inventory.armorInventory.length; i++) { + JsonElement itemElement = items.get(i); + if(itemElement != null && itemElement.isJsonObject()) { + entityPlayer.inventory.armorInventory[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(itemElement.getAsJsonObject(), false); + } + } + } + if(playerLocationSkin == null) { + try { + Minecraft.getMinecraft().getSkinManager().loadProfileTextures(entityPlayer.getGameProfile(), new SkinManager.SkinAvailableCallback() { + public void skinAvailable(MinecraftProfileTexture.Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) { + switch (type) { + case SKIN: + playerLocationSkin = location; + skinType = profileTexture.getMetadata("model"); + + if(skinType == null) { + skinType = "default"; + } + + break; + case CAPE: + playerLocationCape = location; + } + } + }, false); + } catch(Exception e){} + } + + drawEntityOnScreen(guiLeft+63, guiTop+129, 30, guiLeft+63-mouseX, guiTop+129-mouseY, entityPlayer); + + + PlayerStats.Stats stats = profile.getStats(null); + + for(int i=0; i<PlayerStats.defaultStatNames.length; i++) { + String statName = PlayerStats.defaultStatNames[i]; + String statNamePretty = PlayerStats.defaultStatNamesPretty[i]; + + int val = Math.round(stats.get(statName)); + + + + for(int xOff=-1; xOff<=1; xOff++) { + for(int yOff=-1; yOff<=1; yOff++) { + if(Math.abs(xOff) != Math.abs(yOff)) { + //Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(statNamePretty) + " " + val, Minecraft.getMinecraft().fontRendererObj, + // guiLeft+172f+xOff, guiTop+36+12.5f*i+yOff, false, 85, new Color(100, 100, 100, 100).getRGB()); + } + } + } + + GlStateManager.color(1, 1, 1, 1); + Utils.drawStringCenteredScaledMaxWidth(statNamePretty + " " + EnumChatFormatting.WHITE + val, Minecraft.getMinecraft().fontRendererObj, + guiLeft+172f, guiTop+36+12.5f*i, true, 85, Color.BLACK.getRGB()); + } + + int position = 0; + for(Map.Entry<String, String> entry : skillToSkillNameMap.entrySet()) { + int yPosition = position % 7; + int xPosition = position / 7; + + String skillName = entry.getValue(); + + float level = (int)skillInfo.get(entry.getKey()).getAsFloat(); + + for(int xOff=-1; xOff<=1; xOff++) { + for(int yOff=-1; yOff<=1; yOff++) { + if(Math.abs(xOff) != Math.abs(yOff)) { + //Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(skillName) + " " + level, Minecraft.getMinecraft().fontRendererObj, + // guiLeft+tl.x+tl2.x*xPosition+xOff, guiTop+tl.y+tl2.y*yPosition+yOff, false, 85, new Color(100, 100, 100, 100).getRGB()); + } + } + } + + GlStateManager.color(1, 1, 1, 1); + Utils.drawStringCenteredScaledMaxWidth(skillName + " " + EnumChatFormatting.WHITE + level, Minecraft.getMinecraft().fontRendererObj, + guiLeft+277+86*xPosition, guiTop+36+21*yPosition, true, 85, Color.BLACK.getRGB()); + + position++; + } + } + + private static final LinkedHashMap<String, String> skillToSkillNameMap = new LinkedHashMap<>(); + static { + skillToSkillNameMap.put("level_skill_taming", "Taming"); + skillToSkillNameMap.put("level_skill_mining", "Mining"); + skillToSkillNameMap.put("level_skill_foraging", "Foraging"); + skillToSkillNameMap.put("level_skill_enchanting", "Enchanting"); + skillToSkillNameMap.put("level_skill_carpentry", "Carpentry"); + skillToSkillNameMap.put("level_skill_farming", "Farming"); + skillToSkillNameMap.put("level_skill_combat", "Combat"); + skillToSkillNameMap.put("level_skill_fishing", "Fishing"); + skillToSkillNameMap.put("level_skill_alchemy", "Alchemy"); + skillToSkillNameMap.put("level_skill_runecrafting", "Runecrafting"); + skillToSkillNameMap.put("level_slayer_zombie", "Revenant Slayer"); + skillToSkillNameMap.put("level_slayer_spider", "Tarantula Slayer"); + skillToSkillNameMap.put("level_slayer_wolf", "Sven Slayer"); + } + + /*private void renderBar(float x, float y, float xSize, float ySize, float completed) { + this.mc.getTextureManager().bindTexture(Gui.icons); + + float yScale = ySize/5; + + + if (i > 0) + { + int j = 182; + int k = (int)(this.mc.thePlayer.experience * (float)(j + 1)); + int l = p_175176_1_.getScaledHeight() - 32 + 3; + + Utils.drawTexturedRect(x, y, xSize, ); + + this.drawTexturedModalRect(p_175176_2_, l, 0, 64, j, 5); + + if (k > 0) + { + this.drawTexturedModalRect(p_175176_2_, l, 0, 69, k, 5); + } + } + + if (this.mc.thePlayer.experienceLevel > 0) + { + this.mc.mcProfiler.startSection("expLevel"); + int k1 = 8453920; + String s = "" + this.mc.thePlayer.experienceLevel; + int l1 = (p_175176_1_.getScaledWidth() - this.getFontRenderer().getStringWidth(s)) / 2; + int i1 = p_175176_1_.getScaledHeight() - 31 - 4; + int j1 = 0; + this.getFontRenderer().drawString(s, l1 + 1, i1, 0); + this.getFontRenderer().drawString(s, l1 - 1, i1, 0); + this.getFontRenderer().drawString(s, l1, i1 + 1, 0); + this.getFontRenderer().drawString(s, l1, i1 - 1, 0); + this.getFontRenderer().drawString(s, l1, i1, k1); + this.mc.mcProfiler.endSection(); + } + }*/ + + public static void drawEntityOnScreen(int posX, int posY, int scale, float mouseX, float mouseY, EntityLivingBase ent) { + GlStateManager.enableColorMaterial(); + GlStateManager.pushMatrix(); + GlStateManager.translate((float)posX, (float)posY, 50.0F); + GlStateManager.scale((float)(-scale), (float)scale, (float)scale); + GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); + float f = ent.renderYawOffset; + float f1 = ent.rotationYaw; + float f2 = ent.rotationPitch; + float f3 = ent.prevRotationYawHead; + float f4 = ent.rotationYawHead; + GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F); + RenderHelper.enableStandardItemLighting(); + GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(-((float)Math.atan((double)(mouseY / 40.0F))) * 20.0F, 1.0F, 0.0F, 0.0F); + ent.renderYawOffset = (float)Math.atan((double)(mouseX / 40.0F)) * 20.0F; + ent.rotationYaw = (float)Math.atan((double)(mouseX / 40.0F)) * 40.0F; + ent.rotationPitch = -((float)Math.atan((double)(mouseY / 40.0F))) * 20.0F; + ent.rotationYawHead = ent.rotationYaw; + ent.prevRotationYawHead = ent.rotationYaw; + GlStateManager.translate(0.0F, 0.0F, 0.0F); + RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager(); + rendermanager.setPlayerViewY(180.0F); + rendermanager.setRenderShadow(false); + rendermanager.renderEntityWithPosYaw(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F); + rendermanager.setRenderShadow(true); + ent.renderYawOffset = f; + ent.rotationYaw = f1; + ent.rotationPitch = f2; + ent.prevRotationYawHead = f3; + ent.rotationYawHead = f4; + GlStateManager.popMatrix(); + RenderHelper.disableStandardItemLighting(); + GlStateManager.disableRescaleNormal(); + GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); + GlStateManager.disableTexture2D(); + GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java new file mode 100644 index 00000000..25b7356d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java @@ -0,0 +1,537 @@ +package io.github.moulberry.notenoughupdates.profileviewer; + +import com.google.gson.*; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.nbt.*; +import net.minecraft.util.EnumChatFormatting; +import org.apache.commons.lang3.StringUtils; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Base64; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PlayerStats { + public static final String HEALTH = "health"; + public static final String DEFENCE = "defence"; + public static final String STRENGTH = "strength"; + public static final String SPEED = "speed"; + public static final String CRIT_CHANCE = "crit_chance"; + public static final String CRIT_DAMAGE = "crit_damage"; + public static final String BONUS_ATTACK_SPEED = "bonus_attack_speed"; + public static final String INTELLIGENCE = "intelligence"; + public static final String SEA_CREATURE_CHANCE = "sea_creature_chance"; + public static final String MAGIC_FIND = "magic_find"; + public static final String PET_LUCK = "pet_luck"; + + public static final String[] defaultStatNames = new String[]{"health","defence","strength","speed","crit_chance", + "crit_damage","bonus_attack_speed","intelligence","sea_creature_chance","magic_find","pet_luck"}; + public static final String[] defaultStatNamesPretty = new String[]{EnumChatFormatting.RED+"\u2764 Health",EnumChatFormatting.GREEN+"\u2748 Defence", + EnumChatFormatting.RED+"\u2741 Strength",EnumChatFormatting.WHITE+"\u2726 Speed",EnumChatFormatting.BLUE+"\u2623 Crit Chance", + EnumChatFormatting.BLUE+"\u2620 Crit Damage",EnumChatFormatting.YELLOW+"\u2694 Attack Speed",EnumChatFormatting.AQUA+"\u270e Intelligence", + EnumChatFormatting.DARK_AQUA+"\u03b1 SC Chance",EnumChatFormatting.AQUA+"\u272f Magic Find",EnumChatFormatting.LIGHT_PURPLE+"\u2663 Pet Luck"}; + + public static class Stats { + JsonObject statsJson = new JsonObject(); + + /*public float health; + public float defence; + public float strength; + public float speed; + public float crit_chance; + public float crit_damage; + public float bonus_attack_speed; + public float intelligence; + public float sea_creature_chance; + public float magic_find; + public float pet_luck;*/ + + public Stats(Stats... statses) { + for(Stats stats : statses) { + add(stats); + } + } + + /*@Override + public String toString() { + return String.format("{health=%s,defence=%s,strength=%s,speed=%s,crit_chance=%s,crit_damage=%s," + + "bonus_attack_speed=%s,intelligence=%s,sea_creature_chance=%s,magic_find=%s,pet_luck=%s}", + stats.get("health"), defence, strength, speed, crit_chance, crit_damage, bonus_attack_speed, intelligence, + sea_creature_chance, magic_find, pet_luck); + }*/ + + public float get(String statName) { + if(statsJson.has(statName)) { + return statsJson.get(statName).getAsFloat(); + } else { + return 0; + } + } + + public Stats add(Stats stats) { + for(Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) { + if(statEntry.getValue().isJsonPrimitive() && ((JsonPrimitive)statEntry.getValue()).isNumber()) { + if(!statsJson.has(statEntry.getKey())) { + statsJson.add(statEntry.getKey(), statEntry.getValue()); + } else { + JsonPrimitive e = statsJson.get(statEntry.getKey()).getAsJsonPrimitive(); + float statNum = e.getAsFloat() + statEntry.getValue().getAsFloat(); + statsJson.add(statEntry.getKey(), new JsonPrimitive(statNum)); + } + } + } + return this; + } + + public void scaleAll(float scale) { + for(Map.Entry<String, JsonElement> statEntry : statsJson.entrySet()) { + statsJson.add(statEntry.getKey(), new JsonPrimitive(statEntry.getValue().getAsFloat()*scale)); + } + } + + public void addStat(String statName, float amount) { + if(!statsJson.has(statName)) { + statsJson.add(statName, new JsonPrimitive(amount)); + } else { + JsonPrimitive e = statsJson.get(statName).getAsJsonPrimitive(); + statsJson.add(statName, new JsonPrimitive(e.getAsFloat() + amount)); + } + } + } + + public static Stats getBaseStats() { + JsonObject misc = Utils.getConstant("misc"); + if(misc == null) return null; + + Stats stats = new Stats(); + for(String statName : defaultStatNames) { + stats.addStat(statName, Utils.getElementAsFloat(Utils.getElement(misc, "base_stats."+statName), 0)); + } + return stats; + } + + public static Stats getFairyBonus(int fairyExchanges) { + Stats bonus = new Stats(); + + bonus.addStat(SPEED, fairyExchanges/10); + + for(int i=0; i<fairyExchanges; i++) { + bonus.addStat(STRENGTH, (i + 1) % 5 == 0 ? 2 : 1); + bonus.addStat(DEFENCE, (i + 1) % 5 == 0 ? 2 : 1); + bonus.addStat(HEALTH, 3 + i / 2); + } + + return bonus; + } + + public static Stats getSkillBonus(JsonObject skillInfo) { + JsonObject bonuses = Utils.getConstant("bonuses"); + if(bonuses == null) return null; + + Stats skillBonus = new Stats(); + + for(Map.Entry<String, JsonElement> entry : skillInfo.entrySet()) { + if(entry.getKey().startsWith("level_")) { + String skill = entry.getKey().substring("level_".length()); + JsonObject skillStatMap = Utils.getElement(bonuses, "bonus_stats."+skill).getAsJsonObject(); + + Stats currentBonus = new Stats(); + for(int i=1; i<=entry.getValue().getAsFloat(); i++) { + if(skillStatMap.has(""+i)) { + currentBonus = new Stats(); + for(Map.Entry<String, JsonElement> entry2 : skillStatMap.get(""+i).getAsJsonObject().entrySet()) { + currentBonus.addStat(entry2.getKey(), entry2.getValue().getAsFloat()); + } + } + skillBonus.add(currentBonus); + } + } + } + + return skillBonus; + } + + public static Stats getPetBonus(JsonObject profile) { + JsonObject bonuses = Utils.getConstant("bonuses"); + if(bonuses == null) return null; + + JsonElement petsElement = Utils.getElement(profile, "pets"); + if(petsElement == null) return new Stats(); + + JsonArray pets = petsElement.getAsJsonArray(); + + HashMap<String, String> highestRarityMap = new HashMap<>(); + + for(int i=0; i<pets.size(); i++) { + JsonObject pet = pets.get(i).getAsJsonObject(); + highestRarityMap.put(pet.get("type").getAsString(), pet.get("tier").getAsString()); + } + + int petScore = 0; + for(String value : highestRarityMap.values()) { + petScore += Utils.getElementAsFloat(Utils.getElement(bonuses, "pet_value."+value.toUpperCase()), 0); + } + + JsonElement petRewardsElement = Utils.getElement(bonuses, "pet_rewards"); + if(petRewardsElement == null) return null; + JsonObject petRewards = petRewardsElement.getAsJsonObject(); + + Stats petBonus = new Stats(); + for(int i=0; i<=petScore; i++) { + if(petRewards.has(""+i)) { + petBonus = new Stats(); + for(Map.Entry<String, JsonElement> entry : petRewards.get(""+i).getAsJsonObject().entrySet()) { + petBonus.addStat(entry.getKey(), entry.getValue().getAsFloat()); + } + } + } + return petBonus; + } + + public static float harpBonus(JsonObject profile) { + String talk_to_melody = Utils.getElementAsString(Utils.getElement(profile, "objectives.talk_to_melody.status"), "INCOMPLETE"); + if(talk_to_melody.equalsIgnoreCase("COMPLETE")) { + return 26; + } else { + return 0; + } + } + + + public static Stats getPassiveBonuses(JsonObject skillInfo, JsonObject profile) { + Stats passiveBonuses = new Stats(); + + //TODO: null checking + Stats fairyBonus = getFairyBonus((int)Utils.getElementAsFloat(Utils.getElement(profile, "fairy_exchanges"), 0)); + Stats skillBonus = getSkillBonus(skillInfo); + Stats petBonus = getPetBonus(profile); + + if(fairyBonus == null || skillBonus == null || petBonus == null) return null; + + passiveBonuses.add(fairyBonus); + passiveBonuses.add(skillBonus); + passiveBonuses.addStat(INTELLIGENCE, harpBonus(profile)); + passiveBonuses.add(petBonus); + + return passiveBonuses; + } + + public static String getFullset(JsonArray armor, int ignore) { + String fullset = null; + for(int i=0; i<armor.size(); i++) { + if(i == ignore) continue; + + JsonElement itemElement = armor.get(i); + if(itemElement == null || !itemElement.isJsonObject()) { + fullset = null; + break; + } + JsonObject item = itemElement.getAsJsonObject(); + String internalname = item.get("internalname").getAsString(); + + String[] split = internalname.split("_"); + split[split.length-1] = ""; + String armorname = StringUtils.join(split, "_"); + + if(fullset == null) { + fullset = armorname; + } else if(!fullset.equalsIgnoreCase(armorname)){ + fullset = null; + break; + } + } + return fullset; + } + + public static Stats getSetBonuses(Stats stats, JsonObject inventoryInfo, JsonObject collectionInfo, JsonObject skillInfo, JsonObject profile) { + JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); + + Stats bonuses = new Stats(); + + String fullset = getFullset(armor, -1); + + if(fullset != null) { + switch(fullset) { + case "LAPIS_ARMOR_": + bonuses.addStat(HEALTH, 60); + break; + case "EMERALD_ARMOR_": + { + int bonus = (int)Math.floor(Utils.getElementAsFloat(Utils.getElement(collectionInfo, "EMERALD"), 0)/3000); + bonuses.addStat(HEALTH, bonus); + bonuses.addStat(DEFENCE, bonus); + } + break; + case "FAIRY_": + bonuses.addStat(HEALTH, Utils.getElementAsFloat(Utils.getElement(profile, "fairy_souls_collected"), 0)); + break; + case "SPEEDSTER_": + bonuses.addStat(SPEED, 20); + break; + case "YOUNG_DRAGON_": + bonuses.addStat(SPEED, 70); + break; + case "MASTIFF_": + bonuses.addStat(HEALTH, 50*Math.round(stats.get(CRIT_DAMAGE))); + break; + case "ANGLER_": + bonuses.addStat(HEALTH, 10*(float)Math.floor(Utils.getElementAsFloat(Utils.getElement(skillInfo, "level_skill_fishing"), 0))); + bonuses.addStat(SEA_CREATURE_CHANCE, 4); + break; + case "ARMOR_OF_MAGMA_": + int bonus = (int)Math.min(200, Math.floor(Utils.getElementAsFloat(Utils.getElement(profile, "stats.kills_magma_cube"), 0)/10)); + bonuses.addStat(HEALTH, bonus); + bonuses.addStat(INTELLIGENCE, bonus); + case "OLD_DRAGON_": + bonuses.addStat(HEALTH, 200); + bonuses.addStat(DEFENCE, 40); + break; + } + } + + JsonElement chestplateElement = armor.get(2); + if(chestplateElement != null && chestplateElement.isJsonObject()) { + JsonObject chestplate = chestplateElement.getAsJsonObject(); + if(chestplate.get("internalname").getAsString().equals("OBSIDIAN_CHESTPLATE")) { + JsonArray inventory = Utils.getElement(inventoryInfo, "inv_contents").getAsJsonArray(); + for(int i=0; i<inventory.size(); i++) { + JsonElement itemElement = inventory.get(i); + if(itemElement != null && itemElement.isJsonObject()) { + JsonObject item = itemElement.getAsJsonObject(); + if(item.get("internalname").getAsString().equals("OBSIDIAN")) { + int count = 1; + if(item.has("count")) { + count = item.get("count").getAsInt(); + } + bonuses.addStat(SPEED, count/20); + } + } + } + } + } + + return bonuses; + } + + private static String[] rarityArr = new String[] { + "COMMON", "UNCOMMON", "RARE", "EPIC", "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", + }; + public static int checkItemType(JsonArray lore, boolean contains, String... typeMatches) { + for(int i=lore.size()-1; i>=0; i--) { + String line = lore.get(i).getAsString(); + for(String rarity : rarityArr) { + for(int j=0; j<typeMatches.length; j++) { + if(contains) { + if(line.trim().contains(rarity + " " + typeMatches[j])) { + return j; + } else if(line.trim().contains(rarity + " DUNGEON " + typeMatches[j])) { + return j; + } + } else { + if(line.trim().endsWith(rarity + " " + typeMatches[j])) { + return j; + } else if(line.trim().endsWith(rarity + " DUNGEON " + typeMatches[j])) { + return j; + } + } + } + } + } + return -1; + } + + private static final Pattern HEALTH_PATTERN = Pattern.compile("^Health: \\+([0-9]+)"); + private static final Pattern DEFENCE_PATTERN = Pattern.compile("^Defense: \\+([0-9]+)"); + private static final Pattern STRENGTH_PATTERN = Pattern.compile("^Strength: \\+([0-9]+)"); + private static final Pattern SPEED_PATTERN = Pattern.compile("^Speed: \\+([0-9]+)"); + private static final Pattern CC_PATTERN = Pattern.compile("^Crit Chance: \\+([0-9]+)"); + private static final Pattern CD_PATTERN = Pattern.compile("^Crit Damage: \\+([0-9]+)"); + private static final Pattern ATKSPEED_PATTERN = Pattern.compile("^Bonus Attack Speed: \\+([0-9]+)"); + private static final Pattern INTELLIGENCE_PATTERN = Pattern.compile("^Intelligence: \\+([0-9]+)"); + private static final Pattern SCC_PATTERN = Pattern.compile("^Sea Creature Chance: \\+([0-9]+)"); + private static final HashMap<String, Pattern> STAT_PATTERN_MAP = new HashMap<>(); + static { + STAT_PATTERN_MAP.put("health", HEALTH_PATTERN); + STAT_PATTERN_MAP.put("defence", DEFENCE_PATTERN); + STAT_PATTERN_MAP.put("strength", STRENGTH_PATTERN); + STAT_PATTERN_MAP.put("speed", SPEED_PATTERN); + STAT_PATTERN_MAP.put("crit_chance", CC_PATTERN); + STAT_PATTERN_MAP.put("crit_damage", CD_PATTERN); + STAT_PATTERN_MAP.put("bonus_attack_speed", ATKSPEED_PATTERN); + STAT_PATTERN_MAP.put("intelligence", INTELLIGENCE_PATTERN); + STAT_PATTERN_MAP.put("sea_creature_chance", SCC_PATTERN); + } + public static Stats getStatForItem(String internalname, JsonObject item, JsonArray lore) { + Stats stats = new Stats(); + for(int i=0; i<lore.size(); i++) { + String line = lore.get(i).getAsString(); + for(Map.Entry<String, Pattern> entry : STAT_PATTERN_MAP.entrySet()) { + Matcher matcher = entry.getValue().matcher(Utils.cleanColour(line)); + if(matcher.find()) { + int bonus = Integer.parseInt(matcher.group(1)); + //System.out.println(entry.getKey() + ":" + bonus); + stats.addStat(entry.getKey(), bonus); + } + } + } + if(internalname.equals("DAY_CRYSTAL") || internalname.equals("NIGHT_CRYSTAL")) { + stats.addStat(STRENGTH, 2.5f); + stats.addStat(DEFENCE, 2.5f); + System.out.println("added day"); + } + if(internalname.equals("NEW_YEAR_CAKE_BAG") && item.has("item_contents")) { + + JsonArray bytesArr = item.get("item_contents").getAsJsonArray(); + byte[] bytes = new byte[bytesArr.size()]; + for(int i=0; i<bytesArr.size(); i++) { + bytes[i] = bytesArr.get(i).getAsByte(); + } + try { + NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes)); + NBTTagList items = contents_nbt.getTagList("i", 10); + HashSet<Integer> cakes = new HashSet<>(); + for(int j=0; j<items.tagCount(); j++) { + if(items.getCompoundTagAt(j).getKeySet().size() > 0) { + NBTTagCompound nbt = items.getCompoundTagAt(j).getCompoundTag("tag"); + if(nbt != null && nbt.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = nbt.getCompoundTag("ExtraAttributes"); + if (ea.hasKey("new_years_cake")) { + cakes.add(ea.getInteger("new_years_cake")); + } + } + } + } + stats.addStat(HEALTH, cakes.size()); + } catch(IOException e) { + e.printStackTrace(); + return stats; + } + } + return stats; + } + public static Stats getItemBonuses(boolean talismanOnly, JsonArray... inventories) { + JsonObject misc = Utils.getConstant("misc"); + if(misc == null) return null; + JsonElement talisman_upgrades_element = misc.get("talisman_upgrades"); + if(talisman_upgrades_element == null) return null; + JsonObject talisman_upgrades = talisman_upgrades_element.getAsJsonObject(); + + HashMap<String, Stats> itemBonuses = new HashMap<>(); + for(JsonArray inventory : inventories) { + for(int i=0; i<inventory.size(); i++) { + JsonElement itemElement = inventory.get(i); + //if(itemElement != null) System.out.println("item element:"+itemElement.getClass()); + if(itemElement != null && itemElement.isJsonObject()) { + JsonObject item = itemElement.getAsJsonObject(); + String internalname = item.get("internalname").getAsString(); + if(itemBonuses.containsKey(internalname)) { + continue; + } + if(!talismanOnly || checkItemType(item.get("lore").getAsJsonArray(), true, "ACCESSORY") >= 0) { + Stats itemBonus = getStatForItem(internalname, item, item.get("lore").getAsJsonArray()); + + itemBonuses.put(internalname, itemBonus); + + for(Map.Entry<String, JsonElement> talisman_upgrades_item : talisman_upgrades.entrySet()) { + JsonArray upgrades = talisman_upgrades_item.getValue().getAsJsonArray(); + for(int j=0; j<upgrades.size(); j++) { + String upgrade = upgrades.get(j).getAsString(); + if(upgrade.equals(internalname)) { + itemBonuses.put(talisman_upgrades_item.getKey(), new Stats()); + break; + } + } + } + } + } + } + } + Stats itemBonusesStats = new Stats(); + for(Stats stats : itemBonuses.values()) { + itemBonusesStats.add(stats); + } + return itemBonusesStats; + } + + public static float getStatMult(JsonObject inventoryInfo) { + float mult = 1f; + + JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); + + String fullset = getFullset(armor, -1); + + if(fullset != null && fullset.equals("SUPERIOR_DRAGON_")) { + mult *= 1.05f; + } + + for(int i=0; i<armor.size(); i++) { + JsonElement itemElement = armor.get(i); + if(itemElement == null || !itemElement.isJsonObject()) continue; + + JsonObject item = itemElement.getAsJsonObject(); + String internalname = item.get("internalname").getAsString(); + + String reforge = Utils.getElementAsString(Utils.getElement(item, "ExtraAttributes.modifier"), ""); + + if(reforge.equals("renowned")) { + mult *= 1.01f; + } + } + + return mult; + } + + public static void applyLimits(Stats stats, JsonObject inventoryInfo) { + //>0 + JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); + + String fullset = getFullset(armor, 3); + + if(fullset != null) { + switch(fullset) { + case "CHEAP_TUXEDO_": + stats.statsJson.add(HEALTH, new JsonPrimitive(Math.min(75, stats.get(HEALTH)))); + case "FANCY_TUXEDO_": + stats.statsJson.add(HEALTH, new JsonPrimitive(Math.min(150, stats.get(HEALTH)))); + case "ELEGANT_TUXEDO_": + stats.statsJson.add(HEALTH, new JsonPrimitive(Math.min(250, stats.get(HEALTH)))); + } + } + + for(Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) { + stats.statsJson.add(statEntry.getKey(), new JsonPrimitive(Math.max(0, statEntry.getValue().getAsFloat()))); + } + } + + public static Stats getStats(JsonObject skillInfo, JsonObject inventoryInfo, JsonObject collectionInfo, JsonObject profile) { + JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); + JsonArray inventory = Utils.getElement(inventoryInfo, "inv_contents").getAsJsonArray(); + JsonArray talisman_bag = Utils.getElement(inventoryInfo, "talisman_bag").getAsJsonArray(); + + Stats passiveBonuses = getPassiveBonuses(skillInfo, profile); + System.out.println("passive:"+new Stats(passiveBonuses, getBaseStats())); + Stats armorBonuses = getItemBonuses(false, armor); + Stats talismanBonuses = getItemBonuses(true, inventory, talisman_bag); + + if(passiveBonuses == null) System.out.println("passive null"); + if(armorBonuses == null) System.out.println("armorBonuses null"); + if(talismanBonuses == null) System.out.println("talismanBonuses null"); + + if(passiveBonuses == null || armorBonuses == null || talismanBonuses == null) return null; + + Stats stats = getBaseStats().add(passiveBonuses).add(armorBonuses).add(talismanBonuses); + + stats.add(getSetBonuses(stats, inventoryInfo, collectionInfo, skillInfo, profile)); + + stats.scaleAll(getStatMult(inventoryInfo)); + + applyLimits(stats, inventoryInfo); + + return stats; + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java new file mode 100644 index 00000000..db90cca8 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java @@ -0,0 +1,370 @@ +package io.github.moulberry.notenoughupdates.profileviewer; + +import com.google.common.base.Splitter; +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.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.ChatComponentText; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ProfileViewer { + + private final NEUManager manager; + + public ProfileViewer(NEUManager manager) { + this.manager = manager; + } + + public class Profile { + private final String uuid; + private String latestProfile = null; + + private JsonArray playerInformation = null; + private JsonObject basicInfo = null; + + private final HashMap<String, JsonObject> profileMap = new HashMap<>(); + private final HashMap<String, JsonObject> skillInfoMap = new HashMap<>(); + private final HashMap<String, JsonObject> inventoryInfoMap = new HashMap<>(); + private final HashMap<String, JsonObject> collectionInfoMap = new HashMap<>(); + private PlayerStats.Stats stats = null; + + public Profile(String uuid) { + this.uuid = uuid; + } + + private AtomicBoolean updatingPlayerInfoState = new AtomicBoolean(false); + + public JsonArray getPlayerInformation(Runnable runnable) { + if(playerInformation != null) return playerInformation; + if(updatingPlayerInfoState.get()) return null; + + updatingPlayerInfoState.set(true); + + HashMap<String, String> args = new HashMap<>(); + args.put("uuid", ""+uuid); + manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles", + args, jsonObject -> { + updatingPlayerInfoState.set(false); + if(jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + playerInformation = jsonObject.get("profiles").getAsJsonArray(); + if(playerInformation == null) return; + String backup = null; + long backupLastSave = 0; + for(int i=0; i<playerInformation.size(); i++) { + JsonObject profile = playerInformation.get(i).getAsJsonObject(); + String cute_name = profile.get("cute_name").getAsString(); + + if(backup == null) backup = cute_name; + + if(!profile.has("members")) continue; + JsonObject members = profile.get("members").getAsJsonObject(); + + if(members.has(uuid)) { + JsonObject member = members.get(uuid).getAsJsonObject(); + long last_save = member.get("last_save").getAsLong(); + if(last_save > backupLastSave) { + backupLastSave = last_save; + backup = cute_name; + } + } + } + System.out.println("accepting runnable"); + runnable.run(); + latestProfile = backup; + } + } + ); + + return null; + } + + public JsonObject getProfileInformation(String profileId) { + JsonArray playerInfo = getPlayerInformation(() -> {}); + if(playerInfo == null) return null; + if(profileId == null) profileId = latestProfile; + if(profileMap.containsKey(profileId)) return profileMap.get(profileId); + + for(int i=0; i<playerInformation.size(); i++) { + JsonObject profile = playerInformation.get(i).getAsJsonObject(); + if(profile.get("cute_name").getAsString().equalsIgnoreCase(profileId)) { + if(!profile.has("members")) return null; + JsonObject members = profile.get("members").getAsJsonObject(); + if(!members.has(uuid)) return null; + JsonObject profileInfo = members.get(uuid).getAsJsonObject(); + if(profile.has("banking")) { + profileInfo.add("banking", profile.get("banking").getAsJsonObject()); + } + System.out.println("got profile"); + profileMap.put(profileId, profileInfo); + return profileInfo; + } + } + System.out.println("couldnt get profile"); + + return null; + } + + public void resetCache() { + playerInformation = null; + basicInfo = null; + profileMap.clear(); + skillInfoMap.clear(); + inventoryInfoMap.clear(); + collectionInfoMap.clear(); + } + + public float getLevel(JsonArray levelingArray, float xp) { + for(int level=0; level<levelingArray.size(); level++) { + float levelXp = levelingArray.get(level).getAsFloat(); + if(levelXp > xp) { + return level + xp/levelXp; + } else { + xp -= levelXp; + } + } + return levelingArray.size(); + } + + public JsonObject getSkillInfo(String profileId) { + JsonObject profileInfo = getProfileInformation(profileId); + if(profileInfo == null) return null; + if(profileId == null) profileId = latestProfile; + if(skillInfoMap.containsKey(profileId)) return skillInfoMap.get(profileId); + JsonObject leveling = Utils.getConstant("leveling"); + if(leveling == null) return null; + + float experience_skill_taming = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_taming"), 0); + float experience_skill_mining = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_mining"), 0); + float experience_skill_foraging = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_foraging"), 0); + float experience_skill_enchanting = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_enchanting"), 0); + float experience_skill_carpentry = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_carpentry"), 0); + float experience_skill_farming = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_farming"), 0); + float experience_skill_combat = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_combat"), 0); + float experience_skill_fishing = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_fishing"), 0); + float experience_skill_alchemy = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_alchemy"), 0); + float experience_skill_runecrafting = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_runecrafting"), 0); + + float experience_slayer_zombie = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.xp"), 0); + float experience_slayer_spider = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.spider.xp"), 0); + float experience_slayer_wolf = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.xp"), 0); + + float totalSkillXP = experience_skill_taming + experience_skill_mining + experience_skill_foraging + + experience_skill_enchanting + experience_skill_carpentry + experience_skill_farming + + experience_skill_combat + experience_skill_fishing + experience_skill_alchemy + + experience_skill_runecrafting; + + if(totalSkillXP <= 0) { + System.out.println("couldnt get skill xp"); + return null; + } + + JsonObject skillInfo = new JsonObject(); + + skillInfo.addProperty("experience_skill_taming", experience_skill_taming); + skillInfo.addProperty("experience_skill_mining", experience_skill_mining); + skillInfo.addProperty("experience_skill_foraging", experience_skill_foraging); + skillInfo.addProperty("experience_skill_enchanting", experience_skill_enchanting); + skillInfo.addProperty("experience_skill_carpentry", experience_skill_carpentry); + skillInfo.addProperty("experience_skill_farming", experience_skill_farming); + skillInfo.addProperty("experience_skill_combat", experience_skill_combat); + skillInfo.addProperty("experience_skill_fishing", experience_skill_fishing); + skillInfo.addProperty("experience_skill_alchemy", experience_skill_alchemy); + skillInfo.addProperty("experience_skill_runecrafting", experience_skill_runecrafting); + + skillInfo.addProperty("experience_slayer_zombie", experience_slayer_zombie); + skillInfo.addProperty("experience_slayer_spider", experience_slayer_spider); + skillInfo.addProperty("experience_slayer_wolf", experience_slayer_wolf); + + skillInfo.addProperty("level_skill_taming", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_taming)); + skillInfo.addProperty("level_skill_mining", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_mining)); + skillInfo.addProperty("level_skill_foraging", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_foraging)); + skillInfo.addProperty("level_skill_enchanting", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_enchanting)); + skillInfo.addProperty("level_skill_carpentry", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_carpentry)); + skillInfo.addProperty("level_skill_farming", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_farming)); + skillInfo.addProperty("level_skill_combat", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_combat)); + skillInfo.addProperty("level_skill_fishing", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_fishing)); + skillInfo.addProperty("level_skill_alchemy", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_alchemy)); + skillInfo.addProperty("level_skill_runecrafting", getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_runecrafting)); + + skillInfo.addProperty("level_slayer_zombie", getLevel(Utils.getElement(leveling, "slayer_xp.zombie").getAsJsonArray(), experience_slayer_zombie)); + skillInfo.addProperty("level_slayer_spider", getLevel(Utils.getElement(leveling, "slayer_xp.spider").getAsJsonArray(), experience_slayer_spider)); + skillInfo.addProperty("level_slayer_wolf", getLevel(Utils.getElement(leveling, "slayer_xp.wolf").getAsJsonArray(), experience_slayer_wolf)); + + return skillInfo; + } + + public JsonObject getInventoryInfo(String profileId) { + JsonObject profileInfo = getProfileInformation(profileId); + if(profileInfo == null) return null; + if(profileId == null) profileId = latestProfile; + if(inventoryInfoMap.containsKey(profileId)) return inventoryInfoMap.get(profileId); + + //inv_armor, fishing_bag, quiver, ender_chest_contents, wardrobe_contents, potion_bag, inv_contents, talisman_bag, candy_inventory_contents + + String inv_armor_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "inv_armor.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String fishing_bag_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "fishing_bag.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String quiver_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "quiver.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String ender_chest_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "ender_chest_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String wardrobe_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "wardrobe_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String potion_bag_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "potion_bag.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String inv_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "inv_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String talisman_bag_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "talisman_bag.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + String candy_inventory_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "candy_inventory_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); + + JsonObject inventoryInfo = new JsonObject(); + + String[] inv_names = new String[]{"inv_armor", "fishing_bag", "quiver", "ender_chest_contents", "wardrobe_contents", + "potion_bag", "inv_contents", "talisman_bag", "candy_inventory_contents"}; + String[] inv_bytes = new String[]{inv_armor_bytes, fishing_bag_bytes, quiver_bytes, ender_chest_contents_bytes, wardrobe_contents_bytes, + potion_bag_bytes, inv_contents_bytes, talisman_bag_bytes, candy_inventory_contents_bytes}; + for(int i=0; i<inv_bytes.length; i++) { + try { + String bytes = inv_bytes[i]; + + JsonArray contents = new JsonArray(); + NBTTagCompound inv_contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(bytes))); + NBTTagList items = inv_contents_nbt.getTagList("i", 10); + for(int j=0; j<items.tagCount(); j++) { + JsonObject item = manager.getJsonFromNBTEntry(items.getCompoundTagAt(j)); + contents.add(item); + } + inventoryInfo.add(inv_names[i], contents); + } catch(IOException e) { + inventoryInfo.add(inv_names[i], new JsonArray()); + } + } + + return inventoryInfo; + } + + private final Pattern COLL_TIER_PATTERN = Pattern.compile("_(-?[0-9]+)"); + public JsonObject getCollectionInfo(String profileId) { + JsonObject profileInfo = getProfileInformation(profileId); + if(profileInfo == null) return null; + if(profileId == null) profileId = latestProfile; + if(collectionInfoMap.containsKey(profileId)) return collectionInfoMap.get(profileId); + + + JsonElement unlocked_coll_tiers_element = Utils.getElement(profileInfo, "unlocked_coll_tiers"); + if(unlocked_coll_tiers_element == null) { + JsonObject collectionInfo = new JsonObject(); + collectionInfo.add("collection_tiers", new JsonObject()); + return collectionInfo; + } + JsonArray unlocked_coll_tiers = unlocked_coll_tiers_element.getAsJsonArray(); + + JsonElement collectionInfoElement = Utils.getElement(profileInfo, "collections"); + if(collectionInfoElement == null) { + JsonObject collectionInfo = new JsonObject(); + collectionInfo.add("collection_tiers", new JsonObject()); + return collectionInfo; + } + JsonObject collectionInfo = collectionInfoElement.getAsJsonObject(); + JsonObject collectionTiers = new JsonObject(); + + for(int i=0; i<unlocked_coll_tiers.size(); i++) { + String unlocked = unlocked_coll_tiers.get(i).getAsString(); + + Matcher matcher = COLL_TIER_PATTERN.matcher(unlocked); + + if(matcher.find()) { + String tier_str = matcher.group(1); + int tier = Integer.parseInt(tier_str); + String coll = unlocked.substring(0, unlocked.length()-(matcher.group().length())); + if(!collectionTiers.has(coll) || collectionTiers.get(coll).getAsInt() < tier) { + collectionTiers.addProperty(coll, tier); + } + } + } + + collectionInfo.add("collection_tiers", collectionInfo); + + return collectionInfo; + } + + public PlayerStats.Stats getStats(String profileId) { + if(stats != null) return stats; + JsonObject profileInfo = getProfileInformation(profileId); + if(profileInfo == null) return PlayerStats.getBaseStats(); + + stats = PlayerStats.getStats(getSkillInfo(profileId), getInventoryInfo(profileId), getCollectionInfo(profileId), profileInfo); + return stats; + } + + public String getUuid() { + return uuid; + } + + public JsonObject getHypixelProfile() { + if(uuidToHypixelProfile.containsKey(uuid)) return uuidToHypixelProfile.get(uuid); + return null; + } + } + + private HashMap<String, JsonObject> nameToHypixelProfile = new HashMap<>(); + private HashMap<String, JsonObject> uuidToHypixelProfile = new HashMap<>(); + private HashMap<String, Profile> uuidToProfileMap = new HashMap<>(); + + public void getHypixelProfile(String name, Consumer<JsonObject> callback) { + HashMap<String, String> args = new HashMap<>(); + args.put("name", ""+name); + manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "player", + args, jsonObject -> { + if(jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + nameToHypixelProfile.put(name, jsonObject.get("player").getAsJsonObject()); + uuidToHypixelProfile.put(jsonObject.get("player").getAsJsonObject().get("uuid").getAsString(), jsonObject.get("player").getAsJsonObject()); + if(callback != null) callback.accept(jsonObject); + } + } + ); + } + + public Profile getProfileByName(String name, Consumer<Profile> callback) { + if(nameToHypixelProfile.containsKey(name)) { + return getProfileReset(nameToHypixelProfile.get(name).get("uuid").getAsString(), callback); + } else { + getHypixelProfile(name, jsonObject -> { + System.out.println("getting profile with callback"); + getProfileReset(jsonObject.get("player").getAsJsonObject().get("uuid").getAsString(), callback); + }); + return null; + } + } + + public Profile getProfile(String uuid, Consumer<Profile> callback) { + Profile profile = uuidToProfileMap.computeIfAbsent(uuid, k -> new Profile(uuid)); + if(profile.playerInformation != null) { + System.out.println("getting profile with callback1"); + callback.accept(profile); + } else { + System.out.println("getting profile with callback3"); + profile.getPlayerInformation(() -> callback.accept(profile)); + } + return profile; + } + + public Profile getProfileReset(String uuid, Consumer<Profile> callback) { + Profile profile = getProfile(uuid, callback); + profile.resetCache(); + return profile; + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java index 951cfa50..27f9f293 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java @@ -40,7 +40,6 @@ public class RequirementApi extends Requirement { private static JsonElement getElement(JsonElement element, String path) { List<String> path_split = PATH_SPLITTER.splitToList(path); if(element instanceof JsonObject) { - System.out.println(path_split.get(0)); JsonElement e = element.getAsJsonObject().get(path_split.get(0)); if(path_split.size() > 1) { return getElement(e, path_split.get(1)); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java index c271d63a..133619ae 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java @@ -62,11 +62,11 @@ public class HypixelApi { } public String generateApiUrl(String apiKey, String method, HashMap<String, String> args) { - String url = "https://api.hypixel.net/" + method + "?key=" + apiKey; + StringBuilder url = new StringBuilder("https://api.hypixel.net/" + method + "?key=" + apiKey); for(Map.Entry<String, String> entry : args.entrySet()) { - url += "&" + entry.getKey() + "=" + entry.getValue(); + url.append("&").append(entry.getKey()).append("=").append(entry.getValue()); } - return url; + return url.toString(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index 57b89a0a..66400c00 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -1,5 +1,9 @@ package io.github.moulberry.notenoughupdates.util; +import com.google.common.base.Splitter; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import com.mojang.authlib.Agent; import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; @@ -376,6 +380,50 @@ public class Utils { drawHoveringText(textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth, font, true); } + public static JsonObject getConstant(String constant) { + File repo = NotEnoughUpdates.INSTANCE.manager.repoLocation; + if(repo.exists()) { + File jsonFile = new File(repo, "constants/"+constant+".json"); + try { + return NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(jsonFile); + } catch (Exception ignored) { + } + } + System.out.println(constant + " = null"); + return null; + } + + public static float getElementAsFloat(JsonElement element, float def) { + if(element == null) return def; + if(!element.isJsonPrimitive()) return def; + JsonPrimitive prim = element.getAsJsonPrimitive(); + if(!prim.isNumber()) return def; + return prim.getAsFloat(); + } + + public static String getElementAsString(JsonElement element, String def) { + if(element == null) return def; + if(!element.isJsonPrimitive()) return def; + JsonPrimitive prim = element.getAsJsonPrimitive(); + if(!prim.isString()) return def; + return prim.getAsString(); + } + + public static Splitter PATH_SPLITTER = Splitter.on(".").omitEmptyStrings().limit(2); + public static JsonElement getElement(JsonElement element, String path) { + List<String> path_split = PATH_SPLITTER.splitToList(path); + if(element instanceof JsonObject) { + JsonElement e = element.getAsJsonObject().get(path_split.get(0)); + if(path_split.size() > 1) { + return getElement(e, path_split.get(1)); + } else { + return e; + } + } else { + return element; + } + } + public static ChatStyle createClickStyle(ClickEvent.Action action, String value) { ChatStyle style = new ChatStyle(); style.setChatClickEvent(new ClickEvent(action, value)); diff --git a/src/main/resources/assets/notenoughupdates/pv_basic.png b/src/main/resources/assets/notenoughupdates/pv_basic.png Binary files differnew file mode 100644 index 00000000..8e9c8d85 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/pv_basic.png |