Dumped the classpatchmanager and now i'm calling GDiffPatcher directly in my transformer.
My transformer looks like this. still getting an exception from GDiffPatcher on the actual patching:
patchClassInJar just opens the jar and reads the *.binpatch file in a byte array and it's passed on to the method applyPatch that calls GDiffPatcher
package mod.culegooner.CreeperBurnCore;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.patcher.ClassPatch;
import cpw.mods.fml.common.patcher.ClassPatchManager;
import cpw.mods.fml.repackage.com.nothome.delta.GDiffPatcher;
public class CBClassTransformer implements net.minecraft.launchwrapper.IClassTransformer {
private GDiffPatcher patcher = new GDiffPatcher();
@Override
public byte[] transform(String arg0, String arg1, byte[] arg2) {
//Check if the JVM is about to process the tc.class or the EntityCreeper.class
if (arg0.equals("te") || arg0.equals("net.minecraft.entity.monster.EntityCreeper")) {
System.out.println("********* INSIDE CREEPER TRANSFORMER ABOUT TO PATCH: " + arg0);
//arg2 = patchClassInJar(arg0, arg2, arg0, CBFMLLoadingPlugin.location);
return applyPatch(arg0, arg1, patchClassInJar(arg0,CBFMLLoadingPlugin.location), arg2);
}
return arg2;
}
//a small helper method that takes the class name we want to replace and our jar file.
//It then uses the java zip library to open up the jar file and extract the classes.
//Afterwards it serializes the class in bytes and pushes it on to the JVM.
//with the original bytes that JVM was about to process ignored completely
public byte[] patchClassInJar(String name, File location) {
byte[] bytes = null;
try {
//open the jar as zip
ZipFile zip = new ZipFile(location);
//find the file inside the zip that is called te.class or net.minecraft.entity.monster.EntityCreeper.class
//replacing the . to / so it would look for net/minecraft/entity/monster/EntityCreeper.class
ZipEntry entry = zip.getEntry("binpatch/client/" + name + ".binpatch");
if (entry == null) {
System.out.println(name + " not found in " + location.getName());
} else {
//serialize the class file into the bytes array
InputStream zin = zip.getInputStream(entry);
bytes = new byte[(int) entry.getSize()];
zin.read(bytes);
zin.close();
System.out.println("[" + "CreeperBurnCore" + "]: " + "Class " + name + " patched!");
}
zip.close();
} catch (Exception e) {
throw new RuntimeException("Error overriding " + name + " from " + location.getName(), e);
}
//return the new bytes
return bytes;
}
public byte[] applyPatch(String name, String mappedName, byte[] xpatch,byte[] inputData)
{
if (xpatch == null)
{
return inputData;
}
boolean ignoredError = false;
synchronized (patcher)
{
try
{
inputData = patcher.patch(inputData, xpatch);
}
catch (IOException e)
{
System.out.println("Encountered problem runtime patching class " + name);
}
}
if (!ignoredError)
{
FMLLog.fine("Successfully applied runtime patches for %s (new size %d)", mappedName, inputData.length);
}
return inputData;
}
}
EDIT: Error i'm getting cpw.mods.fml.repackage.com.nothome.delta.PatchException: magic string not found. So it's not seeing it as a valid patch file :/
I seem to have gotten this method working!
First, I modified my class using MCP and generated the reobfuscated data. Then I generated the GDiff data using the included classes with Forge. I then used 7zip to add the GDiff data to a jar archive.
Next, I opened the command prompt and created a pack200 archive like so:
Hi guys! I've been trying to wrap my head around ASM bytecoding, with all its nodes and mechanics. And now I feel like I sorta got the hang of it, thanks to you guys. But right when I put it to the test, I keep getting NoClassDef errors. Here's the error log.
[22:38:15] [main/ERROR] [LaunchWrapper]: Unable to launch
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:134) [launchwrapper-1.9.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.9.jar:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_65]
at GradleStart.bounce(GradleStart.java:108) [start/:?]
at GradleStart.startClient(GradleStart.java:101) [start/:?]
at GradleStart.main(GradleStart.java:56) [start/:?]
Caused by: java.lang.NoClassDefFoundError: net/minecraft/block/BlockTorch
at net.minecraft.block.Block.registerBlocks(Block.java:297) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.(Minecraft.java:333) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 13 more
Caused by: java.lang.ClassNotFoundException: net.minecraft.block.BlockTorch
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:188) ~[launchwrapper-1.9.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.block.Block.registerBlocks(Block.java:297) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.(Minecraft.java:333) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 13 more
Caused by: java.lang.ClassFormatError: Field "torchUnlit" in class net/minecraft/block/BlockTorch has illegal signature "Lnet/minecraft/block/Block"
at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.7.0_65]
at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.7.0_65]
at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:180) ~[launchwrapper-1.9.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.block.Block.registerBlocks(Block.java:297) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.(Minecraft.java:333) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 13 more
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at GradleStart.main(GradleStart.java:60)
Sorry to necro, but I'm trying to patch AnvilChunkLoader to skip loading a chunk if that chunk crashes.
The error:
java.lang.NoClassDefFoundError: net/minecraft/world/chunk/storage/AnvilChunkLoader
at net.minecraft.world.chunk.storage.AnvilSaveHandler.func_75763_a(AnvilSaveHandler.java:34) ~[aym.class:?]
at net.minecraft.world.WorldServer.func_72970_h(WorldServer.java:653) ~[mt.class:?]
at net.minecraft.world.World.<init>(World.java:245) ~[ahb.class:?]
at net.minecraft.world.WorldServer.<init>(WorldServer.java:97) ~[mt.class:?]
at net.minecraft.server.integrated.IntegratedServer.func_71247_a(IntegratedServer.java:62) ~[bsx.class:?]
at net.minecraft.server.integrated.IntegratedServer.func_71197_b(IntegratedServer.java:92) ~[bsx.class:?]
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:387) [MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:685) [?:?]
Caused by: java.lang.ClassNotFoundException: net.minecraft.world.chunk.storage.AnvilChunkLoader
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
... 8 more
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: dh
at org.objectweb.asm.ClassWriter.getCommonSuperClass(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.ClassWriter.a(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.Frame.a(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.Frame.a(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.MethodNode.accept(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.MethodNode.accept(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.ClassNode.accept(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at com.nuclearfarts.nftweaks.NFTweaksClassTransformer.transformAnvilChunkLoader(NFTweaksClassTransformer.java:223) ~[NFTweaksClassTransformer.class:?]
at com.nuclearfarts.nftweaks.NFTweaksClassTransformer.transform(NFTweaksClassTransformer.java:44) ~[NFTweaksClassTransformer.class:?]
at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
My code:
private byte[] transformAnvilChunkLoader(String name, String transformedName, byte[] basicClass)
{
//sets up the injection
System.out.println("NFTweaks in AnvilChunkLoader about to transform: " + name);
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);
Iterator<MethodNode> methods = classNode.methods.iterator();
//injection goes here
while(methods.hasNext())
{
MethodNode method = methods.next();
System.out.println(method.name);
if(method.name.equals("loadChunk__Async"))
{
//changes the modified class back to a byte[]
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
I seem to have gotten this method working!
First, I modified my class using MCP and generated the reobfuscated data. Then I generated the GDiff data using the included classes with Forge. I then used 7zip to add the GDiff data to a jar archive.
Next, I opened the command prompt and created a pack200 archive like so:
I then switched to a Linux machine to run this command on the pack200 archive:
I then switched back to my Windows machine and created these classes: https://github.com/ajwgeek/Patching-Transformer
I then ran these commands with Gradle:
After opening the created jar file, I added this line to the META-INF file:
I then added the jar to the Forge mods folder. I ran Minecraft and the patching transformer appeared to work with no errors!
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:134) [launchwrapper-1.9.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.9.jar:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_65]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_65]
at GradleStart.bounce(GradleStart.java:108) [start/:?]
at GradleStart.startClient(GradleStart.java:101) [start/:?]
at GradleStart.main(GradleStart.java:56) [start/:?]
Caused by: java.lang.NoClassDefFoundError: net/minecraft/block/BlockTorch
at net.minecraft.block.Block.registerBlocks(Block.java:297) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.(Minecraft.java:333) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 13 more
Caused by: java.lang.ClassNotFoundException: net.minecraft.block.BlockTorch
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:188) ~[launchwrapper-1.9.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.block.Block.registerBlocks(Block.java:297) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.(Minecraft.java:333) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 13 more
Caused by: java.lang.ClassFormatError: Field "torchUnlit" in class net/minecraft/block/BlockTorch has illegal signature "Lnet/minecraft/block/Block"
at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.7.0_65]
at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.7.0_65]
at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:180) ~[launchwrapper-1.9.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_65]
at net.minecraft.block.Block.registerBlocks(Block.java:297) ~[Block.class:?]
at net.minecraft.init.Bootstrap.func_151354_b(Bootstrap.java:457) ~[Bootstrap.class:?]
at net.minecraft.client.Minecraft.(Minecraft.java:333) ~[Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:141) ~[Main.class:?]
... 13 more
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at GradleStart.main(GradleStart.java:60)
Bytecode for Method I am injecting into:
L0
LINENUMBER 125 L0
ALOAD 0
ALOAD 1
ILOAD 2
ILOAD 3
ILOAD 4
ALOAD 5
INVOKESPECIAL net/minecraft/block/Block.updateTick (Lnet/minecraft/world/World;IIILjava/util/Random;)V
L1
LINENUMBER 127 L1
ALOAD 1
ILOAD 2
ILOAD 3
ILOAD 4
INVOKEVIRTUAL net/minecraft/world/World.getBlockMetadata (III)I
IFNE L2
L3
LINENUMBER 129 L3
ALOAD 0
ALOAD 1
ILOAD 2
ILOAD 3
ILOAD 4
INVOKEVIRTUAL net/minecraft/block/BlockTorch.onBlockAdded (Lnet/minecraft/world/World;III)V
L2
LINENUMBER 131 L2
FRAME SAME
//HERE IS WHERE I AM INJECTING TO
RETURN
L4
LOCALVARIABLE this Lnet/minecraft/block/BlockTorch; L0 L4 0
LOCALVARIABLE p_149674_1_ Lnet/minecraft/world/World; L0 L4 1
LOCALVARIABLE p_149674_2_ I L0 L4 2
LOCALVARIABLE p_149674_3_ I L0 L4 3
LOCALVARIABLE p_149674_4_ I L0 L4 4
LOCALVARIABLE p_149674_5_ Ljava/util/Random; L0 L4 5
MAXSTACK = 6
MAXLOCALS = 6
My ClassTransformer:
I hope someone can tell me what went wrong here, because I am stumped. Thank you!
Satchels, Quivers, Turtles, Looms, Turnips, QuartzTools, and the list goes on...
I can't get a te.class with forge gradlew, it didn't reobf my edited class.
", cursive">Vanilla Servers with teleport, login, permission and protection system! check out this: Slash Mod
That working on 1.7.+?
Please don't care about my English skill...
Sorry to necro, but I'm trying to patch AnvilChunkLoader to skip loading a chunk if that chunk crashes.
The error:
java.lang.NoClassDefFoundError: net/minecraft/world/chunk/storage/AnvilChunkLoader
at net.minecraft.world.chunk.storage.AnvilSaveHandler.func_75763_a(AnvilSaveHandler.java:34) ~[aym.class:?]
at net.minecraft.world.WorldServer.func_72970_h(WorldServer.java:653) ~[mt.class:?]
at net.minecraft.world.World.<init>(World.java:245) ~[ahb.class:?]
at net.minecraft.world.WorldServer.<init>(WorldServer.java:97) ~[mt.class:?]
at net.minecraft.server.integrated.IntegratedServer.func_71247_a(IntegratedServer.java:62) ~[bsx.class:?]
at net.minecraft.server.integrated.IntegratedServer.func_71197_b(IntegratedServer.java:92) ~[bsx.class:?]
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:387) [MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:685) [?:?]
Caused by: java.lang.ClassNotFoundException: net.minecraft.world.chunk.storage.AnvilChunkLoader
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
... 8 more
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: dh
at org.objectweb.asm.ClassWriter.getCommonSuperClass(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.ClassWriter.a(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.Frame.a(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.Frame.a(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.MethodNode.accept(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.MethodNode.accept(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.ClassNode.accept(Unknown Source) ~[asm-all-5.0.3.jar:5.0.3]
at com.nuclearfarts.nftweaks.NFTweaksClassTransformer.transformAnvilChunkLoader(NFTweaksClassTransformer.java:223) ~[NFTweaksClassTransformer.class:?]
at com.nuclearfarts.nftweaks.NFTweaksClassTransformer.transform(NFTweaksClassTransformer.java:44) ~[NFTweaksClassTransformer.class:?]
at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_45]
My code:
private byte[] transformAnvilChunkLoader(String name, String transformedName, byte[] basicClass)
{
//sets up the injection
System.out.println("NFTweaks in AnvilChunkLoader about to transform: " + name);
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);
Iterator<MethodNode> methods = classNode.methods.iterator();
//injection goes here
while(methods.hasNext())
{
MethodNode method = methods.next();
System.out.println(method.name);
if(method.name.equals("loadChunk__Async"))
{
System.out.println("NFTweaks found loadChunk__Async");
System.out.println("NFTweaks building instruction list...");
LabelNode startLabel;
LabelNode endLabel = new LabelNode();
startLabel = (LabelNode) method.instructions.get(0);
method.instructions.add(endLabel);
method.instructions.add(new VarInsnNode(ACONST_NULL, 1));
method.instructions.add(new VarInsnNode(ARETURN, 1));
method.tryCatchBlocks.add(new TryCatchBlockNode(startLabel, endLabel, endLabel, "java/lang/Exception"));
System.out.println("Incjected sucessfully");
}
}
//changes the modified class back to a byte[]
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
I'm using 1.7.10, if it matters.