I would like to use a smartpointer's address as a ID value

Started by
15 comments, last by ankhd 9 years, 1 month ago

That is the range of 32-bit.
I think you meant 2^64 = 1,844674407371e+19 or the galaxy's stars several times over tongue.png


Well, you only need 64 bit IDs if you have more than 4294967296 players. If you have less than that you can stick with 32 bit IDs.
Advertisement

The 64 bit was to hold the address of a 64 bit pointer 32 bit's can't hold all the bits of a 64 bit pointer.

Yeah the 64 bit id is over kill, i'll be lucky to have 8 - 16 players per game. Like everyone has stated I can now generate the ID per Game that gets joined the host or the server could allocate the ID to new Players when they join the game lobby. I was trying to give ID as each player logged on to the server, But that ID would be a user account type ID not needed for game play.

I think I found a way to link the remote objects. Each computer that joins a game has a list of current players that contain that players remote objects in a map based on the objects ID, this way its a look up based on the players ID and the Objects ID.

If the server says Player 1 died it would send out a message killplayer that contains PlayerID(int), ObjectID, MessageType, and on remote Pc the message comes in and it first finds the players remotes, then finds the object in the map and that object can be killed and removed.

I'll give this a try to day.

hi again.

Is there a elegant solution to some thing like this. I need to map the ID to the Connection and visa versa

.


//holds all clients of this lobby
std::set<cConnection_ptr> Clients;
	
//map the connection pointer to the id
boost::unordered_map<cConnection_ptr, int32_t> ClientID;

//map the ID to connection
boost::unordered_map<int32_t, cConnection_ptr> IDToConnection;

//client data is set when a client sends its accountinfo
boost::unordered_map<int32_t, cClientData> ClientData;

int32_t LobbyID;//each client gets a id

.

It gets really ugly when a client disconnects

.


void leave(cConnection_ptr client)
{
     std::set<cConnection_ptr>::iterator it = Clients.find(client);

     if(it != Clients.end())
     {
	boost::unordered_map<cConnection_ptr, int32_t>::const_iterator  itid = ClientID.find((*it));

       if(itid != ClientID.end())
       {	
	  boost::unordered_map<int32_t, cConnection_ptr>::const_iterator  itidtocon = IDToConnection.find(itid->second);
	 
	  boost::unordered_map<int32_t, cClientData>::const_iterator  itcdata = ClientData.find(itid->second);
//
	  if(itidtocon != IDToConnection.end())
		IDToConnection.erase(itidtocon);

	  if(itcdata != ClientData.end())
		ClientData.erase(itcdata);
						
       }//end itid
	 
       Clients.erase(it);
    }//end it
	  
	 
    Clients.rerase(client);
  }

If you don't mind taking a dependency on Boost, then Boost.Bimap is your friend for two-way mappings.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Wow.

If you don't mind taking a dependency on Boost, then Boost.Bimap is your friend for two-way mappings.

what a beast that all is.

I think this example is what I may need to follow.

.


typedef bimap<

    multiset_of< std::string >, // author
         set_of< std::string >, // title

      with_info< std::string >  // abstract THIS COULD BE THE ACCOUNT INFO

> bm_type;
typedef bm_type::value_type book;

bm_type bm;

bm.insert(

    book( "Bjarne Stroustrup"   , "The C++ Programming Language",

          "For C++ old-timers, the first edition of this book is"
          "the one that started it all—the font of our knowledge." )
);


// Print the author of the bible
std::cout << bm.right.at("The C++ Programming Language");

// Print the abstract of this book
bm_type::left_iterator i = bm.left.find("Bjarne Stroustrup");
std::cout << i->info;


.

Looking into it. thanks for the link, I tried a search on containers with 2 key values and a data element but came up short.(thats Gold).

What tonemgub said. This is a bad, bad idea.

A perfectly acceptable alternative is to just shove the pointer into an array. The player ID is the index into this array. If players can join mid-progress with the game, use a free-list of some sort to recycle player IDs when someone quits the game.

Note also that you don't want the player to ever tell the server who he is. You might tell a player that his ID is 2 and then he might send a command SelfDestruct(player=4) and bam, he just killed another player.

Each connection should have an implicit player ID on the server side. When input is received from a connection then the ID that is associated with it is automatically associated with the input. The player ID should only be used by players to identify other players when _requesting_ things over the network from the absolutely-authoritative server. Requests that affect a player himself should rely on that implicit player ID on the server, not sending the ID to the server as part of the request.

This is a good idea, but still if you do this remember to always range check your array index server side (common sense really).

Otherwise the first person to request that their character attack player id -54124 or such will bring you a whole new definition to the meaning of frustration.

Thanks everyone.

Here is a example of the bimap(I chuckle when I write that).

.


#include <boost/shared_ptr.hpp>
#include <boost/bimap.hpp>


class cClientData
{
public:
	cClientData(){}
	~cClientData(){}

	std::string Name;
};

typedef boost::shared_ptr<cClientData> cConnection_ptr;

typedef boost::bimap<

		cConnection_ptr , // connection
        int32_t ,  // ID
		boost::bimaps::with_info<cClientData>  // abstract

>bm_type;
typedef bm_type::value_type client_bm_type;







int main()
{
  

        //it will be a connection class in the real app
        //just testing smart pointer
        cConnection_ptr PTR =  boost::shared_ptr<cClientData>(new cClientData());

        cConnection_ptr PTR2 =  boost::shared_ptr<cClientData>(new cClientData());

	cConnection_ptr PTR3 =  boost::shared_ptr<cClientData>(new cClientData());

	cConnection_ptr PTR4 =  boost::shared_ptr<cClientData>(new cClientData());

	cClientData cd;
	

	bm_type bm;
	int32_t id = 10;
	int32_t id2 = 13;
	int32_t id3 = 16;
	int32_t id4 = 11;

	cd.Name = "Sam1";
	bm.insert(client_bm_type(PTR, id, cd));//this is typedef bm_type::value_type client;

	cd.Name = "Sam2 Long ffffffffffffffffffffffffffffffffffffff";
	bm.insert(client_bm_type(PTR2, id2, cd));//this is typedef bm_type::value_type client;

	cd.Name = "Sam3";
	bm.insert(client_bm_type(PTR3, id3, cd));//this is typedef bm_type::value_type client;

	cd.Name = "Sam4";
	bm.insert(client_bm_type(PTR4, id4, cd));//this is typedef bm_type::value_type client;

	

	

	// Print the new abstract by using connection pointer
std::cout << "abstract Data using Pointer Key = " << bm.left.info_at(PTR).Name << std::endl;

std::cout << "abstract Data using int32_t Key = " << bm.right.info_at(id).Name << std::endl;


// Print the client data by left side 
bm_type::left_iterator i = bm.left.find(PTR);
if(i != bm.left.end())
	std::cout << "Finding by Pointer1 = " << i->info.Name << std::endl;


i = bm.left.find(PTR2);
if(i != bm.left.end())
	std::cout << "Finding by Pointer2 = " << i->info.Name << std::endl;

i = bm.left.find(PTR3);
if(i != bm.left.end())
	std::cout << "Finding by Pointer3 = " << i->info.Name << std::endl;

i = bm.left.find(PTR4);
if(i != bm.left.end())
	std::cout << "Finding by Pointer4 = " << i->info.Name << std::endl;




// Print the client data by right side 
bm_type::right_iterator ir = bm.right.find(20);//not a entry
if(ir != bm.right.end())
	std::cout << "Finding by ID = " << i->info.Name << std::endl;
else
	std::cout << "Finding Failed No ID";


	return 0;
}

.

And if your searching the web with boost::bimap watch out stay with boost pages , here or stackoverflow.

This topic is closed to new replies.

Advertisement