/*
* 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.miscgui.minionhelper.render;
import com.google.common.collect.ArrayListMultimap;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.ApiData;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewLine;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewText;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.CollectionRequirement;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.MinionRequirement;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.ReputationRequirement;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.CraftingSource;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.MinionSource;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.NpcSource;
import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiChest;
import org.lwjgl.input.Mouse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class MinionHelperOverlayHover {
private final MinionHelperOverlay overlay;
private final MinionHelperManager manager;
public MinionHelperOverlayHover(MinionHelperOverlay overlay, MinionHelperManager manager) {
this.overlay = overlay;
this.manager = manager;
}
void renderHover(LinkedHashMap renderMap) {
if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) return;
final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
final int scaledWidth = scaledresolution.getScaledWidth();
final int scaledHeight = scaledresolution.getScaledHeight();
int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth;
int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1;
OverviewLine mouseObject = overlay.getObjectOverMouse(renderMap);
if (mouseObject != null) {
Utils.drawHoveringText(getTooltip(mouseObject), mouseX, mouseY, scaledWidth, scaledHeight, -1);
}
renderButtons();
}
private void renderButtons() {
GuiScreen gui = Minecraft.getMinecraft().currentScreen;
if (!(gui instanceof GuiChest)) return;
int xSize = ((AccessorGuiContainer) gui).getXSize();
int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft();
int guiTop = ((AccessorGuiContainer) gui).getGuiTop();
final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
final int scaledWidth = scaledresolution.getScaledWidth();
final int scaledHeight = scaledresolution.getScaledHeight();
int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth;
int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1;
int x = guiLeft + xSize + 4 + 149 - 3;
int y = guiTop + 109 - 3;
if (mouseX > x && mouseX < x + 16 &&
mouseY > y && mouseY < y + 16) {
renderFilterButton(scaledWidth, scaledHeight, mouseX, mouseY);
}
x = guiLeft + xSize + 4 + 149 - 3 - 16 - 3;
y = guiTop + 109 - 3;
if (mouseX > x && mouseX < x + 16 &&
mouseY > y && mouseY < y + 16) {
renderBuyPriceButton(scaledWidth, scaledHeight, mouseX, mouseY);
}
}
private void renderFilterButton(int scaledWidth, int scaledHeight, int mouseX, int mouseY) {
List list = new ArrayList<>();
if (overlay.isFilterEnabled()) {
list.add("§aFilter enabled");
list.add("§7Only show minions that can be");
list.add("§7crafted and meet requirements.");
} else {
list.add("§cFilter disabled");
list.add("§7Show all minions. §cRed ones §7have");
list.add("§7missing requirements.");
}
list.add("");
list.add("§eClick to toggle!");
Utils.drawHoveringText(list, mouseX, mouseY, scaledWidth, scaledHeight, -1);
}
private void renderBuyPriceButton(int scaledWidth, int scaledHeight, int mouseX, int mouseY) {
List list = new ArrayList<>();
if (overlay.isUseInstantBuyPrice()) {
list.add("§bUse Instant Buy price");
list.add("§7Use the price to pay when");
list.add("§7buying the item right now.");
list.add("§7This will be more expensive!");
} else {
list.add("§6Use Buy Offer price");
list.add("§7Use the price for creating an");
list.add("§7offer to buy the item cheaper.");
list.add("§7This can take longer!");
}
list.add("");
list.add("§eClick to toggle!");
Utils.drawHoveringText(list, mouseX, mouseY, scaledWidth, scaledHeight, -1);
}
private List getTooltip(OverviewLine overviewLine) {
List lines = new ArrayList<>();
if (overviewLine instanceof OverviewText) {
OverviewText overviewText = (OverviewText) overviewLine;
lines.addAll(overviewText.getLines());
} else if (overviewLine instanceof Minion) {
Minion minion = (Minion) overviewLine;
MinionSource minionSource = minion.getMinionSource();
if (minion.getCustomSource() != null) {
minionSource = minion.getCustomSource();
}
String displayName = minion.getDisplayName();
lines.add("§9" + displayName + " " + minion.getTier());
List requirements = manager.getRequirementsManager().getRequirements(minion);
if (!requirements.isEmpty()) {
for (MinionRequirement requirement : requirements) {
String result = getRequirementDescription(minion, requirement);
if (result == null) continue;
lines.add(result);
}
} else {
lines.add("§cNo requirements loaded!");
}
if (minionSource instanceof CraftingSource) {
CraftingSource craftingSource = (CraftingSource) minionSource;
lines.add("");
String format = manager.getPriceCalculation().calculateUpgradeCostsFormat(minion, true);
if (minion.getTier() == 1) {
lines.add("§7Full crafting cost: " + format);
} else {
lines.add("§7Upgrade cost: " + format);
}
formatItems(lines, grabAllItems(craftingSource.getItems()));
} else if (minionSource instanceof NpcSource) {
NpcSource npcSource = (NpcSource) minionSource;
String npcName = npcSource.getNpcName();
lines.add("");
lines.add("§7Buy from: §9" + npcName + " (NPC)");
lines.add("");
lines.add("§7Cost: " + manager.getPriceCalculation().calculateUpgradeCostsFormat(minion, true));
int coins = npcSource.getCoins();
if (coins != 0) {
lines.add(" §8- " + manager.getPriceCalculation().formatCoins(coins));
}
formatItems(lines, grabAllItems(npcSource.getItems()));
}
lines.add("");
lines.add("§eClick to view recipe!");
lines.add("§eCtrl-Click to open bazaar!");
}
return lines;
}
private String getRequirementDescription(Minion minion, MinionRequirement requirement) {
boolean meetRequirement = manager.getRequirementsManager().meetRequirement(minion, requirement);
String color = meetRequirement ? "§a" : "§c";
String description = requirement.printDescription(color);
if (requirement instanceof CollectionRequirement && manager.getApi().isCollectionApiDisabled()) {
description += " §cAPI DISABLED! §7";
}
if (!meetRequirement) {
if (requirement instanceof ReputationRequirement) {
ReputationRequirement reputationRequirement = (ReputationRequirement) requirement;
String reputationType = reputationRequirement.getReputationType();
ApiData apiData = manager.getApi().getApiData();
int having;
if (reputationType.equals("BARBARIAN")) {
having = apiData.getBarbariansReputation();
} else if (reputationType.equals("MAGE")) {
having = apiData.getMagesReputation();
} else {
Utils.addChatMessage("§c[NEU] Minion Helper: Unknown reputation type: '" + reputationType + "'");
return null;
}
int need = reputationRequirement.getReputation();
if (having < 0) having = 0;
String reputationName = StringUtils.firstUpperLetter(reputationType.toLowerCase(Locale.ROOT));
String havingFormat = Utils.formatNumberWithDots(having);
String needFormat = Utils.formatNumberWithDots(need);
description = "Reputation: §c" + havingFormat + "§8/§c" + needFormat + " §7" + reputationName + " Reputation";
}
}
return " §8- §7" + description;
}
private void formatItems(List lines, Map allItems) {
for (Map.Entry entry : allItems.entrySet()) {
String internalName = entry.getKey();
int amount = entry.getValue();
if (internalName.equals("SKYBLOCK_PELT")) {
int peltCount = manager.getApi().getApiData().getPeltCount();
lines.add(" §8- §5" + peltCount + "§8/§5" + amount + " Pelts");
continue;
}
if (internalName.equals("SKYBLOCK_NORTH_STAR")) {
// North Stars are not in the API
lines.add(" §8- §a" + amount + "§7x §d" + "North Star");
continue;
}
String name = NotEnoughUpdates.INSTANCE.manager.getDisplayName(internalName);
double price = manager.getPriceCalculation().getPrice(internalName);
String priceFormat = manager.getPriceCalculation().formatCoins(price * amount);
lines.add(" §8- §a" + amount + "§7x §f" + name + " " + priceFormat);
}
}
private Map grabAllItems(ArrayListMultimap multimap) {
Map allItems = new HashMap<>();
for (Map.Entry entry : multimap.entries()) {
String name = entry.getKey();
int amount = entry.getValue();
amount = allItems.getOrDefault(name, 0) + amount;
allItems.put(name, amount);
}
return allItems;
}
}