/*
* 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;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.Slot;
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.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TradeWindow {
private static final ResourceLocation location = new ResourceLocation("notenoughupdates", "custom_trade.png");
private static final int xSize = 176;
private static final int ySize = 204;
private static int guiLeft;
private static int guiTop;
private static long lastTradeMillis = -1;
private static final long CHANGE_EXCLAM_MILLIS = 5000;
private static Integer[] ourTradeIndexes = new Integer[16];
private static Integer[] theirTradeIndexes = new Integer[16];
private static String[] theirTradeOld = new String[16];
private static Long[] theirTradeChangesMillis = new Long[16];
public static boolean hypixelTradeWindowActive(String containerName) {
return containerName != null && containerName.trim().startsWith("You ");
}
public static boolean tradeWindowActive(String containerName) {
if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return false;
if (!NotEnoughUpdates.INSTANCE.config.tradeMenu.enableCustomTrade) return false;
if (hypixelTradeWindowActive(containerName)) {
return true;
}
if (lastTradeMillis != -99) {
lastTradeMillis = -99;
ourTradeIndexes = new Integer[16];
theirTradeIndexes = new Integer[16];
theirTradeOld = new String[16];
theirTradeChangesMillis = new Long[16];
}
return false;
}
private static void drawStringShadow(String str, float x, float y, int len) {
for (int xOff = -2; xOff <= 2; xOff++) {
for (int yOff = -2; yOff <= 2; yOff++) {
if (Math.abs(xOff) != Math.abs(yOff)) {
Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str),
x + xOff / 2f, y + yOff / 2f, false, len,
new Color(20, 20, 20, 100 / Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB()
);
}
}
}
Utils.drawStringCenteredScaledMaxWidth(str, x, y, false, len, new Color(64, 64, 64, 255).getRGB());
}
private static long getPrice(String internalName) {
long pricePer = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalName);
if (pricePer == -1) {
JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalName);
if (bazaarInfo != null && bazaarInfo.has("avg_buy")) {
pricePer = (long) bazaarInfo.get("avg_buy").getAsDouble();
}
}
if (pricePer == -1) {
JsonObject info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalName);
if (info != null && !NotEnoughUpdates.INSTANCE.manager.auctionManager.isVanillaItem(internalName) &&
info.has("price") && info.has("count")) {
pricePer = (long) (info.get("price").getAsDouble() / info.get("count").getAsDouble());
}
}
if (pricePer == -1) {
APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalName);
if (craftCost != null) {
pricePer = (int) craftCost.craftCost;
}
}
return pricePer;
}
private static long processTopItems(
ItemStack stack, Map> topItems,
Map topItemsStack, Map topItemsCount
) {
String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
if (internalname == null) {
if (stack.getDisplayName().endsWith(" coins")) {
String clean = Utils.cleanColour(stack.getDisplayName());
int mult = 1;
StringBuilder sb = new StringBuilder();
for (int index = 0; index < clean.length(); index++) {
char c = clean.charAt(index);
if ("0123456789.".indexOf(c) >= 0) {
sb.append(c);
} else {
switch (c) {
case 'K':
case 'k':
mult = 1000;
break;
case 'M':
case 'm':
mult = 1000000;
break;
case 'B':
case 'b':
mult = 1000000000;
break;
default:
break;
}
break;
}
}
try {
int coins = (int) (Float.parseFloat(sb.toString()) * mult);
topItemsStack.putIfAbsent("TRADE_COINS", stack);
long existingPrice = coins;
Set toRemove = new HashSet<>();
for (Map.Entry> entry : topItems.entrySet()) {
if (entry.getValue().contains("TRADE_COINS")) {
entry.getValue().remove("TRADE_COINS");
existingPrice += entry.getKey();
}
if (entry.getValue().isEmpty()) toRemove.add(entry.getKey());
}
topItems.keySet().removeAll(toRemove);
Set items = topItems.computeIfAbsent(existingPrice, k -> new HashSet<>());
items.add("TRADE_COINS");
return coins;
} catch (Exception ignored) {
}
}
} else {
long pricePer = getPrice(internalname);
if (pricePer > 0) {
topItemsStack.putIfAbsent(internalname, stack);
long price = pricePer * stack.stackSize;
long priceInclBackpack = price;
NBTTagCompound tag = stack.getTagCompound();
if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
byte[] bytes = null;
for (String key : ea.getKeySet()) {
if (key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) {
bytes = ea.getByteArray(key);
break;
}
}
if (bytes != null) {
try {
NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
NBTTagList items = contents_nbt.getTagList("i", 10);
for (int k = 0; k < items.tagCount(); k++) {
if (items.getCompoundTagAt(k).getKeySet().size() > 0) {
NBTTagCompound nbt = items.getCompoundTagAt(k).getCompoundTag("tag");
int id2 = items.getCompoundTagAt(k).getShort("id");
int count2 = items.getCompoundTagAt(k).getByte("Count");
int damage2 = items.getCompoundTagAt(k).getShort("Damage");
if (id2 == 141) id2 = 391; //for some reason hypixel thinks carrots have id 141
Item mcItem = Item.getItemById(id2);
if (mcItem == null) continue;
ItemStack stack2 = new ItemStack(mcItem, count2, damage2);
stack2.setTagCompound(nbt);
priceInclBackpack += processTopItems(stack2, topItems, topItemsStack, topItemsCount);
}
}
} catch (Exception ignored) {
}
}
}
long existingPrice = price;
Set toRemove = new HashSet<>();
for (Map.Entry> entry : topItems.entrySet()) {
if (entry.getValue().contains(internalname)) {
entry.getValue().remove(internalname);
existingPrice += entry.getKey();
}
if (entry.getValue().isEmpty()) toRemove.add(entry.getKey());
}
topItems.keySet().removeAll(toRemove);
Set items = topItems.computeIfAbsent(existingPrice, k -> new HashSet<>());
items.add(internalname);
int count = topItemsCount.computeIfAbsent(internalname, l -> 0);
topItemsCount.put(internalname, count + stack.stackSize);
return priceInclBackpack;
}
}
return 0;
}
private static int getBackpackValue(ItemStack stack) {
int price = 0;
NBTTagCompound tag = stack.getTagCompound();
if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
byte[] bytes = null;
for (String key : ea.getKeySet()) {
if (key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) {
bytes = ea.getByteArray(key);
break;
}
}
if (bytes != null) {
try {
NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
NBTTagList items = contents_nbt.getTagList("i", 10);
for (int k = 0; k < items.tagCount(); k++) {
if (items.getCompoundTagAt(k).getKeySet().size() > 0) {
NBTTagCompound nbt = items.getCompoundTagAt(k).getCompoundTag("tag");
String internalname2 = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery()
.withItemNBT(nbt)
.resolveInternalName();
if (internalname2 != null) {
long pricePer2 = getPrice(internalname2);
if (pricePer2 > 0) {
int count2 = items.getCompoundTagAt(k).getByte("Count");
price += pricePer2 * count2;
}
}
}
}
} catch (Exception ignored) {
}
}
}
return price;
}
public static void render(int mouseX, int mouseY) {
if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
ContainerChest cc = (ContainerChest) chest.inventorySlots;
String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
guiLeft = (scaledResolution.getScaledWidth() - xSize) / 2;
guiTop = (scaledResolution.getScaledHeight() - ySize) / 2;
List tooltipToDisplay = null;
ItemStack stackToRender = null;
int tooltipLen = -1;
//Set index mappings
//Our slots
TreeMap> ourTradeMap = new TreeMap<>();
for (int i = 0; i < 16; i++) {
ourTradeIndexes[i] = -1;
int x = i % 4;
int y = i / 4;
int containerIndex = y * 9 + x;
ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
if (stack == null) continue;
String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
if (internalname == null) {
if (stack.getDisplayName().endsWith(" coins")) {
String clean = Utils.cleanColour(stack.getDisplayName());
int mult = 1;
StringBuilder sb = new StringBuilder();
for (int index = 0; index < clean.length(); index++) {
char c = clean.charAt(index);
if ("0123456789.".indexOf(c) >= 0) {
sb.append(c);
} else {
switch (c) {
case 'K':
case 'k':
mult = 1000;
break;
case 'M':
case 'm':
mult = 1000000;
break;
case 'B':
case 'b':
mult = 1000000000;
break;
default:
break;
}
break;
}
}
try {
int coins = (int) (Float.parseFloat(sb.toString()) * mult);
List list = ourTradeMap.computeIfAbsent((long) coins, k -> new ArrayList<>());
list.add(containerIndex);
} catch (Exception ignored) {
List list = ourTradeMap.computeIfAbsent(-1L, k -> new ArrayList<>());
list.add(containerIndex);
}
} else {
List list = ourTradeMap.computeIfAbsent(-1L, k -> new ArrayList<>());
list.add(containerIndex);
}
} else {
long price = getPrice(internalname);
if (price == -1) price = 0;
price += getBackpackValue(stack);
List list = ourTradeMap.computeIfAbsent(price, k -> new ArrayList<>());
list.add(containerIndex);
}
}
long currentTime = System.currentTimeMillis();
List theirTradeCurrent = new ArrayList<>();
TreeMap> theirTradeMap = new TreeMap<>();
HashMap displayCountMap = new HashMap<>();
for (int i = 0; i < 16; i++) {
theirTradeIndexes[i] = -1;
if (theirTradeChangesMillis[i] == null || currentTime - theirTradeChangesMillis[i] > CHANGE_EXCLAM_MILLIS) {
theirTradeChangesMillis[i] = -1L;
}
int x = i % 4;
int y = i / 4;
int containerIndex = y * 9 + x + 5;
ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
if (stack == null) continue;
NBTTagCompound tag = stack.getTagCompound();
String uuid;
if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
if (ea.hasKey("uuid", 8)) {
uuid = ea.getString("uuid");
} else {
int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k -> 0);
uuid = stack.getDisplayName() + ":" + displayCount;
displayCountMap.put(stack.getDisplayName(), displayCount + 1);
}
} else {
int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k -> 0);
uuid = stack.getDisplayName() + ":" + displayCount;
displayCountMap.put(stack.getDisplayName(), displayCount + 1);
}
if (uuid != null) theirTradeCurrent.add(uuid);
String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
if (internalname == null) {
if (stack.getDisplayName().endsWith(" coins")) {
String clean = Utils.cleanColour(stack.getDisplayName());
int mult = 1;
StringBuilder sb = new StringBuilder();
for (int index = 0; index < clean.length(); index++) {
char c = clean.charAt(index);
if ("0123456789.".indexOf(c) >= 0) {
sb.append(c);
} else {
switch (c) {
case 'K':
case 'k':
mult = 1000;
break;
case 'M':
case 'm':
mult = 1000000;
break;
case 'B':
case 'b':
mult = 1000000000;
break;
default:
break;
}
break;
}
}
try {
int coins = (int) (Float.parseFloat(sb.toString()) * mult);
List list = theirTradeMap.computeIfAbsent(coins, k -> new ArrayList<>());
list.add(containerIndex);
} catch (Exception ignored) {
List list = theirTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
list.add(containerIndex);
}
} else {
List list = theirTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
list.add(containerIndex);
}
} else {
JsonObject info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
int price = -1;
if (info != null && info.has("price") && info.has("count")) {
int auctionPricePer = (int) (info.get("price").getAsFloat() / info.get("count").getAsFloat());
price = auctionPricePer * stack.stackSize;
} else {
JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
if (bazaarInfo != null && bazaarInfo.has("avg_buy")) {
price = (int) bazaarInfo.get("avg_buy").getAsFloat() * stack.stackSize;
}
}
price += getBackpackValue(stack);
List list = theirTradeMap.computeIfAbsent(price, k -> new ArrayList<>());
list.add(containerIndex);
}
}
int ourTradeIndex = 0;
for (Map.Entry> entry : ourTradeMap.descendingMap().entrySet()) {
for (Integer index : entry.getValue()) {
ourTradeIndexes[ourTradeIndex++] = index;
}
}
//Their slots
int maxMissing = 16 - theirTradeCurrent.size();
int j = 0;
for (int i = 0; i < 16; i++) {
while (j <= 15 && (j - i < maxMissing) && theirTradeChangesMillis[j] >= 0) j++;
j = Math.min(15, j);
String oldUUID = theirTradeOld[i];
if (oldUUID != null && !theirTradeCurrent.contains(oldUUID)) {
theirTradeChangesMillis[j] = System.currentTimeMillis();
}
j++;
}
for (int i = 0; i < 16; i++) {
theirTradeOld[i] = null;
}
int theirTradeIndex = 0;
displayCountMap.clear();
j = 0;
for (Map.Entry> entry : theirTradeMap.descendingMap().entrySet()) {
for (Integer index : entry.getValue()) {
while (j <= 15 && (j - theirTradeIndex < maxMissing) && theirTradeChangesMillis[j] >= 0) j++;
j = Math.min(15, j);
theirTradeIndexes[j] = index;
ItemStack stack = chest.inventorySlots.getInventory().get(index);
if (stack == null) continue;
NBTTagCompound tag = stack.getTagCompound();
String uuid;
if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
if (ea.hasKey("uuid", 8)) {
uuid = ea.getString("uuid");
} else {
int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k -> 0);
uuid = stack.getDisplayName() + ":" + displayCount;
displayCountMap.put(stack.getDisplayName(), displayCount + 1);
}
} else {
int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k -> 0);
uuid = stack.getDisplayName() + ":" + displayCount;
displayCountMap.put(stack.getDisplayName(), displayCount + 1);
}
//System.out.println(uuid);
theirTradeOld[theirTradeIndex] = uuid;
j++;
theirTradeIndex++;
}
}
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(location);
Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, 0, 176 / 256f, 0, 204 / 256f, GL11.GL_NEAREST);
Utils.drawStringF(new ChatComponentTranslation("container.inventory").getUnformattedText(),
guiLeft + 8, guiTop + 111, false, 4210752
);
Utils.drawStringF("You", guiLeft + 8, guiTop + 5, false, 421752);
String[] split = containerName.split(" ");
if (split.length >= 1) {
Utils.drawStringF(split[split.length - 1],
guiLeft + 167 - Minecraft.getMinecraft().fontRendererObj.getStringWidth(split[split.length - 1]),
guiTop + 5, false, 4210752
);
}
int index = 0;
for (ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
int x = 8 + 18 * (index % 9);
int y = 104 + 18 * (index / 9);
if (index < 9) y = 180;
((AccessorGuiContainer) chest).doDrawSlot(new Slot(
Minecraft.getMinecraft().thePlayer.inventory,
index,
guiLeft + x,
guiTop + y
));
int col = 0x80ffffff;
if (SlotLocking.getInstance().isSlotIndexLocked(index)) {
col = 0x80ff8080;
}
if (mouseX > guiLeft + x - 1 && mouseX < guiLeft + x + 18) {
if (mouseY > guiTop + y - 1 && mouseY < guiTop + y + 18) {
if (stack != null) stackToRender = stack;
GlStateManager.disableLighting();
GlStateManager.disableDepth();
GlStateManager.colorMask(true, true, true, false);
Utils.drawGradientRect(guiLeft + x, guiTop + y,
guiLeft + x + 16, guiTop + y + 16, col, col
);
GlStateManager.colorMask(true, true, true, true);
GlStateManager.enableLighting();
GlStateManager.enableDepth();
}
}
index++;
}
for (int i = 0; i < 16; i++) {
int x = i % 4;
int y = i / 4;
int containerIndex = ourTradeIndexes[i];
ItemStack stack = null;
if (containerIndex >= 0) {
stack = chest.inventorySlots.getInventory().get(containerIndex);
Utils.drawItemStack(stack, guiLeft + 10 + x * 18, guiTop + 15 + y * 18);
}
if (mouseX > guiLeft + 10 + x * 18 - 1 && mouseX < guiLeft + 10 + x * 18 + 18) {
if (mouseY > guiTop + 15 + y * 18 - 1 && mouseY < guiTop + 15 + y * 18 + 18) {
if (stack != null) stackToRender = stack;
GlStateManager.disableLighting();
GlStateManager.disableDepth();
GlStateManager.colorMask(true, true, true, false);
Utils.drawGradientRect(guiLeft + 10 + x * 18, guiTop + 15 + y * 18,
guiLeft + 10 + x * 18 + 16, guiTop + 15 + y * 18 + 16, -2130706433, -2130706433
);
GlStateManager.colorMask(true, true, true, true);
GlStateManager.enableLighting();
GlStateManager.enableDepth();
}
}
}
ItemStack bidStack = chest.inventorySlots.getInventory().get(36);
if (bidStack != null) {
Utils.drawItemStack(bidStack, guiLeft + 10, guiTop + 90);
if (mouseX > guiLeft + 10 - 1 && mouseX < guiLeft + 10 + 18) {
if (mouseY > guiTop + 90 - 1 && mouseY < guiTop + 90 + 18) {
tooltipToDisplay = bidStack.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
}
}
ItemStack confirmStack = chest.inventorySlots.getInventory().get(39);
if (confirmStack != null) {
String confirmDisplay = confirmStack.getDisplayName();
if (!confirmDisplay.equals(EnumChatFormatting.GREEN + "Trading!")) {
if (mouseX > guiLeft + 81 - 51 && mouseX < guiLeft + 81) {
if (mouseY > guiTop + 91 && mouseY < guiTop + 91 + 14) {
tooltipToDisplay = confirmStack.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
}
Minecraft.getMinecraft().getTextureManager().bindTexture(location);
Utils.drawTexturedRect(guiLeft + 81 - 51, guiTop + 91, 51, 14,
0, 51 / 256f, ySize / 256f, (ySize + 14) / 256f, GL11.GL_NEAREST
);
Pattern pattern = Pattern.compile(
EnumChatFormatting.GRAY + "\\(" + EnumChatFormatting.YELLOW + "([0-9]+)" + EnumChatFormatting.GRAY + "\\)");
Matcher matcher = pattern.matcher(confirmDisplay);
if (!confirmDisplay.equals(EnumChatFormatting.YELLOW + "Warning!") &&
!confirmDisplay.equals(EnumChatFormatting.YELLOW + "Deal!")) {
lastTradeMillis = -1;
}
if (matcher.find()) {
String numS = matcher.group(1);
int num = Integer.parseInt(numS);
Utils.drawStringCentered(
EnumChatFormatting.DARK_RED + "Check " + EnumChatFormatting.BOLD + (char) (9311 + num),
guiLeft + 56, guiTop + 99,
false,
4210752
);
} else if (confirmDisplay.equals(EnumChatFormatting.AQUA + "Gift!")) {
Utils.drawStringCentered(EnumChatFormatting.GREEN + "Accept", guiLeft + 56, guiTop + 99, true, 4210752);
} else if (confirmDisplay.equals(EnumChatFormatting.GREEN + "Deal accepted!")) {
Utils.drawStringCentered(EnumChatFormatting.GREEN + "Accepted", guiLeft + 56, guiTop + 99, true, 4210752);
} else if (lastTradeMillis > 0) {
long delta = System.currentTimeMillis() - lastTradeMillis;
if (delta > 2000) {
Utils.drawStringCentered(
EnumChatFormatting.GREEN + "Accept",
guiLeft + 56,
guiTop + 99,
true,
4210752
);
} else {
Utils.drawStringCentered(
EnumChatFormatting.YELLOW + "Trade " + EnumChatFormatting.BOLD + (char) (9312 + (2000 - delta) / 1000),
guiLeft + 56,
guiTop + 99,
true,
4210752
);
}
} else {
Utils.drawStringCentered(
EnumChatFormatting.YELLOW + "Trade " + EnumChatFormatting.BOLD + (char) (9314),
guiLeft + 56,
guiTop + 99,
true,
4210752
);
}
}
}
ItemStack theirConfirmStack = chest.inventorySlots.getInventory().get(41);
if (theirConfirmStack != null) {
String confirmDisplay = theirConfirmStack.getDisplayName();
if (mouseX > guiLeft + 95 && mouseX < guiLeft + 95 + 51) {
if (mouseY > guiTop + 91 && mouseY < guiTop + 91 + 14) {
tooltipToDisplay = theirConfirmStack.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
}
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(location);
Utils.drawTexturedRect(guiLeft + 95, guiTop + 91, 51, 14,
0, 51 / 256f, ySize / 256f, (ySize + 14) / 256f, GL11.GL_NEAREST
);
if (confirmDisplay.equals(EnumChatFormatting.YELLOW + "Pending their confirm")) {
Utils.drawStringCentered(EnumChatFormatting.YELLOW + "Pending", guiLeft + 120, guiTop + 99, true, 4210752);
} else if (confirmDisplay.equals(EnumChatFormatting.YELLOW + "Deal timer...")) {
Utils.drawStringCentered(EnumChatFormatting.YELLOW + "Pending", guiLeft + 120, guiTop + 99, true, 4210752);
} else if (confirmDisplay.equals(EnumChatFormatting.GREEN + "Other player confirmed!")) {
Utils.drawStringCentered(EnumChatFormatting.GREEN + "Accepted", guiLeft + 120, guiTop + 99, true, 4210752);
}
}
for (int i = 0; i < 16; i++) {
int x = i % 4;
int y = i / 4;
int containerIndex = theirTradeIndexes[i];
ItemStack stack = null;
if (containerIndex >= 0) {
stack = chest.inventorySlots.getInventory().get(containerIndex);
Utils.drawItemStack(stack, guiLeft + 96 + x * 18, guiTop + 15 + y * 18);
}
if (currentTime % 400 > 200 && theirTradeChangesMillis[i] != null && theirTradeChangesMillis[i] > 0) {
GlStateManager.translate(0, 0, 200);
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(location);
Utils.drawTexturedRect(guiLeft + 96 + x * 18, guiTop + 15 + y * 18, 16, 16,
51 / 256f, 67 / 256f, 204 / 256f, 220 / 256f, GL11.GL_NEAREST
);
GlStateManager.translate(0, 0, -200);
}
if (mouseX > guiLeft + 96 + x * 18 - 1 && mouseX < guiLeft + 96 + x * 18 + 18) {
if (mouseY > guiTop + 15 + y * 18 - 1 && mouseY < guiTop + 15 + y * 18 + 18) {
if (stack != null) stackToRender = stack;
GlStateManager.disableLighting();
GlStateManager.disableDepth();
GlStateManager.colorMask(true, true, true, false);
Utils.drawGradientRect(guiLeft + 96 + x * 18, guiTop + 15 + y * 18,
guiLeft + 96 + x * 18 + 16, guiTop + 15 + y * 18 + 16, -2130706433, -2130706433
);
GlStateManager.colorMask(true, true, true, true);
GlStateManager.enableLighting();
GlStateManager.enableDepth();
}
}
}
if (NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePrices) {
TreeMap> ourTopItems = new TreeMap<>();
TreeMap ourTopItemsStack = new TreeMap<>();
TreeMap ourTopItemsCount = new TreeMap<>();
double ourPrice = 0;
for (int i = 0; i < 16; i++) {
int x = i % 4;
int y = i / 4;
int containerIndex = y * 9 + x;
ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
if (stack == null) continue;
ourPrice += processTopItems(stack, ourTopItems, ourTopItemsStack, ourTopItemsCount);
}
TreeMap> theirTopItems = new TreeMap<>();
TreeMap theirTopItemsStack = new TreeMap<>();
TreeMap theirTopItemsCount = new TreeMap<>();
double theirPrice = 0;
for (int i = 0; i < 16; i++) {
int x = i % 4;
int y = i / 4;
int containerIndex = y * 9 + x + 5;
ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
if (stack == null) continue;
theirPrice += processTopItems(stack, theirTopItems, theirTopItemsStack, theirTopItemsCount);
}
GlStateManager.disableLighting();
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(location);
Utils.drawTexturedRect(guiLeft - 80 - 3, guiTop, 80, 106,
176 / 256f, 1, 0, 106 / 256f, GL11.GL_NEAREST
);
drawStringShadow(EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + "Total Value",
guiLeft - 40 - 3, guiTop + 11, 72
);
drawStringShadow(EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + StringUtils.formatNumber(ourPrice),
guiLeft - 40 - 3, guiTop + 21, 72
);
int ourTopIndex = Math.max(0, 3 - ourTopItemsStack.size());
out:
for (Map.Entry> entry : ourTopItems.descendingMap().entrySet()) {
for (String ourTopItemInternal : entry.getValue()) {
ItemStack stack = ourTopItemsStack.get(ourTopItemInternal);
if (stack == null) continue;
if (NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePriceStyle) {
String countS = "";
if (ourTopItemsCount.containsKey(ourTopItemInternal)) {
int count = ourTopItemsCount.get(ourTopItemInternal);
if (count > 999999) {
countS = Math.floor(count / 10000f) / 100f + "m";
} else if (count > 999) {
countS = Math.floor(count / 10f) / 100f + "k";
} else {
countS = "" + count;
}
}
Utils.drawItemStackWithText(stack, guiLeft - 75 - 3, guiTop + 49 + 18 * ourTopIndex, countS);
GlStateManager.disableLighting();
GlStateManager.disableBlend();
GlStateManager.color(1, 1, 1, 1);
drawStringShadow(
EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + StringUtils.formatNumber(entry.getKey()),
guiLeft - 29 - 3,
guiTop + 57 + 18 * ourTopIndex,
52
);
GlStateManager.enableBlend();
} else {
drawStringShadow(
stack.getDisplayName() + EnumChatFormatting.GRAY + "x" + ourTopItemsCount.get(ourTopItemInternal),
guiLeft - 40 - 3,
guiTop + 46 + 20 * ourTopIndex,
72
);
drawStringShadow(
EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + StringUtils.formatNumber(entry.getKey()),
guiLeft - 40 - 3,
guiTop + 56 + 20 * ourTopIndex,
72
);
}
if (++ourTopIndex >= 3) break out;
}
}
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(location);
Utils.drawTexturedRect(guiLeft + xSize + 3, guiTop, 80, 106,
176 / 256f, 1, 0, 106 / 256f, GL11.GL_NEAREST
);
drawStringShadow(EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + "Total Value",
guiLeft + xSize + 3 + 40, guiTop + 11, 72
);
drawStringShadow(EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + StringUtils.formatNumber(theirPrice),
guiLeft + xSize + 3 + 40, guiTop + 21, 72
);
int theirTopIndex = Math.max(0, 3 - theirTopItemsStack.size());
out:
for (Map.Entry> entry : theirTopItems.descendingMap().entrySet()) {
for (String theirTopItemInternal : entry.getValue()) {
ItemStack stack = theirTopItemsStack.get(theirTopItemInternal);
if (stack == null) continue;
if (NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePriceStyle) {
String countS = "";
if (theirTopItemsCount.containsKey(theirTopItemInternal)) {
int count = theirTopItemsCount.get(theirTopItemInternal);
if (count > 999999) {
countS = Math.floor(count / 10000f) / 100f + "m";
} else if (count > 999) {
countS = Math.floor(count / 10f) / 100f + "k";
} else {
countS = "" + count;
}
}
Utils.drawItemStackWithText(stack, guiLeft + xSize + 25 + 3 - 16, guiTop + 49 + 18 * theirTopIndex, countS);
GlStateManager.disableLighting();
GlStateManager.disableBlend();
GlStateManager.color(1, 1, 1, 1);
drawStringShadow(
EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + StringUtils.formatNumber(entry.getKey()),
guiLeft + xSize + 3 + 51,
guiTop + 57 + 18 * theirTopIndex,
52
);
GlStateManager.enableBlend();
} else {
drawStringShadow(stack.getDisplayName(),
guiLeft + xSize + 3 + 40, guiTop + 46 + 20 * theirTopIndex, 72
);
drawStringShadow(
EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + StringUtils.formatNumber(entry.getKey()),
guiLeft + xSize + 3 + 40,
guiTop + 56 + 20 * theirTopIndex,
72
);
}
if (++theirTopIndex >= 3) break out;
}
}
}
boolean button1 = NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePriceStyle;
boolean button2 = NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePrices;
boolean button3 = NotEnoughUpdates.INSTANCE.config.tradeMenu.enableCustomTrade;
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(location);
Utils.drawTexturedRect(guiLeft + xSize + 3, guiTop + ySize - 19, 17, 17,
(button3 ? 17 : 0) / 256f, (button3 ? 34 : 17) / 256f, 218 / 256f, 235 / 256f, GL11.GL_NEAREST
);
Utils.drawTexturedRect(guiLeft + xSize + 3, guiTop + ySize - 38, 17, 17,
(button2 ? 17 : 0) / 256f, (button2 ? 34 : 17) / 256f, 218 / 256f, 235 / 256f, GL11.GL_NEAREST
);
Utils.drawTexturedRect(guiLeft + xSize + 3, guiTop + ySize - 57, 17, 17,
(button1 ? 17 : 0) / 256f, (button1 ? 34 : 17) / 256f, 218 / 256f, 235 / 256f, GL11.GL_NEAREST
);
if (mouseX >= guiLeft + xSize + 3 && mouseX <= guiLeft + xSize + 3 + 17) {
if (mouseY >= guiTop + ySize - 19 && mouseY <= guiTop + ySize - 19 + 17) {
tooltipToDisplay = new ArrayList() {{
add(EnumChatFormatting.GOLD + "Enable Custom Trade Menu");
add(EnumChatFormatting.GRAY + "Use this menu instead of the default trade window");
}};
tooltipLen = 200;
} else if (mouseY >= guiTop + ySize - 38 && mouseY <= guiTop + ySize - 38 + 17) {
tooltipToDisplay = new ArrayList() {{
add(EnumChatFormatting.GOLD + "Price Information");
add(EnumChatFormatting.GRAY + "Show the price of items on both sides");
}};
tooltipLen = 200;
} else if (mouseY >= guiTop + ySize - 57 && mouseY <= guiTop + ySize - 57 + 17) {
tooltipToDisplay = new ArrayList() {{
add(EnumChatFormatting.GOLD + "Trade Prices Style");
add(EnumChatFormatting.GRAY + "Changes the style of the top item prices");
}};
tooltipLen = 200;
}
}
if (stackToRender != null) {
tooltipToDisplay = stackToRender.getTooltip(
Minecraft.getMinecraft().thePlayer,
Minecraft.getMinecraft().gameSettings.advancedItemTooltips
);
}
if (tooltipToDisplay != null) {
Utils.drawHoveringText(
tooltipToDisplay,
mouseX,
mouseY,
scaledResolution.getScaledWidth(),
scaledResolution.getScaledHeight(),
tooltipLen
);
}
}
public static void handleMouseInput() {
if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledResolution.getScaledWidth();
int height = scaledResolution.getScaledHeight();
int mouseX = Mouse.getEventX() * width / Minecraft.getMinecraft().displayWidth;
int mouseY = height - Mouse.getEventY() * height / Minecraft.getMinecraft().displayHeight - 1;
GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
if (Mouse.getEventButtonState() && Mouse.isButtonDown(0)) {
int index = 0;
for (ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
if (stack == null) {
index++;
continue;
}
int x = 8 + 18 * (index % 9);
int y = 104 + 18 * (index / 9);
if (index < 9) y = 180;
if (mouseX > guiLeft + x && mouseX < guiLeft + x + 16) {
if (mouseY > guiTop + y && mouseY < guiTop + y + 16) {
Slot slot = chest.inventorySlots.getSlotFromInventory(Minecraft.getMinecraft().thePlayer.inventory, index);
if (!NotEnoughUpdates.INSTANCE.config.slotLocking.lockSlotsInTrade ||
!SlotLocking.getInstance().isSlotLocked(slot)) {
Minecraft.getMinecraft().playerController.windowClick(
chest.inventorySlots.windowId,
slot.slotNumber, 0, 0, Minecraft.getMinecraft().thePlayer
);
}
return;
}
}
index++;
}
for (int i = 0; i < 16; i++) {
int x = i % 4;
int y = i / 4;
Integer containerIndex = ourTradeIndexes[i];
if (containerIndex == null || containerIndex < 0) continue;
if (mouseX > guiLeft + 10 + x * 18 - 1 && mouseX < guiLeft + 10 + x * 18 + 18) {
if (mouseY > guiTop + 15 + y * 18 - 1 && mouseY < guiTop + 15 + y * 18 + 18) {
Minecraft.getMinecraft().playerController.windowClick(
chest.inventorySlots.windowId,
containerIndex, 2, 3, Minecraft.getMinecraft().thePlayer
);
return;
}
}
}
if (mouseX > guiLeft + 10 - 1 && mouseX < guiLeft + 10 + 18) {
if (mouseY > guiTop + 90 - 1 && mouseY < guiTop + 90 + 18) {
Minecraft.getMinecraft().playerController.windowClick(
chest.inventorySlots.windowId,
36, 2, 3, Minecraft.getMinecraft().thePlayer
);
return;
}
}
ItemStack confirmStack = chest.inventorySlots.getInventory().get(39);
if (confirmStack != null) {
String confirmDisplay = confirmStack.getDisplayName();
if (!confirmDisplay.equals(EnumChatFormatting.GREEN + "Trading!")) {
if (mouseX > guiLeft + 42 && mouseX < guiLeft + 42 + 40) {
if (mouseY > guiTop + 92 && mouseY < guiTop + 92 + 14) {
if ((confirmDisplay.equals(EnumChatFormatting.YELLOW + "Warning!") ||
confirmDisplay.equals(EnumChatFormatting.YELLOW + "Deal!")) && lastTradeMillis < 0) {
lastTradeMillis = System.currentTimeMillis();
} else if (lastTradeMillis < 0 || System.currentTimeMillis() - lastTradeMillis > 2000) {
Minecraft.getMinecraft().playerController.windowClick(
chest.inventorySlots.windowId,
39, 2, 3, Minecraft.getMinecraft().thePlayer
);
return;
}
}
}
}
}
if (mouseX >= guiLeft + xSize + 3 && mouseX <= guiLeft + xSize + 3 + 17) {
if (mouseY >= guiTop + ySize - 19 && mouseY <= guiTop + ySize - 19 + 17) {
NotEnoughUpdates.INSTANCE.config.tradeMenu.enableCustomTrade =
!NotEnoughUpdates.INSTANCE.config.tradeMenu.enableCustomTrade;
} else if (mouseY >= guiTop + ySize - 38 && mouseY <= guiTop + ySize - 38 + 17) {
NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePrices =
!NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePrices;
} else if (mouseY >= guiTop + ySize - 57 && mouseY <= guiTop + ySize - 57 + 17) {
NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePriceStyle =
!NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePriceStyle;
}
}
}
}
public static boolean keyboardInput() {
if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking &&
NotEnoughUpdates.INSTANCE.config.slotLocking.lockSlotsInTrade &&
!Keyboard.isRepeatEvent() &&
KeybindHelper.isKeyPressed(NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockKey)) {
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledResolution.getScaledWidth();
int height = scaledResolution.getScaledHeight();
int mouseX = Mouse.getEventX() * width / Minecraft.getMinecraft().displayWidth;
int mouseY = height - Mouse.getEventY() * height / Minecraft.getMinecraft().displayHeight - 1;
int index = 0;
for (ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
if (stack == null) {
index++;
continue;
}
int x = 8 + 18 * (index % 9);
int y = 104 + 18 * (index / 9);
if (index < 9) y = 180;
if (mouseX > guiLeft + x && mouseX < guiLeft + x + 16) {
if (mouseY > guiTop + y && mouseY < guiTop + y + 16) {
SlotLocking.getInstance().toggleLock(index);
return true;
}
}
index++;
}
}
return Keyboard.getEventKey() != Keyboard.KEY_ESCAPE;
}
}