diff options
Diffstat (limited to 'src/main/java')
34 files changed, 2503 insertions, 1083 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java index 613ebe5f..200569df 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java @@ -1,89 +1,241 @@ package io.github.moulberry.notenoughupdates; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.util.TexLoc; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiCrafting; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraft.inventory.ContainerWorkbench; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; +import net.minecraft.inventory.SlotCrafting; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.Vector2f; +import org.lwjgl.util.vector.Vector3f; -public class GuiItemRecipe extends GuiCrafting { +import java.awt.*; +import java.io.IOException; +import java.util.List; - private ItemStack[] craftMatrix; - private JsonObject result; - private String text; - private String craftText = ""; +public class GuiItemRecipe extends GuiScreen { + + private static final ResourceLocation resourcePacksTexture = new ResourceLocation("textures/gui/resource_packs.png"); + private static final ResourceLocation craftingTableGuiTextures = new ResourceLocation("textures/gui/container/crafting_table.png"); + + private List<ItemStack[]> craftMatrices; + private List<JsonObject> results; + private int currentIndex = 0; + + private String title; private NEUManager manager; - public GuiItemRecipe(ItemStack[] craftMatrix, JsonObject result, String text, NEUManager manager) { - super(Minecraft.getMinecraft().thePlayer.inventory, Minecraft.getMinecraft().theWorld); - this.craftMatrix = craftMatrix; - this.result = result; - this.text = text; + private int guiLeft = 0; + private int guiTop = 0; + private int xSize = 176; + private int ySize = 166; + + public GuiItemRecipe(String title, List<ItemStack[]> craftMatrices, List<JsonObject> results, NEUManager manager) { + this.craftMatrices = craftMatrices; + this.results = results; this.manager = manager; + this.title = title; + } - setContents(); + private String getCraftText() { + if(results.get(currentIndex).has("crafttext")) { + return results.get(currentIndex).get("crafttext").getAsString(); + } else { + return ""; + } } - public void setContents() { - ContainerWorkbench cw = (ContainerWorkbench) this.inventorySlots; - for(int i=0; i<Math.min(craftMatrix.length, 9); i++) { - if(craftMatrix[i] == null) continue; - cw.craftMatrix.setInventorySlotContents(i, craftMatrix[i]); + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + drawDefaultBackground(); + + if(currentIndex < 0) { + currentIndex = 0; + } else if(currentIndex >= craftMatrices.size()) { + currentIndex = craftMatrices.size()-1; } - if(result.has("crafttext")) { - craftText = result.get("crafttext").getAsString(); + + FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj; + + this.guiLeft = (width - this.xSize) / 2; + this.guiTop = (height - this.ySize) / 2; + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(craftingTableGuiTextures); + this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize); + + List<String> tooltipToRender = null; + for(int index=0; index <= 45; index++) { + Vector2f pos = getPositionForIndex(index); + Utils.drawItemStack(getStackForIndex(index), (int)pos.x, (int)pos.y); + + if(mouseX > pos.x && mouseX < pos.x+16) { + if(mouseY > pos.y && mouseY < pos.y+16) { + ItemStack stack = getStackForIndex(index); + if(stack != null) { + tooltipToRender = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } + } } - cw.craftResult.setInventorySlotContents(0, manager.jsonToStack(result)); - } - protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { - setContents(); + if(craftMatrices.size() > 1) { + int guiX = mouseX - guiLeft; + int guiY = mouseY - guiTop; + + int buttonWidth = 7; + int buttonHeight = 11; + + boolean leftSelected = false; + boolean rightSelected = false; + + if(guiY > + 63 && guiY < + 63 + buttonHeight) { + if(guiX > + 110 && guiX < 110 + buttonWidth) { + leftSelected = true; + } else if(guiX > 147 && guiX < 147 + buttonWidth) { + rightSelected = true; + } + } - String t = text.equals("") ? I18n.format("container.crafting", new Object[0]) : text; + Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture); + //Left arrow + Utils.drawTexturedRect(guiLeft+110, guiTop+63, 7, 11, 34/256f, 48/256f, + 5/256f + (leftSelected ? 32/256f : 0), 27/256f + (leftSelected ? 32/256f : 0)); + //Right arrow + Utils.drawTexturedRect(guiLeft+147, guiTop+63, 7, 11, 10/256f, 24/256f, + 5/256f + (rightSelected ? 32/256f : 0), 27/256f + (rightSelected ? 32/256f : 0)); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); - Utils.drawStringScaledMaxWidth(t, fontRendererObj, 28, 6, t.contains("\u00a7"), xSize-38, 4210752); - this.fontRendererObj.drawString(I18n.format("container.inventory", new Object[0]), 8, this.ySize - 96 + 2, 4210752); + String str = (currentIndex+1)+"/"+craftMatrices.size(); + Utils.drawStringCenteredScaledMaxWidth(str, fontRendererObj, guiLeft+132, guiTop+69, + false, 24, Color.BLACK.getRGB()); + } - Utils.drawStringCenteredScaledMaxWidth(craftText, fontRendererObj, 132, 25, + Utils.drawStringCenteredScaledMaxWidth(getCraftText(), fontRendererObj, guiLeft+132, guiTop+25, false, 75, 4210752); + + Utils.drawStringScaledMaxWidth(title, fontRendererObj, guiLeft+28, guiTop+6, title.contains("\u00a7"), xSize-38, 4210752); + + if(tooltipToRender != null) { + Utils.drawHoveringText(tooltipToRender, mouseX, mouseY, width, height, -1, fontRendererObj); + } } - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + public ItemStack getStackForIndex(int index) { + if(index == 0) { + return manager.jsonToStack(results.get(currentIndex)); + } else if(index >= 1 && index <= 9) { + return craftMatrices.get(currentIndex)[index-1]; + } else { + return Minecraft.getMinecraft().thePlayer.inventory.getStackInSlot(index-10); + } } - protected void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType) { - ItemStack click = null; - if(slotId >= 1 && slotId <= 9) { - click = craftMatrix[slotId-1]; - } else if(slotId == 0) { - ContainerWorkbench cw = (ContainerWorkbench) this.inventorySlots; - click = cw.craftResult.getStackInSlot(0); + public Vector2f getPositionForIndex(int index) { + //0 = result + //1-9 = craft matrix + //10-18 = hotbar + //19-45 = player inv + + if(index == 0) { + return new Vector2f(guiLeft+124, guiTop+35); + } else if(index >= 1 && index <= 9) { + index -= 1; + int x = index % 3; + int y = index / 3; + return new Vector2f(guiLeft+30 + x*18, guiTop+17 + y * 18); + } else if(index >= 10 && index <= 18) { + index -= 10; + return new Vector2f(guiLeft+8 + index*18, guiTop+142); + } else if(index >= 19 && index <= 45) { + index -= 19; + int x = index % 9; + int y = index / 9; + return new Vector2f(guiLeft+8 + x*18, guiTop+84 + y*18); } - if(click != null) { - if(clickedButton == 0) { - manager.displayGuiItemRecipe(manager.getInternalNameForItem(click), ""); - } else if(clickedButton == 1) { - manager.displayGuiItemUsages(manager.getInternalNameForItem(click), ""); + return null; + } + + @Override + public void handleKeyboardInput() throws IOException { + super.handleKeyboardInput(); //TODO: r and u + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter()+256 : Keyboard.getEventKey(); + + for(int index=0; index <= 45; index++) { + Vector2f pos = getPositionForIndex(index); + if(mouseX > pos.x && mouseX < pos.x+16) { + if(mouseY > pos.y && mouseY < pos.y+16) { + ItemStack stack = getStackForIndex(index); + if(stack != null) { + if(keyPressed == manager.keybindViewRecipe.getKeyCode()) { + manager.displayGuiItemRecipe(manager.getInternalNameForItem(stack), ""); + } else if(keyPressed == manager.keybindViewUsages.getKeyCode()) { + manager.displayGuiItemUsages(manager.getInternalNameForItem(stack)); + } + } + return; + } } } } - /*public void handleMouseInput() throws IOException { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - int height = scaledresolution.getScaledHeight(); + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + + int guiX = mouseX - guiLeft; + int guiY = mouseY - guiTop; - int mouseX = Mouse.getX() / scaledresolution.getScaleFactor(); - int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor(); - if(mouseY > this.guiTop + this.ySize - 94 || mouseY < this.guiTop || - mouseX < this.guiLeft || mouseX > this.guiLeft+this.xSize) { - //Potentially allow mouse input in the future. For now this is still broken. - //super.handleMouseInput(); + int buttonWidth = 7; + int buttonHeight = 11; + + if(guiY > + 63 && guiY < + 63 + buttonHeight) { + if(guiX > + 110 && guiX < 110 + buttonWidth) { + currentIndex--; + Utils.playPressSound(); + return; + } else if(guiX > 147 && guiX < 147 + buttonWidth) { + currentIndex++; + Utils.playPressSound(); + return; + } } - }*/ - public void onCraftMatrixChanged(IInventory inventoryIn){} + for(int index=0; index <= 45; index++) { + Vector2f pos = getPositionForIndex(index); + if(mouseX > pos.x && mouseX < pos.x+16) { + if(mouseY > pos.y && mouseY < pos.y+16) { + ItemStack stack = getStackForIndex(index); + if(stack != null) { + if(mouseButton == 0) { + manager.displayGuiItemRecipe(manager.getInternalNameForItem(stack), ""); + } else if(mouseButton == 1) { + manager.displayGuiItemUsages(manager.getInternalNameForItem(stack)); + } + } + return; + } + } + } + } + } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java deleted file mode 100644 index a56293e9..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java +++ /dev/null @@ -1,170 +0,0 @@ -package io.github.moulberry.notenoughupdates; - -import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.util.TexLoc; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiCrafting; -import net.minecraft.client.resources.I18n; -import net.minecraft.inventory.ContainerWorkbench; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.Slot; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; - -import java.awt.*; -import java.io.IOException; -import java.util.List; - -public class GuiItemUsages extends GuiCrafting { - private static final ResourceLocation resourcePacksTexture = new ResourceLocation("textures/gui/resource_packs.png"); - - private List<ItemStack[]> craftMatrices; - private List<JsonObject> results; - private int currentIndex = 0; - - private String text; - private String craftText = ""; - private String collectionText = ""; - private NEUManager manager; - - private TexLoc left = new TexLoc(0, 0, Keyboard.KEY_N); - private TexLoc right = new TexLoc(0, 0, Keyboard.KEY_M); - - public GuiItemUsages(List<ItemStack[]> craftMatrices, List<JsonObject> results, String text, NEUManager manager) { - super(Minecraft.getMinecraft().thePlayer.inventory, Minecraft.getMinecraft().theWorld); - - this.craftMatrices = craftMatrices; - this.results = results; - this.text = text; - this.manager = manager; - - setIndex(0); - } - - private void setIndex(int index) { - if(index < 0 || index >= craftMatrices.size()) { - return; - } else { - currentIndex = index; - - ContainerWorkbench cw = (ContainerWorkbench) this.inventorySlots; - for(int i=0; i<Math.min(craftMatrices.get(currentIndex).length, 9); i++) { - cw.craftMatrix.setInventorySlotContents(i, craftMatrices.get(currentIndex)[i]); - } - if(results.get(currentIndex).has("crafttext")) { - craftText = results.get(currentIndex).get("crafttext").getAsString(); - } else { - craftText = ""; - } - cw.craftResult.setInventorySlotContents(0, manager.jsonToStack(results.get(currentIndex))); - } - } - - protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { - String t = "Crafting Usages"; - - setIndex(currentIndex); - - int guiX = mouseX - guiLeft; - int guiY = mouseY - guiTop; - - int buttonWidth = 7; - int buttonHeight = 11; - - boolean leftSelected = false; - boolean rightSelected = false; - - if(guiY > + 63 && guiY < + 63 + buttonHeight) { - if(guiX > + 110 && guiX < 110 + buttonWidth) { - leftSelected = true; - } else if(guiX > 147 && guiX < 147 + buttonWidth) { - rightSelected = true; - } - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture); - //Left arrow - Utils.drawTexturedRect(110, 63, 7, 11, 34/256f, 48/256f, - 5/256f + (leftSelected ? 32/256f : 0), 27/256f + (leftSelected ? 32/256f : 0)); - //Right arrow - Utils.drawTexturedRect(147, 63, 7, 11, 10/256f, 24/256f, - 5/256f + (rightSelected ? 32/256f : 0), 27/256f + (rightSelected ? 32/256f : 0)); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); - - String str = (currentIndex+1)+"/"+craftMatrices.size(); - Utils.drawStringCenteredScaledMaxWidth(str, fontRendererObj, 132, 69, - false, 24, Color.BLACK.getRGB()); - - - Utils.drawStringCenteredScaledMaxWidth(craftText, fontRendererObj, 132, 25, - false, 75, 4210752); - - - Utils.drawStringScaledMaxWidth(t, fontRendererObj, 28, 6, t.contains("\u00a7"), xSize-38, 4210752); - this.fontRendererObj.drawString(I18n.format("container.inventory", new Object[0]), 8, this.ySize - 96 + 2, 4210752); - } - - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - } - - @Override - public void handleKeyboardInput() throws IOException { - super.handleKeyboardInput(); //TODO: r and u - left.handleKeyboardInput(); - right.handleKeyboardInput(); - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - super.mouseClicked(mouseX, mouseY, mouseButton); - - int guiX = mouseX - guiLeft; - int guiY = mouseY - guiTop; - - int buttonWidth = 7; - int buttonHeight = 11; - - if(guiY > + 63 && guiY < + 63 + buttonHeight) { - if(guiX > + 110 && guiX < 110 + buttonWidth) { - setIndex(currentIndex-1); - } else if(guiX > 147 && guiX < 147 + buttonWidth) { - setIndex(currentIndex+1); - } - } - } - - protected void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType) { - ItemStack click = null; - if(slotId >= 1 && slotId <= 9) { - click = craftMatrices.get(currentIndex)[slotId-1]; - } else if(slotId == 0) { - ContainerWorkbench cw = (ContainerWorkbench) this.inventorySlots; - click = cw.craftResult.getStackInSlot(0); - } - if(click != null) { - if(clickedButton == 0) { - manager.displayGuiItemRecipe(manager.getInternalNameForItem(click), ""); - } else if(clickedButton == 1) { - manager.displayGuiItemUsages(manager.getInternalNameForItem(click), ""); - } - } - } - - /*public void handleMouseInput() throws IOException { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - int height = scaledresolution.getScaledHeight(); - - int mouseX = Mouse.getX() / scaledresolution.getScaleFactor(); - int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor(); - if(mouseY > this.guiTop + this.ySize - 94 || mouseY < this.guiTop || - mouseX < this.guiLeft || mouseX > this.guiLeft+this.xSize) { - //Potentially allow mouse input in the future. For now this is still broken. - //super.handleMouseInput(); - } - }*/ - - public void onCraftMatrixChanged(IInventory inventoryIn){} -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java index 573e20cf..1f87018b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java @@ -22,6 +22,9 @@ public class GuiTextures { public static final ResourceLocation slider_button = new ResourceLocation("notenoughupdates:slider_button.png"); public static final ResourceLocation item_mask = new ResourceLocation("notenoughupdates:item_mask.png"); + public static final ResourceLocation button_tex = new ResourceLocation("notenoughupdates:button.png"); + + public static final ResourceLocation dungeon_chest_worth = new ResourceLocation("notenoughupdates:dungeon_chest_worth.png"); public static final ResourceLocation auction_view = new ResourceLocation("notenoughupdates:auction_view.png"); public static final ResourceLocation auction_accept = new ResourceLocation("notenoughupdates:auction_accept.png"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java index d2190425..b9f086a4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java @@ -74,13 +74,10 @@ public class NEUIO { GHRepository repo = github.getRepositoryById("247692460"); for(GHTreeEntry treeEntry : repo.getTreeRecursive("master", 1).getTree()) { - if(treeEntry.getPath().startsWith("items/")) { - String[] split = treeEntry.getPath().split("/"); - String name = split[split.length-1]; - - String oldSha = oldShas.get(name); + if(treeEntry.getPath().contains(".")) { + String oldSha = oldShas.get(treeEntry.getPath()); if(!treeEntry.getSha().equals(oldSha)) { - changedFiles.put(name, treeEntry.getSha()); + changedFiles.put(treeEntry.getPath(), treeEntry.getSha()); } } } @@ -109,22 +106,4 @@ public class NEUIO { removedItems.removeAll(repoItems); return removedItems; } - - /** - * Takes set of filename (eg. BOW.json) and returns map from that filename to the individual download link. - */ - public Map<String, String> getItemsDownload(Set<String> filename) { - HashMap<String, String> downloadUrls = new HashMap<>(); - try { - GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build(); - GHRepository repo = github.getRepositoryById("247692460"); - - for(GHContent content : repo.getDirectoryContent("items")) { - if(filename.contains(content.getName())) { - downloadUrls.put(content.getName(), content.getDownloadUrl()); - } - } - } catch(IOException e) { } - return downloadUrls; - } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 77d3be7f..8d625c14 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -1,14 +1,15 @@ package io.github.moulberry.notenoughupdates; +import com.google.common.collect.Lists; import com.google.gson.*; -import io.github.moulberry.notenoughupdates.auction.AuctionManager; -import io.github.moulberry.notenoughupdates.auction.CustomAH; +import io.github.moulberry.notenoughupdates.auction.APIManager; +import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.options.Options; import io.github.moulberry.notenoughupdates.util.HypixelApi; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; import net.minecraft.init.Blocks; -import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.*; @@ -22,10 +23,6 @@ import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -35,7 +32,7 @@ public class NEUManager { private final NotEnoughUpdates neu; public final NEUIO neuio; public final Gson gson; - public final AuctionManager auctionManager; + public final APIManager auctionManager; private TreeMap<String, JsonObject> itemMap = new TreeMap<>(); @@ -53,7 +50,8 @@ public class NEUManager { public String viewItemAttemptID = null; public long viewItemAttemptTime = 0; - public String currentProfile = ""; + private String currentProfile = ""; + private String currentProfileBackup = ""; public final HypixelApi hypixelApi = new HypixelApi(); private ResourceLocation wkZip = new ResourceLocation("notenoughupdates:wkhtmltox.zip"); @@ -67,17 +65,17 @@ public class NEUManager { private HashMap<String, Set<String>> usagesMap = new HashMap<>(); public File configLocation; - private File itemsLocation; + public File repoLocation; private File itemShaLocation; private JsonObject itemShaConfig; - private File configFile; + public File configFile; public Options config; public NEUManager(NotEnoughUpdates neu, NEUIO neuio, File configLocation) { this.neu = neu; this.configLocation = configLocation; this.neuio = neuio; - this.auctionManager = new AuctionManager(this); + this.auctionManager = new APIManager(this); GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting(); gsonBuilder.registerTypeAdapter(Options.Option.class, Options.createSerializer()); @@ -86,8 +84,8 @@ public class NEUManager { this.loadConfig(); - this.itemsLocation = new File(configLocation, "items"); - itemsLocation.mkdir(); + this.repoLocation = new File(configLocation, "repo"); + repoLocation.mkdir(); this.itemShaLocation = new File(configLocation, "itemSha.json"); try { @@ -112,6 +110,22 @@ public class NEUManager { public float craftCost = -1; } + public void setCurrentProfile(String currentProfile) { + this.currentProfile = currentProfile; + } + + public void setCurrentProfileBackup(String currentProfile) { + this.currentProfileBackup = currentProfile; + } + + public String getCurrentProfile() { + if(currentProfile == null || currentProfile.length() == 0) { + return currentProfileBackup; + } else { + return currentProfile; + } + } + public boolean isVanillaItem(String internalname) { //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES String vanillaName = internalname.split("-")[0]; @@ -344,54 +358,83 @@ public class NEUManager { * repository. */ public void loadItemInformation() { - if(config.autoupdate.value) { - JOptionPane pane = new JOptionPane("Getting items to download from remote repository."); - JDialog dialog = pane.createDialog("NotEnoughUpdates Remote Sync"); - dialog.setModal(false); - //dialog.setVisible(true); + try { + if(config.autoupdate.value) { + JOptionPane pane = new JOptionPane("Getting items to download from remote repository."); + JDialog dialog = pane.createDialog("NotEnoughUpdates Remote Sync"); + dialog.setModal(false); + //dialog.setVisible(true); - if (Display.isActive()) dialog.toFront(); + if (Display.isActive()) dialog.toFront(); - HashMap<String, String> oldShas = new HashMap<>(); - for (Map.Entry<String, JsonElement> entry : itemShaConfig.entrySet()) { - if (new File(itemsLocation, entry.getKey() + ".json").exists()) { - oldShas.put(entry.getKey() + ".json", entry.getValue().getAsString()); + HashMap<String, String> oldShas = new HashMap<>(); + for (Map.Entry<String, JsonElement> entry : itemShaConfig.entrySet()) { + if (new File(repoLocation, entry.getKey() + ".json").exists()) { + oldShas.put(entry.getKey() + ".json", entry.getValue().getAsString()); + } } - } - Map<String, String> changedFiles = neuio.getChangedItems(oldShas); + Map<String, String> changedFiles = neuio.getChangedItems(oldShas); - if (changedFiles != null) { - for (Map.Entry<String, String> changedFile : changedFiles.entrySet()) { - itemShaConfig.addProperty(changedFile.getKey().substring(0, changedFile.getKey().length() - 5), - changedFile.getValue()); - } - try { - writeJson(itemShaConfig, itemShaLocation); - } catch (IOException e) { + if (changedFiles != null) { + for (Map.Entry<String, String> changedFile : changedFiles.entrySet()) { + itemShaConfig.addProperty(changedFile.getKey().substring(0, changedFile.getKey().length() - 5), + changedFile.getValue()); + } + try { + writeJson(itemShaConfig, itemShaLocation); + } catch (IOException e) { + } } - } - if (Display.isActive()) dialog.toFront(); + if (Display.isActive()) dialog.toFront(); + + if (changedFiles != null && changedFiles.size() <= 20) { + + String startMessage = "NotEnoughUpdates: Syncing with remote repository ("; + int downloaded = 0; - if (changedFiles != null && changedFiles.size() <= 20) { - Map<String, String> downloads = neuio.getItemsDownload(changedFiles.keySet()); + String dlUrl = "https://raw.githubusercontent.com/Moulberry/NotEnoughUpdates-REPO/master/"; - String startMessage = "NotEnoughUpdates: Syncing with remote repository ("; - int downloaded = 0; + for (String name : changedFiles.keySet()) { + pane.setMessage(startMessage + (++downloaded) + "/" + changedFiles.size() + ")\nCurrent: " + name); + dialog.pack(); + dialog.setVisible(true); + if (Display.isActive()) dialog.toFront(); - for (Map.Entry<String, String> entry : downloads.entrySet()) { - pane.setMessage(startMessage + (++downloaded) + "/" + downloads.size() + ")\nCurrent: " + entry.getKey()); + File item = new File(repoLocation, name); + try { + item.createNewFile(); + } catch (IOException e) { + } + try (BufferedInputStream inStream = new BufferedInputStream(new URL(dlUrl+name).openStream()); + FileOutputStream fileOutputStream = new FileOutputStream(item)) { + byte dataBuffer[] = new byte[1024]; + int bytesRead; + while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { + fileOutputStream.write(dataBuffer, 0, bytesRead); + } + } catch (IOException e) { + } + } + } else { + Utils.recursiveDelete(repoLocation); + repoLocation.mkdirs(); + + //TODO: Store hard-coded value somewhere else + String dlUrl = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip"; + + pane.setMessage("Downloading NEU Master Archive. (DL# >20)"); dialog.pack(); dialog.setVisible(true); if (Display.isActive()) dialog.toFront(); - File item = new File(itemsLocation, entry.getKey()); + File itemsZip = new File(repoLocation, "neu-items-master.zip"); try { - item.createNewFile(); + itemsZip.createNewFile(); } catch (IOException e) { } - try (BufferedInputStream inStream = new BufferedInputStream(new URL(entry.getValue()).openStream()); - FileOutputStream fileOutputStream = new FileOutputStream(item)) { + try (BufferedInputStream inStream = new BufferedInputStream(new URL(dlUrl).openStream()); + FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) { byte dataBuffer[] = new byte[1024]; int bytesRead; while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { @@ -400,45 +443,21 @@ public class NEUManager { } catch (IOException e) { e.printStackTrace(); } - } - } else { - //TODO: Store hard-coded value somewhere else - String dlUrl = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip"; - pane.setMessage("Downloading NEU Master Archive. (DL# >20)"); - dialog.pack(); - dialog.setVisible(true); - if (Display.isActive()) dialog.toFront(); + pane.setMessage("Unzipping NEU Master Archive."); + dialog.pack(); + dialog.setVisible(true); + if (Display.isActive()) dialog.toFront(); - File itemsZip = new File(configLocation, "neu-items-master.zip"); - try { - itemsZip.createNewFile(); - } catch (IOException e) { - } - try (BufferedInputStream inStream = new BufferedInputStream(new URL(dlUrl).openStream()); - FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) { - byte dataBuffer[] = new byte[1024]; - int bytesRead; - while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { - fileOutputStream.write(dataBuffer, 0, bytesRead); - } - } catch (IOException e) { - e.printStackTrace(); + unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath()); } - pane.setMessage("Unzipping NEU Master Archive."); - dialog.pack(); - dialog.setVisible(true); - if (Display.isActive()) dialog.toFront(); - - unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), configLocation.getAbsolutePath()); + dialog.dispose(); } - - dialog.dispose(); - } + } catch(Exception e) {} Set<String> currentlyInstalledItems = new HashSet<>(); - for(File f : itemsLocation.listFiles()) { + for(File f : new File(repoLocation, "items").listFiles()) { currentlyInstalledItems.add(f.getName().substring(0, f.getName().length()-5)); } @@ -448,7 +467,7 @@ public class NEUManager { } else { removedItems = new HashSet<>(); } - for(File f : itemsLocation.listFiles()) { + for(File f : new File(repoLocation, "items").listFiles()) { String internalname = f.getName().substring(0, f.getName().length()-5); if(!removedItems.contains(internalname)) { loadItem(internalname); @@ -464,7 +483,7 @@ public class NEUManager { public void loadItem(String internalName) { itemstackCache.remove(internalName); try { - JsonObject json = getJsonFromFile(new File(itemsLocation, internalName + ".json")); + JsonObject json = getJsonFromFile(new File(new File(repoLocation, "items"), internalName + ".json")); if(json == null) { return; } @@ -826,6 +845,14 @@ public class NEUManager { } } } + if("ENCHANTED_BOOK".equals(internalname)) { + NBTTagCompound enchants = ea.getCompoundTag("enchantments"); + + for(String enchname : enchants.getKeySet()) { + internalname = enchname.toUpperCase() + ";" + enchants.getInteger(enchname); + break; + } + } } return internalname; @@ -966,11 +993,11 @@ public class NEUManager { } public String getInternalNameForItem(ItemStack stack) { + if(stack == null) return null; NBTTagCompound tag = stack.getTagCompound(); return getInternalnameFromNBT(tag); } - //Currently unused in production. public void writeItemToFile(ItemStack stack) { String internalname = getInternalNameForItem(stack); @@ -984,7 +1011,7 @@ public class NEUManager { json.addProperty("modver", NotEnoughUpdates.VERSION); try { - writeJson(json, new File(itemsLocation, internalname+".json")); + writeJson(json, new File(new File(repoLocation, "items"), internalname+".json")); } catch (IOException e) {} loadItem(internalname); @@ -993,7 +1020,7 @@ public class NEUManager { /** * Constructs a GuiItemUsages from the recipe usage data (see #usagesMap) of a given item */ - public boolean displayGuiItemUsages(String internalName, String text) { + public boolean displayGuiItemUsages(String internalName) { List<ItemStack[]> craftMatrices = new ArrayList<>(); List<JsonObject> results = new ArrayList<>(); @@ -1035,14 +1062,14 @@ public class NEUManager { if(craftMatrices.size() > 0) { Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow( Minecraft.getMinecraft().thePlayer.openContainer.windowId)); - Minecraft.getMinecraft().displayGuiScreen(new GuiItemUsages(craftMatrices, results, text, this)); + Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe("Item Usages", craftMatrices, results, this)); return true; } return false; } /** - * Constructs a GuiItemRecipe from the recipe data of a given item. + * Constructs a GuiItemRecipeOld from the recipe data of a given item. */ public boolean displayGuiItemRecipe(String internalName, String text) { JsonObject item = getItemInformation().get(internalName); @@ -1071,7 +1098,8 @@ public class NEUManager { Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow( Minecraft.getMinecraft().thePlayer.openContainer.windowId)); - Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe(craftMatrix, item, text, this)); + Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe(text!=null?text:"Item Recipe", + Lists.<ItemStack[]>newArrayList(craftMatrix), Lists.newArrayList(item), this)); return true; } return false; @@ -1299,7 +1327,7 @@ public class NEUManager { } public void writeJsonDefaultDir(JsonObject json, String filename) throws IOException { - File file = new File(itemsLocation, filename); + File file = new File(new File(repoLocation, "items"), filename); writeJson(json, file); } @@ -1335,6 +1363,7 @@ public class NEUManager { NBTTagCompound tag = JsonToNBT.getTagFromJson(json.get("nbttag").getAsString()); stack.setTagCompound(tag); } catch(NBTException e) { + if(json.get("internalname").getAsString().equalsIgnoreCase("ROCK;0")) e.printStackTrace(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 475f6a99..23def271 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -1,9 +1,14 @@ package io.github.moulberry.notenoughupdates; +import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.infopanes.*; import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor; +import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint; +import io.github.moulberry.notenoughupdates.mbgui.MBGuiElement; +import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupFloating; +import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupHorz; import io.github.moulberry.notenoughupdates.util.LerpingFloat; import io.github.moulberry.notenoughupdates.util.LerpingInteger; import io.github.moulberry.notenoughupdates.util.Utils; @@ -37,6 +42,7 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; +import org.lwjgl.util.vector.Vector2f; import java.awt.*; import java.lang.reflect.InvocationTargetException; @@ -72,8 +78,8 @@ public class NEUOverlay extends Gui { //Various constants used for GUI structure private int searchBarXSize = 200; - private final int searchBarYOffset = 10; private final int searchBarYSize = 40; + private final int searchBarYOffset = 10; private final int searchBarPadding = 2; private float oldWidthMult = 0; @@ -109,7 +115,7 @@ public class NEUOverlay extends Gui { private boolean redrawItems = false; private boolean searchBarHasFocus = false; - GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0); + private GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0); private static final int COMPARE_MODE_ALPHABETICAL = 0; private static final int COMPARE_MODE_RARITY = 1; @@ -126,10 +132,403 @@ public class NEUOverlay extends Gui { private boolean disabled = false; + private int lastScreenWidth; + private int lastScreenHeight; + private int lastScale; + + private List<String> textToDisplay = null; + + public MBGuiGroupFloating guiGroup = null; + public NEUOverlay(NEUManager manager) { this.manager = manager; textField.setFocused(true); textField.setCanLoseFocus(false); + + guiGroup = createGuiGroup(); + } + + private MBGuiElement createSearchBar() { + return new MBGuiElement() { + public int getWidth() { + int paddingUnscaled = getPaddingUnscaled(); + + return getSearchBarXSize() + 2*paddingUnscaled; + } + + public int getHeight() { + int paddingUnscaled = getPaddingUnscaled(); + + return getSearchBarYSize() + 2*paddingUnscaled; + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if(Mouse.getEventButtonState()) { + setSearchBarFocus(true); + if(Mouse.getEventButton() == 1) { //Right mouse button down + textField.setText(""); + updateSearch(); + } else { + if(System.currentTimeMillis() - millisLastLeftClick < 300) { + searchMode = !searchMode; + } + textField.setCursorPosition(getClickedIndex(mouseX, mouseY)); + millisLastLeftClick = System.currentTimeMillis(); + } + } + } + + @Override + public void mouseClickOutside() { + setSearchBarFocus(false); + } + + @Override + public void render(float x, float y) { + 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()); + + drawRect((int)x + paddingUnscaled, (int)y + paddingUnscaled, + (int)x - paddingUnscaled + getWidth(), (int)y - paddingUnscaled + getHeight(), + Color.BLACK.getRGB()); + + //Search bar text + fr.drawString(textField.getText(), (int)x + 5, + (int) y-4 + getHeight()/2, Color.WHITE.getRGB()); + + //Determines position of cursor. Cursor blinks on and off every 500ms. + if(searchBarHasFocus && System.currentTimeMillis()%1000>500) { + String textBeforeCursor = textField.getText().substring(0, textField.getCursorPosition()); + int textBeforeCursorWidth = fr.getStringWidth(textBeforeCursor); + drawRect((int)x + 5 + textBeforeCursorWidth, + (int)y-5 + getHeight()/2, + (int)x + 5 + textBeforeCursorWidth+1, + (int)y-4+9 + getHeight()/2, Color.WHITE.getRGB()); + } + + String selectedText = textField.getSelectedText(); + if(!selectedText.isEmpty()) { + int selectionWidth = fr.getStringWidth(selectedText); + + int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd()); + String textBeforeSelection = textField.getText().substring(0, leftIndex); + int textBeforeSelectionWidth = fr.getStringWidth(textBeforeSelection); + + drawRect((int)x + 5 + textBeforeSelectionWidth, + (int)y-5 + getHeight()/2, + (int)x + 5 + textBeforeSelectionWidth + selectionWidth, + (int)y-4+9 + getHeight()/2, Color.LIGHT_GRAY.getRGB()); + + fr.drawString(selectedText, + (int)x + 5 + textBeforeSelectionWidth, + (int)y-4 + getHeight()/2, Color.BLACK.getRGB()); + } + } + + @Override + public void recalculate() { + } + }; + } + + private MBGuiElement createSettingsButton(NEUOverlay overlay) { + return new MBGuiElement() { + @Override + public int getWidth() { + return getSearchBarYSize()+getPaddingUnscaled()*2; + } + + @Override + public int getHeight() { + return getWidth(); + } + + @Override + public void recalculate() { + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if(Mouse.getEventButtonState()) { + if(activeInfoPane instanceof SettingsInfoPane) { + displayInformationPane(null); + } else { + displayInformationPane(new SettingsInfoPane(overlay, manager)); + } + Utils.playPressSound(); + } + } + + @Override + public void mouseClickOutside() { + } + + @Override + public void render(float x, float y) { + int paddingUnscaled = getPaddingUnscaled(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(settings); + drawRect((int)x, (int)y, + (int)x + getWidth(), (int)y + getHeight(), + Color.WHITE.getRGB()); + + + drawRect((int)x + paddingUnscaled, (int)y + paddingUnscaled, + (int)x + getWidth() - paddingUnscaled, (int)y + getHeight() - paddingUnscaled, + Color.GRAY.getRGB()); + + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect((int)x + paddingUnscaled, (int)y + paddingUnscaled, + getSearchBarYSize(), getSearchBarYSize()); + GlStateManager.bindTexture(0); + } + }; + } + + private MBGuiElement createHelpButton(NEUOverlay overlay) { + return new MBGuiElement() { + @Override + public int getWidth() { + return getSearchBarYSize()+getPaddingUnscaled()*2; + } + + @Override + public int getHeight() { + return getWidth(); + } + + @Override + public void recalculate() { + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if(Mouse.getEventButtonState()) { + displayInformationPane(HTMLInfoPane.createFromWikiUrl(overlay, manager, "Help", + "https://moulberry.github.io/files/neu_help.html")); + Utils.playPressSound(); + } + } + + @Override + public void mouseClickOutside() { + } + + @Override + public void render(float x, float y) { + int paddingUnscaled = getPaddingUnscaled(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(help); + drawRect((int)x, (int)y, + (int)x + getWidth(), (int)y + getHeight(), + Color.WHITE.getRGB()); + + drawRect((int)x + paddingUnscaled, (int)y + paddingUnscaled, + (int)x + getWidth() - paddingUnscaled, (int)y + getHeight() - paddingUnscaled, + Color.GRAY.getRGB()); + + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect((int)x + paddingUnscaled, (int)y + paddingUnscaled, + getSearchBarYSize(), getSearchBarYSize()); + GlStateManager.bindTexture(0); + } + }; + } + + private MBGuiElement createQuickCommand(String quickCommandStr) { + return new MBGuiElement() { + @Override + public int getWidth() { + return getSearchBarYSize()+getPaddingUnscaled()*2; + } + + @Override + public int getHeight() { + return getWidth(); + } + + @Override + public void recalculate() { + } + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + if(!manager.config.showQuickCommands.value) return; + + if((manager.config.quickcommandMousePress.value && Mouse.getEventButtonState()) || + (!manager.config.quickcommandMousePress.value && !Mouse.getEventButtonState() && Mouse.getEventButton() != -1)) { + if(quickCommandStr.contains(":")) { + String command = quickCommandStr.split(":")[0].trim(); + if(command.startsWith("/")) { + NotEnoughUpdates.INSTANCE.sendChatMessage(command); + Utils.playPressSound(); + } else { + ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/"+command); //Need to add '/' because of sk1er's patcher being unbelievably shit + Utils.playPressSound(); + } + } + } + } + + @Override + public void mouseClickOutside() { + } + + @Override + public void render(float x, float y) { + if(!manager.config.showQuickCommands.value) return; + + int paddingUnscaled = getPaddingUnscaled(); + int bigItemSize = getSearchBarYSize(); + + if(quickCommandStr.split(":").length!=3) { + return; + } + String display = quickCommandStr.split(":")[2]; + ItemStack render = null; + float extraScale = 1; + if(display.length() > 20) { //Custom head + 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(display.getBytes()).toString(); + skullOwner.setString("Id", uuid); + skullOwner.setString("Name", uuid); + + textures_0.setString("Value", display); + textures.appendTag(textures_0); + + properties.setTag("textures", textures); + skullOwner.setTag("Properties", properties); + nbt.setTag("SkullOwner", skullOwner); + render.setTagCompound(nbt); + + extraScale = 1.3f; + } else if(manager.getItemInformation().containsKey(display)) { + render = manager.jsonToStack(manager.getItemInformation().get(display)); + } else { + Item item = Item.itemRegistry.getObject(new ResourceLocation(display.toLowerCase())); + if(item != null) { + render = new ItemStack(item); + } + } + if(render != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(x, y, + bigItemSize + paddingUnscaled*2, bigItemSize + paddingUnscaled*2, GL11.GL_LINEAR); + GlStateManager.color(fg.getRed() / 255f,fg.getGreen() / 255f, + fg.getBlue() / 255f, fg.getAlpha() / 255f); + Utils.drawTexturedRect(x+paddingUnscaled, y+paddingUnscaled, bigItemSize, bigItemSize, GL11.GL_LINEAR); + + int mouseX = Mouse.getX() * scaledresolution.getScaledWidth() / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledresolution.getScaledHeight() - Mouse.getY() * scaledresolution.getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1; + + if(mouseX > x && mouseX < x+bigItemSize) { + if(mouseY > y && mouseY < y+bigItemSize) { + textToDisplay = new ArrayList<>(); + textToDisplay.add(EnumChatFormatting.GRAY+quickCommandStr.split(":")[1]); + } + } + + float itemScale = bigItemSize/(float)ITEM_SIZE*extraScale; + GlStateManager.pushMatrix(); + GlStateManager.scale(itemScale, itemScale, 1); + GlStateManager.translate((x-(extraScale-1)*bigItemSize/2+paddingUnscaled) /itemScale, + (y-(extraScale-1)*bigItemSize/2+paddingUnscaled)/itemScale, 0f); + Utils.drawItemStack(render, 0, 0); + GlStateManager.popMatrix(); + } + } + }; + } + + private MBGuiGroupHorz createQuickCommandGroup() { + List<MBGuiElement> children = new ArrayList<>(); + for(String quickCommand : manager.config.quickCommands.value) { + children.add(createQuickCommand(quickCommand)); + } + return new MBGuiGroupHorz(children) { + public int getPadding() { + return getPaddingUnscaled()*4; + } + }; + } + + private MBGuiGroupHorz createSearchBarGroup() { + List<MBGuiElement> children = Lists.newArrayList(createSettingsButton(this), createSearchBar(), createHelpButton(this)); + return new MBGuiGroupHorz(children) { + public int getPadding() { + return getPaddingUnscaled()*4; + } + }; + } + + private MBGuiGroupFloating createGuiGroup() { + LinkedHashMap<MBGuiElement, MBAnchorPoint> map = new LinkedHashMap<>(); + + MBAnchorPoint searchBarAnchor = MBAnchorPoint.createFromString(manager.config.overlaySearchBar.value); + MBAnchorPoint quickCommandAnchor = MBAnchorPoint.createFromString(manager.config.overlayQuickCommand.value); + + searchBarAnchor = searchBarAnchor != null ? searchBarAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); + quickCommandAnchor = quickCommandAnchor != null ? quickCommandAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, + -searchBarYOffset-getSearchBarYSize()-getPaddingUnscaled()*4)); + + map.put(createSearchBarGroup(), searchBarAnchor); + map.put(createQuickCommandGroup(), quickCommandAnchor); + + return new MBGuiGroupFloating(scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight(), map); + } + + public void resetAnchors(boolean onlyIfNull) { + MBAnchorPoint searchBarAnchor = MBAnchorPoint.createFromString(manager.config.overlaySearchBar.value); + MBAnchorPoint quickCommandAnchor = MBAnchorPoint.createFromString(manager.config.overlayQuickCommand.value); + + if(onlyIfNull) { + searchBarAnchor = searchBarAnchor != null ? null : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); + quickCommandAnchor = quickCommandAnchor != null ? null : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, + -searchBarYOffset-getSearchBarYSize()-getPaddingUnscaled()*4)); + } else { + searchBarAnchor = searchBarAnchor != null ? searchBarAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, -searchBarYOffset)); + quickCommandAnchor = quickCommandAnchor != null ? quickCommandAnchor : + new MBAnchorPoint(MBAnchorPoint.AnchorPoint.BOTMID, new Vector2f(0, + -searchBarYOffset-getSearchBarYSize()-getPaddingUnscaled()*4)); + } + + + int index = 0; + Set<MBGuiElement> set = new LinkedHashSet<>(guiGroup.getChildrenMap().keySet()); + for(MBGuiElement element : set) { + switch(index) { + case 0: + if(searchBarAnchor == null) continue; + guiGroup.getChildrenMap().get(element).anchorPoint = searchBarAnchor.anchorPoint; + guiGroup.getChildrenMap().get(element).offset = searchBarAnchor.offset; + break; + case 1: + if(quickCommandAnchor == null) continue; + guiGroup.getChildrenMap().get(element).anchorPoint = quickCommandAnchor.anchorPoint; + guiGroup.getChildrenMap().get(element).offset = quickCommandAnchor.offset; + break; + } + index++; + } } /** @@ -201,6 +600,8 @@ public class NEUOverlay extends Gui { //Unfocuses the search bar by default. Search bar is focused if the click is on the bar itself. if(Mouse.getEventButtonState()) setSearchBarFocus(false); + guiGroup.mouseClick(0, 0, mouseX, mouseY); + //Item selection (right) gui if(mouseX > width*getItemPaneOffsetFactor()) { if(!Mouse.getEventButtonState()) return true; //End early if the mouse isn't pressed, but still cancel event. @@ -318,89 +719,6 @@ public class NEUOverlay extends Gui { } } } - - - //Quickcommands - int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); - if(paddingUnscaled < 1) paddingUnscaled = 1; - int topTextBox = height - searchBarYOffset - getSearchBarYSize(); - - if(Mouse.getEventButtonState() && manager.config.showQuickCommands.value) { - ArrayList<String> quickCommands = manager.config.quickCommands.value; - int bigItemSize = getSearchBarYSize(); - int bigItemPadding = paddingUnscaled*4; - int xStart = width/2 + bigItemPadding/2 - (bigItemSize+bigItemPadding)*quickCommands.size()/2; - int xEnd = width/2 - bigItemPadding/2 + (bigItemSize+bigItemPadding)*quickCommands.size()/2; - int y = topTextBox - bigItemSize - bigItemPadding - paddingUnscaled*2; - - if(mouseY >= y && mouseY <= topTextBox-paddingUnscaled*2) { - if(mouseX > xStart && mouseX < xEnd) { - if((mouseX - xStart)%(bigItemSize+bigItemPadding) < bigItemSize) { - int index = (mouseX - xStart)/(bigItemSize+bigItemPadding); - if(index >= 0 && index < quickCommands.size()) { - String quickCommand = quickCommands.get(index); - if(quickCommand.contains(":")) { - String command = quickCommand.split(":")[0].trim(); - if(command.startsWith("/")) { - NotEnoughUpdates.INSTANCE.sendChatMessage(command); - Utils.playPressSound(); - return true; - } else { - ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/"+command); //Need to add '/' because of sk1er's patcher being unbelievably shit - Utils.playPressSound(); - return true; - } - } - } - } - } - } - } - - //Search bar - if(mouseX >= width/2 - getSearchBarXSize()/2 && mouseX <= width/2 + getSearchBarXSize()/2) { - if(mouseY >= height - searchBarYOffset - getSearchBarYSize() && - mouseY <= height - searchBarYOffset) { - if(Mouse.getEventButtonState()) { - setSearchBarFocus(true); - if(Mouse.getEventButton() == 1) { //Right mouse button down - textField.setText(""); - updateSearch(); - } else { - if(System.currentTimeMillis() - millisLastLeftClick < 300) { - searchMode = !searchMode; - } - textField.setCursorPosition(getClickedIndex(mouseX, mouseY)); - millisLastLeftClick = System.currentTimeMillis(); - } - } - return true; - } - } - - int iconSize = getSearchBarYSize()+paddingUnscaled*2; - - if(mouseY > topTextBox - paddingUnscaled && mouseY < topTextBox - paddingUnscaled + iconSize) { - if(mouseX > width/2 + getSearchBarXSize()/2 + paddingUnscaled*6 && - mouseX < width/2 + getSearchBarXSize()/2 + paddingUnscaled*6 + iconSize) { - if(Mouse.getEventButtonState()) { - displayInformationPane(HTMLInfoPane.createFromWikiUrl(this, manager, "Help", - "https://moulberry.github.io/files/neu_help.html")); - Utils.playPressSound(); - } - } else if(mouseX > width/2 - getSearchBarXSize()/2 - paddingUnscaled*6 - iconSize && - mouseX < width/2 - getSearchBarXSize()/2 - paddingUnscaled*6) { - if(Mouse.getEventButtonState()) { - if(activeInfoPane instanceof SettingsInfoPane) { - displayInformationPane(null); - } else { - displayInformationPane(new SettingsInfoPane(this, manager)); - } - Utils.playPressSound(); - } - } - } - if(activeInfoPane != null) { if(mouseX < width*getInfoPaneOffsetFactor()) { activeInfoPane.mouseInput(width, height, mouseX, mouseY, mouseDown); @@ -413,6 +731,13 @@ public class NEUOverlay extends Gui { return false; } + public int getPaddingUnscaled() { + int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); + if(paddingUnscaled < 1) paddingUnscaled = 1; + + return paddingUnscaled; + } + /** * Returns searchBarXSize, scaled by 0.8 if gui scale == AUTO. */ @@ -554,7 +879,7 @@ public class NEUOverlay extends Gui { JsonObject item = manager.getItemInformation().get(internalname.get()); if(item != null) { if(keyPressed == manager.keybindViewUsages.getKeyCode()) { - manager.displayGuiItemUsages(internalname.get(), ""); + manager.displayGuiItemUsages(internalname.get()); return true; } else if(keyPressed == manager.keybindFavourite.getKeyCode()) { toggleFavourite(item.get("internalname").getAsString()); @@ -660,8 +985,11 @@ public class NEUOverlay extends Gui { if(rarity1 < rarity2) return mult; if(rarity1 > rarity2) return -mult; } else if(getCompareMode() == COMPARE_MODE_VALUE) { - float cost1 = manager.getCraftCost(o1.get("internalname").getAsString()).craftCost; - float cost2 = manager.getCraftCost(o2.get("internalname").getAsString()).craftCost; + float cost1 = manager.auctionManager.getLowestBin(o1.get("internalname").getAsString()); + float cost2 = manager.auctionManager.getLowestBin(o2.get("internalname").getAsString()); + + if(cost1 == -1) cost1 = manager.getCraftCost(o1.get("internalname").getAsString()).craftCost; + if(cost2 == -1) cost2 = manager.getCraftCost(o2.get("internalname").getAsString()).craftCost; if(cost1 < cost2) return mult; if(cost1 > cost2) return -mult; @@ -1203,6 +1531,24 @@ public class NEUOverlay extends Gui { blurOutputVert.unbindFramebufferTexture(); } + public void updateGuiGroupSize() { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledresolution.getScaledWidth(); + int height = scaledresolution.getScaledHeight(); + + if(lastScreenWidth != width || lastScreenHeight != height || scaledresolution.getScaleFactor() != lastScale) { + guiGroup.width = width; + guiGroup.height = height; + + resetAnchors(true); + guiGroup.recalculate(); + + lastScreenWidth = width; + lastScreenHeight = height; + lastScale = scaledresolution.getScaleFactor(); + } + } + int guiScaleLast = 0; /** @@ -1217,6 +1563,8 @@ public class NEUOverlay extends Gui { int width = scaledresolution.getScaledWidth(); int height = scaledresolution.getScaledHeight(); + updateGuiGroupSize(); + if(guiScaleLast != scaledresolution.getScaleFactor()) { guiScaleLast = scaledresolution.getScaleFactor(); redrawItems = true; @@ -1285,7 +1633,6 @@ public class NEUOverlay extends Gui { int rightSide = leftSide+paneWidth-getBoxPadding()-getItemBoxXPadding(); //Tab - Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow); GlStateManager.color(1f, 1f, 1f, 0.3f); Utils.drawTexturedRect(width-itemPaneTabOffset.getValue(), height/2 - 50, 20, 100); @@ -1294,7 +1641,9 @@ public class NEUOverlay extends Gui { if(mouseX > width-itemPaneTabOffset.getValue() && mouseY > height/2 - 50 && mouseY < height/2 + 50) { if(!hoveringItemPaneToggle) { - itemPaneOpen = !itemPaneOpen; + if(!manager.config.disableItemTabOpen.value) { + itemPaneOpen = !itemPaneOpen; + } hoveringItemPaneToggle = true; } } else { @@ -1303,7 +1652,6 @@ 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); - List<String> textToDisplay = null; if(itemPaneOffsetFactor.getValue() < 1) { renderBlurredBackground(width, height, leftSide+getBoxPadding()-5, getBoxPadding()-5, @@ -1430,159 +1778,10 @@ public class NEUOverlay extends Gui { } /** - * Search bar + * Search bar & quickcommand elements */ - int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); - if(paddingUnscaled < 1) paddingUnscaled = 1; - - int topTextBox = height - searchBarYOffset - getSearchBarYSize(); - - //Search bar background - drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled, - topTextBox - paddingUnscaled, - width/2 + getSearchBarXSize()/2 + paddingUnscaled, - height - searchBarYOffset + paddingUnscaled, searchMode ? Color.YELLOW.getRGB() : Color.WHITE.getRGB()); - drawRect(width/2 - getSearchBarXSize()/2, - topTextBox, - width/2 + getSearchBarXSize()/2, - height - searchBarYOffset, Color.BLACK.getRGB()); - - //Quickcommands - if(manager.config.showQuickCommands.value) { - ArrayList<String> quickCommands = manager.config.quickCommands.value; - int bigItemSize = getSearchBarYSize(); - int bigItemPadding = paddingUnscaled*4; - int x = width/2 + bigItemPadding/2 - (bigItemSize+bigItemPadding)*quickCommands.size()/2; - int y = topTextBox - bigItemSize - bigItemPadding - paddingUnscaled*2; - - for(String quickCommand : quickCommands) { - if(quickCommand.split(":").length!=3) { - continue; - } - String display = quickCommand.split(":")[2]; - ItemStack render = null; - float extraScale = 1; - if(display.length() > 20) { //Custom head - 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(display.getBytes()).toString(); - skullOwner.setString("Id", uuid); - skullOwner.setString("Name", uuid); - - textures_0.setString("Value", display); - textures.appendTag(textures_0); - - properties.setTag("textures", textures); - skullOwner.setTag("Properties", properties); - nbt.setTag("SkullOwner", skullOwner); - render.setTagCompound(nbt); - - extraScale = 1.3f; - } else if(manager.getItemInformation().containsKey(display)) { - render = manager.jsonToStack(manager.getItemInformation().get(display)); - } else { - Item item = Item.itemRegistry.getObject(new ResourceLocation(display.toLowerCase())); - if(item != null) { - render = new ItemStack(item); - } - } - if(render != null) { - Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(x - paddingUnscaled, y - paddingUnscaled, - bigItemSize + paddingUnscaled*2, bigItemSize + paddingUnscaled*2, GL11.GL_NEAREST); - GlStateManager.color(fg.getRed() / 255f,fg.getGreen() / 255f, - fg.getBlue() / 255f, fg.getAlpha() / 255f); - Utils.drawTexturedRect(x, y, bigItemSize, bigItemSize, GL11.GL_NEAREST); - - if(mouseX > x && mouseX < x+bigItemSize) { - if(mouseY > y && mouseY < y+bigItemSize) { - textToDisplay = new ArrayList<>(); - textToDisplay.add(EnumChatFormatting.GRAY+quickCommand.split(":")[1]); - } - } - - float itemScale = bigItemSize/(float)ITEM_SIZE*extraScale; - GlStateManager.pushMatrix(); - GlStateManager.scale(itemScale, itemScale, 1); - GlStateManager.translate((x-(extraScale-1)*bigItemSize/2) /itemScale, - (y-(extraScale-1)*bigItemSize/2)/itemScale, 0f); - Utils.drawItemStack(render, 0, 0); - GlStateManager.popMatrix(); - } - x += bigItemSize + bigItemPadding; - } - } - - //Settings - int iconSize = getSearchBarYSize()+paddingUnscaled*2; - Minecraft.getMinecraft().getTextureManager().bindTexture(settings); - drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*6 - iconSize, - topTextBox - paddingUnscaled, - width/2 - getSearchBarXSize()/2 - paddingUnscaled*6, - topTextBox - paddingUnscaled + iconSize, Color.WHITE.getRGB()); - - drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*5 - iconSize, - topTextBox, - width/2 - getSearchBarXSize()/2 - paddingUnscaled*7, - topTextBox - paddingUnscaled*2 + iconSize, Color.GRAY.getRGB()); - GlStateManager.color(1f, 1f, 1f, 1f); - Utils.drawTexturedRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*6 - iconSize, topTextBox - paddingUnscaled, iconSize, iconSize); - GlStateManager.bindTexture(0); - - //Help - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - drawRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*6, - topTextBox - paddingUnscaled, - width/2 + getSearchBarXSize()/2 + paddingUnscaled*6 + iconSize, - topTextBox - paddingUnscaled + iconSize, Color.WHITE.getRGB()); - - drawRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*7, - topTextBox, - width/2 + getSearchBarXSize()/2 + paddingUnscaled*5 + iconSize, - topTextBox - paddingUnscaled*2 + iconSize, Color.GRAY.getRGB()); - GlStateManager.color(1f, 1f, 1f, 1f); - Utils.drawTexturedRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*7, topTextBox, - iconSize-paddingUnscaled*2, iconSize-paddingUnscaled*2); - GlStateManager.bindTexture(0); - - //Search bar text - fr.drawString(textField.getText(), width/2 - getSearchBarXSize()/2 + 5, - topTextBox+(getSearchBarYSize()-8)/2, Color.WHITE.getRGB()); - - //Determines position of cursor. Cursor blinks on and off every 500ms. - if(searchBarHasFocus && System.currentTimeMillis()%1000>500) { - String textBeforeCursor = textField.getText().substring(0, textField.getCursorPosition()); - int textBeforeCursorWidth = fr.getStringWidth(textBeforeCursor); - drawRect(width/2 - getSearchBarXSize()/2 + 5 + textBeforeCursorWidth, - topTextBox+(getSearchBarYSize()-8)/2-1, - width/2 - getSearchBarXSize()/2 + 5 + textBeforeCursorWidth+1, - topTextBox+(getSearchBarYSize()-8)/2+9, Color.WHITE.getRGB()); - } - - String selectedText = textField.getSelectedText(); - if(!selectedText.isEmpty()) { - int selectionWidth = fr.getStringWidth(selectedText); - - int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd()); - String textBeforeSelection = textField.getText().substring(0, leftIndex); - int textBeforeSelectionWidth = fr.getStringWidth(textBeforeSelection); - - drawRect(width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth, - topTextBox+(getSearchBarYSize()-8)/2-1, - width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth + selectionWidth, - topTextBox+(getSearchBarYSize()-8)/2+9, Color.LIGHT_GRAY.getRGB()); - - fr.drawString(selectedText, - width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth, - topTextBox+(getSearchBarYSize()-8)/2, Color.BLACK.getRGB()); - } + guiGroup.render(0, 0); + resetAnchors(true); /** * Item info (left) gui element rendering @@ -1611,17 +1810,24 @@ public class NEUOverlay extends Gui { text.add(lore.get(i).getAsString()); } - JsonObject auctionInfo = manager.getItemAuctionInfo(json.get("internalname").getAsString()); - JsonObject bazaarInfo = manager.getBazaarInfo(json.get("internalname").getAsString()); + String internalname = json.get("internalname").getAsString(); + JsonObject auctionInfo = manager.getItemAuctionInfo(internalname); + JsonObject bazaarInfo = manager.getBazaarInfo(internalname); boolean hasAuctionPrice = auctionInfo != null; boolean hasBazaarPrice = bazaarInfo != null; + int lowestBin = manager.auctionManager.getLowestBin(internalname); + NumberFormat format = NumberFormat.getInstance(Locale.US); NEUManager.CraftInfo craftCost = manager.getCraftCost(json.get("internalname").getAsString()); - if(hasAuctionPrice || hasBazaarPrice || craftCost.fromRecipe) text.add(""); + if(hasAuctionPrice || hasBazaarPrice || craftCost.fromRecipe || lowestBin > 0) text.add(""); + if(lowestBin > 0) { + text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Lowest BIN: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(lowestBin)+" coins"); + } if(hasBazaarPrice) { int bazaarBuyPrice = (int)bazaarInfo.get("avg_buy").getAsFloat(); text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+ @@ -1665,6 +1871,7 @@ public class NEUOverlay extends Gui { } if(textToDisplay != null) { Utils.drawHoveringText(textToDisplay, mouseX, mouseY, width, height, -1, fr); + textToDisplay = null; } GlStateManager.enableBlend(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java new file mode 100644 index 00000000..28ecbc8e --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java @@ -0,0 +1,185 @@ +package io.github.moulberry.notenoughupdates; + +import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint; +import io.github.moulberry.notenoughupdates.mbgui.MBGuiElement; +import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroup; +import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupFloating; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import org.lwjgl.input.Keyboard; +import org.lwjgl.util.vector.Vector2f; + +import java.awt.*; +import java.io.IOException; + +public class NEUOverlayPlacements extends GuiScreen { + + private int clickedX; + private int clickedY; + private int clickedAnchorX; + private int clickedAnchorY; + private MBGuiElement clickedElement; + private GuiButton guiButton = new GuiButton(0, 5, 5, "Reset to Default"); + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + drawDefaultBackground(); + + if(mouseX < 300 && mouseY < 300 && clickedElement != null) { + guiButton.yPosition = height - 5 - guiButton.height; + } else { + guiButton.yPosition = 5; + } + + guiButton.drawButton(Minecraft.getMinecraft(), mouseX, mouseY); + + NotEnoughUpdates.INSTANCE.overlay.updateGuiGroupSize(); + + MBGuiGroupFloating mainGroup = NotEnoughUpdates.INSTANCE.overlay.guiGroup; + for(MBGuiElement element : mainGroup.getChildren()) { + MBAnchorPoint anchorPoint = mainGroup.getChildrenMap().get(element); + Vector2f position = mainGroup.getChildrenPosition().get(element); + + drawRect((int)position.x, (int)position.y, + (int)position.x+element.getWidth(), (int)position.y+element.getHeight(), new Color(100, 100, 100, 200).getRGB()); + + + switch(anchorPoint.anchorPoint) { + case TOPLEFT: + case TOPRIGHT: + case BOTLEFT: + case BOTRIGHT: + drawRect((int)(position.x+element.getWidth()*anchorPoint.anchorPoint.x*0.9f), + (int)(position.y+element.getHeight()*anchorPoint.anchorPoint.y*0.9f), + (int)(position.x+element.getWidth()*anchorPoint.anchorPoint.x*0.9f+element.getWidth()*0.1f), + (int)(position.y+element.getHeight()*anchorPoint.anchorPoint.y*0.9f+element.getHeight()*0.1f), + new Color(200, 200, 200, 100).getRGB()); + break; + case TOPMID: + drawRect((int)position.x, (int)position.y, + (int)position.x+element.getWidth(), (int)(position.y+element.getHeight()*0.1f), + new Color(200, 200, 200, 100).getRGB()); + break; + case MIDLEFT: + drawRect((int)position.x, (int)position.y, + (int)(position.x+element.getWidth()*0.1f), (int)position.y+element.getHeight(), + new Color(200, 200, 200, 100).getRGB()); + break; + case MIDRIGHT: + drawRect((int)(position.x+element.getWidth()*0.9f), (int)position.y, + (int)position.x+element.getWidth(), (int)position.y+element.getHeight(), + new Color(200, 200, 200, 100).getRGB()); + break; + case BOTMID: + drawRect((int)position.x, (int)(position.y+element.getHeight()*0.9f), + (int)position.x+element.getWidth(), (int)position.y+element.getHeight(), + new Color(200, 200, 200, 100).getRGB()); + break; + case MIDMID: + drawRect((int)(position.x+element.getWidth()*0.45f), (int)(position.y+element.getHeight()*0.45f), + (int)(position.x+element.getWidth()*0.55f), (int)(position.y+element.getHeight()*0.55f), + new Color(200, 200, 200, 100).getRGB()); + break; + + } + } + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + MBGuiGroupFloating mainGroup = NotEnoughUpdates.INSTANCE.overlay.guiGroup; + for(MBGuiElement element : mainGroup.getChildren()) { + MBAnchorPoint anchorPoint = mainGroup.getChildrenMap().get(element); + Vector2f position = mainGroup.getChildrenPosition().get(element); + + if(mouseX > position.x && mouseX < position.x + element.getWidth()) { + if(mouseY > position.y && mouseY < position.y + element.getHeight()) { + if(mouseButton == 0) { + clickedElement = element; + clickedX = mouseX; + clickedY = mouseY; + clickedAnchorX = (int)anchorPoint.offset.x; + clickedAnchorY = (int)anchorPoint.offset.y; + } else { + float anchorX = (width-element.getWidth()) * anchorPoint.anchorPoint.x + anchorPoint.offset.x; + float anchorY = (height-element.getHeight()) * anchorPoint.anchorPoint.y + anchorPoint.offset.y; + + MBAnchorPoint.AnchorPoint[] vals = MBAnchorPoint.AnchorPoint.values(); + anchorPoint.anchorPoint = vals[(anchorPoint.anchorPoint.ordinal()+1)%vals.length]; + + float screenX = (width-element.getWidth()) * anchorPoint.anchorPoint.x; + float screenY = (height-element.getHeight()) * anchorPoint.anchorPoint.y; + anchorPoint.offset.x = anchorX - screenX; + anchorPoint.offset.y = anchorY - screenY; + + mainGroup.recalculate(); + } + return; + } + } + } + + if(guiButton.mousePressed(Minecraft.getMinecraft(), mouseX, mouseY)) { + NotEnoughUpdates.INSTANCE.manager.config.overlayQuickCommand.value = ""; + NotEnoughUpdates.INSTANCE.manager.config.overlaySearchBar.value = ""; + try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {} + NotEnoughUpdates.INSTANCE.overlay.resetAnchors(false); + + mainGroup.recalculate(); + } + clickedElement = null; + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int state) { + clickedElement = null; + } + + @Override + protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); + if(clickedElement != null) { + MBGuiGroupFloating mainGroup = NotEnoughUpdates.INSTANCE.overlay.guiGroup; + MBAnchorPoint anchorPoint = mainGroup.getChildrenMap().get(clickedElement); + + if(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { + int dX = mouseX - clickedX; + int dY = mouseY - clickedY; + if(Math.abs(dX) > Math.abs(dY)) { + anchorPoint.offset.x = mouseX - clickedX + clickedAnchorX; + anchorPoint.offset.y = clickedAnchorY; + } else { + anchorPoint.offset.x = clickedAnchorX; + anchorPoint.offset.y = mouseY - clickedY + clickedAnchorY; + } + } else { + anchorPoint.offset.x = mouseX - clickedX + clickedAnchorX; + anchorPoint.offset.y = mouseY - clickedY + clickedAnchorY; + } + + int index = 0; + for(MBGuiElement element : mainGroup.getChildren()) { + if(element == clickedElement) { + if(index == 0) { + NotEnoughUpdates.INSTANCE.manager.config.overlaySearchBar.value = anchorPoint.toString(); + } else if(index == 1) { + NotEnoughUpdates.INSTANCE.manager.config.overlayQuickCommand.value = anchorPoint.toString(); + } + try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {} + break; + } + index++; + } + + mainGroup.recalculate(); + } + } + + @Override + public boolean doesGuiPauseGame() { + return false; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 0724a132..a589fe2b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -11,14 +11,19 @@ import io.github.moulberry.notenoughupdates.commands.SimpleCommand; import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.infopanes.CollectionLogInfoPane; import io.github.moulberry.notenoughupdates.infopanes.CosmeticsInfoPane; +import io.github.moulberry.notenoughupdates.questing.GuiQuestLine; +import io.github.moulberry.notenoughupdates.questing.NEUQuesting; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.*; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.settings.KeyBinding; import net.minecraft.command.ICommandSender; +import net.minecraft.event.ClickEvent; import net.minecraft.init.Blocks; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; @@ -29,6 +34,7 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.Session; import net.minecraftforge.client.ClientCommandHandler; @@ -62,15 +68,17 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import static io.github.moulberry.notenoughupdates.GuiTextures.*; + @Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION) public class NotEnoughUpdates { public static final String MODID = "notenoughupdates"; - public static final String VERSION = "1.0.0"; + public static final String VERSION = "REL-1.0.0"; public static NotEnoughUpdates INSTANCE = null; public NEUManager manager; - private NEUOverlay overlay; + public NEUOverlay overlay; private NEUIO neuio; private static final long CHAT_MSG_COOLDOWN = 200; @@ -81,6 +89,8 @@ public class NotEnoughUpdates { private boolean hoverInv = false; private boolean focusInv = false; + private boolean joinedSB = false; + //Stolen from Biscut and used for detecting whether in skyblock private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK","\u7A7A\u5C9B\u751F\u5B58"); @@ -100,7 +110,7 @@ public class NotEnoughUpdates { SimpleCommand collectionLogCommand = new SimpleCommand("neucl", new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { if(!OpenGlHelper.isFramebufferEnabled()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+ + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "This feature requires FBOs to work. Try disabling Optifine's 'Fast Render'.")); } else { if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { @@ -112,6 +122,19 @@ public class NotEnoughUpdates { } }); + + SimpleCommand questingCommand = new SimpleCommand("neuquest", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + openGui = new GuiQuestLine(); + } + }); + + SimpleCommand overlayPlacementsCommand = new SimpleCommand("neuoverlay", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + openGui = new NEUOverlayPlacements(); + } + }); + SimpleCommand cosmeticsCommand = new SimpleCommand("neucosmetics", new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { @@ -126,7 +149,7 @@ public class NotEnoughUpdates { if(!hasSkyblockScoreboard()) { Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+ "You must be on Skyblock to use this feature.")); - } else if(manager.config.apiKey.value == null || manager.config.apiKey.value.isEmpty()) { + } else if(manager.config.apiKey.value == null || manager.config.apiKey.value.trim().isEmpty()) { Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+ "Can't open NeuAH, Api Key is not set. Run /api new and put the result in settings.")); } else { @@ -152,6 +175,8 @@ public class NotEnoughUpdates { f.mkdirs(); ClientCommandHandler.instance.registerCommand(collectionLogCommand); ClientCommandHandler.instance.registerCommand(cosmeticsCommand); + ClientCommandHandler.instance.registerCommand(overlayPlacementsCommand); + //ClientCommandHandler.instance.registerCommand(questingCommand); ClientCommandHandler.instance.registerCommand(neuAhCommand); neuio = new NEUIO(getAccessToken()); @@ -178,7 +203,7 @@ public class NotEnoughUpdates { })); //TODO: login code. Ignore this, used for testing. - try { + /*try { Field field = Minecraft.class.getDeclaredField("session"); YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString()) @@ -207,7 +232,7 @@ public class NotEnoughUpdates { field.setAccessible(true); field.set(Minecraft.getMinecraft(), session); } catch (NoSuchFieldException | AuthenticationException | IllegalAccessException e) { - } + }*/ } /** @@ -239,17 +264,93 @@ public class NotEnoughUpdates { } if(hasSkyblockScoreboard()) { manager.auctionManager.tick(); + if(!joinedSB && manager.config.showUpdateMsg.value) { + File repo = manager.repoLocation; + if(repo.exists()) { + File updateJson = new File(repo, "update.json"); + try { + JsonObject o = manager.getJsonFromFile(updateJson); + + String version = o.get("version").getAsString(); + + if(!VERSION.equalsIgnoreCase(version)) { + String update_msg = o.get("update_msg").getAsString(); + String discord_link = o.get("discord_link").getAsString(); + String youtube_link = o.get("youtube_link").getAsString(); + String update_link = o.get("update_link").getAsString(); + String github_link = o.get("github_link").getAsString(); + String other_text = o.get("other_text").getAsString(); + String other_link = o.get("other_link").getAsString(); + + int first_len = -1; + for(String line : update_msg.split("\n")) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int len = fr.getStringWidth(line); + if(first_len == -1) { + first_len = len; + } + int missing_len = first_len-len; + if(missing_len > 0) { + StringBuilder sb = new StringBuilder(line); + for(int i=0; i<missing_len/8; i++) { + sb.insert(0, " "); + } + line = sb.toString(); + } + line = line.replaceAll("\\{version}", version); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); + } + ChatComponentText other = null; + if(other_text.length() > 0) { + other = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+other_text+EnumChatFormatting.GRAY+"]"); + other.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, other_link)); + } + ChatComponentText links = new ChatComponentText(""); + ChatComponentText separator = new ChatComponentText( + EnumChatFormatting.GRAY+EnumChatFormatting.BOLD.toString()+EnumChatFormatting.STRIKETHROUGH+(other==null?"---":"--")); + ChatComponentText discord = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+"Discord"+EnumChatFormatting.GRAY+"]"); + discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link)); + ChatComponentText youtube = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.RED+"YouTube"+EnumChatFormatting.GRAY+"]"); + youtube.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, youtube_link)); + ChatComponentText release = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.GREEN+"Release"+EnumChatFormatting.GRAY+"]"); + release.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, update_link)); + ChatComponentText github = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.DARK_PURPLE+"GitHub"+EnumChatFormatting.GRAY+"]"); + github.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, github_link)); + + + links.appendSibling(separator); + links.appendSibling(discord); + links.appendSibling(separator); + links.appendSibling(youtube); + links.appendSibling(separator); + links.appendSibling(release); + links.appendSibling(separator); + links.appendSibling(github); + links.appendSibling(separator); + if(other != null) { + links.appendSibling(other); + links.appendSibling(separator); + } + + Minecraft.getMinecraft().thePlayer.addChatMessage(links); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + + } + + joinedSB = true; + } catch(Exception ignored) {} + } + } + //NEUQuesting.getInstance().tick(); + //GuiQuestLine.questLine.tick(); } if(currChatMessage != null && System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) { lastChatMessage = System.currentTimeMillis(); Minecraft.getMinecraft().thePlayer.sendChatMessage(currChatMessage); currChatMessage = null; } - if(hasSkyblockScoreboard() && manager.currentProfile != null && manager.currentProfile.length() > 0) { + if(hasSkyblockScoreboard() && manager.getCurrentProfile() != null && manager.getCurrentProfile().length() > 0) { HashSet<String> newItem = new HashSet<>(); - for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { - processUniqueStack(stack, newItem); - } if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer && !(Minecraft.getMinecraft().currentScreen instanceof GuiCrafting)) { boolean usableContainer = true; @@ -281,6 +382,14 @@ public class NotEnoughUpdates { for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) { processUniqueStack(stack, newItem); } + for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { + processUniqueStack(stack, newItem); + } + } + } else { + + for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { + processUniqueStack(stack, newItem); } } newItemAddMap.keySet().retainAll(newItem); @@ -292,7 +401,7 @@ public class NotEnoughUpdates { String internalname = manager.getInternalNameForItem(stack); if(internalname != null) { ArrayList<String> log = manager.config.collectionLog.value.computeIfAbsent( - manager.currentProfile, k -> new ArrayList<>()); + manager.getCurrentProfile(), k -> new ArrayList<>()); if(!log.contains(internalname)) { newItem.add(internalname); if(newItemAddMap.containsKey(internalname)) { @@ -464,11 +573,14 @@ public class NotEnoughUpdates { @SubscribeEvent(priority = EventPriority.LOW) public void onGuiChat(ClientChatReceivedEvent e) { String r = null; - String unformatted = e.message.getUnformattedText().replaceAll("(?i)\\u00A7.", ""); + String unformatted = Utils.cleanColour(e.message.getUnformattedText()); if(unformatted.startsWith("You are playing on profile: ")) { - manager.currentProfile = unformatted.substring("You are playing on profile: ".length()).split(" ")[0].trim(); + manager.setCurrentProfile(unformatted.substring("You are playing on profile: ".length()).split(" ")[0].trim()); } else if(unformatted.startsWith("Your profile was changed to: ")) {//Your profile was changed to: - manager.currentProfile = unformatted.substring("Your profile was changed to: ".length()).split(" ")[0].trim(); + manager.setCurrentProfile(unformatted.substring("Your profile was changed to: ".length()).split(" ")[0].trim()); + } else if(unformatted.startsWith("Your new API key is ")) { + manager.config.apiKey.value = unformatted.substring("Your new API key is ".length()); + try { manager.saveConfig(); } catch(IOException ioe) {} } if(e.message.getFormattedText().equals(EnumChatFormatting.RESET.toString()+ EnumChatFormatting.RED+"You haven't unlocked this recipe!"+EnumChatFormatting.RESET)) { @@ -574,6 +686,9 @@ public class NotEnoughUpdates { public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) { if(!(event.gui instanceof CustomAHGui || manager.auctionManager.customAH.isRenderOverAuctionView())) { if(event.gui instanceof GuiContainer && isOnSkyblock()) { + + renderDungeonChestOverlay(event.gui); + if(!focusInv) { GL11.glTranslatef(0, 0, 300); overlay.render(event.mouseX, event.mouseY, hoverInv && focusInv); @@ -584,6 +699,86 @@ public class NotEnoughUpdates { } } + private void renderDungeonChestOverlay(GuiScreen gui) { + if(gui instanceof GuiChest && manager.auctionManager.activeAuctions > 0) { + 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"); + + GuiChest eventGui = (GuiChest) gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + ItemStack rewardChest = lower.getStackInSlot(31); + if (rewardChest != null && rewardChest.getDisplayName().endsWith(EnumChatFormatting.GREEN+"Open Reward Chest")) { + int chestCost = 0; + String line6 = Utils.cleanColour(manager.getLoreFromNBT(rewardChest.getTagCompound())[6]); + StringBuilder cost = new StringBuilder(); + for(int i=0; i<line6.length(); i++) { + char c = line6.charAt(i); + if("0123456789".indexOf(c) >= 0) { + cost.append(c); + } + } + if(cost.length() > 0) { + chestCost = Integer.parseInt(cost.toString()); + } + + boolean missing = false; + int totalValue = 0; + for(int i=0; i<5; i++) { + ItemStack item = lower.getStackInSlot(11+i); + String internal = manager.getInternalNameForItem(item); + if(internal != null) { + int worth = manager.auctionManager.getLowestBin(internal); + if(worth > 0) { + totalValue += worth; + } else { + missing = true; + break; + } + } + } + int profitLoss = totalValue - chestCost; + + NumberFormat format = NumberFormat.getInstance(Locale.US); + String valueString; + if(!missing) { + valueString = EnumChatFormatting.BLUE+"Chest value: " + EnumChatFormatting.GOLD + + EnumChatFormatting.BOLD + format.format(totalValue) + " coins"; + } else { + valueString = EnumChatFormatting.BLUE+"Couldn't find item on AH. Item is very rare!"; + } + String plString; + if(missing) { + plString = ""; + } else if(profitLoss >= 0) { + plString = EnumChatFormatting.BLUE+"Profit/loss: " + EnumChatFormatting.DARK_GREEN + + EnumChatFormatting.BOLD + "+" + format.format(profitLoss) + " coins"; + } else { + plString = EnumChatFormatting.BLUE+"Profit/loss: " + EnumChatFormatting.RED + + EnumChatFormatting.BOLD + "-" + format.format(-profitLoss) + " coins"; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth); + GL11.glColor4f(1, 1, 1, 1); + GlStateManager.disableLighting(); + Utils.drawTexturedRect(guiLeft+xSize+4, guiTop, 180, 45, 0, 180/256f, 0, 45/256f, GL11.GL_NEAREST); + + Utils.drawStringCenteredScaledMaxWidth(valueString, Minecraft.getMinecraft().fontRendererObj, guiLeft+xSize+4+90, + guiTop+14, true, 170, Color.BLACK.getRGB()); + Utils.drawStringCenteredScaledMaxWidth(plString, Minecraft.getMinecraft().fontRendererObj, guiLeft+xSize+4+90, + guiTop+28, true, 170, Color.BLACK.getRGB()); + + } + } catch(Exception e) { + e.printStackTrace(); + } + } + } + /** * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused. * Will also cancel the event if if NEUOverlay#mouseInput returns true. @@ -757,7 +952,7 @@ public class NotEnoughUpdates { } } //AH prices - if(Minecraft.getMinecraft().currentScreen != null) { + /*if(Minecraft.getMinecraft().currentScreen != null) { if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; ContainerChest container = (ContainerChest) chest.inventorySlots; @@ -804,7 +999,7 @@ public class NotEnoughUpdates { } } } - } + }*/ if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || !manager.config.dev.value) return; if(event.toolTip.size()>0&&event.toolTip.get(event.toolTip.size()-1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) { event.toolTip.remove(event.toolTip.size()-1); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/StreamerMode.java b/src/main/java/io/github/moulberry/notenoughupdates/StreamerMode.java index 3ad2eba6..051313d1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/StreamerMode.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/StreamerMode.java @@ -1,5 +1,7 @@ package io.github.moulberry.notenoughupdates; +import io.github.moulberry.notenoughupdates.util.Utils; + import java.io.File; import java.io.IOException; import java.io.PrintWriter; @@ -26,7 +28,7 @@ public class StreamerMode { } public static String filterScoreboard(String line) { - line = filterLobbyNames(cleanDuplicateColourCodes(line)); + line = filterLobbyNames(Utils.cleanDuplicateColourCodes(line)); return line; } @@ -35,29 +37,4 @@ public class StreamerMode { return line; } - private static String cleanDuplicateColourCodes(String line) { - StringBuilder sb = new StringBuilder(); - char currentColourCode = 'r'; - boolean sectionSymbolLast = false; - for(char c : line.toCharArray()) { - if((int)c > 50000) continue; - - if(c == '\u00a7') { - sectionSymbolLast = true; - } else { - if(sectionSymbolLast) { - if(currentColourCode != c) { - sb.append('\u00a7'); - sb.append(c); - currentColourCode = c; - } - sectionSymbolLast = false; - } else { - sb.append(c); - } - } - } - return sb.toString(); - } - } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/AuctionManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index 3f87f774..20ac86ba 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/AuctionManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -5,24 +5,22 @@ import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.event.ClickEvent; +import net.minecraft.event.HoverEvent; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; import net.minecraft.util.EnumChatFormatting; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -public class AuctionManager { +public class APIManager { private NEUManager manager; public final CustomAH customAH; @@ -34,10 +32,17 @@ public class AuctionManager { private TreeMap<String, Auction> auctionMap = new TreeMap<>(); public HashMap<String, HashSet<String>> internalnameToAucIdMap = new HashMap<>(); private HashSet<String> playerBids = new HashSet<>(); + private HashSet<String> playerBidsNotified = new HashSet<>(); + private HashSet<String> playerBidsFinishedNotified = new HashSet<>(); - public TreeMap<String, HashSet<String>> extrasToAucIdMap = new TreeMap<>(); + private HashMap<String, TreeMap<Integer, String>> internalnameToLowestBIN = new HashMap<>(); + + private JsonArray playerInformation = null; + + public TreeMap<String, HashMap<Integer, HashSet<String>>> extrasToAucIdMap = new TreeMap<>(); private long lastPageUpdate = 0; + private long lastProfileUpdate = 0; private long lastCustomAHSearch = 0; private long lastCleanup = 0; @@ -48,11 +53,28 @@ public class AuctionManager { public int taggedAuctions = 0; public int processMillis = 0; - public AuctionManager(NEUManager manager) { + private boolean doFullUpdate = false; + + public APIManager(NEUManager manager) { this.manager = manager; customAH = new CustomAH(manager); } + public JsonObject getPlayerInformation() { + if(playerInformation == null) return null; + for(int i=0; i<playerInformation.size(); i++) { + JsonObject profile = playerInformation.get(i).getAsJsonObject(); + if(profile.get("cute_name").getAsString().equalsIgnoreCase(manager.getCurrentProfile())) { + if(!profile.has("members")) return null; + JsonObject members = profile.get("members").getAsJsonObject(); + String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); + if(!members.has(uuid)) return null; + return members.get(uuid).getAsJsonObject(); + } + } + return null; + } + public TreeMap<String, Auction> getAuctionItems() { return auctionMap; } @@ -111,6 +133,11 @@ public class AuctionManager { if(System.currentTimeMillis() - lastPageUpdate > 5*1000) { lastPageUpdate = System.currentTimeMillis(); updatePageTick(); + ahNotification(); + } + if(System.currentTimeMillis() - lastProfileUpdate > 10*1000) { + lastProfileUpdate = System.currentTimeMillis(); + updateProfiles(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")); } if(System.currentTimeMillis() - lastCleanup > 120*1000) { lastCleanup = System.currentTimeMillis(); @@ -125,6 +152,100 @@ public class AuctionManager { } } + public void updateProfiles(String uuid) { + HashMap<String, String> args = new HashMap<>(); + args.put("uuid", ""+uuid); + manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles", + args, jsonObject -> { + if(jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + playerInformation = jsonObject.get("profiles").getAsJsonArray(); + if(playerInformation == null) return; + String backup = null; + long backupLastSave = 0; + for(int i=0; i<playerInformation.size(); i++) { + JsonObject profile = playerInformation.get(i).getAsJsonObject(); + String cute_name = profile.get("cute_name").getAsString(); + + if(backup == null) backup = cute_name; + + if(!profile.has("members")) continue; + JsonObject members = profile.get("members").getAsJsonObject(); + + if(members.has(uuid)) { + JsonObject member = members.get(uuid).getAsJsonObject(); + long last_save = member.get("last_save").getAsLong(); + if(last_save > backupLastSave) { + backupLastSave = last_save; + backup = cute_name; + } + } + } + + manager.setCurrentProfileBackup(backup); + } + } + ); + } + + private String niceAucId(String aucId) { + if(aucId.length()!=32) return aucId; + + StringBuilder niceAucId = new StringBuilder(); + niceAucId.append(aucId, 0, 8); + niceAucId.append("-"); + niceAucId.append(aucId, 8, 12); + niceAucId.append("-"); + niceAucId.append(aucId, 12, 16); + niceAucId.append("-"); + niceAucId.append(aucId, 16, 20); + niceAucId.append("-"); + niceAucId.append(aucId, 20, 32); + return niceAucId.toString(); + } + + public int getLowestBin(String internalname) { + TreeMap<Integer, String> lowestBIN = internalnameToLowestBIN.get(internalname); + if(lowestBIN == null || lowestBIN.isEmpty()) return -1; + return lowestBIN.firstKey(); + } + + private void ahNotification() { + playerBidsNotified.retainAll(playerBids); + playerBidsFinishedNotified.retainAll(playerBids); + if(manager.config.ahNotification.value <= 0) { + return; + } + for(String aucid : playerBids) { + Auction auc = auctionMap.get(aucid); + if(!playerBidsNotified.contains(aucid)) { + if(auc != null && auc.end - System.currentTimeMillis() < 1000*60*manager.config.ahNotification.value) { + ChatComponentText message = new ChatComponentText( + EnumChatFormatting.YELLOW+"The " + auc.getStack().getDisplayName() + EnumChatFormatting.YELLOW + " you have bid on is ending soon! Click here to view."); + ChatStyle clickEvent = new ChatStyle().setChatClickEvent( + new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewauction " + niceAucId(aucid))); + clickEvent.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW+"View auction"))); + message.setChatStyle(clickEvent); + Minecraft.getMinecraft().thePlayer.addChatMessage(message); + + playerBidsNotified.add(aucid); + } + } + if(!playerBidsFinishedNotified.contains(aucid)) { + if(auc != null && auc.end < System.currentTimeMillis()) { + ChatComponentText message = new ChatComponentText( + EnumChatFormatting.YELLOW+"The " + auc.getStack().getDisplayName() + EnumChatFormatting.YELLOW + " you have bid on (might) have ended! Click here to view."); + ChatStyle clickEvent = new ChatStyle().setChatClickEvent( + new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/viewauction " + niceAucId(aucid))); + clickEvent.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW+"View auction"))); + message.setChatStyle(clickEvent); + Minecraft.getMinecraft().thePlayer.addChatMessage(message); + + playerBidsFinishedNotified.add(aucid); + } + } + } + } + private void cleanup() { try { long currTime = System.currentTimeMillis(); @@ -141,15 +262,19 @@ public class AuctionManager { for(String aucid : toRemove) { auctionMap.remove(aucid); } - for(HashSet<String> aucids : extrasToAucIdMap.values()) { - for(String aucid : toRemove) { - aucids.remove(aucid); + for(HashMap<Integer, HashSet<String>> extrasMap : extrasToAucIdMap.values()) { + for(HashSet<String> aucids : extrasMap.values()) { + for(String aucid : toRemove) { + aucids.remove(aucid); + } } } for(HashSet<String> aucids : internalnameToAucIdMap.values()) { aucids.removeAll(toRemove); } - playerBids.removeAll(toRemove); + for(TreeMap<Integer, String> lowestBINs : internalnameToLowestBIN.values()) { + lowestBINs.values().removeAll(toRemove); + } } catch(ConcurrentModificationException e) { cleanup(); } @@ -158,6 +283,11 @@ public class AuctionManager { private void updatePageTick() { if(totalPages == 0) { getPageFromAPI(0); + } else if(doFullUpdate) { + doFullUpdate = false; + for(int i=0; i<totalPages; i++) { + getPageFromAPI(i); + } } else { if(needUpdate.isEmpty()) resetNeedUpdate(); @@ -180,8 +310,10 @@ public class AuctionManager { internalnameTaggedAuctions = aucs.size(); totalTags = extrasToAucIdMap.size(); aucs = new HashSet<>(); - for(HashSet<String> aucids : extrasToAucIdMap.values()) { - aucs.addAll(aucids); + for(HashMap<Integer, HashSet<String>> extrasMap : extrasToAucIdMap.values()) { + for(HashSet<String> aucids : extrasMap.values()) { + aucs.addAll(aucids); + } } taggedAuctions = aucs.size(); } catch(Exception e) {} @@ -191,14 +323,22 @@ public class AuctionManager { "COMMON", "UNCOMMON", "RARE", "EPIC", "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", }; - public int checkItemType(String lore, String... typeMatches) { + public int checkItemType(String lore, boolean contains, String... typeMatches) { String[] split = lore.split("\n"); for(int i=split.length-1; i>=0; i--) { String line = split[i]; for(String rarity : rarityArr) { for(int j=0; j<typeMatches.length; j++) { - if(line.trim().endsWith(rarity + " " + typeMatches[j])) { - return j; + if(contains) { + if(line.trim().contains(rarity + " " + typeMatches[j])) { + return j; + } + } else { + if(line.trim().endsWith(rarity + " " + typeMatches[j])) { + return j; + } else if(line.trim().endsWith(rarity + " DUNGEON " + typeMatches[j])) { + return j; + } } } } @@ -219,6 +359,10 @@ public class AuctionManager { int lastUpdated = jsonObject.get("lastUpdated").getAsInt(); if(lastApiUpdate != lastUpdated) { + if(manager.config.quickAHUpdate.value && + (Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView())) { + doFullUpdate = true; + } resetNeedUpdate(); } @@ -253,7 +397,6 @@ public class AuctionManager { String rarity = auction.get("tier").getAsString(); JsonArray bids = auction.get("bids").getAsJsonArray(); - for(String lvl4Max : lvl4Maxes) { item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1"); } @@ -286,12 +429,24 @@ public class AuctionManager { tag.setTag("display", display); item_tag.getTagList("i", 10).getCompoundTagAt(0).setTag("tag", tag); - for(String str : extras.replaceAll(displayNormal, "").split(" ")) { + int index=0; + for(String str : extras.split(" ")) { str = Utils.cleanColour(str).toLowerCase(); if(str.length() > 0) { - HashSet<String> aucids = extrasToAucIdMap.computeIfAbsent(str, k -> new HashSet<>()); + HashMap<Integer, HashSet<String>> extrasMap = extrasToAucIdMap.computeIfAbsent(str, k -> new HashMap<>()); + HashSet<String> aucids = extrasMap.computeIfAbsent(index, k -> new HashSet<>()); aucids.add(auctionUuid); } + index++; + } + + if(bin) { + TreeMap<Integer, String> lowestBINs = internalnameToLowestBIN.computeIfAbsent(internalname, k -> new TreeMap<>()); + int count = item_tag.getInteger("Count"); + lowestBINs.put(starting_bid/(count>0?count:1), auctionUuid); + if(lowestBINs.size() > 5) { + lowestBINs.keySet().remove(lowestBINs.lastKey()); + } } for(int j=0; j<bids.size(); j++) { @@ -301,9 +456,15 @@ public class AuctionManager { } } + if(checkItemType(item_lore, true, "DUNGEON") >= 0) { + HashMap<Integer, HashSet<String>> extrasMap = extrasToAucIdMap.computeIfAbsent("dungeon", k -> new HashMap<>()); + HashSet<String> aucids = extrasMap.computeIfAbsent(0, k -> new HashSet<>()); + aucids.add(auctionUuid); + } + //Categories String category = sbCategory; - int itemType = checkItemType(item_lore, "SWORD", "FISHING ROD", "PICKAXE", + int itemType = checkItemType(item_lore, false,"SWORD", "FISHING ROD", "PICKAXE", "AXE", "SHOVEL", "PET ITEM", "TRAVEL SCROLL", "REFORGE STONE", "BOW"); if(itemType >= 0 && itemType < categoryItemType.length) { category = categoryItemType[itemType]; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java index dd02c887..17ce216e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java @@ -1,8 +1,6 @@ package io.github.moulberry.notenoughupdates.auction; import io.github.moulberry.notenoughupdates.NEUManager; -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.util.TexLoc; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -283,7 +281,7 @@ public class CustomAH extends Gui { } public List<String> getTooltipForAucId(String aucId) { - AuctionManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucId); + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucId); List<String> tooltip = new ArrayList<>(); @@ -473,7 +471,7 @@ public class CustomAH extends Gui { long auctionViewEndsIn = prettyTimeToMillis(endsInStr); if(auctionViewEndsIn > 0) { if(System.currentTimeMillis() - currAucIdSetTimer > 1000) { - AuctionManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); if(auc != null) { auc.end = auctionViewEndsIn + lastGuiScreenSwitch; } @@ -943,7 +941,7 @@ public class CustomAH extends Gui { return mainCategory.subcategories[clickedSubCategory]; } - private boolean doesAucMatch(AuctionManager.Auction auc) { + private boolean doesAucMatch(APIManager.Auction auc) { if(auc == null) return false; Category currentCategory = getCurrentCategory(); @@ -988,28 +986,48 @@ public class CustomAH extends Gui { Set<String> itemMatches = manager.search(query); for(String internalname : itemMatches) { for(String aucid : manager.auctionManager.getAuctionsForInternalname(internalname)) { - AuctionManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); if(doesAucMatch(auc)) { - matches.add(aucid); + //matches.add(aucid); } else { dontMatch.add(aucid); } } } - if(!query.contains(" ")) { - for(HashSet<String> aucids : manager.subMapWithKeysThatAreSuffixes(query, + HashMap<String, List<Integer>> extrasMatches = new HashMap<>(); + HashMap<String, List<Integer>> extrasMatchesCurrent = new HashMap<>(); + boolean first = true; + for(String subQuery : query.split(" ")) { + for(HashMap<Integer, HashSet<String>> extrasMap : manager.subMapWithKeysThatAreSuffixes(subQuery.toLowerCase(), manager.auctionManager.extrasToAucIdMap).values()) { - for(String aucid : aucids) { - AuctionManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); - if(!dontMatch.contains(aucid) && doesAucMatch(auc)) { - matches.add(aucid); - } else { - dontMatch.add(aucid); + for(int index : extrasMap.keySet()) { + for(String aucid : extrasMap.get(index)) { + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + if(!dontMatch.contains(aucid) && doesAucMatch(auc)) { + if(first) { + List<Integer> indexList = extrasMatchesCurrent.computeIfAbsent(aucid, k -> new ArrayList<>()); + indexList.add(index); + } else { + List<Integer> indexList = extrasMatches.computeIfAbsent(aucid, k -> new ArrayList<>()); + if(indexList.contains(index-1)) { + List<Integer> indexListCurrent = extrasMatchesCurrent.computeIfAbsent(aucid, k -> new ArrayList<>()); + indexListCurrent.add(index); + } + } + } else { + dontMatch.add(aucid); + } } } + } + + extrasMatches = (HashMap<String, List<Integer>>) extrasMatchesCurrent.clone(); + extrasMatchesCurrent.clear(); + first = false; } + matches.addAll(extrasMatches.keySet()); return matches; } @@ -1036,13 +1054,13 @@ public class CustomAH extends Gui { auctionIds.clear(); if(filterMyAuctions) { for(String aucid : manager.auctionManager.getPlayerBids()) { - AuctionManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); if(doesAucMatch(auc)) { auctionIds.add(aucid); } } } else if(searchField.getText().length() == 0) { - for(Map.Entry<String, AuctionManager.Auction> entry : manager.auctionManager.getAuctionItems().entrySet()) { + for(Map.Entry<String, APIManager.Auction> entry : manager.auctionManager.getAuctionItems().entrySet()) { if(doesAucMatch(entry.getValue())) { auctionIds.add(entry.getKey()); } @@ -1053,7 +1071,7 @@ public class CustomAH extends Gui { HashSet<String> allMatch = new HashSet<>(); if(query.contains("!")) { //only used for inverted queries, so dont need to populate unless ! in query - for(Map.Entry<String, AuctionManager.Auction> entry : manager.auctionManager.getAuctionItems().entrySet()) { + for(Map.Entry<String, APIManager.Auction> entry : manager.auctionManager.getAuctionItems().entrySet()) { if(doesAucMatch(entry.getValue())) { allMatch.add(entry.getKey()); } else { @@ -1124,8 +1142,8 @@ public class CustomAH extends Gui { sortedAuctionIds.clear(); sortedAuctionIds.addAll(auctionIds); sortedAuctionIds.sort((o1, o2) -> { - AuctionManager.Auction auc1 = manager.auctionManager.getAuctionItems().get(o1); - AuctionManager.Auction auc2 = manager.auctionManager.getAuctionItems().get(o2); + APIManager.Auction auc1 = manager.auctionManager.getAuctionItems().get(o1); + APIManager.Auction auc2 = manager.auctionManager.getAuctionItems().get(o2); if(auc1 == null) return 1; if(auc2 == null) return -1; @@ -1311,8 +1329,10 @@ public class CustomAH extends Gui { break; case 8: if(rightClicked) { - StringSelection selection = new StringSelection(niceAucId(currentAucId)); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + if(currentAucId != null) { + StringSelection selection = new StringSelection(niceAucId(currentAucId)); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + } } else { manager.auctionManager.calculateStats(); } @@ -1424,7 +1444,7 @@ public class CustomAH extends Gui { aucid = sortedAuctionIds.get(id); } catch (IndexOutOfBoundsException e) { break out; } - AuctionManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); if(auc != null) { if(mouseX > itemX && mouseX < itemX+16) { if(mouseY > itemY && mouseY < itemY+16) { 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 9afbd17f..331ba8b1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java @@ -1,10 +1,13 @@ package io.github.moulberry.notenoughupdates.cosmetics; +import io.github.moulberry.notenoughupdates.NEUManager; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -25,9 +28,13 @@ public class CapeManager { public void setCape(String player, String capename) { if(capename == null) { + NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value = ""; capeMap.remove(player); return; } + if(player.equalsIgnoreCase(Minecraft.getMinecraft().thePlayer.getName())) { + NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value = capename; + } if(capeMap.containsKey(player)) { Pair<NEUCape, String> capePair = capeMap.get(player); capePair.setValue(capename); @@ -56,6 +63,14 @@ public class CapeManager { @SubscribeEvent public void onRenderPlayer(RenderPlayerEvent.Post e) { + if(e.partialRenderTick == 1.0F) return; //rendering in inventory + if(e.entityPlayer == Minecraft.getMinecraft().thePlayer) { + if(NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value != null && + !NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value.isEmpty()) { + setCape(Minecraft.getMinecraft().thePlayer.getName(), + NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value); + } + } if(capeMap.containsKey(e.entityPlayer.getName())) { capeMap.get(e.entityPlayer.getName()).getLeft().onRenderPlayer(e); } @@ -87,15 +102,20 @@ public class CapeManager { return capes; } + private String[] contributors = new String[]{"thatgravyboat", "twasnt", "traxyrr", "some1sm", "meguminqt", "marethyu_77"}; + public boolean getPermissionForCape(String player, String capename) { if(capename == null) { return false; } else if(player.equalsIgnoreCase("Moulberry")) { return true; //Oh yeah gimme gimme - } else if(capename.equals("nullzee")) { - return player.equalsIgnoreCase("Nullzee"); - } else if(capename.equals("gravy")) { - return player.equalsIgnoreCase("ThatGravyBoat"); + } else { + switch(capename) { + case "nullzee": return player.equalsIgnoreCase("Nullzee"); + case "gravy": return player.equalsIgnoreCase("ThatGravyBoat"); + case "contrib": return ArrayUtils.contains(contributors, player.toLowerCase()); + case "fade": return true; + } } return false; } 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 8ca3a538..08d91057 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java @@ -244,7 +244,7 @@ public class NEUCape { shaderManager.loadShader(shaderName); loadShaderUniforms(shaderManager); - if(!Keyboard.isKeyDown(Keyboard.KEY_K)) renderCape(player, e.partialRenderTick); + renderCape(player, e.partialRenderTick); GL11.glTranslatef((float)viewerX, (float)viewerY, (float)viewerZ); @@ -569,7 +569,7 @@ public class NEUCape { newPosition.y = node.lastPosition.y + (node.position.y - node.lastPosition.y) * partialRenderTick; newPosition.z = node.lastPosition.z + (node.position.z - node.lastPosition.z) * partialRenderTick; - if(node.oldRenderPosition[node.oldRenderPosition.length-1] == null || Keyboard.isKeyDown(Keyboard.KEY_B)) { + if(node.oldRenderPosition[node.oldRenderPosition.length-1] == null) { node.renderPosition = newPosition; } else { Vector3f accum = new Vector3f(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java index 38edc0f9..5f9e6af1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java @@ -40,6 +40,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { private int previousX = 0; private int previousFilter = 0; + private long lastUpdate = 0; + private static final int FILTER_ALL = 0; private static final int FILTER_WEAPON = 1; private static final int FILTER_ARMOR = 2; @@ -58,6 +60,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { private Framebuffer itemFramebufferGrayscale = null; private Shader grayscaleShader = null; + private int updateCounter = 0; + public CollectionLogInfoPane(NEUOverlay overlay, NEUManager manager) { super(overlay, manager); refreshItems(); @@ -75,6 +79,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { items.clear(); for(String internalname : manager.getItemInformation().keySet()) { if(!manager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) { + JsonObject item = manager.getItemInformation().get(internalname); JsonArray lore = manager.getItemInformation().get(internalname).get("lore").getAsJsonArray(); switch(filterMode) { case FILTER_WEAPON: @@ -87,19 +92,19 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { if(overlay.checkItemType(lore, "ACCESSORY") < 0) continue; break; case FILTER_PET: - if(!internalname.matches(petRegex)) continue; + if(!internalname.matches(petRegex) || !item.get("displayname").getAsString().contains("[")) continue; break; case FILTER_TOOL: if(overlay.checkItemType(lore, "AXE", "PICKAXE", "FISHING ROD", "SHOVEL", "HOE") < 0) continue; break; case FILTER_SLAYER_ZOMBIE: - if(!loreContains(lore, "\u00A7c\u2620 \u00A75Requires Zombie")) continue; + if(!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("ZOMBIE")) continue; break; case FILTER_SLAYER_WOLF: - if(!loreContains(lore, "\u00A7c\u2620 \u00A75Requires Wolf")) continue; + if(!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("WOLF")) continue; break; case FILTER_SLAYER_SPIDER: - if(!loreContains(lore, "\u00A7c\u2620 \u00A75Requires Spider")) continue; + if(!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("SPIDER")) continue; break; } items.add(internalname); @@ -113,8 +118,11 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { private Comparator<String> getItemComparator() { return (o1, o2) -> { - float cost1 = manager.getCraftCost(o1).craftCost; - float cost2 = manager.getCraftCost(o2).craftCost; + float cost1 = manager.auctionManager.getLowestBin(o1); + float cost2 = manager.auctionManager.getLowestBin(o2); + + if(cost1 == -1) cost1 = manager.getCraftCost(o1).craftCost; + if(cost2 == -1) cost2 = manager.getCraftCost(o2).craftCost; if(cost1 < cost2) return 1; if(cost1 > cost2) return -1; @@ -160,8 +168,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { int own = 0; for(String item : items) { if(getAcquiredItems() != null && - getAcquiredItems().containsKey(manager.currentProfile) && - getAcquiredItems().get(manager.currentProfile).contains(item)) { + getAcquiredItems().containsKey(manager.getCurrentProfile()) && + getAcquiredItems().get(manager.getCurrentProfile()).contains(item)) { own++; } @@ -248,8 +256,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { public int getCurrentAcquiredCount() { if(getAcquiredItems() == null) return 0; - if(!getAcquiredItems().containsKey(manager.currentProfile)) return 0; - return getAcquiredItems().get(manager.currentProfile).size(); + if(!getAcquiredItems().containsKey(manager.getCurrentProfile())) return 0; + return getAcquiredItems().get(manager.getCurrentProfile()).size(); } private void renderCollectionLog(Color fg, int width, int height, int left, int right, int top, int bottom) { @@ -272,7 +280,9 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { scaledresolution.getScaleFactor()); if(!manager.config.cacheRenderedItempane.value || previousAcquiredCount != getCurrentAcquiredCount() || - previousScroll != scrollHeight.getValue() || previousX != left || previousFilter != filterMode) { + previousScroll != scrollHeight.getValue() || previousX != left || previousFilter != filterMode || + System.currentTimeMillis() - lastUpdate > 5000) { + lastUpdate = System.currentTimeMillis(); renderItemsToImage(itemFramebuffer, fg, left+5, right, top+1, bottom); renderItemBGToImage(itemBGFramebuffer, fg, left+5, right, top+1, bottom); } @@ -316,35 +326,37 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { iterateItemSlots(new ItemSlotConsumer() { @Override public void consume(int x, int y, int id) { - String internalname = items[id]; - if(id == 0) isTop.set(true); + if(id < items.length) { + String internalname = items[id]; + if(id == 0) isTop.set(true); - int leftI = x-1; - int rightI = x+17; - int topI = y-1; - int bottomI = y+17; + int leftI = x-1; + int rightI = x+17; + int topI = y-1; + int bottomI = y+17; - lowestY.set(Math.max(bottomI, lowestY.get())); + lowestY.set(Math.max(bottomI, lowestY.get())); - if(mouseX > leftI && mouseX < rightI) { - if(mouseY > topI && mouseY < bottomI) { - tooltipToDisplay.set(manager.getItemInformation().get(internalname)); + if(mouseX > leftI && mouseX < rightI) { + if(mouseY > topI && mouseY < bottomI) { + tooltipToDisplay.set(manager.getItemInformation().get(internalname)); + } } - } - if(getAcquiredItems() != null && - getAcquiredItems().containsKey(manager.currentProfile) && - getAcquiredItems().get(manager.currentProfile).contains(internalname)) { - return; - } + if(getAcquiredItems() != null && + getAcquiredItems().containsKey(manager.getCurrentProfile()) && + getAcquiredItems().get(manager.getCurrentProfile()).contains(internalname)) { + return; + } - topI = Math.max(topI, top); - bottomI = Math.min(bottomI, bottom); + topI = Math.max(topI, top); + bottomI = Math.min(bottomI, bottom); - Utils.drawTexturedRect(leftI, topI, rightI-leftI, bottomI-topI, - leftI/(float)width, rightI/(float)width, - (height-topI)/(float)height, (height-bottomI)/(float)height); + Utils.drawTexturedRect(leftI, topI, rightI-leftI, bottomI-topI, + leftI/(float)width, rightI/(float)width, + (height-topI)/(float)height, (height-bottomI)/(float)height); + } } }, left+5, right, top+1, bottom); @@ -410,24 +422,26 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { String[] items = getItemList(); iterateItemSlots(new ItemSlotConsumer() { public void consume(int x, int y, int id) { - String internalname = items[id]; + if(id < items.length) { + String internalname = items[id]; - Color color = fgCustomOpacity; - if(getAcquiredItems() != null && - getAcquiredItems().containsKey(manager.currentProfile) && - getAcquiredItems().get(manager.currentProfile).contains(internalname)) { - color = fgGold; - } + Color color = fgCustomOpacity; + if(getAcquiredItems() != null && + getAcquiredItems().containsKey(manager.getCurrentProfile()) && + getAcquiredItems().get(manager.getCurrentProfile()).contains(internalname)) { + color = fgGold; + } - Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); - if(manager.config.itemStyle.value) { - GlStateManager.color(color.getRed() / 255f, color.getGreen() / 255f, - color.getBlue() / 255f, color.getAlpha() / 255f); - Utils.drawTexturedRect(x - 1, y - 1, overlay.ITEM_SIZE + 2, overlay.ITEM_SIZE + 2, GL11.GL_NEAREST); - } else { - drawRect(x-1, y-1, x+overlay.ITEM_SIZE+1, y+overlay.ITEM_SIZE+1, color.getRGB()); + Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); + if(manager.config.itemStyle.value) { + GlStateManager.color(color.getRed() / 255f, color.getGreen() / 255f, + color.getBlue() / 255f, color.getAlpha() / 255f); + Utils.drawTexturedRect(x - 1, y - 1, overlay.ITEM_SIZE + 2, overlay.ITEM_SIZE + 2, GL11.GL_NEAREST); + } else { + drawRect(x-1, y-1, x+overlay.ITEM_SIZE+1, y+overlay.ITEM_SIZE+1, color.getRGB()); + } + GlStateManager.bindTexture(0); } - GlStateManager.bindTexture(0); } }, left, right, top, bottom); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java index e972e2c8..707968e3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java @@ -68,13 +68,9 @@ public class CosmeticsInfoPane extends InfoPane { public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) { if(mouseDown && selectedCape != null) { if(selectedCape.equals(CapeManager.getInstance().getCape(Minecraft.getMinecraft().thePlayer.getName()))) { - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - CapeManager.getInstance().setCape(player.getName(), null); - } + CapeManager.getInstance().setCape(Minecraft.getMinecraft().thePlayer.getName(), null); } else { - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - CapeManager.getInstance().setCape(player.getName(), selectedCape); - } + CapeManager.getInstance().setCape(Minecraft.getMinecraft().thePlayer.getName(), selectedCape); } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java deleted file mode 100644 index 5cc7211e..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java +++ /dev/null @@ -1,341 +0,0 @@ -package io.github.moulberry.notenoughupdates.infopanes; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.NEUManager; -import io.github.moulberry.notenoughupdates.NEUOverlay; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompressedStreamTools; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.EnumChatFormatting; - -import java.awt.*; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.*; -import java.util.List; - -public class QOLInfoPane extends ScrollableInfoPane { - - /** - * Not currently used in BETA-1.6 - */ - - private LinkedHashMap<String, ItemStack> accessoryMap = new LinkedHashMap<>(); - private LinkedHashMap<String, JsonObject> allTalismans = new LinkedHashMap<>(); - private List<JsonObject> recommended = new ArrayList<>(); - private int maxAccessories = 39; //TODO: Get from API - - private Integer[] talismanRarityValue = new Integer[]{1, 2, 4, 7, 10}; - - public QOLInfoPane(NEUOverlay overlay, NEUManager manager) { - super(overlay, manager); - - Comparator<JsonObject> rarityComparator = new Comparator<JsonObject>() { - @Override - public int compare(JsonObject o1, JsonObject o2) { - int rarity1 = overlay.getRarity(o1.get("lore").getAsJsonArray()); - int rarity2 = overlay.getRarity(o2.get("lore").getAsJsonArray()); - - int rarityDiff = rarity2 - rarity1; - if(rarityDiff != 0) { - return rarityDiff; - } - - return o2.get("internalname").getAsString().compareTo(o1.get("internalname").getAsString()); - } - }; - - TreeSet<JsonObject> all = new TreeSet<>(rarityComparator); - LinkedHashMap<String, JsonObject> highestRarity = new LinkedHashMap<>(); - LinkedHashMap<String, JsonObject> lowerRarity = new LinkedHashMap<>(); - - for(Map.Entry<String, JsonObject> entry : manager.getItemInformation().entrySet()) { - if(overlay.checkItemType(entry.getValue().get("lore").getAsJsonArray(), "ACCESSORY") >= 0) { - all.add(entry.getValue()); - } - } - outer: - for(JsonObject o : all) { - String internalname = o.get("internalname").getAsString(); - String name = getTalismanName(internalname); - int power = getTalismanPower(internalname); - for(JsonObject o2 : all) { - if(o != o2) { - String internalname2 = o2.get("internalname").getAsString(); - String name2 = getTalismanName(internalname2); - if(name2.equals(name)) { - int power2 = getTalismanPower(internalname2); - if(power2 > power) { - lowerRarity.put(internalname, o); - continue outer; - } - } - } - } - highestRarity.put(internalname, o); - } - for(Map.Entry<String, JsonObject> entry : highestRarity.entrySet()) { - allTalismans.put(entry.getKey(), entry.getValue()); - } - for(Map.Entry<String, JsonObject> entry : lowerRarity.entrySet()) { - allTalismans.put(entry.getKey(), entry.getValue()); - } - - HashMap<String, String> args = new HashMap<>(); - String uuid = Minecraft.getMinecraft().thePlayer.getGameProfile().getId().toString(); - args.put("uuid", uuid); - manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles", - args, jsonObject -> { - if(jsonObject.get("success").getAsBoolean()) { - JsonObject currProfile = null; - for(JsonElement e : jsonObject.get("profiles").getAsJsonArray()) { - JsonObject profile = e.getAsJsonObject(); - String profileId = profile.get("profile_id").getAsString(); - String cuteName = profile.get("cute_name").getAsString(); - - if(manager.currentProfile.equals(cuteName)) { - JsonObject members = profile.get("members").getAsJsonObject(); - JsonObject profile_member = members.get(uuid.replaceAll("-","")).getAsJsonObject(); - currProfile = profile_member; - } - } - if(currProfile.has("talisman_bag")) { - String b64 = currProfile.get("talisman_bag").getAsJsonObject().get("data").getAsString(); - try { - NBTTagCompound tag = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(b64))); - NBTTagList list = tag.getTagList("i", 10); - for(int i=0; i<list.tagCount(); i++) { - NBTTagCompound accessory = list.getCompoundTagAt(i); - if(accessory.hasKey("tag")) { - String accessoryID = accessory.getCompoundTag("tag") - .getCompoundTag("ExtraAttributes").getString("id"); - ItemStack accessoryStack = ItemStack.loadItemStackFromNBT(accessory); - accessoryMap.put(accessoryID, accessoryStack); - } - - } - } catch(IOException e) { - } - - int lowestRarity = -1; - if(accessoryMap.size() >= maxAccessories) { - lowestRarity = 999; - for(Map.Entry<String, ItemStack> entry : accessoryMap.entrySet()) { - JsonObject json = manager.getJsonForItem(entry.getValue()); - int rarity = overlay.getRarity(json.get("lore").getAsJsonArray()); - if(rarity < lowestRarity) { - lowestRarity = rarity; - } - } - } - System.out.println("lowestrarity:"+lowestRarity); - - TreeMap<Float, JsonObject> valueMap = new TreeMap<>(); - outer: - for(Map.Entry<String, JsonObject> entry : allTalismans.entrySet()) { - int rarity = overlay.getRarity(entry.getValue().get("lore").getAsJsonArray()); - System.out.println(entry.getKey() + ":" + rarity); - if(rarity > lowestRarity) { - System.out.println("found greater:"+entry.getKey()); - float rarityVal = (float)talismanRarityValue[rarity]; - System.out.println("rarity val:"+rarityVal); - float price = manager.getCraftCost(entry.getKey()).craftCost; - - System.out.println("cc:"+price); - if(price < 0) { - System.out.println("invalid price:"+entry.getKey()); - continue; - } - - String internalname = entry.getValue().get("internalname").getAsString(); - String name = getTalismanName(internalname); - int power = getTalismanPower(internalname); - for(Map.Entry<String, ItemStack> entry2 : accessoryMap.entrySet()) { - try { - JsonObject json = manager.getJsonForItem(entry2.getValue()); - String internalname2 = json.get("internalname").getAsString(); - - if(internalname.equals(internalname2)) { - //continue outer; - } - - String name2 = getTalismanName(internalname2); - } catch(Exception e) { - e.printStackTrace(); - System.out.println(":( -> " + entry2.getKey()); - } - - - /*if(name2.equals(name)) { - int power2 = getTalismanPower(internalname2); - if(power2 > power) { - continue outer; - } - }*/ - } - - valueMap.put(-rarityVal/price, entry.getValue()); - } - } - System.out.println("valuemap size:"+valueMap.size()); - int i=0; - for(Map.Entry<Float, JsonObject> entry : valueMap.entrySet()) { - recommended.add(entry.getValue()); - if(++i >= 500) { - break; - } - } - System.out.println("recommended size:"+recommended.size()); - } - //jsonObject.get("profiles") - } - }); - } - - - String[] talismanPowers = new String[]{"RING","ARTIFACT"}; - public int getTalismanPower(String internalname) { - for(int i=0; i<talismanPowers.length; i++) { - if(internalname.endsWith("_"+talismanPowers[i])) { - return i+1; - } - } - return 0; - } - - public String getTalismanName(String internalname) { - String[] split = internalname.split("_"); - StringBuilder name = new StringBuilder(); - for(int i=0; i<split.length; i++) { - name.append(split[i]); - if(i < split.length-1) { - name.append("_"); - } - } - return name.toString(); - } - - public void render(int width, int height, Color bg, Color fg, ScaledResolution scaledresolution, int mouseX, int mouseY) { - renderDefaultBackground(width, height, bg); - - int paneWidth = (int)(width/3*overlay.getWidthMult()); - int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor()); - int leftSide = rightSide - paneWidth; - - int y=overlay.getBoxPadding()+10; - y += renderParagraph(width, height, y, "Current Accessories"); - - ItemStack display = null; - int x=leftSide+overlay.getBoxPadding()+5; - for(Map.Entry<String, ItemStack> entry : accessoryMap.entrySet()) { - if(mouseX > x && mouseX < x+16) { - if(mouseY > y && mouseY < y+16) { - display = entry.getValue(); - } - } - - drawRect(x, y, x+16, y+16, fg.getRGB()); - Utils.drawItemStack(entry.getValue(), x, y); - x += 20; - if(x + 20 + (leftSide+overlay.getBoxPadding()+5) > paneWidth) { - x=leftSide+overlay.getBoxPadding()+5; - y+=20; - } - } - - y+=20; - - y += renderParagraph(width, height, y, "Missing Accessories"); - - y+=10; - - x=leftSide+overlay.getBoxPadding()+5; - for(Map.Entry<String, JsonObject> entry : allTalismans.entrySet()) { - if(accessoryMap.containsKey(entry.getKey())) { - continue; - } - if(mouseX > x && mouseX < x+16) { - if(mouseY > y && mouseY < y+16) { - display = manager.jsonToStack(entry.getValue()); - } - } - - drawRect(x, y, x+16, y+16, fg.getRGB()); - Utils.drawItemStack(manager.jsonToStack(entry.getValue()), x, y); - x += 20; - if(x + 20 + (leftSide+overlay.getBoxPadding()+5) > paneWidth) { - x=leftSide+overlay.getBoxPadding()+5; - y+=20; - } - } - - y+=20; - y += renderParagraph(width, height, y, "Recommended Accessory Upgrades"); - - x=leftSide+overlay.getBoxPadding()+5; - for(JsonObject json : recommended) { - if(mouseX > x && mouseX < x+16) { - if(mouseY > y && mouseY < y+16) { - display = manager.jsonToStack(json); - } - } - - drawRect(x, y, x+16, y+16, fg.getRGB()); - Utils.drawItemStack(manager.jsonToStack(json), x, y); - x += 20; - if(x + 20 + (leftSide+overlay.getBoxPadding()+5) > paneWidth) { - x=leftSide+overlay.getBoxPadding()+5; - y+=20; - } - } - - //L:9/cost, E=6/cost, R=3/cost, C=1/cost - - - if(display != null) { - List<String> list = display.getTooltip(Minecraft.getMinecraft().thePlayer, - Minecraft.getMinecraft().gameSettings.advancedItemTooltips); - - for (int i = 0; i < list.size(); ++i){ - if (i == 0){ - list.set(i, display.getRarity().rarityColor + list.get(i)); - } else { - list.set(i, EnumChatFormatting.GRAY + list.get(i)); - } - } - - Utils.drawHoveringText(list, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); - } - } - - public boolean keyboardInput() { - return false; - } - - - private int renderParagraph(int width, int height, int startY, String text) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - int paneWidth = (int)(width/3*overlay.getWidthMult()); - int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor()); - int leftSide = rightSide - paneWidth; - - int yOff = 0; - for(String line : text.split("\n")) { - yOff += Utils.renderStringTrimWidth(line, fr, false,leftSide+overlay.getBoxPadding() + 5, - startY + yOff, - width*1/3-overlay.getBoxPadding()*2-10, Color.WHITE.getRGB(), -1); - yOff += 16; - } - - return yOff; - } - - -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java index 147c006c..2bba6426 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java @@ -58,13 +58,37 @@ public class SettingsInfoPane extends InfoPane { AtomicInteger tfTopX = new AtomicInteger(); AtomicInteger tfTopY = new AtomicInteger(); iterateSettingTile(new SettingsTileConsumer() { - public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option) { + public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option, Options.Button button) { float mult = tileWidth/90f; drawRect(x, y, x+tileWidth, y+tileHeight, fg.getRGB()); if(manager.config.hideApiKey.value && option==manager.config.apiKey) return; + if(option == null) { + Utils.renderStringTrimWidth(button.displayName, fr, true, x+(int)(8*mult), y+(int)(8*mult), + tileWidth-(int)(16*mult), new Color(100,255,150).getRGB(), 3, + 2f/scaledresolution.getScaleFactor()); + + GlStateManager.color(1f, 1f, 1f, 1f); + Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex); + Utils.drawTexturedRect(x + tileWidth/2f - (int) (32 * mult), y + tileHeight - (int) (20 * mult), (int) (48 * mult), (int) (16 * mult)); + + Minecraft.getMinecraft().getTextureManager().bindTexture(help); + Utils.drawTexturedRect(x + tileWidth/2f + (int) (19 * mult), y + tileHeight - (int) (19 * mult), (int) (14 * mult), (int) (14 * mult)); + GlStateManager.bindTexture(0); + + if (mouseX > x + tileWidth / 2 + (int) (19 * mult) && mouseX < x + tileWidth / 2 + (int) (19 * mult) + (int) (14 * mult)) { + if (mouseY > y + tileHeight - (int) (19 * mult) && mouseY < y + tileHeight - (int) (19 * mult) + (int) (14 * mult)) { + List<String> textLines = new ArrayList<>(); + textLines.add(button.displayName); + textLines.add(EnumChatFormatting.GRAY + button.desc); + textToDisplay.set(textLines); + } + } + return; + } + Utils.renderStringTrimWidth(option.displayName, fr, true, x+(int)(8*mult), y+(int)(8*mult), tileWidth-(int)(16*mult), new Color(100,255,150).getRGB(), 3, 2f/scaledresolution.getScaleFactor()); @@ -166,9 +190,18 @@ public class SettingsInfoPane extends InfoPane { public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) { iterateSettingTile(new SettingsTileConsumer() { @Override - public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option) { + public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option, Options.Button button) { float mult = tileWidth/90f; - if(option.value instanceof Boolean) { + if(option == null) { + if(Mouse.getEventButtonState()) { + if(mouseX > x+tileWidth/2-(int)(32*mult) && mouseX < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) { + if(mouseY > y+tileHeight-(int)(20*mult) && mouseY < y+tileHeight-(int)(20*mult)+(int)(16*mult)) { + button.click.run(); + return; + } + } + } + } else if(option.value instanceof Boolean) { if(Mouse.getEventButtonState()) { if(mouseX > x+tileWidth/2-(int)(32*mult) && mouseX < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) { if(mouseY > y+tileHeight-(int)(20*mult) && mouseY < y+tileHeight-(int)(20*mult)+(int)(16*mult)) { @@ -293,7 +326,9 @@ public class SettingsInfoPane extends InfoPane { AtomicBoolean ret = new AtomicBoolean(false); iterateSettingTile(new SettingsTileConsumer() { @Override - public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option) { + public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option, Options.Button button) { + if(option == null) return; + if(!textConfigMap.containsKey(option)) { textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0)); } @@ -312,7 +347,7 @@ public class SettingsInfoPane extends InfoPane { } private abstract static class SettingsTileConsumer { - public abstract void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option); + public abstract void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option, Options.Button button); } public void iterateSettingTile(SettingsTileConsumer settingsTileConsumer) { @@ -340,7 +375,7 @@ public class SettingsInfoPane extends InfoPane { int currPage=0; int x=0; int y=tilePadding+overlay.getBoxPadding()+overlay.getSearchBarYSize(); - for(int i=0; i<manager.config.getOptions().size(); i++) { + for(int i=0; i<manager.config.getOptions().size()+manager.config.getButtons().size(); i++) { if(i!=0 && i%numHorz==0) { x = 0; y += tileHeight+tilePadding; @@ -354,7 +389,13 @@ public class SettingsInfoPane extends InfoPane { x+=tilePadding; if(currPage == page) { - settingsTileConsumer.consume(boxLeft+x, y, tileWidth, tileHeight, manager.config.getOptions().get(i)); + if(i < manager.config.getButtons().size()) { + settingsTileConsumer.consume(boxLeft+x, y, tileWidth, tileHeight, + null, manager.config.getButtons().get(i)); + } else { + settingsTileConsumer.consume(boxLeft+x, y, tileWidth, tileHeight, + manager.config.getOptions().get(i-manager.config.getButtons().size()), null); + } } x+=tileWidth; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java new file mode 100644 index 00000000..7f0eb46f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java @@ -0,0 +1,48 @@ +package io.github.moulberry.notenoughupdates.mbgui; + +import org.lwjgl.util.vector.Vector2f; + +import java.io.Serializable; + +public class MBAnchorPoint implements Serializable { + + public enum AnchorPoint { + TOPLEFT(0, 0), TOPMID(0.5f, 0), TOPRIGHT(1, 0), + MIDRIGHT(1, 0.5f), BOTRIGHT(1, 1), BOTMID(0.5f, 1), + BOTLEFT(0, 1), MIDLEFT(0, 0.5f), MIDMID(0.5f, 0.5f); + + public final float x; + public final float y; + + AnchorPoint(float x, float y) { + this.x = x; + this.y = y; + } + } + + public AnchorPoint anchorPoint; + public Vector2f offset; + + public MBAnchorPoint(AnchorPoint anchorPoint, Vector2f offset) { + this.anchorPoint = anchorPoint; + this.offset = offset; + } + + public static MBAnchorPoint createFromString(String str) { + if(str == null || str.split(":").length != 3) { + return null; + } + + try { + String[] split = str.split(":"); + AnchorPoint point = AnchorPoint.valueOf(split[0].toUpperCase()); + Vector2f pos = new Vector2f(Float.valueOf(split[1]), Float.valueOf(split[2])); + return new MBAnchorPoint(point, pos); + } catch(Exception e) { return null; } + } + + @Override + public String toString() { + return anchorPoint.toString() + ":" + offset.x + ":" + offset.y; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java new file mode 100644 index 00000000..56a3f42c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java @@ -0,0 +1,12 @@ +package io.github.moulberry.notenoughupdates.mbgui; + +public abstract class MBGuiElement { + + public abstract int getWidth(); + public abstract int getHeight(); + public abstract void recalculate(); + public abstract void mouseClick(float x, float y, int mouseX, int mouseY); + public abstract void mouseClickOutside(); + public abstract void render(float x, float y); + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java new file mode 100644 index 00000000..4759d99b --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java @@ -0,0 +1,64 @@ +package io.github.moulberry.notenoughupdates.mbgui; + +import org.lwjgl.util.vector.Vector2f; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public abstract class MBGuiGroup extends MBGuiElement { + + public int width; + public int height; + protected HashMap<MBGuiElement, Vector2f> childrenPosition = new HashMap<>(); + + public MBGuiGroup() { + } + + public abstract Collection<MBGuiElement> getChildren(); + + public Map<MBGuiElement, Vector2f> getChildrenPosition() { + return Collections.unmodifiableMap(childrenPosition); + } + + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } + + + @Override + public void mouseClick(float x, float y, int mouseX, int mouseY) { + for(MBGuiElement child : getChildren()) { + Vector2f childPos = childrenPosition.get(child); + if(mouseX > x+childPos.x && mouseX < x+childPos.x+child.getWidth()) { + if(mouseY > y+childPos.y && mouseY < y+childPos.y+child.getHeight()) { + child.mouseClick(x+childPos.x, y+childPos.y, mouseX, mouseY); + } + } + } + } + + @Override + public void mouseClickOutside() { + for(MBGuiElement child : getChildren()) { + child.mouseClickOutside(); + } + } + + @Override + public void render(float x, float y) { + for(MBGuiElement child : getChildren()) { + Vector2f childPos = childrenPosition.get(child); + child.render(x+childPos.x, y+childPos.y); + } + } + + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java new file mode 100644 index 00000000..91cca2d7 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java @@ -0,0 +1,42 @@ +package io.github.moulberry.notenoughupdates.mbgui; + +import org.lwjgl.util.vector.Vector2f; + +import java.util.*; + +public class MBGuiGroupFloating extends MBGuiGroup { + + private LinkedHashMap<MBGuiElement, MBAnchorPoint> children; + + public MBGuiGroupFloating(int width, int height, LinkedHashMap<MBGuiElement, MBAnchorPoint> children) { + this.width = width; + this.height = height; + this.children = children; + recalculate(); + } + + public Map<MBGuiElement, MBAnchorPoint> getChildrenMap() { + return Collections.unmodifiableMap(children); + } + + @Override + public void recalculate() { + for(MBGuiElement child : children.keySet()) { + child.recalculate(); + } + + for(Map.Entry<MBGuiElement, MBAnchorPoint> entry : children.entrySet()) { + MBGuiElement child = entry.getKey(); + MBAnchorPoint anchorPoint = entry.getValue(); + float x = anchorPoint.anchorPoint.x * width - anchorPoint.anchorPoint.x * child.getWidth() + anchorPoint.offset.x; + float y = anchorPoint.anchorPoint.y * height - anchorPoint.anchorPoint.y * child.getHeight() + anchorPoint.offset.y; + childrenPosition.put(child, new Vector2f(x, y)); + } + } + + @Override + public Collection<MBGuiElement> getChildren() { + return children.keySet(); + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupHorz.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupHorz.java new file mode 100644 index 00000000..cf477eac --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupHorz.java @@ -0,0 +1,47 @@ +package io.github.moulberry.notenoughupdates.mbgui; + +import org.lwjgl.util.vector.Vector2f; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +public abstract class MBGuiGroupHorz extends MBGuiGroup { + + private List<MBGuiElement> children; + + public MBGuiGroupHorz(List<MBGuiElement> children) { + this.children = children; + recalculate(); + } + + public abstract int getPadding(); + + public Collection<MBGuiElement> getChildren() { + return children; + } + + public void recalculate() { + for(MBGuiElement child : children) { + child.recalculate(); + } + + width = 0; + for(int i=0; i<children.size(); i++) { + MBGuiElement child = children.get(i); + childrenPosition.put(child, new Vector2f(width, 0)); + width += child.getWidth(); + if(i != children.size()-1) width += getPadding(); + } + + height = 0; + for(MBGuiElement child : children) { + int childHeight = child.getHeight(); + if(childHeight > height) { + height = childHeight; + } + } + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java index 047ca5af..1c8a6e07 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java @@ -1,8 +1,17 @@ package io.github.moulberry.notenoughupdates.options; import com.google.gson.*; +import io.github.moulberry.notenoughupdates.NEUOverlayPlacements; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint; import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Util; +import net.minecraftforge.client.ClientCommandHandler; +import net.minecraftforge.client.ForgeHooksClient; +import org.lwjgl.util.vector.Vector2f; +import java.awt.*; import java.io.*; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; @@ -38,6 +47,11 @@ public class Options { "Quick Commands", false, "Shows QuickCommands™ above search bar."); + public Option<Boolean> showUpdateMsg = new Option( + true, + "Show Update Notifs", + false, + "Shows update messages if NEU is out-of-date."); public Option<Boolean> tooltipBorderColours = new Option( true, "Coloured Tooltip Borders", @@ -63,6 +77,11 @@ public class Options { "Hide Apikey Setting", false, "Hides the Apikey setting (please try not to leak Apikey if you're recording)"); + public Option<Boolean> quickAHUpdate = new Option( + false, + "NeuAH Quick Update", + false, + "Will instantly update the whole AH when an api update is detected (aka as fast as possible). Warning: Uses lots of data."); public Option<Double> bgBlurFactor = new Option( 5.0, "Background Blur", @@ -78,6 +97,16 @@ public class Options { "Automatically Update Items", false, "If true, updated items will automatically download from the remote repository when you start the game. \nHIGHLY RECOMMENDED."); + public Option<Boolean> quickcommandMousePress = new Option( + false, + "QuickCommand on Mouse Press", + false, + "If true, quickcommands will trigger on mouse down instead of mouse up."); + public Option<Boolean> disableItemTabOpen = new Option( + false, + "No Tab Open", + false, + "If True, moving your mouse to the item tab on the right side won't open the itempane."); public Option<Boolean> keepopen = new Option( false, "Keep Itempane Open", @@ -113,6 +142,16 @@ public class Options { "Pane Padding", false, "Changes the padding of the panes. Value between 0-20.", 0, 20); + public Option<Double> ahNotification = new Option( + 2.0, + "AH Notification (Mins, 0 = off)", + false, + "Minutes before AH ends to notify. 0-10.", 0, 10); + public Option<Double> tooltipBorderOpacity = new Option( + 200.0, + "Coloured Tooltip Border Opacity", + false, + "Coloured tooltips only apply to tooltips in my GUIs. Value between 0-255.", 0, 255); /** * OPTIONS THAT DON'T SHOW IN GUI @@ -122,6 +161,11 @@ public class Options { "Show Dev Options", true, "Dev Feature. Please don't use."); + public Option<String> selectedCape = new Option( + "", + "Selected Cape", + true, + "Selected Cape"); public Option<Double> compareMode = new Option( 0.0, "Compare Mode", @@ -152,6 +196,16 @@ public class Options { "Quick Commands", false, "Quick Commands"); + public Option<String> overlaySearchBar = new Option( + "", + "OverlaySearchBar", + false, + "OverlaySearchBar"); + public Option<String> overlayQuickCommand = new Option( + "", + "OverlaySearchBar", + false, + "OverlaySearchBar"); private ArrayList<String> createDefaultQuickCommands() { ArrayList<String> arr = new ArrayList<>(); @@ -160,34 +214,74 @@ public class Options { arr.add("/craft:Crafting Table:CRAFTING_TABLE"); arr.add("/enderchest:Ender Chest:ENDER_CHEST"); arr.add("/wardrobe:Wardrobe:LEATHER_CHESTPLATE"); + arr.add("/pets:Pets:BONE"); arr.add("neucl:Collection Log:MAP"); arr.add("neuah:NEU Auction House:GOLD_BLOCK"); return arr; } + public class Button { + public String displayName; + public String desc; + public Runnable click; + + public Button(String displayName, String desc, Runnable click) { + this.displayName = displayName; + this.desc = desc; + this.click = click; + } + } + + private transient List<Button> buttons = new ArrayList<>(); + { + buttons.add(new Button("Open Config Folder", "Opens the config folder. Be careful.", () -> { + if(Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + if(NotEnoughUpdates.INSTANCE.manager.configFile.getParentFile().exists()) { + try { + desktop.open(NotEnoughUpdates.INSTANCE.manager.configFile.getParentFile()); + } catch(IOException ignored) {} + } + } + })); + + buttons.add(new Button("Edit Gui Positions", "Allows you to change the position of the search bar, etc.", () -> { + Minecraft.getMinecraft().displayGuiScreen(new NEUOverlayPlacements()); + })); + } + + public List<Button> getButtons() { + return buttons; + } + public List<Option> getOptions() { List<Option> options = new ArrayList<>(); //Buttons tryAddOption(enableItemEditing, options); tryAddOption(onlyShowOnSkyblock, options); - tryAddOption(hidePotionEffect, options); - tryAddOption(advancedPriceInfo, options); - tryAddOption(cacheRenderedItempane, options); - tryAddOption(streamerMode, options); tryAddOption(showQuickCommands, options); + tryAddOption(hidePotionEffect, options); + tryAddOption(hideEmptyPanes, options); + //tryAddOption(advancedPriceInfo, options); + tryAddOption(showUpdateMsg, options); tryAddOption(tooltipBorderColours, options); tryAddOption(hideApiKey, options); + tryAddOption(streamerMode, options); + tryAddOption(quickAHUpdate, options); tryAddOption(autoupdate, options); - tryAddOption(keepopen, options); + tryAddOption(cacheRenderedItempane, options); tryAddOption(itemStyle, options); - tryAddOption(hideEmptyPanes, options); + tryAddOption(keepopen, options); + tryAddOption(disableItemTabOpen, options); //Sliders tryAddOption(bgBlurFactor, options); tryAddOption(paneWidthMult, options); + tryAddOption(ahNotification, options); tryAddOption(bgOpacity, options); tryAddOption(fgOpacity, options); tryAddOption(panePadding, options); + tryAddOption(tooltipBorderOpacity, options); //Text tryAddOption(apiKey, options); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/GuiQuestLine.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/GuiQuestLine.java new file mode 100644 index 00000000..6840a5aa --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/GuiQuestLine.java @@ -0,0 +1,27 @@ +package io.github.moulberry.notenoughupdates.questing; + +import net.minecraft.client.gui.GuiScreen; + +import java.awt.*; + +public class GuiQuestLine extends GuiScreen { + + public static QuestLine questLine = new QuestLine(); + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + + drawDefaultBackground(); + + drawRect(0, 0, 20, height, new Color(100, 100, 100, 100).getRGB()); + drawRect(20, 0, 21, height, new Color(50, 50, 50, 200).getRGB()); + + questLine.render(width, height, mouseX, mouseY); + } + + @Override + public boolean doesGuiPauseGame() { + return false; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/NEUQuesting.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/NEUQuesting.java new file mode 100644 index 00000000..8be12c95 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/NEUQuesting.java @@ -0,0 +1,67 @@ +package io.github.moulberry.notenoughupdates.questing; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.scoreboard.Score; +import net.minecraft.scoreboard.ScoreObjective; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.scoreboard.Scoreboard; +import net.minecraft.util.EnumChatFormatting; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class NEUQuesting { + + private static final NEUQuesting INSTANCE = new NEUQuesting(); + + private static final Pattern locationPattern = Pattern.compile("(\\u00a7)(?!.*\\u00a7).+"); + private static final Pattern timePattern = Pattern.compile(".+(am|pm)"); + + public String location = ""; + public String date = ""; + public String time = ""; + + public static NEUQuesting getInstance() { + return INSTANCE; + } + + public void tick() { + Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); + + ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); //§707/14/20 + + List<Score> scores = new ArrayList<>(); + for(Score score : scoreboard.getSortedScores(sidebarObjective)) { + scores.add(score); + } + List<String> lines = new ArrayList<>(); + for(int i=scores.size()-1; i>=0; i--) { + Score score = scores.get(i); + ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score.getPlayerName()); + String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName()); + line = Utils.cleanDuplicateColourCodes(line); + lines.add(line); + } + if(lines.size() >= 5) { + date = Utils.cleanColour(lines.get(2)).trim(); + //§74:40am + Matcher matcher = timePattern.matcher(lines.get(3)); + if(matcher.find()) { + time = Utils.cleanColour(matcher.group()).trim(); + } + matcher = locationPattern.matcher(lines.get(4)); + if(matcher.find()) { + location = Utils.cleanColour(matcher.group()).trim(); + } + } + //System.out.println(date + ":" + time + ":" + location); + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/QuestLine.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/QuestLine.java new file mode 100644 index 00000000..4e541583 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/QuestLine.java @@ -0,0 +1,226 @@ +package io.github.moulberry.notenoughupdates.questing; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NEUResourceManager; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.cosmetics.CapeNode; +import io.github.moulberry.notenoughupdates.questing.requirements.*; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.shader.Shader; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Matrix4f; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; +import org.lwjgl.util.vector.Vector3f; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static io.github.moulberry.notenoughupdates.GuiTextures.item_mask; + +public class QuestLine { + + private List<Quest> quests = new ArrayList<>(); + private Framebuffer framebuffer = null; + private Framebuffer framebufferGrayscale = null; + private Shader grayscaleShader = null; + + public class Quest { + //requirements + //rewards + //display icon + //x,y offset + //prerequisite quests id:0,6 + + private Requirement requirement; + + private int x; + private int y; + private ItemStack display; + private String[] tooltip = new String[0]; + private int[] prerequisites; + private boolean completed = false; + + public Quest(ItemStack display, Requirement requirement, int x, int y, int... prerequisites) { + this.requirement = requirement; + this.display = display; + this.x = x; + this.y = y; + this.prerequisites = prerequisites; + } + + public String[] render(int mouseX, int mouseY, boolean hasCompleted) { + if(hasCompleted != completed) return null; + + Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); + if(completed) { + GlStateManager.color(200/255f, 150/255f, 50/255f, 255/255f); + } else { + GlStateManager.color(100/255f, 100/255f, 100/255f, 255/255f); + } + Utils.drawTexturedRect(x-9, y-9, 18, 18, GL11.GL_NEAREST); + + Utils.drawItemStack(display, x-8, y-8); + + GlStateManager.color(100/255f, 100/255f, 100/255f, 255/255f); + GlStateManager.disableTexture2D(); + for(int prereq : prerequisites) { + Quest other = quests.get(prereq); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(x, y, 0).endVertex(); + worldrenderer.pos(other.x, other.y, 0).endVertex(); + tessellator.draw(); + } + + if(mouseX > x-9 && mouseX < x+9) { + if(mouseY > y-9 && mouseY < y+9) { + return tooltip; + } + } + return null; + } + + public void tick() { + if(completed) return; + for(int prereq : prerequisites) { + Quest other = quests.get(prereq); + if(!other.completed) return; + } + requirement.updateRequirement(); + if(requirement.getCompleted()) { + completed = true; + } + } + } + + private Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height, int scaleFactor) { + int sw = width*scaleFactor; + int sh = height*scaleFactor; + + if(framebuffer == null || framebuffer.framebufferWidth != sw || framebuffer.framebufferHeight != sh) { + if(framebuffer == null) { + framebuffer = new Framebuffer(sw, sh, true); + } else { + framebuffer.createBindFramebuffer(sw, sh); + } + framebuffer.setFramebufferFilter(GL11.GL_NEAREST); + } + return framebuffer; + } + + private Matrix4f createProjectionMatrix(int width, int height) { + Matrix4f projMatrix = new Matrix4f(); + projMatrix.setIdentity(); + projMatrix.m00 = 2.0F / (float)width; + projMatrix.m11 = 2.0F / (float)(-height); + projMatrix.m22 = -0.0020001999F; + projMatrix.m33 = 1.0F; + projMatrix.m03 = -1.0F; + projMatrix.m13 = 1.0F; + projMatrix.m23 = -1.0001999F; + return projMatrix; + } + + public void render(int width, int height, int mouseX, int mouseY) { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + + GL11.glTranslatef(width/2f, height/2f, 0); + String[] tooltipDisplay = null; + for(Quest quest : quests) { + String[] tooltip = quest.render(mouseX-width/2, mouseY-height/2, true); + if(tooltip != null && tooltip.length > 0) tooltipDisplay = tooltip; + } + GL11.glTranslatef(-width/2f, -height/2f, 0); + + //FBO/Shader setup + if(framebuffer != null && grayscaleShader != null && (framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height)) { + grayscaleShader.setProjectionMatrix(createProjectionMatrix( + width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor())); + } + framebuffer = checkFramebufferSizes(framebuffer, width, height, + scaledresolution.getScaleFactor()); + framebufferGrayscale = checkFramebufferSizes(framebufferGrayscale, width, height, + scaledresolution.getScaleFactor()); + if(grayscaleShader == null) { + try { + grayscaleShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()), + "grayscale", + framebuffer, framebufferGrayscale); + grayscaleShader.setProjectionMatrix(createProjectionMatrix( + width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor())); + } catch(Exception e) { + return; + } + } + + //Render contents of framebuffer to screen + framebufferGrayscale.bindFramebufferTexture(); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(0, 0, width, height, 0, 1, 1, 0); + framebufferGrayscale.unbindFramebufferTexture(); + + //Render uncompleted quests to framebuffer + GL11.glPushMatrix(); + framebuffer.framebufferClear(); + framebuffer.bindFramebuffer(false); + GlStateManager.color(1f, 1f, 1f, 1f); + GL11.glTranslatef(width/2f, height/2f, 0); + for(Quest quest : quests) { + String[] tooltip = quest.render(mouseX-width/2, mouseY-height/2, false); + if(tooltip != null && tooltip.length > 0) tooltipDisplay = tooltip; + } + GL11.glTranslatef(-width/2f, -height/2f, 0); + framebuffer.unbindFramebuffer(); + GL11.glPopMatrix(); + + //Execute shader + GL11.glPushMatrix(); + grayscaleShader.loadShader(0); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + GL11.glPopMatrix(); + + if(tooltipDisplay != null) { + List<String> tooltip = new ArrayList<>(); + tooltip.addAll(Arrays.asList(tooltipDisplay)); + + Utils.drawHoveringText(tooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj, false); + } + } + + public void tick() { + for(Quest quest : quests) { + quest.tick(); + } + } + + { + //Requirement hubRequirement = new RequirementIslandType("Village"); + //Requirement locationRequirement = new RequirementLocation(-29, 79, -108, 2); + //Requirement locationRequirement2 = new RequirementLocation(-29, 79, -108, 2, hubRequirement); + Requirement req1 = new RequirementApi("coin_purse>20000"); + Requirement req2 = new RequirementIslandType("The End"); + Requirement req3 = new RequirementGuiOpen("Auctions Browser"); + + Quest quest1 = new Quest(new ItemStack(Items.rotten_flesh), req1, 0, 0); + Quest quest2 = new Quest(new ItemStack(Items.cooked_porkchop), req2, 0, 30); + Quest quest3 = new Quest(new ItemStack(Items.diamond_axe), req3, 30, 30, 0, 1); + quest1.tooltip = new String[]{"Line1", "Line2", "Line3"}; + quests.add(quest1); + quests.add(quest2); + quests.add(quest3); + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/Requirement.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/Requirement.java new file mode 100644 index 00000000..a7f40e73 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/Requirement.java @@ -0,0 +1,29 @@ +package io.github.moulberry.notenoughupdates.questing.requirements; + +public abstract class Requirement { + + private Requirement[] preconditions; + + protected boolean completed = false; + + public Requirement(Requirement... preconditions) { + this.preconditions = preconditions; + } + + public boolean getPreconditionCompleted() { + boolean completed = true; + for(Requirement precondition : preconditions) { + completed &= precondition.completed; + } + return completed; + } + + //Collection, Item obtained, GUI Open, Fake npc interact + + public boolean getCompleted() { + return completed && getPreconditionCompleted(); + } + + public abstract void updateRequirement(); + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java new file mode 100644 index 00000000..951cfa50 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java @@ -0,0 +1,111 @@ +package io.github.moulberry.notenoughupdates.questing.requirements; + +import com.google.common.base.Splitter; +import com.google.gson.*; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.questing.NEUQuesting; + +import java.util.List; +import java.util.Map; + +public class RequirementApi extends Requirement { + + private boolean valid = false; + private String requirementLeft; //a.b.c + private String op; //!=,<=,>=,=,<,> + private String requirementRight; //true,float,etc. + + private String[] ops = new String[]{"!=","<=",">=","=","<",">"}; + + public RequirementApi(String apiCheck, Requirement... preconditions) { + super(preconditions); + + processApiCheck(apiCheck); + } + + public void processApiCheck(String apiCheck) { + for(String operator : ops) { + if(apiCheck.contains(operator)) { + String[] split = apiCheck.split(operator); + requirementLeft = split[0]; + requirementRight = split[1]; + op = operator; + valid = true; + return; + } + } + } + + private static Splitter PATH_SPLITTER = Splitter.on(".").omitEmptyStrings().limit(2); + private static JsonElement getElement(JsonElement element, String path) { + List<String> path_split = PATH_SPLITTER.splitToList(path); + if(element instanceof JsonObject) { + System.out.println(path_split.get(0)); + JsonElement e = element.getAsJsonObject().get(path_split.get(0)); + if(path_split.size() > 1) { + return getElement(e, path_split.get(1)); + } else { + return e; + } + } else { + return element; + } + } + + private static boolean checkElementSatisfiesComparison(JsonElement element, String op, String value) { + try { + if(element instanceof JsonNull) { + return value.equals("null"); + } else if(element instanceof JsonObject) { + if(value.contains(".")) { + StringBuilder sb = new StringBuilder(); + String[] split = value.split("\\."); + for(int i=0; i<split.length-1; i++) { + sb.append(split[i]).append("."); + } + return checkElementSatisfiesComparison(getElement(element, sb.toString()), op, split[split.length-1]); + } else { + boolean containsValue = element.getAsJsonObject().has(value); + switch(op) { + case "=": return containsValue; + case "!=": return !containsValue; + default: return false; + } + } + } else if(element instanceof JsonArray) { + for(int i=0; i<element.getAsJsonArray().size(); i++) { + JsonElement e = element.getAsJsonArray().get(i); + if(checkElementSatisfiesComparison(e, op, value)) return true; + } + } else if(element instanceof JsonPrimitive) { + JsonPrimitive prim = element.getAsJsonPrimitive(); + if(!prim.isNumber()) { + return prim.getAsString().equals(value); + } else { + switch(op) { + case "=": return prim.getAsString().equals(value); + case "!=": return !prim.getAsString().equals(value); + case ">": return prim.getAsDouble() > Double.parseDouble(value); + case "<": return prim.getAsDouble() < Double.parseDouble(value); + case "<=": return prim.getAsDouble() <= Double.parseDouble(value); + case ">=": return prim.getAsDouble() >= Double.parseDouble(value); + default: return false; + } + } + } + } catch(Exception e) {} + return false; + } + + @Override + public void updateRequirement() { + if(valid) { + JsonObject profile = NotEnoughUpdates.INSTANCE.manager.auctionManager.getPlayerInformation(); + if(profile != null) { + System.out.println("-----------"); + JsonElement element = getElement(profile, requirementLeft); + completed = checkElementSatisfiesComparison(element, op, requirementRight); + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementGuiOpen.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementGuiOpen.java new file mode 100644 index 00000000..e53a1aca --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementGuiOpen.java @@ -0,0 +1,28 @@ +package io.github.moulberry.notenoughupdates.questing.requirements; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.inventory.ContainerChest; + +public class RequirementGuiOpen extends Requirement { + + private String guiName; + + public RequirementGuiOpen(String guiName, Requirement... preconditions) { + super(preconditions); + this.guiName = guiName; + } + + @Override + public void updateRequirement() { + if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest container = (ContainerChest) chest.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + + if(containerName.equals(guiName)) { + completed = true; + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java new file mode 100644 index 00000000..5ee005f5 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java @@ -0,0 +1,19 @@ +package io.github.moulberry.notenoughupdates.questing.requirements; + +import io.github.moulberry.notenoughupdates.questing.NEUQuesting; + +public class RequirementIslandType extends Requirement { + + private String islandType; + + public RequirementIslandType(String islandType, Requirement... preconditions) { + super(preconditions); + this.islandType = islandType; + } + + + @Override + public void updateRequirement() { + completed = islandType.equalsIgnoreCase(NEUQuesting.getInstance().location); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementItemObtained.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementItemObtained.java new file mode 100644 index 00000000..0627a1cf --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementItemObtained.java @@ -0,0 +1,29 @@ +package io.github.moulberry.notenoughupdates.questing.requirements; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; + +import java.util.ArrayList; +import java.util.Map; + +public class RequirementItemObtained extends Requirement { + + private String internalname; + + public RequirementItemObtained(String internalname, Requirement... preconditions) { + super(preconditions); + this.internalname = internalname; + } + + private Map<String, ArrayList<String>> getAcquiredItems() { + return NotEnoughUpdates.INSTANCE.manager.config.collectionLog.value; + } + + @Override + public void updateRequirement() { + if(getAcquiredItems() != null && + getAcquiredItems().containsKey(NotEnoughUpdates.INSTANCE.manager.getCurrentProfile()) && + getAcquiredItems().get(NotEnoughUpdates.INSTANCE.manager.getCurrentProfile()).contains(internalname)) { + completed = true; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementLocation.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementLocation.java new file mode 100644 index 00000000..0e995f34 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementLocation.java @@ -0,0 +1,26 @@ +package io.github.moulberry.notenoughupdates.questing.requirements; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; + +public class RequirementLocation extends Requirement { + + private int x; + private int y; + private int z; + private float radius; + + public RequirementLocation(int x, int y, int z, float radius, Requirement... preconditions) { + super(preconditions); + this.x = x; + this.y = y; + this.z = z; + this.radius = radius; + } + + @Override + public void updateRequirement() { + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + completed = player.getDistance(x, y, z) < radius; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementLocationRect.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementLocationRect.java new file mode 100644 index 00000000..fff71af7 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementLocationRect.java @@ -0,0 +1,34 @@ +package io.github.moulberry.notenoughupdates.questing.requirements; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; + +public class RequirementLocationRect extends Requirement { + + private int x1; + private int y1; + private int z1; + private int x2; + private int y2; + private int z2; + + public RequirementLocationRect(int x1, int y1, int z1, int x2, int y2, int z2, Requirement... preconditions) { + super(preconditions); + this.x1 = Math.min(x1, x2); + this.y1 = Math.min(y1, y2); + this.z1 = Math.min(z1, z2); + + this.x2 = Math.max(x1, x2); + this.y2 = Math.max(y1, y2); + this.z2 = Math.max(z1, z2); + } + + @Override + public void updateRequirement() { + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + completed = true; + completed &= player.posX > x1 && player.posX < x2; + completed &= player.posY > y1 && player.posY < y2; + completed &= player.posZ > z1 && player.posZ < z2; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index 639449c0..57b89a0a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -16,6 +16,8 @@ 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.event.ClickEvent; +import net.minecraft.event.HoverEvent; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -23,18 +25,19 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Session; +import net.minecraft.util.*; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; import javax.swing.*; import java.awt.*; +import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.Proxy; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -126,7 +129,11 @@ public class Utils { } public static String cleanColour(String in) { - return in.replaceAll("(?i)\\u00C2\\u00A7.", "").replaceAll("(?i)\\u00A7.", ""); + return in.replaceAll("(?i)\\u00A7.", ""); + } + + public static String cleanColourNotModifiers(String in) { + return in.replaceAll("(?i)\\u00A7[0-9a-f]", ""); } public static String fixBrokenAPIColour(String in) { @@ -142,6 +149,31 @@ public class Utils { new ResourceLocation("gui.button.press"), 1.0F)); } + public static String cleanDuplicateColourCodes(String line) { + StringBuilder sb = new StringBuilder(); + char currentColourCode = 'r'; + boolean sectionSymbolLast = false; + for(char c : line.toCharArray()) { + if((int)c > 50000) continue; + + if(c == '\u00a7') { + sectionSymbolLast = true; + } else { + if(sectionSymbolLast) { + if(currentColourCode != c) { + sb.append('\u00a7'); + sb.append(c); + currentColourCode = c; + } + sectionSymbolLast = false; + } else { + sb.append(c); + } + } + } + return sb.toString(); + } + public static void drawTexturedRect(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax, int filter) { GlStateManager.enableTexture2D(); GlStateManager.enableBlend(); @@ -344,6 +376,22 @@ public class Utils { drawHoveringText(textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth, font, true); } + public static ChatStyle createClickStyle(ClickEvent.Action action, String value) { + ChatStyle style = new ChatStyle(); + style.setChatClickEvent(new ClickEvent(action, value)); + style.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText(EnumChatFormatting.YELLOW+value))); + return style; + } + + public static void recursiveDelete(File file) { + if(file.isDirectory() && !Files.isSymbolicLink(file.toPath())) { + for(File child : file.listFiles()) { + recursiveDelete(child); + } + } + file.delete(); + } + public static void drawHoveringText(List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font, boolean coloured) { if (!textLines.isEmpty()) { @@ -451,7 +499,7 @@ public class Utils { drawGradientRect(zLevel, tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); //TODO: Coloured Borders int borderColorStart = 0x505000FF; - if(NotEnoughUpdates.INSTANCE.manager.config.tooltipBorderColours.value) { + if(NotEnoughUpdates.INSTANCE.manager.config.tooltipBorderColours.value && coloured) { if(textLines.size() > 0) { String first = textLines.get(0); int lastColourCode = -99; @@ -483,7 +531,8 @@ public class Utils { } int colourInt = font.getColorCode("0123456789abcdef".charAt(currentColour)); - borderColorStart = new Color(colourInt).darker().getRGB() & 0x00FFFFFF | 0x80000000; + borderColorStart = new Color(colourInt).darker().getRGB() & 0x00FFFFFF | + ((NotEnoughUpdates.INSTANCE.manager.config.tooltipBorderOpacity.value.intValue()) << 24); } } final int borderColorEnd = (borderColorStart & 0xFEFEFE) >> 1 | borderColorStart & 0xFF000000; |