aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java181
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java139
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java124
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java57
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java17
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java60
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java817
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java83
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java5
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java13
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java35
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java234
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java257
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java97
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java677
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/GuiContainerAccessor.java22
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java16
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java22
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCreeperCharge.java26
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java6
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java82
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java181
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java3
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java2
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/alexxoffi.pngbin0 -> 588408 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/alexxoffi_preview.pngbin0 -> 135662 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/dsm.pngbin62154 -> 56800 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/dsm_preview.pngbin0 -> 42820 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/furf.pngbin15699 -> 8145 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/furf_preview.pngbin11892 -> 3360 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/jakethybro.pngbin0 -> 151284 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/jakethybro_preview.pngbin0 -> 111454 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/parallax.pngbin0 -> 357618 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/zera.pngbin0 -> 325454 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/zera_preview.pngbin0 -> 156882 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/editor.pngbin0 -> 1806 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/expanded_inventory.pngbin0 -> 2494 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons.json18
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory.pngbin0 -> 1778 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory_gold.pngbin0 -> 1859 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor.pngbin0 -> 1782 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor_gold.pngbin0 -> 1917 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles.pngbin0 -> 776 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles_gold.pngbin0 -> 810 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/cross.pngbin0 -> 1747 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/green_check.pngbin0 -> 1637 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet.pngbin0 -> 1826 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet_gold.pngbin0 -> 1919 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/question.pngbin0 -> 1517 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/recipe.pngbin0 -> 2176 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/search.pngbin0 -> 2018 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/settings.pngbin0 -> 3962 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/skyblock_menu.pngbin0 -> 2108 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/extraicons/white_check.pngbin0 -> 1684 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/invbuttons/presets.json2729
-rw-r--r--src/main/resources/assets/notenoughupdates/search_bar.pngbin0 -> 2964 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/search_bar_gold.pngbin0 -> 4159 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.frag185
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.vert14
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.frag50
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.vert12
-rw-r--r--src/main/resources/mixins.notenoughupdates.json5
69 files changed, 5568 insertions, 634 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
index 58efa371..ff618f10 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
@@ -3,6 +3,7 @@ package io.github.moulberry.notenoughupdates;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
@@ -15,6 +16,10 @@ import java.util.Locale;
public class ItemPriceInformation {
public static boolean addToTooltip(List<String> tooltip, String internalname, ItemStack stack) {
+ return addToTooltip(tooltip, internalname, stack, true);
+ }
+
+ public static boolean addToTooltip(List<String> tooltip, String internalname, ItemStack stack, boolean useStackSize) {
JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
float lowestBinAvg = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalname);
@@ -35,7 +40,7 @@ public class ItemPriceInformation {
boolean shiftPressed = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
int stackMultiplier = 1;
- int shiftStackMultiplier = 64;
+ int shiftStackMultiplier = useStackSize && stack.stackSize > 1 ? stack.stackSize : 64;
if(shiftPressed) {
stackMultiplier = shiftStackMultiplier;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
index 838f0b0a..8219c903 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
@@ -1,5 +1,6 @@
package io.github.moulberry.notenoughupdates;
+import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -16,6 +17,8 @@ import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
import io.github.moulberry.notenoughupdates.gamemodes.SBGamemodes;
import io.github.moulberry.notenoughupdates.miscfeatures.*;
import io.github.moulberry.notenoughupdates.miscgui.*;
+import io.github.moulberry.notenoughupdates.mixins.GuiContainerAccessor;
+import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.overlays.*;
import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
import io.github.moulberry.notenoughupdates.util.*;
@@ -27,6 +30,7 @@ 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.gui.inventory.GuiInventory;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.EntityPlayer;
@@ -41,6 +45,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.*;
+import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.client.event.*;
import net.minecraftforge.event.entity.player.EntityInteractEvent;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
@@ -204,7 +209,6 @@ public class NEUEventListener {
CrystalOverlay.tick();
DwarvenMinesTextures.tick();
FairySouls.tick();
- MiningStuff.tick();
XPInformation.getInstance().tick();
ProfileApiSyncer.getInstance().tick();
DamageCommas.tick();
@@ -734,6 +738,8 @@ public class NEUEventListener {
}
}
+ public static boolean drawingGuiScreen = false;
+
/**
* Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when
* (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true).
@@ -756,10 +762,10 @@ public class NEUEventListener {
if(event.gui instanceof GuiContainer) {
try {
- int xSize = (int) Utils.getField(GuiContainer.class, event.gui, "xSize", "field_146999_f");
- int ySize = (int) Utils.getField(GuiContainer.class, event.gui, "ySize", "field_147000_g");
- int guiLeft = (int) Utils.getField(GuiContainer.class, event.gui, "guiLeft", "field_147003_i");
- int guiTop = (int) Utils.getField(GuiContainer.class, event.gui, "guiTop", "field_147009_r");
+ int xSize = ((GuiContainerAccessor)event.gui).getXSize();
+ int ySize = ((GuiContainerAccessor)event.gui).getYSize();
+ int guiLeft = ((GuiContainerAccessor)event.gui).getGuiLeft();
+ int guiTop = ((GuiContainerAccessor)event.gui).getGuiTop();
hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize &&
event.getMouseY() > guiTop && event.getMouseY() < guiTop + ySize;
@@ -797,10 +803,16 @@ public class NEUEventListener {
}
}
}
+
+ drawingGuiScreen = true;
}
+ private boolean doInventoryButtons = false;
+
@SubscribeEvent
public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) {
+ doInventoryButtons = false;
+
if(AuctionSearchOverlay.shouldReplace()) {
AuctionSearchOverlay.render();
event.setCanceled(true);
@@ -839,6 +851,49 @@ public class NEUEventListener {
}
}
}
+
+ if(CalendarOverlay.isEnabled() || event.isCanceled()) return;
+ if(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui)
+ && event.gui instanceof GuiContainer) {
+ doInventoryButtons = true;
+
+ int zOffset = 50;
+
+ GlStateManager.translate(0, 0, zOffset);
+
+ int xSize = ((GuiContainerAccessor)event.gui).getXSize();
+ int ySize = ((GuiContainerAccessor)event.gui).getYSize();
+ int guiLeft = ((GuiContainerAccessor)event.gui).getGuiLeft();
+ int guiTop = ((GuiContainerAccessor)event.gui).getGuiTop();
+
+ for(NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ if(!button.isActive()) continue;
+ if(button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
+
+ int x = guiLeft+button.x;
+ int y = guiTop+button.y;
+ if(button.anchorRight) {
+ x += xSize;
+ }
+ if(button.anchorBottom) {
+ y += ySize;
+ }
+
+ GlStateManager.color(1, 1, 1, 1f);
+
+ GlStateManager.enableDepth();
+ GlStateManager.enableAlpha();
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ Utils.drawTexturedRect(x, y, 18, 18,
+ button.backgroundIndex*18/256f, (button.backgroundIndex*18+18)/256f,
+ 18/256f, 36/256f, GL11.GL_NEAREST);
+
+ if(button.icon != null && !button.icon.trim().isEmpty()) {
+ GuiInvButtonEditor.renderIcon(button.icon, x+1, y+1);
+ }
+ }
+ GlStateManager.translate(0, 0, -zOffset);
+ }
}
private static boolean shouldRenderOverlay(Gui gui) {
@@ -854,6 +909,11 @@ public class NEUEventListener {
return validGui;
}
+ private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png");
+ private NEUConfig.InventoryButton buttonHovered = null;
+ private long buttonHoveredMillis = 0;
+ public static boolean disableCraftingText = false;
+
/**
* Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay
* will draw over Items in the inventory (which render at a z value of about 250))
@@ -861,6 +921,9 @@ public class NEUEventListener {
*/
@SubscribeEvent
public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) {
+ drawingGuiScreen = false;
+ disableCraftingText = false;
+
if(!(TradeWindow.tradeWindowActive() || event.gui instanceof CustomAHGui ||
neu.manager.auctionManager.customAH.isRenderOverAuctionView())) {
if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
@@ -870,7 +933,6 @@ public class NEUEventListener {
neu.overlay.render(hoverInv && focusInv);
GL11.glTranslatef(0, 0, -300);
}
- neu.overlay.renderOverlay();
GlStateManager.popMatrix();
}
}
@@ -881,6 +943,56 @@ public class NEUEventListener {
AccessoryBagOverlay.renderOverlay();
}
}
+
+ boolean hoveringButton = false;
+ if(!doInventoryButtons) return;
+ if(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) &&
+ event.gui instanceof GuiContainer) {
+ int xSize = ((GuiContainerAccessor)event.gui).getXSize();
+ int ySize = ((GuiContainerAccessor)event.gui).getYSize();
+ int guiLeft = ((GuiContainerAccessor)event.gui).getGuiLeft();
+ int guiTop = ((GuiContainerAccessor)event.gui).getGuiTop();
+
+ for(NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ if(!button.isActive()) continue;
+ if(button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
+
+ int x = guiLeft+button.x;
+ int y = guiTop+button.y;
+ if(button.anchorRight) {
+ x += xSize;
+ }
+ if(button.anchorBottom) {
+ y += ySize;
+ }
+
+ if(x-guiLeft >= 85 && x-guiLeft <= 115 && y-guiTop >= 4 && y-guiTop <= 25) {
+ disableCraftingText = true;
+ }
+
+ if(event.mouseX >= x && event.mouseX <= x+18 &&
+ event.mouseY >= y && event.mouseY <= y+18) {
+ hoveringButton = true;
+ long currentTime = System.currentTimeMillis();
+
+ if(buttonHovered != button) {
+ buttonHoveredMillis = currentTime;
+ buttonHovered = button;
+ }
+
+ if(currentTime - buttonHoveredMillis > 600) {
+ String command = button.command.trim();
+ if(!command.startsWith("/")) {
+ command = "/" + command;
+ }
+
+ Utils.drawHoveringText(Lists.newArrayList("\u00a77"+command), event.mouseX, event.mouseY,
+ event.gui.width, event.gui.height, -1, Minecraft.getMinecraft().fontRendererObj);
+ }
+ }
+ }
+ }
+ if(!hoveringButton) buttonHovered = null;
}
private void renderDungeonChestOverlay(GuiScreen gui) {
@@ -888,10 +1000,10 @@ public class NEUEventListener {
if(gui instanceof GuiChest && neu.config.dungeons.profitDisplayLoc != 2) {
try {
- int xSize = (int) Utils.getField(GuiContainer.class, gui, "xSize", "field_146999_f");
- int ySize = (int) Utils.getField(GuiContainer.class, gui, "ySize", "field_147000_g");
- int guiLeft = (int) Utils.getField(GuiContainer.class, gui, "guiLeft", "field_147003_i");
- int guiTop = (int) Utils.getField(GuiContainer.class, gui, "guiTop", "field_147009_r");
+ int xSize = ((GuiContainerAccessor)gui).getXSize();
+ int ySize = ((GuiContainerAccessor)gui).getYSize();
+ int guiLeft = ((GuiContainerAccessor)gui).getGuiLeft();
+ int guiTop = ((GuiContainerAccessor)gui).getGuiTop();
GuiChest eventGui = (GuiChest) gui;
ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
@@ -1083,7 +1195,7 @@ public class NEUEventListener {
* Will also cancel the event if if NEUOverlay#mouseInput returns true.
* @param event
*/
- @SubscribeEvent
+ @SubscribeEvent(priority = EventPriority.LOW)
public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) {
if(!event.isCanceled()) {
Utils.scrollTooltip(Mouse.getEventDWheel());
@@ -1121,6 +1233,53 @@ public class NEUEventListener {
}
}
}
+ if(event.isCanceled()) return;
+ if(!doInventoryButtons) return;
+ if(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) && Mouse.getEventButton() >= 0
+ && event.gui instanceof GuiContainer) {
+ int xSize = ((GuiContainerAccessor)event.gui).getXSize();
+ int ySize = ((GuiContainerAccessor)event.gui).getYSize();
+ int guiLeft = ((GuiContainerAccessor)event.gui).getGuiLeft();
+ int guiTop = ((GuiContainerAccessor)event.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;
+
+ for(NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ if(!button.isActive()) continue;
+ if(button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
+
+ int x = guiLeft+button.x;
+ int y = guiTop+button.y;
+ if(button.anchorRight) {
+ x += xSize;
+ }
+ if(button.anchorBottom) {
+ y += ySize;
+ }
+
+ if(mouseX >= x && mouseX <= x+18 && mouseY >= y && mouseY <= y+18) {
+ if(Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
+ int clickType = NotEnoughUpdates.INSTANCE.config.inventoryButtons.clickType;
+ if((clickType == 0 && Mouse.getEventButtonState()) || (clickType == 1 && !Mouse.getEventButtonState())) {
+ String command = button.command.trim();
+ if(!command.startsWith("/")) {
+ command = "/" + command;
+ }
+ if(ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command) == 0) {
+ NotEnoughUpdates.INSTANCE.sendChatMessage(command);
+ }
+ }
+ } else {
+ event.setCanceled(true);
+ }
+ return;
+ }
+ }
+ }
}
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index 061d6774..4f392ae8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -17,6 +17,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
import net.minecraft.network.play.client.C0DPacketCloseWindow;
import net.minecraft.util.ResourceLocation;
+import org.apache.commons.io.FileUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
@@ -26,6 +27,8 @@ import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -57,10 +60,10 @@ public class NEUManager {
private String currentProfileBackup = "";
public final HypixelApi hypixelApi = new HypixelApi();
- private ResourceLocation wkZip = new ResourceLocation("notenoughupdates:wkhtmltox.zip");
private Map<String, ItemStack> itemstackCache = new HashMap<>();
- //private static final String AUCTIONS_PRICE_URL = "https://moulberry.github.io/files/auc_avg_jsons/average_3day.json.gz";
+ private ExecutorService repoLoaderES = Executors.newSingleThreadExecutor();
+
private static final String GIT_COMMITS_URL = "https://api.github.com/repos/Moulberry/NotEnoughUpdates-REPO/commits/master";
private HashMap<String, Set<String>> usagesMap = new HashMap<>();
@@ -88,15 +91,6 @@ public class NEUManager {
if(itemRenameJson == null) {
itemRenameJson = new JsonObject();
}
-
- File wkShell = new File(configLocation, "wkhtmltox/bin/wkhtmltoimage");
- if(!wkShell.exists()) {
- try {
- InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(wkZip).getInputStream();
- unzip(is, configLocation);
- } catch (IOException e) {
- }
- }
}
public void setCurrentProfile(String currentProfile) {
@@ -163,7 +157,7 @@ public class NEUManager {
}*/
- Thread thread = new Thread(() -> {
+ repoLoaderES.submit(() -> {
JDialog dialog = null;
try {
if(NotEnoughUpdates.INSTANCE.config.hidden.autoupdate) {
@@ -211,12 +205,23 @@ public class NEUManager {
} catch (IOException e) {
return;
}
+
+
URL url = new URL(dlUrl);
URLConnection urlConnection = url.openConnection();
urlConnection.setConnectTimeout(15000);
- urlConnection.setReadTimeout(20000);
- try (BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream());
- FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) {
+ urlConnection.setReadTimeout(30000);
+
+ try(InputStream is = urlConnection.getInputStream()) {
+ FileUtils.copyInputStreamToFile(is, itemsZip);
+ } catch (IOException e) {
+ dialog.dispose();
+ e.printStackTrace();
+ System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator");
+ return;
+ }
+ /*try (BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream());
+ FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) {
@@ -225,7 +230,7 @@ public class NEUManager {
} catch (IOException e) {
dialog.dispose();
return;
- }
+ }*/
pane.setMessage("Unzipping NEU Master Archive.");
dialog.pack();
@@ -242,6 +247,8 @@ public class NEUManager {
} catch (IOException e) {
}
}
+
+ Constants.reload();
}
} catch(Exception e) {
e.printStackTrace();
@@ -249,31 +256,40 @@ public class NEUManager {
if(dialog != null) dialog.dispose();
}
+ System.err.println("First load");
+
File items = new File(repoLocation, "items");
if(items.exists()) {
File[] itemFiles = new File(repoLocation, "items").listFiles();
if(itemFiles != null) {
for(File f : itemFiles) {
String internalname = f.getName().substring(0, f.getName().length()-5);
- if(!getItemInformation().keySet().contains(internalname)) {
- loadItem(internalname);
+ synchronized(itemMap) {
+ if(!itemMap.keySet().contains(internalname)) {
+ loadItem(internalname);
+ }
}
}
}
}
});
+ System.err.println("Second load");
+
File items = new File(repoLocation, "items");
if(items.exists()) {
File[] itemFiles = new File(repoLocation, "items").listFiles();
if(itemFiles != null) {
for(File f : itemFiles) {
String internalname = f.getName().substring(0, f.getName().length()-5);
- loadItem(internalname);
+ synchronized(itemMap) {
+ if(!itemMap.keySet().contains(internalname)) {
+ loadItem(internalname);
+ }
+ }
}
}
}
- thread.start();
}
/**
@@ -301,56 +317,69 @@ public class NEUManager {
itemMap.put(internalName, json);
if(json.has("recipe")) {
- JsonObject recipe = json.get("recipe").getAsJsonObject();
-
- String[] x = {"1","2","3"};
- String[] y = {"A","B","C"};
- for(int i=0; i<9; i++) {
- String name = y[i/3]+x[i%3];
- String itemS = recipe.get(name).getAsString();
- if(itemS != null && itemS.split(":").length == 2) {
- itemS = itemS.split(":")[0];
- }
+ synchronized(usagesMap) {
+ JsonObject recipe = json.get("recipe").getAsJsonObject();
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ String name = y[i/3]+x[i%3];
+ String itemS = recipe.get(name).getAsString();
+ if(itemS != null && itemS.split(":").length == 2) {
+ itemS = itemS.split(":")[0];
+ }
- if(!usagesMap.containsKey(itemS)) {
- usagesMap.put(itemS, new HashSet<>());
+ if(!usagesMap.containsKey(itemS)) {
+ usagesMap.put(itemS, new HashSet<>());
+ }
+ usagesMap.get(itemS).add(internalName);
}
- usagesMap.get(itemS).add(internalName);
}
}
if(json.has("displayname")) {
- int wordIndex=0;
- for(String str : json.get("displayname").getAsString().split(" ")) {
- str = clean(str);
- if(!titleWordMap.containsKey(str)) {
- titleWordMap.put(str, new HashMap<>());
- }
- if(!titleWordMap.get(str).containsKey(internalName)) {
- titleWordMap.get(str).put(internalName, new ArrayList<>());
+ synchronized(titleWordMap) {
+ int wordIndex=0;
+ for(String str : json.get("displayname").getAsString().split(" ")) {
+ str = clean(str);
+ if(!titleWordMap.containsKey(str)) {
+ titleWordMap.put(str, new HashMap<>());
+ }
+ if(!titleWordMap.get(str).containsKey(internalName)) {
+ titleWordMap.get(str).put(internalName, new ArrayList<>());
+ }
+ titleWordMap.get(str).get(internalName).add(wordIndex);
+ wordIndex++;
}
- titleWordMap.get(str).get(internalName).add(wordIndex);
- wordIndex++;
}
}
if(json.has("lore")) {
- int wordIndex=0;
- for(JsonElement element : json.get("lore").getAsJsonArray()) {
- for(String str : element.getAsString().split(" ")) {
- str = clean(str);
- if(!loreWordMap.containsKey(str)) {
- loreWordMap.put(str, new HashMap<>());
- }
- if(!loreWordMap.get(str).containsKey(internalName)) {
- loreWordMap.get(str).put(internalName, new ArrayList<>());
+ synchronized(loreWordMap) {
+ int wordIndex=0;
+ for(JsonElement element : json.get("lore").getAsJsonArray()) {
+ for(String str : element.getAsString().split(" ")) {
+ str = clean(str);
+ if(!loreWordMap.containsKey(str)) {
+ loreWordMap.put(str, new HashMap<>());
+ }
+ if(!loreWordMap.get(str).containsKey(internalName)) {
+ loreWordMap.get(str).put(internalName, new ArrayList<>());
+ }
+ loreWordMap.get(str).get(internalName).add(wordIndex);
+ wordIndex++;
}
- loreWordMap.get(str).get(internalName).add(wordIndex);
- wordIndex++;
}
}
}
} catch(Exception e) {
+ synchronized(loreWordMap) {
+ System.out.println("loreWordMap is : " + loreWordMap);
+ }
+ synchronized(titleWordMap) {
+ System.out.println("titleWordMap is : " + titleWordMap);
+ }
+ System.out.println("internalName is : " + internalName);
e.printStackTrace();
}
}
@@ -1037,7 +1066,7 @@ public class NEUManager {
/**
* Modified from https://www.journaldev.com/960/java-unzip-file-example
*/
- private static void unzip(InputStream src, File dest) {
+ public static void unzip(InputStream src, File dest) {
//buffer for read and write data to file
byte[] buffer = new byte[1024];
try {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
index 952d8f59..fa83ff0a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
@@ -65,6 +65,8 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.*;
public class NEUOverlay extends Gui {
private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = new ResourceLocation("notenoughupdates:supersecretassets/bald.png");
+ private static final ResourceLocation SEARCH_BAR = new ResourceLocation("notenoughupdates:search_bar.png");
+ private static final ResourceLocation SEARCH_BAR_GOLD = new ResourceLocation("notenoughupdates:search_bar_gold.png");
private NEUManager manager;
@@ -117,12 +119,15 @@ public class NEUOverlay extends Gui {
private LerpingInteger itemPaneTabOffset = new LerpingInteger(20, 50);
private LerpingFloat infoPaneOffsetFactor = new LerpingFloat(0);
- private boolean searchMode = false;
+ public boolean searchMode = false;
private long millisLastLeftClick = 0;
private long millisLastMouseMove = 0;
private int lastMouseX = 0;
private int lastMouseY = 0;
+ public static final int overlayColourDark = new Color(0, 0, 0, 120).getRGB();
+ public static final int overlayColourLight = new Color(255, 255, 255, 120).getRGB();
+
boolean mouseDown = false;
private boolean redrawItems = false;
@@ -200,14 +205,51 @@ public class NEUOverlay extends Gui {
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
int paddingUnscaled = getPaddingUnscaled();
- //Search bar background
- drawRect((int)x, (int)y,
- (int)x + getWidth(), (int)y + getHeight(),
- searchMode ? Color.YELLOW.getRGB() : Color.WHITE.getRGB());
+ GlStateManager.color(1, 1, 1, 1);
+ if(searchMode) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_BAR_GOLD);
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_BAR);
+ }
+
+ int w = getWidth();
+ int h = getHeight();
+
+ for(int yIndex=0; yIndex<=2; yIndex++) {
+ for(int xIndex=0; xIndex<=2; xIndex++) {
+ float uMin = 0;
+ float uMax = 4/20f;
+ int partX = (int)x;
+ int partW = 4;
+ if(xIndex == 1) {
+ partX += 4;
+ uMin = 4/20f;
+ uMax = 16/20f;
+ partW = w-8;
+ } else if(xIndex == 2) {
+ partX += w-4;
+ uMin = 16/20f;
+ uMax = 20/20f;
+ }
- drawRect((int)x + paddingUnscaled, (int)y + paddingUnscaled,
- (int)x - paddingUnscaled + getWidth(), (int)y - paddingUnscaled + getHeight(),
- Color.BLACK.getRGB());
+ float vMin = 0;
+ float vMax = 4/20f;
+ int partY = (int)y;
+ int partH = 4;
+ if(yIndex == 1) {
+ partY += 4;
+ vMin = 4/20f;
+ vMax = 16/20f;
+ partH = h-8;
+ } else if(yIndex == 2) {
+ partY += h-4;
+ vMin = 16/20f;
+ vMax = 20/20f;
+ }
+
+ Utils.drawTexturedRect(partX, partY, partW, partH, uMin, uMax, vMin, vMax, GL11.GL_NEAREST);
+ }
+ }
//Search bar text
fr.drawString(textField.getText(), (int)x + 5,
@@ -792,6 +834,10 @@ public class NEUOverlay extends Gui {
return paddingUnscaled;
}
+ public GuiTextField getTextField() {
+ return textField;
+ }
+
/**
* Returns searchBarXSize, scaled by 0.8 if gui scale == AUTO.
*/
@@ -1522,52 +1568,6 @@ public class NEUOverlay extends Gui {
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
}
- /**
- * Renders black squares over the inventory to indicate items that do not match a specific search. (When searchMode
- * is enabled)
- */
- public void renderOverlay() {
- int width = Utils.peekGuiScale().getScaledWidth();
- int height = Utils.peekGuiScale().getScaledHeight();
- int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
- int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
-
- if(searchMode && textField.getText().length() > 0) {
- if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) {
- GuiContainer inv = (GuiContainer) Minecraft.getMinecraft().currentScreen;
- int guiLeftI = (int)Utils.getField(GuiContainer.class, inv, "guiLeft", "field_147003_i");
- int guiTopI = (int)Utils.getField(GuiContainer.class, inv, "guiTop", "field_147009_r");
-
- GL11.glTranslatef(0, 0, 260);
- int overlay = new Color(0, 0, 0, 100).getRGB();
- for(Slot slot : inv.inventorySlots.inventorySlots) {
- boolean matches = false;
- for(String search : textField.getText().split("\\|")) {
- matches |= slot.getStack() != null && manager.doesStackMatchSearch(slot.getStack(), search.trim());
- }
- if(!matches) {
- drawRect(guiLeftI+slot.xDisplayPosition, guiTopI+slot.yDisplayPosition,
- guiLeftI+slot.xDisplayPosition+16, guiTopI+slot.yDisplayPosition+16,
- overlay);
- }
- }
- if(Utils.getSlotUnderMouse(inv) != null) {
- ItemStack stack = Utils.getSlotUnderMouse(inv).getStack();
- //Minecraft.getMinecraft().currentScreen.renderToolTip(stack, mouseX, mouseY);
- Class<?>[] params = new Class[]{ItemStack.class, int.class, int.class};
- Method renderToolTip = Utils.getMethod(GuiScreen.class, params, "renderToolTip", "func_146285_a");
- if(renderToolTip != null) {
- renderToolTip.setAccessible(true);
- try {
- renderToolTip.invoke(Minecraft.getMinecraft().currentScreen, stack, mouseX, mouseY);
- } catch(Exception e) {}
- }
- }
- GL11.glTranslatef(0, 0, -260);
- }
- }
- }
-
Shader blurShaderHorz = null;
Framebuffer blurOutputHorz = null;
Shader blurShaderVert = null;
@@ -1730,13 +1730,15 @@ public class NEUOverlay extends Gui {
//Atomic reference used so that below lambda doesn't complain about non-effectively-final variable
AtomicReference<JsonObject> tooltipToDisplay = new AtomicReference<>(null);
if(itemPaneOffsetFactor.getValue() < 1) {
- BackgroundBlur.renderBlurredBackground(NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor,
- width, height,
- leftSide+getBoxPadding()-5, getBoxPadding()-5,
- paneWidth-getBoxPadding()*2+10, height-getBoxPadding()*2+10, true);
- Gui.drawRect(leftSide+getBoxPadding()-5, getBoxPadding()-5,
- leftSide+getBoxPadding()-5+paneWidth-getBoxPadding()*2+10,
- getBoxPadding()-5+height-getBoxPadding()*2+10, 0xc8101010);
+ if(NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor > 0.5) {
+ BackgroundBlur.renderBlurredBackground(NotEnoughUpdates.INSTANCE.config.itemlist.bgBlurFactor,
+ width, height,
+ leftSide+getBoxPadding()-5, getBoxPadding()-5,
+ paneWidth-getBoxPadding()*2+10, height-getBoxPadding()*2+10, true);
+ Gui.drawRect(leftSide+getBoxPadding()-5, getBoxPadding()-5,
+ leftSide+getBoxPadding()-5+paneWidth-getBoxPadding()*2+10,
+ getBoxPadding()-5+height-getBoxPadding()*2+10, 0xc8101010);
+ }
drawRect(leftSide+getBoxPadding()-5, getBoxPadding()-5,
leftSide+paneWidth-getBoxPadding()+5, height-getBoxPadding()+5, bg.getRGB());
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index 59c821b0..2da79f84 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -18,10 +18,7 @@ import io.github.moulberry.notenoughupdates.gamemodes.GuiGamemodes;
import io.github.moulberry.notenoughupdates.gamemodes.SBGamemodes;
import io.github.moulberry.notenoughupdates.infopanes.CollectionLogInfoPane;
import io.github.moulberry.notenoughupdates.miscfeatures.*;
-import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay;
-import io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour;
-import io.github.moulberry.notenoughupdates.miscgui.HelpGUI;
-import io.github.moulberry.notenoughupdates.miscgui.NEUOverlayPlacements;
+import io.github.moulberry.notenoughupdates.miscgui.*;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.options.NEUConfigEditor;
import io.github.moulberry.notenoughupdates.overlays.FuelBar;
@@ -35,6 +32,7 @@ import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.XPInformation;
import net.minecraft.block.material.MapColor;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiInventory;
@@ -123,6 +121,32 @@ public class NotEnoughUpdates {
}
});
+ SimpleCommand nullzeeSphereCommand = new SimpleCommand("neuzeesphere", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ if(args.length != 1) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+"Usage: /neuzeesphere [on/off] or /neuzeesphere (radius) or /neuzeesphere setCenter"));
+ return;
+ }
+ if(args[0].equalsIgnoreCase("on")) {
+ NullzeeSphere.enabled = true;
+ } else if(args[0].equalsIgnoreCase("off")) {
+ NullzeeSphere.enabled = false;
+ } else if(args[0].equalsIgnoreCase("setCenter")) {
+ EntityPlayerSP p = ((EntityPlayerSP)sender);
+ NullzeeSphere.centerPos = new BlockPos(p.posX, p.posY, p.posZ);
+ NullzeeSphere.overlayVBO = null;
+ } else {
+ try {
+ float radius = Float.parseFloat(args[0]);
+ NullzeeSphere.size = radius;
+ NullzeeSphere.overlayVBO = null;
+ } catch(Exception e) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+"Can't parse radius: " + args[0]));
+ }
+ }
+ }
+ });
+
SimpleCommand itemRenameCommand = new SimpleCommand("neurename", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
if(args.length == 0) {
@@ -215,6 +239,12 @@ public class NotEnoughUpdates {
}
});
+ SimpleCommand buttonsCommand = new SimpleCommand("neubuttons", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ openGui = new GuiInvButtonEditor();
+ }
+ });
+
SimpleCommand enchantColourCommand = new SimpleCommand("neuec", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
openGui = new GuiEnchantColour();
@@ -250,6 +280,13 @@ public class NotEnoughUpdates {
}
}
Constants.reload();
+
+ configFile = new File(neuDir, "configNew.json");
+ if(configFile.exists()) {
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8))) {
+ config = gson.fromJson(reader, NEUConfig.class);
+ } catch(Exception e) { }
+ }
}
});
@@ -690,7 +727,14 @@ public class NotEnoughUpdates {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+devFailStrings[devFailIndex++]));
return;
}
- if(args.length == 1 && args[0].equalsIgnoreCase("dev")) NotEnoughUpdates.INSTANCE.config.hidden.dev = true;
+ if(args.length == 1 && args[0].equalsIgnoreCase("dev")) {
+ NotEnoughUpdates.INSTANCE.config.hidden.dev = true;
+ return;
+ }
+ if(args.length == 1 && args[0].equalsIgnoreCase("saveconfig")) {
+ saveConfig();
+ return;
+ }
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Executing dubious code"));
/*Minecraft.getMinecraft().thePlayer.rotationYaw = 0;
Minecraft.getMinecraft().thePlayer.rotationPitch = 0;
@@ -991,15 +1035,18 @@ public class NotEnoughUpdates {
MinecraftForge.EVENT_BUS.register(XPInformation.getInstance());
MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay);
MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay);
+ MinecraftForge.EVENT_BUS.register(new NullzeeSphere());
if(Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) {
((IReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(CustomSkulls.getInstance());
}
ClientCommandHandler.instance.registerCommand(collectionLogCommand);
+ ClientCommandHandler.instance.registerCommand(nullzeeSphereCommand);
ClientCommandHandler.instance.registerCommand(cosmeticsCommand);
ClientCommandHandler.instance.registerCommand(linksCommand);
ClientCommandHandler.instance.registerCommand(gamemodesCommand);
+ ClientCommandHandler.instance.registerCommand(buttonsCommand);
ClientCommandHandler.instance.registerCommand(resetRepoCommand);
ClientCommandHandler.instance.registerCommand(reloadRepoCommand);
ClientCommandHandler.instance.registerCommand(itemRenameCommand);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java
index b2f947d6..111803e8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java
@@ -2,6 +2,7 @@ package io.github.moulberry.notenoughupdates.core;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiScreen;
@@ -462,14 +463,21 @@ public class GuiElementTextField {
String selectedText = textField.getSelectedText();
if(!selectedText.isEmpty()) {
+ System.out.println("Start");
int leftIndex = Math.min(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length());
int rightIndex = Math.max(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length());
float texX = 0;
int texY = 0;
boolean sectionSignPrev = false;
+ boolean ignoreNext = false;
boolean bold = false;
for(int i=0; i<textNoColor.length(); i++) {
+ if(ignoreNext) {
+ ignoreNext = false;
+ continue;
+ }
+
char c = textNoColor.charAt(i);
if(sectionSignPrev) {
if(c != 'k' && c != 'K'
@@ -478,9 +486,13 @@ public class GuiElementTextField {
&& c != 'o' && c != 'O') {
bold = c == 'l' || c == 'L';
}
+ sectionSignPrev = false;
+ if(i < prependText.length()) continue;
+ }
+ if(c == '\u00B6') {
+ sectionSignPrev = true;
+ if(i < prependText.length()) continue;
}
- sectionSignPrev = false;
- if(c == '\u00B6') sectionSignPrev = true;
if(c == '\n') {
if(i >= leftIndex && i < rightIndex) {
@@ -497,6 +509,7 @@ public class GuiElementTextField {
//String c2 = bold ? EnumChatFormatting.BOLD.toString() : "" + c;
+ System.out.println("Adding len for char:"+c+":"+Integer.toHexString(c));
int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c));
if(bold) len++;
if(i >= leftIndex && i < rightIndex) {
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 963b91c3..21f6baaf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
@@ -48,8 +48,11 @@ public class CapeManager {
public JsonObject lastJsonSync = null;
private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee",
- "gravy", "space", "mcworld", "lava", "packshq", "mbstaff", "thebakery", "negative", "void", "ironmoon", "krusty", "furf", "soldier", "dsm" };
- public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true, false, false, false, true, true, true, false, false, true, false, true, true, true };
+ "gravy", "space", "mcworld", "lava", "packshq", "mbstaff", "thebakery", "negative",
+ "void", "ironmoon", "krusty", "furf", "soldier", "dsm", "zera", "tunnel", "alexxoffi", "parallax", "jakethybro", "planets" };
+ public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true,
+ true, false, false, false, true, true, true, false,
+ false, true, false, true, true, true, true, false, true, true, true, 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 b01365d3..06bc6db4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
@@ -31,6 +31,10 @@ public class CapeNode {
public Vector3f sideNormal = null;
public boolean fixed = false;
+ public static final int DRAW_MASK_FRONT = 0b1;
+ public static final int DRAW_MASK_BACK = 0b10;
+ public static final int DRAW_MASK_SIDES = 0b100;
+
public HashMap<NEUCape.Offset, CapeNode> neighbors = new HashMap<>();
public float texU = 0;
@@ -279,6 +283,10 @@ public class CapeNode {
}
public void renderNode() {
+ renderNode(DRAW_MASK_FRONT | DRAW_MASK_BACK | DRAW_MASK_SIDES);
+ }
+
+ public void renderNode(int mask) {
CapeNode nodeLeft = getNeighbor(new NEUCape.Offset(NEUCape.Direction.LEFT, 1));
CapeNode nodeUp = getNeighbor(new NEUCape.Offset(NEUCape.Direction.UP, 1));
CapeNode nodeDown = getNeighbor(new NEUCape.Offset(NEUCape.Direction.DOWN, 1));
@@ -290,36 +298,42 @@ public class CapeNode {
if(nodeDown != null && nodeRight != null && nodeDownRight != null) {
//Back
- worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_NORMAL);
- for(CapeNode node : new CapeNode[]{this, nodeDown, nodeRight, nodeDownRight}) {
- Vector3f nodeNorm = node.normal();
- worldrenderer.pos(node.renderPosition.x, node.renderPosition.y, node.renderPosition.z)
- .tex(1-node.texU, node.texV)
- .normal(-nodeNorm.x, -nodeNorm.y, -nodeNorm.z).endVertex();
+ if((mask & DRAW_MASK_BACK) != 0) {
+ worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_NORMAL);
+ for(CapeNode node : new CapeNode[]{this, nodeDown, nodeRight, nodeDownRight}) {
+ Vector3f nodeNorm = node.normal();
+ worldrenderer.pos(node.renderPosition.x, node.renderPosition.y, node.renderPosition.z)
+ .tex(1-node.texU, node.texV)
+ .normal(-nodeNorm.x, -nodeNorm.y, -nodeNorm.z).endVertex();
+ }
+ tessellator.draw();
}
- tessellator.draw();
//Front (Offset by normal)
- worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_NORMAL);
- for(CapeNode node : new CapeNode[]{this, nodeDown, nodeRight, nodeDownRight}) {
- Vector3f nodeNorm = node.normal();
- worldrenderer.pos(node.renderPosition.x+nodeNorm.x*0.05f, node.renderPosition.y+nodeNorm.y*0.05f, node.renderPosition.z+nodeNorm.z*0.05f)
- .tex(node.texU, node.texV)
- .normal(nodeNorm.x, nodeNorm.y, nodeNorm.z).endVertex();
+ if((mask & DRAW_MASK_FRONT) != 0) {
+ worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_NORMAL);
+ for(CapeNode node : new CapeNode[]{nodeDownRight, nodeDown, nodeRight, this}) {
+ Vector3f nodeNorm = node.normal();
+ worldrenderer.pos(node.renderPosition.x+nodeNorm.x*0.05f, node.renderPosition.y+nodeNorm.y*0.05f, node.renderPosition.z+nodeNorm.z*0.05f)
+ .tex(node.texU, node.texV)
+ .normal(nodeNorm.x, nodeNorm.y, nodeNorm.z).endVertex();
+ }
+ tessellator.draw();
}
- tessellator.draw();
}
- if(nodeLeft == null || nodeRight == null) {
- //Render left/right edge
- if(nodeDown != null) {
- renderEdge(nodeDown, true);
+ if((mask & DRAW_MASK_SIDES) != 0) {
+ if(nodeLeft == null || nodeRight == null) {
+ //Render left/right edge
+ if(nodeDown != null) {
+ renderEdge(nodeDown, true);
+ }
}
- }
- if(nodeUp == null || nodeDown == null) {
- //Render up/down edge
- if(nodeRight != null) {
- renderEdge(nodeRight, false);
+ if(nodeUp == null || nodeDown == null) {
+ //Render up/down edge
+ if(nodeRight != null) {
+ renderEdge(nodeRight, false);
+ }
}
}
}
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 d0651075..164dfeb8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
@@ -269,7 +269,7 @@ public class GuiCosmetics extends GuiScreen {
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);
+ wantToEquipCape, true);
lastCapeEquip = System.currentTimeMillis();
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 b2d220c8..163b14dd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
@@ -1,7 +1,9 @@
package io.github.moulberry.notenoughupdates.cosmetics;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils;
+import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer;
import io.github.moulberry.notenoughupdates.util.TexLoc;
+import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
@@ -9,6 +11,8 @@ import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.renderer.vertex.VertexFormat;
+import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
@@ -16,6 +20,7 @@ import net.minecraft.potion.Potion;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.Vec3;
import net.minecraft.world.gen.NoiseGeneratorSimplex;
import net.minecraftforge.client.event.RenderPlayerEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@@ -27,6 +32,7 @@ import org.lwjgl.opengl.*;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
+import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.security.Key;
@@ -45,7 +51,7 @@ public class NEUCape {
private static int ANIM_MODE_PINGPONG = 1;
private int animMode = ANIM_MODE_LOOP;
- private List<List<CapeNode>> nodes = null;
+ private CapeNode[] nodes = null;
private Random random = new Random();
@@ -60,7 +66,7 @@ public class NEUCape {
public static final int HORZ_NODES = 6;
public static final int VERT_NODES = 22;
- public static float targetDist = 1/20f;
+ public static float targetDist = 1 / 20f;
private EntityPlayer currentPlayer;
private boolean keepCurrentPlayer = false;
@@ -93,11 +99,15 @@ public class NEUCape {
shaderName = "negative";
} else if(capeName.equalsIgnoreCase("void")) {
shaderName = "void";
+ } else if(capeName.equalsIgnoreCase("tunnel")) {
+ shaderName = "tunnel";
+ } else if(capeName.equalsIgnoreCase("planets")) {
+ shaderName = "planets";
} else {
shaderName = "shiny_cape";
}
- ResourceLocation staticCapeTex = new ResourceLocation("notenoughupdates:capes/"+capeName+".png");
+ ResourceLocation staticCapeTex = new ResourceLocation("notenoughupdates:capes/" + capeName + ".png");
capeTextures = new ResourceLocation[1];
capeTextures[0] = staticCapeTex;
@@ -128,17 +138,17 @@ public class NEUCape {
if(CapeManager.getInstance().backgroundFramebuffer != null) {
CapeManager.getInstance().backgroundFramebuffer.bindFramebufferTexture();
}
- } else if(capeTextures != null && capeTextures.length>0) {
+ } else if(capeTextures != null && capeTextures.length > 0) {
long currentTime = System.currentTimeMillis();
if(currentTime - lastFrameUpdate > 100) {
- lastFrameUpdate = currentTime/100*100;
+ lastFrameUpdate = currentTime / 100 * 100;
currentFrame++;
if(animMode == ANIM_MODE_PINGPONG) {
if(capeTextures.length == 1) {
currentFrame = displayFrame = 0;
} else {
- int frameCount = 2*capeTextures.length-2;
+ int frameCount = 2 * capeTextures.length - 2;
currentFrame %= frameCount;
displayFrame = currentFrame;
if(currentFrame >= capeTextures.length) {
@@ -154,80 +164,72 @@ public class NEUCape {
}
}
- public boolean rlExists(ResourceLocation loc) {
- try {
- return !Minecraft.getMinecraft().getResourceManager().getAllResources(loc).isEmpty();
- } catch(Exception e) {
- return false;
- }
+ private CapeNode getNode(int x, int y) {
+ return nodes[x + y * HORZ_NODES];
}
public void createCapeNodes(EntityPlayer player) {
- nodes = new ArrayList<>();
+ nodes = new CapeNode[HORZ_NODES * VERT_NODES];
- float pX = (float)player.posX % 7789;
- float pY = (float)player.posY;
- float pZ = (float)player.posZ % 7789;
+ float pX = (float) player.posX % 7789;
+ float pY = (float) player.posY;
+ float pZ = (float) player.posZ % 7789;
- float uMinTop = 48/1024f;
- float uMaxTop = 246/1024f;
- float uMinBottom = 0/1024f;
- float uMaxBottom = 293/1024f;
+ float uMinTop = 48 / 1024f;
+ float uMaxTop = 246 / 1024f;
+ float uMinBottom = 0 / 1024f;
+ float uMaxBottom = 293 / 1024f;
- float vMaxSide = 404/1024f;
- float vMaxCenter = 419/1024f;
+ float vMaxSide = 404 / 1024f;
+ float vMaxCenter = 419 / 1024f;
- for(int i=0; i<VERT_NODES; i++) {
- float uMin = uMinTop + (uMinBottom - uMinTop) * i/(float)(VERT_NODES-1);
- float uMax = uMaxTop + (uMaxBottom - uMaxTop) * i/(float)(VERT_NODES-1);
+ for(int i = 0; i < VERT_NODES; i++) {
+ float uMin = uMinTop + (uMinBottom - uMinTop) * i / (float) (VERT_NODES - 1);
+ float uMax = uMaxTop + (uMaxBottom - uMaxTop) * i / (float) (VERT_NODES - 1);
- List<CapeNode> row = new ArrayList<>();
- for(int j=0; j<HORZ_NODES; j++) {
+ for(int j = 0; j < HORZ_NODES; j++) {
float vMin = 0f;
- float centerMult = 1-Math.abs(j-(HORZ_NODES-1)/2f)/((HORZ_NODES-1)/2f);//0-(horzCapeNodes) -> 0-1-0
+ float centerMult = 1 - Math.abs(j - (HORZ_NODES - 1) / 2f) / ((HORZ_NODES - 1) / 2f);//0-(horzCapeNodes) -> 0-1-0
float vMax = vMaxSide + (vMaxCenter - vMaxSide) * centerMult;
CapeNode node = new CapeNode(pX, pY, pZ);//pX-1, pY+2-i*targetDist, pZ+(j-(horzCapeNodes-1)/2f)*targetDist*2
- node.texU = uMin + (uMax - uMin) * j/(float)(HORZ_NODES-1);
- node.texV = vMin + (vMax - vMin) * i/(float)(VERT_NODES-1);
+ node.texU = uMin + (uMax - uMin) * j / (float) (HORZ_NODES - 1);
+ node.texV = vMin + (vMax - vMin) * i / (float) (VERT_NODES - 1);
- node.horzDistMult = 2f+1f*i/(float)(VERT_NODES-1);
+ node.horzDistMult = 2f + 1f * i / (float) (VERT_NODES - 1);
- if(j == 0 || j == HORZ_NODES-1) {
- node.horzSideTexU = 406/1024f * i/(float)(VERT_NODES-1);
+ if(j == 0 || j == HORZ_NODES - 1) {
+ node.horzSideTexU = 406 / 1024f * i / (float) (VERT_NODES - 1);
if(j == 0) {
- node.horzSideTexVTop = 1 - 20/1024f;
+ node.horzSideTexVTop = 1 - 20 / 1024f;
} else {
- node.horzSideTexVTop = 1 - 40/1024f;
+ node.horzSideTexVTop = 1 - 40 / 1024f;
}
}
if(i == 0) {
- node.vertSideTexU = 198/1024f * j/(float)(HORZ_NODES-1);
- node.vertSideTexVTop = 1 - 60/1024f;
- } else if(i == VERT_NODES-1) {
- node.vertSideTexU = 300/1024f * j/(float)(HORZ_NODES-1);
- node.vertSideTexVTop = 1 - 80/1024f;
+ node.vertSideTexU = 198 / 1024f * j / (float) (HORZ_NODES - 1);
+ node.vertSideTexVTop = 1 - 60 / 1024f;
+ } else if(i == VERT_NODES - 1) {
+ node.vertSideTexU = 300 / 1024f * j / (float) (HORZ_NODES - 1);
+ node.vertSideTexVTop = 1 - 80 / 1024f;
}
- row.add(node);
+ nodes[j + i * HORZ_NODES] = node;
}
-
- nodes.add(row);
}
- for(int y=0; y<nodes.size(); y++) {
- int xSize = nodes.get(y).size();
- for(int x=0; x<xSize; x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
for(Direction dir : Direction.values()) {
- for(int i=1; i<=2; i++) {
+ for(int i = 1; i <= 2; i++) {
Offset offset = new Offset(dir, i);
- int xNeighbor = x+offset.getXOffset();
- int yNeighbor = y+offset.getYOffset();
+ int xNeighbor = x + offset.getXOffset();
+ int yNeighbor = y + offset.getYOffset();
- if(xNeighbor >= 0 && xNeighbor < nodes.get(y).size()
- && yNeighbor >= 0 && yNeighbor < nodes.size()) {
- CapeNode neighbor = nodes.get(yNeighbor).get(xNeighbor);
+ if(xNeighbor >= 0 && xNeighbor < HORZ_NODES
+ && yNeighbor >= 0 && yNeighbor < VERT_NODES) {
+ CapeNode neighbor = nodes[xNeighbor + yNeighbor * HORZ_NODES];
node.setNeighbor(offset, neighbor);
}
}
@@ -291,11 +293,11 @@ public class NEUCape {
}
public int getXOffset() {
- return direction.xOff*steps;
+ return direction.xOff * steps;
}
public int getYOffset() {
- return direction.yOff*steps;
+ return direction.yOff * steps;
}
public boolean equals(Object obj) {
@@ -308,27 +310,27 @@ public class NEUCape {
@Override
public int hashCode() {
- return 13*direction.ordinal() + 7*steps;
+ return 13 * direction.ordinal() + 7 * steps;
}
}
private void loadShaderUniforms(ShaderManager shaderManager) {
- String shaderId = "capes/"+shaderName+"/"+shaderName;
- if(shaderName.equalsIgnoreCase("fade_cape")) {
- shaderManager.loadData(shaderId, "millis", (int)(System.currentTimeMillis()-startTime));
+ String shaderId = "capes/" + shaderName + "/" + shaderName;
+ if(shaderName.equalsIgnoreCase("fade_cape") || shaderName.equalsIgnoreCase("planets")) {
+ shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime));
} else if(shaderName.equalsIgnoreCase("space_cape")) {
- shaderManager.loadData(shaderId, "millis", (int)(System.currentTimeMillis()-startTime));
- shaderManager.loadData(shaderId, "eventMillis", (int)(System.currentTimeMillis()-eventMillis));
+ shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime));
+ shaderManager.loadData(shaderId, "eventMillis", (int) (System.currentTimeMillis() - eventMillis));
shaderManager.loadData(shaderId, "eventRand", eventRandom);
} else if(shaderName.equalsIgnoreCase("mcworld_cape")) {
shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime));
} else if(shaderName.equalsIgnoreCase("lava_cape")) {
shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime));
- } else if(shaderName.equalsIgnoreCase("lightning_cape")) {
+ } else if(shaderName.equalsIgnoreCase("tunnel")) {
shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime));
} else if(shaderName.equalsIgnoreCase("biscuit_cape") || shaderName.equalsIgnoreCase("shiny_cape")) {
shaderManager.loadData(shaderId, "millis", (int) (System.currentTimeMillis() - startTime));
- shaderManager.loadData(shaderId, "eventMillis", (int)(System.currentTimeMillis()-eventMillis));
+ shaderManager.loadData(shaderId, "eventMillis", (int) (System.currentTimeMillis() - eventMillis));
} else if(shaderName.equalsIgnoreCase("negative")) {
shaderManager.loadData(shaderId, "screensize", new Vector2f(
Minecraft.getMinecraft().displayWidth,
@@ -344,6 +346,7 @@ public class NEUCape {
}
long lastRender = 0;
+
public void onRenderPlayer(RenderPlayerEvent.Post e) {
EntityPlayer player = e.entityPlayer;
@@ -378,21 +381,23 @@ public class NEUCape {
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
}
- GL11.glTranslatef(-(float)viewerX, -(float)viewerY, -(float)viewerZ);
+ GL11.glTranslatef(-(float) viewerX, -(float) viewerY, -(float) viewerZ);
ShaderManager shaderManager = ShaderManager.getInstance();
- shaderManager.loadShader("capes/"+shaderName+"/"+shaderName);
+ shaderManager.loadShader("capes/" + shaderName + "/" + shaderName);
loadShaderUniforms(shaderManager);
renderCape(player, e.partialRenderTick);
- GL11.glTranslatef((float)viewerX, (float)viewerY, (float)viewerZ);
+ GL11.glTranslatef((float) viewerX, (float) viewerY, (float) viewerZ);
GL20.glUseProgram(0);
GlStateManager.enableCull();
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
+ GlStateManager.enableDepth();
+ GlStateManager.enableLighting();
GlStateManager.popMatrix();
lastRender = System.currentTimeMillis();
@@ -412,9 +417,9 @@ public class NEUCape {
ensureCapeNodesCreated(player);
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
node.lastPosition.x = node.position.x;
node.lastPosition.y = node.position.y;
node.lastPosition.z = node.position.z;
@@ -429,9 +434,11 @@ public class NEUCape {
private static double interpolateRotation(float a, float b, float amount) {
double f;
- for (f = b - a; f < -180.0F; f += 360.0F) {;}
+ for(f = b - a; f < -180.0F; f += 360.0F) {
+ ;
+ }
- while (f >= 180.0F) {
+ while(f >= 180.0F) {
f -= 360.0F;
}
@@ -475,22 +482,21 @@ public class NEUCape {
double vertOffset2 = vertOffset + (player.isSneaking() ? -0.22f : 0) + (player.getCurrentArmor(2) != null ? 0.06f : 0);
double shoulderWidth2 = shoulderWidth + (player.getCurrentArmor(2) != null ? 0.08f : 0);
- float xOff = (float)(Math.cos(angle)*shoulderLength);
- float zOff = (float)(Math.sin(angle)*shoulderLength);
+ float xOff = (float) (Math.cos(angle) * shoulderLength);
+ float zOff = (float) (Math.sin(angle) * shoulderLength);
float totalDX = 0;
float totalDY = 0;
float totalDZ = 0;
int totalMovements = 0;
- int xSize = nodes.get(0).size();
- for(int i=0; i<xSize; i++) {
- float mult = 1 - 2f*i/(xSize-1); //1 -> -1
- float widthMult = 1.25f-(1.414f*i/(xSize-1) - 0.707f)*(1.414f*i/(xSize-1) - 0.707f);
- CapeNode node = nodes.get(0).get(i);
- float x = (float)pX+(float)(xOff*mult-widthMult*Math.cos(angle+Math.PI/2)*shoulderWidth2);
- float y = (float)pY+(float)(vertOffset2);
- float z = (float)pZ+(float)(zOff*mult-widthMult*Math.sin(angle+Math.PI/2)*shoulderWidth2);
+ for(int i = 0; i < HORZ_NODES; i++) {
+ float mult = 1 - 2f * i / (HORZ_NODES - 1); //1 -> -1
+ float widthMult = 1.25f - (1.414f * i / (HORZ_NODES - 1) - 0.707f) * (1.414f * i / (HORZ_NODES - 1) - 0.707f);
+ CapeNode node = nodes[i];
+ float x = (float) pX + (float) (xOff * mult - widthMult * Math.cos(angle + Math.PI / 2) * shoulderWidth2);
+ float y = (float) pY + (float) (vertOffset2);
+ float z = (float) pZ + (float) (zOff * mult - widthMult * Math.sin(angle + Math.PI / 2) * shoulderWidth2);
totalDX += x - node.position.x;
totalDY += y - node.position.y;
totalDZ += z - node.position.z;
@@ -501,9 +507,9 @@ public class NEUCape {
node.fixed = true;
}
- float avgDX = totalDX/totalMovements;
- float avgDY = totalDY/totalMovements;
- float avgDZ = totalDZ/totalMovements;
+ float avgDX = totalDX / totalMovements;
+ float avgDY = totalDY / totalMovements;
+ float avgDZ = totalDZ / totalMovements;
return new Vector3f(avgDX, avgDY, avgDZ);
}
@@ -517,17 +523,16 @@ public class NEUCape {
double vertOffset2 = vertOffset + (player.isSneaking() ? -0.22f : 0) + (player.getCurrentArmor(2) != null ? 0.06f : 0);
double shoulderWidth2 = shoulderWidth + (player.getCurrentArmor(2) != null ? 0.08f : 0);
- float xOff = (float)(Math.cos(angle)*shoulderLength);
- float zOff = (float)(Math.sin(angle)*shoulderLength);
-
- int xSize = nodes.get(0).size();
- for(int i=0; i<xSize; i++) {
- float mult = 1 - 2f*i/(xSize-1); //1 -> -1
- float widthMult = 1.25f-(1.414f*i/(xSize-1) - 0.707f)*(1.414f*i/(xSize-1) - 0.707f);
- CapeNode node = nodes.get(0).get(i);
- node.renderPosition.x = (float)pX+(float)(xOff*mult-widthMult*Math.cos(angle+Math.PI/2)*shoulderWidth2);
- node.renderPosition.y = (float)pY+(float)(vertOffset2);
- node.renderPosition.z = (float)pZ+(float)(zOff*mult-widthMult*Math.sin(angle+Math.PI/2)*shoulderWidth2);
+ float xOff = (float) (Math.cos(angle) * shoulderLength);
+ float zOff = (float) (Math.sin(angle) * shoulderLength);
+
+ for(int i = 0; i < HORZ_NODES; i++) {
+ float mult = 1 - 2f * i / (HORZ_NODES - 1); //1 -> -1
+ float widthMult = 1.25f - (1.414f * i / (HORZ_NODES - 1) - 0.707f) * (1.414f * i / (HORZ_NODES - 1) - 0.707f);
+ CapeNode node = nodes[i];
+ node.renderPosition.x = (float) pX + (float) (xOff * mult - widthMult * Math.cos(angle + Math.PI / 2) * shoulderWidth2);
+ node.renderPosition.y = (float) pY + (float) (vertOffset2);
+ node.renderPosition.z = (float) pZ + (float) (zOff * mult - widthMult * Math.sin(angle + Math.PI / 2) * shoulderWidth2);
node.fixed = true;
}
}
@@ -536,57 +541,58 @@ public class NEUCape {
private double oldPlayerAngle;
private int crouchTicks = 0;
long startTime = 0;
+
private void updateCape(EntityPlayer player) {
Vector3f capeTranslation = updateFixedCapeNodes(player);
if(shaderName.equals("space_cape")) {
long currentTime = System.currentTimeMillis();
- if(currentTime-startTime > eventMillis-startTime+eventLength) {
+ if(currentTime - startTime > eventMillis - startTime + eventLength) {
eventMillis = currentTime;
- eventLength = random.nextFloat()*2000+4000;
+ eventLength = random.nextFloat() * 2000 + 4000;
eventRandom = random.nextFloat();
}
} else if(shaderName.equals("biscuit_cape") || shaderName.equals("shiny_cape")) {
long currentTime = System.currentTimeMillis();
- if(currentTime-startTime > eventMillis-startTime+eventLength) {
+ if(currentTime - startTime > eventMillis - startTime + eventLength) {
eventMillis = currentTime;
- eventLength = random.nextFloat()*3000+3000;
+ eventLength = random.nextFloat() * 3000 + 3000;
}
}
double playerAngle = getPlayerRenderAngle(player, 0);
double deltaAngle = playerAngle - oldPlayerAngle;
if(deltaAngle > Math.PI) {
- deltaAngle = 2*Math.PI - deltaAngle;
+ deltaAngle = 2 * Math.PI - deltaAngle;
}
if(deltaAngle < -Math.PI) {
- deltaAngle = 2*Math.PI + deltaAngle;
+ deltaAngle = 2 * Math.PI + deltaAngle;
}
deltaAngleAccum *= 0.5f;
deltaAngleAccum += deltaAngle;
- float dX = (float)Math.cos(playerAngle+Math.PI/2f);
- float dZ = (float)Math.sin(playerAngle+Math.PI/2f);
+ float dX = (float) Math.cos(playerAngle + Math.PI / 2f);
+ float dZ = (float) Math.sin(playerAngle + Math.PI / 2f);
- float factor = (float)(deltaAngleAccum*deltaAngleAccum);
+ float factor = (float) (deltaAngleAccum * deltaAngleAccum);
float capeTransLength = capeTranslation.length();
float capeTranslationFactor = 0f;
if(capeTransLength > 0.5f) {
- capeTranslationFactor = (capeTransLength-0.5f)/capeTransLength;
+ capeTranslationFactor = (capeTransLength - 0.5f) / capeTransLength;
}
Vector3f lookDir = new Vector3f(dX, 0, dZ);
Vector3f lookDirNorm = lookDir.normalise(null);
float dot = Vector3f.dot(capeTranslation, lookDirNorm);
if(dot < 0) { //Moving backwards
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
if(!node.fixed) {
- node.position.x += lookDirNorm.x*dot;
- node.position.y += lookDirNorm.y*dot;
- node.position.z += lookDirNorm.z*dot;
+ node.position.x += lookDirNorm.x * dot;
+ node.position.y += lookDirNorm.y * dot;
+ node.position.z += lookDirNorm.z * dot;
}
}
}
@@ -595,21 +601,21 @@ public class NEUCape {
}
if(factor > 0) {
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).applyForce(-dX*factor, 0, -dZ*factor);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].applyForce(-dX * factor, 0, -dZ * factor);
}
}
}
if(capeTranslationFactor > 0f) {
- float capeDX = capeTranslation.x*capeTranslationFactor;
- float capeDY = capeTranslation.y*capeTranslationFactor;
- float capeDZ = capeTranslation.z*capeTranslationFactor;
+ float capeDX = capeTranslation.x * capeTranslationFactor;
+ float capeDY = capeTranslation.y * capeTranslationFactor;
+ float capeDZ = capeTranslation.z * capeTranslationFactor;
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
if(!node.fixed) {
node.position.x += capeDX;
node.position.y += capeDY;
@@ -620,15 +626,15 @@ public class NEUCape {
}
//Wind
- float currTime = (System.currentTimeMillis()-startTime)/1000f;
- float windRandom = Math.abs((float)(0.5f*Math.sin(0.22f*currTime)+Math.sin(0.44f*currTime)*Math.sin(0.47f*currTime)));
- double windDir = playerAngle+Math.PI/4f*Math.sin(0.2f*currTime);
-
- float windDX = (float)Math.cos(windDir+Math.PI/2f);
- float windDZ = (float)Math.sin(windDir+Math.PI/2f);
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).applyForce(-windDX*windRandom*0.01f, 0, -windDZ*windRandom*0.01f);
+ float currTime = (System.currentTimeMillis() - startTime) / 1000f;
+ float windRandom = Math.abs((float) (0.5f * Math.sin(0.22f * currTime) + Math.sin(0.44f * currTime) * Math.sin(0.47f * currTime)));
+ double windDir = playerAngle + Math.PI / 4f * Math.sin(0.2f * currTime);
+
+ float windDX = (float) Math.cos(windDir + Math.PI / 2f);
+ float windDZ = (float) Math.sin(windDir + Math.PI / 2f);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].applyForce(-windDX * windRandom * 0.01f, 0, -windDZ * windRandom * 0.01f);
}
}
@@ -638,9 +644,9 @@ public class NEUCape {
if(crouchTicks < 5) {
mult = 2f;
}
- for(int y=0; y<8; y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).applyForce(-dX*mult, 0, -dZ*mult);
+ for(int y = 0; y < 8; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].applyForce(-dX * mult, 0, -dZ * mult);
}
}
} else {
@@ -648,13 +654,13 @@ public class NEUCape {
}
Vector3f avgPosition = avgFixedPosition();
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
Vector3f delta = Vector3f.sub(node.position, avgPosition, null);
- if(delta.lengthSquared() > 5*5) {
+ if(delta.lengthSquared() > 5 * 5) {
Vector3f norm = delta.normalise(null);
node.position = Vector3f.add(avgPosition, norm, null);
}
@@ -663,32 +669,33 @@ public class NEUCape {
oldPlayerAngle = playerAngle;
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).update();
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].update();
}
}
int updates = player == Minecraft.getMinecraft().thePlayer ? 50 : 50;
- for(int i=0; i<updates; i++) {
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).resolveAll(2+1f*y/nodes.size(), false);
+ for(int i = 0; i < updates; i++) {
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].resolveAll(2 + 1f * y / VERT_NODES, false);
}
}
}
}
private int ssbo = -1;
+
private void generateSSBO() {
ssbo = GL15.glGenBuffers();
loadSBBO();
}
private void loadSBBO() {
- FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM*HORZ_NODES*VERT_NODES);
- for(int y=0; y<VERT_NODES; y++) {
- for(int x=0; x<HORZ_NODES; x++) {
- nodes.get(y).get(x).loadIntoBuffer(buff);
+ FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM * HORZ_NODES * VERT_NODES);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].loadIntoBuffer(buff);
}
}
buff.flip();
@@ -714,32 +721,64 @@ public class NEUCape {
GL20.glUseProgram(program);
- for(int i=0; i<30; i++) {
+ for(int i = 0; i < 30; i++) {
GL43.glDispatchCompute(VERT_NODES, 1, 1);
GL42.glMemoryBarrier(GL43.GL_SHADER_STORAGE_BARRIER_BIT);
}
GL20.glUseProgram(0);
- FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM*HORZ_NODES*VERT_NODES);
+ FloatBuffer buff = BufferUtils.createFloatBuffer(CapeNode.FLOAT_NUM * HORZ_NODES * VERT_NODES);
GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, ssbo);
GL15.glGetBufferSubData(GL43.GL_SHADER_STORAGE_BUFFER, 0, buff);
GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, 0);
- for(int y=0; y<VERT_NODES; y++) {
- for(int x=0; x<HORZ_NODES; x++) {
- nodes.get(y).get(x).readFromBuffer(buff);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].readFromBuffer(buff);
+ }
+ }
+ }
+
+ private Vector3f avgRenderPosition() {
+ Vector3f accum = new Vector3f();
+ int num = 0;
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
+ Vector3f.add(accum, node.renderPosition, accum);
+ num++;
+ }
+ }
+ if(num != 0) {
+ accum.scale(1f / num);
+ }
+ return accum;
+ }
+
+ private Vector3f avgNormal() {
+ Vector3f accum = new Vector3f();
+ int num = 0;
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
+ Vector3f.add(accum, node.normal(), accum);
+ num++;
}
}
+ if(num != 0) {
+ accum.scale(1f / num);
+ }
+ return accum;
}
private Vector3f avgFixedRenderPosition() {
Vector3f accum = new Vector3f();
int numFixed = 0;
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
if(node.fixed) {
Vector3f.add(accum, node.renderPosition, accum);
numFixed++;
@@ -747,7 +786,7 @@ public class NEUCape {
}
}
if(numFixed != 0) {
- accum.scale(1f/numFixed);
+ accum.scale(1f / numFixed);
}
return accum;
}
@@ -755,9 +794,9 @@ public class NEUCape {
private Vector3f avgFixedPosition() {
Vector3f accum = new Vector3f();
int numFixed = 0;
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
if(node.fixed) {
Vector3f.add(accum, node.position, accum);
numFixed++;
@@ -765,11 +804,429 @@ public class NEUCape {
}
}
if(numFixed != 0) {
- accum.scale(1f/numFixed);
+ accum.scale(1f / numFixed);
}
return accum;
}
+ private void renderBackAndDoFrontStencil() {
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].renderNode(CapeNode.DRAW_MASK_BACK | CapeNode.DRAW_MASK_SIDES);
+ }
+ }
+
+ if(!Minecraft.getMinecraft().getFramebuffer().isStencilEnabled())
+ Minecraft.getMinecraft().getFramebuffer().enableStencil();
+
+ GL11.glEnable(GL11.GL_STENCIL_TEST);
+ GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
+ GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_REPLACE);
+ GL11.glStencilMask(0xFF);
+ GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
+ GlStateManager.enableDepth();
+
+ GL11.glColorMask(false, false, false, false);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].renderNode(CapeNode.DRAW_MASK_FRONT);
+ }
+ }
+ GL11.glColorMask(true, true, true, true);
+
+ // Only pass stencil test if equal to 1
+ GL11.glStencilMask(0x00);
+ GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
+ }
+
+ private Vector3f getPoint(Vector3f point, Vector3f... vectors) {
+ Vector3f res = new Vector3f(point);
+ for(Vector3f vec : vectors) Vector3f.add(res, vec, res);
+ return res;
+ }
+
+ private static void renderVBO(WorldRenderer worldRenderer) {
+ if(worldRenderer != null && worldRenderer.getVertexCount() > 0) {
+ VertexFormat vertexformat = worldRenderer.getVertexFormat();
+ int stride = vertexformat.getNextOffset();
+ ByteBuffer bytebuffer = worldRenderer.getByteBuffer();
+ List<VertexFormatElement> list = vertexformat.getElements();
+
+ for(int index = 0; index < list.size(); index++) {
+ VertexFormatElement vertexformatelement = list.get(index);
+ vertexformatelement.getUsage().preDraw(vertexformat, index, stride, bytebuffer);
+ }
+
+ GL11.glDrawArrays(worldRenderer.getDrawMode(), 0, worldRenderer.getVertexCount());
+
+ for(int index = 0; index < list.size(); index++) {
+ VertexFormatElement vertexformatelement = list.get(index);
+ vertexformatelement.getUsage().postDraw(vertexformat, index, stride, bytebuffer);
+ }
+ }
+ }
+
+ private static WorldRenderer sphereVBO = null;
+
+ private void renderNodes() {
+ if(capeName.equalsIgnoreCase("planets")) {
+ renderBackAndDoFrontStencil();
+
+ Vector3f pointNorm = avgNormal();
+ Vector3f capeAvgPos = avgRenderPosition();
+
+ pointNorm.scale(0.5f / pointNorm.length());
+ pointNorm.scale(1 - pointNorm.y / 1.3f);
+ Vector3f point = Vector3f.sub(capeAvgPos, pointNorm, null);
+
+ if(sphereVBO == null || Keyboard.isKeyDown(Keyboard.KEY_K)) {
+ if(sphereVBO != null) sphereVBO.reset();
+
+ int arcSegments = 24;
+ int rotationSegments = 24;
+ double arcAngleDelta = Math.PI / (arcSegments - 1);
+
+ float xScale = 0.95f;
+
+ double diameterUnitArcLen = 0;
+
+ double arcAngle = 0;
+ for(int i = 0; i < arcSegments; i++) {
+ diameterUnitArcLen += Math.sin(arcAngle);
+ arcAngle += arcAngleDelta;
+ }
+ double arcLength = 2f / diameterUnitArcLen;
+
+ List<List<Vector3f>> arcs = new ArrayList<>();
+ for(int angleI = 0; angleI < rotationSegments; angleI++) {
+ double angle = Math.PI * 2 * angleI / rotationSegments;
+
+ List<Vector3f> arc = new ArrayList<>();
+
+ Vector3f arcPos = new Vector3f(0, 0, -1);
+
+ arc.add(arcPos);
+
+ arcAngle = 0;
+ for(int segmentI = 0; segmentI < arcSegments; segmentI++) {
+
+ double deltaZ = Math.sin(arcAngle) * arcLength;
+ double deltaY = Math.cos(arcAngle) * Math.cos(angle) * arcLength;
+ double deltaX = Math.cos(arcAngle) * Math.sin(angle) * arcLength * xScale;
+
+ arcPos = new Vector3f(arcPos);
+ arcPos.z += deltaZ;
+ arcPos.y += deltaY;
+ arcPos.x += deltaX;
+ arcPos.normalise();
+ arc.add(arcPos);
+
+ arcAngle += arcAngleDelta;
+ }
+
+ arcs.add(arc);
+ }
+
+ sphereVBO = new WorldRenderer(8 * 4 * rotationSegments * arcSegments);
+ sphereVBO.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_NORMAL);
+
+ double maxXYRad = 0;
+ for(int angleI = 0; angleI < rotationSegments; angleI++) {
+ for(int segmentI = 0; segmentI <= arcSegments; segmentI++) {
+ List<Vector3f> thisArc = arcs.get(angleI);
+ Vector3f point1 = thisArc.get(segmentI);
+ double rad = Math.sqrt(point1.x * point1.x + point1.y * point1.y);
+ maxXYRad = Math.max(maxXYRad, rad);
+ }
+ }
+
+ for(int angleI = 0; angleI < rotationSegments; angleI++) {
+
+ int nextAngleI = angleI + 1;
+ if(angleI == rotationSegments - 1) {
+ nextAngleI = 0;
+ }
+
+ float v = 0.5f * (angleI) / (rotationSegments);
+ float v2 = 0.5f * (angleI + 1) / (rotationSegments);
+ //if(v2 == 0) v2 = 0.5f;
+
+ List<Vector3f> thisArc = arcs.get(angleI);
+ List<Vector3f> nextArc = arcs.get(nextAngleI);
+
+ for(int segmentI = 1; segmentI <= arcSegments; segmentI++) {
+ Vector3f point1 = thisArc.get(segmentI);
+ Vector3f point2 = thisArc.get(segmentI - 1);
+ Vector3f point3 = nextArc.get(segmentI - 1);
+ Vector3f point4 = nextArc.get(segmentI);
+
+ double u1 = 0.5f * segmentI / arcSegments;
+ double u2 = 0.5f * (segmentI - 1) / arcSegments;
+
+ sphereVBO.pos(point4.x, point4.y, point4.z)
+ .tex(u1, v2).normal(-point4.x, -point4.y, -point4.z).endVertex();
+ sphereVBO.pos(point3.x, point3.y, point3.z)
+ .tex(u2, v2).normal(-point3.x, -point3.y, -point3.z).endVertex();
+ sphereVBO.pos(point2.x, point2.y, point2.z)
+ .tex(u2, v).normal(-point2.x, -point2.y, -point2.z).endVertex();
+ sphereVBO.pos(point1.x, point1.y, point1.z)
+ .tex(u1, v).normal(-point1.x, -point1.y, -point1.z).endVertex();
+ }
+ }
+ }
+
+ String shaderId = "capes/" + shaderName + "/" + shaderName;
+ double mercuryAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 10000f % 1);
+ double mercuryX = Math.sin(mercuryAngle) * 0.3;
+ double mercuryZ = Math.cos(mercuryAngle) * 0.3;
+
+ double earthAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 30000f % 1);
+ double earthSlant = Math.PI * 0.1;
+ double earthX = Math.sin(earthAngle) * Math.cos(earthSlant) * 0.6;
+ double earthY = Math.sin(earthAngle) * Math.sin(earthSlant) * 0.6;
+ double earthZ = Math.cos(earthAngle) * Math.cos(earthSlant) * 0.6;
+
+ float sunDist = Vector3f.sub(point, capeAvgPos, null).lengthSquared();
+ float mercuryDist = Vector3f.sub(new Vector3f(point.x + (float) mercuryX, point.y, point.z + (float) mercuryZ),
+ capeAvgPos, null).lengthSquared();
+ float earthDist = Vector3f.sub(new Vector3f(point.x + (float) earthX, point.y + (float) earthY, point.z + (float) earthZ),
+ capeAvgPos, null).lengthSquared();
+
+ double jupiterAngle = Math.PI * 2 * ((System.currentTimeMillis() - startTime) / 200000f % 1);
+ double jupiterSlant = Math.PI * -0.08;
+ double jupiterX = Math.sin(jupiterAngle) * Math.cos(jupiterSlant) * 1.5;
+ double jupiterY = Math.sin(jupiterAngle) * Math.sin(jupiterSlant) * 1.5;
+ double jupiterZ = Math.cos(jupiterAngle) * Math.cos(jupiterSlant) * 1.5;
+ float jupiterDist = Vector3f.sub(new Vector3f(point.x + (float) jupiterX, point.y + (float) jupiterY, point.z + (float) jupiterZ),
+ capeAvgPos, null).lengthSquared();
+
+ double neptuneX = -Math.sin(earthAngle) * Math.cos(earthSlant);
+ double neptuneY = -Math.sin(earthAngle) * Math.sin(earthSlant);
+ double neptuneZ = -Math.cos(earthAngle) * Math.cos(earthSlant);
+
+ float neptuneDist = Vector3f.sub(new Vector3f(point.x + (float) neptuneX, point.y + (float) neptuneY, point.z + (float) neptuneZ),
+ capeAvgPos, null).lengthSquared();
+
+ TreeMap<Float, Integer> orbitals = new TreeMap<>();
+ orbitals.put(sunDist, 0);
+ orbitals.put(earthDist, 1);
+ orbitals.put(mercuryDist, 2);
+
+ double delta = Minecraft.getMinecraft().getRenderViewEntity().getRotationYawHead() % 360;
+ while(delta < 0) delta += 360;
+
+ double jupDelta = (delta + Math.toDegrees(jupiterAngle)) % 360;
+ while(jupDelta < 0) jupDelta += 360;
+ if(jupDelta > 250 || jupDelta < 110) orbitals.put(jupiterDist, 3);
+
+ double nepDelta = (delta + Math.toDegrees(-earthAngle)) % 360;
+ while(nepDelta < 0) nepDelta += 360;
+ if(nepDelta > 250 || nepDelta < 110) orbitals.put(neptuneDist, 4);
+
+ GlStateManager.disableDepth();
+ GlStateManager.enableCull();
+
+ for(int planetId : orbitals.descendingMap().values()) {
+ GlStateManager.pushMatrix();
+ switch(planetId) {
+ case 0: {
+ GlStateManager.translate(point.x, point.y, point.z);
+ GlStateManager.scale(0.2f, 0.2f, 0.2f);
+ break;
+ }
+ case 1: {
+ Vector3f sunVec = new Vector3f((float) earthX, (float) earthY, (float) earthZ);
+ ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec);
+ GlStateManager.translate(point.x + earthX, point.y + earthY, point.z + earthZ);
+ GlStateManager.scale(0.1f, 0.1f, 0.1f);
+ break;
+ }
+ case 2: {
+ Vector3f sunVec = new Vector3f((float) mercuryX, 0, (float) mercuryZ);
+ ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec);
+ GlStateManager.translate(point.x + mercuryX, point.y, point.z + mercuryZ);
+ GlStateManager.scale(0.05f, 0.05f, 0.05f);
+ break;
+ }
+ case 3: {
+ Vector3f sunVec = new Vector3f((float) jupiterX, (float) jupiterY, (float) jupiterZ);
+ ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec);
+ GlStateManager.translate(point.x + jupiterX, point.y + jupiterY, point.z + jupiterZ);
+ GlStateManager.scale(0.3f, 0.3f, 0.3f);
+ break;
+ }
+ case 4: {
+ Vector3f sunVec = new Vector3f((float) neptuneX, (float) neptuneY, (float) neptuneZ);
+ ShaderManager.getInstance().loadData(shaderId, "sunVec", sunVec);
+ GlStateManager.translate(point.x + neptuneX, point.y + neptuneY, point.z + neptuneZ);
+ GlStateManager.scale(0.15f, 0.15f, 0.15f);
+ break;
+ }
+ }
+ ShaderManager.getInstance().loadData(shaderId, "planetType", planetId);
+ renderVBO(sphereVBO);
+ GlStateManager.popMatrix();
+ }
+
+
+ GlStateManager.disableCull();
+ GlStateManager.enableDepth();
+
+ GL11.glDisable(GL11.GL_STENCIL_TEST);
+ } else if(capeName.equalsIgnoreCase("parallax")) {
+ renderBackAndDoFrontStencil();
+
+ Vector3f pointNorm = avgNormal();
+ pointNorm.scale(-0.2f / pointNorm.length());
+ Vector3f negPointNorm = new Vector3f(pointNorm);
+ negPointNorm.scale(-1);
+ //pointNorm.scale(1 - pointNorm.y/1.3f);
+ Vector3f point = Vector3f.add(avgRenderPosition(), pointNorm, null);
+ Vector3f fixedPoint = Vector3f.add(avgFixedRenderPosition(), pointNorm, null);
+
+ Vector3f up = Vector3f.sub(fixedPoint, point, null);
+ float halfUp = up.length();
+
+ Vector3f down = new Vector3f(up);
+ down.scale(-1);
+
+ Vector3f left = Vector3f.cross(up, pointNorm, null);
+ left.scale(halfUp * 522f / 341f / left.length());
+ Vector3f right = new Vector3f(left);
+ right.scale(-1);
+
+ Vector3f point1 = getPoint(point, left);
+ Vector3f point2 = getPoint(point, left, down, down);
+ Vector3f point3 = getPoint(point, right, down, down);
+ Vector3f point4 = getPoint(point, right);
+
+ Vector3f point2Edge = getPoint(point2, negPointNorm, negPointNorm);
+ Vector3f point3Edge = getPoint(point3, negPointNorm, negPointNorm);
+
+ GlStateManager.disableDepth();
+ GlStateManager.disableCull();
+
+ GlStateManager.color(1, 1, 1, 1);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
+
+ worldrenderer.pos(point1.x, point1.y, point1.z)
+ .tex(0, 943 / 1024f).endVertex();
+ worldrenderer.pos(point2.x, point2.y, point2.z)
+ .tex(280 / 1024f, 943 / 1024f).endVertex();
+ worldrenderer.pos(point3.x, point3.y, point3.z)
+ .tex(280 / 1024f, 421 / 1024f).endVertex();
+ worldrenderer.pos(point4.x, point4.y, point4.z)
+ .tex(0, 421 / 1024f).endVertex();
+
+ tessellator.draw();
+
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
+
+ worldrenderer.pos(point2.x, point2.y, point2.z)
+ .tex(280 / 1024f, 943 / 1024f).endVertex();
+ worldrenderer.pos(point2Edge.x, point2Edge.y, point2Edge.z)
+ .tex(341 / 1024f, 943 / 1024f).endVertex();
+ worldrenderer.pos(point3Edge.x, point3Edge.y, point3Edge.z)
+ .tex(341 / 1024f, 421 / 1024f).endVertex();
+ worldrenderer.pos(point3.x, point3.y, point3.z)
+ .tex(280 / 1024f, 421 / 1024f).endVertex();
+
+ tessellator.draw();
+
+
+ GlStateManager.disableCull();
+ GlStateManager.enableDepth();
+
+ GL11.glDisable(GL11.GL_STENCIL_TEST);
+ } else if(capeName.equalsIgnoreCase("tunnel")) {
+ renderBackAndDoFrontStencil();
+
+ Vector3f pointNorm = avgNormal();
+
+ pointNorm.scale(0.7f / pointNorm.length());
+ pointNorm.scale(1 - pointNorm.y / 1.3f);
+ Vector3f point = Vector3f.sub(avgRenderPosition(), pointNorm, null);
+
+ List<CapeNode> edgeNodes = new ArrayList<>();
+ List<Vector2f> edgeCoords = new ArrayList<>();
+
+ //Left edge
+ for(int y = 0; y < VERT_NODES; y++) {
+ edgeNodes.add(nodes[y * HORZ_NODES]);
+ edgeCoords.add(new Vector2f(0, (float) y / (VERT_NODES - 1)));
+ }
+ edgeNodes.add(null);
+ edgeCoords.add(null);
+ //Bottom edge
+ int bottomIndex = VERT_NODES - 1;
+ int botSize = HORZ_NODES;
+ for(int x = 0; x < botSize; x++) {
+ edgeNodes.add(getNode(x, bottomIndex));
+ edgeCoords.add(new Vector2f((float) x / (botSize - 1), 1));
+ }
+ edgeNodes.add(null);
+ edgeCoords.add(null);
+ //Right edge
+ for(int y = VERT_NODES - 1; y >= 0; y--) {
+ edgeNodes.add(getNode(HORZ_NODES - 1, y));
+ edgeCoords.add(new Vector2f(1, (float) y / VERT_NODES));
+ }
+ edgeNodes.add(null);
+ edgeCoords.add(null);
+ //Top edge
+ int topSize = HORZ_NODES;
+ for(int x = topSize - 1; x >= 0; x--) {
+ edgeNodes.add(getNode(x, 0));
+ edgeCoords.add(new Vector2f((float) x / (topSize - 1), 0));
+ }
+
+ GlStateManager.disableDepth();
+ GlStateManager.enableCull();
+ CapeNode last = null;
+ for(int i = 0; i < edgeNodes.size(); i++) {
+ CapeNode node = edgeNodes.get(i);
+ if(last != null && node != null) {
+ Vector2f lastCoord = edgeCoords.get(i - 1);
+ Vector2f coord = edgeCoords.get(i);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX_NORMAL);
+
+ Vector3f lastNodeNorm = last.normal();
+ worldrenderer.pos(last.renderPosition.x + lastNodeNorm.x * 0.05f, last.renderPosition.y + lastNodeNorm.y * 0.05f, last.renderPosition.z + lastNodeNorm.z * 0.05f)
+ .tex(lastCoord.x * 300f / 1024f, lastCoord.y * 420f / 1024f)
+ .normal(-lastNodeNorm.x, -lastNodeNorm.y, -lastNodeNorm.z).endVertex();
+
+ Vector3f nodeNorm = node.normal();
+ worldrenderer.pos(node.renderPosition.x + nodeNorm.x * 0.05f, node.renderPosition.y + nodeNorm.y * 0.05f, node.renderPosition.z + nodeNorm.z * 0.05f)
+ .tex(coord.x * 300f / 1024f, coord.y * 420f / 1024f)
+ .normal(-nodeNorm.x, -nodeNorm.y, -nodeNorm.z).endVertex();
+
+ worldrenderer.pos(point.x, point.y, point.z)
+ .tex(150f / 1024f, 210f / 1024f)
+ .normal(-pointNorm.x, -pointNorm.y, -pointNorm.z).endVertex();
+
+ tessellator.draw();
+ }
+ last = node;
+ }
+ GlStateManager.disableCull();
+ GlStateManager.enableDepth();
+
+ GL11.glDisable(GL11.GL_STENCIL_TEST);
+ } else {
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ nodes[x + y * HORZ_NODES].renderNode();
+ }
+ }
+ }
+ }
+
private void renderCape(EntityPlayer player, float partialRenderTick) {
ensureCapeNodesCreated(player);
@@ -781,9 +1238,9 @@ public class NEUCape {
if(delta.lengthSquared() > 9) {
updateFixedCapeNodes(player);
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
if(!node.fixed) {
Vector3f.add(node.renderPosition, delta, node.renderPosition);
node.position.set(node.renderPosition);
@@ -794,17 +1251,13 @@ public class NEUCape {
}
}
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).renderNode();
- }
- }
+ renderNodes();
return;
}
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
+ for(int y = 0; y < VERT_NODES; y++) {
+ for(int x = 0; x < HORZ_NODES; x++) {
+ CapeNode node = nodes[x + y * HORZ_NODES];
node.resetNormal();
@@ -821,31 +1274,31 @@ public class NEUCape {
if(fps < 50) {
length = 2;
} else if(fps < 100) {
- length = 2 + (int)((fps-50)/50f*3);
+ length = 2 + (int) ((fps - 50) / 50f * 3);
}
- if(node.oldRenderPosition[length-1] == null) {
+ if(node.oldRenderPosition[length - 1] == null) {
Arrays.fill(node.oldRenderPosition, Vector3f.sub(newPosition, avgPositionFixed, null));
node.renderPosition = newPosition;
} else {
Vector3f accum = new Vector3f();
- for(int i=0; i<length; i++) {
+ for(int i = 0; i < length; i++) {
Vector3f.add(accum, node.oldRenderPosition[i], accum);
Vector3f.add(accum, avgPositionFixed, accum);
}
- accum.scale(1/(float)(length));
+ accum.scale(1 / (float) (length));
- float blendFactor = 0.5f+0.3f*y/(float)(nodes.size()-1); //0.5/0.5 -> 0.8/0.2 //0-1
+ float blendFactor = 0.5f + 0.3f * y / (float) (VERT_NODES - 1); //0.5/0.5 -> 0.8/0.2 //0-1
accum.scale(blendFactor);
- newPosition.scale(1-blendFactor);
+ newPosition.scale(1 - blendFactor);
Vector3f.add(accum, newPosition, accum);
node.renderPosition = accum;
}
if(!Minecraft.getMinecraft().isGamePaused()) {
- for(int i=node.oldRenderPosition.length-1; i>=0; i--) {
+ for(int i = node.oldRenderPosition.length - 1; i >= 0; i--) {
if(i > 0) {
- node.oldRenderPosition[i] = node.oldRenderPosition[i-1];
+ node.oldRenderPosition[i] = node.oldRenderPosition[i - 1];
} else {
node.oldRenderPosition[i] = Vector3f.sub(node.renderPosition, avgPositionFixed, null);
}
@@ -853,11 +1306,7 @@ public class NEUCape {
}
}
}
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).renderNode();
- }
- }
+ renderNodes();
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
index 9981e6f9..df7069d4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
@@ -19,11 +19,15 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.SystemUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
@@ -43,6 +47,8 @@ public class HTMLInfoPane extends TextInfoPane {
private int imageHeight = 0;
private int imageWidth = 0;
+ private static boolean hasAttemptedDownload = false;
+
/**
* Creates a wiki model and sets the configuration to work with hypixel-skyblock wikia.
*/
@@ -140,6 +146,9 @@ public class HTMLInfoPane extends TextInfoPane {
return str.replace(" ", "\\ ");
}
+ private static final ExecutorService wkDownloadES = Executors.newSingleThreadExecutor();
+ private static final ExecutorService rendererES = Executors.newCachedThreadPool();
+
/**
* Uses the wkhtmltoimage command-line tool to generate an image from the HTML code. This
* generation is done asynchronously as sometimes it can take up to 10 seconds for more
@@ -149,8 +158,68 @@ public class HTMLInfoPane extends TextInfoPane {
super(overlay, manager, name, "");
this.title = name;
+ String osId;
+ if(SystemUtils.IS_OS_WINDOWS) {
+ osId = "win";
+ } else if(SystemUtils.IS_OS_MAC) {
+ osId = "mac";
+ } else if(SystemUtils.IS_OS_LINUX) {
+ osId = "linux";
+ } else {
+ text = EnumChatFormatting.RED+"Unsupported operating system.";
+ return;
+ }
+
File cssFile = new File(manager.configLocation, "wikia.css");
- File wkHtmlToImage = new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage");
+ File wkHtmlToImage = new File(manager.configLocation, "wkhtmltox-"+osId+"/bin/wkhtmltoimage");
+
+ //Use old binary folder
+ if(new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage").exists() && SystemUtils.IS_OS_WINDOWS) {
+ wkHtmlToImage = new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage");
+ }
+
+ Runtime runtime = Runtime.getRuntime();
+ String[] chmodCommand = new String[]{ "chmod", "-R", "777", new File(manager.configLocation, "wkhtmltox-"+osId).getAbsolutePath() };
+ try {
+ Process p = runtime.exec(chmodCommand);
+ p.waitFor();
+ } catch(IOException | InterruptedException e) {}
+
+ if(!wkHtmlToImage.exists()) {
+ if(hasAttemptedDownload) {
+ text = EnumChatFormatting.RED+"Downloading web renderer failed? Or still downloading? Not sure what to do";
+ return;
+ } else {
+ hasAttemptedDownload = true;
+ Utils.recursiveDelete(new File(manager.configLocation, "wkhtmltox-"+osId));
+ wkDownloadES.submit(() -> {
+ try {
+ File itemsZip = new File(manager.configLocation, "wkhtmltox-"+osId+".zip");
+ if(!itemsZip.exists()) {
+ URL url = new URL("https://moulberry.codes/wkhtmltox/wkhtmltox-"+osId+".zip");
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setConnectTimeout(15000);
+ urlConnection.setReadTimeout(60000);
+
+ FileUtils.copyInputStreamToFile(urlConnection.getInputStream(), itemsZip);
+ }
+
+ try(InputStream is = new FileInputStream(itemsZip)) {
+ manager.unzip(is, manager.configLocation);
+ }
+
+ itemsZip.delete();
+ itemsZip.deleteOnExit();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+
+ text = EnumChatFormatting.YELLOW+"Downloading web renderer... try again soon";
+ return;
+ }
+ }
+
File input = new File(manager.configLocation, "tmp/input.html");
String outputFileName = filename.replaceAll("(?i)\\u00A7.", "")
.replaceAll("[^a-zA-Z0-9_\\-]", "_");
@@ -179,7 +248,7 @@ public class HTMLInfoPane extends TextInfoPane {
} else {
html = "<div id=\"mw-content-text\" lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr mw-content-text\">"+html+"</div>";
html = "<div id=\"WikiaArticle\" class=\"WikiaArticle\">"+html+"</div>";
- html = "<link rel=\"stylesheet\" href=\"file:///"+cssFile.getAbsolutePath()+"\">\n"+html;
+ html = "<link rel=\"stylesheet\" href=\"file:///"+cssFile.getAbsolutePath().replaceAll("^/", "")+"\">\n"+html;
try(PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(input), StandardCharsets.UTF_8)), false)) {
@@ -187,16 +256,12 @@ public class HTMLInfoPane extends TextInfoPane {
out.println(encodeNonAscii(html));
} catch(IOException e) {}
-
- ExecutorService ste = Executors.newSingleThreadExecutor();
try {
text = EnumChatFormatting.GRAY+"Rendering webpage (" + name + EnumChatFormatting.RESET+
EnumChatFormatting.GRAY+"), please wait...";
- Runtime runtime = Runtime.getRuntime();
-
String[] wkCommand = new String[]{ wkHtmlToImage.getAbsolutePath(), "--width", ""+IMAGE_WIDTH*ZOOM_FACTOR,
- "--transparent", "--zoom", ""+ZOOM_FACTOR, input.getAbsolutePath(), output.getAbsolutePath()};
+ "--transparent", "--allow", manager.configLocation.getAbsolutePath(), "--zoom", ""+ZOOM_FACTOR, input.getAbsolutePath(), output.getAbsolutePath()};
Process p = runtime.exec(wkCommand);
/*Process p = runtime.exec(spaceEscape(wkHtmlToImage.getAbsolutePath()) + " --width "+
IMAGE_WIDTH*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR + " " + spaceEscape(input.getAbsolutePath()) +
@@ -207,7 +272,7 @@ public class HTMLInfoPane extends TextInfoPane {
/*Process p2 = runtime.exec("\""+wkHtmlToImage.getAbsolutePath() + "\" --width "+
(IMAGE_WIDTH+EXT_WIDTH)*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR+" \"" + input.getAbsolutePath() +
"\" \"" + outputExt.getAbsolutePath() + "\"");*/
- ste.submit(() -> {
+ rendererES.submit(() -> {
try {
if(p.waitFor(15, TimeUnit.SECONDS)) {
//if(p2.waitFor(5, TimeUnit.SECONDS)) {
@@ -260,8 +325,6 @@ public class HTMLInfoPane extends TextInfoPane {
} catch(IOException e) {
e.printStackTrace();
text = EnumChatFormatting.RED+"Failed to exec webpage renderer.";
- } finally {
- ste.shutdown();
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
index 7e073bbd..20915503 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
@@ -10,6 +10,7 @@ import net.minecraft.block.BlockPackedIce;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.*;
@@ -408,6 +409,9 @@ public class CustomItemEffects {
cropBlocksZapper.add(Blocks.melon_stem);
cropBlocksZapper.add(Blocks.cactus);
cropBlocksZapper.add(Blocks.reeds);
+ cropBlocksZapper.add(Blocks.nether_wart);
+ cropBlocksZapper.add(Blocks.tallgrass);
+ cropBlocksZapper.add(Blocks.double_plant);
otherBannedBlocksZapper.add(Blocks.farmland);
}
@@ -436,6 +440,7 @@ public class CustomItemEffects {
zapperDirty = false;
zapperBlocks.clear();
+
LinkedList<BlockPos> returnablePositions = new LinkedList<>();
BlockPos pos = event.target.getBlockPos();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java
index eed1ec60..26e87ae9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java
@@ -311,8 +311,7 @@ public class EnchantingSolvers {
if(chronomatronReplayIndex < chronomatronOrder.size()) {
String chronomatronCurrent = chronomatronOrder.get(chronomatronReplayIndex);
- if(!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.preventMisclicks ||
- chronomatronCurrent.equals(displayName)) {
+ if(true) {
chronomatronReplayIndex++;
Minecraft.getMinecraft().playerController.windowClick(windowId, slotId,
2, mode, Minecraft.getMinecraft().thePlayer);
@@ -334,9 +333,7 @@ public class EnchantingSolvers {
return true;
}
long currentTime = System.currentTimeMillis();
- if(currentTime - millisLastClick > 150 &&
- (!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.preventMisclicks ||
- current.containerIndex == slotId)) {
+ if(currentTime - millisLastClick > 150) {
ultrasequencerReplayIndex++;
Minecraft.getMinecraft().playerController.windowClick(windowId, slotId,
2, mode, Minecraft.getMinecraft().thePlayer);
@@ -354,7 +351,9 @@ public class EnchantingSolvers {
return false;
}
- public static void processInventoryContents() {
+ public static void processInventoryContents(boolean fromTick) {
+ if(currentSolver != SolverType.CHRONOMATRON && !fromTick) return;
+
if(!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enableEnchantingSolvers) {
return;
}
@@ -536,7 +535,7 @@ public class EnchantingSolvers {
return;
}
- processInventoryContents();
+ processInventoryContents(true);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
index d01a173f..6f706b5c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
@@ -104,26 +104,6 @@ public class MiningStuff {
}
}
- public static void tick() {
- if(SBInfo.getInstance().getLocation() == null) return;
- if(!SBInfo.getInstance().getLocation().equals("mining_3")) return;
- if(Minecraft.getMinecraft().theWorld == null) return;
-
- for(Entity entity : Minecraft.getMinecraft().theWorld.loadedEntityList) {
- if(entity instanceof EntityCreeper) {
- EntityCreeper creeper = (EntityCreeper) entity;
- if(creeper.isInvisible() && creeper.getPowered()) {
-
- BlockPos below = creeper.getPosition().down();
- IBlockState state = Minecraft.getMinecraft().theWorld.getBlockState(below);
- if(state != null && state.getBlock() == Blocks.stained_glass) {
- creeper.setInvisible(!NotEnoughUpdates.INSTANCE.config.mining.revealMistCreepers);
- }
- }
- }
- }
- }
-
@SubscribeEvent
public void renderWorldLast(RenderWorldLastEvent event) {
if(overlayLoc == null) return;
@@ -186,19 +166,4 @@ public class MiningStuff {
}
}
- public static boolean blockClicked(BlockPos loc) {
- if(loc.equals(overlayLoc)) {
- overlayLoc = null;
- }
- IBlockState state = Minecraft.getMinecraft().theWorld.getBlockState(loc);
- if(NotEnoughUpdates.INSTANCE.config.mining.dontMineStone &&
- state != null && SBInfo.getInstance().getLocation() != null &&
- SBInfo.getInstance().getLocation().startsWith("mining_") &&
- (state.getBlock() == Blocks.stone && state.getValue(BlockStone.VARIANT) == BlockStone.EnumType.STONE ||
- state.getBlock() == Blocks.cobblestone)) {
- return true;
- }
- return false;
- }
-
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java
new file mode 100644
index 00000000..7e297c58
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java
@@ -0,0 +1,234 @@
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.renderer.vertex.VertexFormat;
+import net.minecraft.client.renderer.vertex.VertexFormatElement;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.BlockPos;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.nio.ByteBuffer;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class NullzeeSphere {
+
+ public static boolean enabled = false;
+ public static float size = 20;
+ public static BlockPos centerPos = new BlockPos(0, 0, 0);
+
+ public static ReverseWorldRenderer overlayVBO = null;
+
+ public ReverseWorldRenderer getOverlayVBO() {
+ if(overlayVBO != null) return overlayVBO;
+
+ EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
+ if(p == null) return null;
+
+ //per vertex = 6
+ //per size = 4
+ //per block = 8
+ //total per block = 196
+
+ Set<BlockPos> circleOffsets = getCircleOffsets(size);
+
+ ReverseWorldRenderer worldRenderer = new ReverseWorldRenderer(196*circleOffsets.size());
+ worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
+
+ String col = SpecialColour.special(0, 180, 0xffff9900);
+ for(BlockPos offset : circleOffsets) {
+ BlockPos overlayPos = new BlockPos(offset.getX(), offset.getY(), offset.getZ());
+
+ AxisAlignedBB bb = new AxisAlignedBB(
+ overlayPos.getX(),
+ overlayPos.getY(),
+ overlayPos.getZ(),
+ overlayPos.getX()+1,
+ overlayPos.getY()+1,
+ overlayPos.getZ()+1
+ ).expand(0.001f, 0.001f, 0.001f);
+ uploadFilledBoundingBox(bb, 1f, col, worldRenderer);
+ }
+
+ overlayVBO = worldRenderer;
+ return overlayVBO;
+ }
+
+ public Set<BlockPos> getCircleOffsets(float radius) {
+ Set<BlockPos> circleOffsets = new HashSet<>();
+
+ int radiusI = (int)Math.ceil(radius)+1;
+ for(int x=-radiusI; x<=radiusI; x++) {
+ for(int y=-radiusI; y<=radiusI; y++) {
+ for(int z=-radiusI; z<=radiusI; z++) {
+ float distSq = x*x + y*y + z*z;
+ if(distSq >= (radius-0.5)*(radius-0.5) && distSq <= (radius+0.5)*(radius+0.5)) {
+ circleOffsets.add(new BlockPos(x, y, z));
+ }
+ }
+ }
+ }
+
+ return circleOffsets;
+ }
+
+ long lastUpdate = 0;
+
+ private static double posLastUpdateX;
+ private static double posLastUpdateY;
+ private static double posLastUpdateZ;
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if(!enabled) return;
+
+ EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
+ if(p == null) return;
+
+ if(event.phase == TickEvent.Phase.START) {
+ double dX = p.posX - posLastUpdateX;
+ double dY = p.posY - posLastUpdateY;
+ double dZ = p.posZ - posLastUpdateZ;
+
+ if(dX*dX + dY*dY + dZ*dZ < 1) {
+ return;
+ }
+
+ posLastUpdateX = p.posX;
+ posLastUpdateY = p.posY;
+ posLastUpdateZ = p.posZ;
+
+ long currentTime = System.currentTimeMillis();
+ if(currentTime - lastUpdate < 250) {
+ return;
+ }
+ lastUpdate = currentTime;
+
+ ReverseWorldRenderer worldRenderer = getOverlayVBO();
+ if(worldRenderer != null) {
+ worldRenderer.setTranslation(0, 0,0 );
+ worldRenderer.sortVertexData(
+ (float)p.posX-centerPos.getX(),
+ (float)p.posY-centerPos.getY(),
+ (float)p.posZ-centerPos.getZ());
+
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderLast(RenderWorldLastEvent event) {
+ if(!enabled) return;
+
+ Entity viewer = Minecraft.getMinecraft().getRenderViewEntity();
+ double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * event.partialTicks;
+ double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * event.partialTicks;
+ double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * event.partialTicks;
+
+ GlStateManager.enableBlend();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.disableTexture2D();
+
+ GlStateManager.translate(-viewerX, -viewerY, -viewerZ);
+
+ GL11.glPolygonOffset(5, 5);
+ ReverseWorldRenderer worldRenderer = getOverlayVBO();
+ if(worldRenderer != null && worldRenderer.getVertexCount() > 0) {
+ GlStateManager.translate(centerPos.getX(), centerPos.getY(), centerPos.getZ());
+
+ VertexFormat vertexformat = worldRenderer.getVertexFormat();
+ int stride = vertexformat.getNextOffset();
+ ByteBuffer bytebuffer = worldRenderer.getByteBuffer();
+ List<VertexFormatElement> list = vertexformat.getElements();
+
+ for (int index = 0; index < list.size(); index++) {
+ VertexFormatElement vertexformatelement = list.get(index);
+ vertexformatelement.getUsage().preDraw(vertexformat, index, stride, bytebuffer);
+ }
+
+ GL11.glDrawArrays(worldRenderer.getDrawMode(), 0, worldRenderer.getVertexCount());
+
+ for (int index = 0; index < list.size(); index++) {
+ VertexFormatElement vertexformatelement = list.get(index);
+ vertexformatelement.getUsage().postDraw(vertexformat, index, stride, bytebuffer);
+ }
+
+ GlStateManager.translate(-centerPos.getX(), -centerPos.getY(), -centerPos.getZ());
+ }
+ GL11.glPolygonOffset(0, 0);
+
+ GlStateManager.translate(viewerX, viewerY, viewerZ);
+
+ GlStateManager.enableTexture2D();
+ }
+
+ public static void uploadFilledBoundingBox(AxisAlignedBB p_181561_0_, float alpha, String special, ReverseWorldRenderer worldrenderer) {
+ Color c = new Color(SpecialColour.specialToChromaRGB(special), true);
+
+ //vertical
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ)
+ .color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha).endVertex();
+
+ //x
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha).endVertex();
+
+ //z
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ)
+ .color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha).endVertex();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
index 09ae3071..f759ba7d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
@@ -48,7 +48,7 @@ public class PetInfoOverlay extends TextOverlay {
private static final Pattern XP_BOOST_PATTERN = Pattern.compile("PET_ITEM_(COMBAT|FISHING|MINING|FORAGING|ALL|FARMING)_(SKILL|SKILLS)_BOOST_(COMMON|UNCOMMON|RARE|EPIC)");
private static final Pattern PET_CONTAINER_PAGE = Pattern.compile("\\((\\d)/(\\d)\\) Pets");
private static final Pattern PET_NAME_PATTERN = Pattern.compile("\u00a77\\[Lvl \\d+] \u00a7(.+)");
- private static final Pattern XP_LINE_PATTERN = Pattern.compile("-------------------- (\\d+(?:,\\d+)*(?:\\.\\d+)?)/(\\d+(?:\\.\\d+)?[b|m|k]?)");
+ private static final Pattern XP_LINE_PATTERN = Pattern.compile("-------------------- (\\d+(?:,\\d+)*(?:\\.\\d+)?)/(\\d+(?:\\.\\d+)?[B|M|k]?)");
public PetInfoOverlay(Position position, Supplier<List<String>> dummyStrings, Supplier<TextOverlayStyle> styleSupplier) {
super(position, dummyStrings, styleSupplier);
@@ -95,6 +95,7 @@ public class PetInfoOverlay extends TextOverlay {
private static HashMap<Integer, Pet> petMap = new HashMap<>();
private static int selectedPet = -1;
+ private static int selectedPet2 = -1;
private static long lastPetSelect = -1;
//public static Pet currentPet = null;
//public static HashMap<String, Set<Pet>> petList = new HashMap<>();
@@ -103,23 +104,40 @@ public class PetInfoOverlay extends TextOverlay {
public static float beastMultiplier = 0;
public static boolean setActivePet = false;
- private long lastUpdate = 0;
- private float levelXpLast = 0;
+ private static long lastUpdate = 0;
+ private static float levelXpLast = 0;
- private LinkedList<Float> xpGainQueue = new LinkedList<>();
- private float xpGainHourLast = -1;
- private float xpGainHour = -1;
+ private static LinkedList<Float> xpGainQueue = new LinkedList<>();
+ private static float xpGainHourLast = -1;
+ private static float xpGainHour = -1;
+
+ private static float xpGainHourSecondPet = -1;
private int xpAddTimer = 0;
public static void clearPet() {
selectedPet = -1;
+ selectedPet2 = -1;
+ }
+
+ public static void setCurrentPet(int index) {
+ selectedPet2 = selectedPet;
+ xpGainHourSecondPet = xpGainHour;
+ xpGainHourLast = xpGainHour;
+ xpGainQueue.clear();
+ selectedPet = index;
}
public static Pet getCurrentPet() {
return petMap.get(selectedPet);
}
+ public static Pet getCurrentPet2() {
+ if(!NotEnoughUpdates.INSTANCE.config.petOverlay.dualPets) return null;
+ if(selectedPet == selectedPet2) return null;
+ return petMap.get(selectedPet2);
+ }
+
public float getLevelPercent() {
DecimalFormat df = new DecimalFormat("#.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
Pet pet = getCurrentPet();
@@ -306,57 +324,59 @@ public class PetInfoOverlay extends TextOverlay {
return interp;
}
- @Override
- public void updateFrequent() {
- Pet currentPet = getCurrentPet();
- if(!NotEnoughUpdates.INSTANCE.config.petOverlay.enablePetInfo || currentPet == null) {
- overlayStrings = null;
+ private List<String> createStringsForPet(Pet currentPet, boolean secondPet) {
+ float levelXp = currentPet.petLevel.levelXp;
+ if(!secondPet) levelXp = interp(currentPet.petLevel.levelXp, levelXpLast);
+ if(levelXp < 0) levelXp = 0;
+
+ String petName = EnumChatFormatting.GREEN + "[Lvl " + (int) currentPet.petLevel.level + "] " + currentPet.rarity.chatFormatting +
+ WordUtils.capitalizeFully(currentPet.petType.replace("_", " "));
+
+ String lvlStringShort = EnumChatFormatting.AQUA + "" + roundFloat(levelXp) + "/" +
+ roundFloat(currentPet.petLevel.currentLevelRequirement)
+ + EnumChatFormatting.YELLOW + " (" + getLevelPercent() + "%)";
+
+ String lvlString = EnumChatFormatting.AQUA + "" + Utils.shortNumberFormat(levelXp, 0) + "/" +
+ Utils.shortNumberFormat(currentPet.petLevel.currentLevelRequirement, 0)
+ + EnumChatFormatting.YELLOW + " (" + getLevelPercent() + "%)";
+
+ float xpGain;
+ if(!secondPet) {
+ xpGain = interp(xpGainHour, xpGainHourLast);
} else {
- float levelXp = interp(currentPet.petLevel.levelXp, levelXpLast);
- if(levelXp < 0) levelXp = 0;
-
- String petName = EnumChatFormatting.GREEN + "[Lvl " + (int) currentPet.petLevel.level + "] " + currentPet.rarity.chatFormatting +
- WordUtils.capitalizeFully(currentPet.petType.replace("_", " "));
-
- String lvlStringShort = EnumChatFormatting.AQUA + "" + roundFloat(levelXp) + "/" +
- roundFloat(currentPet.petLevel.currentLevelRequirement)
- + EnumChatFormatting.YELLOW + " (" + getLevelPercent() + "%)";
-
- String lvlString = EnumChatFormatting.AQUA + "" + Utils.shortNumberFormat(levelXp, 0) + "/" +
- Utils.shortNumberFormat(currentPet.petLevel.currentLevelRequirement, 0)
- + EnumChatFormatting.YELLOW + " (" + getLevelPercent() + "%)";
-
- float xpGain = interp(xpGainHour, xpGainHourLast);
- if(xpGain < 0) xpGain = 0;
- String xpGainString = EnumChatFormatting.AQUA + "XP/h: " +
- EnumChatFormatting.YELLOW + roundFloat(xpGain);
- if(xpGain > 0 && xpGainHour == xpGainHourLast) xpGainString += EnumChatFormatting.RED + " (PAUSED)";
-
- String totalXpString = EnumChatFormatting.AQUA + "Total XP: " + EnumChatFormatting.YELLOW + roundFloat(currentPet.petLevel.totalXp);
-
- String petItemStr = EnumChatFormatting.AQUA+ "Held Item: " + EnumChatFormatting.RED + "None";
- if(currentPet.petItem != null) {
- JsonObject json = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(currentPet.petItem);
- if(json != null) {
- String name = NotEnoughUpdates.INSTANCE.manager.jsonToStack(json).getDisplayName();
- petItemStr = EnumChatFormatting.AQUA + "Held Item: " + name;
- }
+ xpGain = xpGainHourSecondPet;
+ }
+ if(xpGain < 0) xpGain = 0;
+ String xpGainString = EnumChatFormatting.AQUA + "XP/h: " +
+ EnumChatFormatting.YELLOW + roundFloat(xpGain);
+ if(xpGain > 0 && xpGainHour == xpGainHourLast) xpGainString += EnumChatFormatting.RED + " (PAUSED)";
+
+ String totalXpString = EnumChatFormatting.AQUA + "Total XP: " + EnumChatFormatting.YELLOW + roundFloat(currentPet.petLevel.totalXp);
+
+ String petItemStr = EnumChatFormatting.AQUA+ "Held Item: " + EnumChatFormatting.RED + "None";
+ if(currentPet.petItem != null) {
+ JsonObject json = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(currentPet.petItem);
+ if(json != null) {
+ String name = NotEnoughUpdates.INSTANCE.manager.jsonToStack(json).getDisplayName();
+ petItemStr = EnumChatFormatting.AQUA + "Held Item: " + name;
}
+ }
- String etaStr = null;
- String etaMaxStr = null;
- if(currentPet.petLevel.level < 100) {
- float remaining = currentPet.petLevel.currentLevelRequirement - currentPet.petLevel.levelXp;
- if(remaining > 0) {
- if(xpGain < 1000) {
- etaStr = EnumChatFormatting.AQUA+"Until L"+(int)(currentPet.petLevel.level+1)+": " +
- EnumChatFormatting.YELLOW+"N/A";
- } else {
- etaStr = EnumChatFormatting.AQUA+"Until L"+(int)(currentPet.petLevel.level+1)+": " +
- EnumChatFormatting.YELLOW + Utils.prettyTime((long)(remaining)*1000*60*60/(long)xpGain);
- }
+ String etaStr = null;
+ String etaMaxStr = null;
+ if(currentPet.petLevel.level < 100) {
+ float remaining = currentPet.petLevel.currentLevelRequirement - currentPet.petLevel.levelXp;
+ if(remaining > 0) {
+ if(xpGain < 1000) {
+ etaStr = EnumChatFormatting.AQUA+"Until L"+(int)(currentPet.petLevel.level+1)+": " +
+ EnumChatFormatting.YELLOW+"N/A";
+ } else {
+ etaStr = EnumChatFormatting.AQUA+"Until L"+(int)(currentPet.petLevel.level+1)+": " +
+ EnumChatFormatting.YELLOW + Utils.prettyTime((long)(remaining)*1000*60*60/(long)xpGain);
}
+ }
+ if(currentPet.petLevel.level < 99 || !NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.contains(6)) {
float remainingMax = currentPet.petLevel.maxXP - currentPet.petLevel.totalXp;
if(remaining > 0) {
if(xpGain < 1000) {
@@ -368,28 +388,48 @@ public class PetInfoOverlay extends TextOverlay {
}
}
}
+ }
+
+ List<String> strings = new ArrayList<>();
+
+ for(int index : NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText) {
+ switch(index) {
+ case 0:
+ strings.add(petName); break;
+ case 1:
+ strings.add(lvlStringShort); break;
+ case 2:
+ strings.add(lvlString); break;
+ case 3:
+ strings.add(xpGainString); break;
+ case 4:
+ strings.add(totalXpString); break;
+ case 5:
+ strings.add(petItemStr); break;
+ case 6:
+ if(etaStr != null) strings.add(etaStr); break;
+ case 7:
+ if(etaMaxStr != null) strings.add(etaMaxStr); break;
+ }
+ }
+ return strings;
+ }
+
+ @Override
+ public void updateFrequent() {
+ Pet currentPet = getCurrentPet();
+ if(!NotEnoughUpdates.INSTANCE.config.petOverlay.enablePetInfo || currentPet == null) {
+ overlayStrings = null;
+ } else {
overlayStrings = new ArrayList<>();
- for(int index : NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText) {
- switch(index) {
- case 0:
- overlayStrings.add(petName); break;
- case 1:
- overlayStrings.add(lvlStringShort); break;
- case 2:
- overlayStrings.add(lvlString); break;
- case 3:
- overlayStrings.add(xpGainString); break;
- case 4:
- overlayStrings.add(totalXpString); break;
- case 5:
- overlayStrings.add(petItemStr); break;
- case 6:
- if(etaStr != null) overlayStrings.add(etaStr); break;
- case 7:
- if(etaMaxStr != null) overlayStrings.add(etaMaxStr); break;
- }
+ overlayStrings.addAll(createStringsForPet(currentPet, false));
+
+ Pet currentPet2 = getCurrentPet2();
+ if(currentPet2 != null) {
+ overlayStrings.add("");
+ overlayStrings.addAll(createStringsForPet(currentPet2, true));
}
}
@@ -403,18 +443,8 @@ public class PetInfoOverlay extends TextOverlay {
NEUConfig config = NotEnoughUpdates.INSTANCE.config;
int updateTime = 60000;
- if((config.itemOverlays.enableMonkeyCheck) && !config.petOverlay.enablePetInfo)
- updateTime = 300000;
if(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
- /*if(petList.isEmpty()) {
- ProfileViewer.Profile profile = NotEnoughUpdates.profileViewer.getProfileRaw(Minecraft.getMinecraft().thePlayer
- .getUniqueID().toString().replace("-", ""));
- if(profile != null) {
- getAndSetPet(profile);
- }
- }*/
-
ProfileApiSyncer.getInstance().requestResync("petinfo", updateTime, () -> {
}, PetInfoOverlay::getAndSetPet);
}
@@ -429,6 +459,32 @@ public class PetInfoOverlay extends TextOverlay {
}
}
+ private static GuiProfileViewer.PetLevel getMaxLevel(JsonArray levels, int offset) {
+ float xpTotal = 0;
+ float level = 1;
+ float currentLevelRequirement = 0;
+
+ for(int i=offset; i<offset+99; i++) {
+ currentLevelRequirement = levels.get(i).getAsFloat();
+ xpTotal += currentLevelRequirement;
+ level += 1;
+ }
+
+ if(level <= 0) {
+ level = 1;
+ } else if(level > 100) {
+ level = 100;
+ }
+ GuiProfileViewer.PetLevel levelObj = new GuiProfileViewer.PetLevel();
+ levelObj.level = level;
+ levelObj.currentLevelRequirement = currentLevelRequirement;
+ levelObj.maxXP = xpTotal;
+ levelObj.levelPercentage = 1;
+ levelObj.levelXp = currentLevelRequirement-5;
+ levelObj.totalXp = xpTotal-5;
+ return levelObj;
+ }
+
private static GuiProfileViewer.PetLevel getLevel(JsonArray levels, int offset, float xpThisLevel, int xpMaxThisLevel) {
float xpTotal = 0;
float level = 1;
@@ -498,7 +554,6 @@ public class PetInfoOverlay extends TextOverlay {
.replace(" ", "_").toUpperCase();
}
if(petType == null || rarity == null) {
- System.out.println("Failed pet : " + name);
return null;
}
@@ -541,7 +596,7 @@ public class PetInfoOverlay extends TextOverlay {
}
} else if(xpLineMatcher.matches()) {
String xpThisLevelS = xpLineMatcher.group(1);
- String xpMaxThisLevelS = xpLineMatcher.group(2);
+ String xpMaxThisLevelS = xpLineMatcher.group(2).toLowerCase();
try {
float xpThisLevel = Float.parseFloat(xpThisLevelS.replace(",", ""));
@@ -561,6 +616,8 @@ public class PetInfoOverlay extends TextOverlay {
level = getLevel(Constants.PETS.get("pet_levels").getAsJsonArray(), rarity.petOffset, xpThisLevel, xpMaxThisLevel);
} catch(NumberFormatException ignored) {}
+ } else if(line.equals("\u00a7b\u00a7lMAX LEVEL")) {
+ level = getMaxLevel(Constants.PETS.get("pet_levels").getAsJsonArray(), rarity.petOffset);
}
}
@@ -583,9 +640,6 @@ public class PetInfoOverlay extends TextOverlay {
@SubscribeEvent
public void onTick(TickEvent.ClientTickEvent event) {
- if(Keyboard.isKeyDown(Keyboard.KEY_K)) {
- System.out.println("Current:"+selectedPet+":"+getCurrentPet());
- }
if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
ContainerChest container = (ContainerChest) chest.inventorySlots;
@@ -667,7 +721,7 @@ public class PetInfoOverlay extends TextOverlay {
}
}
if(!foundDespawn && selectedPet == petIndex) {
- selectedPet = -1;
+ clearPet();
}
}
}
@@ -744,6 +798,24 @@ public class PetInfoOverlay extends TextOverlay {
Utils.drawItemStack(stack, 0, 0);
GlStateManager.popMatrix();
}
+
+ Pet currentPet2 = getCurrentPet2();
+ if(currentPet2 != null) {
+ JsonObject petItem2 = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(currentPet2.petType + ";" + currentPet2.rarity.petId);
+ if(petItem2 != null) {
+ Vector2f position = getPosition(overlayWidth, overlayHeight);
+ int x = (int)position.x;
+ int y = (int)position.y + NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.size()*10+10;
+
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(petItem2);
+ GlStateManager.enableDepth();
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x-2, y-2, 0);
+ GlStateManager.scale(2, 2, 1);
+ Utils.drawItemStack(stack, 0, 0);
+ GlStateManager.popMatrix();
+ }
+ }
}
public static float getBoostMultiplier(String boostName) {
@@ -807,14 +879,13 @@ public class PetInfoOverlay extends TextOverlay {
System.out.println("removing");
System.out.println("new:"+newSelected+":OLD:"+selectedPet);
if(newSelected == selectedPet) {
- System.out.println("setting to -1");
- selectedPet = -1;
+ clearPet();
} else if(selectedPet > newSelected) {
System.out.println("decrementing");
selectedPet--;
}
} else {
- selectedPet = newSelected;
+ setCurrentPet(newSelected);
String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound());
Pet pet = getPetFromStack(stack.getDisplayName(), lore);
@@ -831,6 +902,8 @@ public class PetInfoOverlay extends TextOverlay {
}
public static float getXpGain(Pet pet, float xp, String xpType) {
+ if(pet.petLevel.level >= 100) return 0;
+
if(validXpTypes == null) validXpTypes = Lists.newArrayList("mining","foraging","enchanting","farming","combat","fishing","alchemy");
if(!validXpTypes.contains(xpType.toLowerCase())) return 0;
@@ -1021,10 +1094,10 @@ public class PetInfoOverlay extends TextOverlay {
.replaceAll("[^\\w ]", "").trim()
.replace(" ", "_").toUpperCase();
- selectedPet = getClosestPetIndex(pet, rarity.petId, "", lastLevelHovered);
+ setCurrentPet(getClosestPetIndex(pet, rarity.petId, "", lastLevelHovered));
if(selectedPet == -1) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+"[NEU] Can't find pet \u00a7" + petStringMatch +
- EnumChatFormatting.RED + " try visiting all pages of /pets."));
+ EnumChatFormatting.RED + " try revisiting all pages of /pets."));
}
} else if(chatMessage.toLowerCase().startsWith("you despawned your")) {
clearPet();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
index 4a343f9e..3305cd13 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
@@ -5,6 +5,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
@@ -787,7 +788,6 @@ public class CalendarOverlay {
@SubscribeEvent
public void onGuiScreenDrawTimer(GuiScreenEvent.BackgroundDrawnEvent event) {
- blurBackground();
if(!drawTimerForeground) {
drawTimer();
}
@@ -903,7 +903,7 @@ public class CalendarOverlay {
GlStateManager.disableLighting();
GlStateManager.disableColorMaterial();
- renderBlurredBackground(width, height, guiLeft+3, guiTop+3, xSize-6, ySize-6);
+ renderBlurredBackground(10, width, height, guiLeft+3, guiTop+3, xSize-6, ySize-6);
Minecraft.getMinecraft().getTextureManager().bindTexture(DISPLAYBAR);
Utils.drawTexturedRect(guiLeft, guiTop, xSize, 20, GL11.GL_NEAREST);
@@ -985,6 +985,13 @@ public class CalendarOverlay {
GlStateManager.popMatrix();
}
+ private void renderBlurredBackground(float blurStrength, int screenWidth, int screenHeight,
+ int x, int y, int blurWidth, int blurHeight) {
+ BackgroundBlur.renderBlurredBackground(blurStrength, screenWidth, screenHeight, x, y, blurWidth, blurHeight);
+ Gui.drawRect(x, y, x+blurWidth, y+blurHeight, 0xc8101010);
+ GlStateManager.color(1, 1, 1, 1);
+ }
+
@SubscribeEvent
public void onGuiDraw(GuiScreenEvent.DrawScreenEvent.Pre event) {
if(!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) {
@@ -1021,10 +1028,10 @@ public class CalendarOverlay {
Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680);
- renderBlurredBackground(width, height, guiLeft+3, guiTop+3, 162, 14);
- renderBlurredBackground(width, height, guiLeft+3, guiTop+26, 14, 141);
- renderBlurredBackground(width, height, guiLeft+151, guiTop+26, 14, 141);
- renderBlurredBackground(width, height, guiLeft+26, guiTop+26, 116, 141);
+ renderBlurredBackground(10, width, height, guiLeft+3, guiTop+3, 162, 14);
+ renderBlurredBackground(10, width, height, guiLeft+3, guiTop+26, 14, 141);
+ renderBlurredBackground(10, width, height, guiLeft+151, guiTop+26, 14, 141);
+ renderBlurredBackground(10, width, height, guiLeft+26, guiTop+26, 116, 141);
Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, GL11.GL_NEAREST);
@@ -1381,82 +1388,4 @@ public class CalendarOverlay {
return projMatrix;
}
- private double lastBgBlurFactor = -1;
- private void blurBackground() {
- if(!OpenGlHelper.isFramebufferEnabled()) return;
-
- int width = Minecraft.getMinecraft().displayWidth;
- int height = Minecraft.getMinecraft().displayHeight;
-
- if(blurOutputHorz == null) {
- blurOutputHorz = new Framebuffer(width, height, false);
- blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST);
- }
- if(blurOutputVert == null) {
- blurOutputVert = new Framebuffer(width, height, false);
- blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST);
- }
- if(blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) {
- blurOutputHorz.createBindFramebuffer(width, height);
- blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
- }
- if(blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) {
- blurOutputVert.createBindFramebuffer(width, height);
- blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
- }
-
- if(blurShaderHorz == null) {
- try {
- blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
- Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz);
- blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
- blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
- } catch(Exception e) { }
- }
- if(blurShaderVert == null) {
- try {
- blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
- blurOutputHorz, blurOutputVert);
- blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1);
- blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
- } catch(Exception e) { }
- }
- if(blurShaderHorz != null && blurShaderVert != null) {
- if(15 != lastBgBlurFactor) {
- blurShaderHorz.getShaderManager().getShaderUniform("Radius").set((float)15);
- blurShaderVert.getShaderManager().getShaderUniform("Radius").set((float)15);
- lastBgBlurFactor = 15;
- }
- GL11.glPushMatrix();
- blurShaderHorz.loadShader(0);
- blurShaderVert.loadShader(0);
- GlStateManager.enableDepth();
- GL11.glPopMatrix();
-
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
- }
- }
-
- /**
- * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen.
- * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight]
- */
- public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) {
- if(!OpenGlHelper.isFramebufferEnabled()) return;
-
- float uMin = x/(float)width;
- float uMax = (x+blurWidth)/(float)width;
- float vMin = (height-y)/(float)height;
- float vMax = (height-y-blurHeight)/(float)height;
-
- GlStateManager.depthMask(false);
- blurOutputVert.bindFramebufferTexture();
- GlStateManager.color(1f, 1f, 1f, 1f);
- Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax);
- blurOutputVert.unbindFramebufferTexture();
- GlStateManager.depthMask(true);
- }
-
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java
new file mode 100644
index 00000000..1260dbd2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java
@@ -0,0 +1,677 @@
+package io.github.moulberry.notenoughupdates.miscgui;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.GlScissorStack;
+import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger;
+import io.github.moulberry.notenoughupdates.options.NEUConfig;
+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.renderer.GlStateManager;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class GuiInvButtonEditor extends GuiScreen {
+
+ private static final ResourceLocation INVENTORY = new ResourceLocation("minecraft:textures/gui/container/inventory.png");
+ private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png");
+ private static final ResourceLocation EXTRA_ICONS_JSON = new ResourceLocation("notenoughupdates:invbuttons/extraicons.json");
+ private static final ResourceLocation PRESETS_JSON = new ResourceLocation("notenoughupdates:invbuttons/presets.json");
+
+ private int xSize = 176;
+ private int ySize = 166;
+
+ private int guiLeft;
+ private int guiTop;
+
+ private static final int BACKGROUND_TYPES = 5;
+ private static final int ICON_TYPES = 3;
+ private int iconTypeIndex = 0;
+
+ private int editorXSize = 150;
+ private int editorYSize = 204;
+ private int editorLeft;
+ private int editorTop;
+
+ private GuiElementTextField commandTextField = new GuiElementTextField("", editorXSize-14, 16, GuiElementTextField.SCALE_TEXT);
+ private GuiElementTextField iconTextField = new GuiElementTextField("", editorXSize-14, 16, GuiElementTextField.SCALE_TEXT);
+
+ private static final HashSet<String> prioritisedIcons = new HashSet<>();
+ static {
+ prioritisedIcons.add("WORKBENCH");
+ prioritisedIcons.add("LEATHER_CHESTPLATE");
+ prioritisedIcons.add("CHEST");
+ prioritisedIcons.add("BONE");
+ prioritisedIcons.add("ENDER_CHEST");
+ prioritisedIcons.add("GOLD_BARDING");
+ prioritisedIcons.add("COMPASS");
+ prioritisedIcons.add("GOLD_BLOCK");
+ prioritisedIcons.add("EMPTY_MAP");
+ prioritisedIcons.add("RAW_FISH");
+ prioritisedIcons.add("FISHING_ROD");
+ prioritisedIcons.add("EMERALD");
+ prioritisedIcons.add("IRON_SWORD");
+ prioritisedIcons.add("POTION");
+ prioritisedIcons.add("NETHER_STAR");
+ prioritisedIcons.add("PAINTING");
+ prioritisedIcons.add("COMMAND");
+ prioritisedIcons.add("BOOK");
+ }
+
+ private static HashMap<String, String> extraIcons = null;
+
+ private static final HashMap<String, String> skullIcons = new HashMap<>();
+ static {
+ skullIcons.put("personal bank", "skull:e36e94f6c34a35465fce4a90f2e25976389eb9709a12273574ff70fd4daa6852");
+ skullIcons.put("skyblock hub", "skull:d7cc6687423d0570d556ac53e0676cb563bbdd9717cd8269bdebed6f6d4e7bf8");
+ skullIcons.put("private island", "skull:c9c8881e42915a9d29bb61a16fb26d059913204d265df5b439b3d792acd56");
+ skullIcons.put("castle", "skull:f4559d75464b2e40a518e4de8e6cf3085f0a3ca0b1b7012614c4cd96fed60378");
+ skullIcons.put("sirius shack", "skull:7ab83858ebc8ee85c3e54ab13aabfcc1ef2ad446d6a900e471c3f33b78906a5b");
+ skullIcons.put("crypts", "skull:25d2f31ba162fe6272e831aed17f53213db6fa1c4cbe4fc827f3963cc98b9");
+ skullIcons.put("spiders den", "skull:c754318a3376f470e481dfcd6c83a59aa690ad4b4dd7577fdad1c2ef08d8aee6");
+ skullIcons.put("top of the nest", "skull:9d7e3b19ac4f3dee9c5677c135333b9d35a7f568b63d1ef4ada4b068b5a25");
+ skullIcons.put("blazing fortress", "skull:c3687e25c632bce8aa61e0d64c24e694c3eea629ea944f4cf30dcfb4fbce071");
+ skullIcons.put("blazing fortress magma boss", "skull:38957d5023c937c4c41aa2412d43410bda23cf79a9f6ab36b76fef2d7c429");
+ skullIcons.put("the end", "skull:7840b87d52271d2a755dedc82877e0ed3df67dcc42ea479ec146176b02779a5");
+ skullIcons.put("the end dragons nest", "skull:a1cd6d2d03f135e7c6b5d6cdae1b3a68743db4eb749faf7341e9fb347aa283b");
+ skullIcons.put("the park", "skull:a221f813dacee0fef8c59f76894dbb26415478d9ddfc44c2e708a6d3b7549b");
+ skullIcons.put("the park jungle", "skull:79ca3540621c1c79c32bf42438708ff1f5f7d0af9b14a074731107edfeb691c");
+ skullIcons.put("the park howling cave", "skull:1832d53997b451635c9cf9004b0f22bb3d99ab5a093942b5b5f6bb4e4de47065");
+ skullIcons.put("gold mines", "skull:73bc965d579c3c6039f0a17eb7c2e6faf538c7a5de8e60ec7a719360d0a857a9");
+ skullIcons.put("deep caverns", "skull:569a1f114151b4521373f34bc14c2963a5011cdc25a6554c48c708cd96ebfc");
+ skullIcons.put("the barn", "skull:4d3a6bd98ac1833c664c4909ff8d2dc62ce887bdcf3cc5b3848651ae5af6b");
+ skullIcons.put("mushroom desert", "skull:2116b9d8df346a25edd05f842e7a9345beaf16dca4118abf5a68c75bcaae10");
+ skullIcons.put("dungeon hub", "skull:9b56895b9659896ad647f58599238af532d46db9c1b0389b8bbeb70999dab33d");
+ skullIcons.put("dwarven mines", "skull:569a1f114151b4521373f34bc14c2963a5011cdc25a6554c48c708cd96ebfc");
+ skullIcons.put("hotm heart of the mountain", "skull:86f06eaa3004aeed09b3d5b45d976de584e691c0e9cade133635de93d23b9edb");
+ skullIcons.put("bazaar dude", "skull:c232e3820897429157619b0ee099fec0628f602fff12b695de54aef11d923ad7");
+ }
+
+ private static LinkedHashMap<String, List<NEUConfig.InventoryButton>> presets = null;
+
+ public GuiInvButtonEditor() {
+ super();
+ reloadExtraIcons();
+ reloadPresets();
+ Keyboard.enableRepeatEvents(true);
+ }
+
+ private static void reloadExtraIcons() {
+ extraIcons = new HashMap<>();
+
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(
+ Minecraft.getMinecraft().getResourceManager().getResource(EXTRA_ICONS_JSON).getInputStream(), StandardCharsets.UTF_8))) {
+ JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class);
+
+ for(Map.Entry<String, JsonElement> entry : json.entrySet()) {
+ if(entry.getValue().isJsonPrimitive()) {
+ extraIcons.put(entry.getKey(), "extra:"+entry.getValue().getAsString());
+ }
+ }
+ } catch(Exception e) {
+ }
+ }
+
+ private static void reloadPresets() {
+ presets = new LinkedHashMap<>();
+
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(
+ Minecraft.getMinecraft().getResourceManager().getResource(PRESETS_JSON).getInputStream(), StandardCharsets.UTF_8))) {
+ JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class);
+
+ for(Map.Entry<String, JsonElement> entry : json.entrySet()) {
+ if(entry.getValue().isJsonArray()) {
+ JsonArray arr = entry.getValue().getAsJsonArray();
+ List<NEUConfig.InventoryButton> buttons = new ArrayList<>();
+ for(int i=0; i<arr.size(); i++) {
+ JsonObject o = arr.get(i).getAsJsonObject();
+ NEUConfig.InventoryButton button = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(o, NEUConfig.InventoryButton.class);
+ buttons.add(button);
+ }
+ presets.put(entry.getKey(), buttons);
+ }
+ }
+ } catch(Exception e) {
+ }
+ }
+
+ private static final Comparator<String> prioritisingComparator = (o1, o2) -> {
+ boolean c1 = prioritisedIcons.contains(o1);
+ boolean c2 = prioritisedIcons.contains(o2);
+
+ if(c1 && !c2) return -1;
+ if(!c1 && c2) return 1;
+
+ return o1.compareTo(o2);
+ };
+
+ private final List<String> searchedIcons = new ArrayList<>();
+
+ private LerpingInteger itemScroll = new LerpingInteger(0, 100);
+
+ private NEUConfig.InventoryButton editingButton = null;
+
+ private static HashMap<String, ItemStack> skullMap = new HashMap<>();
+
+ public static void renderIcon(String icon, int x, int y) {
+ if(extraIcons == null) {
+ reloadExtraIcons();
+ }
+
+ if(icon.startsWith("extra:")) {
+ String name = icon.substring("extra:".length());
+ ResourceLocation resourceLocation = new ResourceLocation("notenoughupdates:invbuttons/extraicons/"+name+".png");
+ Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(x, y, 16, 16, GL11.GL_NEAREST);
+ } else {
+ ItemStack stack = getStack(icon);
+
+ float scale = 1;
+ if(icon.startsWith("skull:")) {
+ scale = 1.2f;
+ }
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x+8, y+8, 0);
+ GlStateManager.scale(scale, scale, 1);
+ GlStateManager.translate(-8, -8, 0);
+ Utils.drawItemStack(stack, 0, 0);
+ GlStateManager.popMatrix();
+ }
+ }
+
+ public static ItemStack getStack(String icon) {
+ if(icon.startsWith("extra:")) {
+ return null;
+ } else if(icon.startsWith("skull:")) {
+ String link = icon.substring("skull:".length());
+ if(skullMap.containsKey(link)) return skullMap.get(link);
+
+ ItemStack render = new ItemStack(Items.skull, 1, 3);
+ NBTTagCompound nbt = new NBTTagCompound();
+ NBTTagCompound skullOwner = new NBTTagCompound();
+ NBTTagCompound properties = new NBTTagCompound();
+ NBTTagList textures = new NBTTagList();
+ NBTTagCompound textures_0 = new NBTTagCompound();
+
+ String uuid = UUID.nameUUIDFromBytes(link.getBytes()).toString();
+ skullOwner.setString("Id", uuid);
+ skullOwner.setString("Name", uuid);
+
+ String display = "{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/"+link+"\"}}}";
+ String displayB64 = Base64.getEncoder().encodeToString(display.getBytes());
+
+ textures_0.setString("Value", displayB64);
+ textures.appendTag(textures_0);
+
+ properties.setTag("textures", textures);
+ skullOwner.setTag("Properties", properties);
+ nbt.setTag("SkullOwner", skullOwner);
+ render.setTagCompound(nbt);
+
+ skullMap.put(link, render);
+ return render;
+ } else {
+ return NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(icon));
+ }
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ super.drawScreen(mouseX, mouseY, partialTicks);
+
+ super.drawDefaultBackground();
+
+ guiLeft = width/2 - xSize/2;
+ guiTop = height/2 - ySize/2;
+
+ GlStateManager.enableDepth();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(INVENTORY);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, 0, xSize/256f, 0, ySize/256f, GL11.GL_NEAREST);
+
+ for(NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ int x = guiLeft+button.x;
+ int y = guiTop+button.y;
+ if(button.anchorRight) {
+ x += xSize;
+ }
+ if(button.anchorBottom) {
+ y += ySize;
+ }
+
+ if(button.isActive()) {
+ GlStateManager.color(1, 1, 1, 1f);
+ } else {
+ GlStateManager.color(1, 1, 1, 0.5f);
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ Utils.drawTexturedRect(x, y, 18, 18,
+ button.backgroundIndex*18/256f, (button.backgroundIndex*18+18)/256f, 18/256f, 36/256f, GL11.GL_NEAREST);
+
+ if(button.isActive()) {
+ if(button.icon != null && !button.icon.trim().isEmpty()) {
+ GlStateManager.enableDepth();
+
+ renderIcon(button.icon, x+1, y+1);
+ }
+ } else {
+ fontRendererObj.drawString("+", x+6, y+5, 0xffcccccc);
+ }
+ }
+
+ if(presets != null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ Utils.drawTexturedRect(guiLeft+xSize+22, guiTop, 80, ySize,
+ editorXSize/256f, (editorXSize+80)/256f, 41/256f, (41+ySize)/256f, GL11.GL_NEAREST);
+ Utils.drawStringCenteredScaledMaxWidth("\u00a7nPresets", fontRendererObj, guiLeft+xSize+22+40, guiTop+10, false, 70, 0xffa0a0a0);
+
+ int index = 0;
+ for(String presetName : presets.keySet()) {
+ Utils.drawStringCenteredScaledMaxWidth(presetName, fontRendererObj, guiLeft+xSize+22+40, guiTop+25+10*(index++),
+ false, 70, 0xff909090);
+ }
+ }
+
+ if(editingButton != null) {
+ int x = guiLeft+editingButton.x;
+ int y = guiTop+editingButton.y;
+ if(editingButton.anchorRight) {
+ x += xSize;
+ }
+ if(editingButton.anchorBottom) {
+ y += ySize;
+ }
+
+ GlStateManager.translate(0, 0, 300);
+ editorLeft = x + 8 - editorXSize/2;
+ editorTop = y + 18 + 2;
+
+ boolean showArrow = true;
+ if(editorTop+editorYSize+5 > height) {
+ editorTop = height-editorYSize-5;
+ showArrow = false;
+ }
+ if(editorLeft < 5) {
+ editorLeft = 5;
+ showArrow = false;
+ }
+ if(editorLeft+editorXSize+5 > width) {
+ editorLeft = width-editorXSize-5;
+ showArrow = false;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ GlStateManager.color(1, 1, 1, 1f);
+ Utils.drawTexturedRect(editorLeft, editorTop, editorXSize, editorYSize, 0, editorXSize/256f, 41/256f, (41+editorYSize)/256f, GL11.GL_NEAREST);
+
+ if(showArrow) Utils.drawTexturedRect(x+8-3, y+18, 10, 5, 0, 6/256f, 36/256f, 41/256f, GL11.GL_NEAREST);
+
+ fontRendererObj.drawString("Command", editorLeft+7, editorTop+7, 0xffa0a0a0, false);
+
+ commandTextField.setSize(editorXSize-14, 16);
+ commandTextField.setText(commandTextField.getText().replaceAll("^ +", ""));
+ if(commandTextField.getText().startsWith("/")) {
+ commandTextField.setPrependText("");
+ } else {
+ commandTextField.setPrependText("\u00a77/\u00a7r");
+ }
+ commandTextField.render(editorLeft+7, editorTop+19);
+
+ fontRendererObj.drawString("Background", editorLeft+7, editorTop+40, 0xffa0a0a0, false);
+
+ for(int i=0; i<BACKGROUND_TYPES; i++) {
+ if(i == editingButton.backgroundIndex) {
+ Gui.drawRect(editorLeft+7+20*i-1, editorTop+50-1, editorLeft+7+20*i+19, editorTop+50+19, 0xff0000ff);
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(editorLeft+7+20*i, editorTop+50, 18, 18,
+ i*18/256f, (i*18+18)/256f, 0/256f, 18/256f, GL11.GL_NEAREST);
+ }
+
+ fontRendererObj.drawString("Icon Type", editorLeft+7, editorTop+50+24, 0xffa0a0a0, false);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ GlStateManager.color(1, 1, 1, 1);
+ float uMin = 18/256f;
+ float uMax = 36/256f;
+ float vMin = 0;
+ float vMax = 18/256f;
+
+ for(int i=0; i<ICON_TYPES; i++) {
+ boolean flip = iconTypeIndex == i;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(editorLeft+7+20*i, editorTop+50+34, 18, 18,
+ flip ? uMax : uMin, flip ? uMin : uMax, flip ? vMax : vMin, flip ? vMin : vMax, GL11.GL_NEAREST);
+
+ ItemStack stack = null;
+ if(i == 0) {
+ stack = new ItemStack(Items.diamond_sword);
+ } else if(i == 1) {
+ stack = getStack("skull:c9c8881e42915a9d29bb61a16fb26d059913204d265df5b439b3d792acd56");
+ } else if(i == 2) {
+ stack = new ItemStack(Items.lead);
+ }
+ if(stack != null) Utils.drawItemStack(stack, editorLeft+8+20*i, editorTop+50+35);
+ }
+
+ fontRendererObj.drawString("Icon Selector", editorLeft+7, editorTop+50+55, 0xffa0a0a0, false);
+
+ iconTextField.render(editorLeft+7, editorTop+50+65);
+
+ GlStateManager.enableDepth();
+
+ itemScroll.tick();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ GlScissorStack.push(0, editorTop+136, width, editorTop+196, scaledResolution);
+
+ synchronized(searchedIcons) {
+ if(iconTextField.getText().trim().isEmpty() && searchedIcons.isEmpty()) {
+ searchedIcons.addAll(NotEnoughUpdates.INSTANCE.manager.getItemInformation().keySet());
+ searchedIcons.sort(prioritisingComparator);
+ }
+
+ int max = (searchedIcons.size()-1)/6*20-40;
+ int scroll = itemScroll.getValue();
+ if(scroll > max) scroll = max;
+
+ int scrollBarHeight = (int)Math.ceil(3f*54f/(searchedIcons.size()-18));
+ if(scrollBarHeight < 0) scrollBarHeight = 54;
+ if(scrollBarHeight < 2) scrollBarHeight = 2;
+ int scrollY = (int)Math.floor(54f*((scroll/20f) / ((searchedIcons.size()-18)/6f)));
+ if(scrollY+scrollBarHeight > 54) scrollY = 54-scrollBarHeight;
+
+ Gui.drawRect(editorLeft+137, editorTop+139+scrollY, editorLeft+139, editorTop+139+scrollY+scrollBarHeight, 0xff202020);
+
+ int endIndex = searchedIcons.size();
+ int startIndex = scroll/20*6;
+ if(startIndex < 0) startIndex = 0;
+ if(endIndex > startIndex+24) endIndex = startIndex+24;
+
+ for(int i=startIndex; i<endIndex; i++) {
+ String iconS = searchedIcons.get(i);
+
+ int iconX = editorLeft+12+((i-startIndex)%6)*20;
+ int iconY = editorTop+137+((i-startIndex)/6)*20 - (itemScroll.getValue()%20);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(iconX, iconY, 18, 18,
+ 18/256f, 36/256f, 0/256f, 18/256f, GL11.GL_NEAREST);
+
+ renderIcon(iconS, iconX+1, iconY+1);
+ }
+ }
+
+ GlScissorStack.pop(scaledResolution);
+
+ GlStateManager.translate(0, 0, -300);
+ }
+ }
+
+ @Override
+ public void handleMouseInput() throws IOException {
+ int scroll = Mouse.getEventDWheel();
+ if(scroll != 0) {
+ scroll = -scroll;
+ if(scroll > 1) scroll = 8;
+ if(scroll < -1) scroll = -8;
+
+ int delta = Math.abs(itemScroll.getTarget() - itemScroll.getValue());
+ float acc = delta/20+1;
+ scroll *= acc;
+
+ int max = (searchedIcons.size()-1)/6*20-40;
+ int newTarget = itemScroll.getTarget() + scroll;
+
+ if(newTarget > max) newTarget = max;
+ if(newTarget < 0) newTarget = 0;
+
+ itemScroll.setTarget(newTarget);
+ itemScroll.resetTimer();
+ }
+
+ super.handleMouseInput();
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ super.mouseClicked(mouseX, mouseY, mouseButton);
+
+ if(editingButton != null) {
+ if(mouseX >= editorLeft && mouseX <= editorLeft+editorXSize &&
+ mouseY >= editorTop & mouseY <= editorTop + editorYSize) {
+ if(mouseX >= editorLeft+7 && mouseX <= editorLeft+7+commandTextField.getWidth() &&
+ mouseY >= editorTop+12 && mouseY <= editorTop+12+commandTextField.getHeight()) {
+ commandTextField.mouseClicked(mouseX, mouseY, mouseButton);
+ iconTextField.unfocus();
+ editingButton.command = commandTextField.getText();
+ return;
+ }
+ if(mouseX >= editorLeft+7 && mouseX <= editorLeft+7+iconTextField.getWidth() &&
+ mouseY >= editorTop+50+65 && mouseY <= editorTop+50+65+iconTextField.getHeight()) {
+ iconTextField.mouseClicked(mouseX, mouseY, mouseButton);
+
+ if(mouseButton == 1) {
+ search();
+ }
+
+ commandTextField.unfocus();
+ return;
+ }
+ if(mouseY >= editorTop+50 && mouseY <= editorTop+50+18) {
+ for(int i=0; i<BACKGROUND_TYPES; i++) {
+ if(mouseX >= editorLeft+7+20*i && mouseX <= editorLeft+7+20*i+18) {
+ editingButton.backgroundIndex = i;
+ return;
+ }
+ }
+ }
+ for(int i=0; i<ICON_TYPES; i++) {
+ if(mouseX >= editorLeft+7+20*i && mouseX <= editorLeft+7+20*i+18 &&
+ mouseY >= editorTop+50+34 && mouseY <= editorTop+50+34+18) {
+ if(iconTypeIndex != i) {
+ iconTypeIndex = i;
+ search();
+ }
+ return;
+ }
+ }
+ if(mouseX > editorLeft+8 && mouseX < editorLeft+editorXSize-16 && mouseY > editorTop+136 && mouseY < editorTop+196) {
+ synchronized(searchedIcons) {
+ int max = (searchedIcons.size()-1)/6*20-40;
+ int scroll = itemScroll.getValue();
+ if(scroll > max) scroll = max;
+
+ int endIndex = searchedIcons.size();
+ int startIndex = scroll/20*6;
+ if(startIndex < 0) startIndex = 0;
+ if(endIndex > startIndex+24) endIndex = startIndex+24;
+
+ for(int i=startIndex; i<endIndex; i++) {
+ String iconS = searchedIcons.get(i);
+
+ int x = editorLeft+12+((i-startIndex)%6)*20;
+ int y = editorTop+137+((i-startIndex)/6)*20 - (itemScroll.getValue()%20);
+
+ if(mouseX >= x && mouseX <= x+18 &&
+ mouseY >= y && mouseY <= y+18) {
+ editingButton.icon = iconS;
+ return;
+ }
+ }
+ }
+ }
+ return;
+ }
+ }
+
+ for(NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ int x = guiLeft+button.x;
+ int y = guiTop+button.y;
+ if(button.anchorRight) {
+ x += xSize;
+ }
+ if(button.anchorBottom) {
+ y += ySize;
+ }
+
+ if(mouseX >= x && mouseY >= y &&
+ mouseX <= x+18 && mouseY <= y+18) {
+ if(editingButton == button) {
+ editingButton = null;
+ } else {
+ editingButton = button;
+ commandTextField.setText(editingButton.command);
+ }
+ return;
+ }
+ }
+
+ if(editingButton == null) {
+ int index = 0;
+ for(List<NEUConfig.InventoryButton> buttons : presets.values()) {
+ if(mouseX >= guiLeft+xSize+22 && mouseX <= guiLeft+xSize+22+80 &&
+ mouseY >= guiTop+21+10*index && mouseY <= guiTop+21+10*index+10) {
+ NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons = buttons;
+ return;
+ }
+ index++;
+ }
+ }
+
+ editingButton = null;
+ }
+
+ @Override
+ protected void keyTyped(char typedChar, int keyCode) throws IOException {
+ super.keyTyped(typedChar, keyCode);
+
+ if(editingButton != null && commandTextField.getFocus()) {
+ commandTextField.keyTyped(typedChar, keyCode);
+ editingButton.command = commandTextField.getText();
+ } else if(editingButton != null && iconTextField.getFocus()) {
+ String old = iconTextField.getText().trim();
+ iconTextField.keyTyped(typedChar, keyCode);
+ String newText = iconTextField.getText().trim();
+
+ if(!old.equalsIgnoreCase(newText)) {
+ search();
+ }
+ }
+ }
+
+ private ExecutorService searchES = Executors.newSingleThreadExecutor();
+ private AtomicInteger searchId = new AtomicInteger(0);
+
+ public void search() {
+ final int thisSearchId = searchId.incrementAndGet();
+ final String searchString = iconTextField.getText();
+
+ if(iconTypeIndex == 0) {
+ if(searchString.trim().isEmpty()) {
+ synchronized(searchedIcons) {
+ searchedIcons.clear();
+
+ List<String> unsorted = new ArrayList<>(NotEnoughUpdates.INSTANCE.manager.getItemInformation().keySet());
+ unsorted.sort(prioritisingComparator);
+ searchedIcons.addAll(unsorted);
+ }
+ return;
+ }
+
+ searchES.submit(() -> {
+ if(thisSearchId != searchId.get()) return;
+
+ List<String> title = new ArrayList<>(NotEnoughUpdates.INSTANCE.manager.search("title:" + searchString.trim()));
+
+ if(thisSearchId != searchId.get()) return;
+
+ if(!searchString.trim().contains(" ")) {
+ StringBuilder sb = new StringBuilder();
+ for(char c : searchString.toCharArray()) {
+ sb.append(c).append(" ");
+ }
+ title.addAll(NotEnoughUpdates.INSTANCE.manager.search("title:" + sb.toString().trim()));
+ }
+
+ if(thisSearchId != searchId.get()) return;
+
+ List<String> desc = new ArrayList<>(NotEnoughUpdates.INSTANCE.manager.search("desc:" + searchString.trim()));
+ desc.removeAll(title);
+
+ if(thisSearchId != searchId.get()) return;
+
+ title.sort(prioritisingComparator);
+ desc.sort(prioritisingComparator);
+
+ if(thisSearchId != searchId.get()) return;
+
+ synchronized(searchedIcons) {
+ searchedIcons.clear();
+ searchedIcons.addAll(title);
+ searchedIcons.addAll(desc);
+ }
+ });
+ } else if(iconTypeIndex == 1) {
+ if(searchString.trim().isEmpty()) {
+ searchedIcons.clear();
+ searchedIcons.addAll(skullIcons.values());
+ return;
+ }
+
+ synchronized(searchedIcons) {
+ searchedIcons.clear();
+ for(Map.Entry<String, String> entry : skullIcons.entrySet()) {
+ if(NotEnoughUpdates.INSTANCE.manager.searchString(entry.getKey(), searchString)) {
+ searchedIcons.add(entry.getValue());
+ }
+ }
+ }
+ } else if(iconTypeIndex == 2) {
+ if(searchString.trim().isEmpty()) {
+ searchedIcons.clear();
+ searchedIcons.addAll(extraIcons.values());
+ return;
+ }
+
+ synchronized(searchedIcons) {
+ searchedIcons.clear();
+ for(Map.Entry<String, String> entry : extraIcons.entrySet()) {
+ if(NotEnoughUpdates.INSTANCE.manager.searchString(entry.getKey(), searchString)) {
+ searchedIcons.add(entry.getValue());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/GuiContainerAccessor.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/GuiContainerAccessor.java
new file mode 100644
index 00000000..57d4de2a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/GuiContainerAccessor.java
@@ -0,0 +1,22 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.client.gui.inventory.GuiContainer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(GuiContainer.class)
+public interface GuiContainerAccessor {
+
+ @Accessor
+ int getXSize();
+
+ @Accessor
+ int getYSize();
+
+ @Accessor
+ int getGuiLeft();
+
+ @Accessor
+ int getGuiTop();
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java
index fb6fba4e..58aeb828 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java
@@ -17,7 +17,7 @@ public class MixinContainer {
@Inject(method = "putStacksInSlots", at=@At("RETURN"))
public void putStacksInSlots(ItemStack[] stacks, CallbackInfo ci) {
- EnchantingSolvers.processInventoryContents();
+ EnchantingSolvers.processInventoryContents(false);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
index 1281dec4..0c822827 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
@@ -1,13 +1,19 @@
package io.github.moulberry.notenoughupdates.mixins;
+import io.github.moulberry.notenoughupdates.NEUEventListener;
+import io.github.moulberry.notenoughupdates.NEUOverlay;
import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers;
import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
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.GuiTextField;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ContainerChest;
@@ -28,6 +34,16 @@ public abstract class MixinGuiContainer extends GuiScreen {
public void drawSlot(Slot slot, CallbackInfo ci) {
if(slot == null) return;
+ if(slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 100 + Minecraft.getMinecraft().getRenderItem().zLevel);
+ GlStateManager.depthMask(false);
+ Gui.drawRect(slot.xDisplayPosition, slot.yDisplayPosition,
+ slot.xDisplayPosition+16, slot.yDisplayPosition+16, NEUOverlay.overlayColourDark);
+ GlStateManager.depthMask(true);
+ GlStateManager.popMatrix();
+ }
+
GuiContainer $this = (GuiContainer)(Object)this;
ItemStack stack = slot.getStack();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java
new file mode 100644
index 00000000..9a5d739e
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java
@@ -0,0 +1,22 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.NEUEventListener;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import net.minecraft.client.gui.inventory.GuiInventory;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(GuiInventory.class)
+public class MixinGuiInventory {
+
+ @Inject(method="drawGuiContainerForegroundLayer", at=@At("HEAD"), cancellable = true)
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY, CallbackInfo ci) {
+ if(NotEnoughUpdates.INSTANCE.config.inventoryButtons.hideCrafting ||
+ NEUEventListener.disableCraftingText) {
+ ci.cancel();
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
index c20ccebe..239dbe93 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
@@ -28,6 +28,10 @@ public class MixinItemStack {
@Inject(method="getDisplayName",at=@At("HEAD"), cancellable=true)
public void getDisplayName(CallbackInfoReturnable<String> returnable) {
try {
+ if(stackTagCompound == null || !stackTagCompound.hasKey("ExtraAttributes", 10)) {
+ return;
+ }
+
String customName = NotEnoughUpdates.INSTANCE.manager.itemRenameJson
.get(stackTagCompound.getCompoundTag("ExtraAttributes").getString("uuid")).getAsString();
if(customName != null && !customName.equals("")) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCreeperCharge.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCreeperCharge.java
deleted file mode 100644
index e6c9f048..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCreeperCharge.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package io.github.moulberry.notenoughupdates.mixins;
-
-import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.entity.layers.LayerCreeperCharge;
-import net.minecraft.entity.monster.EntityCreeper;
-import org.lwjgl.util.vector.Vector3f;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.Redirect;
-
-@Mixin(LayerCreeperCharge.class)
-public class MixinLayerCreeperCharge {
-
- /*@Redirect(method="doRenderLayer", at=@At(
- value = "INVOKE",
- target = "Lnet/minecraft/client/renderer/GlStateManager;color(FFFF)V"))
- public void doRenderLayer_color(float red, float green, float blue, float alpha) {
- Vector3f col = MiningStuff.getCreeperColour();
- GlStateManager.color(col.getX(), col.getY(), col.getZ(), alpha);
- }*/
-
-
-
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
index f20a5557..7f88b369 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
@@ -31,7 +31,7 @@ public class MixinNetHandlerPlayClient {
@Inject(method="handleSetSlot", at=@At("HEAD"))
public void handleSetSlot(S2FPacketSetSlot packetIn, CallbackInfo ci) {
- EnchantingSolvers.processInventoryContents();
+ EnchantingSolvers.processInventoryContents(false);
}
@Inject(method="handleBlockChange", at=@At("HEAD"))
@@ -45,13 +45,13 @@ public class MixinNetHandlerPlayClient {
FlyFix.onReceiveAbilities(packetIn);
}
- @Inject(method="addToSendQueue", at=@At("HEAD"))
+ /*@Inject(method="addToSendQueue", at=@At("HEAD"))
public void addToSendQueue(Packet packet, CallbackInfo ci) {
if(packet instanceof C13PacketPlayerAbilities) {
C13PacketPlayerAbilities abilities = (C13PacketPlayerAbilities) packet;
FlyFix.onSendAbilities(abilities);
}
- }
+ }*/
@Inject(method="handlePlayerListHeaderFooter", at=@At("HEAD"))
public void handlePlayerListHeaderFooter(S47PacketPlayerListHeaderFooter packetIn, CallbackInfo ci) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
index 2183e437..308dc779 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
@@ -20,10 +20,10 @@ public class MixinPlayerControllerMP {
@Inject(method="clickBlock", at=@At("HEAD"), cancellable = true)
public void clickBlock(BlockPos loc, EnumFacing face, CallbackInfoReturnable<Boolean> cir) {
ItemCooldowns.blockClicked(loc);
- if(MiningStuff.blockClicked(loc)) {
+ /*if(MiningStuff.blockClicked(loc)) {
cir.setReturnValue(false);
((PlayerControllerMP)(Object)this).resetBlockRemoving();
- }
+ }*/
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
index afd44fd3..5fcb6e84 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
@@ -1,13 +1,20 @@
package io.github.moulberry.notenoughupdates.mixins;
+import io.github.moulberry.notenoughupdates.NEUEventListener;
+import io.github.moulberry.notenoughupdates.NEUOverlay;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemRarityHalo;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiTextField;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.item.ItemStack;
import org.lwjgl.input.Keyboard;
import org.spongepowered.asm.mixin.Mixin;
@@ -17,6 +24,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import java.awt.*;
+
@Mixin({RenderItem.class})
public abstract class MixinRenderItem {
@@ -34,8 +43,81 @@ public abstract class MixinRenderItem {
Tessellator.getInstance().draw();
}
+ @Inject(method="renderItemIntoGUI", at=@At("HEAD"))
+ public void renderItemHead(ItemStack stack, int x, int y, CallbackInfo ci) {
+ if(NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ boolean matches = false;
+
+ GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField();
+
+ if(textField.getText().trim().isEmpty()) {
+ matches = true;
+ } else if(stack != null) {
+ for(String search : textField.getText().split("\\|")) {
+ matches |= NotEnoughUpdates.INSTANCE.manager.doesStackMatchSearch(stack, search.trim());
+ }
+ }
+ if(matches) {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 100 + Minecraft.getMinecraft().getRenderItem().zLevel);
+ GlStateManager.depthMask(false);
+ Gui.drawRect(x, y, x+16, y+16, NEUOverlay.overlayColourLight);
+ GlStateManager.depthMask(true);
+ GlStateManager.popMatrix();
+ }
+ }
+ }
+
+ @Inject(method="renderItemIntoGUI", at=@At("RETURN"))
+ public void renderItemReturn(ItemStack stack, int x, int y, CallbackInfo ci) {
+ if(stack != null && stack.stackSize != 1) return;
+ if(NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ boolean matches = false;
+
+ GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField();
+
+ if(textField.getText().trim().isEmpty()) {
+ matches = true;
+ } else if(stack != null) {
+ for(String search : textField.getText().split("\\|")) {
+ matches |= NotEnoughUpdates.INSTANCE.manager.doesStackMatchSearch(stack, search.trim());
+ }
+ }
+ if(!matches) {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 110 + Minecraft.getMinecraft().getRenderItem().zLevel);
+ Gui.drawRect(x, y, x+16, y+16, NEUOverlay.overlayColourDark);
+ GlStateManager.popMatrix();
+ }
+ }
+ }
+
@Inject(method="renderItemOverlayIntoGUI", at=@At("RETURN"))
public void renderItemOverlayIntoGUI(FontRenderer fr, ItemStack stack, int xPosition, int yPosition, String text, CallbackInfo ci) {
+ if(stack != null && stack.stackSize != 1) {
+ if(NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ boolean matches = false;
+
+ GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField();
+
+ if(textField.getText().trim().isEmpty()) {
+ matches = true;
+ } else {
+ for(String search : textField.getText().split("\\|")) {
+ matches |= NotEnoughUpdates.INSTANCE.manager.doesStackMatchSearch(stack, search.trim());
+ }
+ }
+ if(!matches) {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 110 + Minecraft.getMinecraft().getRenderItem().zLevel);
+ GlStateManager.disableDepth();
+ Gui.drawRect(xPosition, yPosition, xPosition+16, yPosition+16, NEUOverlay.overlayColourDark);
+ GlStateManager.enableDepth();
+ GlStateManager.popMatrix();
+ }
+ }
+ }
+
if(stack == null) return;
float damageOverride = ItemCooldowns.getDurabilityOverride(stack);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
index 6e2f2dfd..b3850112 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
@@ -8,6 +8,8 @@ import io.github.moulberry.notenoughupdates.core.config.Config;
import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.core.config.annotations.*;
import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor;
+import io.github.moulberry.notenoughupdates.miscgui.GuiInvButtonEditor;
+import io.github.moulberry.notenoughupdates.miscgui.NEUOverlayPlacements;
import io.github.moulberry.notenoughupdates.overlays.*;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import net.minecraft.client.Minecraft;
@@ -70,6 +72,12 @@ public class NEUConfig extends Config {
case 5:
editOverlay(activeConfigCategory, OverlayManager.timersOverlay, miscOverlays.todoPosition);
return;
+ case 6:
+ NotEnoughUpdates.INSTANCE.openGui = new NEUOverlayPlacements();
+ return;
+ case 7:
+ NotEnoughUpdates.INSTANCE.openGui = new GuiInvButtonEditor();
+ return;
}
}
@@ -104,6 +112,13 @@ public class NEUConfig extends Config {
@Expose
@Category(
+ name = "Inventory Buttons",
+ desc = "Inventory Buttons"
+ )
+ public InventoryButtons inventoryButtons = new InventoryButtons();
+
+ @Expose
+ @Category(
name = "Tooltip Tweaks",
desc = "Tooltip Tweaks"
)
@@ -394,6 +409,14 @@ public class NEUConfig extends Config {
public static class Toolbar {
@Expose
@ConfigOption(
+ name = "Edit Toolbar Positions",
+ desc = "Edit the position of the QuickCommands / Search Bar"
+ )
+ @ConfigEditorButton(runnableId = 6, buttonText = "Edit")
+ public boolean positionButton = true;
+
+ @Expose
+ @ConfigOption(
name = "Show Quick Commands",
desc = "Show QuickCommands\u2122 in the NEU toolbar"
)
@@ -443,6 +466,34 @@ public class NEUConfig extends Config {
public int quickCommandsClickType = 0;
}
+ public static class InventoryButtons {
+ @Expose
+ @ConfigOption(
+ name = "Open Button Editor",
+ desc = "Open button editor GUI (/neubuttons)"
+ )
+ @ConfigEditorButton(runnableId = 7, buttonText = "Open")
+ public boolean openEditorButton = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Always Hide \"Crafting\" Text",
+ desc = "Hide crafting text in inventory, even when no button is there"
+ )
+ @ConfigEditorBoolean
+ public boolean hideCrafting = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Button Click Type",
+ desc = "Change the click type needed to trigger commands"
+ )
+ @ConfigEditorDropdown(
+ values = {"Mouse Down", "Mouse Up"}
+ )
+ public int clickType = 0;
+ }
+
public static class TooltipTweaks {
@ConfigOption(
name = "Tooltip Price Information",
@@ -1035,24 +1086,25 @@ public class NEUConfig extends Config {
)
@ConfigAccordionId(id = 0)
public int todoStyle = 0;
- }
- public static class EnchSolvers {
@Expose
@ConfigOption(
- name = "Enable Solvers",
- desc = "Turn on solvers for the experimentation table"
+ name = "Todo Icons",
+ desc = "Add little item icons next to the lines in the todo overlay"
)
@ConfigEditorBoolean
- public boolean enableEnchantingSolvers = true;
+ @ConfigAccordionId(id = 0)
+ public boolean todoIcons = true;
+ }
+ public static class EnchSolvers {
@Expose
@ConfigOption(
- name = "Prevent Misclicks",
- desc = "Prevent accidentally failing the Chronomatron and Ultrasequencer experiments"
+ name = "Enable Solvers",
+ desc = "Turn on solvers for the experimentation table"
)
@ConfigEditorBoolean
- public boolean preventMisclicks = true;
+ public boolean enableEnchantingSolvers = true;
@Expose
@ConfigOption(
@@ -1282,21 +1334,6 @@ public class NEUConfig extends Config {
@ConfigEditorBoolean
public boolean titaniumAlert = true;
- @Expose
- @ConfigOption(
- name = "Don't Mine Stone",
- desc = "Prevent mining stone blocks in mining areas"
- )
- @ConfigEditorBoolean
- public boolean dontMineStone = true;
-
- @Expose
- @ConfigOption(
- name = "Reveal Mist Creepers",
- desc = "Make the creepers in the Dwarven Mines mist visible"
- )
- @ConfigEditorBoolean
- public boolean revealMistCreepers = true;
}
public static class NeuAuctionHouse {
@@ -1502,6 +1539,14 @@ public class NEUConfig extends Config {
values = {"Background", "No Shadow", "Shadow Only", "Full Shadow"}
)
public int petInfoOverlayStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Last Pet",
+ desc = "Show 2 pets on the overlay\nUseful if training two pets at once with autopet"
+ )
+ @ConfigEditorBoolean
+ public boolean dualPets = false;
}
public static class AuctionHouseSearch {
@@ -1594,6 +1639,7 @@ public class NEUConfig extends Config {
public static class Hidden {
@Expose public HashMap<String, HiddenProfileSpecific> profileSpecific = new HashMap<>();
+ @Expose public List<InventoryButton> inventoryButtons = createDefaultInventoryButtons();
@Expose public boolean enableItemEditing = false;
@Expose public boolean cacheRenderedItempane = true;
@@ -1620,6 +1666,95 @@ public class NEUConfig extends Config {
"Looting:\u003e:3:5:0");
}
+ public static List<InventoryButton> createDefaultInventoryButtons() {
+ List<InventoryButton> buttons = new ArrayList<>();
+ //Below crafting
+ buttons.add(new InventoryButton(87, 63, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+21, 63, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+21*2, 63, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+21*3, 63, null, true, false, false, 0, ""));
+
+ //Above crafting
+ buttons.add(new InventoryButton(87, 5, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+21, 5, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+21*2, 5, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+21*3, 5, null, true, false, false, 0, ""));
+
+ //Crafting square
+ buttons.add(new InventoryButton(87, 25, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+18, 25, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87, 25+18, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(87+18, 25+18, null, true, false, false, 0, ""));
+
+ //Crafting result
+ buttons.add(new InventoryButton(143, 35, null, true, false, false, 0, ""));
+
+ //Player menu area
+ buttons.add(new InventoryButton(60, 8, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(60, 60, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(26, 8, null, true, false, false, 0, ""));
+ buttons.add(new InventoryButton(26, 60, null, true, false, false, 0, ""));
+
+ //Right side
+ for(int i=0; i<8; i++) {
+ int y = 2+20*i;
+ if(y < 80) {
+ buttons.add(new InventoryButton(2, 2+20*i, null, false, true, false, 0, ""));
+ } else {
+ buttons.add(new InventoryButton(2, 2+20*i-166, null, false, true, true, 0, ""));
+ }
+ }
+
+ //Top side
+ for(int i=0; i<8; i++) {
+ buttons.add(new InventoryButton(4+21*i, -19, null, false, false, false, 0, ""));
+ }
+
+ //Left side
+ for(int i=0; i<8; i++) {
+ int y = 2+20*i;
+ if(y < 80) {
+ buttons.add(new InventoryButton(-19, 2+20*i, null, false, false, false, 0, ""));
+ } else {
+ buttons.add(new InventoryButton(-19, 2+20*i-166, null, false, false, true, 0, ""));
+ }
+ }
+
+ //Bottom side
+ for(int i=0; i<8; i++) {
+ buttons.add(new InventoryButton(4+21*i, 2, null, false, false, true, 0, ""));
+ }
+ return buttons;
+ }
+
+ public static class InventoryButton {
+ @Expose public int x;
+ @Expose public int y;
+ @Expose public boolean playerInvOnly;
+
+ @Expose public boolean anchorRight;
+ @Expose public boolean anchorBottom;
+
+ @Expose public int backgroundIndex;
+ @Expose public String command;
+ @Expose public String icon;
+
+ public boolean isActive() {
+ return command.trim().length() > 0;
+ }
+
+ public InventoryButton(int x, int y, String icon, boolean playerInvOnly, boolean anchorRight, boolean anchorBottom, int backgroundIndex, String command) {
+ this.x = x;
+ this.y = y;
+ this.icon = icon;
+ this.playerInvOnly = playerInvOnly;
+ this.anchorRight = anchorRight;
+ this.anchorBottom = anchorBottom;
+ this.backgroundIndex = backgroundIndex;
+ this.command = command;
+ }
+ }
+
public static class DungeonMap {
@Expose
@ConfigOption(
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java
index da2b9bee..d4132f76 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java
@@ -103,6 +103,11 @@ public class TimersOverlay extends TextOverlay {
@Override
protected void renderLine(String line, Vector2f position, boolean dummy) {
+ if(!NotEnoughUpdates.INSTANCE.config.miscOverlays.todoIcons) {
+ return;
+ }
+ GlStateManager.enableDepth();
+
ItemStack icon = null;
String clean = Utils.cleanColour(line);
@@ -115,7 +120,7 @@ public class TimersOverlay extends TextOverlay {
if(FETCHUR_ICONS == null) {
FETCHUR_ICONS = new ItemStack[] {
new ItemStack(Blocks.wool, 50, 14),
- new ItemStack(Blocks.glass, 20, 4),
+ new ItemStack(Blocks.stained_glass, 20, 4),
new ItemStack(Items.compass, 1, 0),
new ItemStack(Items.prismarine_crystals, 20, 0),
new ItemStack(Items.fireworks, 1, 0),
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
index 4a9a9257..13ada4bf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
@@ -840,7 +840,7 @@ public class GuiProfileViewer extends GuiScreen {
Utils.renderAlignedString(EnumChatFormatting.YELLOW+"Secrets (Total) ",
EnumChatFormatting.WHITE.toString()+shortNumberFormat(secrets, 0), x, miscTopY+20, sectionWidth);
Utils.renderAlignedString(EnumChatFormatting.YELLOW+"Secrets (/Run) ",
- EnumChatFormatting.WHITE.toString()+(Math.round(secrets/Math.max(1, totalRunsF5)*100)/100f), x, miscTopY+30, sectionWidth);
+ EnumChatFormatting.WHITE.toString()+(Math.round(secrets/Math.max(1, totalRuns)*100)/100f), x, miscTopY+30, sectionWidth);
Utils.renderAlignedString(EnumChatFormatting.YELLOW+"Mob Kills (Total) ",
EnumChatFormatting.WHITE.toString()+shortNumberFormat(mobKills, 0), x, miscTopY+40, sectionWidth);
@@ -2528,7 +2528,6 @@ public class GuiProfileViewer extends GuiScreen {
Arrays.fill(entityPlayer.inventory.armorInventory, null);
}
}
- System.out.println(entityPlayer.getUniqueID().toString());
if(entityPlayer.getUniqueID().toString().equals("ae6193ab-494a-4719-b6e7-d50392c8f012")) {
entityPlayer.inventory.armorInventory[3] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("SMALL_BACKPACK"));
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 c61a0914..b2b19189 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
@@ -398,7 +398,7 @@ public class ProfileViewer {
JsonObject bzInfo2 = manager.auctionManager.getBazaarInfo(internalname2);
int auctionPrice2;
- if(bzInfo2 != null && bzInfo.has("curr_sell")) {
+ if(bzInfo2 != null && bzInfo2.has("curr_sell")) {
auctionPrice2 = (int)bzInfo2.get("curr_sell").getAsFloat();
} else {
auctionPrice2 = (int)manager.auctionManager.getItemAvgBin(internalname2);
diff --git a/src/main/resources/assets/notenoughupdates/capes/alexxoffi.png b/src/main/resources/assets/notenoughupdates/capes/alexxoffi.png
new file mode 100644
index 00000000..dd81d641
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/alexxoffi.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/alexxoffi_preview.png b/src/main/resources/assets/notenoughupdates/capes/alexxoffi_preview.png
new file mode 100644
index 00000000..146e487f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/alexxoffi_preview.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/dsm.png b/src/main/resources/assets/notenoughupdates/capes/dsm.png
index 0b691c9c..c452db0d 100644
--- a/src/main/resources/assets/notenoughupdates/capes/dsm.png
+++ b/src/main/resources/assets/notenoughupdates/capes/dsm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/dsm_preview.png b/src/main/resources/assets/notenoughupdates/capes/dsm_preview.png
new file mode 100644
index 00000000..7589e2a9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/dsm_preview.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/furf.png b/src/main/resources/assets/notenoughupdates/capes/furf.png
index ce9f4c19..61f1e45a 100644
--- a/src/main/resources/assets/notenoughupdates/capes/furf.png
+++ b/src/main/resources/assets/notenoughupdates/capes/furf.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/furf_preview.png b/src/main/resources/assets/notenoughupdates/capes/furf_preview.png
index a4ee6851..c2a2a106 100644
--- a/src/main/resources/assets/notenoughupdates/capes/furf_preview.png
+++ b/src/main/resources/assets/notenoughupdates/capes/furf_preview.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/jakethybro.png b/src/main/resources/assets/notenoughupdates/capes/jakethybro.png
new file mode 100644
index 00000000..3e957503
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/jakethybro.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/jakethybro_preview.png b/src/main/resources/assets/notenoughupdates/capes/jakethybro_preview.png
new file mode 100644
index 00000000..96483e98
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/jakethybro_preview.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/parallax.png b/src/main/resources/assets/notenoughupdates/capes/parallax.png
new file mode 100644
index 00000000..b7b4a027
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/parallax.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/zera.png b/src/main/resources/assets/notenoughupdates/capes/zera.png
new file mode 100644
index 00000000..74121976
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/zera.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/zera_preview.png b/src/main/resources/assets/notenoughupdates/capes/zera_preview.png
new file mode 100644
index 00000000..684cbd9e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/zera_preview.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/editor.png b/src/main/resources/assets/notenoughupdates/invbuttons/editor.png
new file mode 100644
index 00000000..0d58e0c9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/editor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/expanded_inventory.png b/src/main/resources/assets/notenoughupdates/invbuttons/expanded_inventory.png
new file mode 100644
index 00000000..d941fa6e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/expanded_inventory.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons.json b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons.json
new file mode 100644
index 00000000..5a99f3f0
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons.json
@@ -0,0 +1,18 @@
+{
+ "baubles ring": "baubles",
+ "baubles gold ring": "baubles_gold",
+ "cross x": "cross",
+ "green check mark": "green_check",
+ "white check mark": "white_check",
+ "question mark help": "question",
+ "settings cog config": "settings",
+ "accessory ring": "accessory",
+ "accessory ring gold": "accessory_gold",
+ "armor chestplate": "armor",
+ "armor gold chestplate": "armor_gold",
+ "pet cat": "pet",
+ "pet cat gold": "pet_gold",
+ "skyblock menu": "skyblock_menu",
+ "recipe book": "recipe",
+ "search glass": "search"
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory.png
new file mode 100644
index 00000000..867b00fd
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory_gold.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory_gold.png
new file mode 100644
index 00000000..70f8558a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/accessory_gold.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor.png
new file mode 100644
index 00000000..69edc534
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor_gold.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor_gold.png
new file mode 100644
index 00000000..ee606367
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/armor_gold.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles.png
new file mode 100644
index 00000000..9c1f5035
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles_gold.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles_gold.png
new file mode 100644
index 00000000..963ce85d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/baubles_gold.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/cross.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/cross.png
new file mode 100644
index 00000000..6ee727a6
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/cross.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/green_check.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/green_check.png
new file mode 100644
index 00000000..5c5ffb45
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/green_check.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet.png
new file mode 100644
index 00000000..9aebf1fd
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet_gold.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet_gold.png
new file mode 100644
index 00000000..f86e367a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/pet_gold.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/question.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/question.png
new file mode 100644
index 00000000..3f9fe254
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/question.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/recipe.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/recipe.png
new file mode 100644
index 00000000..4eaca5c8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/recipe.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/search.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/search.png
new file mode 100644
index 00000000..70a0476e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/search.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/settings.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/settings.png
new file mode 100644
index 00000000..481a0588
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/settings.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/skyblock_menu.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/skyblock_menu.png
new file mode 100644
index 00000000..c0f62308
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/skyblock_menu.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/white_check.png b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/white_check.png
new file mode 100644
index 00000000..d646e498
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/extraicons/white_check.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/invbuttons/presets.json b/src/main/resources/assets/notenoughupdates/invbuttons/presets.json
new file mode 100644
index 00000000..7692fc07
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/invbuttons/presets.json
@@ -0,0 +1,2729 @@
+{
+ "Empty":[
+ {
+ "x":87,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":108,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":129,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":150,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":87,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":108,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":129,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":150,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":143,
+ "y":35,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":60,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":60,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":2,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ }
+ ],
+ "Empty (Dark)":[
+ {
+ "x":87,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":108,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":129,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":150,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":87,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":108,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":129,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":150,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":143,
+ "y":35,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":60,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":60,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":2,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":1,
+ "command":""
+ }
+ ],
+ "Simple":[
+ {
+ "x":87,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/warp home",
+ "icon":"skull:c9c8881e42915a9d29bb61a16fb26d059913204d265df5b439b3d792acd56"
+ },
+ {
+ "x":108,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/warp hub",
+ "icon":"skull:d7cc6687423d0570d556ac53e0676cb563bbdd9717cd8269bdebed6f6d4e7bf8"
+ },
+ {
+ "x":129,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/enderchest",
+ "icon":"ENDER_CHEST"
+ },
+ {
+ "x":150,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/pets",
+ "icon":"extra:pet_gold"
+ },
+ {
+ "x":87,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":108,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":129,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":150,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":143,
+ "y":35,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":60,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":2,
+ "command":"/wardrobe",
+ "icon":"extra:baubles_gold"
+ },
+ {
+ "x":60,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":"BONE"
+ },
+ {
+ "x":2,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ }
+ ],
+ "All Warps":[
+ {
+ "x":87,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"pets",
+ "icon":"extra:pet_gold"
+ },
+ {
+ "x":108,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/wardrobe",
+ "icon":"extra:armor"
+ },
+ {
+ "x":129,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/enderchest",
+ "icon":"ENDER_CHEST"
+ },
+ {
+ "x":150,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"hotm",
+ "icon":"skull:86f06eaa3004aeed09b3d5b45d976de584e691c0e9cade133635de93d23b9edb"
+ },
+ {
+ "x":87,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":"GOLD_BLOCK"
+ },
+ {
+ "x":108,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":129,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":150,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/pv",
+ "icon":"PAINTING"
+ },
+ {
+ "x":87,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":143,
+ "y":35,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":60,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":"extra:baubles_gold"
+ },
+ {
+ "x":60,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/ah",
+ "icon":"GOLD_BLOCK"
+ },
+ {
+ "x":2,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/bz",
+ "icon":"GOLD_BARDING"
+ },
+ {
+ "x":2,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp home",
+ "icon":"skull:c9c8881e42915a9d29bb61a16fb26d059913204d265df5b439b3d792acd56"
+ },
+ {
+ "x":2,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp hub",
+ "icon":"skull:d7cc6687423d0570d556ac53e0676cb563bbdd9717cd8269bdebed6f6d4e7bf8"
+ },
+ {
+ "x":2,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp dungeon_hub",
+ "icon":"skull:9b56895b9659896ad647f58599238af532d46db9c1b0389b8bbeb70999dab33d"
+ },
+ {
+ "x":2,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp end",
+ "icon":"skull:7840b87d52271d2a755dedc82877e0ed3df67dcc42ea479ec146176b02779a5"
+ },
+ {
+ "x":4,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp barn",
+ "icon":"skull:4d3a6bd98ac1833c664c4909ff8d2dc62ce887bdcf3cc5b3848651ae5af6b"
+ },
+ {
+ "x":25,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp desert",
+ "icon":"skull:2116b9d8df346a25edd05f842e7a9345beaf16dca4118abf5a68c75bcaae10"
+ },
+ {
+ "x":46,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp gold",
+ "icon":"skull:73bc965d579c3c6039f0a17eb7c2e6faf538c7a5de8e60ec7a719360d0a857a9"
+ },
+ {
+ "x":67,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp deep",
+ "icon":"skull:569a1f114151b4521373f34bc14c2963a5011cdc25a6554c48c708cd96ebfc"
+ },
+ {
+ "x":88,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp mines",
+ "icon":"skull:c754318a3376f470e481dfcd6c83a59aa690ad4b4dd7577fdad1c2ef08d8aee6"
+ },
+ {
+ "x":109,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp park",
+ "icon":"skull:a221f813dacee0fef8c59f76894dbb26415478d9ddfc44c2e708a6d3b7549b"
+ },
+ {
+ "x":130,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp spider",
+ "icon":"skull:9d7e3b19ac4f3dee9c5677c135333b9d35a7f568b63d1ef4ada4b068b5a25"
+ },
+ {
+ "x":151,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/warp nether",
+ "icon":"skull:38957d5023c937c4c41aa2412d43410bda23cf79a9f6ab36b76fef2d7c429"
+ }
+ ],
+ "More Buttons":[
+ {
+ "x":87,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/sbmenu",
+ "icon":"SKYBLOCK_MENU"
+ },
+ {
+ "x":108,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"enderchest",
+ "icon":"ENDER_CHEST"
+ },
+ {
+ "x":129,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"pets",
+ "icon":"BONE"
+ },
+ {
+ "x":150,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"effects",
+ "icon":"POTION"
+ },
+ {
+ "x":87,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/recipes",
+ "icon":"extra:recipe"
+ },
+ {
+ "x":108,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/collections",
+ "icon":"PAINTING"
+ },
+ {
+ "x":129,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/scg",
+ "icon":"BOOK"
+ },
+ {
+ "x":150,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/calendar",
+ "icon":"BOOK_AND_QUILL"
+ },
+ {
+ "x":87,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":"CHEST"
+ },
+ {
+ "x":105,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":143,
+ "y":35,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"craft",
+ "icon":"WORKBENCH"
+ },
+ {
+ "x":60,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":2,
+ "command":"/wardrobe",
+ "icon":"extra:baubles_gold"
+ },
+ {
+ "x":60,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/warp hub",
+ "icon":"skull:d7cc6687423d0570d556ac53e0676cb563bbdd9717cd8269bdebed6f6d4e7bf8"
+ },
+ {
+ "x":2,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/warp home",
+ "icon":"skull:c9c8881e42915a9d29bb61a16fb26d059913204d265df5b439b3d792acd56"
+ },
+ {
+ "x":2,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":2,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":"BONE"
+ },
+ {
+ "x":2,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/ah",
+ "icon":"GOLD_BLOCK"
+ },
+ {
+ "x":-19,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/bz",
+ "icon":"GOLD_BARDING"
+ },
+ {
+ "x":-19,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ }
+ ],
+ "Dungeons":[
+ {
+ "x":87,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"warp dungeon_hub",
+ "icon":"skull:9b56895b9659896ad647f58599238af532d46db9c1b0389b8bbeb70999dab33d"
+ },
+ {
+ "x":108,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"reparty",
+ "icon":"COMMAND"
+ },
+ {
+ "x":129,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"/p FragRunBot azael_mew azael_mewh",
+ "icon":"GIANT_FRAGMENT_DIAMOND"
+ },
+ {
+ "x":150,
+ "y":63,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"pets",
+ "icon":"extra:pet_gold"
+ },
+ {
+ "x":87,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":108,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":129,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":150,
+ "y":5,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":25,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":87,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":105,
+ "y":43,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":143,
+ "y":35,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":60,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":2,
+ "command":"/wardrobe",
+ "icon":"extra:baubles_gold"
+ },
+ {
+ "x":60,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":8,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":26,
+ "y":60,
+ "playerInvOnly":true,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"",
+ "icon":""
+ },
+ {
+ "x":2,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":2,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":true,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":-19,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":-19,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"joindungeon catacombs 1",
+ "icon":"GOLD_BONZO_HEAD"
+ },
+ {
+ "x":-19,
+ "y":22,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"joindungeon catacombs 2",
+ "icon":"GOLD_SCARF_HEAD"
+ },
+ {
+ "x":-19,
+ "y":42,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"joindungeon catacombs 3",
+ "icon":"GOLD_PROFESSOR_HEAD"
+ },
+ {
+ "x":-19,
+ "y":62,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":false,
+ "backgroundIndex":0,
+ "command":"joindungeon catacombs 4",
+ "icon":"GOLD_THORN_HEAD"
+ },
+ {
+ "x":-19,
+ "y":-84,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"joindungeon catacombs 5",
+ "icon":"GOLD_LIVID_HEAD"
+ },
+ {
+ "x":-19,
+ "y":-64,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"/joindungeon catacombs 6",
+ "icon":"GOLD_SADAN_HEAD"
+ },
+ {
+ "x":-19,
+ "y":-44,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":"joindungeons catacombs 7",
+ "icon":"GOLD_NECRON_HEAD"
+ },
+ {
+ "x":-19,
+ "y":-24,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":4,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":25,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":46,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":67,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":88,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":109,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":130,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ },
+ {
+ "x":151,
+ "y":2,
+ "playerInvOnly":false,
+ "anchorRight":false,
+ "anchorBottom":true,
+ "backgroundIndex":0,
+ "command":""
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/search_bar.png b/src/main/resources/assets/notenoughupdates/search_bar.png
new file mode 100644
index 00000000..c029ee85
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/search_bar.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/search_bar_gold.png b/src/main/resources/assets/notenoughupdates/search_bar_gold.png
new file mode 100644
index 00000000..481b4930
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/search_bar_gold.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.frag b/src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.frag
new file mode 100644
index 00000000..2c34682a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.frag
@@ -0,0 +1,185 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+varying vec3 passVertex;
+
+uniform sampler2D textureIn;
+uniform int millis;
+uniform int planetType;
+uniform vec3 sunVec;
+
+vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
+float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));}
+vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
+float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;}
+
+vec4 grad4(float j, vec4 ip){
+ const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
+ vec4 p,s;
+
+ p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
+ p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
+ s = vec4(lessThan(p, vec4(0.0)));
+ p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;
+
+ return p;
+}
+
+float snoise(vec4 v){
+ const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4
+ 0.309016994374947451); // (sqrt(5) - 1)/4 F4
+// First corner
+ vec4 i = floor(v + dot(v, C.yyyy) );
+ vec4 x0 = v - i + dot(i, C.xxxx);
+
+// Other corners
+
+// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
+ vec4 i0;
+
+ vec3 isX = step( x0.yzw, x0.xxx );
+ vec3 isYZ = step( x0.zww, x0.yyz );
+// i0.x = dot( isX, vec3( 1.0 ) );
+ i0.x = isX.x + isX.y + isX.z;
+ i0.yzw = 1.0 - isX;
+
+// i0.y += dot( isYZ.xy, vec2( 1.0 ) );
+ i0.y += isYZ.x + isYZ.y;
+ i0.zw += 1.0 - isYZ.xy;
+
+ i0.z += isYZ.z;
+ i0.w += 1.0 - isYZ.z;
+
+ // i0 now contains the unique values 0,1,2,3 in each channel
+ vec4 i3 = clamp( i0, 0.0, 1.0 );
+ vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
+ vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );
+
+ // x0 = x0 - 0.0 + 0.0 * C
+ vec4 x1 = x0 - i1 + 1.0 * C.xxxx;
+ vec4 x2 = x0 - i2 + 2.0 * C.xxxx;
+ vec4 x3 = x0 - i3 + 3.0 * C.xxxx;
+ vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;
+
+// Permutations
+ i = mod(i, 289.0);
+ float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);
+ vec4 j1 = permute( permute( permute( permute (
+ i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
+ + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
+ + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
+ + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));
+// Gradients
+// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)
+// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
+
+ vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;
+
+ vec4 p0 = grad4(j0, ip);
+ vec4 p1 = grad4(j1.x, ip);
+ vec4 p2 = grad4(j1.y, ip);
+ vec4 p3 = grad4(j1.z, ip);
+ vec4 p4 = grad4(j1.w, ip);
+
+// Normalise gradients
+ vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
+ p0 *= norm.x;
+ p1 *= norm.y;
+ p2 *= norm.z;
+ p3 *= norm.w;
+ p4 *= taylorInvSqrt(dot(p4,p4));
+
+// Mix contributions from the five corners
+ vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
+ vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);
+ m0 = m0 * m0;
+ m1 = m1 * m1;
+ return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
+ + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;
+
+}
+
+vec3 interp_hsv(vec3 one, vec3 two, float amount) {
+ return one + (two - one) * amount;
+}
+
+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 ocean_deep = vec3(245.0/365.0, 82.0/100.0, 67.0/100.0);
+vec3 ocean_shallow = vec3(220.0/365.0, 75.0/100.0, 67.0/100.0);
+vec3 land_low = vec3(93.0/365.0, 87.0/100.0, 86.0/100.0);
+vec3 land_med = vec3(135.0/365.0, 84.0/100.0, 82.0/100.0);
+vec3 land_high = vec3(40.0/365.0, 52.0/100.0, 82.0/100.0);
+
+vec3 gray_light = vec3(31.0/365.0, 38.0/100.0, 80.0/100.0);
+vec3 gray_dark = vec3(15.0/365.0, 50.0/100.0, 24.0/100.0);
+
+vec3 jupiter_light = vec3(31.0/365.0, 50.0/100.0, 80.0/100.0);
+vec3 jupiter_dark = vec3(15.0/365.0, 70.0/100.0, 24.0/100.0);
+
+void main() {
+ if(gl_TexCoord[0].s > 0.5f || gl_TexCoord[0].t > 0.5f) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ return;
+ }
+ vec2 uv = gl_TexCoord[0].st;
+
+ if(planetType == 0) {
+ float perlin = (snoise(vec4(passVertex.x*10.0, passVertex.y*10.0, passVertex.z*10.0, millis/1000.0))+1.0)/2.0;
+ float perlin2 = snoise(vec4(passVertex.x*2.0, passVertex.y*2.0, passVertex.z*2.0, millis/10000.0));
+
+ vec3 col1 = vec3(1, 0.1+perlin*0.6, 0);
+ vec3 col2 = vec3(perlin2*0.7);
+ vec3 colF = max(col1, col2);
+ gl_FragColor = vec4(colF,1.0);
+ return;
+ } else if(planetType == 1) {
+ float perlin = (snoise(vec4(passVertex.x*2.0, passVertex.y*2.0, passVertex.z*2.0, 0.0))+1.0)/2.0;
+ float perlin2 = snoise(vec4(passVertex.x*1.0, passVertex.y*1.0, passVertex.z*1.0, millis/10000.0));
+
+ vec3 col1 = vec3(0, 0, 1);
+ if(perlin < 0.55) {
+ col1 = hsv2rgb(interp_hsv(ocean_deep, ocean_shallow, perlin*perlin/0.55/0.55));
+ } else if(perlin < 0.9) {
+ col1 = hsv2rgb(interp_hsv(land_low, land_med, (perlin-0.55)/0.35));
+ } else {
+ col1 = hsv2rgb(interp_hsv(land_med, land_high, (perlin-0.9)/0.1));
+ }
+ vec3 col2 = vec3(perlin2*0.7);
+ vec3 colF = max(col1, col2);
+
+ gl_FragColor = vec4(colF,1.0);
+
+ gl_FragColor.rgb *= 1.2*max(0.35, dot(normalize(sunVec), normalize(passNormal)));
+
+ return;
+ } else if(planetType == 2) {
+ float perlin = (snoise(vec4(passVertex.x*10.0, passVertex.y*10.0, passVertex.z*10.0, 0.0))+1.0)/2.0;
+ gl_FragColor = vec4(hsv2rgb(interp_hsv(gray_light, gray_dark, perlin)), 1.0);
+
+ gl_FragColor.rgb *= 1.2*max(0.35, dot(normalize(sunVec), normalize(passNormal)));
+
+ return;
+ } else if(planetType == 3) {
+ float perlin = (snoise(vec4(passVertex.x*0.2, passVertex.y*10.0, passVertex.z*0.2, 0.0))+1.0)/2.0;
+ gl_FragColor = vec4(hsv2rgb(interp_hsv(jupiter_light, jupiter_dark, perlin)), 1.0);
+
+ gl_FragColor.rgb *= 1.2*max(0.35, dot(normalize(sunVec), normalize(passNormal)));
+
+ return;
+ } else if(planetType == 4) {
+ float perlin = (snoise(vec4(passVertex.x*0.2, passVertex.y*10.0, passVertex.z*0.2, 0.0))+1.0)/2.0;
+ gl_FragColor = vec4(hsv2rgb(interp_hsv(ocean_deep, ocean_shallow, perlin)), 1.0);
+
+ gl_FragColor.rgb *= 1.2*max(0.35, dot(normalize(sunVec), normalize(passNormal)));
+
+ return;
+ }
+
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.vert b/src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.vert
new file mode 100644
index 00000000..632a4f94
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/capes/planets/planets.vert
@@ -0,0 +1,14 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+varying vec3 passVertex;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ passColour = gl_Color;
+ passNormal = normalize(gl_Normal);
+ passVertex = vec3(gl_Vertex.x, gl_Vertex.y, gl_Vertex.z);
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.frag b/src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.frag
new file mode 100644
index 00000000..fa3455ce
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.frag
@@ -0,0 +1,50 @@
+#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);
+}
+
+void main()
+{
+ float num = 5.0;
+
+ vec2 uv = vec2(gl_TexCoord[0].s*1024.0/300.0, gl_TexCoord[0].t*1024.0/420.0);
+
+ float timeMod = mod(millis/1000.0/num, 1.0/num);
+
+ if(uv.x > 1.5 || uv.y > 1) {
+ vec3 rgb = hsv2rgb(vec3((-1.0/num-millis/1000.0/num+timeMod)/2.0, 0.6, 0.8)) * 1.4;
+ gl_FragColor = vec4(rgb, 1.0);
+ return;
+ }
+
+ float xDist = 1.0 - min(uv.x, 1.0 - uv.x)*2.0;
+ float yDist = 1.0 - min(uv.y, 1.0 - uv.y)*2.0;
+ //float a = 20.0;
+ //float edgeDist = 1.0 - pow(pow(xDist, a) + pow(yDist, a), 1.0/a);
+ float edgeDist = 1.0 - max(xDist, yDist);
+
+ edgeDist += 0.2;
+ edgeDist *= edgeDist;
+ edgeDist -= timeMod;
+
+ float factor = 1.0 - mod(edgeDist*num, 1.0);
+ factor *= factor*factor;
+ factor = 1.4 - factor;
+ factor = max(0.8, factor);
+
+ edgeDist = floor(edgeDist*num)/num;
+
+ vec3 rgb = hsv2rgb(vec3((edgeDist-millis/1000.0/num+timeMod)/2.0, 0.6, 0.8));
+
+ gl_FragColor = vec4(rgb*factor, 1.0);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.vert b/src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.vert
new file mode 100644
index 00000000..2b5c48f8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/capes/tunnel/tunnel.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
diff --git a/src/main/resources/mixins.notenoughupdates.json b/src/main/resources/mixins.notenoughupdates.json
index 3fc98025..f3ef20a6 100644
--- a/src/main/resources/mixins.notenoughupdates.json
+++ b/src/main/resources/mixins.notenoughupdates.json
@@ -21,12 +21,13 @@
"MixinContainer",
"MixinWorld",
"MixinPlayerControllerMP",
- "MixinLayerCreeperCharge",
"MixinEffectRenderer",
"MixinRendererLivingEntity",
"GuiEditSignAccessor",
"MixinGuiScreen",
"MixinTileEntitySkullRenderer",
- "MixinItemCameraTransforms"
+ "MixinItemCameraTransforms",
+ "GuiContainerAccessor",
+ "MixinGuiInventory"
]
} \ No newline at end of file