@Override void setClassMod(ClassMod classMod) { super.setClassMod(classMod); if (deobfMethod != null && deobfMethod.getClassName() == null) { deobfMethod = new MethodRef(classMod.getDeobfClass(), deobfMethod.getName(), deobfMethod.getType()); } }
RenderGlobalMod(Mod mod) { super(mod); final FieldRef clouds; final FieldRef mc = new FieldRef(getDeobfClass(), "mc", "LMinecraft;"); final FieldRef gameSettings = new FieldRef("Minecraft", "gameSettings", "LGameSettings;"); final JavaRef fancyGraphics; final int fancyGraphicsOp; final String fancyGraphicsIf; final MethodRef drawFancyClouds; if (getMinecraftVersion().compareTo("1.8.1-pre4") < 0) { fancyGraphics = new FieldRef("GameSettings", "fancyGraphics", "Z"); fancyGraphicsOp = GETFIELD; fancyGraphicsIf = buildExpression(IFEQ, any(2)); drawFancyClouds = new MethodRef(MCPatcherUtils.COLORIZE_WORLD_CLASS, "drawFancyClouds", "(Z)Z"); } else { fancyGraphics = new MethodRef("GameSettings", "fancyGraphics", "()I"); fancyGraphicsOp = INVOKEVIRTUAL; fancyGraphicsIf = buildExpression(ICONST_2, IF_ICMPNE_or_IF_ICMPEQ, any(2)); drawFancyClouds = new MethodRef(MCPatcherUtils.COLORIZE_WORLD_CLASS, "drawFancyClouds", "(I)I"); } final boolean intParam = getMinecraftVersion().compareTo("14w25a") >= 0; final MethodRef renderClouds = new MethodRef(getDeobfClass(), "renderClouds", "(F" + (intParam ? "I" : "") + ")V"); final MethodRef renderCloudsFancy = new MethodRef(getDeobfClass(), "renderCloudsFancy", renderClouds.getType()); final FieldRef endSkyColor = new FieldRef(MCPatcherUtils.COLORIZE_WORLD_CLASS, "endSkyColor", "I"); RenderUtilsMod.setup(this); if (ResourceLocationMod.haveClass()) { clouds = new FieldRef(getDeobfClass(), "clouds", "LResourceLocation;"); addClassSignature( new ResourceLocationSignature(this, clouds, "textures/environment/clouds.png")); } else { addClassSignature(new ConstSignature("/environment/clouds.png")); clouds = null; } addClassSignature( new BytecodeSignature() { { setMethod(renderClouds); addXref(1, mc); addXref(2, gameSettings); addXref(3, fancyGraphics); addXref(4, renderCloudsFancy); if (clouds != null) { addXref(5, clouds); } } @Override public String getMatchExpression() { return buildExpression( // 1.8.1-pre4+: if (mc.gameSettings.fancyGraphics() == 2) { // earlier: if (mc.gameSettings.fancyGraphics) { ALOAD_0, captureReference(GETFIELD), captureReference(GETFIELD), captureReference(fancyGraphicsOp), fancyGraphicsIf, // this.renderCloudsFancy(...); ALOAD_0, FLOAD_1, intParam ? build(ILOAD_2) : "", captureReference(INVOKESPECIAL, INVOKEVIRTUAL), or(build(GOTO, any(2)), build(RETURN)), // ... any(0, 150), // ...(RenderGlobal.clouds); // ...("/environment/clouds.png"); clouds == null ? push("/environment/clouds.png") : captureReference(GETSTATIC)); } }); addPatch( new BytecodePatch() { @Override public String getDescription() { return "override cloud type"; } @Override public String getMatchExpression() { return buildExpression( capture( build( ALOAD_0, reference(GETFIELD, mc), reference(GETFIELD, gameSettings), reference(fancyGraphicsOp, fancyGraphics))), capture(fancyGraphicsIf)); } @Override public byte[] getReplacementBytes() { return buildCode( getCaptureGroup(1), reference(INVOKESTATIC, drawFancyClouds), getCaptureGroup(2)); } }.targetMethod(renderClouds)); if (TessellatorMod.haveVertexFormatClass()) { addPatch( new BytecodePatch() { @Override public String getDescription() { return "override end sky color"; } @Override public String getMatchExpression() { return buildExpression( // 40, 40, 40, 255 push(40), push(40), push(40), push(255)); } @Override public byte[] getReplacementBytes() { return buildCode( // (ColorizeWorld.endSkyColor >> 16) & 0xff reference(GETSTATIC, endSkyColor), push(16), ISHR, push(0xff), IAND, // (ColorizeWorld.endSkyColor >> 8) & 0xff reference(GETSTATIC, endSkyColor), push(8), ISHR, push(0xff), IAND, // ColorizeWorld.endSkyColor & 0xff reference(GETSTATIC, endSkyColor), push(0xff), IAND, // 255 push(255)); } }); } else { addPatch( new BytecodePatch() { @Override public String getDescription() { return "override end sky color"; } @Override public String getMatchExpression() { return buildExpression( or( build(push(0x181818)), // pre-12w23a build(push(0x282828)) // 12w23a+ )); } @Override public byte[] getReplacementBytes() { return buildCode(reference(GETSTATIC, endSkyColor)); } }); } }
public boolean match(String filename, ClassFile classFile, ClassMap tempClassMap) { for (Object o : classFile.getMethods()) { MethodInfo methodInfo = (MethodInfo) o; classMod.methodInfo = methodInfo; CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); if (codeAttribute == null) { continue; } if (getClassMap().hasMap(deobfMethod)) { MethodRef obfTarget = (MethodRef) getClassMap().map(deobfMethod); if (!methodInfo.getName().equals(obfTarget.getName())) { continue; } } ArrayList<String> deobfTypes = null; ArrayList<String> obfTypes = null; if (deobfMethod != null && deobfMethod.getType() != null) { deobfTypes = ConstPoolUtils.parseDescriptor(deobfMethod.getType()); obfTypes = ConstPoolUtils.parseDescriptor(methodInfo.getDescriptor()); if (!isPotentialTypeMatch(deobfTypes, obfTypes)) { continue; } } ConstPool constPool = methodInfo.getConstPool(); CodeIterator codeIterator = codeAttribute.iterator(); initMatcher(); ArrayList<JavaRef> tempMappings = new ArrayList<JavaRef>(); try { match: for (int offset = 0; offset < codeIterator.getCodeLength() && matcher.match(methodInfo, offset); offset = codeIterator.next()) { tempMappings.clear(); for (Map.Entry<Integer, JavaRef> entry : xrefs.entrySet()) { int captureGroup = entry.getKey(); JavaRef xref = entry.getValue(); byte[] code = matcher.getCaptureGroup(captureGroup); int index = Util.demarshal(code, 1, 2); ConstPoolUtils.matchOpcodeToRefType(code[0], xref); ConstPoolUtils.matchConstPoolTagToRefType(constPool.getTag(index), xref); JavaRef newRef = ConstPoolUtils.getRefForIndex(constPool, index); if (!isPotentialTypeMatch(xref.getType(), newRef.getType())) { if (deobfMethod != null) { Logger.log( Logger.LOG_METHOD, "method %s %s matches %s %s, but", methodInfo.getName(), methodInfo.getDescriptor(), deobfMethod.getName(), deobfMethod.getType()); } Logger.log( Logger.LOG_METHOD, "method %s %s failed xref #%d %s %s -> %s %s", methodInfo.getName(), methodInfo.getDescriptor(), captureGroup, xref.getName(), xref.getType(), newRef.getName(), newRef.getType()); continue match; } tempMappings.add(xref); tempMappings.add(newRef); } for (int i = 0; i + 1 < tempMappings.size(); i += 2) { tempClassMap.addMap(tempMappings.get(i), tempMappings.get(i + 1)); } if (deobfMethod != null) { String deobfName = classMod.getDeobfClass(); tempClassMap.addClassMap(deobfName, ClassMap.filenameToClassName(filename)); tempClassMap.addMethodMap( deobfName, deobfMethod.getName(), methodInfo.getName(), methodInfo.getDescriptor()); if (deobfTypes != null && obfTypes != null) { for (int i = 0; i < deobfTypes.size(); i++) { String desc = ClassMap.descriptorToClassName(deobfTypes.get(i)); String obf = ClassMap.descriptorToClassName(obfTypes.get(i)); if (!obf.equals(desc)) { tempClassMap.addClassMap(desc, obf); } } } } afterMatch(classFile, methodInfo); classMod.methodInfo = null; return true; } } catch (BadBytecode e) { Logger.log(e); } } classMod.methodInfo = null; return false; }