/*
* 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.rift;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage;
import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
import io.github.moulberry.notenoughupdates.profileviewer.SkyblockProfiles;
import io.github.moulberry.notenoughupdates.profileviewer.data.APIDataJson;
import io.github.moulberry.notenoughupdates.util.ItemUtils;
import io.github.moulberry.notenoughupdates.util.PetLeveling;
import io.github.moulberry.notenoughupdates.util.Utils;
import lombok.var;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
public class RiftPage extends GuiProfileViewerPage {
private static final ResourceLocation pv_rift = new ResourceLocation("notenoughupdates:pv_rift.png");
int pages = 0;
int onPage = 0;
private static final ResourceLocation CHEST_GUI_TEXTURE =
new ResourceLocation("textures/gui/container/generic_54.png");
boolean inInventory = true; // false = in enderchest
int guiLeft;
int guiTop;
private final ItemStack fillerStack = new ItemStack(Item.getItemFromBlock(Blocks.stained_glass_pane), 1, 15);
public RiftPage(GuiProfileViewer instance) {
super(instance);
}
@Override
public void drawPage(int mouseX, int mouseY, float partialTicks) {
guiLeft = GuiProfileViewer.getGuiLeft();
guiTop = GuiProfileViewer.getGuiTop();
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_rift);
Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
SkyblockProfiles.SkyblockProfile selectedProfile = getSelectedProfile();
if (selectedProfile == null) {
drawErrorMessage();
return;
}
JsonObject profileInfo = selectedProfile.getProfileJson();
APIDataJson data = selectedProfile.getAPIDataJson();
if (!profileInfo.has("rift") || data == null || data.rift == null) {
drawErrorMessage();
return;
}
var rift = data.rift;
JsonObject riftData = profileInfo.getAsJsonObject("rift");
JsonObject riftInventory = riftData.getAsJsonObject("inventory");
APIDataJson.Rift.RiftInventory.Inventory riftArmor = rift.inventory.inv_armor;
if (riftArmor != null) {
List armorData = riftArmor.readItems();
if (armorData != null) {
drawArmorAndEquipment(armorData, guiLeft, guiTop, 27, 64, mouseX, mouseY, true);
}
}
APIDataJson.Rift.RiftInventory.Inventory riftEquipment = rift.inventory.equipment_contents;
if (riftEquipment != null) {
List equipmentData = riftEquipment.readItems();
if (equipmentData != null) {
drawArmorAndEquipment(equipmentData, guiLeft, guiTop, 46, 64, mouseX, mouseY, false);
}
}
// pet
GlStateManager.color(1,1,1);
Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements);
Utils.drawTexturedRect(guiLeft + 35, guiTop + 156, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
APIDataJson.Rift.RiftDeadCats deadCats = rift.dead_cats;
if (deadCats != null && deadCats.found_cats != null) {
List foundCats = deadCats.found_cats;
int size = foundCats.size();
int riftTime = size * 15;
int manaRegen = size * 2;
APIDataJson.Rift.RiftDeadCats.Pet montezuma = deadCats.montezuma;
if (montezuma != null && !"UNKNOWN".equals(montezuma.type)) {
PetInfoOverlay.Pet pet = new PetInfoOverlay.Pet();
pet.petLevel = new PetLeveling.PetLevel(100, 100, 0, 0, 0, montezuma.exp);
pet.rarity = PetInfoOverlay.Rarity.valueOf(montezuma.tier);
pet.petType = montezuma.type;
pet.candyUsed = montezuma.candyUsed;
ItemStack petItemStackFromPetInfo = ItemUtils.createPetItemstackFromPetInfo(pet);
Utils.drawItemStack(petItemStackFromPetInfo, guiLeft + 37, guiTop + 158, true);
if ((mouseX > guiLeft + 37 && mouseX < guiLeft + 37 + 20) &&
(mouseY > guiTop + 158 && mouseY < guiTop + 158 + 20)) {
List tooltip = petItemStackFromPetInfo.getTooltip(Minecraft.getMinecraft().thePlayer, false);
ListIterator iterator = tooltip.listIterator();
while (iterator.hasNext()) {
String next = iterator.next();
if (next.startsWith("§7Found: §9")) {
iterator.set("§7Found: §9" + size + "/9 Soul Pieces");
} else if (next.startsWith("§7Rift Time: §a+")) {
iterator.set("§7Rift Time: §a+" + riftTime + "s");
} else if (next.startsWith("§7Mana Regen: §a") && pet.rarity == PetInfoOverlay.Rarity.EPIC) {
iterator.set("§7Mana Regen: §a+" + manaRegen + "%");
}
}
getInstance().tooltipToDisplay = tooltip;
}
} else if (size > 0) {
String montezumaError = EnumChatFormatting.RED + "Could not get pet";
Utils.drawStringCentered(montezumaError, guiLeft + 91 / 2f, guiTop + 158 + 10, true, 0);
}
}
float motesPurse = data.currencies.motes_purse;
Utils.drawStringCenteredScaledMaxWidth(
"§dMotes: §f" + Utils.shortNumberFormat(motesPurse, 0),
guiLeft + 45,
guiTop + 16,
true,
84,
0
);
if ((mouseX > guiLeft + 3 && mouseX < guiLeft + 90) &&
(mouseY > guiTop + 3 && mouseY < guiTop + 25)) {
int stats = data.player_stats.rift.lifetime_motes_earned;
getInstance().tooltipToDisplay = Collections.singletonList(
"§dLifetime Motes: §f" + Utils.shortNumberFormat(stats, 0));
}
// Timecharms
if (rift.gallery != null && rift.gallery.secured_trophies != null) {
JsonArray timecharm = rift.gallery.secured_trophies;
Utils.renderAlignedString(
EnumChatFormatting.RED + "Timecharms:",
EnumChatFormatting.WHITE.toString() + timecharm.size() + "/7",
guiLeft + 336,
guiTop + 39,
83
);
if ((mouseX > guiLeft + 336 && mouseX < guiLeft + 336 + 80) &&
(mouseY > guiTop + 39 && mouseY < guiTop + 39 + 15)) {
List displayNames = new ArrayList<>();
for (JsonElement jsonElement : timecharm) {
String timecharmType = jsonElement.getAsJsonObject().get("type").getAsString().toUpperCase(Locale.ROOT);
ItemStack timecharmItem = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withKnownInternalName(
"RIFT_TROPHY_" + timecharmType).resolveToItemStack();
if (timecharmItem != null) {
displayNames.add(timecharmItem.getDisplayName() + "§7: §a✔");
} else {
displayNames.add(EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "ERROR LOADING TIMECHARM!");
displayNames.add(EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "PLEASE REPORT THIS AT " +
EnumChatFormatting.GOLD + "discord.gg/moulberry");
displayNames.add(EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "WITH THE FOLLOWING TEXT: " +
EnumChatFormatting.AQUA + timecharmType);
}
}
getInstance().tooltipToDisplay = displayNames;
}
renderItem("GLASS", 316, 36, guiLeft, guiTop);
}
int grubberStacks = rift.castle.grubber_stacks;
Utils.renderAlignedString(
EnumChatFormatting.GOLD + "Burger:",
EnumChatFormatting.WHITE.toString() + grubberStacks + "/5",
guiLeft + 331,
guiTop + 87,
83
);
renderItem("MCGRUBBER_BURGER", 314, +84, guiLeft, guiTop);
ProfileViewer.Level vampire = selectedProfile.getLevelingInfo().get("vampire");
Utils.renderAlignedString(
"§6Vampire",
EnumChatFormatting.WHITE.toString() + (int) vampire.level,
guiLeft + 336,
guiTop + 61,
60
);
if (vampire.maxed) {
getInstance().renderGoldBar(guiLeft + 320, guiTop + 71, 90);
} else {
getInstance().renderBar(guiLeft + 320, guiTop + 71, 90, vampire.level % 1);
}
if (mouseX > guiLeft + 300 && mouseX < guiLeft + 410) {
if (mouseY > guiTop + 58 && mouseY < guiTop + 80) {
getInstance().tooltipToDisplay = new ArrayList<>();
List tooltipToDisplay = getInstance().tooltipToDisplay;
tooltipToDisplay.add("§6Vampire Slayer");
if (vampire.maxed) {
tooltipToDisplay.add(
EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.GOLD + "MAXED!");
} else {
int maxXp = (int) vampire.maxXpForLevel;
getInstance()
.tooltipToDisplay.add(
EnumChatFormatting.GRAY +
"Progress: " +
EnumChatFormatting.DARK_PURPLE +
StringUtils.shortNumberFormat(Math.round((vampire.level % 1) * maxXp)) +
"/" +
StringUtils.shortNumberFormat(maxXp));
}
}
}
if (rift.enigma != null && rift.enigma.found_souls != null) {
int foundSouls = rift.enigma.found_souls.size();
Utils.renderAlignedString(
EnumChatFormatting.DARK_PURPLE + "Enigma Souls:",
EnumChatFormatting.WHITE.toString() + foundSouls + "/42",
guiLeft + 331,
guiTop + 110,
83
);
renderItem("SKYBLOCK_ENIGMA_SOUL", 314, 106, guiLeft, guiTop);
}
if (riftInventory == null) {
String message = EnumChatFormatting.RED + "Inventory API not enabled!";
Utils.drawStringCentered(message, guiLeft + 431 / 2f, guiTop + 61, true, 0);
}
// button
if (riftInventory != null) {
addInventoryButton(156, 16, guiLeft, guiTop, mouseX, mouseY, "§7Inventory", "CHEST");
addInventoryButton(222, 16, guiLeft, guiTop, mouseX, mouseY, "§7Ender Chest", "ENDER_CHEST");
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
Minecraft.getMinecraft().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
int inventoryRows = inInventory ? 4 : 5;
int invSizeY = inventoryRows * 18 + 17 + 7;
int inventoryX = guiLeft + 203 - 176 / 2;
int inventoryY = guiTop + 130 - invSizeY / 2;
getInstance().drawTexturedModalRect(inventoryX, inventoryY, 0, 0, 176, inventoryRows * 18 + 17);
getInstance().drawTexturedModalRect(inventoryX, inventoryY + inventoryRows * 18 + 17, 0, 215, 176, 7);
Utils.drawStringF(
inInventory ? "Inventory" : "Ender Chest",
guiLeft + 122,
inInventory ? guiTop + 87 + 1 : guiTop + 79,
false,
4210752
);
if (!inInventory) {
if (!riftInventory.has("ender_chest_contents")) {
drawErrorMessage();
return;
}
APIDataJson.Rift.RiftInventory.Inventory riftEnderChest = rift.inventory.ender_chest_contents;
if (riftEnderChest != null) {
List enderChestContents = riftEnderChest.readItems();
if (enderChestContents != null) {
pages = (int) (Math.ceil(enderChestContents.size() / 45d));
drawArrows(onPage, pages, 190, 77);
for (int i = 0; i <= pages; i++) {
if (i != onPage) continue;
List page = enderChestContents.subList(
Math.min(i == 0 ? 0 : i * 45, enderChestContents.size() - 45),
i == 0 ? 45 : enderChestContents.size()
); // if anybody has an idea how to make this less hard coded on 2 pages (more pages) please do it for me, i am doing this at 4 am
int row = 0;
int slot = 0;
for (int j = 0; j < page.size(); j++) {
JsonObject jsonObject = page.get(j);
if (j % 9 == 0 && j > 0) {
slot = 0;
row++;
}
int x = (inventoryX - guiLeft) + 8 + (slot * 18);
int y = 91 + (row * 18);
slot++;
if (jsonObject != null) {
ItemStack itemStack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(jsonObject, false);
if ((mouseX >= guiLeft + x && mouseX <= guiLeft + x + 16) &&
(mouseY >= guiTop + y && mouseY <= guiTop + y + 16)) {
getInstance().tooltipToDisplay =
itemStack.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
renderItem(itemStack, x, y, guiLeft, guiTop);
}
}
}
}
}
} else {
if (riftInventory == null || !riftInventory.has("inv_contents")) {
drawErrorMessage();
return;
}
APIDataJson.Rift.RiftInventory.Inventory riftInventory2 = rift.inventory.inv_contents;
if (riftInventory2 != null) {
List inventoryContents = riftInventory2.readItems();
if (inventoryContents != null) {
List hotbar = new ArrayList<>();
for (int i = 0; i < 9; i++) {
hotbar.add(inventoryContents.get(i));
}
inventoryContents.removeAll(hotbar);
int hotbarSlot = 0;
for (JsonObject jsonObject : hotbar) {
if (jsonObject != null) {
int drawX = 123 + (hotbarSlot * 18);
ItemStack itemStack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(jsonObject, false);
if ((mouseX >= guiLeft + drawX && mouseX <= guiLeft + drawX + 16) &&
(mouseY >= guiTop + 154 && mouseY <= guiTop + 154 + 16)) {
getInstance().tooltipToDisplay =
itemStack.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
renderItem(itemStack, drawX, 154, guiLeft, guiTop);
}
hotbarSlot++;
}
int row = 1;
int slot = 0;
for (int i = 0; i < inventoryContents.size(); i++) {
JsonObject jsonObject = inventoryContents.get(i);
if (i % 9 == 0 && i > 0) {
slot = 0;
row++;
}
if (jsonObject != null) {
ItemStack itemStack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(jsonObject, false);
int x1 = (inventoryX - guiLeft) + (slot * 18) + 8;
int y1 = (inventoryY - guiTop) + (row * 18);
if ((mouseX >= guiLeft + x1 && mouseX <= guiLeft + x1 + 16) &&
(mouseY >= guiTop + y1 && mouseY <= guiTop + y1 + 16)) {
getInstance().tooltipToDisplay =
itemStack.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
renderItem(itemStack, x1, y1, guiLeft, guiTop);
}
slot++;
}
}
}
}
}
}
private void drawArrows(int page, int maxPages, int x, int y) {
ArrowPagesUtils.onDraw(guiLeft, guiTop, new int[]{x, y}, page, maxPages);
}
@Override
public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
if ((mouseX >= guiLeft + 156 - 1 && mouseX <= guiLeft + 156 + 20) &&
(mouseY >= guiTop + 16 && mouseY <= guiTop + 16 + 20)) {
inInventory = true;
Utils.playPressSound();
}
ArrowPagesUtils.onPageSwitchMouse(
guiLeft,
guiTop,
new int[]{190, 77},
onPage,
pages,
pageChange -> {
onPage = pageChange;
}
);
if ((mouseX >= guiLeft + 222 - 1 && mouseX <= guiLeft + 222 + 20) &&
(mouseY >= guiTop + 16 && mouseY <= guiTop + 16 + 20)) {
inInventory = false;
Utils.playPressSound();
}
return false;
}
@Override
public void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
if (getInstance().playerNameTextField.getFocus()) return;
switch (keyCode) {
case Keyboard.KEY_1:
inInventory = true;
Utils.playPressSound();
break;
case Keyboard.KEY_2:
inInventory = false;
Utils.playPressSound();
break;
}
}
public void addInventoryButton(
int x,
int y,
int guiLeft,
int guiTop,
int mouseX,
int mouseY,
String title,
String internalNameForItem
) {
Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements);
if (internalNameForItem.equals("CHEST") && inInventory) {
Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20, 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST);
} else if (internalNameForItem.equals("ENDER_CHEST") && !inInventory) {
Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20, 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST);
} else {
// should never happen
Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
}
renderItem(internalNameForItem, x + 2, y + 2, guiLeft, guiTop);
if ((mouseX >= guiLeft + x - 1 && mouseX <= guiLeft + x + 20) &&
(mouseY >= guiTop + y && mouseY <= guiTop + y + 20)) {
getInstance().tooltipToDisplay = Collections.singletonList(title);
}
}
public void renderItem(String internalName, int x, int y, int guiLeft, int guiTop) {
ItemStack itemStack = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withKnownInternalName(
internalName).resolveToItemStack();
renderItem(itemStack, x, y, guiLeft, guiTop);
}
public void renderItem(ItemStack itemStack, int x, int y, int guiLeft, int guiTop) {
GlStateManager.disableLighting();
RenderHelper.enableGUIStandardItemLighting();
Utils.drawItemStack(itemStack, guiLeft + x, guiTop + y);
GlStateManager.enableLighting();
RenderHelper.disableStandardItemLighting();
}
public void drawArmorAndEquipment(
List jsonObjects,
int guiLeft,
int guiTop,
int x,
int y,
int mouseX,
int mouseY,
boolean reverse
) {
ItemStack[] itemStacks = new ItemStack[4];
if (reverse) Collections.reverse(jsonObjects); // is this intensive??
for (int i = 0; i < jsonObjects.size(); i++) {
JsonObject json = jsonObjects.get(i);
if (json == null) continue;
ItemStack itemStack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(json, false);
if (itemStack == null) itemStack = fillerStack;
itemStacks[i] = itemStack;
}
for (int i = 0; i < itemStacks.length; i++) {
ItemStack stack = itemStacks[i];
if (stack == null) continue;
Utils.drawItemStack(stack, guiLeft + x, guiTop + y + (i * 18), true);
if (stack == fillerStack) continue;
if ((mouseX >= guiLeft + x - 1 && mouseX <= guiLeft + x + 16 + 1) &&
(mouseY >= guiTop + y + (i * 18) && mouseY <= guiTop + y + (i * 18) + 16)) {
getInstance().tooltipToDisplay =
stack.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
}
}
public static List readBase64(String data) {
List itemStacks = new ArrayList<>();
try {
NBTTagList items = CompressedStreamTools.readCompressed(
new ByteArrayInputStream(Base64.getDecoder().decode(data))
).getTagList("i", 10);
for (int j = 0; j < items.tagCount(); j++) {
JsonObject item = NotEnoughUpdates.INSTANCE.manager.getJsonFromNBTEntry(items.getCompoundTagAt(j));
itemStacks.add(item);
}
} catch (IOException ignored) {
}
return itemStacks;
}
public void drawErrorMessage() {
String message = EnumChatFormatting.RED + "No Rift data available!";
Utils.drawStringCentered(message, guiLeft + 431 / 2f, guiTop + 61, true, 0);
}
}