With Forge being incompatible with ModLoaderMP, someone should better write a tutorial on how to make your mod compatible with Forge's NetworkMod. Here we go!
First things first: DO NOT PM ME WITH PROBLEMS YOU MIGHT HAVE
ASK IN THE FORGE IRC CHANNEL
POKE LEXMANOS AND CPW
esper.net/#minecraftforge
You should not have any mods installed in the jars you decompile in order to not get bugs with Forge source patches. However it might be wise to pre-install TooManyItems (or install NotEnoughItems from it's sourcecode afterwards, and use updatemd5) because creative mode is sort of painful for testing.
Step 2 : Decompile, install Forge sources
Head to your MPC/Forge/ folder and execute the install file. Forge should now do the rest by itself, and you end up with a fully decompiled client and server mcp forge setup.
If there are any issues here (there might), see if you can fix the code problem yourself. If you can, run "updatemd5" after fixing the sources to compile, and proceed with step 3.
Same goes for APIs (Industrialcraft, Buildcraft, any major mod...) or other mods that you need included. Put them in now, run updatemd5 so they get excluded from your reobfuscations.
Step 3 : Add old MLMP mod source to new MCP
If your mod was previously made to work with ModLoaderMP, you can port it to work with Forge's NetworkMod instead. There are several changes you need to make.
1. Go into your "mod_MODNAME.java" file and change
extends BaseModMp
to
extends NetworkMod
this will also require you import forge, so why don't we add this on top
import net.minecraft.src.forge.*;
2. Override methods
NetworkMod extends BaseMod, which means most of your old MLMP Overrides (assuming your source is MC 1.2.3 or newer) should just keep working. The one thing NetworkMod has different are these methods, which you should add now:
@Override
public boolean clientSideRequired()
{
return true;
}
@Override
public boolean serverSideRequired()
{
return false;
}
Their meaning should be obvious. clientSideRequired determines if a server with the mod allows clients without it to connect, serverSideRequired if a client can join a server without the mod. In the words of cpw: "For crying out loud do not force serverSideRequired()"
In general, just open up /forge/MinecraftForge.java and see what it has to offer you.
4. Entities
To fix Entities to work with Networkmod, you need to make sure
is present. LexManos tells me the ID should be irrelevant, to be on the safe side however pick some unique number, as you did with MLMP. If your Entity is a Mob, you should not have to change anything from MLMP.
You _can_ leave this line away and still create your Entities, however your Entities will not be saved/loaded upon client/server shutdown and restart.
4.b other, non-Mob Entities
The ModLoaderMp.registerHandler/Tracker methods for client and server need to be replaced with
/**
* Registers a Entity class tracking information. Used for sendingEntity
* information over the network.
*
* @param entityClass The class for the Entity
* @param mod The BaseMod that provides this Entity.
* @param ID The ID for the Entity. Needs to be unique combination of Mod and ID <128
* @param range How close a player has to be to be informed this Entity exists.
* @param updateFrequency How many ticks between checking and sending information updates for this Entity.
* @param sendVelocityInfo If velocity information should be included in the update information.
* @return True, if successfully registered. False if the class is already registered.
*/
public static boolean registerEntity(Class entityClass, NetworkMod mod, int ID, int range, int updateFrequency, boolean sendVelocityInfo)
on both client and server.
5. GUI
in your client mod_ file, you need to replace
ModLoaderMp.RegisterGUI(this, guiID);
on the server side, you replace
public GuiScreen HandleGUI(int inventoryType)
{
if(inventoryType == guiID)
return new Gui_____(args);
else return null;
}
your Networkmod (or another class you specify here) needs to implement IGuiHandler:
public interface IGuiHandler
{
/**
* Returns a Container to be displayed to the user.
* On the client side, this needs to return a instance of GuiScreen
* On the server side, this needs to return a instance of Container
*
* @param ID The Gui ID Number
* @param player The player viewing the Gui
* @param world The current world
* @param x X Position
* @param y Y Position
* @param z Z Position
* @return A GuiScreen/Container to be displayed to the user, null if none.
*/
public Object getGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z);
}
and having done all that, your GUIs should work. You can open them using this method Forge adds into EntityPlayer
/**
* Opens a Gui for the player.
*
* @param mod The mod associated with the gui
* @param ID The ID number for the Gui
* @param world The World
* @param x X Position
* @param y Y Position
* @param z Z Position
*/
public void openGui(BaseMod mod, int ID, World world, int x, int y, int z)
6. Custom Packets
Packets are by far the most difficult to port, mainly because MLMP had such a rigid implementation and Forge doesn't. To make your NetworkMod use packets, you need to:
Implement the related Interfaces in your NetworkMod
implements IConnectionHandler, IPacketHandler
Register your NetworkMod or whatever class you put it in with Forge for the connection handler
Override the methods the Interfaces specify, and make sure to register a packet channel for your packets with a name of your choice.
Note that onLogin fires on server BEFORE onLogin on client, so if you want to send packets to the client in there already, make sure the client side registers his channel in the onConnect callback.
@Override
public void onConnect(NetworkManager network)
{
}
@Override
public void onLogin(NetworkManager network, Packet1Login login)
{
MessageManager.getInstance().registerChannel(network, this, "channelname");
}
@Override
public void onDisconnect(NetworkManager network, String message, Object[] args)
{
}
@Override
public void onPacketData(NetworkManager network, String channel, byte[] data)
{
// HANDLE INCOMING PACKET DATA HERE
}
Now. We are all set up, now how to send and receive packets?
Here is an example of the Nether Ores Mod, at the sending(server) end:
public static void causeFuseSoundAt(World world, int i, int j, int k)
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
DataOutputStream data = new DataOutputStream(bytes);
try
{
int[] coords = {i, j, k};
for(int a = 0; a < 3; a++)
{
data.writeInt(coords[a]);
}
}
catch(IOException e)
{
e.printStackTrace();
}
Packet250CustomPayload packet = new Packet250CustomPayload();
packet.channel = "mod_NetherOres"; // CHANNEL MAX 16 CHARS
packet.data = bytes.toByteArray();
packet.length = packet.data.length;
ModLoader.getMinecraftServerInstance().configManager.sendPacketToAllPlayers(packet);
}
Here is an example of the Nether Ores Mod, at the receiving end:
@Override
public void onPacketData(NetworkManager network, String channel, byte[] bytes)
{
DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(bytes));
int coords[] = new int[3];
try
{
for(int i = 0; i < 3; i++)
{
coords[i] = dataStream.readInt();
}
}
catch(IOException e)
{
e.printStackTrace();
}
causeFuseSoundAt(ModLoader.getMinecraftInstance().theWorld, coords[0], coords[1], coords[2]);
}
If you want to see a more in-depth example (with custom packet classes and packaging) check out Buildcraft's implementation, to be seen here http://buildcraft.tr...work?order=name
will get you the player that sent the packet you are trying to process.
To send a packet from clientside to server the easiest way is to just use ModLoader.sendPacket.
Another hint:
If you get a "String length less than zero, wierd String!" client crash message, your packet channel has a name with >16 chars. It is limited to 16 chars. Do not use more than 16 chars.
7. Recompile
Now recompile and make sure it works. If your mod worked with MLMP previously, these steps *should* cover all necessities.
You should not have any mods installed in the jars you decompile in order to not get bugs with Forge source patches. However it might be wise to pre-install TooManyItems (or install NotEnoughItems from it's sourcecode afterwards, and use updatemd5) because creative mode is sort of painful for testing.
Step 2 : Decompile, install Forge sources
Head to your MPC/Forge/ folder and execute the install file. Forge should now do the rest by itself, and you end up with a fully decompiled client and server mcp forge setup.
If there are any issues here (there might), see if you can fix the code problem yourself. If you can, run "updatemd5" after fixing the sources to compile, and proceed with step 3.
Same goes for APIs (Industrialcraft, Buildcraft, any major mod...) or other mods that you need included. Put them in now, run updatemd5 so they get excluded from your reobfuscations.
Step 3 : Add old mod source to new MCP, both on client and server side
There are several changes you need to make on both sides.
To start off, you can delete all Render, Model, GUI and TextureFX classes. Server doesnt need them. Also delete references to those.
1. Go into your "mod_MODNAME.java" file and change
extends BaseMod
to
extends NetworkMod
this will also require you import forge, so why don't we add this on top
import net.minecraft.src.forge.*;
2. Override methods
NetworkMod extends BaseMod, which means most of your old ML Overrides (assuming your source is 1.2.3 or newer) should just keep working. The one thing NetworkMod has different are these methods, which you should add now:
@Override
public boolean clientSideRequired()
{
return true;
}
@Override
public boolean serverSideRequired()
{
return false;
}
Their meaning should be obvious. clientSideRequired determines if a server with the mod allows clients without it to connect, serverSideRequired if a client can join a server without the mod. In the words of cpw: "For crying out loud do not force serverSideRequired()"
In general, just open up /forge/MinecraftForge.java and see what it has to offer you.
4. Entities
To fix Entities to work with Networkmod, you need to replace
LexManos tells me the ID should be irrelevant, to be on the safe side however pick some unique number, as you would with MLMP.
You _can_ leave this line away and still create your Entities, however your Entities will not be saved/loaded upon client/server shutdown and restart.
[Note: this constructor is no longer mandatory, as of forge #84. The standard (World world) constructor will do.]
You also need to make sure your Entity class has a constructor
public ENTITYCLASS(World world, double x, double y, double z) {...}
since that is the one NetworkMod uses to spawn Entities. Make sure to use setLocation with the xyz values, because they will not be updated on the client until the Entity moves.
4.b other, non-Mob Entities
If your Entity is not a Mob you need to register a tracker using this MinecraftForge method
/**
* Registers a Entity class tracking information. Used for sendingEntity
* information over the network.
*
* @param entityClass The class for the Entity
* @param mod The BaseMod that provides this Entity.
* @param ID The ID for the Entity. Needs to be unique combination of Mod and ID.
* @param range How close a player has to be to be informed this Entity exists.
* @param updateFrequency How many ticks between checking and sending information updates for this Entity.
* @param sendVelocityInfo If velocity information should be included in the update information.
* @return True, if successfully registered. False if the class is already registered.
*/
public static boolean registerEntity(Class entityClass, NetworkMod mod, int ID, int range, int updateFrequency, boolean sendVelocityInfo)
on both client and server.
5. GUI
you need to get your client GUI opening methods into this format
/**
* Opens a Gui for the player.
*
* @param mod The mod associated with the gui
* @param ID The ID number for the Gui
* @param world The World
* @param x X Position
* @param y Y Position
* @param z Z Position
*/
public void openGui(BaseMod mod, int ID, World world, int x, int y, int z)
Also this needs to be called somewhere before, in your mod_ file:
your Networkmod (or another class you specify here) needs to implement IGuiHandler:
public interface IGuiHandler
{
/**
* Returns a Container to be displayed to the user.
* On the client side, this needs to return a instance of GuiScreen
* On the server side, this needs to return a instance of Container
*
* @param ID The Gui ID Number
* @param player The player viewing the Gui
* @param world The current world
* @param x X Position
* @param y Y Position
* @param z Z Position
* @return A GuiScreen/Container to be displayed to the user, null if none.
*/
public Object getGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z);
}
and having done all that, your GUIs should work.
6. Custom Packets
See post above.
7. Recompile
Now recompile and make sure it works. Fix problems as you see fit. You will probably have to fix more things on client by checking for world.isRemote before setting any fields (because if you are on a server, the server does this).
Good stuff, even though most of the credit goes to Flan. You won the award for getting your tutorial out first so everyone goes to yours. But really, it helped a lot.
There's only one thing i'm confused about(I'm probably just reading this too fast):
clientSideRequired determines if a server with the mod allows clients without it to connect, serverSideRequired if a client can join a server without the mod
but to me it sounds like you're saying the exact same thing twice
FMl is incompatible with MLMP
MLMP actually did NOT update quickely, it never has, and it never has done a proper update.
Hence the need for FML
From the point of view of the modder using FML will actually be EASIER then using MLMP due to the fact that it will acuratly emulate the ML api as MLMP should of always been doing.
You will need to adjust away from any MLMP specific things you are using, but honestly the bulk of that will be to change from BaseModMP to BaseMod, and to strip out any calls to ModLoaderMP.*
There's only one thing i'm confused about(I'm probably just reading this too fast):
but to me it sounds like you're saying the exact same thing twice
Yeah read it more closely:
clientSideRequired: can a client without the mod connect to the server with the mod?
serverSideRequired: can a client with the mod connect to a server without the mod?
yes you are right then it could be interpreted that way but really it could say it either way
serverSideRequired if a client can join a server without the mod
could be saying if a client, which does not have the mod, can join a server
or if a client can join a server that does not have the mod
so i think technically we're both right
Thank you Atomic, although I'm still a bit miffed how one converts a SSP mod into SMP but I'll learn one day
I know that it should be a lot easier with Forge, But i'm not up to speed yet
If you follow flan's tutorial first (you will get errors), then this tutorial, it's a breeze
Yah, I'd like to know this too. You could probably approximate it with a boolean though, just use an onUpdate/onTickInGame method to check whether it's pressed. But does anyone really understand the GUIs? I need to know how to register the individual GUIs, but right now all I can guess at is this:
public void MakeGUIs()
{
/* //THE SECOND PARAMETER IS AN INT USED TO IDENTIFY THE GUI
ModLoaderMp.registerGUI(this, biomeBusterGUI);
ModLoaderMp.registerGUI(this, c4GUI);
ModLoaderMp.registerGUI(this, hBombGUI);
ModLoaderMp.registerGUI(this, megaNukeGUI);
ModLoaderMp.registerGUI(this, napalmGUI);
ModLoaderMp.registerGUI(this, novaGUI);
ModLoaderMp.registerGUI(this, nukeGUI);
ModLoaderMp.registerGUI(this, preciseTNTGUI);
ModLoaderMp.registerGUI(this, stickyTNTGUI);
ModLoaderMp.registerGUI(this, volcanoGUI);
ModLoaderMp.registerGUI(this, creeperGUI);
*/
MinecraftForge.setGuiHandler(this, this);
}
@Override
public Object getGuiElement(int inventoryType, EntityPlayer player, World world,
int x, int y, int z)
{
if(inventoryType == nukeGUI)
return new GuiExplosivesPlusConfigNuke(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == megaNukeGUI)
return new GuiExplosivesPlusConfigMegaNuke(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == napalmGUI)
return new GuiExplosivesPlusConfigNapalm(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == preciseTNTGUI)
return new GuiExplosivesPlusConfigPreciseTNT(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == stickyTNTGUI)
return new GuiExplosivesPlusConfigStickyTNT(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == c4GUI)
return new GuiExplosivesPlusConfigC4(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == hBombGUI)
return new GuiExplosivesPlusConfigHBomb(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == biomeBusterGUI)
return new GuiExplosivesPlusConfigBiomeBuster(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == novaGUI)
return new GuiExplosivesPlusConfigNova(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == volcanoGUI)
return new GuiExplosivesPlusConfigVolcano(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
if(inventoryType == creeperGUI)
return new GuiExplosivesPlusConfigNuclearCreeper(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance());
else return null;
}
...
Check this "Jump Key" packet construction i made for MoCreatures SMP
...
Thanks for posting that, AtomicStryker! It was greatly helpful for me to see an example of a packet going the other direction, where the server has to know which player it's coming from.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumHeavily based off Flan's MLMP Tutorial
http://www.minecraft...modding-310511/
With Forge being incompatible with ModLoaderMP, someone should better write a tutorial on how to make your mod compatible with Forge's NetworkMod. Here we go!
First things first: DO NOT PM ME WITH PROBLEMS YOU MIGHT HAVE
ASK IN THE FORGE IRC CHANNEL
POKE LEXMANOS AND CPW
esper.net/#minecraftforge
Step 1 : Install MCP with Forge
USE A NEW MCP FOLDER
http://mcp.ocean-lab...hp/MCP_Releases
Aquire latest Forge build and install into your MCP directory
http://lexmanos.no-i...8080/job/Forge/
You should not have any mods installed in the jars you decompile in order to not get bugs with Forge source patches. However it might be wise to pre-install TooManyItems (or install NotEnoughItems from it's sourcecode afterwards, and use updatemd5) because creative mode is sort of painful for testing.
Step 2 : Decompile, install Forge sources
Head to your MPC/Forge/ folder and execute the install file. Forge should now do the rest by itself, and you end up with a fully decompiled client and server mcp forge setup.
If there are any issues here (there might), see if you can fix the code problem yourself. If you can, run "updatemd5" after fixing the sources to compile, and proceed with step 3.
Same goes for APIs (Industrialcraft, Buildcraft, any major mod...) or other mods that you need included. Put them in now, run updatemd5 so they get excluded from your reobfuscations.
Step 3 : Add old MLMP mod source to new MCP
If your mod was previously made to work with ModLoaderMP, you can port it to work with Forge's NetworkMod instead. There are several changes you need to make.
1. Go into your "mod_MODNAME.java" file and change
to
this will also require you import forge, so why don't we add this on top
2. Override methods
NetworkMod extends BaseMod, which means most of your old MLMP Overrides (assuming your source is MC 1.2.3 or newer) should just keep working. The one thing NetworkMod has different are these methods, which you should add now:
@Override public boolean clientSideRequired() { return true; } @Override public boolean serverSideRequired() { return false; }Their meaning should be obvious. clientSideRequired determines if a server with the mod allows clients without it to connect, serverSideRequired if a client can join a server without the mod. In the words of cpw: "For crying out loud do not force serverSideRequired()"
In general, just open up /forge/MinecraftForge.java and see what it has to offer you.
4. Entities
To fix Entities to work with Networkmod, you need to make sure
is present. LexManos tells me the ID should be irrelevant, to be on the safe side however pick some unique number, as you did with MLMP. If your Entity is a Mob, you should not have to change anything from MLMP.
You _can_ leave this line away and still create your Entities, however your Entities will not be saved/loaded upon client/server shutdown and restart.
4.b other, non-Mob Entities
The ModLoaderMp.registerHandler/Tracker methods for client and server need to be replaced with
on both client and server.
5. GUI
in your client mod_ file, you need to replace
on the server side, you replace
public GuiScreen HandleGUI(int inventoryType) { if(inventoryType == guiID) return new Gui_____(args); else return null; }both with:
your Networkmod (or another class you specify here) needs to implement IGuiHandler:
public interface IGuiHandler { /** * Returns a Container to be displayed to the user. * On the client side, this needs to return a instance of GuiScreen * On the server side, this needs to return a instance of Container * * @param ID The Gui ID Number * @param player The player viewing the Gui * @param world The current world * @param x X Position * @param y Y Position * @param z Z Position * @return A GuiScreen/Container to be displayed to the user, null if none. */ public Object getGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z); }and having done all that, your GUIs should work. You can open them using this method Forge adds into EntityPlayer
6. Custom Packets
Packets are by far the most difficult to port, mainly because MLMP had such a rigid implementation and Forge doesn't. To make your NetworkMod use packets, you need to:
Implement the related Interfaces in your NetworkMod
Register your NetworkMod or whatever class you put it in with Forge for the connection handler
Override the methods the Interfaces specify, and make sure to register a packet channel for your packets with a name of your choice.
Note that onLogin fires on server BEFORE onLogin on client, so if you want to send packets to the client in there already, make sure the client side registers his channel in the onConnect callback.
@Override public void onConnect(NetworkManager network) { } @Override public void onLogin(NetworkManager network, Packet1Login login) { MessageManager.getInstance().registerChannel(network, this, "channelname"); } @Override public void onDisconnect(NetworkManager network, String message, Object[] args) { } @Override public void onPacketData(NetworkManager network, String channel, byte[] data) { // HANDLE INCOMING PACKET DATA HERE }Now. We are all set up, now how to send and receive packets?
Here is an example of the Nether Ores Mod, at the sending(server) end:
public static void causeFuseSoundAt(World world, int i, int j, int k) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream data = new DataOutputStream(bytes); try { int[] coords = {i, j, k}; for(int a = 0; a < 3; a++) { data.writeInt(coords[a]); } } catch(IOException e) { e.printStackTrace(); } Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "mod_NetherOres"; // CHANNEL MAX 16 CHARS packet.data = bytes.toByteArray(); packet.length = packet.data.length; ModLoader.getMinecraftServerInstance().configManager.sendPacketToAllPlayers(packet); }Here is an example of the Nether Ores Mod, at the receiving end:
@Override public void onPacketData(NetworkManager network, String channel, byte[] bytes) { DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(bytes)); int coords[] = new int[3]; try { for(int i = 0; i < 3; i++) { coords[i] = dataStream.readInt(); } } catch(IOException e) { e.printStackTrace(); } causeFuseSoundAt(ModLoader.getMinecraftInstance().theWorld, coords[0], coords[1], coords[2]); }If you want to see a more in-depth example (with custom packet classes and packaging) check out Buildcraft's implementation, to be seen here
http://buildcraft.tr...work?order=name
A hint for server side implementation: This line
will get you the player that sent the packet you are trying to process.
To send a packet from clientside to server the easiest way is to just use ModLoader.sendPacket.
Another hint:
If you get a "String length less than zero, wierd String!" client crash message, your packet channel has a name with >16 chars. It is limited to 16 chars. Do not use more than 16 chars.
7. Recompile
Now recompile and make sure it works. If your mod worked with MLMP previously, these steps *should* cover all necessities.
-
View User Profile
-
View Posts
-
Send Message
Curse Premiumhttp://www.minecraft...modding-310511/
Here is the second part of the Tutorial, this time for networking your previously single-player-only mod.
First things first: DO NOT PM ME WITH PROBLEMS YOU MIGHT HAVE
ASK IN THE FORGE IRC CHANNEL
POKE LEXMANOS AND CPW
esper.net/#minecraftforge
Step 1 : Install MCP with Forge
USE A NEW MCP FOLDER
http://mcp.ocean-lab...hp/MCP_Releases
Aquire latest Forge build and install into your MCP directory
http://lexmanos.no-i...8080/job/Forge/
You should not have any mods installed in the jars you decompile in order to not get bugs with Forge source patches. However it might be wise to pre-install TooManyItems (or install NotEnoughItems from it's sourcecode afterwards, and use updatemd5) because creative mode is sort of painful for testing.
Step 2 : Decompile, install Forge sources
Head to your MPC/Forge/ folder and execute the install file. Forge should now do the rest by itself, and you end up with a fully decompiled client and server mcp forge setup.
If there are any issues here (there might), see if you can fix the code problem yourself. If you can, run "updatemd5" after fixing the sources to compile, and proceed with step 3.
Same goes for APIs (Industrialcraft, Buildcraft, any major mod...) or other mods that you need included. Put them in now, run updatemd5 so they get excluded from your reobfuscations.
Step 3 : Add old mod source to new MCP, both on client and server side
There are several changes you need to make on both sides.
To start off, you can delete all Render, Model, GUI and TextureFX classes. Server doesnt need them. Also delete references to those.
1. Go into your "mod_MODNAME.java" file and change
to
this will also require you import forge, so why don't we add this on top
2. Override methods
NetworkMod extends BaseMod, which means most of your old ML Overrides (assuming your source is 1.2.3 or newer) should just keep working. The one thing NetworkMod has different are these methods, which you should add now:
@Override public boolean clientSideRequired() { return true; } @Override public boolean serverSideRequired() { return false; }Their meaning should be obvious. clientSideRequired determines if a server with the mod allows clients without it to connect, serverSideRequired if a client can join a server without the mod. In the words of cpw: "For crying out loud do not force serverSideRequired()"
In general, just open up /forge/MinecraftForge.java and see what it has to offer you.
4. Entities
To fix Entities to work with Networkmod, you need to replace
with
LexManos tells me the ID should be irrelevant, to be on the safe side however pick some unique number, as you would with MLMP.
You _can_ leave this line away and still create your Entities, however your Entities will not be saved/loaded upon client/server shutdown and restart.
[Note: this constructor is no longer mandatory, as of forge #84. The standard (World world) constructor will do.]
You also need to make sure your Entity class has a constructor
public ENTITYCLASS(World world, double x, double y, double z) {...}since that is the one NetworkMod uses to spawn Entities. Make sure to use setLocation with the xyz values, because they will not be updated on the client until the Entity moves.
4.b other, non-Mob Entities
If your Entity is not a Mob you need to register a tracker using this MinecraftForge method
on both client and server.
5. GUI
you need to get your client GUI opening methods into this format
and on server, call this in EntityPlayer:
Also this needs to be called somewhere before, in your mod_ file:
your Networkmod (or another class you specify here) needs to implement IGuiHandler:
public interface IGuiHandler { /** * Returns a Container to be displayed to the user. * On the client side, this needs to return a instance of GuiScreen * On the server side, this needs to return a instance of Container * * @param ID The Gui ID Number * @param player The player viewing the Gui * @param world The current world * @param x X Position * @param y Y Position * @param z Z Position * @return A GuiScreen/Container to be displayed to the user, null if none. */ public Object getGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z); }and having done all that, your GUIs should work.
6. Custom Packets
See post above.
7. Recompile
Now recompile and make sure it works. Fix problems as you see fit. You will probably have to fix more things on client by checking for world.isRemote before setting any fields (because if you are on a server, the server does this).
There's only one thing i'm confused about(I'm probably just reading this too fast):
but to me it sounds like you're saying the exact same thing twice
MLMP actually did NOT update quickely, it never has, and it never has done a proper update.
Hence the need for FML
From the point of view of the modder using FML will actually be EASIER then using MLMP due to the fact that it will acuratly emulate the ML api as MLMP should of always been doing.
You will need to adjust away from any MLMP specific things you are using, but honestly the bulk of that will be to change from BaseModMP to BaseMod, and to strip out any calls to ModLoaderMP.*
posted in the buildcraft forums by lexmanos
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumYeah read it more closely:
clientSideRequired: can a client without the mod connect to the server with the mod?
serverSideRequired: can a client with the mod connect to a server without the mod?
yes you are right then it could be interpreted that way but really it could say it either way
could be saying if a client, which does not have the mod, can join a server
or if a client can join a server that does not have the mod
so i think technically we're both right
-
View User Profile
-
View Posts
-
Send Message
Curse Premium-
View User Profile
-
View Posts
-
Send Message
Curse Premium(Previously known as the Bluestone Dust Mod)
If you follow flan's tutorial first (you will get errors), then this tutorial, it's a breeze
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumTo Forge?
Yah, I'd like to know this too. You could probably approximate it with a boolean though, just use an onUpdate/onTickInGame method to check whether it's pressed. But does anyone really understand the GUIs? I need to know how to register the individual GUIs, but right now all I can guess at is this:
public void MakeGUIs() { /* //THE SECOND PARAMETER IS AN INT USED TO IDENTIFY THE GUI ModLoaderMp.registerGUI(this, biomeBusterGUI); ModLoaderMp.registerGUI(this, c4GUI); ModLoaderMp.registerGUI(this, hBombGUI); ModLoaderMp.registerGUI(this, megaNukeGUI); ModLoaderMp.registerGUI(this, napalmGUI); ModLoaderMp.registerGUI(this, novaGUI); ModLoaderMp.registerGUI(this, nukeGUI); ModLoaderMp.registerGUI(this, preciseTNTGUI); ModLoaderMp.registerGUI(this, stickyTNTGUI); ModLoaderMp.registerGUI(this, volcanoGUI); ModLoaderMp.registerGUI(this, creeperGUI); */ MinecraftForge.setGuiHandler(this, this); } @Override public Object getGuiElement(int inventoryType, EntityPlayer player, World world, int x, int y, int z) { if(inventoryType == nukeGUI) return new GuiExplosivesPlusConfigNuke(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == megaNukeGUI) return new GuiExplosivesPlusConfigMegaNuke(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == napalmGUI) return new GuiExplosivesPlusConfigNapalm(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == preciseTNTGUI) return new GuiExplosivesPlusConfigPreciseTNT(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == stickyTNTGUI) return new GuiExplosivesPlusConfigStickyTNT(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == c4GUI) return new GuiExplosivesPlusConfigC4(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == hBombGUI) return new GuiExplosivesPlusConfigHBomb(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == biomeBusterGUI) return new GuiExplosivesPlusConfigBiomeBuster(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == novaGUI) return new GuiExplosivesPlusConfigNova(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == volcanoGUI) return new GuiExplosivesPlusConfigVolcano(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); if(inventoryType == creeperGUI) return new GuiExplosivesPlusConfigNuclearCreeper(ModLoader.getMinecraftInstance().theWorld, ModLoader.getMinecraftInstance()); else return null; }I don't think that's right...anyone get this?
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumCheck this "Jump Key" packet construction i made for MoCreatures SMP
clientside
if (mc.gameSettings.keyBindJump.pressed) { Entity ridden = mc.thePlayer.ridingEntity; if (ridden != null && ridden instanceof MoCEntityHorse && ridden.motionY < 0D && ridden.motionY > -0.2D && !ridden.isAirBorne) { if (!mc.theWorld.isRemote) { ((MoCEntityHorse)mc.thePlayer.ridingEntity).makeHorseJump(); } else { sendHorseJumpPacket(); } } } private void sendHorseJumpPacket() { // client sending horse jump command. first packet int: 1 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream data = new DataOutputStream(bytes); try { data.writeInt(Integer.valueOf(1)); } catch(IOException e) { e.printStackTrace(); } Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "MoCreatures"; packet.data = bytes.toByteArray(); packet.length = packet.data.length; ModLoader.sendPacket(packet); }serverside
@Override public void onPacketData(NetworkManager network, String channel, byte[] bytes) { DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(bytes)); try { int packetID = dataStream.readInt(); if (packetID == 1) // server receives horse jump command packet. make the horse under this player jump { EntityPlayer player = ((NetServerHandler)network.getNetHandler()).getPlayerEntity(); if (player.ridingEntity != null && player.ridingEntity instanceof MoCEntityHorse) { ((MoCEntityHorse)player.ridingEntity).makeHorseJump(); } } } catch (IOException e) { e.printStackTrace(); } }@Pheenix
Your GUI code looks good, for clientside atleast. Now you need to open those GUIs for the player using (EntityPlayer).openGUI
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumAnybody know what to do with
?
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumThanks for posting that, AtomicStryker! It was greatly helpful for me to see an example of a packet going the other direction, where the server has to know which player it's coming from.
I dropped it into the load() functions in both client and server, and it's working. That might be a good thing to mention in the tutorial.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumYep I agree.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumHow can I make it throw just one?
and is this correct for both server and client?
public static boolean registerEntity(Class entityClass, NetworkMod mod, int ID, int range, int updateFrequency, boolean sendVelocityInfo) { entityClass = MCEntityDynamite.class; ID = DynamiteID; range = 10; updateFrequency = 5; sendVelocityInfo = true; MinecraftForge.registerEntity(entityClass, mod, ID, range, updateFrequency, sendVelocityInfo); return true; }-
View User Profile
-
View Posts
-
Send Message
Curse PremiumAlways check how minecraft does it. You will notice that on all actions that spawn an Entity (such as firing a bow...) the client has a
check infront of it. That prevents the bug you are having.
And no, what you do is incorrect ... you are supposed to call the method, not declare it yourself.
Like so:
But thats java (any programming language really) basics. Perhaps you should consult some tutorials first.