Network Object

The network object class allows you to refer to objects in a common fashion over different computers
The Network Object class is an optional class you can derive from that will automatically assign identification numbers to objects that inherit from it. This is very useful for multiplayer games, because otherwise you have no way to refer to dynamic objects on remote systems.
IMPORTANT:
The Network Object must know if the server is running or the client is running (or both) in order to work. It assumes that there is an externally instantiated server and client, which there is if you use the Multiplayer class.
Network Object MUST have access to a server and/or a client. You can use your own instantiations, but then you would need to modify Network Object to work.
In the simplest case, here's how it works:
Use GetID() to get the ID of an object. If no ID was assigned, it will return UNASSIGNED_OBJECT_ID
Use SetID() to set the ID of an object.
It's easy to get in trouble if you do this wrong, which is why the Network Object has commented printf and puts statements in there. For debug, you should uncomment those and run your own message handler so you can get the warnings or errors if you do something wrong.

1. Don't call SetID on an object that already had it set, unless you want to reassign IDs.
2. If you delete an object on one system this will invalidate the IDs so you need to delete the object on all systems.
3. Due to lag it's possible that an object exists on one system but not another. When you use GET_OBJECT_FROM_ID to convert an objectID into a pointer, you must check for a 0 return value.

As a server:
IDs are automatically assigned, so GetID() will always work and you should not call SetID(). When the server creates a new Network Object, the clients must know about it. So you would generally do this:
MyObject *myObject = new MyObject; // MyObject inherits from Network Object
ObjectID objectId = myObject->GetID();
Create a packet with an ObjectID field, then send it to the clients.
When the client gets the packet:
MyObject *myObject = new MyObject; // MyObject inherits from Network Object
myObject->SetID(objectId); // objectID was contained in the packet
As a client:
IDs are never assigned, you must get them from the server. If you create or want to create an object, you must program things in such a way that the server will return a packet to you telling you what the ID is of the object you just created. If the server creates an object (or another client did and the server tells you about it, which is the same thing) then you can just assign IDs as usual.
The easiest way to handle creation of objects on the client is to ask the server for the object and only create the object when the server replies. Send something like ID_REQUEST_CREATE_OBJECT or whatever. You can then program the server to create the object and reply to the sender of this packet with the ID encoded into the packet (just like we did above).
On the server:
// Code to handle ID_REQUEST_CREATE_OBJECT
MyObject *myObject = new MyObject; // MyObject inherits from Network Object
ObjectID objectId = myObject->GetID();
Create a packet with an ObjectID field, then send it to the clients. The packet should be something along the lines of ID_CREATE_OBJECT for whatever type of object was just requested.
When the client gets the packet:
MyObject *myObject = new MyObject; // MyObject inherits from Network Object
myObject->SetID(objectId); // objectID was contained in the packet
As a side note, it's a good idea to put some kind of cheat detection here. For example if the client asks to create 50 tanks, and it's only 5 seconds into the game, you know something is wrong. Generally RakNet will block any kind of packet modification or duplication. But ANYTHING can be hacked given enough time, so it can't hurt as long as it's easy to code.
Programming Tip
Not everything in your game has to or should derive from NetworkObject. Only the things you need to refer to in some common fashion over the various systems need this. If there is some obvious way to refer to the objects, such as there only being one type of that object per system, you wouldn't need it.
Examples of when to derive from NetworkObject:
Your game has many enemies arranged in no particular order.
Your game has many enemies, who are deleted when they die.
Your game has triggers, such as when a player walks within 10 feet of a barrel it explodes. You could make the trigger itself derive from NetworkObject.
Examples of when not to derive from NetworkObject:
All the enemies in your game are created in a specific order in an array. You could just send the array index in that case.
There's only one castle in your game. Whenever a packet refers to a castle, you implicitly know which one it is.
The object is never referred to by the network. For example, a bullet fired from a gun. You interact with the player doing the shooting and the player getting hit, but don't worry about the gun itself.
Other functions
NetworkObject* GET_OBJECT_FROM_ID(ObjectID x);
This function will lookup the item you are looking for in its internal representation (an AVL balanced binary tree) and return a pointer to a NetworkObject. You can then cast the pointer to the type you know it should be, depending on the context of what you are looking up.
Example:
MyObject *myObject = (MyObject *) GET_OBJECT_FROM_ID(packet->objectId);
if (myObject==0)
return; // Couldn't find the object
static unsigned short GetStaticItemID(void);
static void SetStaticItemID(unsigned short i);
These are advanced functions you probably won't need and shouldn't use unless you fully understand Network Object. You can use them for force ID numbers to start at some particular value, and to get the current high value that the server will use for ID numbers. This is only useful for loading the server into an existing game state that already uses IDs. For example, if I were to save a game on the server that used IDs from 0 to 1000 and wanted to continue that game I could load the game and call SetStaticItemID(1001); That way newly assigned IDs won't conflict with existing IDs.

See Also

Index