Transmission of datablocks during mission load
by Robert Nall · in Torque Game Engine · 10/25/2004 (3:26 pm) · 20 replies
Hey all,
I know there are a ton of posts on datablocks (i've been going through them all day), but I'm not finding a solution to my problem in them.
Here's what's goin' on. I'm rewriting the scripts to have a the mission loading seperate from the creation of the server, so that on the end of a mission, everyon gets dumped out of the mission and goes back to a lobby screen to set up the next mission. My server stuff seems to work great and I'm having no problems with creating and deleting missions with a local client. However, once I got all this to the point where I felt like it was working, I hooked up another client and that client crashes out when the server creates it a new camera.
The problem seems to be that the cameraData datablock doesn't exist on the client. So on the server it's setting:
new Camera = %client.camera{ datablock = camdata };
but the client crashes at this line of code. With checks I've found that the server recognizes the camdata object but the client does not.
Here's the pertinent part of the flow of my mission load:
- call to load mission
- instantGroup set to ServerGroup (ServerGroup was created when the server was created)
- exec the camera script that contains the camdata datablock
- exec the mission file
- check that I got a MissionGroup out of the mission file
- instantGroup set to missionCleanup (missionCleanup was created when the server was created)
- transmitDatablocks with missionSequence = 1
Now if I have the client exec the camera script on its own, everything works fine. However, that's not the way it's done in the starter examples because then presumably a user could edit his data to be different from the server's and cause all kinds of mess. The server is supposed to create and send all the datablocks, right? So I don't want to have the client load all my vehicle and player datablocks.
So, I'm guessing here that I'm missing some detail and I'm hoping someone out there might be able to point it out for me before I pull my hair out.
Thanks,
-Rob
I know there are a ton of posts on datablocks (i've been going through them all day), but I'm not finding a solution to my problem in them.
Here's what's goin' on. I'm rewriting the scripts to have a the mission loading seperate from the creation of the server, so that on the end of a mission, everyon gets dumped out of the mission and goes back to a lobby screen to set up the next mission. My server stuff seems to work great and I'm having no problems with creating and deleting missions with a local client. However, once I got all this to the point where I felt like it was working, I hooked up another client and that client crashes out when the server creates it a new camera.
The problem seems to be that the cameraData datablock doesn't exist on the client. So on the server it's setting:
new Camera = %client.camera{ datablock = camdata };
but the client crashes at this line of code. With checks I've found that the server recognizes the camdata object but the client does not.
Here's the pertinent part of the flow of my mission load:
- call to load mission
- instantGroup set to ServerGroup (ServerGroup was created when the server was created)
- exec the camera script that contains the camdata datablock
- exec the mission file
- check that I got a MissionGroup out of the mission file
- instantGroup set to missionCleanup (missionCleanup was created when the server was created)
- transmitDatablocks with missionSequence = 1
Now if I have the client exec the camera script on its own, everything works fine. However, that's not the way it's done in the starter examples because then presumably a user could edit his data to be different from the server's and cause all kinds of mess. The server is supposed to create and send all the datablocks, right? So I don't want to have the client load all my vehicle and player datablocks.
So, I'm guessing here that I'm missing some detail and I'm hoping someone out there might be able to point it out for me before I pull my hair out.
Thanks,
-Rob
#2
10/26/2004 (9:44 am)
You don't create Camera objects client side... you have to create it on the server and let the networking system ghost it over to the appropriate clients.
#3
This is what I've got:
I have a function similar to the GameConnection::OnClientEnterGame that's defined like this:
function GameConnection::onClientLoadedMission(%client)
{
new Camera = %client.camera
{
datablock = camData;
};
set scope to client
make client.camera camera object
make client.camera control object
}
onClientLoadedMission is called in the serverCmdOnMissionStartPhase3Ack like this:
%client.onClientLoadMission();
Am I missing some ghosting setup somewhere?
-Rob
10/26/2004 (10:30 am)
I'm creating the camera on the server in the client connection object the same way (from what I understand) it's done in the examples.This is what I've got:
I have a function similar to the GameConnection::OnClientEnterGame that's defined like this:
function GameConnection::onClientLoadedMission(%client)
{
new Camera = %client.camera
{
datablock = camData;
};
set scope to client
make client.camera camera object
make client.camera control object
}
onClientLoadedMission is called in the serverCmdOnMissionStartPhase3Ack like this:
%client.onClientLoadMission();
Am I missing some ghosting setup somewhere?
-Rob
#4
10/27/2004 (8:36 am)
. . . bump?
#5
10/27/2004 (9:38 am)
Shouldn't the code be something similar to:%client.camera = new Camera()
{
dataBlock = camData;
};
#6
10/27/2004 (10:17 am)
Yeah, that's right . . . sorry I was typing the lines from memory, but the way you've posted it is the way it's coded in my script.function GameConnection::onClientMissionLoaded(%client)
{
// Create a new camera object.
%client.camera = new Camera()
{
dataBlock = DefaultCam;
};
MissionCleanup.add( %client.camera );
%client.camera.scopeToClient(%client);
//Client controls the camera by default.
%client.setCameraClientControlled();
}
#7
10/27/2004 (11:09 am)
Post the exact console error message. Without that we will be sitting here grasping at straws all day.
#8
I have to asssume I've set something up incorrectly, because it appears to work in the tge examples just fine. However, I can't find what it is that I've done differently. I was hoping there was someone who knew about the datablock transfer system and could point out that I hadn't set so-and-so global or I didn't add the newly defined datablocks into some sort of package that the server automatically sends on the call to transferDatablocks(). Unfortunately no one seems to have an answer for this one at the moment and I have other work to do this week so I can't get back on it until next week.
So I'll rephrase my question in hopes of providing people a different perspective. If I load a datablock on my server and use transferDatablocks(), should I expect that the client now has a copy of that datablock in memory that would pass an isOBject() call? If so, how do I make sure the server is sending said datablock?
Thanks,
-Rob
10/27/2004 (12:43 pm)
If there were any errors, believe me you'd have had them in the initial post. However, there is no error, it's a hard crash on the client when the server assigns the client a camera object. After fussing with it for three days, I've come to the conclusion that the server is not sending all the datablocks correctly. When the client knows the datablock for the camera the server's assigned it (done by having the client explicitly load the camera.cs file), the game runs fine, when the client doesn't know the datablock (just relying on transmitDatablocks()), it crashes.I have to asssume I've set something up incorrectly, because it appears to work in the tge examples just fine. However, I can't find what it is that I've done differently. I was hoping there was someone who knew about the datablock transfer system and could point out that I hadn't set so-and-so global or I didn't add the newly defined datablocks into some sort of package that the server automatically sends on the call to transferDatablocks(). Unfortunately no one seems to have an answer for this one at the moment and I have other work to do this week so I can't get back on it until next week.
So I'll rephrase my question in hopes of providing people a different perspective. If I load a datablock on my server and use transferDatablocks(), should I expect that the client now has a copy of that datablock in memory that would pass an isOBject() call? If so, how do I make sure the server is sending said datablock?
Thanks,
-Rob
#9
10/27/2004 (3:13 pm)
Are you sure the server is executing the file the camera datablock is in? Double check your datablock names as well, your referencing "DefaultCam" when possibly you named it something else. I have only ever had a datablock problem when trying to declare a new block after the load sequence.
#10
The camera creation code is correct. It's lifted straight from a previous version. The camera creation code isn't the problem. The problem is that datablocks that I'm creating on the server ARE NOT getting to clients. It's not just the DefaultCam datablock. Any datablock I create that's not in a MissionGroup in my mission file is not getting sent to the clients. I'm just trying to figure out the specifics of transferring datablocks and how to be sure that everything I create on my server is going to get to the client.
-Rob
10/27/2004 (3:41 pm)
Yup, the console tells me it's loaded the camera.cs script and I've done an isObject() check on DefaultCam on the server and the client both, the server has it, and the client does not. The client crashes and the server does not. The host client creates the camera and shows the mission. The connecting client crashes to the desktop. If I explicitly tell the connecting client to load the camera.cs file, the camera gets created and displays the mission on both machines just fine. The camera creation code is correct. It's lifted straight from a previous version. The camera creation code isn't the problem. The problem is that datablocks that I'm creating on the server ARE NOT getting to clients. It's not just the DefaultCam datablock. Any datablock I create that's not in a MissionGroup in my mission file is not getting sent to the clients. I'm just trying to figure out the specifics of transferring datablocks and how to be sure that everything I create on my server is going to get to the client.
-Rob
#11
10/28/2004 (10:46 am)
Bump : (
#12
[Edit] Hmmm, that thread is in the SDK area, so you need to be an SDK owner to view it. Here is an extract:
Interesting new development. If I don't scope the camera the the client in the bad variant of the code, it works !!!
ie.
strange, since the other version does this, and there is no problem with that one...
10/29/2004 (9:00 am)
Check the resolution in this thread, and see if it works for you.[Edit] Hmmm, that thread is in the SDK area, so you need to be an SDK owner to view it. Here is an extract:
Interesting new development. If I don't scope the camera the the client in the bad variant of the code, it works !!!
ie.
function GameConnection::OnClientEnterGame(%this)
{
// Create a new camera object.
%this.camera = new Camera() {
dataBlock = Observer;
};
MissionCleanup.add( %this.camera );
// %this.camera.scopeToClient(%this); <-- commented out this line
%this.CreatePlayer("0 0 300 1 0 0 0");
}strange, since the other version does this, and there is no problem with that one...
#13
Note that the client only gets datablock's IDs, not their names.
10/29/2004 (1:20 pm)
How are you defining your datablocks? With new or datablock?Note that the client only gets datablock's IDs, not their names.
#14
10/29/2004 (2:51 pm)
To make this easy you should just create a camera group outside MissionCleanup and set each camera to the camera group instead of mission cleanup. That way a client can just keep his one camera untill he leaves the server which is when GameConnection::onDrop will call GameConnection::onClientLeaveGame(%this) and they will be deleted for you.
#15
You said in an earlier post:
As far as I am aware, you always have to exec in the code for a particular client side object. Note that exec doesn't actually call functions in your script file directly, it just makes them available for reference by the console.
In other words, when you create an object server side with the intent of having it transmitted to the client, the server doesn't actually send ALL of the required information to have the console instantiate the object--it just ties a client version of the object with the server object as a "master".
I still don't think I'm saying what I want very well, but I'm pretty sure you have to exec in the .cs files for any objects that are created server side, regardless of the fact that you are transmitting the datablock(s).
10/29/2004 (3:06 pm)
I've wanted to post on this thread 5 times now, and I'm still not sure I'm right, but I wanted to throw this out there:You said in an earlier post:
Quote:When the client knows the datablock for the camera the server's assigned it (done by having the client explicitly load the camera.cs file), the game runs fine, when the client doesn't know the datablock (just relying on transmitDatablocks()), it crashes.
As far as I am aware, you always have to exec in the code for a particular client side object. Note that exec doesn't actually call functions in your script file directly, it just makes them available for reference by the console.
In other words, when you create an object server side with the intent of having it transmitted to the client, the server doesn't actually send ALL of the required information to have the console instantiate the object--it just ties a client version of the object with the server object as a "master".
I still don't think I'm saying what I want very well, but I'm pretty sure you have to exec in the .cs files for any objects that are created server side, regardless of the fact that you are transmitting the datablock(s).
#16
10/30/2004 (3:04 am)
The client should never ever ever execute any line defining a datablock.
#17
10/30/2004 (4:49 am)
EDIT: I stand corrected--I searched through my client environment, and we do not have a camera.cs anywhere, so I guess I misunderstand how client instantiation of a server side object works--my bad, sorry.
#18
@Ben
This is my datablock call:
Also, is there a way I can check the datablock ID's on the client side? From what I can tell transmitDatablocks is not sending anything to the client. Right now the only datablock in the game is the camrea one shown above and the clients don't seem to be getting it from the server.
11/02/2004 (9:45 am)
Hey all, I was out of town for the weekend, so I'm just now getting to these responses . . .@Ben
This is my datablock call:
datablock CameraData(DefaultCam)
{
mode = "Observer";
};Also, is there a way I can check the datablock ID's on the client side? From what I can tell transmitDatablocks is not sending anything to the client. Right now the only datablock in the game is the camrea one shown above and the clients don't seem to be getting it from the server.
#19
The client doesn't like it if you use datablock 0 as a camera datablock.
I don't know if that's true for everythingthat uses a datablock because right now I have no other objects getting created. But after thorough testing I've found that I have to have at least two datablocks for the game to work and I can't use the first one created.
Is this a known issue that I wasn't aware of for all objects created with datablocks, or is this something new and/or only pertinent to camera data?
-Rob
11/02/2004 (11:03 am)
Ok, so I've found the real problem.The client doesn't like it if you use datablock 0 as a camera datablock.
I don't know if that's true for everythingthat uses a datablock because right now I have no other objects getting created. But after thorough testing I've found that I have to have at least two datablocks for the game to work and I can't use the first one created.
Is this a known issue that I wasn't aware of for all objects created with datablocks, or is this something new and/or only pertinent to camera data?
-Rob
#20
11/02/2004 (11:46 am)
It might be that the camera does an id comparison with an erroneous value. Ie, if(db.id > 1) or something similar.
Torque Owner Robert Nall