diff options
| author | unknown <james.jenour@protonmail.com> | 2020-07-02 00:53:17 +1000 |
|---|---|---|
| committer | unknown <james.jenour@protonmail.com> | 2020-07-02 00:53:17 +1000 |
| commit | bd6f658c6c53d160c40bc3b5fdead7b7b3dd20c4 (patch) | |
| tree | 8cf4a287369c94e377604561d937b7096c0abf50 /src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java | |
| parent | fa7be3a200f26d53eabfc58e509fd9c6d0a2fd10 (diff) | |
| download | notenoughupdates-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.java | 492 |
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; + } +} |
