Minecraft Forge Tutorials
Here 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 Interfaces
By 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 Code
Forge 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 Interfaces
By 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
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.- ghosrec35 - ghosrec35 has written the Forge tutorials.
- -Reaper-
- KoadMaster
- PhantomJedi759
- ZeroLevels
- StangeOne101
- Zildjian97
- NukeAndBeans
- Dragonphly77
12
I have decided that for too long trekkies have not had a minecraft mod! I will make that mod. This mod will be developed by a team (U.S.S Modder). The team is currently:
Captain:
Captain doctor82
First Officer:
Commander 89Mods
Medical(Coders):
Commander 89Mods
Engineering (Textures):
Lt Cmdr CubedCraftingMan
Science (Modelers)
Lt Cmdr Spencerthelizard
We are looking for anyone willing to help out. An very experienced coder would be a great help though.
Pm me/Post below if you are interested in joinin
1
I think I will try to make it as generic as possible but will, when nessecary base it off TOS
1
People don't understand time. It's not what you think it is. … People assume that time is a strict progression of cause to effect... but actually, from a non-linear, non-subjective viewpoint, it's more like a big ball of wibbly-wobbly... timey-wimey... stuff.
2
2
1
The aim of this challenge is to make a city but instead of slowly building a medieval or modern city like many Tekkit challenges
you will start from a stone age camp ending with a modern city.
In many levels there are item requirements that use the format ([number]xP). in this P is the number of players eg (2xP) means 2 of this iteare needed for one player, 4 for 2, 6 for 3 ect
Every few levels there is an sognificant event. They will hepave various effects that last until specified. Any updates during levels is maked with [Event:(EventName)] then the change.
Changelog:
Alpha 1.0 - Created challenge
Alpha 2.0 - Added Stage 2
Alpha 3.0 - Added Stage 3
Alpha 3.5 - Added Maggot Infestation
You cannot mine without a helmet
You must mine in a 3x3 tunnel or staircase with support beams every 10 blocks (cave do not have to be supported, as they are natural)
You must build paths between all buildings as you make them to progress in a stage
You may use things you find in villages, chests, or from rare mob drops (excluding ingots) that you are not allowed to create yet
Play on any difficulty you wish (including peaceful)
Rotten Flesh does not count as food to meet food need in stages, however it still may be eaten.
Items that need to be in the Treasury or Research Center must stay in the Treasury or Research Center (Well, at least in the Research Center until it is not needed there any more). If for any reason you need to take some out, they must be replaced in order to complete the stage. Items that are needed but not for Treasury or Research Center may be used after stage is complete without any penalty.
You Must follow all rules and restrictions for every stage!
No Cheating or using mods or Texture-Packs like X-ray!
Only play challenge in Tekkit Mod Pack (NO TECHNIC! This challenge was not designed for it, as it has mods that are not in Tekkit.)
You May do this Multi-Player, but all players must have a home of their own
Lvl 1: Pre-Stone age
Story:
You must create the foundations of your city in order to begin colonization, but it appears this place is not as desolate as it first seemed.....
Restrictions:
Restrictions:
No use of any blocks of any block you need a pickaxe to mine (excluding Coal)
Only Wooden Tools Allowed
No crafting anything from mob drops (excluding bone to bonemeal)
Need To Progress:
Build a house with:
A front door
A Living Area
A seperate bedroom (with bed)
A fenced off farm with:
(10xP) Wheat
(2xP) Flax
Items Required:
(1xP) Stacks of planks or (16xP) logs
(5xP) Food
(1xP) Leather Helmets
Lvl 2: Stone Age:
Story:
Your tribe is rapidly expanding and have discovered stone. You must upgrade you camp to make room for the expanding population
Restrictions:
No Building with Stone/Sandstone/Marble
No Modded Items (except Sickle)
No Smelting/using Ingots
Need To Progress:
Build 2 more houses with:
A front door
A Living Area
A seperate bedroom (bed not needed)
Build Elders House with:
A Front door
A Chest (the treasury)
Up grade farm to having:
(20xP) Wheat
(8xP) Flax
(3xP) Sugar Cane
Mine 10 blocks deep
Items Required:
(1xP) Full sets of stone tools (Hoe, Sword, Sickle, Pick, Axe, Shovel)
Lvl 3: Bronze age:
Story:
Your tribe has discoved the fact that if you put ore in a furnace you smelt it and has discovered bronze.
Restrictions:
You can only use tin and copper for smelting bronze.
No making machines
No using mods other that ic2 and weapons mod but only for tools
No building with stone
Need To Progress:
Build a small blacksmith's house with:
Front Door
Living Area
Seperate bedroom
Seperate work area in front connected to the living area by a door
A furnace in the work area
Build a tribal barracks with:
A training room with a dummy in it
A storage room with a chest with an Bronze Sword in it
Items Required:
(1xP) Bronze Sword
(1xP) Bronze Chestplate
Significant Event: Maggot Infestastion
For the first day you must collect as much wheat as possible. From then on the wheat not stored is infested with maggots so can't be harvested.
To Be Continued...