/*
* Copyright (C) 2022 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 io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
import java.util.List;
public class BingoPage extends GuiProfileViewerPage {
private static final ResourceLocation BINGO_GUI_TEXTURE = new ResourceLocation("notenoughupdates:pv_bingo_tab.png");
private long lastResourceRequest;
private List bingoGoals = null;
private int currentEventId;
public BingoPage(GuiProfileViewer instance) {
super(instance);
}
@Override
public void drawPage(int mouseX, int mouseY, float partialTicks) {
loadBingoResources();
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledResolution.getScaledWidth();
int height = scaledResolution.getScaledHeight();
int guiLeft = GuiProfileViewer.getGuiLeft();
int guiTop = GuiProfileViewer.getGuiTop();
JsonObject bingoInfo = GuiProfileViewer.getProfile().getBingoInformation();
// Check if the player has created a bingo profile for the current event
if (bingoInfo == null) {
showMissingDataMessage(guiLeft, guiTop);
return;
}
// Bingo goals data not loaded yet
if (bingoGoals == null) {
return;
}
JsonArray events = bingoInfo.get("events").getAsJsonArray();
JsonObject lastEvent = events.get(events.size() - 1).getAsJsonObject();
int lastParticipatedId = lastEvent.get("key").getAsInt();
if (currentEventId != lastParticipatedId) {
showMissingDataMessage(guiLeft, guiTop);
return;
}
List completedGoals = jsonArrayToStringList(lastEvent.get("completed_goals").getAsJsonArray());
Minecraft.getMinecraft().getTextureManager().bindTexture(BINGO_GUI_TEXTURE);
Utils.drawTexturedRect(guiLeft, guiTop, 431, 202, GL11.GL_NEAREST);
GlStateManager.color(1, 1, 1, 1);
GlStateManager.disableLighting();
int row = 0;
int col = 0;
int initialY = guiTop + 46;
int initialX = guiLeft + 231;
int xAdjustment = 0;
int yAdjustment = 0;
for (JsonObject bingoGoal : bingoGoals) {
boolean dye = false;
boolean completed = false;
boolean communityGoal = false;
Item material;
if (bingoGoal.has("tiers")) {
if (isCommunityGoalFinished(bingoGoal)) {
material = Item.getItemFromBlock(Blocks.emerald_block);
} else {
material = Item.getItemFromBlock(Blocks.iron_block);
}
RenderHelper.enableGUIStandardItemLighting();
completed = true;
communityGoal = true;
yAdjustment = -1;
xAdjustment = -1;
} else {
if (completedGoals.contains(bingoGoal.get("id").getAsString())) {
material = Items.dye;
xAdjustment = -1;
dye = true;
completed = true;
} else {
material = Items.paper;
}
}
ItemStack itemStack = new ItemStack(material);
if (dye) {
itemStack.setItemDamage(10);
}
int x = col == 0 ? initialX + xAdjustment : initialX + (24 * col) + xAdjustment;
int y = row == 0 ? initialY + yAdjustment : initialY + (24 * row) + yAdjustment;
Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, x, y);
y = communityGoal ? y - 1 : y;
if (mouseX >= x && mouseX < x + 24) {
if (mouseY >= y && mouseY <= y + 24) {
Utils.drawHoveringText(getTooltip(bingoGoal, completed, communityGoal), mouseX, mouseY, width, height, -1);
}
}
col++;
if (col == 5) {
col = 0;
row++;
}
}
String totalPointsString =
EnumChatFormatting.AQUA + "Collected Points: " + EnumChatFormatting.WHITE + lastEvent.get("points").getAsInt();
int totalGoals = completedGoals.size();
String personalGoalsString;
if (totalGoals == 20) {
personalGoalsString = EnumChatFormatting.AQUA + "Personal Goals: " + EnumChatFormatting.GOLD + "20/20";
} else {
personalGoalsString =
EnumChatFormatting.AQUA +
"Personal Goals: " +
EnumChatFormatting.WHITE +
completedGoals.size() +
EnumChatFormatting.GOLD +
"/" +
EnumChatFormatting.WHITE +
20;
}
Utils.drawStringF(totalPointsString, guiLeft + 22, guiTop + 19, true, 0);
Utils.drawStringF(personalGoalsString, guiLeft + 22, guiTop + 31, true, 0);
GlStateManager.enableLighting();
}
private boolean isCommunityGoalFinished(JsonObject goal) {
JsonArray tiers = goal.get("tiers").getAsJsonArray();
int totalTiers = tiers.size();
long progress = goal.get("progress").getAsLong();
int finalTier = 0;
for (JsonElement tier : tiers) {
long currentTier = tier.getAsLong();
if (progress < currentTier) {
break;
}
finalTier++;
}
return finalTier == totalTiers;
}
private String generateProgressIndicator(double progress, double goal) {
int totalFields = 20;
int filled;
double percentage = progress / goal * 100;
if (percentage >= 100) {
filled = 20;
} else {
filled = (int) Math.round((percentage / 100) * 20);
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(EnumChatFormatting.DARK_GREEN);
for (int i = 0; i < totalFields; i++) {
stringBuilder.append("-");
if (i > filled) {
stringBuilder.append(EnumChatFormatting.GRAY);
}
}
return stringBuilder.toString();
}
private List getTooltip(JsonObject goal, boolean completed, boolean communityGoal) {
List tooltip = new ArrayList<>();
if (communityGoal) {
//get current tier
JsonArray tiers = goal.get("tiers").getAsJsonArray();
int totalTiers = tiers.size();
double progress = goal.get("progress").getAsLong();
int finalTier = 0;
for (JsonElement tier : tiers) {
double currentTier = tier.getAsLong();
if (progress < currentTier) {
break;
}
finalTier++;
}
double nextTier = finalTier < totalTiers ? tiers.get(totalTiers - 1).getAsLong() : tiers
.get(finalTier - 1)
.getAsLong();
int progressToNextTier = (int) Math.round(progress / nextTier * 100);
if (progressToNextTier > 100) progressToNextTier = 100;
String progressBar = generateProgressIndicator(progress, nextTier);
String name = goal.get("name").getAsString();
int nextTierNum = finalTier < totalTiers ? finalTier + 1 : totalTiers;
String nextTierString = Utils.shortNumberFormat(nextTier, 0);
String progressString = Utils.shortNumberFormat(progress, 0);
tooltip.add(EnumChatFormatting.GREEN + name + " " + finalTier);
tooltip.add(EnumChatFormatting.DARK_GRAY + "Community Goal");
tooltip.add("");
tooltip.add(
EnumChatFormatting.GRAY +
"Progress to " +
name +
" " +
nextTierNum +
": " +
EnumChatFormatting.YELLOW +
progressToNextTier +
EnumChatFormatting.GOLD +
"%"
);
tooltip.add(
progressBar +
EnumChatFormatting.YELLOW +
" " +
progressString +
EnumChatFormatting.GOLD +
"/" +
EnumChatFormatting.YELLOW +
nextTierString
);
tooltip.add("");
tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "Community Goals are");
tooltip.add(
EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "collaborative - anyone with a");
tooltip.add(
EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "Bingo profile can help to reach");
tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "the goal!");
tooltip.add("");
tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "The more you contribute");
tooltip.add(
EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "towards the goal, the more you");
tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "will be rewarded");
if (finalTier == totalTiers) {
tooltip.add("");
tooltip.add(EnumChatFormatting.GREEN + "GOAL REACHED");
}
} else {
tooltip.add(EnumChatFormatting.GREEN + goal.get("name").getAsString());
tooltip.add(EnumChatFormatting.DARK_GRAY + "Personal Goal");
tooltip.add("");
tooltip.add(goal.get("lore").getAsString());
tooltip.add("");
tooltip.add(EnumChatFormatting.GRAY + "Reward");
tooltip.add(EnumChatFormatting.GOLD + "1 Bingo Point");
if (completed) {
tooltip.add("");
tooltip.add(EnumChatFormatting.GREEN + "GOAL REACHED");
} else {
tooltip.add("");
tooltip.add(EnumChatFormatting.RED + "You have not reached this goal!");
}
}
return tooltip;
}
private void showMissingDataMessage(int guiLeft, int guiTop) {
String message = EnumChatFormatting.RED + "No Bingo data for current event!";
Utils.drawStringCentered(message, guiLeft + 431 / 2f, guiTop + 101, true, 0);
}
private List jsonArrayToStringList(JsonArray completedGoals) {
List list = new ArrayList<>();
for (JsonElement completedGoal : completedGoals) {
list.add(completedGoal.getAsString());
}
return list;
}
private List jsonArrayToJsonObjectList(JsonArray goals) {
List list = new ArrayList<>();
for (JsonElement goal : goals) {
list.add(goal.getAsJsonObject());
}
return list;
}
private void loadBingoResources() {
long currentTime = System.currentTimeMillis();
//renew every 2 minutes
if (currentTime - lastResourceRequest < 120 * 1000 && bingoGoals != null) return;
lastResourceRequest = currentTime;
NotEnoughUpdates.INSTANCE.manager.apiUtils
.newAnonymousHypixelApiRequest("resources/skyblock/bingo")
.requestJson()
.thenAccept(jsonObject -> {
if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
bingoGoals = jsonArrayToJsonObjectList(jsonObject.get("goals").getAsJsonArray());
currentEventId = jsonObject.get("id").getAsInt();
}
});
}
}