![]() |
The network ID generator class allows you to refer to objects in a common fashion over different computers
The network ID generator 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: There is a derivation of NetworkIDGenerator called NetworkObject. It assumes that there is an externally instantiated server and client, which there is if you use the Multiplayer class. If you want to use your own instantiations, implement the pure virtual functions in a derived class telling NetworkIDGenerator the status of your client and server (or peer). In the simplest case, here's how it works: Use GetNetworkID() to get the ID of an object. If no ID was assigned, it will return UNASSIGNED_OBJECT_ID Use SetNetworkID() to set the ID of an object. It's easy to get in trouble if you do this wrong, which is why the NetworkIDGenerator class 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.
IDs are automatically assigned, so GetNetworkID() will always work and you should not call SetNetworkID(). 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 NetworkIDGenerator. 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 NetworkIDGenerator: 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 NetworkIDGenerator. Examples of when not to derive from NetworkIDGenerator: 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 NetworkIDGenerator* 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 NetworkIDGenerator. 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 the NetworkIDGenerator. 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. |
![]() |
Index |