/// \file /// /// This file is part of RakNet Copyright 2003 Kevin Jenkins. /// /// Usage of RakNet is subject to the appropriate license agreement. /// Creative Commons Licensees are subject to the /// license found at /// http://creativecommons.org/licenses/by-nc/2.5/ /// Single application licensees are subject to the license found at /// http://www.rakkarsoft.com/SingleApplicationLicense.html /// Custom license users are subject to the terms therein. /// GPL license users are subject to the GNU General Public /// License as published by the Free /// Software Foundation; either version 2 of the License, or (at your /// option) any later version. #include "NetworkIDGenerator.h" #ifdef _COMPATIBILITY_1 #elif defined(_WIN32) #include // alloca #elif defined(_COMPATIBILITY_2) #include "Compatibility2Includes.h" #else #include // alloca #endif #include // Note you will need to save and load this if your game supports saving and loading so you start at the same index you left off. // If you don't do this you can overwrite indices unsigned short NetworkIDGenerator::staticItemID = 0; DataStructures::AVLBalancedBinarySearchTree NetworkIDGenerator::IDTree; PlayerID NetworkIDGenerator::externalPlayerId=UNASSIGNED_PLAYER_ID; bool NetworkIDNode::operator==( const NetworkIDNode& right ) const { if ( networkID == right.networkID ) return !0; return 0; } bool NetworkIDNode::operator > ( const NetworkIDNode& right ) const { if ( networkID > right.networkID ) return !0; return 0; } bool NetworkIDNode::operator < ( const NetworkIDNode& right ) const { if ( networkID < right.networkID ) return !0; return 0; } NetworkIDNode::NetworkIDNode() { object = 0; } NetworkIDNode::NetworkIDNode( NetworkID _networkID, NetworkIDGenerator *_object ) { networkID = _networkID; object = _object; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// NetworkIDGenerator::NetworkIDGenerator() { callGenerationCode=true; networkID=UNASSIGNED_NETWORK_ID; parent=0; } //------------------------------------------------------------------------------------- NetworkIDGenerator::~NetworkIDGenerator() { if (networkID!=UNASSIGNED_NETWORK_ID) { NetworkIDNode * object = NetworkIDGenerator::IDTree.GetPointerToNode( NetworkIDNode( ( networkID ), 0 ) ); if ( object->object == this ) IDTree.Del( NetworkIDNode( object->networkID, 0 ) ); } } ////////////////////////////////////////////////////////////////////// // Public Methods ////////////////////////////////////////////////////////////////////// NetworkID NetworkIDGenerator::GetNetworkID( void ) { if (callGenerationCode && IsNetworkIDAuthority()) { GenerateID(); callGenerationCode=false; } return networkID; }; //------------------------------------------------------------------------------------- unsigned short NetworkIDGenerator::GetStaticNetworkID( void ) { return staticItemID; } //------------------------------------------------------------------------------------- void NetworkIDGenerator::SetStaticNetworkID( unsigned short i ) { staticItemID = i; } //------------------------------------------------------------------------------------- void NetworkIDGenerator::SetExternalPlayerID(PlayerID playerId) { assert(playerId!=UNASSIGNED_PLAYER_ID); externalPlayerId=playerId; } //------------------------------------------------------------------------------------- PlayerID NetworkIDGenerator::GetExternalPlayerID(void) { return externalPlayerId; } //------------------------------------------------------------------------------------- bool NetworkIDGenerator::RequiresSetParent(void) const { return false; } //------------------------------------------------------------------------------------- void NetworkIDGenerator::SetNetworkID( NetworkID id ) { callGenerationCode=false; if ( id == UNASSIGNED_NETWORK_ID ) { // puts("Warning: NetworkIDGenerator passed UNASSIGNED_NETWORK_ID. SetID ignored"); return ; } if ( networkID == id ) { // printf("NetworkIDGenerator passed %i which already exists in the tree. SetID ignored", id); return ; } NetworkIDNode* collision = NetworkIDGenerator::IDTree.GetPointerToNode( NetworkIDNode( ( id ), 0 ) ); if ( collision ) // Tree should have only unique values. The new value is already in use. { //printf("Warning: NetworkIDGenerator::SetID passed %i, which has an existing node in the tree. Old node removed, which will cause the item pointed to to be inaccessible to the network", id); IDTree.Del( NetworkIDNode( collision->networkID, collision->object ) ); } if ( networkID == UNASSIGNED_NETWORK_ID ) // Object has not had an ID assigned so does not already exist in the tree { networkID = id; IDTree.Add( NetworkIDNode( networkID, this ) ); } else // Object already exists in the tree and has an assigned ID { IDTree.Del( NetworkIDNode( networkID, this ) ); // Delete the node with whatever ID the existing object is using networkID = id; IDTree.Add( NetworkIDNode( networkID, this ) ); } } //------------------------------------------------------------------------------------- void NetworkIDGenerator::SetParent( void *_parent ) { parent=_parent; #ifdef _DEBUG // Avoid duplicate parents in the tree unsigned size = IDTree.Size(); NetworkIDNode *nodeArray; bool usedAlloca=false; #if !defined(_COMPATIBILITY_1) if (sizeof(NetworkIDNode) * size < MAX_ALLOCA_STACK_ALLOCATION) { nodeArray = (NetworkIDNode*) alloca(sizeof(NetworkIDNode) * size); usedAlloca=true; } else #endif nodeArray = new NetworkIDNode[size]; IDTree.DisplayBreadthFirstSearch( nodeArray ); unsigned i; for (i=0; i < size; i++) { // If this assert hits then this _parent is already in the tree. Classes instance should never contain more than one NetworkIDGenerator assert(nodeArray->object->GetParent()!=parent); } if (usedAlloca==false) delete [] nodeArray; #endif } //------------------------------------------------------------------------------------- void* NetworkIDGenerator::GetParent( void ) const { return parent; } //------------------------------------------------------------------------------------- void NetworkIDGenerator::GenerateID(void) { assert(IsNetworkIDAuthority()); NetworkIDNode* collision; do { networkID.localSystemId=staticItemID++; if (NetworkID::peerToPeerMode) { // If this assert hits you forgot to call SetExternalPlayerID assert(externalPlayerId!=UNASSIGNED_PLAYER_ID); networkID.playerId=externalPlayerId; } collision = NetworkIDGenerator::IDTree.GetPointerToNode( NetworkIDNode( ( networkID ), 0 ) ); } while ( collision ); IDTree.Add( NetworkIDNode( networkID, this ) ); } //------------------------------------------------------------------------------------- void* NetworkIDGenerator::GET_BASE_OBJECT_FROM_ID( NetworkID x ) { if ( x == UNASSIGNED_NETWORK_ID ) return 0; NetworkIDNode *n = NetworkIDGenerator::IDTree.GetPointerToNode( NetworkIDNode( ( x ), 0 ) ); if ( n ) { return n->object; } return 0; } //------------------------------------------------------------------------------------- void* NetworkIDGenerator::GET_OBJECT_FROM_ID( NetworkID x ) { NetworkIDGenerator *object = (NetworkIDGenerator *) GET_BASE_OBJECT_FROM_ID( x ); if (object) { if (object->GetParent()) { return object->GetParent(); } else { #ifdef _DEBUG // If this assert hit then this object requires a call to SetParent and it never got one. assert(object->RequiresSetParent()==false); #endif return object; } } return 0; } //------------------------------------------------------------------------------------- void* GET_OBJECT_FROM_ID( NetworkID x ) { return NetworkIDGenerator::GET_OBJECT_FROM_ID( x ); } ////////////////////////////////////////////////////////////////////// // EOF //////////////////////////////////////////////////////////////////////