Do not thank us for our patience- it is a slim, wavering thing in the sea of faces. Let us thank you for your patience, your perseverance, and your willingness to make something so intricate to give to the masses.
Also from what I can tell it works, so that's quite nice, too.
- ShneekeyTheLost
- Registered Member
-
Member for 14 years and 3 days
Last active Thu, Nov, 9 2017 20:03:44
- 0 Followers
- 74 Total Posts
- 4 Thanks
-
876
TechGuy543 posted a message on TechGuy's Modding TutorialsPosted in: Mapping and Modding TutorialsMinecraft Forge TutorialsHere are some Minecraft Forge tutorials. I thought it would be better to keep them separate from the ModLoader ones. I'll start off with the basics of Forge like Blocks and such. Ghosrec35 will be doing the advanced/important tutorials.
Main Registry
Your Forge registry class has almost nothing in common with your mod_ class from ModLoader except that it registers everything.
Firstly, just start with the package declaration as usual. You can use your own package but I will just use the default Minecraft source package for this example.
package net.minecraft.src;
Next we need to import a few Forge classes.
import cpw.mods.fml.common.network.NetworkMod; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.Init; import cpw.mods.fml.common.Mod.PostInit; import cpw.mods.fml.common.Mod.PreInit; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent;
All annotations are well explained in ghosrec35's Mod Annotation Interfaces tutorial(below)
The first annotation we will use is the @Mod annotation. We will use it to declare some information about our mod.
@Mod( modid = "ExampleMod", name="ExampleModsName", version="ExampleModVersion")
As an example, I use this in Undead+:@Mod( modid = "UndeadPlus", name="Undead+", version="[1.4.7] v1.0.0")
After you have the @Mod annotation we need to add the @NetworkMod annotation. We use this as well as the @Mod annotation because Forge mods are "universal"(one version for both Client and Server).
@NetworkMod ( clientSideRequired = true, serverSideRequired = true, channels = {"example_mod"}, packetHandler = ExampleModPacketHandler.class )
NetworkMod is explained in ghosrec35's tutorial below. You also need to create a PacketHandler, one is below:
package net.minecraft.src; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import net.minecraft.src.EntityClientPlayerMP; import net.minecraft.src.EntityPlayerMP; import net.minecraft.src.Packet250CustomPayload; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Side; import cpw.mods.fml.common.network.IPacketHandler; import cpw.mods.fml.common.network.Player; public class ExampleModPacketHandler implements IPacketHandler { @Override public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) { if (packet.channel.equals("GenericRandom")) { handleRandom(packet); } } private void handleRandom(Packet250CustomPayload packet) { DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); int randomInt1; int randomInt2; try { randomInt1 = inputStream.readInt(); randomInt2 = inputStream.readInt(); } catch (IOException e) { e.printStackTrace(); return; } System.out.println(randomInt1 + " " + randomInt2); } }
After the @NetworkMod annotation you can declare the class. Note that with Forge, this class doesn't require a mod_ prefix or extend BaseMod.
public class ModUndeadMainRegistry {
We then need to add three methods. They are each called at specific times in the loading of the game. The methods can be called anything as long as they have the Forge annotation and parameter that is required. The first is preInit.
@PreInit public void preInit(FMLPreInitializationEvent event)
This method is called before the mods are loaded.
@Init public void init(FMLInitializationEvent event)
This method has the same function as the load() method is ModLoader. In here is where we will register all of our blocks, recipes, entities, etc.
@PostInit public void postInit(FMLPostInitializationEvent event)
This is the final method that is required in the Forge mod registry. Put stuff that you want to happen after the mods are loaded in here.
Final Code:
package net.minecraft.src; import cpw.mods.fml.common.network.NetworkMod; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.Init; import cpw.mods.fml.common.Mod.PostInit; import cpw.mods.fml.common.Mod.PreInit; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; @Mod( modid = "ExampleMod", name="ExampleModsName", version="ExampleModVersion") @NetworkMod ( clientSideRequired = true, serverSideRequired = true, channels = {"example_mod"}, packetHandler = ExampleModPacketHandler.class ) public class ExampleMod { @PreInit public void preInit(FMLPreInitializationEvent event) { } @Init public void init(FMLInitializationEvent event) { } @PostInit public void postInit(FMLPostInitializationEvent event) { } }
Mod Annotation InterfacesBy ghosrec35
package ghosrec35.mods.example.common; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.IMCCallback; import cpw.mods.fml.common.Mod.Init; import cpw.mods.fml.common.Mod.Instance; import cpw.mods.fml.common.Mod.PostInit; import cpw.mods.fml.common.Mod.PreInit; import cpw.mods.fml.common.Mod.ServerStarted; import cpw.mods.fml.common.Mod.ServerStarting; import cpw.mods.fml.common.Mod.ServerStopping; import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLInterModComms; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLServerStartedEvent; import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; import cpw.mods.fml.common.network.NetworkMod; import cpw.mods.fml.common.network.NetworkMod.SidedPacketHandler; @Tutorial("Annotation Interfaces within Forge") @Mod(modid = "Ghosrec35_ExampleMod", name = "ExampleMod", version = "1.0.0.0", dependencies = "after:UniversalElectricity") @NetworkMod(clientSideRequired = true, serverSideRequired = false) public class ExampleMod { @SidedProxy(clientSide = "ghosrec35.mods.examplemod.client.ClientProxy", serverSide = "ghosrec35.mods.examplemod.common.CommonProxy") public static CommonProxy proxy; @Instance("Ghosrec35_ExampleMod") public ExampleMod instance; @PreInit public void loadPre(FMLPreInitializationEvent event) { } @Init public void load(FMLInitializationEvent event) { } @PostInit public void loadPost(FMLPostInitializationEvent event) { } @ServerStarting public void serverStarting(FMLServerStartingEvent event) { } @ServerStarted public void serverStarted(FMLServerStartedEvent event) { } @ServerStopping public void serverStopping(FMLServerStoppingEvent event) { } @IMCCallback public void interModComms(FMLInterModComms event) { } }
Understanding the CodeForge ModLoader and the MinecraftForge API include many different Annotation Interfaces that allow us to create methods within our main mod file that are able to be invoked from outside files without editing base classes. This is achieved by first Annotating the said mod file with the @Mod and @NetworkMod Annotation Interfaces which originally registers these certain files with Forge ModLoader.- The @Mod annotation requires three parameters, modid which must be equivalent to a String, name which must be equivalent to a String, and version which must be equivalent to a String. Now this main mod file is able to contain other Annotation Interfaces located within the Mod.java located in the cpw.mods.fml.common package.
- The First of these methods introduced by the Mod.java is the @Instance annotation. This Annotation Interface Targets ElementTypes of the type Field, and so we annotate a public field of the type our mod file. This Annotation contains a value() of type String which is to be equivalent to your mod file's modid. This Annotation is then used to populate the field of which it annotates with the instance of your Mod File.
- The rest of the Annotations derived from the Mod.java do not require such a level of complexity.
- The first of these methods is the @PreInit Annotation which must Annotate a method with a parmeter of the type FMLPreInitializationEvent. This allows Forge ModLoader to perform two checks (The first being that this is the method designated for Pre-Initialization and the second being that the method again is designated for Pre-Initialization, but also that when invoked the method is able to retrieve information and perform tasks available from the instance of the PreInitEvent which is passed to the method upon its invocation.)
- The next Annotation is the @Init annotation which must Annotate a method with a parameter of the type FMLInitializationEvent. This Annotation works in the same way as @PreInit, except the method is invoked after the Pre Initialization methods of all mods are invoked. This allows for such things as configuration files to be created and for settings to be loaded and saved before other processes begin within the Mod. (Of course, any fields created and initialized will actually be run before the PreInit method as this occurs upon the loading of the Class itself.) The @Init method is run at the normal time of Block Registration, Recipe Registration, etc, to occur within Minecraft.
- The next Annotation is the @PostInit annotation interface, which must annotate a method with a parameter of FMLPostInitializationEvent. This method is invoked after both the @PreInit and @Init Annotated methods are invoked for each and every mod being loaded. These methods allow for easy manipulation of Minecraft and the many Blocks/Items/ and other things that have been introduced by your mod. This method is commonly called modsLoaded, as it occurs after all the mods have been loaded.
- The next Annotation is the @ServerStarting Annotation. This Annotation yet again annotates a method, but this Annotation must annotate a method with a parameter of the type FMLServerStartingEvent. This method allows for the Manipulation of the server while the server is in the process of initializing all its files.
- The next Annotation is the @ServerStarted Annotation, which annotates a method with a parameter of the type FMLServerStartedEvent. This method allows for easy manipulation of the Server after the server has been started, and is currently running.
- The next Annotation interface us the @ServerStopping annotation which annotates must annotate a method with a parameter of the type FMLServerStoppingEvent. This Annotation allows for the invocation of this method to allow for manipulation of the server while the server is stopping.
- The final Annotation I will be discussing is the @IMCCallback Annotation. This Annotation annotates a method with a parameter of the type FMLInterModComms. This allows your mod to send messages to other mods by the use of the Mods' modid and a key-value pairing. The next step is to move on to the NetworkMod annotation interface which continues on with much of the more complicated annotations.
NetworkMod and Associated Annotation InterfacesBy ghosrec35
The first thing to note is that there are only two attributes that are required with the @NetworkMod annotation.
@NetworkMod(clientSideRequired = true, serverSideRequired = false)
Both attributes must equal boolean values. These values determine whether a player is allowed to join a server or not. clientSideRequired should almost always be true, and serverSideRequired should almost always be false. clientSideRequired determines whether the client side of the mod must be installed for a player to join a server with the mod installed, while serverSideRequired determines whether the server side must be installed for the client to be able to join it.
We set clientSideRequired to true almost always because there are very few occassions in which nothing client side would be required for a mod.
We set serverSideRequired to false almost always because we will still want users to be able to join their favorite servers even if the server does not have the mod installed.
There are other attributes that are available for usage. These are channels, packetHandler, tinyPacketHandler, and connectionHandler. There are two more, but I will wait to discuss these until finished with the first three.
The channels attribute must be equivalent to an Array of Strings. This array will contain the Channels that will be automatically registered for your mod.
For Example:
@NetworkMod ( clientSideRequired = true, serverSideRequired = false, channels = {"Channel"} )
DON'T register channels so generic as the one used in this tutorial. Always try to use channel names that are unique and original.
The packetHandler attribute must be equivalent to a class that implement IPacketHandler.
For Example:
@NetworkMod ( clientSideRequired = true, serverSideRequired = false, channels = {"Channel"}, packetHandler = PacketHandler.class )
Any Packets that are sent using the channels you registered in the channels attribute will be sent to this PacketHandler.
The connectionHandler attribute must be equivalent to a class that implements IConnectionHandler.
For Example:
@NetworkMod ( clientSideRequired = true, serverSideRequired = false, channels = {"Channel"}, packetHandler = PacketHandler.class, connectionHandler = ConnectionHandler.class )
The IConnectionHandler interface forces the ConnectionHandler class to override a few different methods that allow you to handle certain events with a player when they're connecting. Some more information on this in a future tutorial.
The tinyPacketHandler attribute must be equivalent to a class that implements ITinyPacketHandler. This works just like a regular PacketHandler, but for smaller packet sizes.
Final NetworkMod annotation so far:
@NetworkMod ( clientSideRequired = true, serverSideRequired = false, channels = {"Channel"}, packetHandler = PacketHandler.class, connectionHandler = ConnectionHandler.class, tinyPacketHandler = TinyPacketHandler.class )
Before we get to the final two attributes, it's important to note again that you only NEED the clientSideRequired and serverSideRequired attributes to run your mod. The rest are only required for things like SMP or Connection Handling.
The final two attributes are a little trickier than the rest. They are clientPacketHandlerSpec and serverPacketHandlerSpec.
These attributes allow you to define separate packet handling classes and channels for both the Server and Client Side. You may use these rather than defining the channels and packetHandler attributes.
Each must be equivalent to an @SidedPacketHandler annotation. We are then able to use the attributes of the @SidedPacketHandler Annotation to further define each. The two attributes are channels, and packetHandler. These attributes function the same as they do above, but when used in an @SidedPacketHandler annotation only register the information with one side of Minecraft.
For Example:
@NetworkMod ( clientSideRequired = true, serverSideRequired = false, connectionHandler = ConnectionHandler.class, clientPacketHandlerSpec = @SidedPacketHandler ( channels = {"ClientChannel1", "ClientChannel2"}, packetHandler = ClientPacketHandler.class ), serverPacketHandlerSpec = @SidedPacketHandler ( channels = {"ServerChannel1", "ServerChannel2"}, packetHandler = ServerPacketHandler.class ) )
The next NetworkMod related annotation is the @SidedProxy annotation. @SidedProxy has a Target of the ElementType FIELD, meaning it must annotate a field. For our example, we are going to create a field of the type CommonProxy.
@SidedProxy(clientSide = "ghosrec35.mods.examplemod.client.ClientProxy", serverSide = "ghosrec35.mods.examplemod.common.CommonProxy") public static CommonProxy proxy;
The two attributes of the @SidedProxy annotation are clientSide and serverSide. These two values are equivalent to String values and will contain the file path (including your package path) to your two separate proxies. More on this later.
You must create a file that will be your CommonProxy (Conventionally, this is usually called CommonProxy), and then you must create another file that will extend CommonProxy which will be your ClientProxy (Conventionally, this is usually called ClientProxy).
The @SidedProxy annotation requires the path to your ClientProxy and CommonProxy, as it automatically populates the proxy field of type CommonProxy with whichever proxy is designated for whichever side. This means that when invoking any methods, you must ensure that both the Client and Common Proxy contain the methods so that no exceptions occur during runtime on either the Server or Client. Proxys are used for such things as preloading textures, as you are able to register rendering information on only the client side by including the render methods in only the client proxy. The ClientProxy must extend the CommonProxy so that you are able to populate the field of the type CommonProxy with your ClientProxy as well.
The final @NetworkMod associated Annotation is the @SideOnly Annotation.
The @SideOnly annotation requires a value of the type Side, which is an enumeration containing the values CLIENT, SERVER, and BUKKIT. Annotating a field with @SideOnly ensures that the method is only run on the designated side. For instance, the vanilla Minecraft code has been edited throughout with@SideOnly(Side.CLIENT)
over certain methods that are used for Client only details such as Rendering or Sound.
Thank you to the following people who have really assisted me well with helping people while I am absent. There are many others who have helped but these are the main ones who keep returning and giving great help to countless amounts of people.Thank-you
- ghosrec35 - ghosrec35 has written the Forge tutorials.
- -Reaper-
- KoadMaster
- PhantomJedi759
- ZeroLevels
- StangeOne101
- Zildjian97
- NukeAndBeans
- Dragonphly77
- To post a comment, please login.
1
I have a minor mod incompatibility issue. Apparently Candleberry seeds are seedCandleberry but the candleberries themselves are cropCandle which means Agricraft doesn't pick it up and thinks that candleberries actually have no fruit at all. Can this please be fixed in your next bughunt update?
1
I would like to inform you that I am using this mod in a private pack that is not to be released publicly.
Also, as a feature request, could you set up a way to have the book stationary, such as a bookstand or something, and it gives you the option to warp to whichever of the pages is in that book? Yes, the idea is similar to Mystcraft, however additional dimensions makes the server cry. All I want is a way for my group to get back and forth from the nether/end without having to use the portals and maybe set up a warp nexus.
1
The PRC is an insanely powerful and awesome device, however it has WAY more functionality than is needed for many small tasks. For example, sometimes, you just want a timer sending pulses every so often. Having to build an entire PRC for this function is expensive, you're blowing diamonds on a simple timer!
What I propose is to have 'logic gates', similar in concept to the Memory Card, except it can only store a single 'page'. You have to program the Logic Circuit at the PRC (so you still have to have one somewhere) with that page, which can then not be edited further, you have to wipe it (combine itself in a crafting square to make a blank version) and re-program it in the PRC to alter it. Then you combine the logic Circuit with the Housing to create the Logic Gate that can then be placed anywhere. Right-Clicking on a Logic Gate spits out the circuit and returns the Housing. Alternately, crafting the logic gate by itself returns the blank Logic Circuit and destroys the housing.
Reasoning: Look at RP2's Logic Gates, they're fairly inexpensive, mostly redstone, stone, and some sticks. Sometimes, you don't want to control eight different subsystems, you just want a simple timer on your blockbreaker or an AND gate on your nuclear reactor for failsafe kill-switches. And I think requiring diamonds for that functionality is probably a bit much.
1
1
Technic should never have put his mod into the pack without his PRIOR permission. Having already pissed him off by ripping his stuff off and bundling it together, you honestly expect him to grant permission NOW?
When they didn't remove the mods they didn't have permission to include, they indicated that they didn't care about intellectual property.
Sengir didn't need to say a damn thing, because nothing needed to be said. Without a 'yes', the default answer is 'no'. He had the maturity and responsibility to not feed more fuel into the fire by refusing to discuss it any further. Sadly, he was the only one around with such restraint.
Since they refused to remove his mod, the only thing left for him to do for his wish to not be included was to code his mod to be explicitly non-compatible. Which he did. Mad props to that.
Magic Loader and, particularly, MultiMC give all the functionality and ease of the Technic Pack, but without the whole 'violation of Intellectual Property rights' thing. It requires user-level knowledge of computers to drag and drop a file into a folder. If you cannot accomplish this task, you don't need to be at a computer. It really is that simple.
Now then, I'd like to agree that Vis and Taint Bees for ThaumCraft2 would be insanely awesome, but would have to be carefully managed. It's relatively difficult to significantly increase the local Vis levels after a point (now that ambient crystals only increase it by so much), so to have vis bees have as an environmental effect to increase the aura might be unbalancing. There's also the matter of what they would produce. Would they produce a substance which has a higher vis content when thrown into a crucible? Would the highest level of vis bee have a chance of producing a (biome-weighted) random crystal? Could some of the products they make count as common artifacts to be researched?
It would take some work to figure out what they could do and how to balance it properly, but I am wholeheartedly supporting the theory. Time to put it in the Q-block surrounded by brains in a jar until we come up with a Discovery!
1
I salute you, good sir.
Also, did you get the sewers set up? Those pallies have to get to their guild somehow, yanno :tongue.gif:
Just as a random thought... if we got a bunch of us together on a SMP server, we could probably recreate pre-Kunark EQ. It'd take a *LOT* of time and effort, which is why I say SMP, but I think it could be done.