diff options
author | Moulberry <james.jenour@student.scotch.wa.edu.au> | 2020-08-23 11:09:19 +1000 |
---|---|---|
committer | Moulberry <james.jenour@student.scotch.wa.edu.au> | 2020-08-23 11:09:19 +1000 |
commit | 3cb08dc571907bdf216ee628c1f8608067a03441 (patch) | |
tree | e98e8e67c74394eae1815c3657eccb92e018ba48 /src | |
parent | 65ae0aa5a0319b6ead2dd6ed07c53a7e7291a23d (diff) | |
download | NotEnoughUpdates-3cb08dc571907bdf216ee628c1f8608067a03441.tar.gz NotEnoughUpdates-3cb08dc571907bdf216ee628c1f8608067a03441.tar.bz2 NotEnoughUpdates-3cb08dc571907bdf216ee628c1f8608067a03441.zip |
fine dj
Diffstat (limited to 'src')
25 files changed, 1092 insertions, 1107 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java index f4fcc41d..fe3c7542 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java @@ -51,7 +51,9 @@ public class CustomItemEffects { if(delta <= 0) return; - if(aoteTeleportationMillis > 300) aoteTeleportationMillis = 300; + if(aoteTeleportationMillis > NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value.intValue()*2) { + aoteTeleportationMillis = NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value.intValue()*2; + } if(aoteTeleportationMillis < 0) aoteTeleportationMillis = 0; if(currentTime - aoteUseMillis > 1000 && aoteTeleportationMillis <= 0) { @@ -91,6 +93,8 @@ public class CustomItemEffects { @SubscribeEvent public void onPlayerInteract(PlayerInteractEvent event) { + if(NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value <= 0) return; + if(event.action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR || event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem(); if(held != null) { @@ -113,6 +117,7 @@ public class CustomItemEffects { if(aoteTeleportationCurr != null && aoteTeleportationMillis > 0) { event.setCanceled(true); } + if(NotEnoughUpdates.INSTANCE.manager.config.disableTreecapOverlay.value) return; ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem(); String heldInternal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held); if(heldInternal != null) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUCape2.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUCape2.java deleted file mode 100644 index 996809da..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUCape2.java +++ /dev/null @@ -1,607 +0,0 @@ -package io.github.moulberry.notenoughupdates; - -import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.texture.SimpleTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.command.CommandBase; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.*; -import net.minecraftforge.client.event.ClientChatReceivedEvent; -import net.minecraftforge.client.event.RenderPlayerEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.EntityJoinWorldEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL20; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class NEUCape2 { - - //private ResourceLocation capeImageLocation = new ResourceLocation(Morus.MODID, "cape.jpg"); - //private SimpleTexture capeTexture; - - private long millisLastRenderUpdate = 0; - - private int horzNodes = 20; - private double targetDist = 1/30.0; - - private EntityPlayer player = null; - - private double vertOffset = 1.4; - private double shoulderLength = 0.3; - private double shoulderWidth = 0.13; - private double crouchWidthOffset = -0.05; - private double maxCrouchOffset = 0.35; - - private double resistance = 0.08; - private double gravity = 0.04; - private int steps = 10; - - private List<List<Node>> nodes = new ArrayList<>(); - - /*private void reloadCapeImage() { - if(capeTexture != null) { - capeTexture.deleteGlTexture(); - } - capeTexture = new SimpleTexture(capeImageLocation); - try { - capeTexture.loadTexture(Minecraft.getMinecraft().getResourceManager()); - } catch(IOException e) { - e.printStackTrace(); - } - }*/ - - private void resetNodes(EntityPlayer player) { - nodes.clear(); - for(int i=0; i<50; i++) { - List<Node> list = new ArrayList<>(); - for(int j=0; j<horzNodes; j++) { - if(horzNodes == 1) { - list.add(new Node(player.posX-1, player.posY+2-i*targetDist, player.posZ, i, j)); - } else if(horzNodes > 1) { - list.add(new Node(player.posX-1, player.posY+2-i*targetDist, player.posZ+((double)j)/(horzNodes-1), i, j)); - } - } - - nodes.add(list); - } - } - - class Node { - public int iIndex; - public int jIndex; - - public boolean fixed = false; - - public double x; - public double y; - public double z; - public double xOld; - public double yOld; - public double zOld; - public double aX; - public double aY; - public double aZ; - - public double normalX; - public double normalY; - public double normalZ; - - public Node(double x, double y, double z, int iIndex, int jIndex) { - this.x = xOld = x; - this.y = xOld = y; - this.z = xOld = z; - this.iIndex = iIndex; - this.jIndex = jIndex; - } - - private void updateNormal(Node up, Node left, Node right, Node down, Node up2, Node left2, Node right2, Node down2) { - Vec3 normal1 = normal(up, left); - Vec3 normal2 = normal(right, up); - Vec3 normal3 = normal(down, right); - Vec3 normal4 = normal(left, down); - Vec3 normal5 = normal(up2, left2); - Vec3 normal6 = normal(right2, up2); - Vec3 normal7 = normal(down2, right2); - Vec3 normal8 = normal(left2, down2); - - Vec3 avgNormal = normal1.add(normal2).add(normal3).add(normal4) - .add(normal5).add(normal6).add(normal7).add(normal8).normalize(); - - normalX = avgNormal.xCoord; - normalY = avgNormal.yCoord; - normalZ = avgNormal.zCoord; - } - - private Vec3 normal(Node node1, Node node2) { - if(node1 == null || node2 == null) { - return new Vec3(0,0,0); - } - Vec3 thisNode = node2vec(this); - Vec3 node1Vec = node2vec(node1); - Vec3 node2Vec = node2vec(node2); - - Vec3 thisTo1 = node1Vec.subtract(thisNode); - Vec3 thisTo2 = node2Vec.subtract(thisNode); - - return thisTo1.crossProduct(thisTo2); - - } - - public void update(double pX, double pY, double pZ, EntityPlayer player) { - if(fixed) { - return; - } - - double xTemp = x; - double yTemp = y; - double zTemp = z; - - double res = resistance; - - BlockPos pos = new BlockPos( - MathHelper.floor_double(x), - MathHelper.floor_double(y), - MathHelper.floor_double(z)); - Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock(); - if(block.getMaterial().isLiquid()) { - aX /= 5; - aY /= 5; - aZ /= 5; - - res = Math.sqrt(res); - } - - double xDiff = x-xOld; - double yDiff = y-yOld; - double zDiff = z-zOld; - - xDiff = MathHelper.clamp_double(xDiff, -0.5, 0.5); - yDiff = MathHelper.clamp_double(yDiff, -0.5, 0.5); - zDiff = MathHelper.clamp_double(zDiff, -0.5, 0.5); - - x = x + xDiff*(1-res)+aX*0.2; - y = y + yDiff*(1-res)+aY*0.2; - z = z + zDiff*(1-res)+aZ*0.2; - - resolvePlayerCollision(pX, pY, pZ, player); - - if(!checkCollision(xTemp, yTemp, zTemp)) { - xOld = xTemp; - yOld = yTemp; - zOld = zTemp; - } - - if(checkCollision(x, y, z)) { - updateFromBoundingBox(); - } - - aX = 0; - aY = 0; - aZ = 0; - } - - public boolean resolvePlayerCollision(double pX, double pY, double pZ, EntityPlayer player) { - double angle = Math.toRadians(player.renderYawOffset); - - double offset = 0; - - if(player.getCurrentArmor(1) != null) { - if(player.isSneaking()) { - offset += 0.15; - } else { - offset += 0.06; - } - } - - if(player.isSneaking()) { - offset -= crouchWidthOffset; - - double dY = y - player.posY; - - if(dY < 0.65) { - offset += maxCrouchOffset; - } else if(dY < 1.2) { - offset += maxCrouchOffset*(1.2-dY)/0.55; - } - } - - double x1 = pX+Math.cos(angle)*2-Math.cos(angle+Math.PI/2)*(shoulderWidth+offset); - double z1 = pZ+Math.sin(angle)*2-Math.sin(angle+Math.PI/2)*(shoulderWidth+offset); - double x2 = pX-Math.cos(angle)*2-Math.cos(angle+Math.PI/2)*(shoulderWidth+offset); - double z2 = pZ-Math.sin(angle)*2-Math.sin(angle+Math.PI/2)*(shoulderWidth+offset); - - boolean crossed = ((x2 - x1)*(z - z1) < (z2 - z1)*(x - x1)); - - if(crossed) { - double dot1 = ((x-x2)*(x1-x2)+(z-z2)*(z1-z2)); - double dot2 = (x1-x2)*(x1-x2)+(z1-z2)*(z1-z2); - double k = dot1/dot2; - - x = xOld = (x1-x2)*k+x2; - z = zOld = (z1-z2)*k+z2; - - return true; - } - return false; - } - - public void updateFromBoundingBox() { - BlockPos pos = new BlockPos( - MathHelper.floor_double(x), - MathHelper.floor_double(y), - MathHelper.floor_double(z)); - Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock(); - block.setBlockBoundsBasedOnState(Minecraft.getMinecraft().theWorld, pos); - AxisAlignedBB bb = block.getSelectedBoundingBox(Minecraft.getMinecraft().theWorld, pos); - - Vec3 center = new Vec3((bb.minX + bb.maxX) / 2, (bb.minY + bb.maxY) / 2, (bb.minZ + bb.maxZ) / 2); - MovingObjectPosition mop = bb.calculateIntercept(center.add(new Vec3(x, y, z).subtract(center).normalize()), center); - - if(mop == null) { - return; - } - - Vec3 vec = mop.hitVec; - - if(vec == null) { - return; - } - - double dX = vec.xCoord - x; - double dY = vec.yCoord - y; - double dZ = vec.zCoord - z; - double adX = Math.abs(dX); - double adY = Math.abs(dY); - double adZ = Math.abs(dZ); - - double tot = adX + adY + adZ; - - //Simulate a little bit of friction - if(tot < 0.15 || checkCollision(vec.xCoord, vec.yCoord, vec.zCoord)) { - x = xOld; - y = yOld; - z = zOld; - return; - } - - //>0.3 check reduces the movement at corners a little bit - if(adX/tot > 0.3) x = xOld = vec.xCoord; - if(adY/tot > 0.3) y = yOld = vec.yCoord; - if(adZ/tot > 0.3) z = zOld = vec.zCoord; - } - - public boolean checkCollision(double x, double y, double z) { - BlockPos pos = new BlockPos( - MathHelper.floor_double(x), - MathHelper.floor_double(y), - MathHelper.floor_double(z)); - Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock(); - - if(block.getMaterial().isSolid()) { - block.setBlockBoundsBasedOnState(Minecraft.getMinecraft().theWorld, pos); - AxisAlignedBB bb = block.getSelectedBoundingBox(Minecraft.getMinecraft().theWorld, pos); - - return bb.isVecInside(new Vec3(x, y, z)); - } else { - return false; - } - } - } - - @SubscribeEvent - public void onRenderTick(TickEvent.RenderTickEvent e) { - if(Minecraft.getMinecraft().theWorld == null || player == null) { - return; - } - - long delta = System.currentTimeMillis() - millisLastRenderUpdate; - - double lagFactor = delta/(1000/60.0); - if(lagFactor > 3) { - lagFactor = 3; - } - - double playerX = player.lastTickPosX + (player.posX - player.lastTickPosX) * e.renderTickTime; - double playerY = player.lastTickPosY + (player.posY - player.lastTickPosY) * e.renderTickTime; - double playerZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * e.renderTickTime; - - updateFixedNodes(playerX, playerY, playerZ, player); - - for(List<Node> nodes2 : nodes) { - for(Node node : nodes2) { - node.aY -= gravity*lagFactor; - node.update(playerX, playerY, playerZ, player); - } - } - for(int step=0; step<steps*lagFactor; step++) { - for(int i=0; i<nodes.size(); i++) { - for (int j = 0; j < horzNodes; j++) { - Node node = nodes.get(i).get(j); - List<Node> struct = new ArrayList<>(); - List<Node> shear = new ArrayList<>(); - List<Node> bend = new ArrayList<>(); - - if(i+1 < nodes.size()) struct.add(nodes.get(i+1).get(j)); - if(j+1 < horzNodes) struct.add(nodes.get(i).get(j+1)); - if(i-1 >= 0) struct.add(nodes.get(i-1).get(j)); - if(j-1 >= 0) struct.add(nodes.get(i).get(j-1)); - - if(i+1 < nodes.size() && j+1 < horzNodes) shear.add(nodes.get(i+1).get(j+1)); - if(i+1 < nodes.size() && j-1 >= 0) shear.add(nodes.get(i+1).get(j-1)); - if(i-1 >= 0 && j+1 < horzNodes) shear.add(nodes.get(i-1).get(j+1)); - if(i-1 >= 0 && j-1 >= 0) shear.add(nodes.get(i-1).get(j-1)); - - if(i+2 < nodes.size()) bend.add(nodes.get(i+2).get(j)); - if(j+2 < horzNodes) bend.add(nodes.get(i).get(j+2)); - if(i-2 >= 0) bend.add(nodes.get(i-2).get(j)); - if(j-2 >= 0) bend.add(nodes.get(i).get(j-2)); - - try { - updateNode(node, struct, shear, bend); - } catch(Exception ex) { - - } - } - } - } - for(int i=0; i<nodes.size(); i++) { - for (int j = 0; j < horzNodes; j++) { - Node up = null, down = null, left = null, right = null; - Node up2 = null, down2 = null, left2 = null, right2 = null; - - if(i+1 < nodes.size()) down = nodes.get(i+1).get(j); - if(j+1 < horzNodes) right = nodes.get(i).get(j+1); - if(i-1 >= 0) up = nodes.get(i-1).get(j); - if(j-1 >= 0) left = nodes.get(i).get(j-1); - - if(i+2 < nodes.size()) down2 = nodes.get(i+2).get(j); - if(j+2 < horzNodes) right2 = nodes.get(i).get(j+2); - if(i-2 >= 0) up2 = nodes.get(i-2).get(j); - if(j-2 >= 0) left2 = nodes.get(i).get(j-2); - - nodes.get(i).get(j).updateNormal(up, left, right, down, up2, left2, right2, down2); - } - } - - millisLastRenderUpdate = System.currentTimeMillis(); - } - - @SubscribeEvent - public void onRenderPlayer(RenderPlayerEvent.Post e) { - EntityPlayer player = e.entityPlayer; - - if(!player.getName().equalsIgnoreCase("Moulberry")) { - return; - } - - if(nodes.size() == 0) { - resetNodes(player); - } - - this.player = player; - - Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); - - double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * e.partialRenderTick; - double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * e.partialRenderTick; - double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * e.partialRenderTick; - - GlStateManager.pushMatrix(); - GlStateManager.enableBlend(); - GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, - GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); - GL11.glDisable(GL11.GL_CULL_FACE); - GlStateManager.enableTexture2D(); - int currTex = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); - //GL11.glBindTexture(GL11.GL_TEXTURE_2D, capeTexture.getGlTextureId()); - - //ShaderManager shaderManager = ShaderManager.getInstance(); - - //shaderManager.loadShader("cape"); - - for(int i=0; i<nodes.size(); i++) { - for(int j=0; j<horzNodes; j++) { - Node node = nodes.get(i).get(j); - if(i+1 < nodes.size() && j+1 < horzNodes) { - GlStateManager.color(1F, 1F, 1F, 1F); - renderNodeConnection(viewerX, viewerY, viewerZ, node, - nodes.get(i+1).get(j), nodes.get(i).get(j+1), - nodes.get(i+1).get(j+1), true); - GlStateManager.color(0.1F, 0.1F, 0.1F, 1F); - renderNodeConnection(viewerX, viewerY, viewerZ, node, - nodes.get(i+1).get(j), nodes.get(i).get(j+1), - nodes.get(i+1).get(j+1), false); - } - } - } - - GlStateManager.color(0.1F, 0.1F, 0.1F, 1F); - for(int i=0; i<nodes.size(); i++) { - if(i+1 < nodes.size()) { - renderSideConnection(viewerX, viewerY, viewerZ, - nodes.get(i).get(0), nodes.get(i+1).get(0)); - renderSideConnection(viewerX, viewerY, viewerZ, - nodes.get(i).get(horzNodes-1), nodes.get(i+1).get(horzNodes-1)); - } - } - - for(int j=0; j<horzNodes; j++) { - if(j+1 < horzNodes) { - renderSideConnection(viewerX, viewerY, viewerZ, - nodes.get(0).get(j), nodes.get(0).get(j+1)); - renderSideConnection(viewerX, viewerY, viewerZ, - nodes.get(nodes.size()-1).get(j), nodes.get(nodes.size()-1).get(j+1)); - } - } - - GL20.glUseProgram(0); - - GL11.glBindTexture(GL11.GL_TEXTURE_2D, currTex); - GL11.glEnable(GL11.GL_CULL_FACE); - GlStateManager.enableTexture2D(); - GlStateManager.disableBlend(); - GlStateManager.popMatrix(); - GlStateManager.color(1F, 1F, 1F, 1F); - } - - private Vec3 node2vec(Node node) { - return new Vec3(node.x, node.y, node.z); - } - - private void renderSideConnection(double pX, double pY, double pZ, Node node1, Node node2) { - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - - worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_NORMAL); - - worldrenderer.pos(node1.x-pX, node1.y-pY, node1.z-pZ) - .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex(); - worldrenderer.pos(node2.x-pX, node2.y-pY, node2.z-pZ) - .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex(); - worldrenderer.pos(node1.x-pX+node1.normalX/15, node1.y-pY+node1.normalY/15, node1.z-pZ+node1.normalZ/15) - .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex(); - worldrenderer.pos(node2.x-pX+node2.normalX/15, node2.y-pY+node2.normalY/15, node2.z-pZ+node2.normalZ/15) - .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex(); - - tessellator.draw(); - } - - private void renderNodeConnection(double pX, double pY, double pZ, Node node1, Node node2, - Node node3, Node node4, boolean offset) { - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - - //Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(node1.normalY + " " + node2.normalY + " " + node3.normalY + " " + node4.normalY)); - - if(offset) { - worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_NORMAL); - - worldrenderer.pos(node1.x-pX+node1.normalX/15, node1.y-pY+node1.normalY/15, node1.z-pZ+node1.normalZ/15) - .tex(((double)node1.jIndex)/(horzNodes-1), ((double)node1.iIndex)/(nodes.size()-1)) - .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex(); - worldrenderer.pos(node2.x-pX+node2.normalX/15, node2.y-pY+node2.normalY/15, node2.z-pZ+node2.normalZ/15) - .tex(((double)node2.jIndex)/(horzNodes-1), ((double)node2.iIndex)/(nodes.size()-1)) - .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex(); - worldrenderer.pos(node3.x-pX+node3.normalX/15, node3.y-pY+node3.normalY/15, node3.z-pZ+node3.normalZ/15) - .tex(((double)node3.jIndex)/(horzNodes-1), ((double)node3.iIndex)/(nodes.size()-1)) - .normal((float)node3.normalX, (float)node3.normalY, (float)node3.normalZ).endVertex(); - worldrenderer.pos(node4.x-pX+node4.normalX/15, node4.y-pY+node4.normalY/15, node4.z-pZ+node4.normalZ/15) - .tex(((double)node4.jIndex)/(horzNodes-1), ((double)node4.iIndex)/(nodes.size()-1)) - .normal((float)node4.normalX, (float)node4.normalY, (float)node4.normalZ).endVertex(); - - } else { - worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_NORMAL); - - worldrenderer.pos(node1.x-pX, node1.y-pY, node1.z-pZ) - .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex(); - worldrenderer.pos(node2.x-pX, node2.y-pY, node2.z-pZ) - .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex(); - worldrenderer.pos(node3.x-pX, node3.y-pY, node3.z-pZ) - .normal((float)node3.normalX, (float)node3.normalY, (float)node3.normalZ).endVertex(); - worldrenderer.pos(node4.x-pX, node4.y-pY, node4.z-pZ) - .normal((float)node4.normalX, (float)node4.normalY, (float)node4.normalZ).endVertex(); - } - - tessellator.draw(); - } - - private Vec3 scale(Vec3 vector, double amount) { - return new Vec3(vector.xCoord * amount, vector.yCoord * amount, vector.zCoord * amount); - } - - private void updateNode(Node node, List<Node> struct, List<Node> shear, List<Node> bend) { - double shearDist = 1.414*targetDist; - double bendDist = 2*targetDist; //Potentially differentiate between corners? - - for(Node bendNode : bend) { - resolve(node, bendNode, bendDist); - } - - for(Node shearNode : shear) { - resolve(node, shearNode, shearDist); - } - - for(Node structNode : struct) { - resolve(node, structNode, targetDist); - } - } - - public void resolve(Node node1, Node node2, double targetDist) { - double dX = node1.x - node2.x; - double dY = node1.y - node2.y; - double dZ = node1.z - node2.z; - - double distSq = dX*dX + dY*dY + dZ*dZ; - double dist = Math.sqrt(distSq); - - dX *= (1 - targetDist/dist)*0.5; - dY *= (1 - targetDist/dist)*0.5; - dZ *= (1 - targetDist/dist)*0.5; - - if(node1.fixed || node2.fixed) { - dX *= 2; - dY *= 2; - dZ *= 2; - } - - if(!node1.fixed) { - node1.x -= dX; - node1.y -= dY; - node1.z -= dZ; - } - - if(!node2.fixed) { - node2.x += dX; - node2.y += dY; - node2.z += dZ; - } - } - - private void updateFixedNodes(double pX, double pY, double pZ, EntityPlayer player) { - double angle = Math.toRadians(player.renderYawOffset); - - double shoulderWidth2 = shoulderWidth + (player.isSneaking()?crouchWidthOffset:0); - if(player.getCurrentArmor(1) != null || player.getCurrentArmor(2) != null) { - if(player.isSneaking()) { - shoulderWidth2 += 0.15; - } else { - shoulderWidth2 += 0.06; - } - } - - Node node = nodes.get(0).get(0); - node.x = pX+Math.cos(angle)*shoulderLength-Math.cos(angle+Math.PI/2)*shoulderWidth2; - node.y = pY+vertOffset-(player.isSneaking()?0.2:0); - node.z = pZ+Math.sin(angle)*shoulderLength-Math.sin(angle+Math.PI/2)*shoulderWidth2; - node.fixed = true; - - node = nodes.get(0).get(nodes.get(0).size()-1); - node.x = pX-Math.cos(angle)*shoulderLength-Math.cos(angle+Math.PI/2)*shoulderWidth2; - node.y = pY+vertOffset-(player.isSneaking()?0.2:0); - node.z = pZ-Math.sin(angle)*shoulderLength-Math.sin(angle+Math.PI/2)*shoulderWidth2; - node.fixed = true; - - - - /*for(int i=0; i<horzNodes; i++) { - Node node = nodes.get(0).get(i); - - node.x = pX-1; - node.y = pY+2; - node.z = pZ+((double)i)/(horzNodes-1); - }*/ - } - - -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java index af23787a..820c14b1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java @@ -1,6 +1,7 @@ package io.github.moulberry.notenoughupdates; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.auction.APIManager; import io.github.moulberry.notenoughupdates.auction.CustomAHGui; import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.gamemodes.SBGamemodes; @@ -22,6 +23,7 @@ import net.minecraft.event.ClickEvent; import net.minecraft.init.Blocks; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -567,7 +569,7 @@ public class NEUEventListener { } private void renderDungeonChestOverlay(GuiScreen gui) { - if(gui instanceof GuiChest && neu.manager.auctionManager.activeAuctions > 0) { + if(gui instanceof GuiChest && neu.manager.auctionManager.activeAuctions > 0 && !neu.manager.config.dungeonProfitLore.value) { try { int xSize = (int) Utils.getField(GuiContainer.class, gui, "xSize", "field_146999_f"); int ySize = (int) Utils.getField(GuiContainer.class, gui, "ySize", "field_147000_g"); @@ -583,7 +585,7 @@ public class NEUEventListener { Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth); GL11.glColor4f(1, 1, 1, 1); GlStateManager.disableLighting(); - Utils.drawTexturedRect(guiLeft+xSize+4, guiTop, 180, 45, 0, 180/256f, 0, 45/256f, GL11.GL_NEAREST); + Utils.drawTexturedRect(guiLeft+xSize+4, guiTop, 180, 71, 0, 180/256f, 0, 71/256f, GL11.GL_NEAREST); int chestCost = 0; String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]); @@ -599,53 +601,84 @@ public class NEUEventListener { } boolean missing = false; - int totalValue = 0; + int totalValueBIN = 0; + int totalValueAUC = 0; for(int i=0; i<5; i++) { ItemStack item = lower.getStackInSlot(11+i); String internal = neu.manager.getInternalNameForItem(item); if(internal != null) { - float worth = neu.manager.auctionManager.getLowestBin(internal); + float worthBIN = neu.manager.auctionManager.getLowestBin(internal); + float worthAUC = -1; + JsonObject aucInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if(aucInfo != null) { + worthAUC = aucInfo.get("price").getAsFloat(); + } - if(worth == -1) worth = neu.manager.getCraftCost(internal).craftCost; + if(worthAUC == -1) worthAUC = neu.manager.auctionManager.getCraftCost(internal).craftCost; - if(worth > 0) { - totalValue += worth; - } else { + if(worthAUC <= 0 && worthBIN <= 0) { missing = true; break; } + + if(worthBIN > 0 && totalValueBIN >= 0) { + totalValueBIN += worthBIN; + } else { + totalValueBIN = -1; + } + + if(worthAUC > 0 && totalValueAUC >= 0) { + totalValueAUC += worthAUC; + } else { + totalValueAUC = -1; + } } } - int profitLoss = totalValue - chestCost; - - NumberFormat format = NumberFormat.getInstance(Locale.US); - String valueString; - if(!missing) { - valueString = EnumChatFormatting.BLUE+"Chest value: " + EnumChatFormatting.GOLD - + EnumChatFormatting.BOLD + format.format(totalValue) + " coins"; - } else { - valueString = EnumChatFormatting.BLUE+"Couldn't find item on AH. Item is very rare!"; + if(totalValueAUC <= 0 && totalValueBIN <= 0) { + missing = true; } - String plString; + if(missing) { - plString = ""; - } else if(profitLoss >= 0) { - plString = EnumChatFormatting.BLUE+"Profit/loss: " + EnumChatFormatting.DARK_GREEN - + EnumChatFormatting.BOLD + "+" + format.format(profitLoss) + " coins"; + drawStringShadow(EnumChatFormatting.BLUE+"Couldn't find item on AH. Item is very rare!", + guiLeft+xSize+4+90, guiTop+14, 170); } else { - plString = EnumChatFormatting.BLUE+"Profit/loss: " + EnumChatFormatting.RED - + EnumChatFormatting.BOLD + "-" + format.format(-profitLoss) + " coins"; - } + NumberFormat format = NumberFormat.getInstance(Locale.US); + String valueStringBIN = EnumChatFormatting.YELLOW+"Value (BIN): " + EnumChatFormatting.GOLD + + EnumChatFormatting.BOLD + format.format(totalValueBIN) + " coins"; + String valueStringAUC = EnumChatFormatting.YELLOW+"Value (AUC): " + EnumChatFormatting.GOLD + + EnumChatFormatting.BOLD + format.format(totalValueAUC) + " coins"; + + + int profitLossBIN = totalValueBIN - chestCost; + String plStringBIN; + if(profitLossBIN >= 0) { + plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN + + EnumChatFormatting.BOLD + "+" + format.format(profitLossBIN) + " coins"; + } else { + plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED + + EnumChatFormatting.BOLD + "-" + format.format(-profitLossBIN) + " coins"; + } + + int profitLossAUC = totalValueAUC - chestCost; + String plStringAUC; + if(profitLossAUC >= 0) { + plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN + + EnumChatFormatting.BOLD + "+" + format.format(profitLossAUC) + " coins"; + } else { + plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED + + EnumChatFormatting.BOLD + "-" + format.format(-profitLossAUC) + " coins"; + } - Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth); - GL11.glColor4f(1, 1, 1, 1); - GlStateManager.disableLighting(); - Utils.drawTexturedRect(guiLeft+xSize+4, guiTop, 180, 45, 0, 180/256f, 0, 45/256f, GL11.GL_NEAREST); + drawStringShadow(valueStringBIN, guiLeft+xSize+4+90, + guiTop+14, 170); + drawStringShadow(plStringBIN, guiLeft+xSize+4+90, + guiTop+26, 170); - Utils.drawStringCenteredScaledMaxWidth(valueString, Minecraft.getMinecraft().fontRendererObj, guiLeft+xSize+4+90, - guiTop+14, true, 170, Color.BLACK.getRGB()); - Utils.drawStringCenteredScaledMaxWidth(plString, Minecraft.getMinecraft().fontRendererObj, guiLeft+xSize+4+90, - guiTop+28, true, 170, Color.BLACK.getRGB()); + drawStringShadow(valueStringAUC, guiLeft+xSize+4+90, + guiTop+44, 170); + drawStringShadow(plStringAUC, guiLeft+xSize+4+90, + guiTop+56, 170); + } } } catch(Exception e) { e.printStackTrace(); @@ -653,6 +686,24 @@ public class NEUEventListener { } } + public void drawStringShadow(String str, float x, float y, int len) { + for(int xOff=-2; xOff<=2; xOff++) { + for(int yOff=-2; yOff<=2; yOff++) { + if(Math.abs(xOff) != Math.abs(yOff)) { + Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str), + Minecraft.getMinecraft().fontRendererObj, + x+xOff/2f, y+yOff/2f, false, len, + new Color(20, 20, 20, 100/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB()); + } + } + } + + Utils.drawStringCenteredScaledMaxWidth(str, + Minecraft.getMinecraft().fontRendererObj, + x, y, false, len, + new Color(64, 64, 64, 255).getRGB()); + } + /** * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused. * Will also cancel the event if if NEUOverlay#mouseInput returns true. @@ -669,9 +720,13 @@ public class NEUEventListener { neu.overlay.mouseInput(); return; } - if(shouldRenderOverlay(event.gui) && !(hoverInv && focusInv) && neu.isOnSkyblock()) { - if(neu.overlay.mouseInput()) { - event.setCanceled(true); + if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { + if(!(hoverInv && focusInv)) { + if(neu.overlay.mouseInput()) { + event.setCanceled(true); + } + } else { + neu.overlay.mouseInputInv(); } } } @@ -815,7 +870,7 @@ public class NEUEventListener { @SubscribeEvent(priority = EventPriority.LOW) public void onItemTooltipLow(ItemTooltipEvent event) { - //NotEnoughUpdates.INSTANCE.neu.manager.config.enchantColours.value + boolean dungeonProfit = false; int index = 0; List<String> newTooltip = new ArrayList<>(); for(String line : event.toolTip) { @@ -904,7 +959,150 @@ public class NEUEventListener { } } } + newTooltip.add(line); + + if(neu.manager.config.auctionPriceInfo.value) { + if(line.contains(EnumChatFormatting.GRAY+"Buy it now: ") || + line.contains(EnumChatFormatting.GRAY+"Bidder: ") || + line.contains(EnumChatFormatting.GRAY+"Starting bid: ")) { + String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); + if(internalname != null) { + newTooltip.add(""); + if(!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + newTooltip.add(EnumChatFormatting.GRAY+"[SHIFT for Price Info]"); + } else { + JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname); + + boolean hasAuctionPrice = auctionInfo != null; + + int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname); + + NumberFormat format = NumberFormat.getInstance(Locale.US); + APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalname); + + if(lowestBin > 0) { + newTooltip.add(EnumChatFormatting.GRAY+"Lowest BIN: "+ + EnumChatFormatting.GOLD+format.format(lowestBin)+" coins"); + } + if(hasAuctionPrice) { + int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + newTooltip.add(EnumChatFormatting.GRAY+"AH Price: "+ + EnumChatFormatting.GOLD+format.format(auctionPrice)+" coins"); + newTooltip.add(EnumChatFormatting.GRAY+"AH Sales: "+ + EnumChatFormatting.GOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day"); + if(auctionInfo.has("clean_price")) { + newTooltip.add(EnumChatFormatting.GRAY+"AH Price (Clean): "+ + EnumChatFormatting.GOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins"); + newTooltip.add(EnumChatFormatting.GRAY+"AH Sales (Clean): "+ + EnumChatFormatting.GOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day"); + } + + } + if(craftCost.fromRecipe) { + newTooltip.add(EnumChatFormatting.GRAY+"Raw Craft Cost: "+ + EnumChatFormatting.GOLD+format.format((int)craftCost.craftCost)+" coins"); + } + } + } + } + } + + if(neu.manager.config.dungeonProfitLore.value && Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + if(line.contains(EnumChatFormatting.GREEN+"Open Reward Chest")) { + dungeonProfit = true; + } else if(index == 7 && dungeonProfit) { + GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + int chestCost = 0; + String line6 = Utils.cleanColour(line); + StringBuilder cost = new StringBuilder(); + for(int i=0; i<line6.length(); i++) { + char c = line6.charAt(i); + if("0123456789".indexOf(c) >= 0) { + cost.append(c); + } + } + if(cost.length() > 0) { + chestCost = Integer.parseInt(cost.toString()); + } + + boolean missing = false; + int totalValueBIN = 0; + int totalValueAUC = 0; + for(int i=0; i<5; i++) { + ItemStack item = lower.getStackInSlot(11+i); + String internal = neu.manager.getInternalNameForItem(item); + if(internal != null) { + float worthBIN = neu.manager.auctionManager.getLowestBin(internal); + float worthAUC = neu.manager.auctionManager.getLowestBin(internal); + + if(worthAUC == -1) worthAUC = neu.manager.auctionManager.getCraftCost(internal).craftCost; + + if(worthAUC <= 0 && worthBIN <= 0) { + missing = true; + break; + } + + if(worthBIN > 0 && totalValueBIN >= 0) { + totalValueBIN += worthBIN; + } else { + totalValueBIN = -1; + } + + if(worthAUC > 0 && totalValueAUC >= 0) { + totalValueAUC += worthAUC; + } else { + totalValueAUC = -1; + } + } + } + if(totalValueAUC <= 0 && totalValueBIN <= 0) { + missing = true; + } + + String neu = EnumChatFormatting.YELLOW + "[NEU] "; + if(missing) { + newTooltip.add(neu + EnumChatFormatting.BLUE+"Couldn't find item on AH. Item is very rare!"); + } else { + NumberFormat format = NumberFormat.getInstance(Locale.US); + String valueStringBIN = EnumChatFormatting.YELLOW+"Value (BIN): " + EnumChatFormatting.GOLD + + EnumChatFormatting.BOLD + format.format(totalValueBIN) + " coins"; + String valueStringAUC = EnumChatFormatting.YELLOW+"Value (AUC): " + EnumChatFormatting.GOLD + + EnumChatFormatting.BOLD + format.format(totalValueAUC) + " coins"; + + + int profitLossBIN = totalValueBIN - chestCost; + String plStringBIN; + if(profitLossBIN >= 0) { + plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN + + EnumChatFormatting.BOLD + "+" + format.format(profitLossBIN) + " coins"; + } else { + plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED + + EnumChatFormatting.BOLD + "-" + format.format(-profitLossBIN) + " coins"; + } + + int profitLossAUC = totalValueAUC - chestCost; + String plStringAUC; + if(profitLossAUC >= 0) { + plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN + + EnumChatFormatting.BOLD + "+" + format.format(profitLossAUC) + " coins"; + } else { + plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED + + EnumChatFormatting.BOLD + "-" + format.format(-profitLossAUC) + " coins"; + } + + newTooltip.add(neu + valueStringBIN); + newTooltip.add(neu + plStringBIN); + newTooltip.add(neu + valueStringAUC); + newTooltip.add(neu + plStringAUC); + } + } + } + + index++; } event.toolTip.clear(); event.toolTip.addAll(newTooltip); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java deleted file mode 100644 index ac828606..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java +++ /dev/null @@ -1,123 +0,0 @@ -package io.github.moulberry.notenoughupdates; - -import org.kohsuke.github.*; - -import java.io.IOException; -import java.util.*; - -public class NEUIO { - - private final String accessToken; - - /** - * THIS CLASS PROVIDES METHODS FOR INTERFACING WITH THE GIT REPOSITORY NotEnoughUpdates-REPO. THIS REPOSITORY - * CONTAINS ALL THE JSON ITEMS. THIS SHOULD NOT BE A PERMANENT SOLUTION AND I SHOULD LOOK AT USING SOME FORM OF - * HOSTING SERVICE OTHER THAN A GIT REPOSITORY IF THE USERBASE OF THE MOD GROWS SIGNIFICANTLY. UNFORTUNATELY I - * CANT AFFORD HOSTING RIGHT NOW SO THIS IS WHAT YOU GET AND GITHUB WILL PROBABLY THROW A FIT IF A LARGE NUMBER - * OF USERS START DOWNLOADING FROM THE REPO ALL AT ONCE. - */ - - public NEUIO(String accessToken) { - this.accessToken = accessToken; - } - - /** - * Creates a new branch, commits to it with a single file change and submits a pull request from the new branch - * back to the master branch. - */ - public boolean createNewRequest(String newBranchName, String prTitle, String prBody, String filename, String content) { - try { - GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build(); - System.out.println("Getting repo"); - - //https://github.com/Moulberry/NotEnoughUpdates-REPO - GHRepository repo = github.getRepositoryById("247692460"); - - System.out.println("Getting last commit"); - String lastCommitSha = repo.getRef("heads/master").getObject().getSha(); - System.out.println("Last master commit sha: " + lastCommitSha); - - String lastTreeSha = repo.getCommit(lastCommitSha).getTree().getSha(); - - GHTreeBuilder tb = repo.createTree(); - tb.baseTree(lastTreeSha); - tb.add(filename, content, false); - GHTree tree = tb.create(); - System.out.println("Created new tree: " + tree.getSha()); - - GHCommitBuilder cb = repo.createCommit(); - cb.message(prTitle); - cb.tree(tree.getSha()); - cb.parent(lastCommitSha); - GHCommit commit = cb.create(); - System.out.println("Created commit: " + commit.getSHA1()); - - repo.createRef("refs/heads/"+newBranchName, commit.getSHA1()); - System.out.println("Set new branch head to commit."); - - repo.createPullRequest(prTitle, newBranchName, "master", prBody); - return true; - } catch(IOException e) { - e.printStackTrace(); - return false; - } - } - - public String getLatestCommit() { - try { - GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build(); - GHRepository repo = github.getRepositoryById("247692460"); - - for(GHCommit commit : repo.listCommits()) { - return commit.getSHA1(); - } - } catch(IOException e) { - return null; - } - return ""; - } - - /** - * @param oldShas Map from filename (eg. BOW.json) to the sha in the local repository - * @return Map from filename to the new shas - */ - public Map<String, String> getChangedItems(Map<String, String> oldShas) { - HashMap<String, String> changedFiles = new HashMap<>(); - try { - GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build(); - GHRepository repo = github.getRepositoryById("247692460"); - - for(GHTreeEntry treeEntry : repo.getTreeRecursive("master", 1).getTree()) { - if(treeEntry.getPath().contains(".")) { - String oldSha = oldShas.get(treeEntry.getPath()); - if(!treeEntry.getSha().equals(oldSha)) { - changedFiles.put(treeEntry.getPath(), treeEntry.getSha()); - } - } - } - } catch(IOException e) { - return null; - } - return changedFiles; - } - - public Set<String> getRemovedItems(Set<String> currentlyInstalled) { - Set<String> removedItems = new HashSet<>(); - Set<String> repoItems = new HashSet<>(); - try { - GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build(); - GHRepository repo = github.getRepositoryById("247692460"); - - for(GHTreeEntry treeEntry : repo.getTreeRecursive("master", 1).getTree()) { - String[] split = treeEntry.getPath().split("/"); - repoItems.add(split[split.length-1].split("\\.")[0]); - } - } catch(IOException e) { - e.printStackTrace(); - return removedItems; - } - removedItems.addAll(currentlyInstalled); - removedItems.removeAll(repoItems); - return removedItems; - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 2ae298e2..a7303ca4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -36,7 +36,6 @@ import java.util.zip.ZipInputStream; public class NEUManager { private final NotEnoughUpdates neu; - public final NEUIO neuio; public final Gson gson; public final APIManager auctionManager; @@ -51,7 +50,9 @@ public class NEUManager { public final KeyBinding keybindViewRecipe = new KeyBinding("Show recipe for item", Keyboard.KEY_R, "NotEnoughUpdates"); public final KeyBinding keybindToggleDisplay = new KeyBinding("Toggle NEU overlay", 0, "NotEnoughUpdates"); public final KeyBinding keybindClosePanes = new KeyBinding("Close NEU panes", 0, "NotEnoughUpdates"); - public final KeyBinding[] keybinds = new KeyBinding[]{keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, keybindToggleDisplay, keybindClosePanes}; + public final KeyBinding keybindItemSelect = new KeyBinding("Select Item", -98 /*middle*/, "NotEnoughUpdates"); + public final KeyBinding[] keybinds = new KeyBinding[]{ keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, + keybindToggleDisplay, keybindClosePanes, keybindItemSelect}; public String viewItemAttemptID = null; public long viewItemAttemptTime = 0; @@ -63,24 +64,21 @@ public class NEUManager { private ResourceLocation wkZip = new ResourceLocation("notenoughupdates:wkhtmltox.zip"); private Map<String, ItemStack> itemstackCache = new HashMap<>(); - private static final String AUCTIONS_PRICE_URL = "https://moulberry.github.io/files/auc_avg_jsons/average_3day.json.gz"; - private JsonObject auctionPricesJson = null; - private long auctionLastUpdate = 0; + //private static final String AUCTIONS_PRICE_URL = "https://moulberry.github.io/files/auc_avg_jsons/average_3day.json.gz"; + private static final String GIT_COMMITS_URL = "https://api.github.com/repos/Moulberry/NotEnoughUpdates-REPO/commits/master"; - private HashMap<String, CraftInfo> craftCost = new HashMap<>(); private HashMap<String, Set<String>> usagesMap = new HashMap<>(); public File configLocation; public File repoLocation; - private File itemShaLocation; - private JsonObject itemShaConfig; public File configFile; + public File itemRenameFile; + public JsonObject itemRenameJson; public Options config; - public NEUManager(NotEnoughUpdates neu, NEUIO neuio, File configLocation) { + public NEUManager(NotEnoughUpdates neu, File configLocation) { this.neu = neu; this.configLocation = configLocation; - this.neuio = neuio; this.auctionManager = new APIManager(this); GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting(); @@ -93,12 +91,11 @@ public class NEUManager { this.repoLocation = new File(configLocation, "repo"); repoLocation.mkdir(); - this.itemShaLocation = new File(configLocation, "itemSha.json"); - try { - itemShaLocation.createNewFile(); - itemShaConfig = getJsonFromFile(itemShaLocation); - if(itemShaConfig == null) itemShaConfig = new JsonObject(); - } catch(IOException e) { } + this.itemRenameFile = new File(configLocation, "itemRename.json"); + try { itemRenameJson = getJsonFromFile(itemRenameFile); } catch(IOException ignored) {} + if(itemRenameJson == null) { + itemRenameJson = new JsonObject(); + } File wkShell = new File(configLocation, "wkhtmltox/bin/wkhtmltoimage"); if(!wkShell.exists()) { @@ -110,12 +107,6 @@ public class NEUManager { } } - public class CraftInfo { - public boolean fromRecipe = false; - public boolean vanillaItem = false; - public float craftCost = -1; - } - public void setCurrentProfile(String currentProfile) { this.currentProfile = currentProfile; } @@ -132,85 +123,8 @@ public class NEUManager { } } - 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. - */ - public CraftInfo getCraftCost(String internalname) { - if(craftCost.containsKey(internalname)) { - return craftCost.get(internalname); - } else { - CraftInfo ci = new CraftInfo(); - - ci.vanillaItem = isVanillaItem(internalname); - - JsonObject auctionInfo = getItemAuctionInfo(internalname); - JsonObject bazaarInfo = getBazaarInfo(internalname); - - if(bazaarInfo != null) { - float bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat(); - ci.craftCost = bazaarInstantBuyPrice; - } - if(auctionInfo != null && !ci.vanillaItem) { //Don't use auction prices for vanilla items cuz people like to transfer money, messing up the cost of vanilla items. - float auctionPrice = auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat(); - if(ci.craftCost < 0 || auctionPrice < ci.craftCost) { - ci.craftCost = auctionPrice; - } - } - JsonObject item = getItemInformation().get(internalname); - if(item != null && item.has("recipe")) { - float craftPrice = 0; - JsonObject recipe = item.get("recipe").getAsJsonObject(); - - String[] x = {"1","2","3"}; - String[] y = {"A","B","C"}; - for(int i=0; i<9; i++) { - String name = y[i/3]+x[i%3]; - String itemS = recipe.get(name).getAsString(); - if(itemS.length() == 0) continue; - - int count = 1; - if(itemS != null && itemS.split(":").length == 2) { - count = Integer.valueOf(itemS.split(":")[1]); - itemS = itemS.split(":")[0]; - } - float compCost = getCraftCost(itemS).craftCost * count; - if(compCost < 0) { - if(!getCraftCost(itemS).vanillaItem) { //If it's a vanilla item without a cost attached to it, let compCost = 0. - craftCost.put(internalname, ci); - return ci; - } - } else { - craftPrice += compCost; - } - } - - if(ci.craftCost < 0 || craftPrice < ci.craftCost) { - ci.craftCost = craftPrice; - ci.fromRecipe = true; - } - } - craftCost.put(internalname, ci); - return ci; - } + public void saveItemRenameConfig() { + try { writeJson(itemRenameJson, itemRenameFile); } catch(IOException ignored) {} } public void saveConfig() throws IOException { @@ -228,130 +142,6 @@ public class NEUManager { } /** - * Downloads and sets auctionPricesJson from the URL specified by AUCTIONS_PRICE_URL. - */ - private ExecutorService es = Executors.newCachedThreadPool(); - public void updatePrices() { - if(System.currentTimeMillis() - auctionLastUpdate > 1000*60*120) { //2 hours - craftCost.clear(); - System.out.println("[NEU] UPDATING PRICE INFORMATION"); - auctionLastUpdate = System.currentTimeMillis(); - es.submit(() -> { - try(Reader inReader = new InputStreamReader(new GZIPInputStream(new URL(AUCTIONS_PRICE_URL).openStream()))) { - auctionPricesJson = gson.fromJson(inReader, JsonObject.class); - } catch (IOException e) { - e.printStackTrace(); - } - }); - } - } - - public boolean hasAuctionInfo(String internalname) { - if(auctionPricesJson == null) return false; - return auctionPricesJson.has("item_data") && auctionPricesJson.get("item_data").getAsJsonObject().has(internalname); - } - - public boolean hasBazaarInfo(String internalname) { - if(auctionPricesJson == null) return false; - return auctionPricesJson.has("bazaar") && auctionPricesJson.get("bazaar").getAsJsonObject().has(internalname); - } - - public JsonObject getItemAuctionInfo(String internalname) { - if(!hasAuctionInfo(internalname)) return null; - JsonElement e = auctionPricesJson.get("item_data").getAsJsonObject().get(internalname); - if(e == null) { - return null; - } - return e.getAsJsonObject(); - } - - public JsonObject getBazaarInfo(String internalname) { - if(!hasBazaarInfo(internalname)) return null; - JsonElement e = auctionPricesJson.get("bazaar").getAsJsonObject().get(internalname); - if(e == null) { - return null; - } - return e.getAsJsonObject(); - } - - /** - * Calculates the cost of enchants + other price modifiers such as pet xp, midas price, etc. - */ - public float getCostOfEnchants(String internalname, NBTTagCompound tag) { - float costOfEnchants = 0; - if(true) return 0; - - JsonObject info = getItemAuctionInfo(internalname); - if(info == null || !info.has("price")) { - return 0; - } - if(auctionPricesJson == null || !auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) { - return 0; - } - JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices"); - JsonObject ench_maximums = auctionPricesJson.getAsJsonObject("ench_maximums"); - if(!ench_prices.has(internalname) || !ench_maximums.has(internalname)) { - return 0; - } - JsonObject iid_variables = ench_prices.getAsJsonObject(internalname); - float ench_maximum = ench_maximums.get(internalname).getAsFloat(); - - int enchants = 0; - float price = getItemAuctionInfo(internalname).get("price").getAsFloat(); - if(tag.hasKey("ExtraAttributes")) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - if(ea.hasKey("enchantments")) { - - NBTTagCompound enchs = ea.getCompoundTag("enchantments"); - for(String ench : enchs.getKeySet()) { - enchants++; - int level = enchs.getInteger(ench); - - for(Map.Entry<String, JsonElement> entry : iid_variables.entrySet()) { - if(matchEnch(ench, level, entry.getKey())) { - costOfEnchants += entry.getValue().getAsJsonObject().get("A").getAsFloat()*price + - entry.getValue().getAsJsonObject().get("B").getAsFloat(); - break; - } - } - } - } - } - return costOfEnchants; - } - - /** - * Checks whether a certain enchant (ench name + lvl) matches an enchant id - * eg. PROTECTION_GE6 will match -> ench_name = PROTECTION, lvl >= 6 - */ - private boolean matchEnch(String ench, int level, String id) { - if(!id.contains(":")) { - return false; - } - - String idEnch = id.split(":")[0]; - String idLevel = id.split(":")[1]; - - if(!ench.equalsIgnoreCase(idEnch)) { - return false; - } - - if(String.valueOf(level).equalsIgnoreCase(idLevel)) { - return true; - } - - if(idLevel.startsWith("LE")) { - int idLevelI = Integer.valueOf(idLevel.substring(2)); - return level <= idLevelI; - } else if(idLevel.startsWith("GE")) { - int idLevelI = Integer.valueOf(idLevel.substring(2)); - return level >= idLevelI; - } - - return false; - } - - /** * Parses a file in to a JsonObject. */ public JsonObject getJsonFromFile(File file) throws IOException { @@ -366,7 +156,6 @@ public class NEUManager { public void resetRepo() { try { Utils.recursiveDelete(new File(configLocation, "repo")); } catch(Exception e) {} try { new File(configLocation, "currentCommit.json").delete(); } catch(Exception e) {} - try { itemShaLocation.delete(); } catch(Exception e) {} } /** @@ -421,10 +210,15 @@ public class NEUManager { JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json")); - String latestCommit = neuio.getLatestCommit(); + String latestCommit = null; + try(Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) { + JsonObject commits = gson.fromJson(inReader, JsonObject.class); + latestCommit = commits.get("sha").getAsString(); + } catch (Exception e) { + e.printStackTrace(); + } if(latestCommit == null || latestCommit.isEmpty()) return; - Map<String, String> changedFiles = null; if(new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) { if(currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestCommit)) { @@ -432,19 +226,19 @@ public class NEUManager { return; } - HashMap<String, String> oldShas = new HashMap<>(); + /*HashMap<String, String> oldShas = new HashMap<>(); for (Map.Entry<String, JsonElement> entry : itemShaConfig.entrySet()) { if (new File(repoLocation, entry.getKey() + ".json").exists()) { oldShas.put(entry.getKey() + ".json", entry.getValue().getAsString()); } } - changedFiles = neuio.getChangedItems(oldShas); + changedFiles = neuio.getChangedItems(oldShas);*/ } if (Display.isActive()) dialog.toFront(); - if (changedFiles != null && changedFiles.size() <= 20) { - String startMessage = "NotEnoughUpdates: Syncing with remote repository ("; + if (false) {//changedFiles != null && changedFiles.size() <= 20) { + /*String startMessage = "NotEnoughUpdates: Syncing with remote repository ("; int downloaded = 0; String dlUrl = "https://raw.githubusercontent.com/Moulberry/NotEnoughUpdates-REPO/master/"; @@ -482,7 +276,7 @@ public class NEUManager { writeJson(itemShaConfig, itemShaLocation); } catch (IOException e) { e.printStackTrace(); - } + }*/ } else { Utils.recursiveDelete(repoLocation); repoLocation.mkdirs(); @@ -524,7 +318,7 @@ public class NEUManager { unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath()); - if (changedFiles != null) { + /*if (changedFiles != null) { for (Map.Entry<String, String> changedFile : changedFiles.entrySet()) { itemShaConfig.addProperty(changedFile.getKey().substring(0, changedFile.getKey().length() - 5), changedFile.getValue()); @@ -533,7 +327,7 @@ public class NEUManager { writeJson(itemShaConfig, itemShaLocation); } catch (IOException e) { } - } + }*/ } if(currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestCommit)) { @@ -921,6 +715,18 @@ public class NEUManager { } } + public String getUUIDFromNBT(NBTTagCompound tag) { + String uuid = null; + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + + if (ea.hasKey("uuid", 8)) { + uuid = ea.getString("uuid"); + } + } + return uuid; + } + public String getInternalnameFromNBT(NBTTagCompound tag) { String internalname = null; if(tag != null && tag.hasKey("ExtraAttributes", 10)) { @@ -1125,6 +931,12 @@ public class NEUManager { return getInternalnameFromNBT(tag); } + public String getUUIDForItem(ItemStack stack) { + if(stack == null) return null; + NBTTagCompound tag = stack.getTagCompound(); + return getUUIDFromNBT(tag); + } + public void writeItemToFile(ItemStack stack) { String internalname = getInternalNameForItem(stack); @@ -1429,9 +1241,9 @@ public class NEUManager { String prTitle = internalname + "-" + username; String prBody = "Internal name: " + internalname + "\nSubmitted by: " + username; String file = "items/"+internalname+".json"; - if(!neuio.createNewRequest(newBranchName, prTitle, prBody, file, gson.toJson(json))) { + /*if(!neuio.createNewRequest(newBranchName, prTitle, prBody, file, gson.toJson(json))) { return false; - } + }*/ try { writeJsonDefaultDir(json, internalname+".json"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 0cb7a548..a13177ca 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -3,6 +3,7 @@ package io.github.moulberry.notenoughupdates; import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.auction.APIManager; import io.github.moulberry.notenoughupdates.infopanes.*; import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor; import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint; @@ -570,6 +571,22 @@ public class NEUOverlay extends Gui { } } + public void mouseInputInv() { + if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) { + if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100) { + Slot slot = Utils.getSlotUnderMouse((GuiContainer)Minecraft.getMinecraft().currentScreen); + if(slot != null) { + ItemStack hover = slot.getStack(); + if(hover != null) { + textField.setText("id:"+manager.getInternalNameForItem(hover)); + itemPaneOpen = true; + updateSearch(); + } + } + } + } + } + /** * Handles the mouse input, cancelling the forge event if a NEU gui element is clicked. */ @@ -619,7 +636,7 @@ public class NEUOverlay extends Gui { manager.showRecipe(item); } else if(Mouse.getEventButton() == 1) { showInfo(item); - } else if(Mouse.getEventButton() == 2) { + } else if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100) { textField.setText("id:"+item.get("internalname").getAsString()); updateSearch(); searchMode = true; @@ -695,21 +712,6 @@ public class NEUOverlay extends Gui { return true; } - if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) { - if(Mouse.getEventButton() == 2) { - Slot slot = Utils.getSlotUnderMouse((GuiContainer)Minecraft.getMinecraft().currentScreen); - if(slot != null) { - ItemStack hover = slot.getStack(); - if(hover != null) { - textField.setText("id:"+manager.getInternalNameForItem(hover)); - updateSearch(); - searchMode = true; - return true; - } - } - } - } - //Clicking on "close info pane" button if(mouseX > width*getInfoPaneOffsetFactor()-getBoxPadding()-8 && mouseX < width*getInfoPaneOffsetFactor()-getBoxPadding()+8) { if(mouseY > getBoxPadding()-8 && mouseY < getBoxPadding()+8) { @@ -988,8 +990,8 @@ public class NEUOverlay extends Gui { float cost1 = manager.auctionManager.getLowestBin(o1.get("internalname").getAsString()); float cost2 = manager.auctionManager.getLowestBin(o2.get("internalname").getAsString()); - if(cost1 == -1) cost1 = manager.getCraftCost(o1.get("internalname").getAsString()).craftCost; - if(cost2 == -1) cost2 = manager.getCraftCost(o2.get("internalname").getAsString()).craftCost; + if(cost1 == -1) cost1 = manager.auctionManager.getCraftCost(o1.get("internalname").getAsString()).craftCost; + if(cost2 == -1) cost2 = manager.auctionManager.getCraftCost(o2.get("internalname").getAsString()).craftCost; if(cost1 < cost2) return mult; if(cost1 > cost2) return -mult; @@ -1589,8 +1591,6 @@ public class NEUOverlay extends Gui { yaw++; yaw %= 360; - manager.updatePrices(); - int opacity = Math.min(255, Math.max(0, manager.config.bgOpacity.value.intValue())); bg = new Color((bg.getRGB() & 0x00ffffff) | opacity << 24, true); @@ -1645,11 +1645,11 @@ public class NEUOverlay extends Gui { if(!manager.config.disableItemTabOpen.value) { Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow); GlStateManager.color(1f, 1f, 1f, 0.3f); - Utils.drawTexturedRect(width-itemPaneTabOffset.getValue(), height/2 - 50, 20, 100); + Utils.drawTexturedRect(width-itemPaneTabOffset.getValue()*64/20f, height/2f - 32, 64, 64); GlStateManager.bindTexture(0); - if(!itemPaneOpen && mouseX > width-itemPaneTabOffset.getValue() && mouseY > height/2 - 50 - && mouseY < height/2 + 50) { + if(!itemPaneOpen && mouseX > width-itemPaneTabOffset.getValue() && mouseY > height/2 - 32 + && mouseY < height/2 + 32) { itemPaneOpen = true; } } @@ -1810,8 +1810,8 @@ public class NEUOverlay extends Gui { List<String> text = manager.jsonToStack(json).getTooltip(Minecraft.getMinecraft().thePlayer, false); String internalname = json.get("internalname").getAsString(); - JsonObject auctionInfo = manager.getItemAuctionInfo(internalname); - JsonObject bazaarInfo = manager.getBazaarInfo(internalname); + JsonObject auctionInfo = manager.auctionManager.getItemAuctionInfo(internalname); + JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalname); boolean hasAuctionPrice = auctionInfo != null; boolean hasBazaarPrice = bazaarInfo != null; @@ -1820,7 +1820,7 @@ public class NEUOverlay extends Gui { NumberFormat format = NumberFormat.getInstance(Locale.US); - NEUManager.CraftInfo craftCost = manager.getCraftCost(json.get("internalname").getAsString()); + APIManager.CraftInfo craftCost = manager.auctionManager.getCraftCost(json.get("internalname").getAsString()); if(hasAuctionPrice || hasBazaarPrice || craftCost.fromRecipe || lowestBin > 0) text.add(""); if(lowestBin > 0) { @@ -1847,6 +1847,19 @@ public class NEUOverlay extends Gui { int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price: "+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionPrice)+" coins"); + if(manager.config.advancedPriceInfo.value) { + text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day"); + } + if(auctionInfo.has("clean_price")) { + text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price (Clean): "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins"); + if(manager.config.advancedPriceInfo.value) { + text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales (Clean): "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day"); + } + } + } if(craftCost.fromRecipe) { text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Raw Craft Cost: "+ diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 69d4a038..5a02e109 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -28,12 +28,10 @@ import net.minecraft.client.settings.KeyBinding; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.event.ClickEvent; +import net.minecraft.event.HoverEvent; import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.util.BlockPos; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.Session; +import net.minecraft.util.*; import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.client.registry.ClientRegistry; @@ -42,16 +40,21 @@ import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.text.WordUtils; +import org.apache.commons.lang3.text.translate.UnicodeUnescaper; import javax.swing.*; -import java.io.File; -import java.io.IOException; +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.io.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.Proxy; +import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -61,13 +64,12 @@ import java.util.concurrent.atomic.AtomicLong; @Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true) public class NotEnoughUpdates { public static final String MODID = "notenoughupdates"; - public static final String VERSION = "1.1-REL"; + public static final String VERSION = "1.2-REL"; public static NotEnoughUpdates INSTANCE = null; public NEUManager manager; public NEUOverlay overlay; - private NEUIO neuio; private static final long CHAT_MSG_COOLDOWN = 200; private long lastChatMessage = 0; @@ -77,34 +79,107 @@ public class NotEnoughUpdates { //Stolen from Biscut and used for detecting whether in skyblock private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK","\u7A7A\u5C9B\u751F\u5B58"); - //Github Access Token, may change. Value hard-coded. - //Token is obfuscated so that github doesn't delete it whenever I upload the jar. - String[] token = new String[]{"b292496d2c","9146a","9f55d0868a545305a8","96344bf"}; - private String getAccessToken() { - String s = ""; - for(String str : token) { - s += str; - } - return s; - } - private GuiScreen openGui = null; SimpleCommand collectionLogCommand = new SimpleCommand("neucl", new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { if(!OpenGlHelper.isFramebufferEnabled()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "This feature requires FBOs to work. Try disabling Optifine's 'Fast Render'.")); } else { if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { openGui = new GuiInventory(Minecraft.getMinecraft().thePlayer); } - manager.updatePrices(); overlay.displayInformationPane(new CollectionLogInfoPane(overlay, manager)); } } }); + SimpleCommand itemRenameCommand = new SimpleCommand("neurename", new SimpleCommand.ProcessCommandRunnable() { + public void processCommand(ICommandSender sender, String[] args) { + if(args.length == 0) { + args = new String[]{"help"}; + } + String heldUUID = manager.getUUIDForItem(Minecraft.getMinecraft().thePlayer.getHeldItem()); + switch(args[0].toLowerCase()) { + case "clearall": + manager.itemRenameJson = new JsonObject(); + manager.saveItemRenameConfig(); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for all items")); + break; + case "clear": + if(heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID")); + return; + } + manager.itemRenameJson.remove(heldUUID); + manager.saveItemRenameConfig(); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for held item")); + break; + case "copyuuid": + if(heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID")); + return; + } + StringSelection selection = new StringSelection(heldUUID); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] UUID copied to clipboard")); + break; + case "uuid": + if(heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't get UUID - no UUID")); + return; + } + ChatStyle style = new ChatStyle(); + style.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, + new ChatComponentText(EnumChatFormatting.GRAY+"Click to copy to clipboard"))); + style.setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "neurename copyuuid")); + + ChatComponentText text = new ChatComponentText(EnumChatFormatting.YELLOW+"[NEU] The UUID of your currently held item is: " + + EnumChatFormatting.GREEN + heldUUID); + text.setChatStyle(style); + sender.addChatMessage(text); + break; + case "set": + if(heldUUID == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't rename item - no UUID")); + return; + } + if(args.length == 1) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Usage: /neurename set [name...]")); + return; + } + StringBuilder sb = new StringBuilder(); + for(int i=1; i<args.length; i++) { + sb.append(args[i]); + if(i<args.length-1) sb.append(" "); + } + String name = sb.toString() + .replace("\\&", "{amp}") + .replace("&", "\u00a7") + .replace("{amp}", "&"); + name = new UnicodeUnescaper().translate(name); + manager.itemRenameJson.addProperty(heldUUID, name); + manager.saveItemRenameConfig(); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Set custom name for held item")); + break; + default: + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Unknown subcommand \""+args[0]+"\"")); + case "help": + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Available commands:")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "help: Print this message")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clearall: Clears all custom names " + + EnumChatFormatting.BOLD + "(Cannot be undone)")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clear: Clears held item name " + + EnumChatFormatting.BOLD + "(Cannot be undone)")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "uuid: Returns the UUID of the currently held item")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "set: Sets the custom name of the currently held item")); + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Usage: /neurename set [name...]")); + + } + } + }); + SimpleCommand questingCommand = new SimpleCommand("neuquest", new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { @@ -144,15 +219,22 @@ public class NotEnoughUpdates { ScheduledExecutorService peekCommandExecutorService = null; SimpleCommand peekCommand = new SimpleCommand("peek", new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { + if(args.length == 0) { + sender.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED+"[PEEK] Usage: /peek (username)")); + return; + } int id = new Random().nextInt(Integer.MAX_VALUE/2)+Integer.MAX_VALUE/2; Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( EnumChatFormatting.YELLOW+"[PEEK] Getting player information..."), id); profileViewer.getProfileByName(args[0], profile -> { - if (profile != null) { + if (profile == null) { + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( + EnumChatFormatting.RED+"[PEEK] Unknown player or api is down."), id); + } else { profile.resetCache(); - if(peekCommandExecutorService == null || peekCommandExecutorService.isShutdown()) { peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor(); } else { @@ -338,13 +420,33 @@ public class NotEnoughUpdates { SimpleCommand.ProcessCommandRunnable viewProfileRunnable = new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { + if(new File(Minecraft.getMinecraft().mcDataDir, "optionsof.txt").exists()) { + try(InputStream in = new FileInputStream(new File(Minecraft.getMinecraft().mcDataDir, "optionsof.txt"))) { + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + + String line; + while((line = reader.readLine()) != null) { + if(line.contains("ofFastRender:true")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "This feature is incompatible with OF Fast Render. Go to Video > Performance to disable it.")); + return; + } + } + } catch(Exception e) { + } + } if (manager.config.apiKey.value == null || manager.config.apiKey.value.trim().isEmpty()) { Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "Can't view profile, apikey is not set. Run /api new and put the result in settings.")); } else if (args.length == 0) { profileViewer.getProfileByName(Minecraft.getMinecraft().thePlayer.getName(), profile -> { - if (profile != null) profile.resetCache(); - openGui = new GuiProfileViewer(profile); + if(profile == null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "Invalid player name/api key. Maybe api is down? Try /api new.")); + } else { + profile.resetCache(); + openGui = new GuiProfileViewer(profile); + } }); } else if (args.length > 1) { Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + @@ -500,6 +602,7 @@ public class NotEnoughUpdates { ClientCommandHandler.instance.registerCommand(linksCommand); ClientCommandHandler.instance.registerCommand(gamemodesCommand); ClientCommandHandler.instance.registerCommand(resetRepoCommand); + ClientCommandHandler.instance.registerCommand(itemRenameCommand); ClientCommandHandler.instance.registerCommand(viewProfileCommand); ClientCommandHandler.instance.registerCommand(viewProfileShortCommand); ClientCommandHandler.instance.registerCommand(viewProfileShort2Command); @@ -509,8 +612,7 @@ public class NotEnoughUpdates { ClientCommandHandler.instance.registerCommand(enchantColourCommand); ClientCommandHandler.instance.registerCommand(neuAhCommand); - neuio = new NEUIO(getAccessToken()); - manager = new NEUManager(this, neuio, f); + manager = new NEUManager(this, f); manager.loadItemInformation(); overlay = new NEUOverlay(manager); profileViewer = new ProfileViewer(manager); @@ -630,7 +732,9 @@ public class NotEnoughUpdates { long currentTime = System.currentTimeMillis(); if (openGui != null) { - Minecraft.getMinecraft().thePlayer.closeScreen(); + if(Minecraft.getMinecraft().thePlayer.openContainer != null) { + Minecraft.getMinecraft().thePlayer.closeScreen(); + } Minecraft.getMinecraft().displayGuiScreen(openGui); openGui = null; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index 457c06d0..14ebdf26 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -8,6 +8,7 @@ import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.event.ClickEvent; import net.minecraft.event.HoverEvent; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; @@ -16,6 +17,7 @@ import net.minecraft.nbt.NBTTagString; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatStyle; import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -39,12 +41,18 @@ public class APIManager { private LinkedList<Integer> pagesToDownload = null; + private JsonObject bazaarJson = null; + private JsonObject auctionPricesJson = null; + private HashMap<String, CraftInfo> craftCost = new HashMap<>(); + public TreeMap<String, HashMap<Integer, HashSet<String>>> extrasToAucIdMap = new TreeMap<>(); private long lastAuctionUpdate = 0; private long lastShortAuctionUpdate = 0; private long lastCustomAHSearch = 0; private long lastCleanup = 0; + private long lastAuctionAvgUpdate = 0; + private long lastBazaarUpdate = 0; private long lastApiUpdate = 0; private long firstHypixelApiUpdate = 0; @@ -172,10 +180,14 @@ public class APIManager { updatePageTickShort(); ahNotification(); } - /*if(currentTime - lastProfileUpdate > 10*1000) { - lastProfileUpdate = System.currentTimeMillis(); - updateProfiles(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")); - }*/ + if(currentTime - lastAuctionAvgUpdate > 120*60*1000) { //2 hours + lastAuctionAvgUpdate = currentTime - 118*60*1000; //Try again in 2 minutes if updateAvgPrices doesn't succeed + updateAvgPrices(); + } + if(currentTime - lastBazaarUpdate > 10*60*1000) { + lastBazaarUpdate = currentTime; + updateBazaar(); + } if(currentTime - lastCleanup > 120*1000) { lastCleanup = currentTime; cleanup(); @@ -538,7 +550,7 @@ public class APIManager { } private void getPageFromAPI(int page) { - System.out.println("downloading page:"+page); + //System.out.println("downloading page:"+page); //System.out.println("Trying to update page: " + page); HashMap<String, String> args = new HashMap<>(); args.put("page", ""+page); @@ -576,6 +588,241 @@ public class APIManager { ); } + public void updateBazaar() { + manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/bazaar", new HashMap<>(), (jsonObject) -> { + if(!jsonObject.get("success").getAsBoolean()) return; + + craftCost.clear(); + bazaarJson = new JsonObject(); + JsonObject products = jsonObject.get("products").getAsJsonObject(); + for(Map.Entry<String, JsonElement> entry : products.entrySet()) { + if(entry.getValue().isJsonObject()) { + JsonObject productInfo = new JsonObject(); + + JsonObject product = entry.getValue().getAsJsonObject(); + JsonObject quickStatus = product.get("quick_status").getAsJsonObject(); + productInfo.addProperty("avg_buy", quickStatus.get("buyPrice").getAsFloat()); + productInfo.addProperty("avg_sell", quickStatus.get("sellPrice").getAsFloat()); + + for(JsonElement element : product.get("sell_summary").getAsJsonArray()) { + if(element.isJsonObject()) { + JsonObject sellSummaryFirst = element.getAsJsonObject(); + productInfo.addProperty("curr_sell", sellSummaryFirst.get("pricePerUnit").getAsFloat()); + break; + } + } + + for(JsonElement element : product.get("buy_summary").getAsJsonArray()) { + if(element.isJsonObject()) { + JsonObject sellSummaryFirst = element.getAsJsonObject(); + productInfo.addProperty("curr_buy", sellSummaryFirst.get("pricePerUnit").getAsFloat()); + break; + } + } + + bazaarJson.add(entry.getKey().replace(":", "-"), productInfo); + } + } + }); + } + + public void updateAvgPrices() { + manager.hypixelApi.getMyApiGZIPAsync("auction_averages/3day.json.gz", (jsonObject) -> { + craftCost.clear(); + auctionPricesJson = jsonObject; + lastAuctionAvgUpdate = System.currentTimeMillis(); + }, () -> {}); + } + + public JsonObject getItemAuctionInfo(String internalname) { + if(auctionPricesJson == null) return null; + JsonElement e = auctionPricesJson.get(internalname); + if(e == null) { + return null; + } + return e.getAsJsonObject(); + } + + public JsonObject getBazaarInfo(String internalname) { + if(bazaarJson == null) return null; + JsonElement e = bazaarJson.get(internalname); + if(e == null) { + return null; + } + return e.getAsJsonObject(); + } + + private static final List<String> hardcodedVanillaItems = Utils.createList( + "WOOD_AXE", "WOOD_HOE", "WOOD_PICKAXE","WOOD_SPADE", "WOOD_SWORD" + ); + public boolean isVanillaItem(String internalname) { + if(hardcodedVanillaItems.contains(internalname)) return true; + + //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; + } + + public class CraftInfo { + public boolean fromRecipe = false; + public boolean vanillaItem = false; + public float craftCost = -1; + } + + /** + * Recursively calculates the cost of crafting an item from raw materials. + */ + public CraftInfo getCraftCost(String internalname) { + if(craftCost.containsKey(internalname)) { + return craftCost.get(internalname); + } else { + CraftInfo ci = new CraftInfo(); + + ci.vanillaItem = isVanillaItem(internalname); + + JsonObject auctionInfo = getItemAuctionInfo(internalname); + JsonObject bazaarInfo = getBazaarInfo(internalname); + + if(bazaarInfo != null) { + float bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat(); + ci.craftCost = bazaarInstantBuyPrice; + } + //Don't use auction prices for vanilla items cuz people like to transfer money, messing up the cost of vanilla items. + if(auctionInfo != null && !ci.vanillaItem) { + float auctionPrice = auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat(); + if(ci.craftCost < 0 || auctionPrice < ci.craftCost) { + ci.craftCost = auctionPrice; + } + } + JsonObject item = manager.getItemInformation().get(internalname); + if(item != null && item.has("recipe")) { + float craftPrice = 0; + JsonObject recipe = item.get("recipe").getAsJsonObject(); + + String[] x = {"1","2","3"}; + String[] y = {"A","B","C"}; + for(int i=0; i<9; i++) { + String name = y[i/3]+x[i%3]; + String itemS = recipe.get(name).getAsString(); + if(itemS == null || itemS.length() == 0) continue; + + int count = 1; + if(itemS.split(":").length == 2) { + count = Integer.parseInt(itemS.split(":")[1]); + itemS = itemS.split(":")[0]; + } + float compCost = getCraftCost(itemS).craftCost * count; + if(compCost < 0) { + //If it's a custom item without a cost, return + if(!getCraftCost(itemS).vanillaItem) { + craftCost.put(internalname, ci); + return ci; + } + } else { + craftPrice += compCost; + } + } + + if(ci.craftCost < 0 || craftPrice < ci.craftCost) { + ci.craftCost = craftPrice; + ci.fromRecipe = true; + } + } + craftCost.put(internalname, ci); + return ci; + } + } + + /** + * Calculates the cost of enchants + other price modifiers such as pet xp, midas price, etc. + */ + public float getCostOfEnchants(String internalname, NBTTagCompound tag) { + float costOfEnchants = 0; + if(true) return 0; + + JsonObject info = getItemAuctionInfo(internalname); + if(info == null || !info.has("price")) { + return 0; + } + if(auctionPricesJson == null || !auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) { + return 0; + } + JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices"); + JsonObject ench_maximums = auctionPricesJson.getAsJsonObject("ench_maximums"); + if(!ench_prices.has(internalname) || !ench_maximums.has(internalname)) { + return 0; + } + JsonObject iid_variables = ench_prices.getAsJsonObject(internalname); + float ench_maximum = ench_maximums.get(internalname).getAsFloat(); + + int enchants = 0; + float price = getItemAuctionInfo(internalname).get("price").getAsFloat(); + if(tag.hasKey("ExtraAttributes")) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + if(ea.hasKey("enchantments")) { + + NBTTagCompound enchs = ea.getCompoundTag("enchantments"); + for(String ench : enchs.getKeySet()) { + enchants++; + int level = enchs.getInteger(ench); + + for(Map.Entry<String, JsonElement> entry : iid_variables.entrySet()) { + if(matchEnch(ench, level, entry.getKey())) { + costOfEnchants += entry.getValue().getAsJsonObject().get("A").getAsFloat()*price + + entry.getValue().getAsJsonObject().get("B").getAsFloat(); + break; + } + } + } + } + } + return costOfEnchants; + } + + /** + * Checks whether a certain enchant (ench name + lvl) matches an enchant id + * eg. PROTECTION_GE6 will match -> ench_name = PROTECTION, lvl >= 6 + */ + private boolean matchEnch(String ench, int level, String id) { + if(!id.contains(":")) { + return false; + } + + String idEnch = id.split(":")[0]; + String idLevel = id.split(":")[1]; + + if(!ench.equalsIgnoreCase(idEnch)) { + return false; + } + + if(String.valueOf(level).equalsIgnoreCase(idLevel)) { + return true; + } + + if(idLevel.startsWith("LE")) { + int idLevelI = Integer.valueOf(idLevel.substring(2)); + return level <= idLevelI; + } else if(idLevel.startsWith("GE")) { + int idLevelI = Integer.valueOf(idLevel.substring(2)); + return level >= idLevelI; + } + + return false; + } + /*ScheduledExecutorService auctionUpdateSES = Executors.newSingleThreadScheduledExecutor(); private AtomicInteger auctionUpdateId = new AtomicInteger(0); public void updateAuctions() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java index 817c9e96..06211f59 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java @@ -1,5 +1,6 @@ package io.github.moulberry.notenoughupdates.auction; +import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.util.Utils; @@ -318,6 +319,47 @@ public class CustomAH extends Gui { } } + if(manager.config.auctionPriceInfo.value) { + String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(auc.getStack()); + if(internalname != null) { + tooltip.add(""); + if(!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + tooltip.add(EnumChatFormatting.GRAY+"[SHIFT for Price Info]"); + } else { + JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname); + + boolean hasAuctionPrice = auctionInfo != null; + + int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname); + + APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalname); + + if(lowestBin > 0) { + tooltip.add(EnumChatFormatting.GRAY+"Lowest BIN: "+ + EnumChatFormatting.GOLD+format.format(lowestBin)+" coins"); + } + if(hasAuctionPrice) { + int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + tooltip.add(EnumChatFormatting.GRAY+"AH Price: "+ + EnumChatFormatting.GOLD+format.format(auctionPrice)+" coins"); + tooltip.add(EnumChatFormatting.GRAY+"AH Sales: "+ + EnumChatFormatting.GOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day"); + if(auctionInfo.has("clean_price")) { + tooltip.add(EnumChatFormatting.GRAY+"AH Price (Clean): "+ + EnumChatFormatting.GOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins"); + tooltip.add(EnumChatFormatting.GRAY+"AH Sales (Clean): "+ + EnumChatFormatting.GOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day"); + } + + } + if(craftCost.fromRecipe) { + tooltip.add(EnumChatFormatting.GRAY+"Raw Craft Cost: "+ + EnumChatFormatting.GOLD+format.format((int)craftCost.craftCost)+" coins"); + } + } + } + } + tooltip.add(""); tooltip.add(EnumChatFormatting.GRAY+"Ends in: "+endsIn); tooltip.add(""); @@ -534,7 +576,63 @@ public class CustomAH extends Gui { } else if(mouseY > guiTop+100 && mouseY < guiTop+100+16) { if(leftStack != null) tooltipToRender = leftStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); } else if(mouseY > guiTop+61 && mouseY < guiTop+61+16) { - if(rightStack != null) tooltipToRender = rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + tooltipToRender = new ArrayList<>(); + APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId); + if(auc != null) { + tooltipToRender.add(EnumChatFormatting.WHITE+"Price Info"); + + String internalname = manager.getInternalNameForItem(auc.getStack()); + JsonObject auctionInfo = manager.auctionManager.getItemAuctionInfo(internalname); + JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalname); + + boolean hasAuctionPrice = auctionInfo != null; + boolean hasBazaarPrice = bazaarInfo != null; + + int lowestBin = manager.auctionManager.getLowestBin(internalname); + + NumberFormat format = NumberFormat.getInstance(Locale.US); + + APIManager.CraftInfo craftCost = manager.auctionManager.getCraftCost(internalname); + + if(lowestBin > 0) { + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Lowest BIN: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(lowestBin)+" coins"); + } + if(hasBazaarPrice) { + int bazaarBuyPrice = (int)bazaarInfo.get("avg_buy").getAsFloat(); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarBuyPrice)+" coins"); + int bazaarSellPrice = (int)bazaarInfo.get("avg_sell").getAsFloat(); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Sell: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarSellPrice)+" coins"); + int bazaarInstantBuyPrice = (int)bazaarInfo.get("curr_buy").getAsFloat(); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Buy: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantBuyPrice)+" coins"); + int bazaarInstantSellPrice = (int)bazaarInfo.get("curr_sell").getAsFloat(); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Sell: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantSellPrice)+" coins"); + } + if(hasAuctionPrice) { + int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionPrice)+" coins"); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day"); + if(auctionInfo.has("clean_price")) { + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price (Clean): "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins"); + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales (Clean): "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day"); + } + + } + if(craftCost.fromRecipe) { + tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Raw Craft Cost: "+ + EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)craftCost.craftCost)+" coins"); + } + tooltipToRender.add(""); + } + if(rightStack != null) tooltipToRender.addAll(rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false)); } else if(mouseY > guiTop+126 && mouseY < guiTop+126+16) { if(middleStack != null) tooltipToRender = middleStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java index 906ccda4..728e692a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java @@ -28,11 +28,12 @@ public class CapeManager { public Pair<NEUCape, String> localCape = null; private HashMap<String, Pair<NEUCape, String>> capeMap = new HashMap<>(); + private int permSyncTries = 5; private boolean allAvailable = false; private HashSet<String> availableCapes = new HashSet<>(); - private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee", "gravy" }; - public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true }; + private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee", "gravy", "space" }; + public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true, false }; public static CapeManager getInstance() { return INSTANCE; @@ -47,7 +48,7 @@ public class CapeManager { } private void updateCapes() { - NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/getactivecape.py", (jsonObject) -> { + NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("activecapes.json", (jsonObject) -> { if(jsonObject.get("success").getAsBoolean()) { lastCapeSynced = System.currentTimeMillis(); for(JsonElement active : jsonObject.get("active").getAsJsonArray()) { @@ -60,18 +61,30 @@ public class CapeManager { }, () -> { System.out.println("[MBAPI] Update capes errored"); }); - if(Minecraft.getMinecraft().thePlayer != null) { - NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/getpermscape.py?uuid="+ - Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), (jsonObject) -> { + + if(Minecraft.getMinecraft().thePlayer != null && permSyncTries > 0) { + String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""); + permSyncTries--; + NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("permscapes.json", (jsonObject) -> { if(jsonObject.get("success").getAsBoolean()) { + permSyncTries = 0; + availableCapes.clear(); - for(JsonElement perm : jsonObject.get("perms").getAsJsonObject().get("perms").getAsJsonArray()) { - if(perm.isJsonPrimitive()) { - String cape = perm.getAsString(); - if(cape.equals("*")) { - allAvailable = true; - } else { - availableCapes.add(cape); + for(JsonElement permPlayer : jsonObject.get("perms").getAsJsonArray()) { + if(permPlayer.isJsonObject()) { + String playerUuid = permPlayer.getAsJsonObject().get("_id").getAsString(); + if(playerUuid != null && playerUuid.equals(uuid)) { + for(JsonElement perm : permPlayer.getAsJsonObject().get("perms").getAsJsonArray()) { + if(perm.isJsonPrimitive()) { + String cape = perm.getAsString(); + if(cape.equals("*")) { + allAvailable = true; + } else { + availableCapes.add(cape); + } + } + } + return; } } } @@ -83,7 +96,7 @@ public class CapeManager { } public HashSet<String> getAvailableCapes() { - return allAvailable ? availableCapes : availableCapes; + return allAvailable ? null : availableCapes; } public void setCape(String playerUUID, String capename, boolean updateConfig) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java index bcd5e26e..1f1876af 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java @@ -45,8 +45,8 @@ public class CapeNode { public float vertSideTexU = 0; public float vertSideTexVTop = 0; - public static final float gravity = 0.1f; - public static final float resistance = 0.5f; + public final float gravity = 0.1f; + public final float resistance = 0.5f; public static final int FLOAT_NUM = 20; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java index 985bc14c..a53b300e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java @@ -27,17 +27,29 @@ import org.lwjgl.util.vector.Vector3f; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.security.Key; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; +import java.util.*; public class NEUCape { - public ResourceLocation capeTex = null; + private int currentFrame = 0; + private int displayFrame = 0; + private String capeName; + public ResourceLocation[] capeTextures = null; + + private long lastFrameUpdate = 0; + + private static int ANIM_MODE_LOOP = 0; + private static int ANIM_MODE_PINGPONG = 1; + private int animMode = ANIM_MODE_LOOP; private List<List<CapeNode>> nodes = null; + private Random random = new Random(); + + private long eventMillis; + private float eventLength; + private float eventRandom; + private static double vertOffset = 1.4; private static double shoulderLength = 0.24; private static double shoulderWidth = 0.13; @@ -56,14 +68,76 @@ public class NEUCape { } public void setCapeTexture(String capeName) { - if(capeTex == null || !capeTex.getResourcePath().equals(capeName+".png")) { - if(capeName.equalsIgnoreCase("fade")) { - shaderName = "fade_cape"; - } else { - shaderName = "cape"; + if(this.capeName != null && this.capeName.equalsIgnoreCase(capeName)) return; + this.capeName = capeName; + + startTime = System.currentTimeMillis(); + + if(capeName.equalsIgnoreCase("fade")) { + shaderName = "fade_cape"; + } else if(capeName.equalsIgnoreCase("space")) { + shaderName = "space_cape"; + } else { + shaderName = "cape"; + } + + ResourceLocation staticCapeTex = new ResourceLocation("notenoughupdates:capes/"+capeName+".png"); + capeTextures = new ResourceLocation[1]; + capeTextures[0] = staticCapeTex; + + /*if(rlExists(staticCapeTex)) { + capeTextures = new ResourceLocation[1]; + capeTextures[0] = staticCapeTex; + } else { + List<ResourceLocation> texs = new ArrayList<>(); + for(int i=0; i<99; i++) { + ResourceLocation frame = new ResourceLocation( + "notenoughupdates:capes/"+capeName+"/"+capeName+"_"+String.format("%02d", i)+".png"); + if(rlExists(frame)) { + texs.add(frame); + } else { + break; + } + } + capeTextures = new ResourceLocation[texs.size()]; + for(int i=0; i<texs.size(); i++) { + capeTextures[i] = texs.get(i); + } + }*/ + } + + private void bindTexture() { + if(capeTextures != null && capeTextures.length>0) { + long currentTime = System.currentTimeMillis(); + if(currentTime - lastFrameUpdate > 100) { + lastFrameUpdate = currentTime/100*100; + currentFrame++; + + if(animMode == ANIM_MODE_PINGPONG) { + if(capeTextures.length == 1) { + currentFrame = displayFrame = 0; + } else { + int frameCount = 2*capeTextures.length-2; + currentFrame %= frameCount; + displayFrame = currentFrame; + if(currentFrame >= capeTextures.length) { + displayFrame = frameCount - displayFrame; + } + } + } else if(animMode == ANIM_MODE_LOOP) { + currentFrame %= capeTextures.length; + displayFrame = currentFrame; + } } - capeTex = new ResourceLocation("notenoughupdates:capes/"+capeName+".png"); - startTime = System.currentTimeMillis(); + Minecraft.getMinecraft().getTextureManager().bindTexture(capeTextures[displayFrame]); + } + } + + public boolean rlExists(ResourceLocation loc) { + try { + return !Minecraft.getMinecraft().getResourceManager().getAllResources(loc).isEmpty(); + } catch(Exception e) { + return false; } } @@ -92,7 +166,7 @@ public class NEUCape { float centerMult = 1-Math.abs(j-(HORZ_NODES-1)/2f)/((HORZ_NODES-1)/2f);//0-(horzCapeNodes) -> 0-1-0 float vMax = vMaxSide + (vMaxCenter - vMaxSide) * centerMult; - CapeNode node = new CapeNode(0, 0, 0);//pX-1, pY+2-i*targetDist, pZ+(j-(horzCapeNodes-1)/2f)*targetDist*2 + CapeNode node = new CapeNode(pX, pY, pZ);//pX-1, pY+2-i*targetDist, pZ+(j-(horzCapeNodes-1)/2f)*targetDist*2 node.texU = uMin + (uMax - uMin) * j/(float)(HORZ_NODES-1); node.texV = vMin + (vMax - vMin) * i/(float)(VERT_NODES-1); @@ -220,6 +294,10 @@ public class NEUCape { private void loadShaderUniforms(ShaderManager shaderManager) { if(shaderName.equalsIgnoreCase("fade_cape")) { shaderManager.loadData(shaderName, "millis", (int)(System.currentTimeMillis()-startTime)); + } else if(shaderName.equalsIgnoreCase("space_cape")) { + shaderManager.loadData(shaderName, "millis", (int)(System.currentTimeMillis()-startTime)); + shaderManager.loadData(shaderName, "eventMillis", (int)(System.currentTimeMillis()-eventMillis)); + shaderManager.loadData(shaderName, "eventRand", eventRandom); } } @@ -243,7 +321,7 @@ public class NEUCape { GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); - Minecraft.getMinecraft().getTextureManager().bindTexture(capeTex); + bindTexture(); GlStateManager.enableTexture2D(); GlStateManager.disableCull(); @@ -373,6 +451,15 @@ public class NEUCape { private void updateCape(EntityPlayer player) { Vector3f capeTranslation = updateFixedCapeNodes(player); + if(shaderName.equals("space_cape")) { + long currentTime = System.currentTimeMillis(); + if(currentTime-startTime > eventMillis-startTime+eventLength) { + eventMillis = currentTime; + eventLength = random.nextFloat()*2000+4000; + eventRandom = random.nextFloat(); + } + } + if(notRendering) { for (int y = 0; y < nodes.size(); y++) { for (int x = 0; x < nodes.get(y).size(); x++) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java index 7dc5daa1..696e226b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java @@ -227,7 +227,7 @@ public class SBGamemodes { @SubscribeEvent public void onPlayerInteract(PlayerInteractEvent event) { - if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; + if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; if(!"Your Island".equals(SBScoreboardData.getInstance().location)) return; @@ -250,7 +250,7 @@ public class SBGamemodes { @SubscribeEvent public void onTick(TickEvent.ClientTickEvent event) { - if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; + if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; if("Your Island".equals(SBScoreboardData.getInstance().location) && (EnumChatFormatting.YELLOW+"Break a log").equals(SBScoreboardData.getInstance().objective)) { @@ -328,7 +328,7 @@ public class SBGamemodes { } if(has) System.out.println("-----END"); }*/ - if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; + if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; String message = event.message.getFormattedText(); if(message.contains("\u2620")) { //Death symbol ( ☠ ) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java index 1516aae1..2912c6bd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java @@ -78,7 +78,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { private void refreshItems() { items.clear(); for(String internalname : manager.getItemInformation().keySet()) { - if(!manager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) { + if(!manager.auctionManager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) { JsonObject item = manager.getItemInformation().get(internalname); JsonArray lore = manager.getItemInformation().get(internalname).get("lore").getAsJsonArray(); switch(filterMode) { @@ -121,8 +121,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane { float cost1 = manager.auctionManager.getLowestBin(o1); float cost2 = manager.auctionManager.getLowestBin(o2); - if(cost1 == -1) cost1 = manager.getCraftCost(o1).craftCost; - if(cost2 == -1) cost2 = manager.getCraftCost(o2).craftCost; + if(cost1 == -1) cost1 = manager.auctionManager.getCraftCost(o1).craftCost; + if(cost2 == -1) cost2 = manager.auctionManager.getCraftCost(o2).craftCost; if(cost1 < cost2) return 1; if(cost1 > cost2) return -1; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java index 234d06a8..c03b98fb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java @@ -194,9 +194,13 @@ public class HTMLInfoPane extends TextInfoPane { EnumChatFormatting.GRAY+"), please wait..."; Runtime runtime = Runtime.getRuntime(); - Process p = runtime.exec(spaceEscape(wkHtmlToImage.getAbsolutePath()) + " --width "+ + + String[] wkCommand = new String[]{ wkHtmlToImage.getAbsolutePath(), "--width", ""+IMAGE_WIDTH*ZOOM_FACTOR, + "--transparent", "--zoom", ""+ZOOM_FACTOR, input.getAbsolutePath(), output.getAbsolutePath()}; + Process p = runtime.exec(wkCommand); + /*Process p = runtime.exec(spaceEscape(wkHtmlToImage.getAbsolutePath()) + " --width "+ IMAGE_WIDTH*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR + " " + spaceEscape(input.getAbsolutePath()) + - " " + spaceEscape(output.getAbsolutePath())); + " " + spaceEscape(output.getAbsolutePath()));*/ /*Process p = runtime.exec("\""+wkHtmlToImage.getAbsolutePath() + "\" --width "+ IMAGE_WIDTH*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR+" \"" + input.getAbsolutePath() + "\" \"" + output.getAbsolutePath() + "\"");*/ diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java index 22cf38d1..1f77b9cc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java @@ -60,7 +60,7 @@ public class MixinEntityRenderer { return d1; } - @ModifyVariable(method="renderWorldPass", at=@At(value="STORE"), ordinal = 2, print = true) + @ModifyVariable(method="renderWorldPass", at=@At(value="STORE"), ordinal = 2) public double renderWorldPass_d2(double d2) { Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition(); if(currentPosition != null) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java index 123c8cb9..34f1ea62 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java @@ -1,8 +1,12 @@ package io.github.moulberry.notenoughupdates.mixins; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -17,4 +21,37 @@ public class MixinItemStack { } } + @Shadow + private NBTTagCompound stackTagCompound; + + @Inject(method="getDisplayName",at=@At("HEAD"), cancellable=true) + public void getDisplayName(CallbackInfoReturnable<String> returnable) { + try { + String customName = NotEnoughUpdates.INSTANCE.manager.itemRenameJson + .get(stackTagCompound.getCompoundTag("ExtraAttributes").getString("uuid")).getAsString(); + if(customName != null && !customName.equals("")) { + String prefix = EnumChatFormatting.RESET.toString(); + if (stackTagCompound != null && stackTagCompound.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = stackTagCompound.getCompoundTag("display"); + + if (nbttagcompound.hasKey("Name", 8)) { + String name = nbttagcompound.getString("Name"); + char[] chars = name.toCharArray(); + + int i; + for(i=0; i<chars.length; i+=2) { + if(chars[i] != '\u00a7'){ + break; + } + } + + prefix = name.substring(0, i); + } + } + returnable.setReturnValue(prefix+customName); + } + } catch(Exception e) { } + } + + } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java index 5d8697b4..0bb84f44 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java @@ -20,7 +20,8 @@ public class MixinNetHandlerPlayClient { @Redirect(method="handlePlayerPosLook", at=@At(value="INVOKE", target=TARGET)) public void handlePlayerPosLook_setPositionAndRotation(EntityPlayer player, double x, double y, double z, float yaw, float pitch) { if(CustomItemEffects.INSTANCE.aoteTeleportationCurr != null) { - CustomItemEffects.INSTANCE.aoteTeleportationMillis += 175; + CustomItemEffects.INSTANCE.aoteTeleportationMillis += + Math.max(0, Math.min(300, NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value)); } player.setPositionAndRotation(x, y, z, yaw, pitch); } 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 4906fa4d..53c6e00b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java @@ -78,6 +78,11 @@ public class Options { "Streamer Mode", false, "Hides or randomises some stuff on your screen to prevent sniping."); + public Option<Boolean> disableTreecapOverlay = new Option( + false, + "Disable Treecap Overlay", + false, + "Disables the treecapitator overlay effect."); public Option<Boolean> hideApiKey = new Option( false, "Hide Apikey Setting", @@ -123,11 +128,26 @@ public class Options { "Hide GUI Filler Tooltips", false, "Hides the tooltip of glass panes in skyblock GUIs. Contrib: ThatGravyBoat"); + public Option<Boolean> dungeonProfitLore = new Option( + false, + "Dungeon Profit in Lore", + false, + "If true, will show the dungeon profit on the tooltip of the 'reward chest' instead of as a GUI."); + public Option<Boolean> auctionPriceInfo = new Option( + true, + "Price Info in Auction Lore", + false, + "If true, will show price information about an item inside the auction house item tooltip."); public Option<Double> paneWidthMult = new Option( 1.0, "Pane Width", false, "Changes how wide the item and info panes are. Value between 0.5-1.5.", 0.5, 1.5); + public Option<Double> smoothAoteMillis = new Option( + 175.0, + "Smooth AOTE Milliseconds", + false, + "How long teleporting with the AOTE takes. 0 = disable.", 0, 300); public Option<Double> bgOpacity = new Option( 30.0, "Pane Background Opacity", @@ -294,18 +314,22 @@ public class Options { tryAddOption(showQuickCommands, options); tryAddOption(hidePotionEffect, options); tryAddOption(hideEmptyPanes, options); - //tryAddOption(advancedPriceInfo, options); + tryAddOption(advancedPriceInfo, options); tryAddOption(showUpdateMsg, options); tryAddOption(tooltipBorderColours, options); tryAddOption(disableAhScroll, options); tryAddOption(hideApiKey, options); tryAddOption(streamerMode, options); + tryAddOption(disableTreecapOverlay, options); tryAddOption(autoupdate, options); tryAddOption(cacheRenderedItempane, options); tryAddOption(itemStyle, options); tryAddOption(keepopen, options); tryAddOption(disableItemTabOpen, options); + tryAddOption(dungeonProfitLore, options); + tryAddOption(auctionPriceInfo, options); //Sliders + tryAddOption(smoothAoteMillis, options); tryAddOption(bgBlurFactor, options); tryAddOption(ahNotification, options); tryAddOption(bgOpacity, options); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java index b925f6da..5ea6c023 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java @@ -24,7 +24,7 @@ public class HypixelApi { private ExecutorService es = Executors.newFixedThreadPool(3); private int myApiErrors = 0; - private String[] myApiURLs = {"https://moulberry.codes/", "https://51.89.22.3/", "http://moulberry.codes/", "http://51.89.22.3/"}; + private String[] myApiURLs = {"https://moulberry.codes/", "http://51.89.22.3/", "http://moulberry.codes/", "https://51.89.22.3/"}; public void getHypixelApiAsync(String apiKey, String method, HashMap<String, String> args, Consumer<JsonObject> consumer) { getHypixelApiAsync(apiKey, method, args, consumer, () -> {}); diff --git a/src/main/resources/assets/notenoughupdates/capes/space.png b/src/main/resources/assets/notenoughupdates/capes/space.png Binary files differnew file mode 100644 index 00000000..ba239e22 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/capes/space.png diff --git a/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png b/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png Binary files differindex 48b4af95..37ad163e 100644 --- a/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png +++ b/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png diff --git a/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png b/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png Binary files differindex d8fc8530..fd23cc35 100644 --- a/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png +++ b/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png diff --git a/src/main/resources/assets/notenoughupdates/shaders/space_cape.frag b/src/main/resources/assets/notenoughupdates/shaders/space_cape.frag new file mode 100644 index 00000000..b3cb8a1d --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/shaders/space_cape.frag @@ -0,0 +1,60 @@ +#version 120 + +varying vec4 passColour; +varying vec3 passNormal; +uniform sampler2D textureIn; + +uniform int millis; +uniform int eventMillis; +uniform float eventRand; //0-1 + +void main() { + vec4 texture = texture2D(textureIn, gl_TexCoord[0].st); + + vec2 texCoord = gl_TexCoord[0].st + vec2(mod(millis/100.0f,1024.0f)/1024.0f, 421.0f/1024.0f); + + vec4 extra = vec4(0,0,0,0); + if(eventRand < 0.4f) { + vec2 extraPos = vec2(45.0f+eventRand/0.4f*250.0f, eventMillis/300.0f*550.0f)/1024.0f; + vec2 extraTexCoord = vec2(48.0f/1024.0f-(gl_TexCoord[0].t-extraPos.y), gl_TexCoord[0].s-extraPos.x+894.0f/1024.0f); + if(extraTexCoord.x > 0.0f && extraTexCoord.x < 200.0f/1024.0f) { + if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) { + extra = texture2D(textureIn, extraTexCoord); + } + } + } else if(eventRand < 0.45f) { + vec2 extraPos = vec2(-30.0f+eventMillis/2000f*370.0f, 50.0f+(eventRand-0.4f)/0.05f*300.0f)/1024.0f; + vec2 extraTexCoord = vec2(gl_TexCoord[0].s-extraPos.x+248.0f/1024.0f, gl_TexCoord[0].t-extraPos.y+894.0f/1024.0f); + if(extraTexCoord.x > 200.0f/1024.0f && extraTexCoord.x < 300.0f/1024.0f) { + if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) { + extra = texture2D(textureIn, extraTexCoord); + } + } + } else if(eventRand < 0.47f) { + vec2 extraPos = vec2(-30.0f+eventMillis/2000f*370.0f, 50.0f+(eventRand-0.45f)/0.02f*300.0f)/1024.0f; + vec2 extraTexCoord = vec2(gl_TexCoord[0].s-extraPos.x+348.0f/1024.0f, gl_TexCoord[0].t-extraPos.y+894.0f/1024.0f); + if(extraTexCoord.x > 300.0f/1024.0f && extraTexCoord.x < 400.0f/1024.0f) { + if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) { + extra = texture2D(textureIn, extraTexCoord); + } + } + } else if(eventRand < 0.48f) { + vec2 extraPos = vec2(-30.0f+eventMillis/2000f*370.0f, 50.0f+(eventRand-0.47f)/0.01f*300.0f)/1024.0f; + vec2 extraTexCoord = vec2(gl_TexCoord[0].s-extraPos.x+448.0f/1024.0f, gl_TexCoord[0].t-extraPos.y+894.0f/1024.0f); + if(extraTexCoord.x > 400.0f/1024.0f && extraTexCoord.x < 500.0f/1024.0f) { + if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) { + extra = texture2D(textureIn, extraTexCoord); + } + } + } + + vec3 space = texture2D(textureIn, texCoord).rgb; + + gl_FragColor = vec4(texture.rgb*texture.a + extra.rgb*extra.a*(1.0f-texture.a) + space*(1.0f-texture.a)*(1.0f-extra.a), 1.0f) * passColour; + + vec3 fakeSunNormal = normalize(vec3(0.2f,1.0f,-0.2f)); + vec3 normNormal = normalize(passNormal); + float shading = max(0.6f, dot(fakeSunNormal, normNormal)); + + gl_FragColor = vec4(gl_FragColor.rgb*shading, gl_FragColor.a); +} diff --git a/src/main/resources/assets/notenoughupdates/shaders/space_cape.vert b/src/main/resources/assets/notenoughupdates/shaders/space_cape.vert new file mode 100644 index 00000000..2b5c48f8 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/shaders/space_cape.vert @@ -0,0 +1,12 @@ +#version 120 + +varying vec4 passColour; +varying vec3 passNormal; + +void main() { + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + + passColour = gl_Color; + passNormal = normalize(gl_Normal); +}
\ No newline at end of file |