diff options
31 files changed, 1412 insertions, 128 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomAH.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomAH.java new file mode 100644 index 00000000..d74d0e5c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomAH.java @@ -0,0 +1,208 @@ +package io.github.moulberry.notenoughupdates; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.util.TexLoc; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.item.Item; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Base64; +import java.util.HashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static io.github.moulberry.notenoughupdates.GuiTextures.*; + +public class CustomAH extends GuiScreen { + + private static final ResourceLocation inventoryBackground = new ResourceLocation("textures/gui/container/inventory.png"); + private static final ResourceLocation creativeTabSearch = new ResourceLocation("textures/gui/container/creative_inventory/tab_item_search.png"); + private static final ResourceLocation creativeInventoryTabs = new ResourceLocation("textures/gui/container/creative_inventory/tabs.png"); + + private int yScrollInitial = 0; + private boolean scrollClicked = false; + + + private int splits = 2; + + private int ySplit = 35; + private int ySplitSize = 18; + private int ySize = 136 + ySplitSize*splits; + private int xSize = 195; + + private float scrollAmount; + + private int guiLeft = 0; + private int guiTop = 0; + + private NEUManager manager; + private HashMap<String, JsonObject> auctionItems = new HashMap<>(); + + private TexLoc tl = new TexLoc(0, 0, Keyboard.KEY_M); + + public CustomAH(NEUManager manager) { + this.manager = manager; + updateAuctions(); + } + + private void updateAuctions() { + HashMap<Integer, JsonObject> pages = new HashMap<>(); + + HashMap<String, String> args = new HashMap<>(); + args.put("page", "0"); + AtomicInteger totalPages = new AtomicInteger(1); + AtomicInteger currentPages = new AtomicInteger(0); + manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles", + args, jsonObject -> { + if(jsonObject.get("success").getAsBoolean()) { + pages.put(0, jsonObject); + totalPages.set(jsonObject.get("totalPages").getAsInt()); + currentPages.incrementAndGet(); + + for(int i=1; i<totalPages.get(); i++) { + int j = i; + HashMap<String, String> args2 = new HashMap<>(); + args2.put("page", ""+i); + manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles", + args2, jsonObject2 -> { + if (jsonObject2.get("success").getAsBoolean()) { + pages.put(j, jsonObject2); + currentPages.incrementAndGet(); + } + } + ); + } + } + } + ); + + ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();//1593549115 () 1593631661919 + long startTime = System.currentTimeMillis(); + ses.schedule(new Runnable() { + public void run() { + if(System.currentTimeMillis() - startTime > 20000) return; + + if(currentPages.get() == totalPages.get()) { + auctionItems.clear(); + for(int pageNum : pages.keySet()) { + JsonObject page = pages.get(pageNum); + JsonArray auctions = page.get("auctions").getAsJsonArray(); + for(int i=0; i<auctions.size(); i++) { + JsonObject auction = auctions.get(i).getAsJsonObject(); + String auctionUuid = auction.get("uuid").getAsString(); + String auctioneerUuid = auction.get("auctioneer").getAsString(); + int end = auction.get("end").getAsInt(); + String category = auction.get("category").getAsString(); + + String item_bytes = auction.get("item_bytes").getAsString(); + + try { + NBTTagCompound tag = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes))); + tag = tag.getTagList("i", 10).getCompoundTagAt(0); + int id = tag.getShort("id"); + int damage = tag.getShort("Damage"); + tag = tag.getCompoundTag("tag"); + + String internalname = ""; + if(tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + if(ea.hasKey("id", 8)) { + internalname = ea.getString("id"); + } + } + + String[] lore = new String[0]; + NBTTagCompound display = tag.getCompoundTag("display"); + + if(display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + lore = new String[list.tagCount()]; + for(int k=0; k<list.tagCount(); k++) { + lore[k] = list.getStringTagAt(k); + } + } + + String itemid = Item.getItemById(id).getRegistryName(); + String displayname = display.getString("Name"); + String[] info = new String[0]; + String clickcommand = ""; + + JsonObject item = new JsonObject(); + + } catch(IOException e) {} + } + } + return; + } + + ses.schedule(this, 1000L, TimeUnit.MILLISECONDS); + } + }, 5000L, TimeUnit.MILLISECONDS); + + } + + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + tl.handleKeyboardInput(); + + guiLeft = (this.width - xSize)/2; + guiTop = (this.height - ySize)/2; + + this.mc.getTextureManager().bindTexture(creativeTabSearch); + this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySplit); + int y = guiTop+ySplit; + for(int i=0; i<splits; i++) { + this.drawTexturedModalRect(guiLeft, y, 0, ySplit, xSize, ySplit+ySplitSize); + y += ySplitSize; + } + this.drawTexturedModalRect(guiLeft, y, 0, ySplit, xSize, 136-ySplit); + + this.mc.getTextureManager().bindTexture(creativeInventoryTabs); + this.drawTexturedModalRect(guiLeft+175, guiTop+18+(int)((95+ySplitSize*2)*scrollAmount), + 256-(scrollClicked?12:24), 0, 12, 15); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + int y = guiTop+18+(int)((95+ySplitSize*2)*scrollAmount); + if(mouseX > guiLeft+175 && mouseX < guiLeft+175+12) { + if(mouseY > y && mouseY < y+15) { + scrollClicked = true; + return; + } + } + scrollClicked = false; + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int state) { + scrollClicked = false; + } + + @Override + protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { + if(scrollClicked) { + int yMin = guiTop+18 + 8; + int yMax = guiTop+18+(95+ySplitSize*2) + 8; + + scrollAmount = (mouseY-yMin)/(float)yMax; + scrollAmount = Math.max(0, Math.min(1, scrollAmount)); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java index 148f1bc5..4328eaf4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java @@ -8,8 +8,8 @@ import net.minecraft.util.EnumChatFormatting; public class CustomItems { /** - * So it has come to this, huh? Snooping through the source to find all my carefully crafted easter eggs. Well - * guess what, you cheated not only the game, but yourself. You didn't grow. You didn't improve. You took a + * So it has come to this, huh? Snooping through the source to find all my carefully crafted easter eggs. You + * cheated not only the game, but yourself. You didn't grow. You didn't improve. You took a * shortcut and gained nothing. You experienced a hollow victory. Nothing was risked and nothing was gained. * It's sad that you don't know the difference. */ @@ -22,7 +22,7 @@ public class CustomItems { "Dirt, AOTD. Dirt, AOTD.", "Ooh, Dirt to Midas! Let's shake it up a little.", "", - "Also, Did you know that only 10% of the people watching are subscribed?", + "Also, did you know that only 8.7% of the people watching are subscribed?", "It's OK, everyone makes mistakes", "Also follow -> twitch.tv/nullzeelive", "Also -> discord.gg/nullzee"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java index 48db19a5..965a7e48 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java @@ -14,12 +14,19 @@ public class GuiTextures { public static final ResourceLocation item_edit = new ResourceLocation("notenoughupdates:item_edit.png"); public static final ResourceLocation close = new ResourceLocation("notenoughupdates:close.png"); public static final ResourceLocation settings = new ResourceLocation("notenoughupdates:settings.png"); + public static final ResourceLocation off = new ResourceLocation("notenoughupdates:off.png"); public static final ResourceLocation on = new ResourceLocation("notenoughupdates:on.png"); public static final ResourceLocation help = new ResourceLocation("notenoughupdates:help.png"); + public static final ResourceLocation slider_off = new ResourceLocation("notenoughupdates:slider_off.png"); + public static final ResourceLocation slider_on = new ResourceLocation("notenoughupdates:slider_on.png"); + 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 ah_item_holder = new ResourceLocation("notenoughupdates:ah_item_holder.png"); + public static final ResourceLocation ah_item_tab = new ResourceLocation("notenoughupdates:ah_item_tab.png"); + public static final ResourceLocation logo = new ResourceLocation("notenoughupdates:logo.png"); public static final ResourceLocation logo_fg = new ResourceLocation("notenoughupdates:logo_fg.png"); public static final ResourceLocation logo_bg = new ResourceLocation("notenoughupdates:logo_bg.png"); @@ -39,8 +46,10 @@ public class GuiTextures { public static final ResourceLocation order_alphabetical = new ResourceLocation("notenoughupdates:order_alphabetical.png"); public static final ResourceLocation order_rarity = new ResourceLocation("notenoughupdates:order_rarity.png"); + public static final ResourceLocation order_value = new ResourceLocation("notenoughupdates:order_value.png"); public static final ResourceLocation order_alphabetical_active = new ResourceLocation("notenoughupdates:order_alphabetical_active.png"); public static final ResourceLocation order_rarity_active = new ResourceLocation("notenoughupdates:order_rarity_active.png"); + public static final ResourceLocation order_value_active = new ResourceLocation("notenoughupdates:order_value_active.png"); public static final ResourceLocation ascending_overlay = new ResourceLocation("notenoughupdates:ascending_overlay.png"); public static final ResourceLocation descending_overlay = new ResourceLocation("notenoughupdates:descending_overlay.png"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java index a7c7a1e4..d2190425 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java @@ -84,13 +84,6 @@ public class NEUIO { } } } - - /*for(GHContent content : repo.getDirectoryContent("items")) { - String oldSha = oldShas.get(content.getName()); - if(!content.getSha().equals(oldSha)) { - changedFiles.put(content.getName(), content.getSha()); - } - }*/ } catch(IOException e) { return null; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index bebd090c..e2c8d928 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -54,7 +54,7 @@ public class NEUManager { public String viewItemAttemptID = null; public long viewItemAttemptTime = 0; - public String currentProfile = ""; + public String currentProfile = "Papaya"; public final HypixelApi hypixelApi = new HypixelApi(); private ResourceLocation wkZip = new ResourceLocation("notenoughupdates:wkhtmltox.zip"); @@ -180,6 +180,25 @@ public class NEUManager { public float craftCost = -1; } + public boolean isVanillaItem(String internalname) { + //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES + String vanillaName = internalname.split("-")[0]; + int sub = 0; + for(int i=vanillaName.length()-1; i>1; i--) { + char c = vanillaName.charAt(i); + if((int)c >= 48 && (int)c <= 57) { //0-9 + sub++; + } else if(c == '_') { + sub++; + break; + } else { + break; + } + } + vanillaName = vanillaName.substring(0, vanillaName.length()-sub).toLowerCase(); + return Item.itemRegistry.getObject(new ResourceLocation(vanillaName)) != null; + } + /** * Recursively calculates the cost of crafting an item from raw materials. */ @@ -189,24 +208,7 @@ public class NEUManager { } else { CraftInfo ci = new CraftInfo(); - //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES - String vanillaName = internalname.split("-")[0]; - int sub = 0; - for(int i=vanillaName.length()-1; i>1; i--) { - char c = vanillaName.charAt(i); - if((int)c >= 48 && (int)c <= 57) { //0-9 - sub++; - } else if(c == '_') { - sub++; - break; - } else { - break; - } - } - vanillaName = vanillaName.substring(0, vanillaName.length()-sub); - if(Item.itemRegistry.getObject(new ResourceLocation(vanillaName)) != null) { - ci.vanillaItem = true; - } + ci.vanillaItem = isVanillaItem(internalname); JsonObject auctionInfo = getItemAuctionInfo(internalname); JsonObject bazaarInfo = getBazaarInfo(internalname); @@ -657,9 +659,29 @@ public class NEUManager { public Set<String> search(String query, boolean multi) { if(multi) { Set<String> result = new HashSet<>(); - for(String query2 : query.split("\\|")) { - result.addAll(search(query2)); + + StringBuilder query2 = new StringBuilder(); + char lastOp = '|'; + for(char c : query.toCharArray()) { + if(c == '|' || c == '&') { + if(lastOp == '|') { + result.addAll(search(query2.toString())); + } else if(lastOp == '&') { + result.retainAll(search(query2.toString())); + } + + query2 = new StringBuilder(); + lastOp = c; + } else { + query2.append(c); + } + } + if(lastOp == '|') { + result.addAll(search(query2.toString())); + } else if(lastOp == '&') { + result.retainAll(search(query2.toString())); } + return result; } else { return search(query); @@ -670,6 +692,10 @@ public class NEUManager { * Returns the name of items which match a certain search query. */ public Set<String> search(String query) { + query = query.trim(); + boolean negate = query.startsWith("!"); + if(negate) query = query.substring(1); + LinkedHashSet<String> results = new LinkedHashSet<>(); if(query.startsWith("title:")) { query = query.substring(6); @@ -691,7 +717,16 @@ public class NEUManager { results.addAll(new TreeSet<>(search(query, titleWordMap))); results.addAll(new TreeSet<>(search(query, loreWordMap))); } - return results; + if(!negate) { + return results; + } else { + Set<String> negatedResults = new HashSet<>(); + for(String internalname : itemMap.keySet()) { + negatedResults.add(internalname); + } + negatedResults.removeAll(results); + return negatedResults; + } } /** diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 59233882..d96be893 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -30,6 +30,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.Matrix4f; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; +import net.minecraftforge.client.ClientCommandHandler; import org.apache.commons.lang3.StringUtils; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; @@ -62,10 +63,10 @@ public class NEUOverlay extends Gui { }; private ResourceLocation[] orderIcons = new ResourceLocation[] { - order_alphabetical, order_rarity + order_alphabetical, order_rarity, order_value }; private ResourceLocation[] orderIconsActive = new ResourceLocation[] { - order_alphabetical_active, order_rarity_active + order_alphabetical_active, order_rarity_active, order_value_active }; //Various constants used for GUI structure @@ -74,9 +75,8 @@ public class NEUOverlay extends Gui { private final int searchBarYSize = 40; private final int searchBarPadding = 2; - private static final int BOX_PADDING = 15; - public static final int ITEM_PADDING = 4; - public static final int ITEM_SIZE = 16; + public static final int ITEM_PADDING = 4; + public static final int ITEM_SIZE = 16; private Color bg = new Color(90, 90, 140, 50); private Color fg = new Color(100,100,100, 255); @@ -97,6 +97,9 @@ public class NEUOverlay extends Gui { private boolean searchMode = false; private long millisLastLeftClick = 0; + private long millisLastMouseMove = 0; + private int lastMouseX = 0; + private int lastMouseY = 0; boolean mouseDown = false; @@ -107,6 +110,7 @@ public class NEUOverlay extends Gui { private static final int COMPARE_MODE_ALPHABETICAL = 0; private static final int COMPARE_MODE_RARITY = 1; + private static final int COMPARE_MODE_VALUE = 2; private static final int SORT_MODE_ALL = 0; private static final int SORT_MODE_MOB = 1; @@ -177,6 +181,13 @@ public class NEUOverlay extends Gui { int mouseX = Mouse.getX() / scaledresolution.getScaleFactor(); int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor(); + if(lastMouseX != mouseX || lastMouseY != mouseY) { + millisLastMouseMove = System.currentTimeMillis(); + } + + lastMouseX = mouseX; + lastMouseY = mouseY; + if(Mouse.getEventButtonState()) { mouseDown = true; } else if(Mouse.getEventButton() != -1) { @@ -288,8 +299,8 @@ public class NEUOverlay extends Gui { } //Clicking on "close info pane" button - if(mouseX > width*getInfoPaneOffsetFactor()-22 && mouseX < width*getInfoPaneOffsetFactor()-6) { - if(mouseY > 7 && mouseY < 23) { + if(mouseX > width*getInfoPaneOffsetFactor()-getBoxPadding()-8 && mouseX < width*getInfoPaneOffsetFactor()-getBoxPadding()+8) { + if(mouseY > getBoxPadding()-8 && mouseY < getBoxPadding()+8) { if(Mouse.getEventButtonState() && Mouse.getEventButton() < 2) { //Left or right click up displayInformationPane(null); return true; @@ -322,6 +333,9 @@ public class NEUOverlay extends Gui { if(command.startsWith("/")) { NotEnoughUpdates.INSTANCE.sendChatMessage(command); return true; + } else { + ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command); + return true; } } } @@ -376,6 +390,8 @@ public class NEUOverlay extends Gui { if(mouseX < width*getInfoPaneOffsetFactor()) { activeInfoPane.mouseInput(width, height, mouseX, mouseY, mouseDown); return true; + } else if(Mouse.getEventButton() <= 1 && Mouse.getEventButtonState()) { //Left or right click + activeInfoPane.mouseInputOutside(); } } @@ -627,6 +643,12 @@ 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; + + if(cost1 < cost2) return mult; + if(cost1 > cost2) return -mult; } String i1 = o1.get("internalname").getAsString(); @@ -776,7 +798,8 @@ public class NEUOverlay extends Gui { } public int getBoxPadding() { - return (BOX_PADDING-5)*2/scaledresolution.getScaleFactor()+5; + double panePadding = Math.max(0, Math.min(20, manager.config.panePadding.value)); + return (int)(panePadding*2/scaledresolution.getScaleFactor()+5); } private abstract class ItemSlotConsumer { @@ -1252,7 +1275,7 @@ 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, @@ -1290,6 +1313,19 @@ public class NEUOverlay extends Gui { GlStateManager.color(1f, 1f, 1f, 1f); Utils.drawTexturedRect(orderIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE,0, 1, 0, 1, GL11.GL_NEAREST); GlStateManager.bindTexture(0); + + if(mouseY > iconTop && mouseY < iconTop+scaledITEM_SIZE) { + if(mouseX > orderIconX && mouseX < orderIconX+scaledITEM_SIZE) { + if(System.currentTimeMillis() - millisLastMouseMove > 400) { + String text = EnumChatFormatting.GRAY+"Order "; + if(i == COMPARE_MODE_ALPHABETICAL) text += "Alphabetically"; + else if(i == COMPARE_MODE_RARITY) text += "by Rarity"; + else if(i == COMPARE_MODE_VALUE) text += "by Item Worth"; + else text = null; + if(text != null) textToDisplay = Utils.createList(text); + } + } + } } for(int i=0; i<sortIcons.length; i++) { @@ -1299,6 +1335,22 @@ public class NEUOverlay extends Gui { GlStateManager.color(1f, 1f, 1f, 1f); Utils.drawTexturedRect(sortIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST); GlStateManager.bindTexture(0); + + if(mouseY > iconTop && mouseY < iconTop+scaledITEM_SIZE) { + if(mouseX > sortIconX && mouseX < sortIconX+scaledITEM_SIZE) { + if(System.currentTimeMillis() - millisLastMouseMove > 400) { + String text = EnumChatFormatting.GRAY+"Filter "; + if(i == SORT_MODE_ALL) text = EnumChatFormatting.GRAY+"No Filter"; + else if(i == SORT_MODE_MOB) text += "Mobs"; + else if(i == SORT_MODE_PET) text += "Pets"; + else if(i == SORT_MODE_TOOL) text += "Tools"; + else if(i == SORT_MODE_ARMOR) text += "Armor"; + else if(i == SORT_MODE_ACCESSORY) text += "Accessories"; + else text = null; + if(text != null) textToDisplay = Utils.createList(text); + } + } + } } if(!hoverInv) { @@ -1355,7 +1407,7 @@ public class NEUOverlay extends Gui { GlStateManager.color(1f, 1f, 1f, 1f); Minecraft.getMinecraft().getTextureManager().bindTexture(close); - Utils.drawTexturedRect(rightSide-22, 7, 16, 16); + Utils.drawTexturedRect(rightSide-getBoxPadding()-8, getBoxPadding()-8, 16, 16); GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); } @@ -1567,7 +1619,10 @@ public class NEUOverlay extends Gui { if(hasClick) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"LMB/R : View recipe!"); if(hasInfo) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"RMB : View additional information!"); - Utils.drawHoveringText(text, mouseX, mouseY, width, height, -1, fr); + textToDisplay = text; + } + if(textToDisplay != null) { + Utils.drawHoveringText(textToDisplay, mouseX, mouseY, width, height, -1, fr); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUResourceManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUResourceManager.java new file mode 100644 index 00000000..41737eda --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUResourceManager.java @@ -0,0 +1,38 @@ +package io.github.moulberry.notenoughupdates; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; + +import java.io.IOException; +import java.util.List; +import java.util.Set; + +public class NEUResourceManager implements IResourceManager { + + private IResourceManager parentResourceManager; + + public NEUResourceManager(IResourceManager parentResourceManager) { + this.parentResourceManager = parentResourceManager; + } + + @Override + public Set<String> getResourceDomains() { + return parentResourceManager.getResourceDomains(); + } + + @Override + public IResource getResource(ResourceLocation location) throws IOException { + return parentResourceManager.getResource(forceNeuRL(location)); + } + + @Override + public List<IResource> getAllResources(ResourceLocation location) throws IOException { + return parentResourceManager.getAllResources(forceNeuRL(location)); + } + + private ResourceLocation forceNeuRL(ResourceLocation location) { + return new ResourceLocation("notenoughupdates", location.getResourcePath()); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index b4b48db5..ab903227 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -6,14 +6,20 @@ import com.mojang.authlib.Agent; import com.mojang.authlib.exceptions.AuthenticationException; import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; +import io.github.moulberry.notenoughupdates.commands.SimpleCommand; +import io.github.moulberry.notenoughupdates.infopanes.CollectionLogInfoPane; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiInventory; import net.minecraft.client.settings.KeyBinding; +import net.minecraft.command.ICommandSender; +import net.minecraft.init.Blocks; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -23,6 +29,7 @@ import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.Session; import net.minecraft.util.StatCollector; +import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.client.event.ClientChatReceivedEvent; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent; @@ -32,6 +39,7 @@ import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.input.Keyboard; @@ -83,6 +91,29 @@ public class NotEnoughUpdates { return s; } + ScheduledExecutorService guiDelaySES = Executors.newScheduledThreadPool(1); + SimpleCommand collectionLogCommand = new SimpleCommand("neucl", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { + guiDelaySES.schedule(()->{ + Minecraft.getMinecraft().displayGuiScreen(new GuiInventory(Minecraft.getMinecraft().thePlayer)); + }, 10L, TimeUnit.MILLISECONDS); + } + manager.updatePrices(); + overlay.displayInformationPane(new CollectionLogInfoPane(overlay, manager)); + } + }); + + SimpleCommand neuAhCommand = new SimpleCommand("neuah", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { + guiDelaySES.schedule(()->{ + Minecraft.getMinecraft().displayGuiScreen(new CustomAH(manager)); + }, 10L, TimeUnit.MILLISECONDS); + } + } + }); + /** * Instantiates NEUIo, NEUManager and NEUOverlay instances. Registers keybinds and adds a shutdown hook to clear tmp folder. * @param event @@ -94,6 +125,9 @@ public class NotEnoughUpdates { File f = new File(event.getModConfigurationDirectory(), "notenoughupdates"); f.mkdirs(); + ClientCommandHandler.instance.registerCommand(collectionLogCommand); + ClientCommandHandler.instance.registerCommand(neuAhCommand); + neuio = new NEUIO(getAccessToken()); manager = new NEUManager(this, neuio, f); manager.loadItemInformation(); @@ -165,16 +199,64 @@ public class NotEnoughUpdates { } /** - * Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message. + * 1)Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message. * This is used in order to prevent the mod spamming messages. + * 2)Adds unique items to the collection log */ - @EventHandler + private HashMap<String, Long> newItemAddMap = new HashMap<>(); + @SubscribeEvent public void onTick(TickEvent.ClientTickEvent event) { 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) { + HashSet<String> newItem = new HashSet<>(); + for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { + processUniqueStack(stack, newItem); + } + boolean usableContainer = true; + for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) { + if(stack == null) { + continue; + } + if(stack.hasTagCompound()) { + NBTTagCompound tag = stack.getTagCompound(); + if(tag.hasKey("ExtraAttributes", 10)) { + continue; + } + } + usableContainer = false; + break; + } + if(usableContainer) { + for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) { + processUniqueStack(stack, newItem); + } + } + newItemAddMap.keySet().retainAll(newItem); + } + } + + private void processUniqueStack(ItemStack stack, HashSet<String> newItem) { + if(stack != null && stack.hasTagCompound()) { + String internalname = manager.getInternalNameForItem(stack); + if(internalname != null) { + ArrayList<String> log = manager.config.collectionLog.value.computeIfAbsent( + manager.currentProfile, k -> new ArrayList<>()); + if(!log.contains(internalname)) { + newItem.add(internalname); + if(newItemAddMap.containsKey(internalname)) { + if(System.currentTimeMillis() - newItemAddMap.get(internalname) > 1000) { + log.add(internalname); + } + } else { + newItemAddMap.put(internalname, System.currentTimeMillis()); + } + } + } + } } /** @@ -302,8 +384,9 @@ public class NotEnoughUpdates { /** * 1) When receiving "You are playing on profile" messages, will set the current profile. * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI) + * 3) Replaces lobby join notifications when streamer mode is active */ - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOW) public void onGuiChat(ClientChatReceivedEvent e) { String r = null; String unformatted = e.message.getUnformattedText().replaceAll("(?i)\\u00A7.", ""); @@ -319,12 +402,20 @@ public class NotEnoughUpdates { EnumChatFormatting.RED+"Invalid recipe ")) { r = ""; } - if(r != null) { + if(r != null) { if(manager.failViewItem(r)) { e.setCanceled(true); } missingRecipe.set(true); } + //System.out.println(e.message); + if(isOnSkyblock() && manager.config.streamerMode.value && e.message instanceof ChatComponentText) { + String m = e.message.getFormattedText(); + String m2 = StreamerMode.filterChat(e.message.getFormattedText()); + if(!m.equals(m2)) { + e.message = new ChatComponentText(m2); + } + } } /** @@ -441,6 +532,9 @@ public class NotEnoughUpdates { JOptionPane.PLAIN_MESSAGE, null, new String[]{"Enter"}, "Enter"); resInternalname = tf.getText(); + if(resInternalname.trim().length() == 0) { + return; + } JsonObject recipe = new JsonObject(); @@ -536,6 +630,16 @@ public class NotEnoughUpdates { */ @SubscribeEvent public void onItemTooltip(ItemTooltipEvent event) { + if(!isOnSkyblock()) return; + if(manager.config.hideEmptyPanes.value && + event.itemStack.getItem().equals(Item.getItemFromBlock(Blocks.stained_glass_pane))) { + String first = Utils.cleanColour(event.toolTip.get(0)); + first = first.replaceAll("\\(.*\\)", "").trim(); + if(first.length() == 0) { + event.toolTip.clear(); + } + } + //AH prices if(Minecraft.getMinecraft().currentScreen != null) { if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; @@ -623,7 +727,10 @@ public class NotEnoughUpdates { //Stolen from Biscut's SkyblockAddons public boolean isOnSkyblock() { if(!manager.config.onlyShowOnSkyblock.value) return true; + return hasSkyblockScoreboard(); + } + public boolean hasSkyblockScoreboard() { Minecraft mc = Minecraft.getMinecraft(); if (mc != null && mc.theWorld != null) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/StreamerMode.java b/src/main/java/io/github/moulberry/notenoughupdates/StreamerMode.java new file mode 100644 index 00000000..c7d5e8ae --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/StreamerMode.java @@ -0,0 +1,63 @@ +package io.github.moulberry.notenoughupdates; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StreamerMode { + + private static final Pattern lobbyPattern = Pattern.compile("(mini|mega)([0-9]{1,3}[A-Z])"); + + public static String filterLobbyNames(String line) { + Matcher matcher = lobbyPattern.matcher(line); + if(matcher.find() && matcher.groupCount() == 2) { + String lobbyType = matcher.group(1); + String lobbyId = matcher.group(2); + long lobbyNum = Long.parseLong(lobbyId.substring(0, lobbyId.length()-1)); + + long obfLobbyNum = (lobbyNum*9182739 + 11) % 500; + char obfLobbyLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt((int)(obfLobbyNum%26)); + + line = line.replaceAll("(mini|mega)([0-9]{1,3}[A-Z])", lobbyType+obfLobbyNum+obfLobbyLetter); + } + return line; + } + + public static String filterScoreboard(String line) { + line = filterLobbyNames(cleanDuplicateColourCodes(line)); + return line; + } + + public static String filterChat(String line) { + line = filterLobbyNames(line); + 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/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/Utils.java index c08adc94..f850b49d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/Utils.java @@ -112,6 +112,10 @@ public class Utils { drawTexturedRect(x, y, width, height, uMin, uMax, vMin , vMax, GL11.GL_LINEAR); } + public static String cleanColour(String in) { + return in.replaceAll("(?i)\\u00A7.", ""); + } + 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(); @@ -137,34 +141,6 @@ public class Utils { .tex(uMin, vMin).endVertex(); tessellator.draw(); - /*Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer - .pos(x, y + height, 0) - .tex(uMin, vMax).endVertex(); - worldrenderer - .pos(x + width, y + height, 0) - .tex(uMax, vMax).endVertex(); - worldrenderer - .pos(x + width, y, 0) - .tex(uMax, vMin).endVertex(); - worldrenderer - .pos(x, y, 0) - .tex(uMin, vMin).endVertex(); - tessellator.draw();*/ - - /*GL11.glBegin(GL11.GL_TRIANGLE_STRIP); - GL11.glTexCoord2f(uMin, vMin); - GL11.glVertex3f(x, y, 0.0F); - GL11.glTexCoord2f(uMin, vMax); - GL11.glVertex3f(x, y+height, 0.0F); - GL11.glTexCoord2f(uMax, vMin); - GL11.glVertex3f(x+width, y, 0.0F); - GL11.glTexCoord2f(uMax, vMax); - GL11.glVertex3f(x+width, y+height, 0.0F); - GL11.glEnd();*/ - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); @@ -204,7 +180,21 @@ public class Utils { drawStringScaled(str, fr, x-len/2, y-fontHeight/2, shadow, colour, factor); } + public static void drawStringCenteredYScaled(String str, FontRenderer fr, float x, float y, boolean shadow, int len, int colour) { + int strLen = fr.getStringWidth(str); + float factor = len/(float)strLen; + float fontHeight = 8*factor; + + drawStringScaled(str, fr, x, y-fontHeight/2, shadow, colour, factor); + } + public static int renderStringTrimWidth(String str, FontRenderer fr, boolean shadow, int x, int y, int len, int colour, int maxLines) { + return renderStringTrimWidth(str, fr, shadow, x, y, len, colour, maxLines, 1); + } + + public static int renderStringTrimWidth(String str, FontRenderer fr, boolean shadow, int x, int y, int len, int colour, int maxLines, float scale) { + len = (int)(len/scale); + int yOff = 0; String excess; String trimmed = trimToWidth(str, len); @@ -221,26 +211,27 @@ public class Utils { int lines = 0; while((lines++<maxLines) || maxLines<0) { if(trimmed.length() == str.length()) { - fr.drawString(trimmed, x, y + yOff, colour, shadow); + drawStringScaled(trimmed, fr, x, y+yOff, shadow, colour, scale); + //fr.drawString(trimmed, x, y + yOff, colour, shadow); break; } else if(trimmed.isEmpty()) { - yOff -= 12; + yOff -= 12*scale; break; } else { if(firstLine) { - fr.drawString(trimmed, x, y + yOff, colour, shadow); + drawStringScaled(trimmed, fr, x, y+yOff, shadow, colour, scale); firstLine = false; } else { if(trimmed.startsWith(" ")) { trimmed = trimmed.substring(1); } - fr.drawString(colourCodes + trimmed, x, y + yOff, colour, shadow); + drawStringScaled(colourCodes + trimmed, fr, x, y+yOff, shadow, colour, scale); } excess = str.substring(trimmedCharacters); trimmed = trimToWidth(excess, len); trimmedCharacters += trimmed.length(); - yOff += 12; + yOff += 12*scale; } } return yOff; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java new file mode 100644 index 00000000..ae27be46 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java @@ -0,0 +1,36 @@ +package io.github.moulberry.notenoughupdates.commands; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; + +public class SimpleCommand extends CommandBase { + + private String commandName; + private ProcessCommandRunnable runnable; + + public SimpleCommand(String commandName, ProcessCommandRunnable runnable) { + this.commandName = commandName; + this.runnable = runnable; + } + + public abstract static class ProcessCommandRunnable { + public abstract void processCommand(ICommandSender sender, String[] args); + } + + public boolean canCommandSenderUseCommand(ICommandSender sender) { + return true; + } + + public String getCommandName() { + return commandName; + } + + public String getCommandUsage(ICommandSender sender) { + return "/" + commandName; + } + + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + runnable.processCommand(sender, args); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java new file mode 100644 index 00000000..1c21e342 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java @@ -0,0 +1,492 @@ +package io.github.moulberry.notenoughupdates.infopanes; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NEUManager; +import io.github.moulberry.notenoughupdates.NEUOverlay; +import io.github.moulberry.notenoughupdates.NEUResourceManager; +import io.github.moulberry.notenoughupdates.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.shader.Shader; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.Matrix4f; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.text.NumberFormat; +import java.util.*; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static io.github.moulberry.notenoughupdates.GuiTextures.item_mask; + +public class CollectionLogInfoPane extends ScrollableInfoPane { + + private String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$"; + private String petRegex = ".*?;[0-4]$"; + + TreeSet<String> items = new TreeSet<>(getItemComparator()); + + private int buttonHover = -1; + + private static final int FILTER_ALL = 0; + private static final int FILTER_WEAPON = 1; + private static final int FILTER_ARMOR = 2; + private static final int FILTER_ACCESSORY = 3; + private static final int FILTER_PET = 4; + private static final int FILTER_TOOL = 5; + private static final int FILTER_SLAYER_ZOMBIE = 6; + private static final int FILTER_SLAYER_WOLF = 7; + private static final int FILTER_SLAYER_SPIDER = 8; + private int filterMode = FILTER_ALL; + private String[] filterPrettyNames = new String[]{"ALL","WEAPON","ARMOR", + "ACCESSORY","PET","TOOL","ZOMBIE SLAYER","WOLF SLAYER","SPIDER SLAYER"}; + + private Framebuffer itemFramebuffer = null; + private Framebuffer itemBGFramebuffer = null; + private Framebuffer itemFramebufferGrayscale = null; + private Shader grayscaleShader = null; + + public CollectionLogInfoPane(NEUOverlay overlay, NEUManager manager) { + super(overlay, manager); + refreshItems(); + } + + private boolean loreContains(JsonArray lore, String str) { + for(int i=0; i<lore.size(); i++) { + String line = lore.get(i).getAsString(); + if(line.contains(str)) return true; + } + return false; + } + + private void refreshItems() { + items.clear(); + for(String internalname : manager.getItemInformation().keySet()) { + if(!manager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) { + JsonArray lore = manager.getItemInformation().get(internalname).get("lore").getAsJsonArray(); + switch(filterMode) { + case FILTER_WEAPON: + if(overlay.checkItemType(lore, "SWORD", "BOW", "WAND") < 0) continue; + break; + case FILTER_ARMOR: + if(overlay.checkItemType(lore, "HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS") < 0) continue; + break; + case FILTER_ACCESSORY: + if(overlay.checkItemType(lore, "ACCESSORY") < 0) continue; + break; + case FILTER_PET: + if(!internalname.matches(petRegex)) 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; + break; + case FILTER_SLAYER_WOLF: + if(!loreContains(lore, "\u00A7c\u2620 \u00A75Requires Wolf")) continue; + break; + case FILTER_SLAYER_SPIDER: + if(!loreContains(lore, "\u00A7c\u2620 \u00A75Requires Spider")) continue; + break; + } + items.add(internalname); + } + } + } + + private Map<String, ArrayList<String>> getAcquiredItems() { + return manager.config.collectionLog.value; + } + + private Comparator<String> getItemComparator() { + return (o1, o2) -> { + float cost1 = manager.getCraftCost(o1).craftCost; + float cost2 = manager.getCraftCost(o2).craftCost; + + if(cost1 < cost2) return 1; + if(cost1 > cost2) return -1; + + return o1.compareTo(o2); + }; + } + + public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) { + super.mouseInput(width, height, mouseX, mouseY, mouseDown); + if(mouseDown) { + if(buttonHover == 0) { + if(Mouse.getEventButton() == 0) { + filterMode++; + if(filterMode >= filterPrettyNames.length) { + filterMode = 0; + } + } else if(Mouse.getEventButton() == 1) { + filterMode--; + if(filterMode < 0) { + filterMode = filterPrettyNames.length-1; + } + } + } + refreshItems(); + } + } + + public void render(int width, int height, Color bg, Color fg, ScaledResolution scaledresolution, int mouseX, int mouseY) { + int paneWidth = (int)(width/3*overlay.getWidthMult()); + int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor()); + int leftSide = rightSide - paneWidth; + int padding = overlay.getBoxPadding(); + + renderDefaultBackground(width, height, bg); + + renderControls(height, padding, leftSide+padding, rightSide-padding, 20, fg); + renderCollectionLog(fg, width, height, leftSide+padding, rightSide-padding, padding+25, height-padding); + } + + private float getCompletedness() { + int total = items.size(); + int own = 0; + for(String item : items) { + if(getAcquiredItems() != null && + getAcquiredItems().containsKey(manager.currentProfile) && + getAcquiredItems().get(manager.currentProfile).contains(item)) { + own++; + } + + } + return own/(float)total; + } + + private EnumChatFormatting[] rainbow = new EnumChatFormatting[]{ + EnumChatFormatting.RED, + EnumChatFormatting.GOLD, + EnumChatFormatting.YELLOW, + EnumChatFormatting.GREEN, + EnumChatFormatting.AQUA, + EnumChatFormatting.LIGHT_PURPLE, + EnumChatFormatting.DARK_PURPLE + }; + + private String getCompletednessString() { + float completedness = getCompletedness(); + String text = (int)(completedness*100)+"% Complete"; + if(completedness >= 1) { + StringBuilder rainbowText = new StringBuilder(); + for(int i=0; i<text.length(); i++) { + char c = text.charAt(i); + int index = (int)(i-System.currentTimeMillis()/100)%rainbow.length; + if(index < 0) index += rainbow.length; + rainbowText.append(rainbow[index]).append(c); + } + text = rainbowText.toString(); + } + return text; + } + + private void renderControls(int height, int top, int left, int right, int ySize, Color fg) { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + + int mouseX = Mouse.getX() / scaledresolution.getScaleFactor(); + int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor(); + + buttonHover = -1; + + int totalAvailable = right-left; + int controlPadding = 3; + String[] controls = new String[]{ + "Filter: "+filterPrettyNames[filterMode], + getCompletednessString()}; + int numControls = controls.length; + int available = totalAvailable-(numControls-1)*controlPadding; + int controlSize = available/numControls; + int extraPadding = (available%controlSize)/2; + + for(int i=0; i<numControls; i++) { + int width = controlSize+controlPadding; + int x = left+extraPadding+i*width; + + if(mouseX > x && mouseX < x+controlSize) { + if(mouseY > top && mouseY < top+ySize) { + buttonHover = i; + } + } + + drawRect(x, top, x+controlSize, top+ySize, + new Color(177,177,177).getRGB()); + drawRect(x+1, top+1, x+controlSize, top+ySize, + new Color(50,50,50).getRGB()); + drawRect(x+1, top+1, x+controlSize-1, top+ySize-1, fg.getRGB()); + Utils.drawStringCenteredScaledMaxWidth(controls[i], Minecraft.getMinecraft().fontRendererObj, + x+width/2f, top+ySize/2f, true, controlSize-4, Color.WHITE.getRGB()); + } + } + + 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; + } + + private void renderCollectionLog(Color fg, int width, int height, int left, int right, int top, int bottom) { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + + int mouseX = Mouse.getX() / scaledresolution.getScaleFactor(); + int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor(); + + if(itemFramebuffer != null && grayscaleShader != null && + (itemFramebuffer.framebufferWidth != width || itemFramebuffer.framebufferHeight != height)) { + grayscaleShader.setProjectionMatrix(createProjectionMatrix( + width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor())); + } + + itemFramebuffer = checkFramebufferSizes(itemFramebuffer, width, height, + scaledresolution.getScaleFactor()); + itemBGFramebuffer = checkFramebufferSizes(itemBGFramebuffer, width, height, + scaledresolution.getScaleFactor()); + itemFramebufferGrayscale = checkFramebufferSizes(itemFramebufferGrayscale, width, height, + scaledresolution.getScaleFactor()); + renderItemsToImage(itemFramebuffer, fg, left+5, right, top+1, bottom); + renderItemBGToImage(itemBGFramebuffer, fg, left+5, right, top+1, bottom); + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + renderFromImage(itemBGFramebuffer, width, height, left, right, top, bottom); + renderFromImage(itemFramebuffer, width, height, left, right, top, bottom); + + if(grayscaleShader == null) { + try { + grayscaleShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()), + "grayscale", + itemFramebuffer, itemFramebufferGrayscale); + grayscaleShader.setProjectionMatrix(createProjectionMatrix( + width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor())); + } catch(Exception e) { + return; + } + } + + GL11.glPushMatrix(); + grayscaleShader.loadShader(0); + GlStateManager.enableDepth(); + GL11.glPopMatrix(); + + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + + itemFramebufferGrayscale.bindFramebufferTexture(); + + AtomicReference<JsonObject> tooltipToDisplay = new AtomicReference<>(null); + + AtomicBoolean isTop = new AtomicBoolean(false); + AtomicInteger lowestY = new AtomicInteger(-1); + + String[] items = getItemList(); + GlStateManager.color(1f, 1f, 1f, 1f); + iterateItemSlots(new ItemSlotConsumer() { + @Override + public void consume(int x, int y, int id) { + 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; + + lowestY.set(Math.max(bottomI, lowestY.get())); + + 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; + } + + + 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); + } + }, left+5, right, top+1, bottom); + + if(!isTop.get()) { + if(lowestY.get() == -1) { + scrollHeight.setValue(0); + } else { + int dist = bottom - lowestY.get() - 10; + if(dist > 0) { + scrollHeight.setValue(scrollHeight.getValue() - dist); + } + } + } + + itemFramebufferGrayscale.unbindFramebufferTexture(); + + JsonObject json = tooltipToDisplay.get(); + if(json != null) { + List<String> text = new ArrayList<>(); + text.add(json.get("displayname").getAsString()); + JsonArray lore = json.get("lore").getAsJsonArray(); + + for(int i=0; i<lore.size(); i++) { + text.add(lore.get(i).getAsString()); + } + + Utils.drawHoveringText(text, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); + } + } + + private String[] getItemList() { + String[] items_arr = new String[items.size()]; + int i=0; + for(String internalname : items) { + items_arr[i++] = internalname; + } + return items_arr; + } + + private int limCol(int col) { + return Math.min(255, Math.max(0, col)); + } + + private void renderItems(int left, int right, int top, int bottom) { + String[] items = getItemList(); + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + String internalname = items[id]; + + ItemStack stack = manager.jsonToStack(manager.getItemInformation().get(internalname)); + Utils.drawItemStack(stack, x, y); + } + }, left, right, top, bottom); + } + + private void renderItemBackgrounds(Color fg, int left, int right, int top, int bottom) { + int opacity = Math.min(255, Math.max(0, manager.config.fgOpacity.value.intValue())); + Color fgGold = new Color(limCol(fg.getRed()+100), limCol(fg.getGreen()+50), limCol(fg.getBlue()-50), opacity); + Color fgCustomOpacity = new Color((fg.getRGB() & 0x00ffffff) | opacity << 24, true); + + String[] items = getItemList(); + iterateItemSlots(new ItemSlotConsumer() { + public void consume(int x, int y, int id) { + String internalname = items[id]; + + Color color = fgCustomOpacity; + if(getAcquiredItems() != null && + getAcquiredItems().containsKey(manager.currentProfile) && + getAcquiredItems().get(manager.currentProfile).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()); + } + GlStateManager.bindTexture(0); + } + }, left, right, top, bottom); + } + + /** + * Checks whether the screen size has changed, if so it reconstructs the itemPane framebuffer and marks that the + * itemPane should be redrawn. + */ + 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 void renderItemsToImage(Framebuffer framebuffer, Color fg, int left, int right, int top, int bottom) { + GL11.glPushMatrix(); + framebuffer.framebufferClear(); + framebuffer.bindFramebuffer(false); + + renderItems(left, right, top, bottom); + + framebuffer.unbindFramebuffer(); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + GL11.glPopMatrix(); + } + + private void renderItemBGToImage(Framebuffer framebuffer, Color fg, int left, int right, int top, int bottom) { + GL11.glPushMatrix(); + framebuffer.framebufferClear(); + framebuffer.bindFramebuffer(false); + + renderItemBackgrounds(fg, left, right, top, bottom); + + framebuffer.unbindFramebuffer(); + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); + GL11.glPopMatrix(); + } + + private void renderFromImage(Framebuffer framebuffer, int width, int height, int left, int right, int top, int bottom) { + framebuffer.bindFramebufferTexture(); + GlStateManager.color(1f, 1f, 1f, 1f); + Utils.drawTexturedRect(left, top, right-left, bottom-top, + left/(float)width, right/(float)width, + (height-top)/(float)height, (height-bottom)/(float)height); + framebuffer.unbindFramebufferTexture(); + } + + private abstract class ItemSlotConsumer { + public abstract void consume(int x, int y, int id); + } + + public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer, int left, int right, int top, int bottom) { + int scrolledTop = top-scrollHeight.getValue(); + + int id = 0; + int extraSize = overlay.ITEM_SIZE+overlay.ITEM_PADDING; + for(int y=scrolledTop; y<bottom; y+=extraSize) { + for(int x=left; x<right-extraSize; x+=extraSize) { + if(y > top-extraSize) { + itemSlotConsumer.consume(x, y, id); + } + if(++id >= items.size()) { + return; + } + } + } + } + + public boolean keyboardInput() { + return false; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java index 2b87fdbc..60f8ca72 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java @@ -23,6 +23,7 @@ public abstract class InfoPane extends Gui { int mouseY); public abstract void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown); + public void mouseInputOutside(){}; public abstract boolean keyboardInput(); 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 2fccbf9e..090410dd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java @@ -30,6 +30,10 @@ public class SettingsInfoPane extends InfoPane { private int page = 0; private int maxPages = 1; + private Options.Option clickedSlider = null; + private int clickedSliderX = 0; + private float clickedSliderMult = 0; + public SettingsInfoPane(NEUOverlay overlay, NEUManager manager) { super(overlay, manager); } @@ -59,33 +63,65 @@ public class SettingsInfoPane extends InfoPane { float mult = tileWidth/90f; drawRect(x, y, x+tileWidth, y+tileHeight, fg.getRGB()); - if(scaledresolution.getScaleFactor()==4) { - GL11.glScalef(0.5f,0.5f,1); - Utils.renderStringTrimWidth(option.displayName, fr, true, (x+(int)(8*mult))*2, (y+(int)(8*mult))*2, - (tileWidth-(int)(16*mult))*2, new Color(100,255,150).getRGB(), 3); - GL11.glScalef(2,2,1); - } else { - 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); - } + + if(manager.config.hideApiKey.value && option==manager.config.apiKey) 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()); if(option.value instanceof Boolean) { GlStateManager.color(1f, 1f, 1f, 1f); - Minecraft.getMinecraft().getTextureManager().bindTexture(((Boolean)option.value) ? on : off); - Utils.drawTexturedRect(x+tileWidth/2-(int)(32*mult), y+tileHeight-(int)(20*mult), (int)(48*mult), (int)(16*mult)); + Minecraft.getMinecraft().getTextureManager().bindTexture(((Boolean) option.value) ? on : off); + 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/2+(int)(19*mult), y+tileHeight-(int)(19*mult), (int)(14*mult), (int)(14*mult)); + 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)) { + 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(option.displayName); - textLines.add(EnumChatFormatting.GRAY+option.desc); + textLines.add(EnumChatFormatting.GRAY + option.desc); textToDisplay.set(textLines); } } + } else if(option.value instanceof Double) { + if(!textConfigMap.containsKey(option)) { + textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), + GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE | GuiElementTextField.SCALE_TEXT)); + } + GuiElementTextField tf = textConfigMap.get(option); + if(tf.getText().trim().endsWith(".0")) { + tf.setText(tf.getText().trim().substring(0, tf.getText().trim().length()-2)); + } + if(tf.getFocus()) { + tf.setSize(Math.max((int)(20*mult), fr.getStringWidth(tf.getText())+10), (int)(16*mult)); + tfTop.set(tf); + tfTopX.set(x+(int)(65*mult)); + tfTopY.set(y+tileHeight-(int)(20*mult)); + } else { + tf.setSize((int)(20*mult), (int)(16*mult)); + tf.render(x+(int)(65*mult), y+tileHeight-(int)(20*mult)); + } + + double sliderAmount = (((Options.Option<Double>)option).value-option.minValue)/(option.maxValue-option.minValue); + sliderAmount = Math.max(0, Math.min(1, sliderAmount)); + + GlStateManager.color(1f, 1f, 1f, 1f); + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on); + Utils.drawTexturedRect(x+5*mult, y + tileHeight-20*mult, (float)(54*mult*sliderAmount), 16*mult, + 0, (float)sliderAmount, 0, 1); + + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off); + Utils.drawTexturedRect((float)(x+5*mult+54*mult*sliderAmount), y + tileHeight - 20*mult, + (float)(54*mult*(1-sliderAmount)), 16*mult, + (float)(sliderAmount), 1, 0, 1); + + Minecraft.getMinecraft().getTextureManager().bindTexture(slider_button); + Utils.drawTexturedRect(x+1*mult+(float)(54*sliderAmount*mult), y + tileHeight - 20*mult, + 8*mult, 16*mult); } else { if(!textConfigMap.containsKey(option)) { textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0)); @@ -121,6 +157,13 @@ public class SettingsInfoPane extends InfoPane { } } + @Override + public void mouseInputOutside() { + for(GuiElementTextField tf : textConfigMap.values()) { + tf.otherComponentClick(); + } + } + public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) { iterateSettingTile(new SettingsTileConsumer() { @Override @@ -136,13 +179,74 @@ public class SettingsInfoPane extends InfoPane { } } } + } else if(option.value instanceof Double) { + if(!textConfigMap.containsKey(option)) { + textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), + GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE | GuiElementTextField.SCALE_TEXT)); + } + + GuiElementTextField tf = textConfigMap.get(option); + int tfX = x+(int)(65*mult); + int tfY = y+tileHeight-(int)(20*mult); + int tfWidth = tf.getWidth(); + int tfHeight = tf.getHeight(); + if(mouseY > tfY && mouseY < tfY+tfHeight) { + if(mouseX > tfX && mouseX < tfX+tfWidth) { + if(Mouse.getEventButtonState()) { + tf.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); + onTextfieldChange(tf, option); + return; + } else if(Mouse.getEventButton() == -1 && mouseDown) { + tf.mouseClickMove(mouseX, mouseY, 0, 0); //last 2 values are unused + return; + } + } else if(clickedSlider != option && Mouse.getEventButtonState() && mouseX > x+1*mult && mouseX < x+63*mult) { + clickedSlider = option; + clickedSliderX = x; + clickedSliderMult = mult; + } + } + + if(clickedSlider == option) { + float xMin = clickedSliderX+5*clickedSliderMult; + float xMax = clickedSliderX+59*clickedSliderMult; + + float sliderAmount = (mouseX - xMin)/(xMax - xMin); + sliderAmount = Math.max(0, Math.min(1, sliderAmount)); + + double range = option.maxValue - option.minValue; + double value = option.minValue + sliderAmount*range; + + if(range >= 10) { + value = Math.round(value); + } else if(range >= 1) { + value = Math.round(value*10)/10.0; + } else { + value = Math.round(value*100)/100.0; + } + + value = Math.max(option.minValue, Math.min(option.maxValue, value)); + + tf.setText(String.valueOf(value)); + onTextfieldChange(tf, option); + + if(Mouse.getEventButton() == 0 && !Mouse.getEventButtonState()) { + clickedSlider = null; + } + } + + if(Mouse.getEventButtonState()) tf.otherComponentClick(); } else { if(!textConfigMap.containsKey(option)) { textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0)); } GuiElementTextField tf = textConfigMap.get(option); - if(mouseX > x+(int)(10*mult) && mouseX < x+(int)(10*mult)+tileWidth-(int)(20*mult)) { - if(mouseY > y+tileHeight-(int)(20*mult) && mouseY < y+tileHeight-(int)(20*mult)+(int)(16*mult)) { + int tfX = x+(int)(10*mult); + int tfY = y+tileHeight-(int)(20*mult); + int tfWidth = tf.getWidth(); + int tfHeight = tf.getHeight(); + if(mouseX > tfX && mouseX < tfX+tfWidth) { + if(mouseY > tfY && mouseY < tfY+tfHeight) { if(Mouse.getEventButtonState()) { tf.mouseClicked(mouseX, mouseY, Mouse.getEventButton()); onTextfieldChange(tf, option); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java index 1112a882..9bcc2891 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java @@ -17,6 +17,7 @@ import java.util.regex.Pattern; public class GuiElementTextField extends GuiElement { + public static final int SCALE_TEXT = 0b100000; public static final int NUM_ONLY = 0b10000; public static final int NO_SPACE = 0b01000; public static final int FORCE_CAPS = 0b00100; @@ -55,6 +56,10 @@ public class GuiElementTextField extends GuiElement { return textField.getText(); } + public void setText(String text) { + textField.setText(text); + } + public void setSize(int searchBarXSize, int searchBarYSize) { this.searchBarXSize = searchBarXSize; this.searchBarYSize = searchBarYSize; @@ -89,6 +94,22 @@ public class GuiElementTextField extends GuiElement { return searchBarXSize + paddingUnscaled*2; } + private float getScaleFactor(String str) { + return Math.min(1, (searchBarXSize-2)/(float)Minecraft.getMinecraft().fontRendererObj.getStringWidth(str)); + } + + private boolean isScaling() { + return (options & SCALE_TEXT) != 0; + } + + private float getStringWidth(String str) { + if(isScaling()) { + return Minecraft.getMinecraft().fontRendererObj.getStringWidth(str)*getScaleFactor(str); + } else { + return Minecraft.getMinecraft().fontRendererObj.getStringWidth(str); + } + } + public int getCursorPos(int mouseX, int mouseY) { int xComp = mouseX - x; int yComp = mouseY - y; @@ -302,7 +323,7 @@ public class GuiElementTextField extends GuiElement { } } - if((options & NUM_ONLY) != 0 && textField.getText().matches("[^0-9]")) textField.setText(old); + if((options & NUM_ONLY) != 0 && textField.getText().matches("[^0-9.]")) textField.setText(old); } } @@ -364,8 +385,15 @@ public class GuiElementTextField extends GuiElement { for(int yOffI = 0; yOffI < texts.length; yOffI++) { int yOff = yOffI*extraSize; - Minecraft.getMinecraft().fontRendererObj.drawString(Utils.trimToWidth(texts[yOffI], searchBarXSize-10), x + 5, - y+(searchBarYSize-8)/2+yOff, Color.WHITE.getRGB()); + if(isScaling() && Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])>searchBarXSize-10) { + Utils.drawStringCenteredScaledMaxWidth(texts[yOffI], Minecraft.getMinecraft().fontRendererObj, x+searchBarXSize/2f, + y+searchBarYSize/2f+yOff, false, + searchBarXSize-2, Color.WHITE.getRGB()); + } else { + Minecraft.getMinecraft().fontRendererObj.drawString(Utils.trimToWidth(texts[yOffI], searchBarXSize-10), x + 5, + y+(searchBarYSize-8)/2+yOff, Color.WHITE.getRGB()); + } + } if(focus && System.currentTimeMillis()%1000>500) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java new file mode 100644 index 00000000..60361306 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java @@ -0,0 +1,24 @@ +package io.github.moulberry.notenoughupdates.mixins; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.StreamerMode; +import net.minecraft.client.gui.GuiIngame; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.scoreboard.Team; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin({GuiIngame.class}) +public class MixinGuiIngame { + + private static final String TARGET = "Lnet/minecraft/scoreboard/ScorePlayerTeam;" + + "formatPlayerName(Lnet/minecraft/scoreboard/Team;Ljava/lang/String;)Ljava/lang/String;"; + @Redirect(method="renderScoreboard", at=@At(value="INVOKE", target=TARGET)) + public String renderScoreboard_formatPlayerName(Team team, String name) { + if(NotEnoughUpdates.INSTANCE.isOnSkyblock() && NotEnoughUpdates.INSTANCE.manager.config.streamerMode.value) { + return StreamerMode.filterScoreboard(ScorePlayerTeam.formatPlayerName(team, name)); + } + return ScorePlayerTeam.formatPlayerName(team, name); + } +} 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 5eae3886..fdda8c66 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java @@ -10,7 +10,9 @@ import java.lang.reflect.Field; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class Options { @@ -23,40 +25,50 @@ public class Options { false, "Enable Item Editing", true, - "Dev Feature. Please don't use."); + "Dev Feature."); public Option<Boolean> onlyShowOnSkyblock = new Option( true, "Only Show On Skyblock", false, - "GUI Overlay only appears when you are playing Skyblock."); + "NEU Overlay only appears when you are playing Skyblock."); public Option<Boolean> hidePotionEffect = new Option( true, - "Hide Potion Effect", + "Hide Potion Effects", false, - "If true, the potion effects will not show in the inventory GUI."); + "Potion effects are hidden in the inventory GUI. Contrib: All the gamers that play on GUI AUTO"); public Option<Boolean> showQuickCommands = new Option( true, "Quick Commands", false, - "If true, shows quick commands above search bar."); + "Shows QuickCommands™ above search bar."); public Option<Boolean> advancedPriceInfo = new Option( false, - "Advanced Price Information", + "Adv. Item Price Info", false, - "Shows some extra information about item sales."); + "Shows some extra information about item prices."); public Option<Boolean> cacheRenderedItempane = new Option( true, - "Cache Rendered Itempane", + "Cache Itempane", + false, + "Caches the drawn itempane, drastically improving performance. Animated textures will not work."); + public Option<Boolean> streamerMode = new Option( + false, + "Streamer Mode", + false, + "Hides or randomises some stuff on your screen to prevent sniping."); + public Option<Boolean> hideApiKey = new Option( false, - "Caches the drawn itempane, drastically improving performance. However, animated textures will not work."); + "Hide Apikey Setting", + false, + "Hides the Apikey setting (please try not to leak Apikey if you're recording)"); public Option<Double> bgBlurFactor = new Option( - 10.0, - "Background Blur Factor", + 5.0, + "Background Blur", false, - "Changes the strength of pane background blur. 0-50."); + "Changes the strength of pane background blur. 0-50.", 0, 50); public Option<String> apiKey = new Option( "", - "Api key used for certain features.", + "Api Key", false, "Type /api new to receive key and put it here."); public Option<Boolean> autoupdate = new Option( @@ -71,24 +83,34 @@ public class Options { "If true, the itempane will stay open after the gui is closed."); public Option<Boolean> itemStyle = new Option( true, - "Circular Item BG Style", + "Circular Item Style", + false, + "Uses the circular item background style instead of the square style. Contrib: Calyps0"); + public Option<Boolean> hideEmptyPanes = new Option( + true, + "Hide GUI Filler Tooltips", false, - "If true, uses the circular item background style instead of the square style."); + "Hides the tooltip of glass panes in skyblock GUIs. Contrib: ThatGravyBoat"); public Option<Double> paneWidthMult = new Option( 1.0, - "Pane Width Multiplier", + "Pane Width", false, - "Changes how wide the item and info panes are. Value between 0.5-1.5."); + "Changes how wide the item and info panes are. Value between 0.5-1.5.", 0.5, 1.5); public Option<Double> bgOpacity = new Option( - 50.0, + 30.0, "Pane Background Opacity", false, - "Changes the background colour opacity of item and info panes. Value between 0-255."); + "Changes the background colour opacity of item and info panes. Value between 0-255.", 0, 255); public Option<Double> fgOpacity = new Option( 255.0, "Item Background Opacity", false, - "Changes the opacity of item background. Value between 0-255."); + "Changes the opacity of item background. Value between 0-255.", 0, 255); + public Option<Double> panePadding = new Option( + 10.0, + "Pane Padding", + false, + "Changes the padding of the panes. Value between 0-20.", 0, 20); /** * OPTIONS THAT DON'T SHOW IN GUI @@ -109,7 +131,7 @@ public class Options { false, "Sort Mode"); public Option<ArrayList<Boolean>> compareAscending = new Option( - Utils.createList(true, true), + Utils.createList(true, true, true), "Compare Ascending", false, "Compare Ascending"); @@ -118,6 +140,11 @@ public class Options { "Favourites", false, "Favourites"); + public Option<Map<String, ArrayList<String>>> collectionLog = new Option( + new HashMap<String, ArrayList<String>>(), + "CollectionLog", + false, + "CollectionLog"); public Option<ArrayList<String>> quickCommands = new Option( createDefaultQuickCommands(), "Quick Commands", @@ -131,31 +158,39 @@ public class Options { arr.add("/craft:CRAFTING_TABLE"); arr.add("/enderchest:ENDER_CHEST"); arr.add("/wardrobe:LEATHER_CHESTPLATE"); + arr.add("/collectionlog:MAP"); return arr; } 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(hideApiKey, options); tryAddOption(autoupdate, options); tryAddOption(keepopen, options); tryAddOption(itemStyle, options); + tryAddOption(hideEmptyPanes, options); + //Sliders tryAddOption(bgBlurFactor, options); - tryAddOption(apiKey, options); tryAddOption(paneWidthMult, options); tryAddOption(bgOpacity, options); tryAddOption(fgOpacity, options); + tryAddOption(panePadding, options); + //Text + tryAddOption(apiKey, options); return options; } private void tryAddOption(Option<?> option, List<Option> list) { - if(!option.secret || dev.value) { + if(!option.secret) {// || dev.value) { list.add(option); } } @@ -166,13 +201,21 @@ public class Options { public final transient String displayName; public final transient boolean secret; public final transient String desc; + public final transient double minValue; + public final transient double maxValue; public Option(T defaultValue, String displayName, boolean secret, String desc) { + this(defaultValue, displayName, secret, desc, 0, 100); + } + + public Option(T defaultValue, String displayName, boolean secret, String desc, double minValue, double maxValue) { this.value = defaultValue; this.defaultValue = defaultValue; this.displayName = displayName; this.secret = secret; this.desc = desc; + this.minValue = minValue; + this.maxValue = maxValue; } public void setValue(String value) { @@ -215,6 +258,12 @@ public class Options { for(Field f : Options.class.getDeclaredFields()) { try { + if(((Option)f.get(oDefault)).value instanceof List) { + //If the default size of the list is greater than the loaded size, use the default value. + if(((List<?>)((Option)f.get(oDefault)).value).size() > ((List<?>)((Option)f.get(oLoad)).value).size()) { + continue; + } + } ((Option)f.get(oDefault)).value = ((Option)f.get(oLoad)).value; } catch (Exception e) { } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java index 65e7305a..48eea22d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java @@ -21,6 +21,8 @@ public class TexLoc { } public void handleKeyboardInput() { + int mult=1; + if(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) mult=10; if(Keyboard.isKeyDown(toggleKey)) { if(!pressedLastTick) { toggled = !toggled; @@ -31,16 +33,16 @@ public class TexLoc { } if(toggled) { if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)) { - if(!dirPressed) x--; + if(!dirPressed) x-=mult; dirPressed = true; } else if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) { - if(!dirPressed) x++; + if(!dirPressed) x+=mult; dirPressed = true; } else if(Keyboard.isKeyDown(Keyboard.KEY_UP)) { - if(!dirPressed) y--; + if(!dirPressed) y-=mult; dirPressed = true; } else if(Keyboard.isKeyDown(Keyboard.KEY_DOWN)) { - if(!dirPressed) y++; + if(!dirPressed) y+=mult; dirPressed = true; } else { dirPressed = false; diff --git a/src/main/resources/assets/notenoughupdates/ah_item_holder.png b/src/main/resources/assets/notenoughupdates/ah_item_holder.png Binary files differnew file mode 100644 index 00000000..ed396f25 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/ah_item_holder.png diff --git a/src/main/resources/assets/notenoughupdates/ah_item_tab.png b/src/main/resources/assets/notenoughupdates/ah_item_tab.png Binary files differnew file mode 100644 index 00000000..c307fa31 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/ah_item_tab.png diff --git a/src/main/resources/assets/notenoughupdates/item_mask.png b/src/main/resources/assets/notenoughupdates/item_mask.png Binary files differindex 7a202a33..3b402d7f 100644 --- a/src/main/resources/assets/notenoughupdates/item_mask.png +++ b/src/main/resources/assets/notenoughupdates/item_mask.png diff --git a/src/main/resources/assets/notenoughupdates/off.png b/src/main/resources/assets/notenoughupdates/off.png Binary files differindex 174d1b4f..cfb17e40 100644 --- a/src/main/resources/assets/notenoughupdates/off.png +++ b/src/main/resources/assets/notenoughupdates/off.png diff --git a/src/main/resources/assets/notenoughupdates/order_value.png b/src/main/resources/assets/notenoughupdates/order_value.png Binary files differnew file mode 100644 index 00000000..5526e8f6 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/order_value.png diff --git a/src/main/resources/assets/notenoughupdates/order_value_active.png b/src/main/resources/assets/notenoughupdates/order_value_active.png Binary files differnew file mode 100644 index 00000000..3864021c --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/order_value_active.png diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/blit.vsh b/src/main/resources/assets/notenoughupdates/shaders/program/blit.vsh new file mode 100644 index 00000000..01a16db5 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/shaders/program/blit.vsh @@ -0,0 +1,16 @@ +#version 120 + +attribute vec4 Position; + +uniform mat4 ProjMat; +uniform vec2 OutSize; + +varying vec2 texCoord; + +void main(){ + vec4 outPos = ProjMat * vec4(Position.xy, 0.0, 1.0); + gl_Position = vec4(outPos.xy, 0.2, 1.0); + + texCoord = Position.xy / OutSize; + texCoord.y = 1.0 - texCoord.y; +} diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/grayscale.fsh b/src/main/resources/assets/notenoughupdates/shaders/program/grayscale.fsh new file mode 100644 index 00000000..70875510 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/shaders/program/grayscale.fsh @@ -0,0 +1,15 @@ +#version 120 + +uniform sampler2D DiffuseSampler; + +varying vec2 texCoord; + +void main(){ + vec3 Gray = vec3(0.3, 0.59, 0.11); + vec4 diffuseColor = texture2D(DiffuseSampler, texCoord); + + float Luma = dot(diffuseColor.rgb, Gray); + diffuseColor.rgb = vec3(Luma, Luma, Luma); + + gl_FragColor = diffuseColor; +} diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/grayscale.json b/src/main/resources/assets/notenoughupdates/shaders/program/grayscale.json new file mode 100644 index 00000000..048ceb9f --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/shaders/program/grayscale.json @@ -0,0 +1,17 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "blit", + "fragment": "grayscale", + "attributes": [ "Position" ], + "samplers": [ + { "name": "DiffuseSampler" } + ], + "uniforms": [ + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } + ] +} diff --git a/src/main/resources/assets/notenoughupdates/slider_button.png b/src/main/resources/assets/notenoughupdates/slider_button.png Binary files differnew file mode 100644 index 00000000..aeb81b86 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/slider_button.png diff --git a/src/main/resources/assets/notenoughupdates/slider_off.png b/src/main/resources/assets/notenoughupdates/slider_off.png Binary files differnew file mode 100644 index 00000000..0f514c41 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/slider_off.png diff --git a/src/main/resources/assets/notenoughupdates/slider_on.png b/src/main/resources/assets/notenoughupdates/slider_on.png Binary files differnew file mode 100644 index 00000000..8d2d6680 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/slider_on.png diff --git a/src/main/resources/mixins.notenoughupdates.json b/src/main/resources/mixins.notenoughupdates.json index 6b616e4e..49e37916 100644 --- a/src/main/resources/mixins.notenoughupdates.json +++ b/src/main/resources/mixins.notenoughupdates.json @@ -4,6 +4,7 @@ "compatibilityLevel": "JAVA_8", "mixins": [ "MixinItemStack", - "MixinInventoryEffectRenderer" + "MixinInventoryEffectRenderer", + "MixinGuiIngame" ] }
\ No newline at end of file |