aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
diff options
context:
space:
mode:
authorunknown <james.jenour@protonmail.com>2020-07-02 00:53:17 +1000
committerunknown <james.jenour@protonmail.com>2020-07-02 00:53:17 +1000
commitbd6f658c6c53d160c40bc3b5fdead7b7b3dd20c4 (patch)
tree8cf4a287369c94e377604561d937b7096c0abf50 /src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
parentfa7be3a200f26d53eabfc58e509fd9c6d0a2fd10 (diff)
downloadnotenoughupdates-bd6f658c6c53d160c40bc3b5fdead7b7b3dd20c4.tar.gz
notenoughupdates-bd6f658c6c53d160c40bc3b5fdead7b7b3dd20c4.tar.bz2
notenoughupdates-bd6f658c6c53d160c40bc3b5fdead7b7b3dd20c4.zip
1.8
Diffstat (limited to 'src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java492
1 files changed, 492 insertions, 0 deletions
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;
+ }
+}