I am trying to add a method to a Minecraft source file, but I have to figure out how to do it without actually editing the source files, since it is illegal to redistribute source files which would have to be included in the mod I am creating. I need to add the method setInPortalZub()
to the file "EntityPlayer located in net.minecraft.entity.player
. I am using the MCP / Minecraft Forge API. I have tried creating an instance of EntityPlayer
, but I'm not exactly sure how that would work.
You are about to enter the wonderful and frustrating world of coremods! Coremods in FML (Forge ModLoader) are the "easiest" way to inject arbitrary code into vanilla Minecraft classes without having to distribute modified versions of those class files.
This is accomplished by utilizing the ASM Bytecode manipulation framework released by Object
Web. This framework allows you to write java code that can read and manipulate the bytecode of a class at load time.
It is impossible for me to explain every step you must take to accomplish this feat, so instead I will post links to my own coremod injection classes and attempt to give an explanation of each.
Here is the CorePlugin
class.
The CorePlugin
class tells Forge ModLoader where to find your transformer class that does the actual code injection.
This class is found by FML based on your .jar
file manifest:
Manifest-Version: 1.0
FMLCorePlugin: bspkrs.treecapitator.fml.asm.TreeCapitatorCorePlugin
FMLCorePluginContainsFMLMod: bspkrs.treecapitator.fml.TreeCapitatorMod
Created-By: 1.7.0 (Oracle Corporation)
FMLCorePlugin
specifies the fully qualified path to your CorePlugin class. If your .jar
file is to contain a regular @Mod
style Forge ModLoader mod class as well you will also need to specify FMLCorePluginContainsFMLMod
(although the expected value is unknown; I don't think it actually matters what you put for the value there, but the key must be there).
Now for the fun part... the actual bytecode transformer. Here is a link to the transformer for Treecapitator
Without going into too much detail, I wrote this class to be able to handle execution both in Eclipse as well as in "production". That's why there are two HashMap
s; one for MCP execution and one for obfuscated execution. Every class that gets loaded is first passed into the transform()
method. The code checks to see if it's a class we want to transform and transforms it if it is.
The end result of implementing all this is that whenever an instance of ItemInWorldManager
is created the transformer runs and adds a single line to a specific location within the removeBlock()
method. This single line serves as a cheap block break hook to allow for code to execute when a player breaks a block.
Tips:
I hope that helps!
EDIT: fixed the broken links to reference an old branch that still contains the classes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With