summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java74
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java29
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java265
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java22
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java38
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java13
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java17
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java108
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java5
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/mcworld.pngbin0 -> 291014 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/custom_trade.pngbin0 -> 9338 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.frag129
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert12
15 files changed, 658 insertions, 62 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
index 820c14b1..84094642 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
@@ -516,7 +516,8 @@ public class NEUEventListener {
@SubscribeEvent
public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) {
- if(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ if(TradeWindow.tradeWindowActive() ||
+ event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
event.setCanceled(true);
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
@@ -527,11 +528,19 @@ public class NEUEventListener {
Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680);
if(event.mouseX < width*neu.overlay.getWidthMult()/3 || event.mouseX > width-width*neu.overlay.getWidthMult()/3) {
- neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ if(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ } else {
+ TradeWindow.render(event.mouseX, event.mouseY);
+ }
neu.overlay.render(event.mouseX, event.mouseY, false);
} else {
neu.overlay.render(event.mouseX, event.mouseY, false);
- neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ if(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ } else {
+ TradeWindow.render(event.mouseX, event.mouseY);
+ }
}
}
}
@@ -556,7 +565,8 @@ public class NEUEventListener {
*/
@SubscribeEvent
public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) {
- if(!(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView())) {
+ if(!(TradeWindow.tradeWindowActive() || event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView())) {
if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
if(!focusInv) {
GL11.glTranslatef(0, 0, 300);
@@ -607,14 +617,25 @@ public class NEUEventListener {
ItemStack item = lower.getStackInSlot(11+i);
String internal = neu.manager.getInternalNameForItem(item);
if(internal != null) {
- float worthBIN = neu.manager.auctionManager.getLowestBin(internal);
- float worthAUC = -1;
- JsonObject aucInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
- if(aucInfo != null) {
- worthAUC = aucInfo.get("price").getAsFloat();
+ float bazaarPrice = -1;
+ JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal);
+ if(bazaarInfo != null && bazaarInfo.has("avg_sell")) {
+ bazaarPrice = bazaarInfo.get("avg_sell").getAsFloat();
}
- if(worthAUC == -1) worthAUC = neu.manager.auctionManager.getCraftCost(internal).craftCost;
+ float worthBIN = -1;
+ float worthAUC = -1;
+
+ if(bazaarPrice > 0) {
+ worthBIN = bazaarPrice;
+ worthAUC = bazaarPrice;
+ } else {
+ worthBIN = neu.manager.auctionManager.getLowestBin(internal);
+ JsonObject aucInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
+ if(aucInfo != null) {
+ worthAUC = aucInfo.get("price").getAsFloat();
+ }
+ }
if(worthAUC <= 0 && worthBIN <= 0) {
missing = true;
@@ -714,9 +735,15 @@ public class NEUEventListener {
if(!event.isCanceled()) {
Utils.scrollTooltip(Mouse.getEventDWheel());
}
- if(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ if(TradeWindow.tradeWindowActive() || event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
event.setCanceled(true);
- neu.manager.auctionManager.customAH.handleMouseInput();
+ if(event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ neu.manager.auctionManager.customAH.handleMouseInput();
+ } else {
+ TradeWindow.handleMouseInput();
+ }
neu.overlay.mouseInput();
return;
}
@@ -739,12 +766,23 @@ public class NEUEventListener {
*/
@SubscribeEvent
public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) {
- if(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
- if(neu.manager.auctionManager.customAH.keyboardInput()) {
- event.setCanceled(true);
- Minecraft.getMinecraft().dispatchKeypresses();
- } else if(neu.overlay.keyboardInput(focusInv)) {
- event.setCanceled(true);
+ if(TradeWindow.tradeWindowActive() || event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ if(event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ if(neu.manager.auctionManager.customAH.keyboardInput()) {
+ event.setCanceled(true);
+ Minecraft.getMinecraft().dispatchKeypresses();
+ } else if(neu.overlay.keyboardInput(focusInv)) {
+ event.setCanceled(true);
+ }
+ } else {
+ if(TradeWindow.keyboardInput()) {
+ event.setCanceled(true);
+ Minecraft.getMinecraft().dispatchKeypresses();
+ } else if(neu.overlay.keyboardInput(focusInv)) {
+ event.setCanceled(true);
+ }
}
return;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index 5a02e109..597beca2 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -35,6 +35,7 @@ import net.minecraft.util.*;
import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.client.registry.ClientRegistry;
+import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@@ -344,7 +345,6 @@ public class NotEnoughUpdates {
float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), -1);
float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0);
-
EnumChatFormatting moneyPrefix = (bankBalance+purseBalance)>10*1000*1000?
((bankBalance+purseBalance)>50*1000*1000?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
@@ -352,7 +352,16 @@ public class NotEnoughUpdates {
(bankBalance == -1 ? EnumChatFormatting.YELLOW+"Disabled" : moneyPrefix+
(isMe?"4.8b":Utils.shortNumberFormat(bankBalance, 0)))));
- overallScore += Math.min(2, (bankBalance+purseBalance)/(50f*1000*1000));
+ long networth = profile.getNetWorth(null);
+ if(networth > 0) {
+ EnumChatFormatting moneyPrefix2 = networth>50*1000*1000?
+ (networth>200*1000*1000?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ g+"Networth : "+moneyPrefix2+Utils.shortNumberFormat(networth, 0)));
+ }
+ if(networth == -1) networth = (long)(bankBalance+purseBalance);
+
+ overallScore += Math.min(2, networth/(100f*1000*1000));
String activePet = Utils.getElementAsString(Utils.getElement(profile.getPetsInfo(null), "active_pet.type"),
"None Active");
@@ -420,7 +429,8 @@ public class NotEnoughUpdates {
SimpleCommand.ProcessCommandRunnable viewProfileRunnable = new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
- if(new File(Minecraft.getMinecraft().mcDataDir, "optionsof.txt").exists()) {
+ if(Loader.isModLoaded("optifine") &&
+ new File(Minecraft.getMinecraft().mcDataDir, "optionsof.txt").exists()) {
try(InputStream in = new FileInputStream(new File(Minecraft.getMinecraft().mcDataDir, "optionsof.txt"))) {
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
@@ -453,8 +463,13 @@ public class NotEnoughUpdates {
"Too many arguments. Usage: /neuprofile [name]"));
} else {
profileViewer.getProfileByName(args[0], profile -> {
- if (profile != null) profile.resetCache();
- openGui = new GuiProfileViewer(profile);
+ if(profile == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "Invalid player name/api key. Maybe api is down? Try /api new."));
+ } else {
+ profile.resetCache();
+ openGui = new GuiProfileViewer(profile);
+ }
});
}
}
@@ -480,7 +495,7 @@ public class NotEnoughUpdates {
SimpleCommand viewProfileShortCommand = new SimpleCommand("pv", new SimpleCommand.ProcessCommandRunnable() {
@Override
public void processCommand(ICommandSender sender, String[] args) {
- if(!hasSkyblockScoreboard()) {
+ if(!isOnSkyblock()) {
Minecraft.getMinecraft().thePlayer.sendChatMessage("/pv " + StringUtils.join(args, " "));
} else {
viewProfileRunnable.processCommand(sender, args);
@@ -506,7 +521,7 @@ public class NotEnoughUpdates {
SimpleCommand viewProfileShort2Command = new SimpleCommand("vp", new SimpleCommand.ProcessCommandRunnable() {
@Override
public void processCommand(ICommandSender sender, String[] args) {
- if(!hasSkyblockScoreboard()) {
+ if(!isOnSkyblock()) {
Minecraft.getMinecraft().thePlayer.sendChatMessage("/vp " + StringUtils.join(args, " "));
} else {
viewProfileRunnable.processCommand(sender, args);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java b/src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java
new file mode 100644
index 00000000..b95acc09
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java
@@ -0,0 +1,265 @@
+package io.github.moulberry.notenoughupdates;
+
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntitySign;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatComponentTranslation;
+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.util.List;
+
+public class TradeWindow {
+
+ private static 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;
+
+ public static boolean tradeWindowActive() {
+ if(Keyboard.isKeyDown(Keyboard.KEY_J)) return false;
+
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+ if(guiScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) guiScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ if(containerName.trim().startsWith("You ")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static TexLoc tl = new TexLoc(0, 0, Keyboard.KEY_M);
+
+ 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<String> tooltipToDisplay = null;
+ tl.handleKeyboardInput();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, 0, 176/256f, 0, 204/256f, GL11.GL_NEAREST);
+
+ Utils.drawTexturedRect(guiLeft+42, guiTop+92, 40, 14,
+ 0, 40/256f, ySize/256f, (ySize+14)/256f, GL11.GL_NEAREST);
+ Utils.drawStringCentered("Confirm", Minecraft.getMinecraft().fontRendererObj, guiLeft+64, guiTop+96,
+ false, 4210752);
+
+ Utils.drawStringF(new ChatComponentTranslation("container.inventory").getUnformattedText(),
+ Minecraft.getMinecraft().fontRendererObj, guiLeft+8, guiTop+111, false, 4210752);
+ Utils.drawStringF("You", Minecraft.getMinecraft().fontRendererObj, guiLeft+8,
+ guiTop+5, false, 4210752);
+ String[] split = containerName.split(" ");
+ if(split.length >= 1) {
+ Utils.drawStringF(split[split.length-1], Minecraft.getMinecraft().fontRendererObj, guiLeft+109,
+ 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;
+
+ Utils.drawItemStack(stack, guiLeft+x, guiTop+y);
+
+ if(mouseX > guiLeft+x-1 && mouseX < guiLeft+x+18) {
+ if(mouseY > guiTop+y-1 && mouseY < guiTop+y+18) {
+ if(stack != null) tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, true);
+
+ GlStateManager.disableLighting();
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Utils.drawGradientRect(guiLeft+x, guiTop+y,
+ guiLeft+x + 16, guiTop+y + 16, -2130706433, -2130706433);
+ 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 = y*9+x;
+
+ ItemStack 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) tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, true);
+
+ 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, true);
+ }
+ }
+ }
+
+ ItemStack confirmStack = chest.inventorySlots.getInventory().get(39);
+ if(confirmStack != null) {
+ if(mouseX > guiLeft+42 && mouseX < guiLeft+42+40) {
+ if (mouseY > guiTop+92 && mouseY < guiTop+92+14) {
+ tooltipToDisplay = confirmStack.getTooltip(Minecraft.getMinecraft().thePlayer, true);
+ }
+ }
+ }
+
+ 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);
+
+ Utils.drawItemStack(stack, guiLeft+96+x*18, guiTop+15+y*18);
+
+ 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) tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, true);
+
+ 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(tooltipToDisplay != null) {
+ Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(),
+ -1, Minecraft.getMinecraft().fontRendererObj);
+ }
+ }
+
+ 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);
+ Minecraft.getMinecraft().playerController.windowClick(
+ chest.inventorySlots.windowId,
+ slot.slotNumber, 2, 3, Minecraft.getMinecraft().thePlayer);
+ return;
+ }
+ }
+
+ index++;
+ }
+
+ for(int i=0; i<16; i++) {
+ int x = i % 4;
+ int y = i / 4;
+ int containerIndex = y*9+x;
+
+ 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;
+ }
+ }
+
+ if(mouseX > guiLeft+42 && mouseX < guiLeft+42+40) {
+ if (mouseY > guiTop+92 && mouseY < guiTop+92+14) {
+ Minecraft.getMinecraft().playerController.windowClick(
+ chest.inventorySlots.windowId,
+ 39, 2, 3, Minecraft.getMinecraft().thePlayer);
+ return;
+ }
+ }
+ }
+ }
+
+ public static boolean keyboardInput() {
+ return Keyboard.getEventKey() != Keyboard.KEY_ESCAPE;
+ }
+
+
+
+}
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 14ebdf26..dadcbd3f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
@@ -37,7 +37,7 @@ public class APIManager {
private HashSet<String> playerBidsNotified = new HashSet<>();
private HashSet<String> playerBidsFinishedNotified = new HashSet<>();
- private HashMap<String, TreeMap<Integer, String>> internalnameToLowestBIN = new HashMap<>();
+ private HashMap<String, TreeMap<Integer, Set<String>>> internalnameToLowestBIN = new HashMap<>();
private LinkedList<Integer> pagesToDownload = null;
@@ -218,7 +218,7 @@ public class APIManager {
}
public int getLowestBin(String internalname) {
- TreeMap<Integer, String> lowestBIN = internalnameToLowestBIN.get(internalname);
+ TreeMap<Integer, Set<String>> lowestBIN = internalnameToLowestBIN.get(internalname);
if(lowestBIN == null || lowestBIN.isEmpty()) return -1;
return lowestBIN.firstKey();
}
@@ -294,8 +294,13 @@ public class APIManager {
for(HashSet<String> aucids : internalnameToAucIdMap.values()) {
aucids.removeAll(toRemove);
}
- for(TreeMap<Integer, String> lowestBINs : internalnameToLowestBIN.values()) {
- lowestBINs.values().removeAll(toRemove);
+ for(TreeMap<Integer, Set<String>> lowestBINs : internalnameToLowestBIN.values()) {
+ Set<Integer> toRemoveSet = new HashSet<>();
+ for(Map.Entry<Integer, Set<String>> entry : lowestBINs.entrySet()) {
+ entry.getValue().removeAll(toRemove);
+ if(entry.getValue().isEmpty()) toRemoveSet.add(entry.getKey());
+ }
+ lowestBINs.keySet().removeAll(toRemoveSet);
}
}
@@ -494,10 +499,11 @@ public class APIManager {
}
if(bin) {
- TreeMap<Integer, String> lowestBINs = internalnameToLowestBIN.computeIfAbsent(internalname, k -> new TreeMap<>());
+ TreeMap<Integer, Set<String>> lowestBINs = internalnameToLowestBIN.computeIfAbsent(internalname, k -> new TreeMap<>());
int count = item_tag.getInteger("Count");
- lowestBINs.put(starting_bid/(count>0?count:1), auctionUuid);
- if(lowestBINs.size() > 5) {
+ int price = starting_bid/(count>0?count:1);
+ lowestBINs.computeIfAbsent(price, k -> new HashSet<>()).add(auctionUuid);
+ if(lowestBINs.size() > 10) {
lowestBINs.keySet().remove(lowestBINs.lastKey());
}
}
@@ -696,7 +702,7 @@ public class APIManager {
JsonObject auctionInfo = getItemAuctionInfo(internalname);
JsonObject bazaarInfo = getBazaarInfo(internalname);
- if(bazaarInfo != null) {
+ if(bazaarInfo != null && bazaarInfo.get("curr_buy") != null) {
float bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat();
ci.craftCost = bazaarInstantBuyPrice;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
index 728e692a..98907029 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
@@ -32,8 +32,8 @@ public class CapeManager {
private boolean allAvailable = false;
private HashSet<String> availableCapes = new HashSet<>();
- private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee", "gravy", "space" };
- public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true, false };
+ private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee", "gravy", "space", "mcworld" };
+ public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true, false, false };
public static CapeManager getInstance() {
return INSTANCE;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
index 1f1876af..bfd33e48 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
@@ -160,8 +160,6 @@ public class CapeNode {
}
public void resolve(CapeNode other, float targetDist, float strength, boolean opt) {
- if(other == null || Keyboard.isKeyDown(Keyboard.KEY_H)) return;
-
double dX = position.x - other.position.x;
double dY = position.y - other.position.y;
double dZ = position.z - other.position.z;
@@ -209,7 +207,7 @@ public class CapeNode {
NEUCape.Offset o = new NEUCape.Offset(d, 1);
CapeNode neighbor = getNeighbor(o);
if(neighbor != null) {
- if(!Keyboard.isKeyDown(Keyboard.KEY_H))resolve(neighbor, 1f*NEUCape.targetDist*(d.yOff==0?horzDistMult:1f), 0.5f*7.5f, opt);
+ resolve(neighbor, 1f*NEUCape.targetDist*(d.yOff==0?horzDistMult:1f), 0.5f*7.5f, opt);
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
index f9c4995e..6712f34f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
@@ -64,8 +64,6 @@ public class GuiCosmetics extends GuiScreen {
public static final ResourceLocation cosmetics_fg = new ResourceLocation("notenoughupdates:cosmetics_fg.png");
public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png");
- private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
-
private CosmeticsPage currentPage = CosmeticsPage.CAPES;
private int sizeX;
private int sizeY;
@@ -152,14 +150,22 @@ public class GuiCosmetics extends GuiScreen {
Minecraft.getMinecraft().fontRendererObj.drawString(EnumChatFormatting.AQUA+statusMsg.toString(),
guiLeft+sizeX-Minecraft.getMinecraft().fontRendererObj.getStringWidth(statusMsg.toString()), guiTop-12, 0, true);
- if(currentPage == CosmeticsPage.CAPES && wantToEquipCape != null) {
+ if(currentPage == CosmeticsPage.CAPES) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown);
Utils.drawTexturedRect(guiLeft+sizeX/2f-50, guiTop+sizeY+5, 100, 20, 0, 100/200f, 0, 20/185f, GL11.GL_NEAREST);
- String equipMsg = EnumChatFormatting.GREEN + "Equip Cape";
- if(System.currentTimeMillis() - lastCapeEquip < 20*1000) {
- equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip)/1000) + "s";
+ String equipMsg;
+ if(wantToEquipCape != null) {
+ equipMsg = EnumChatFormatting.GREEN + "Equip Cape";
+ if(System.currentTimeMillis() - lastCapeEquip < 20*1000) {
+ equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip)/1000) + "s";
+ }
+ } else {
+ equipMsg = EnumChatFormatting.GREEN + "Unequip";
+ if(System.currentTimeMillis() - lastCapeEquip < 20*1000) {
+ equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip)/1000) + "s";
+ }
}
Utils.drawStringCenteredScaledMaxWidth(equipMsg, Minecraft.getMinecraft().fontRendererObj,
@@ -280,7 +286,11 @@ public class GuiCosmetics extends GuiScreen {
return;
} else if(equipable && mouseY > guiTop + 149 && mouseY < guiTop + 149 + 20) {
- wantToEquipCape = cape;
+ if(cape.equals(wantToEquipCape)) {
+ wantToEquipCape = null;
+ } else {
+ wantToEquipCape = cape;
+ }
return;
}
}
@@ -288,16 +298,24 @@ public class GuiCosmetics extends GuiScreen {
displayIndex++;
}
- if(currentPage == CosmeticsPage.CAPES && wantToEquipCape != null) {
+ if(currentPage == CosmeticsPage.CAPES) {
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown);
Utils.drawTexturedRect(guiLeft+sizeX/2f-50, guiTop+sizeY+5, 100, 20, 0, 100/200f, 0, 20/185f, GL11.GL_NEAREST);
if(mouseX > guiLeft+sizeX/2f-50 && mouseX < guiLeft+sizeX/2f+50) {
if(mouseY > guiTop+sizeY+5 && mouseY < guiTop+sizeY+25) {
if(System.currentTimeMillis() - lastCapeEquip > 20*1000) {
+ CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""),
+ null, true);
+
lastCapeEquip = System.currentTimeMillis();
- NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/changecape.py?capeType="+wantToEquipCape+"&accessToken="+
- Minecraft.getMinecraft().getSession().getToken(), (jsonObject) -> {}, () -> {});
+ if(wantToEquipCape == null) {
+ NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/changecape.py?capeType=null&accessToken="+
+ Minecraft.getMinecraft().getSession().getToken(), (jsonObject) -> {}, () -> {});
+ } else {
+ NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/changecape.py?capeType="+wantToEquipCape+"&accessToken="+
+ Minecraft.getMinecraft().getSession().getToken(), (jsonObject) -> {}, () -> {});
+ }
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
index a53b300e..197e5483 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
@@ -77,6 +77,8 @@ public class NEUCape {
shaderName = "fade_cape";
} else if(capeName.equalsIgnoreCase("space")) {
shaderName = "space_cape";
+ } else if(capeName.equalsIgnoreCase("mcworld")) {
+ shaderName = "mcworld_cape";
} else {
shaderName = "cape";
}
@@ -298,6 +300,8 @@ public class NEUCape {
shaderManager.loadData(shaderName, "millis", (int)(System.currentTimeMillis()-startTime));
shaderManager.loadData(shaderName, "eventMillis", (int)(System.currentTimeMillis()-eventMillis));
shaderManager.loadData(shaderName, "eventRand", eventRandom);
+ } else if(shaderName.equalsIgnoreCase("mcworld_cape")) {
+ shaderManager.loadData(shaderName, "millis", (int) (System.currentTimeMillis() - startTime));
}
}
@@ -322,9 +326,18 @@ public class NEUCape {
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA,
GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
bindTexture();
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, 0x8191, GL11.GL_TRUE);
GlStateManager.enableTexture2D();
GlStateManager.disableCull();
+ if(shaderName.equals("mcworld_cape")) {
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
+ } else {
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+ }
+
GL11.glTranslatef(-(float)viewerX, -(float)viewerY, -(float)viewerZ);
ShaderManager shaderManager = ShaderManager.getInstance();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
index 2912c6bd..0302d74a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
@@ -303,7 +303,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
itemFramebufferGrayscale.bindFramebufferTexture();
- AtomicReference<JsonObject> tooltipToDisplay = new AtomicReference<>(null);
+ AtomicReference<ItemStack> tooltipToDisplay = new AtomicReference<>(null);
AtomicBoolean isTop = new AtomicBoolean(false);
AtomicInteger lowestY = new AtomicInteger(-1);
@@ -326,7 +326,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
if(mouseX > leftI && mouseX < rightI) {
if(mouseY > topI && mouseY < bottomI) {
- tooltipToDisplay.set(manager.getItemInformation().get(internalname));
+ tooltipToDisplay.set(manager.jsonToStack(manager.getItemInformation().get(internalname), true));
}
}
@@ -360,16 +360,9 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
itemFramebufferGrayscale.unbindFramebufferTexture();
- JsonObject json = tooltipToDisplay.get();
- if(json != null) {
- List<String> text = new ArrayList<>();
- text.add(json.get("displayname").getAsString());
- JsonArray lore = json.get("lore").getAsJsonArray();
-
- for(int i=0; i<lore.size(); i++) {
- text.add(lore.get(i).getAsString());
- }
-
+ ItemStack displayStack = tooltipToDisplay.get();
+ if(displayStack != null) {
+ List<String> text = displayStack.getTooltip(Minecraft.getMinecraft().thePlayer, true);
Utils.drawHoveringText(text, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
index d2b5ea23..ea177804 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
@@ -36,6 +36,16 @@ public class ProfileViewer {
this.manager = manager;
}
+
+ private static HashMap<String, String> petRarityToNumMap = new HashMap<>();
+ static {
+ petRarityToNumMap.put("COMMON", "0");
+ petRarityToNumMap.put("UNCOMMON", "1");
+ petRarityToNumMap.put("RARE", "2");
+ petRarityToNumMap.put("EPIC", "3");
+ petRarityToNumMap.put("LEGENDARY", "4");
+ }
+
private static final LinkedHashMap<String, ItemStack> skillToSkillDisplayMap = new LinkedHashMap<>();
static {
skillToSkillDisplayMap.put("skill_taming", Utils.createItemStack(Items.spawn_egg, EnumChatFormatting.LIGHT_PURPLE+"Taming"));
@@ -265,6 +275,7 @@ public class ProfileViewer {
private JsonObject playerStatus = null;
private HashMap<String, PlayerStats.Stats> stats = new HashMap<>();
private HashMap<String, PlayerStats.Stats> passiveStats = new HashMap<>();
+ private long networth = -1;
public Profile(String uuid) {
this.uuid = uuid;
@@ -295,6 +306,100 @@ public class ProfileViewer {
return null;
}
+ public long getNetWorth(String profileId) {
+ if(networth != -1) return networth;
+ if(getProfileInformation(profileId) == null) return -1;
+ if(getInventoryInfo(profileId) == null) return -1;
+
+ JsonObject inventoryInfo = getInventoryInfo(profileId);
+ JsonObject profileInfo = getProfileInformation(profileId);
+
+ long networth = 0;
+ for(Map.Entry<String, JsonElement> entry : inventoryInfo.entrySet()) {
+ if(entry.getValue().isJsonArray()) {
+ for(JsonElement element : entry.getValue().getAsJsonArray()) {
+ if(element != null && element.isJsonObject()) {
+ JsonObject item = element.getAsJsonObject();
+ String internalname = item.get("internalname").getAsString();
+
+ if(manager.auctionManager.isVanillaItem(internalname)) continue;
+
+ JsonObject info = manager.auctionManager.getItemAuctionInfo(internalname);
+ if(info == null || !info.has("price") || !info.has("count")) continue;
+
+ int auctionPrice = (int)(info.get("price").getAsFloat() / info.get("count").getAsFloat());
+
+ try {
+ if(item.has("item_contents")) {
+ JsonArray bytesArr = item.get("item_contents").getAsJsonArray();
+ byte[] bytes = new byte[bytesArr.size()];
+ for (int bytesArrI = 0; bytesArrI < bytesArr.size(); bytesArrI++) {
+ bytes[bytesArrI] = bytesArr.get(bytesArrI).getAsByte();
+ }
+ NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
+ NBTTagList items = contents_nbt.getTagList("i", 10);
+ for(int j=0; j<items.tagCount(); j++) {
+ if(items.getCompoundTagAt(j).getKeySet().size() > 0) {
+ NBTTagCompound nbt = items.getCompoundTagAt(j).getCompoundTag("tag");
+ String internalname2 = manager.getInternalnameFromNBT(nbt);
+ if(internalname2 != null) {
+ JsonObject info2 = manager.auctionManager.getItemAuctionInfo(internalname2);
+ if(info2 == null || !info2.has("price") || !info2.has("count")) continue;
+ int auctionPrice2 = (int)(info2.get("price").getAsFloat() / info2.get("count").getAsFloat());
+
+ int count2 = items.getCompoundTagAt(j).getByte("Count");
+ networth += auctionPrice2 * count2;
+ }
+ }
+ }
+ }
+ } catch(IOException ignored) {}
+
+ int count = 1;
+ if(element.getAsJsonObject().has("count")) {
+ count = element.getAsJsonObject().get("count").getAsInt();
+ }
+
+ networth += auctionPrice * count;
+ }
+ }
+ }
+ }
+ if(networth == 0) return -1;
+
+ JsonObject petsInfo = getPetsInfo(profileId);
+ if(petsInfo != null && petsInfo.has("pets")) {
+ if(petsInfo.get("pets").isJsonArray()) {
+ JsonArray pets = petsInfo.get("pets").getAsJsonArray();
+ for(JsonElement element : pets) {
+ if(element.isJsonObject()) {
+ JsonObject pet = element.getAsJsonObject();
+
+ String petname = pet.get("type").getAsString();
+ String tier = pet.get("tier").getAsString();
+ String tierNum = petRarityToNumMap.get(tier);
+ if(tierNum != null) {
+ String internalname2 = petname+";"+tierNum;
+ JsonObject info2 = manager.auctionManager.getItemAuctionInfo(internalname2);
+ if(info2 == null || !info2.has("price") || !info2.has("count")) continue;
+ int auctionPrice2 = (int)(info2.get("price").getAsFloat() / info2.get("count").getAsFloat());
+
+ networth += auctionPrice2;
+ }
+ }
+ }
+ }
+ }
+
+ float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), 0);
+ float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0);
+
+ networth += bankBalance+purseBalance;
+
+ this.networth = networth;
+ return networth;
+ }
+
public String getLatestProfile() {
return latestProfile;
}
@@ -436,6 +541,7 @@ public class ProfileViewer {
skillInfoMap.clear();
inventoryInfoMap.clear();
collectionInfoMap.clear();
+ networth = -1;
}
private class Level {
@@ -619,6 +725,8 @@ public class ProfileViewer {
}
}
+ inventoryInfoMap.put(profileId, inventoryInfo);
+
return inventoryInfo;
}
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 9445514f..7ce180b9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
@@ -97,7 +97,7 @@ public class Utils {
}
public static void drawItemStack(ItemStack stack, int x, int y) {
- if(stack == null)return;
+ if(stack == null) return;
drawItemStackWithText(stack, x, y, null);
}
@@ -361,7 +361,8 @@ public class Utils {
public static void drawStringF(String str, FontRenderer fr, float x, float y, boolean shadow, int colour) {
GL11.glTranslatef(x, y, 0);
- fr.drawString(str, x, y, colour, shadow);
+ fr.drawString(str, 0, 0, colour, shadow);
+ GL11.glTranslatef(-x, -y, 0);
}
public static void drawStringScaledMaxWidth(String str, FontRenderer fr, float x, float y, boolean shadow, int len, int colour) {
diff --git a/src/main/resources/assets/notenoughupdates/capes/mcworld.png b/src/main/resources/assets/notenoughupdates/capes/mcworld.png
new file mode 100644
index 00000000..89b3b367
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/mcworld.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/custom_trade.png b/src/main/resources/assets/notenoughupdates/custom_trade.png
new file mode 100644
index 00000000..14ea9f09
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/custom_trade.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.frag b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.frag
new file mode 100644
index 00000000..1dc5e1c8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.frag
@@ -0,0 +1,129 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+uniform sampler2D textureIn;
+
+uniform int millis;
+
+//Algorithm by hughsk
+vec3 hsv2rgb(vec3 c) {
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+
+vec3 rgb2hsv(vec3 c) {
+ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+ vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+ vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+
+ float d = q.x - min(q.w, q.y);
+ float e = 1.0e-10;
+ return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+}
+
+void main() {
+ vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
+
+ float t = gl_TexCoord[0].t;
+ t = clamp(t, 10.0f/1024.0f, 410.0f/1024.0f);
+
+ float start = 56.0f - 44.0f*t/(420.0f/1024.0f);
+ float width = 182.0f + 90.0f*t/(420.0f/1024.0f);
+ float scaleFactor = 1.0f/(width/1024.0f)*112.0f;
+
+ float index = mod(millis/20.0f+t*scaleFactor, 2820.0f);
+ float yIndex = floor(index/1024.0f)*112.0f-(gl_TexCoord[0].s-start/1024.0f)*scaleFactor+532.0f;
+ float xIndex = mod(index, 1024.0f);
+ vec3 world = texture2D(textureIn, vec2(xIndex/1024.0f, yIndex/1024.0f)).xyz;
+
+ float hue = 0.0f;
+ float saturation = 1.0f;
+ float value = 1.0f;
+ if(index < 208) { //sky
+ float blurFactor = clamp((index-158)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 1.0f - blurFactor;
+ value = 0.9f - 0.6f*blurFactor;
+ } else if(index < 800) { //underground
+ if(index < 400) {
+ float blurFactor = clamp((258-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 0.0f + blurFactor;
+ value = 0.3f + 0.6f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-750)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.0f + 0.5f*blurFactor;
+ value = 0.3f - 0.1f*blurFactor;
+ }
+ } else if(index < 1762) { //nether
+ if(index < 1200) {
+ float blurFactor = clamp((850-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.5f - 0.5f*blurFactor;
+ value = 0.2f + 0.1f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-1712)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.5f - 0.5f*blurFactor;
+ value = 0.2f + 0.1f*blurFactor;
+ }
+ } else if(index < 2200) { //underground
+ if(index < 1900) {
+ float blurFactor = clamp((1812-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.0f + 0.5f*blurFactor;
+ value = 0.3f - 0.1f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-2150)/100.0f, 0.0f, 0.5f);
+
+ hue = 0.0f;
+ saturation = 0.0f;
+ value = 0.3f - 0.3f*blurFactor;
+ }
+ } else if(index < 2600) { //end
+ if(index < 2400) {
+ float blurFactor = clamp((2250-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 0.0f;
+ saturation = 0.0f;
+ value = 0.0f + 0.3f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-2550)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 0.0f + blurFactor;
+ value = 0.0f + 0.9f*blurFactor;
+ }
+ } else { //sky
+ float blurFactor = clamp((2650-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 1.0f - blurFactor;
+ value = 0.9f - 0.9f*blurFactor;
+ }
+ hue = mod(hue, 360.0f);
+ saturation = max(0.0f, min(1.0f, saturation));
+ value = max(0.0f, min(1.0f, value));
+
+ vec3 hsv = rgb2hsv(texture.rgb);
+ hsv.x = hue/360.0f;
+ hsv.y *= saturation;
+ hsv.z *= value;
+
+ gl_FragColor = vec4(hsv2rgb(hsv)*texture.a + world*(1.0f-texture.a), 1.0f) * passColour;
+
+ vec3 fakeSunNormal = normalize(vec3(0.2f,1.0f,-0.2f));
+ vec3 normNormal = normalize(passNormal);
+ float shading = max(0.6f, dot(fakeSunNormal, normNormal));
+
+ gl_FragColor = vec4(gl_FragColor.rgb*shading, gl_FragColor.a);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert
new file mode 100644
index 00000000..2b5c48f8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert
@@ -0,0 +1,12 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ passColour = gl_Color;
+ passNormal = normalize(gl_Normal);
+} \ No newline at end of file