[Help] Keep datablock information when moving from server A to B
by elvince · in Torque 3D Professional · 10/19/2009 (3:44 am) · 9 replies
Hi,
In my game, I will have to run several servers. To reduce the loading time during zoning (move from server A to B), I would like to know if it is feasible to keep all the datablock information on the client when we are killing the 1st server connection.
The servers only differ by the map/mission loaded.
Thanks,
In my game, I will have to run several servers. To reduce the loading time during zoning (move from server A to B), I would like to know if it is feasible to keep all the datablock information on the client when we are killing the 1st server connection.
The servers only differ by the map/mission loaded.
Thanks,
About the author
Recent Threads
#2
10/19/2009 (10:29 am)
There's also a cached datablock resource out on the forums that you can search for that should help as well.
#3
I will look in to this and try to implement a speedup load like in Afx (from a file) because I don't want to share the server source to my clients.
More a recent comment on http://www.garagegames.com/community/resources/view/12879 seems to say that some of the ob is already in T3D engine.
I will try to go deeply into this.
If you have any suggestion or things to avoid/take care of, please update this post.
@Jessel,
I will try to be in touch with Jeff, he will be able to drive me on the good road to do this.
10/19/2009 (3:10 pm)
I found http://www.garagegames.com/community/resources/view/15427 as a resource. Ted Is it the one you are refering to?I will look in to this and try to implement a speedup load like in Afx (from a file) because I don't want to share the server source to my clients.
More a recent comment on http://www.garagegames.com/community/resources/view/12879 seems to say that some of the ob is already in T3D engine.
I will try to go deeply into this.
If you have any suggestion or things to avoid/take care of, please update this post.
@Jessel,
I will try to be in touch with Jeff, he will be able to drive me on the good road to do this.
#4
The datablock transmission and cleanup is done via scripts (do some find in files on the scripts and you'll find where they happen). All you need to do, is to transmit the datablocks only on the first connection and not clean them up when switching servers.
Look in "core/scripts/server/missionDownload.cs". serverCmdMissionStartPhase1Ack() is where the datablocks are sent to the client which is loading the mission, and the callback GameConnection::onDataBlocksDone() right below is called on the server-side gameconnection representing that client when the transmission is done, telling that client to continue the loading process. You only need to make this part more complex and ask the client if they need the datablocks via a commandToClient(), which sends a reply via commandToServer(), which then decides to either send the datablocks or skip them.
Datablocks are identified by their IDs, which are assigned by the order in which they are created (server) or transmitted (clients). If all your server instances have the same datablocks created in the same order, the client should be able to switch servers and keep referencing the correct datablocks.
10/19/2009 (4:04 pm)
@elvince: looking at that resource, it seems to be possible to do it without distributing datablock scripts to the clients.The datablock transmission and cleanup is done via scripts (do some find in files on the scripts and you'll find where they happen). All you need to do, is to transmit the datablocks only on the first connection and not clean them up when switching servers.
Look in "core/scripts/server/missionDownload.cs". serverCmdMissionStartPhase1Ack() is where the datablocks are sent to the client which is loading the mission, and the callback GameConnection::onDataBlocksDone() right below is called on the server-side gameconnection representing that client when the transmission is done, telling that client to continue the loading process. You only need to make this part more complex and ask the client if they need the datablocks via a commandToClient(), which sends a reply via commandToServer(), which then decides to either send the datablocks or skip them.
Datablocks are identified by their IDs, which are assigned by the order in which they are created (server) or transmitted (clients). If all your server instances have the same datablocks created in the same order, the client should be able to switch servers and keep referencing the correct datablocks.
#5
10/19/2009 (6:28 pm)
@Elvince: Yes, that was the one I was referring to.
#6
I agree at 100% on this approach. This will be my first step. I just need to change the loading process and take care to keep mydatablock on the disconnect (in destroyserver function).
10/20/2009 (3:51 am)
@Manoel,I agree at 100% on this approach. This will be my first step. I just need to change the loading process and take care to keep mydatablock on the disconnect (in destroyserver function).
#7
My issue is that, I connect to the server for the 1st time, everything is ok. I disconnect (back to main screen) and I connect again to the same server and the game crash on ShapeBase::unpackUpdate because the datablock associated with the object (mDataBlock) is "empty".
Did I miss something?
Thanks,
10/21/2009 (7:03 pm)
I made a first test by doing the changes below.My issue is that, I connect to the server for the 1st time, everything is ok. I disconnect (back to main screen) and I connect again to the same server and the game crash on ShapeBase::unpackUpdate because the datablock associated with the object (mDataBlock) is "empty".
Did I miss something?
function clientCmdMissionStartPhase1(%seq, %missionName, %musicTrack)
{
// These need to come after the cls.
echo ("*** New Mission: " @ %missionName);
echo ("*** Phase 1: Download Datablocks & Targets");
onMissionDownloadPhase1(%missionName, %musicTrack);
if(!$DatablockLoaded)
commandToServer('MissionStartPhase1Ack', %seq);
else
commandToServer('MissionStartPhase1AckNoDatablock', %seq);
}Add:function serverCmdMissionStartPhase1AckNoDatablock(%client, %seq)
{
//echo("<<<< client will load datablocks from a cache >>>>");
echo(" <<<< skipping datablock transmission >>>>");
// Make sure to ignore calls from a previous mission load
if (%seq != $missionSequence || !$MissionRunning)
return;
if (%client.currentPhase != 0)
return;
%client.currentPhase = 1;
// Start with the CRC
%client.setMissionCRC( $missionCRC );
%client.onDataBlocksDone($missionSequence);
}Add 1 line in:function onPhase1Complete()
{
$DatablockLoaded=true;
}update destroy server withif(!$DatablockLoaded)
deleteDataBlocks();Thanks,
#8
Okay, first, when connecting using a local connection, no datablocks are actually ghosted: since datablocks are strictly addressed by their ID, the local connection directly references the server datablocks (it doesn't create "ghost" copies of them). So when you destroyed your server, your local connection lost its datablocks. Solution: if the client is a localConnection, *always* "transmit" the datablocks (it's safe to do so).
Second: I didn't find any place that explicitly deletes client-side datablocks. So I assume they are added to the ServerConnection object, opened two T3D instances, connected from one to another and checked it out and yes, this is the case. This means that when you disconnect, the ServerConnection is deleted, and with it all client-side datablocks.
To prevent this from happening, you must move the client datablocks somewhere else. Here's a quick and dirty way of doing this: In onDataBlockObjectReceived(), add this:
This will add all client-side datablocks to the DataBlockGroup. For local connections, nothing will change (because the datablocks are already in the DataBlockGroup). This will prevent them from being deleted on disconnect. It also has the side effect that you can delete the client-side datablocks by calling deleteDatablocks() in the client.
10/21/2009 (7:37 pm)
I'm sure there's something missing. You updated destroyServer(), but that's where the server-side datablocks are deleted. The client-side datablocks are deleted elsewhere... lemme search...Okay, first, when connecting using a local connection, no datablocks are actually ghosted: since datablocks are strictly addressed by their ID, the local connection directly references the server datablocks (it doesn't create "ghost" copies of them). So when you destroyed your server, your local connection lost its datablocks. Solution: if the client is a localConnection, *always* "transmit" the datablocks (it's safe to do so).
Second: I didn't find any place that explicitly deletes client-side datablocks. So I assume they are added to the ServerConnection object, opened two T3D instances, connected from one to another and checked it out and yes, this is the case. This means that when you disconnect, the ServerConnection is deleted, and with it all client-side datablocks.
To prevent this from happening, you must move the client datablocks somewhere else. Here's a quick and dirty way of doing this: In onDataBlockObjectReceived(), add this:
DataBlockGroup.schedule(0, add, %index + 3);That "3" is the initial datablock ID. If you ever change that in the source, remember to modify this. The schedule() is needed because the datablock will be created *after* onDataBlockObjectReceived() executes.
This will add all client-side datablocks to the DataBlockGroup. For local connections, nothing will change (because the datablocks are already in the DataBlockGroup). This will prevent them from being deleted on disconnect. It also has the side effect that you can delete the client-side datablocks by calling deleteDatablocks() in the client.
#9
I didn't get to the point that the datablocks were part of the ServerConnection. As the client called the destroy server function, I thought that the datablock were deleted at this time.
I also checked that the delete datablock was not called by another function and this was the case.
May be a stupid question, what the use of datablockgroup in general? is it an object that is used only by the server and there we are hacking it to keep our datablock objects alive after a disconnect on the client side?
Instead of scheduling, it can be better to update simDataBlockEvent::process to add the datablock in the datablockgroup directly in C++. This event should not be used by the server in my "basic" understanding. This will help to avoid issue if the scheduling is fired before the datablock is created.
for the +3, where do you get this information?
Last question, I'm not sure to understand why if the datablock were part of the server connection, we don't need to attach them back on the 2nd connection (the one were you are not loading them). Everything seems to work by it self :D (any sub routine that check if there are already datablock in the group and load them in the new connection?)
Thanks for all,
PS: Yes it's working!!! I need to do further testing in my prototype, but the fast loading seems to work perfectly.
10/22/2009 (4:28 am)
Nice analysis.I didn't get to the point that the datablocks were part of the ServerConnection. As the client called the destroy server function, I thought that the datablock were deleted at this time.
I also checked that the delete datablock was not called by another function and this was the case.
May be a stupid question, what the use of datablockgroup in general? is it an object that is used only by the server and there we are hacking it to keep our datablock objects alive after a disconnect on the client side?
Instead of scheduling, it can be better to update simDataBlockEvent::process to add the datablock in the datablockgroup directly in C++. This event should not be used by the server in my "basic" understanding. This will help to avoid issue if the scheduling is fired before the datablock is created.
for the +3, where do you get this information?
Last question, I'm not sure to understand why if the datablock were part of the server connection, we don't need to attach them back on the 2nd connection (the one were you are not loading them). Everything seems to work by it self :D (any sub routine that check if there are already datablock in the group and load them in the new connection?)
Thanks for all,
PS: Yes it's working!!! I need to do further testing in my prototype, but the fast loading seems to work perfectly.
Torque Owner JesseL
Pyrotronics-Games