I know it's a long video, but it's not very complicated and pretty straight forward. The video covers a little bit of the ASM API at the very end. You need to understand the basic concepts as you put it "stack, ASM opcodes" which this video covers well. I see no harm with it's inclusion.
There is no harm for its inclusion just not necessary at all
There is no harm for its inclusion just not necessary at all
You are entitled to your opinion but i disagree. It appears this goes down to your understanding of what the ASM API is, and what it's an API for. The ASM website says it clearly on the first line "ASM is an all purpose Java bytecode manipulation and analysis framework". It's like saying knowing Forge API doesn't require knowing what Minecraft is, makes no sense to me.
Great tutorial, but as you might remember, I'm just replacing instructions with each other, but is there anyway I can use something like:
this.doSomething()
I can't quite get that to work. Thanks
Your best bet is to use the suggestion of the ASM guys themeselves:
"The best way to learn to use ASM is to write a Java source file that is equivalent to what you want to generate and then use the ASMifier mode of the Bytecode Outline plugin for Eclipse (or the ASMifier tool) to see the equivalent ASM code. If you want to implement a class transformer, write two Java source files (before and after transformation) and use the compare view of the plugin in ASMifier mode to compare the equivalent ASM code."
Seems very useful but very confusing/hard for a beginner like me
Is a coremod those separate jar files the mods use? Or is it something implemented into the files? If I just read through your guide and watch the video, would it be easy to have a full understanding of it?
Seems very useful but very confusing/hard for a beginner like me
Is a coremod those separate jar files the mods use? Or is it something implemented into the files? If I just read through your guide and watch the video, would it be easy to have a full understanding of it?
Before Minecraft 1.6 there used to be a folder called coremods. The jar files that went into the coremods folder are different than the files that go into the mods folder.
Coremods still exist in 1.6 but now they go directly in the mods folder.
Coremods can be described as special mods that alter the vanilla base class files at runtime.
Think of them as base edits, but instead of copying the .class file into the minecraft.jar file directly, it's done at runtime instead, while minecraft is running.
Using coremods is generally not recommended since it might cause conflicts with other mods because it can change minecraft drastically. There is no limitations to what you can do with them, and that's actually a problem because it means there is no compatibility or standards to follow.
i did not know that bytecode plugin thing for eclipse existed. it's.... beautiful... *cry*
Yeah it's a great plugin. I just added a section to the tutorial at the end of the coremod section to using both of the ASMifier and javap inside of eclipse if you don't want to use the plugin, or if people are having trouble installing it.
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 :/
Good luck getting that to work. In the meantime, would you mind helping me? I don't know what I'm doing wrong, but my code doesn't seem to be patching at all.
Good luck getting that to work. In the meantime, would you mind helping me? I don't know what I'm doing wrong, but my code doesn't seem to be patching at all.
Why I have errors when i try replace World or EntityPlayer class?
Client> 2013-07-26 03:02:27 [SEVERE] [ForgeModLoader] Unable to launch
Client> java.lang.reflect.InvocationTargetException
Client> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Client> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
Client> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
Client> at java.lang.reflect.Method.invoke(Unknown Source)
Client> at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
Client> at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
Client> Caused by: java.lang.NoClassDefFoundError: net/minecraft/client/entity/EntityClientPlayerMP
Client> at net.minecraft.client.main.Main.main(SourceFile:37)
Client> ... 6 more
Client> Caused by: java.lang.ClassNotFoundException: net.minecraft.client.entity.EntityClientPlayerMP
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> ... 7 more
Client> Caused by: java.lang.NoClassDefFoundError: net/minecraft/client/entity/EntityPlayerSP
Client> at java.lang.ClassLoader.defineClass1(Native Method)
Client> at java.lang.ClassLoader.defineClass(Unknown Source)
Client> at java.security.SecureClassLoader.defineClass(Unknown Source)
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
Client> ... 9 more
Client> Caused by: java.lang.ClassNotFoundException: net.minecraft.client.entity.EntityPlayerSP
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> ... 13 more
Client> Caused by: java.lang.NoClassDefFoundError: net/minecraft/client/entity/AbstractClientPlayer
Client> at java.lang.ClassLoader.defineClass1(Native Method)
Client> at java.lang.ClassLoader.defineClass(Unknown Source)
Client> at java.security.SecureClassLoader.defineClass(Unknown Source)
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
Client> ... 15 more
Client> Caused by: java.lang.ClassNotFoundException: net.minecraft.client.entity.AbstractClientPlayer
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> ... 19 more
Client> Caused by: java.lang.NoClassDefFoundError: net/minecraft/entity/player/EntityPlayer
Client> at java.lang.ClassLoader.defineClass1(Native Method)
Client> at java.lang.ClassLoader.defineClass(Unknown Source)
Client> at java.security.SecureClassLoader.defineClass(Unknown Source)
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:171)
Client> ... 21 more
Client> Caused by: java.lang.ClassNotFoundException: net.minecraft.entity.player.EntityPlayer
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:179)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> at java.lang.ClassLoader.loadClass(Unknown Source)
Client> ... 25 more
Client> Caused by: java.lang.NullPointerException
Client> at org.objectweb.asm.Type.getArgumentTypes(Unknown Source)
Client> at org.objectweb.asm.commons.Remapper.mapMethodDesc(Unknown Source)
Client> at org.objectweb.asm.commons.RemappingClassAdapter.visitMethod(Unknown Source)
Client> at org.objectweb.asm.ClassReader.b(Unknown Source)
Client> at org.objectweb.asm.ClassReader.accept(Unknown Source)
Client> at org.objectweb.asm.ClassReader.accept(Unknown Source)
Client> at cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer.transform(DeobfuscationTransformer.java:39)
Client> at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:267)
Client> at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:165)
Client> ... 27 more
Game ended with no troubles detected (exit code 0)
That's the weird thing, it SAYS it's patched, no errors, but it's not printing anything when that function is called.
2 Points
I can't see in the transformer when getTranslatedEntityName is called, you are using
getFontRendererFromRenderManager as your target and that comes later.
you are using
m.instructions.insert(targetNode, toInject);
and that always inserts after the target, to insert before use insertBefore
also this method already has a forge hook assigned to it, so you can override it more cleanly with events, you don't need to coremod it i guess
EDIT: Fixed! I had to use 'RenderLivingEvent.Specials.Pre' instead of 'RenderLivingEvent' in the constructor.
Old post:
Uh... how do you get it to work? I tried using events, but I got this error:
2013-07-29 16:21:34 [INFO] [STDERR] java.lang.InstantiationException
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraftforge.event.EventBus.register(EventBus.java:76)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraftforge.event.EventBus.register(EventBus.java:58)
2013-07-29 16:21:34 [INFO] [STDERR] at tlf.HN.common.HideNames.onModInit(HideNames.java:105)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:540)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.Loader.initializeMods(Loader.java:697)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.client.FMLClientHandler.finishMinecraftLoading(FMLClientHandler.java:232)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.client.Minecraft.startGame(Minecraft.java:506)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.client.main.Main.main(Main.java:93)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
Code:
@EventHandler
public void onModInit(FMLInitializationEvent event) {
TickRegistry.registerTickHandler(new CommonTickHandler(), Side.SERVER);
Side side = FMLCommonHandler.instance().getEffectiveSide();
if (side == Side.CLIENT) {
System.out.println("Testing!");
MinecraftForge.EVENT_BUS.register(new HNEventHandler());
}
CommandAPI.addPlayerCommand(new CommandName());
CommandAPI.addPlayerCommand(new CommandNames());
GameRegistry.registerPlayerTracker(new PlayerTracker());
}
package tlf.HN.event;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.client.event.RenderLivingEvent;
import net.minecraftforge.event.ForgeSubscribe;
import tlf.HN.common.HideNames;
public class HNEventHandler
{
@ForgeSubscribe
public void onRenderLiving(RenderLivingEvent event)
{
System.out.println("Testing!");
if (event.entity instanceof EntityPlayerMP)
{
event.setCanceled(!HideNames.instance.hiddenPlayers.get(event.entity.getTranslatedEntityName().toLowerCase()).equalsIgnoreCase("true"));
}
}
}
Well done! I'm glad it worked for you. Just for completeness sake if anyone is wondering, here's an example of a post hook (runs after the method is executed)
Thanks for this tutorial, you made possible my next project
Rollback Post to RevisionRollBack
Custom paintings! My latest project, still in BETA.
A small mod to improve your game, but keeping the vanilla flavour. For Minecraft 1.8.
Also check out my Redstone Jukebox mod, now updated to Minecraft 1.7.10!
Thank you culegooner.
Your tutorial is very useful.
There is a little problem.
I have ClassNotFoundException replacing a big class.
And the cause is InputStream.read( byte[] ) does not read the whole class at once.
It returns the number of bytes actually read which can be smaller than request.
You have to read in a loop using InputStream.read( byte[] b, int off, int len ).
int size = (int) zEntry.getSize();
byte[] newByteArray = new byte[size];
InputStream input = zFile.getInputStream(zEntry);
int pos = 0;
while (pos < size)
{
int readlen = input.read(newByteArray,pos,size-pos);
pos += readlen;
if (readlen == 0)
throw new IOException();
}
ret = newByteArray;
This is a great tutorial, but I'm having trouble installing the Bytecode Outline plugin... I'm using eclipse Kepler - is it not compatible with this newer version of eclipse?
Missing requirement: Bytecode Outline 2.1.0 (de.loskutov.BytecodeOutline.feature.feature.group 2.1.0) requires 'org.eclipse.help.appserver 0.0.0' but it could not be found
There is no harm for its inclusion just not necessary at all
You are entitled to your opinion but i disagree. It appears this goes down to your understanding of what the ASM API is, and what it's an API for. The ASM website says it clearly on the first line "ASM is an all purpose Java bytecode manipulation and analysis framework". It's like saying knowing Forge API doesn't require knowing what Minecraft is, makes no sense to me.
I can't quite get that to work. Thanks
Your best bet is to use the suggestion of the ASM guys themeselves:
"The best way to learn to use ASM is to write a Java source file that is equivalent to what you want to generate and then use the ASMifier mode of the Bytecode Outline plugin for Eclipse (or the ASMifier tool) to see the equivalent ASM code. If you want to implement a class transformer, write two Java source files (before and after transformation) and use the compare view of the plugin in ASMifier mode to compare the equivalent ASM code."
Is a coremod those separate jar files the mods use? Or is it something implemented into the files? If I just read through your guide and watch the video, would it be easy to have a full understanding of it?
:3
Before Minecraft 1.6 there used to be a folder called coremods. The jar files that went into the coremods folder are different than the files that go into the mods folder.
Coremods still exist in 1.6 but now they go directly in the mods folder.
Coremods can be described as special mods that alter the vanilla base class files at runtime.
Think of them as base edits, but instead of copying the .class file into the minecraft.jar file directly, it's done at runtime instead, while minecraft is running.
Using coremods is generally not recommended since it might cause conflicts with other mods because it can change minecraft drastically. There is no limitations to what you can do with them, and that's actually a problem because it means there is no compatibility or standards to follow.
The most famous example of a coremod is NEI.
Yeah it's a great plugin. I just added a section to the tutorial at the end of the coremod section to using both of the ASMifier and javap inside of eclipse if you don't want to use the plugin, or if people are having trouble installing it.
Here's what i'm trying to do so far for the creeperburncore mod.
I deleted my transformer implementation and did the following change to the CBFMLLoadingPlugin file:
That transformer takes care of the xdelta implementation and it tries to patch the files located in the binpatch folder.
For the actual patch what i did is modify the EntityCreeper java file in forge\mcp\src and ran recompile.bat.
Then I ran the forge program cpw.mods.fml.common.patcher.GenDiffSet to generate the binpatch file:
in eclipse the settings in run configuration were the following:
Main class:
Arguments:
Ofcourse i create the binpatch folder in forge/mcp/binpatch
That gave me the file
I created a jar file for my mod and in it I included binpatch/net.minecraft.entity.monster.EntityCreeper.binpatch
but everytime I try and run minecraft forge throws an error and says that the jar is modified
now i can't sleep, i have to figure it out :/
EDIT:
cpw.mods.fml.common.asm.transformers.PatchingTransformer is no friend of mine see next post
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
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 :/
Transformer:
What I'm trying to change:
-tlf
At what point is it failing? can you post the log file?
No idea, unless you show us some code.
-tlf
2 Points
I can't see in the transformer when getTranslatedEntityName is called, you are using
getFontRendererFromRenderManager as your target and that comes later.
you are using
m.instructions.insert(targetNode, toInject);
and that always inserts after the target, to insert before use insertBefore
also this method already has a forge hook assigned to it, so you can override it more cleanly with events, you don't need to coremod it i guess
Old post:
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraftforge.event.EventBus.register(EventBus.java:76)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraftforge.event.EventBus.register(EventBus.java:58)
2013-07-29 16:21:34 [INFO] [STDERR] at tlf.HN.common.HideNames.onModInit(HideNames.java:105)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:540)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:194)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:174)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventHandler.handleEvent(EventHandler.java:74)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.SynchronizedEventHandler.handleEvent(SynchronizedEventHandler.java:45)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatch(EventBus.java:313)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:296)
2013-07-29 16:21:34 [INFO] [STDERR] at com.google.common.eventbus.EventBus.post(EventBus.java:267)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:105)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.common.Loader.initializeMods(Loader.java:697)
2013-07-29 16:21:34 [INFO] [STDERR] at cpw.mods.fml.client.FMLClientHandler.finishMinecraftLoading(FMLClientHandler.java:232)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.client.Minecraft.startGame(Minecraft.java:506)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:796)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.client.main.Main.main(Main.java:93)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
2013-07-29 16:21:34 [INFO] [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
2013-07-29 16:21:34 [INFO] [STDERR] at java.lang.reflect.Method.invoke(Method.java:597)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.launchwrapper.Launch.launch(Launch.java:57)
2013-07-29 16:21:34 [INFO] [STDERR] at net.minecraft.launchwrapper.Launch.main(Launch.java:18)
Code:
-tlf
Well done! I'm glad it worked for you. Just for completeness sake if anyone is wondering, here's an example of a post hook (runs after the method is executed)
https://github.com/micdoodle8/Galacticraft/blob/master/common/micdoodle8/mods/galacticraft/core/client/render/entities/GCCoreRenderPlayer.java
Custom paintings! My latest project, still in BETA.
A small mod to improve your game, but keeping the vanilla flavour. For Minecraft 1.8.
Also check out my Redstone Jukebox mod, now updated to Minecraft 1.7.10!
You're welcome, goodluck on your project.
Your tutorial is very useful.
There is a little problem.
I have ClassNotFoundException replacing a big class.
And the cause is InputStream.read( byte[] ) does not read the whole class at once.
It returns the number of bytes actually read which can be smaller than request.
You have to read in a loop using InputStream.read( byte[] b, int off, int len ).
Missing requirement: Bytecode Outline 2.1.0 (de.loskutov.BytecodeOutline.feature.feature.group 2.1.0) requires 'org.eclipse.help.appserver 0.0.0' but it could not be found