Game Development Community

Problem with commandToClient

by Tom Spilman · in Torque Game Engine · 03/05/2005 (11:16 am) · 27 replies

Ok this one was working for a bit and now it's not. I can't seem to find the issue myself, so maybe some new eyes would help.

I have the following code in server/scripts/game.cs:

if ( %current.letterbox !$= "" ) {
      echo( "[setLetterBox] before call!" );
      commandToClient( %this.client, 'SetLetterbox', %current.letterbox, %current.letterbox );
      echo( "[setLetterBox] after call!" );
  }

And i have this in client/scripts/game.cs:

function clientCmdSetLetterbox(%enable,%msec)
{
   ServerConnection.setLetterbox( %enable, %msec );
   echo( "[clientCmdSetLetterbox] called!" );
}

When i run it i get the 'before' and 'after' echos in my log, but the 'called' echo never appears and the breakpoint in the C++ code never fires. I traced the code into commandToClient and it was creating a RemoteCommandEvent, but the process() member was never called for it.

Anyone have any clue why this would be happening?

About the author

Tom is a programmer and co-owner of Sickhead Games, LLC.

Page «Previous 1 2
#1
03/05/2005 (11:26 am)
First guess is that %this.client isn't a client object. What is %this, and does it in fact have a valid .client?

Second guess would be that there is a syntax problem somewhere (Although I don't see an obvious one), and your code isn't being loaded. Check the command console for any errors?
#2
03/05/2005 (11:32 am)
Well i tracked that first. %this in my case is a controlled shapebase object to which i assigned the client member to access later. I'm sure the client is valid because i use it a few lines below to assign a camera object. Also i stepped thru the code and it gets past the Sim::findObject() check.

No failures loading code... both game.cs files load.

But it has to be something this simple as commandToClient() is fairly well tested.
#3
03/05/2005 (11:41 am)
You could echo(%this.client) to insure it is initalized. . .once you get the game id you could manuall test in the console.
#4
03/05/2005 (11:48 am)
Yep... i'm getting 1391 echo'ed to the console. So i assume that if i typed this into the console...

commandToClient( 1391, 'SetLetterBox', true, 5000 );

... my function *should* be firing? Sorry... still a script newbie. =)
#5
03/05/2005 (12:48 pm)
Yeah Tom it should. *But* your client variable is not the same each time you're connecting since it goes trough the ID's so the example above shouldn't work (althought don't quote me on this one) unless that's the ID you're using.

But yeah, the syntax is correct on the server.
#6
03/05/2005 (12:55 pm)
Could you post the entire function where you assign the %client to the %this? The only suspicion I have left is that somehow you are assigning the wrong client id to %this.client, and it's trying to send the command to a non-existent one.

It would probably be pretty hard to accomplish this "mistake", but I just don't see anything in your code so far that looks wrong.

I'm assuming for this "mistake" to even occur that you are running client and server "co-executed" (single player game style), and that when you assign the %client, somehow it's not appropriate...still guessing here though.

Try this as well: do a tree(); in the console, find the object that you are seeing as %client, and tell us what group it is in in the tree(); display.
#7
03/05/2005 (1:02 pm)
You could also do a %this.client.dump(); in the function then look in the console log to see what type of object you just dumped.
#8
03/05/2005 (1:04 pm)
This is where i'm setting the client on my shapebase derived object:

function GameConnection::createFighter(%this, %spawnPoint)
{
   if ( %this.player > 0 )  {
      error( "Attempting to create an angus ghost!" );
   }

   // Create the advanced camera used for scrolling
   %this.advCamera = new AdvancedCamera(FighterAdvancedCamera) {
      dataBlock = DefaultAdvanceCamera;
   };
   MissionCleanup.add( %this.advCamera );
   %this.advCamera.scopeToClient( %this );

   // Create the fighter object
   %fighter = new ScrollerFlyingVehicle() {
      dataBlock = ScrollerShip;
      client = %this;
   };
   MissionCleanup.add( %fighter );

   // Player setup...
   %fighter.setTransform( %spawnPoint );
   %fighter.setShapeName( %this.name );
   
   // Give the client control of the player
   %this.player = %fighter;
   %this.setControlObject( %this.player );

   // Get it started downn the path! 
   %this.player.followPath( "MissionGroup/StartPath" );
}

This is the script where i actually call commandToClient:

function ScrollerFlyingVehicle::onNode( %this, %node )
{

	%current = %this.path.getObject( %node );
   %camera = %this.client.advCamera;
	if ( !%current || !%camera )
		return;

   // First apply all the non-camera changes to the fighter.
   if ( %current.upControlAxis !$= "" ) {
      %this.setUpControlAxis( %current.upControlAxis );
   }
   
   if ( %current.leftControlAxis !$= "" ) {
      %this.setLeftControlAxis( %current.leftControlAxis );
   }

   if ( %current.scrollOffset !$= "" ) {
      %this.setScrollOffset( %current.scrollOffset );
   }

	// Now do the camera magic!
   if ( %current.cameraDamping !$= "" ) {
      %camera.setDamping( %current.cameraDamping );
   }

   if ( %current.letterbox !$= "" ) {
      echo( "[SetLetterbox] before server call! " @ %this.client );
      commandToClient( %this.client, 'SetLetterbox', %current.letterbox, %current.letterbox );
      echo( "[SetLetterbox] after server call!" );
  }

   if ( %current.cameraMode $= "dolly" ) {

      %camera.setPlayerObject( %this.client.player );
      $firstPerson = false;
      %this.client.setCameraObject( %camera );
      %camera.setDollyMode();
      %camera.setFollowTerrainMode(false);
      %camera.setVerticalFreedomMode(false);

      if ( %current.dollyDistance !$= "" ) {
         %camera.setDollyDistance( %current.dollyDistance );
      }

      if ( %current.dollyAim !$= "" ) {
         %camera.setDollyAim( %current.dollyAim );
      }

   } else if ( %current.cameraMode !$= "" ) {
   
      // If we have a mode that isn't a known type then
      // see if it's a name of a camera placed in the scene.
      %scene_cam = nameToID( "MissionGroup/" @ %current.cameraMode );
      if ( %scene_cam != -1 ) {

         // Hook things up first!
         %scene_cam.setPlayerObject( %this.client.player );
         $firstPerson = false;
         %this.client.setCameraObject( %scene_cam );

         // Now change the cameras mode to what is requested.
         if ( %scene_cam.setMode !$= "" ) {
            eval( "%scene_cam.set" @ %scene_cam.setMode @ "Mode();" );
         }

      }
   }
}

It all seems to be just right... it's weird. I'm starting to think it's something else outside of this code.
#9
03/05/2005 (1:05 pm)
Thank's Harold! That's a great tip! I tired it and yes... %this.client is a GameConnection.
#10
03/05/2005 (1:45 pm)
Heh..when in doubt, punt!

Try deleting the client/scripts/game.cs.dso and see if it changes anything. Make sure you check in your console.log to see if the game.cs.dso is recompiled properly. The code you've shown all looks absolutely fine to my eyes. Only thing I can think of is the new function on the client side never made it in because of a syntax error in the file.
#11
03/05/2005 (1:51 pm)
Cleared the DSOs... same issue. I guess i need to prepare for more debugging. I need to trace thru the read and write net functions in RemoteCommandEvent. Seems like something i can do on the plane to GDC tomorrow morning. =)
#12
03/05/2005 (2:15 pm)
One more thing just jumped out of me:

In your
// Create the fighter object   
  %fighter = new ScrollerFlyingVehicle() {
      dataBlock = ScrollerShip;
      client = %this;
   };

You are setting the client as a parameter to the new command. Normally, the client is set afterwards:

// Create the fighter object   
  %fighter = new ScrollerFlyingVehicle() {
      dataBlock = ScrollerShip;
   };
  %fighter.client = %this;

See if that helps maybe? :)
#13
03/05/2005 (2:30 pm)
Nope... not it... i'm sure it's not the client now.
#14
03/06/2005 (6:17 am)
function ScrollerFlyingVehicle::onNode( %datablock, %this, %node )
{

}

1394 is an awefully low client ID#. I suspect that is your datablock number, but thats just a guess. I assume you are using a copy/hack path implementation and if so, the "onNode" function will return 3 args.

Any chance of posting some log info?
#15
03/06/2005 (4:35 pm)
I'll see if i can post some more logs of that. Humm... my onNode only takes two parameters... is %datablock a special argument like %this is?

Still i don't think that's the problem. If the client ID was the problem then wouldn't my camera changes which are executed thru that client ID fail also? Wouldn't the call to commandToClient fail during it's Sim::findObject() check of the client id? The C++ code for commandToClient seems to exit normally... it's somewhere after that where things go wrong.

I've been tracing the code and somewhere between the RemoteCommandEvent being placed into the mSendEventQueueHead list in NetConnection::postNetEvent and the call to NetConnection::eventWritePacket() mSendEventQueueHead becomes NULL. I'm still looking furthur into this... it may be that i'm seeing the client side call there.

I'll post more later... i just got into San Fran and got my GDC stuff... need to return to my hotel room and debug. =)
#16
03/06/2005 (4:50 pm)
Using %datablock as you described gave syntax errors... i just echo'ed the %this and %node then dumped %this:

Quote:
[ScrollerFlyingVehicle::onNode] 1407 0
Member Fields:
dataBlock = "ScrollerShip"
disableMove = "0"
position = "257 -30 220"
rotation = "1 0 0 0"
scale = "1 1 1"
Tagged Fields:
client = "1391"
invCrossbow = "1"
invCrossbowAmmo = "99999"
loopNode = "-1"
Path = "MissionGroup/StartPath"
speed = "100"
...

My client ID seems to *always* be 1391... is that normal?
#17
03/08/2005 (3:47 pm)
Ok as further proof this isn't a client id issue i changed the code to this:

%client = ClientGroup.getObject(0);
      commandToClient( %client, 'SetLetterbox', %current.letterbox );

My understanding being that in a single player game the first (and only) client in the ClientGroup is the correct player client. Still doesn't work.

Now what i did observe is that if i do the right sequence of Alt C, Tab, Tab... bang... the client command suddenly comes thru to the client. I now suspect this is a scope issue and that it *thinks* the client doesn't need the command based on some visibility query or something. I don't know enough to say for sure if this is it, but it is somehow camera related.
#18
03/08/2005 (6:39 pm)
Tom, if you want, you can email me the suspect scripts and I would be glad to take a closer look at them.
#19
03/09/2005 (7:58 am)
It would be a PITA. It's script files and C++ code combined. I haven't tested it, but i think if i stay in first person (meaning no AdvancedCamera) the problem will go away. I need to debug it further... probably enabled the network debug mode.
#20
03/09/2005 (8:30 pm)
We are only talking a few files here. The scripts that handle the login and the commands, and whatever c++ files you think are relevant. I dont need a working copy to find the problem, I only need to look at the code for a few minutes. I'm completely confidential if you have any worries in that respect and would even sign an NDA if you would like.
Page «Previous 1 2