Game Development Community

how to get client side id of a databock ?

by Ahsan Muzaheed · in Torque 3D Professional · 12/18/2012 (11:12 am) · 13 replies

i know best way is "commandToServer()".

but i need lots of data.
that means lots of commandToServer.

for a shop system that will be stupid enough (from my view).
although i started on that way.
but now my shop system is getting huge.
so i started to look into other solution.
i did this separately on sever and client :

%t=ServerConnection.getControlObject();
%t.dump();


i got this on sever:

Class: Player
Static Fields:
bool canSave = "1"
bool canSaveDynamicFields = "1"
GameBaseData dataBlock = "AdamPlayer"


on client:

Class: Player
Static Fields:
bool canSave = "1"
bool canSaveDynamicFields = "1"
GameBaseData dataBlock = "280"



"280.dump(); " is showing all info.that means i can read dataBlock on client side.
but the problem is that on client side datablock have only a numeric id which differs each time a new connection is created.

i belief there must be a way to get client side id of a datablock.

now question is "how" ?
or there is no way to get id ?




my plan is:
client will send datablcok name on server and server will send the id of that datablock.
using that id client will be able to read all properties of that datablock.

About the author

Torque 3D enthusiastic since 2010.Have been working in several T3D projects besides of Unreal Engine 4 and Unity 3D. NEED a hand with your project? SHoot me a mail. http://www.garagegames.com/community/forums /viewthread/138437/


#1
12/18/2012 (1:31 pm)
There might be a way through the ghost system, but if you start down that path you are defeating part of Torque's built-in network security. Additionally, if any of that data needs to change you'll find that the server won't allow it.

It would be better to find a different way to access your information from the server, perhaps in batches. Functions and methods in Torquescript don't have to return a single piece of information - you can return space- or tab-delimited lists of information with a single function. As long as you know the data format you just parse it out on the other end.
#2
12/18/2012 (4:39 pm)
Could he uuencode the data and send just about anything down the pipe? I don't know if there are functions for that, but it might be a could way to send binary data even.
#3
12/18/2012 (5:20 pm)
I was just thinking about using the standard TorqueScript function return mechanisms. You could send anything if you have a way to deal with it on each end.
#4
12/18/2012 (6:08 pm)
Yeah, I am still in the mode of thinking of functions sending/receiving strings. It kind of weirds me out to write a function using native data types. It just seems wrong in a TS sort of way.
#5
12/18/2012 (7:43 pm)
Well, sure - but you could send a tab-delimited string and just parse it out at the other end. Pure Torquescript string-passing goodness! The only reason I have decided to like tab-delimited strings is that you can use spaces in your fields that way.
#6
12/18/2012 (8:14 pm)
so there is no machanism to get the id from server?

Quote:It would be better to find a different way to access your information from the server, perhaps in batches

same data already exists on both side.so i do not want to waste Brandwidth to get same data.all i need is a way to find out what is the client side id.

i know if someone use same technique and find the id then he could cheat or hack that object.we can use some kind of vertification to verify the request.but that is not needed now.

i got this from full tamplate:

function serverToClientObject( %serverObject )
{
   assert( isObject( LocalClientConnection ), "serverToClientObject() - No local client connection found!" );
   assert( isObject( ServerConnection ), "serverToClientObject() - No server connection found!" );      
         
   %ghostId = LocalClientConnection.getGhostId( %serverObject );
   if ( %ghostId == -1 )
      return 0;
                
   return ServerConnection.resolveGhostID( %ghostId );   
}
plus these lines:

LocalClientConnection.getGhostId( %serverObject );
ServerConnection.resolveGhostID( %ghostIdSentByServer );//On the client,
%client.resolveObjectFromGhostIndex( %ghostId )//On the server,
int NetConnection::getGhostID ( int realID )

all related to ghosting. i think t3d do not ghost everything.not the datablcok. netmeter always show 4 or 2 active ghost object.
so i need a way to ghost all datablocks.
but will that be good idea?
#7
12/19/2012 (1:08 am)
I thought that the datablocks had the same ID on client and server, but that the client datablocks were unaware of their 'name'.

If you look at any of the engine code where dynamic fields which are datablocks get networked, the id is sent as-is, and is used on the client without any kind of translation from server ID to client ID.

Also, I'm pretty sure that every datablock that exists on the server gets sent to the client at mission load time, so there should be no need to re-ghost them.
#8
12/19/2012 (2:59 am)
" same ID on client and server"

how i could be so stupid.
yes. same ID!!!!
i should have check that first.
thanks Guy.


now another problem.on client there is no dynamic field of datablocks.
so again i have to go back to "commandToServer" server solution as most of my shop related info stored as dynamic field.
any thought about alternatives?


", I'm pretty sure that every datablock that exists on the server gets sent to the client at mission load time"
yes i know that.but netmeter almost always shows 2-3 active ghost.
now i think i was misunderstanding that.

edit:
i actually was thinking ghost object and client side datablocks are different things as they are sent by two different functions.
transmitDataBlocks()//// Send over the datablocks...
activateGhosting()//// Start ghosting objects to the client
#9
12/19/2012 (7:22 am)
On the server, grab your data and stuff it into a tab-delimited string:
serverCmdgetObjectData(%client, %object)
{
   %obj = getMyObjectDatablock(%object); // get your data and put it on a copy
   %data = "";
   for (%i = 0; %i < %obj.getDynamicFieldCount(); %i++)
   {
      %data = %data TAB %obj.getDynamicField(%i);
   }
   commandToClient(%client, unpackObjData, trim(%data));  // send tab-delimited data back to client
}
Now %data contains the contents of the dynamic fields on your datablock.
Client-side, just unpack the data using getFieldCount() and getField() (The tab versions of getWordCount() and getWord()).

You can use a similar strategy for setting those field values on the datablock by sending from a client command and unpacking in a server command. That way the server can validate changes.

Not pretty, but it should do the trick.
#10
12/20/2012 (3:25 pm)
@ahsan:
Yes, datablocks and ghosts are two different things. Server side datablocks are always sent to the client when the client first connects. And as you discovered, they share the same IDs between the server and client.

And you are correct that dynamic fields are not sent to the client. The C++ code determines which fields are sent and there is no automatic mechanism to send across dynamic fields. Often this is a good thing as the server uses dynamic fields to keep track of server-side data.

Ghosts are the client-side versions of dynamic server objects. The objects that are ghosted can be different between each game connection as determined by scoping rules. The ghost IDs also don't match the IDs on the server for security reasons.

It looks like you are making a single player game? In that case you can use the handy serverToClientObject() function found in core/scripts/client/client.cs. It takes the server side object as a parameter and returns the actual client side object, or 0 if it couldn't find one.

I hope that helps!

- Dave
#11
12/20/2012 (5:58 pm)
thanks Dave to clarify all of this.

Richard for now i put shop part aside.but i really like your approach.just 1 call and i will get all dynamic fields. although it still using brandwidth. but it will save my time.

"It looks like you are making a single player game?"
no it is completely a multiplayer game.
what give u that impression?
sounds like i have done something wrong which makes u feel that i am working on single player.
#12
12/20/2012 (7:35 pm)
@ahsan:
My apologies. I was eating supper at the same time I was reading through your post and I guess I was distracted. When I saw the code in comment #6 I thought you were using LocalClientConnection, which could only be done with a single player game (or a local client and server). But now I see that it was only part of an example you were showing.

- Dave