Server/Client scheduling questions
by Jason Gossiaux · in Torque Game Engine · 11/18/2007 (10:44 am) · 7 replies
Hello there,
I was hoping to get a feel for what way to best implement scheduling in a multiplayer game using TGE. Right now my current project is adding accelerated real time day/night transitions with seasons.
Initially I thought, ok I'll setup a schedule on the server, and it will raise an update event every 5 seconds on each connected client. The event will then perform the necessary updating on that client so the sun/sky/lighting fits the gametime.
But that sounded kind of tricky, and maybe a better method existed. So the other option turned out to be having each client start off a scheduler as it came up. The scheduler grabs some data off the server every X seconds that tells it how to update its sun/sky/lighting.
I am favoring option 2, because then the client can ask for just the information it wants, when it wants. Say someone has turned down their detail settings and they want to update their lighting every 10 seconds, not every 5. That would be much easier to code I think. But I'm not sure if it would be the best method for things like AI and score keeping.
Heh, I'm still trying to understand the engine, as well as good game architecture. Any insight would be appreciated.
I was hoping to get a feel for what way to best implement scheduling in a multiplayer game using TGE. Right now my current project is adding accelerated real time day/night transitions with seasons.
Initially I thought, ok I'll setup a schedule on the server, and it will raise an update event every 5 seconds on each connected client. The event will then perform the necessary updating on that client so the sun/sky/lighting fits the gametime.
But that sounded kind of tricky, and maybe a better method existed. So the other option turned out to be having each client start off a scheduler as it came up. The scheduler grabs some data off the server every X seconds that tells it how to update its sun/sky/lighting.
I am favoring option 2, because then the client can ask for just the information it wants, when it wants. Say someone has turned down their detail settings and they want to update their lighting every 10 seconds, not every 5. That would be much easier to code I think. But I'm not sure if it would be the best method for things like AI and score keeping.
Heh, I'm still trying to understand the engine, as well as good game architecture. Any insight would be appreciated.
About the author
#2
Actually, fxSunLight already has everything being sent in packUpdate, but it only does so when fxSunLightConfigChangeMask is set. As long as you use the correct console functions, setSunAzimuth/setSunElevation, this mask will be set and all clients will be updated with the new sun position. Just changing the value in script without using the set functions will not result in the mask being set, so don't do that.
The Sky class will take a little more effort, as it only sends updates on InitMask, in other words when first initialized. You could set InitMask, but that might result in sending way more data than you want to. Best to just add an update mask and send only the stuff you intend to change. There are no setFunctions for Sky's various parameters, so you'll want to add them and have those functions set your new update mask. Make sure to make consoleMethod links to those functions.
Probably sounds like more effort than you wanted, but that's the correct way to get it done, and the only way to be sure your time of day system isn't easily disabled by the client.
The best solution, but the one requiring the most effort, is to then actually build time of day into the appropriate classes. You'll still end up with script hooks, but all the work will be done in code. You'll want these script functions:
-setTimeOfDay(hours, minutes, seconds)
-setTimeOfDaySpeed(speedMultiplier) // can be negative to rewind time of day, 0 to stop
-setTimeOfDayState(hours, minutes, seconds) // save the current world state as the defined state for
hours:minutes:seconds.
Here's what will actually happen: Assuming at least 2 states have been saved, the sun and sky params will interpolate between states every frame. In other words, if you have a state set at 12:00 and another state set at 14:00, then at 13:00 it will be an exact 50/50 mix of those two states. When you reach 14:00, it will be 100% that state. The next minute, it will start interpolating with the next state (even if that next state is 12:00 again, it'll just take 22 hours of interpolation to get back to it).
You can set at many states as you want to increase the detail, but it'll always be frame by frame.
11/18/2007 (4:23 pm)
Personally, I would do all the work on the server, then just modify the sun/sky objects to properly update their client ghosts via packUpdate. That way you won't need to run scheduled script events on the client, which is really an ugly way to get it done, and potentially breakable by malicious users. Anyone who manages to break into the client-side script elements would be able to control their view distance and lighting, or at least simply break the ToD system.Actually, fxSunLight already has everything being sent in packUpdate, but it only does so when fxSunLightConfigChangeMask is set. As long as you use the correct console functions, setSunAzimuth/setSunElevation, this mask will be set and all clients will be updated with the new sun position. Just changing the value in script without using the set functions will not result in the mask being set, so don't do that.
The Sky class will take a little more effort, as it only sends updates on InitMask, in other words when first initialized. You could set InitMask, but that might result in sending way more data than you want to. Best to just add an update mask and send only the stuff you intend to change. There are no setFunctions for Sky's various parameters, so you'll want to add them and have those functions set your new update mask. Make sure to make consoleMethod links to those functions.
Probably sounds like more effort than you wanted, but that's the correct way to get it done, and the only way to be sure your time of day system isn't easily disabled by the client.
The best solution, but the one requiring the most effort, is to then actually build time of day into the appropriate classes. You'll still end up with script hooks, but all the work will be done in code. You'll want these script functions:
-setTimeOfDay(hours, minutes, seconds)
-setTimeOfDaySpeed(speedMultiplier) // can be negative to rewind time of day, 0 to stop
-setTimeOfDayState(hours, minutes, seconds) // save the current world state as the defined state for
hours:minutes:seconds.
Here's what will actually happen: Assuming at least 2 states have been saved, the sun and sky params will interpolate between states every frame. In other words, if you have a state set at 12:00 and another state set at 14:00, then at 13:00 it will be an exact 50/50 mix of those two states. When you reach 14:00, it will be 100% that state. The next minute, it will start interpolating with the next state (even if that next state is 12:00 again, it'll just take 22 hours of interpolation to get back to it).
You can set at many states as you want to increase the detail, but it'll always be frame by frame.
#4
James - I rewrote the lighting code. I will selectively relight 1 interior every 5 seconds, and the terrain every minute or so. Time isn't going by quick enough for it to be noticeable, and selective lightmap generation is fast enough for it to not hog resources.
Karen - The celestial day/night code is very old, and since I am new to the engine I didn't want to confuse myself. Its also better if I just design my own method as I don't think anyone has rewritten the lighting code like I have to do what I'm trying to do.
Henry - Ok so I'll do the scheduling on the server. When the game starts I will simply kick off a schedule that runs every 5 seconds. It will loop through all the clients and send them a clientcommand with arguments to run on the appropriate class functions.
When and where is a good place to setup this scheduler? I've traced the script code through the common directory/files into my game directory/files... it can be kind of confusing how it all works. I found that if I tried accessing the ClientGroup too early, no clients were present. Is starting the scheduler after onMissionDownloadComplete() a good spot? I figure I'll be adding more schedulers soon for things like AI and other fun stuff. So its good to put it in a place that makes sense.
Thanks for the helpful ideas everyone.
11/18/2007 (11:31 pm)
Hmm, let me explain a bit...James - I rewrote the lighting code. I will selectively relight 1 interior every 5 seconds, and the terrain every minute or so. Time isn't going by quick enough for it to be noticeable, and selective lightmap generation is fast enough for it to not hog resources.
Karen - The celestial day/night code is very old, and since I am new to the engine I didn't want to confuse myself. Its also better if I just design my own method as I don't think anyone has rewritten the lighting code like I have to do what I'm trying to do.
Henry - Ok so I'll do the scheduling on the server. When the game starts I will simply kick off a schedule that runs every 5 seconds. It will loop through all the clients and send them a clientcommand with arguments to run on the appropriate class functions.
When and where is a good place to setup this scheduler? I've traced the script code through the common directory/files into my game directory/files... it can be kind of confusing how it all works. I found that if I tried accessing the ClientGroup too early, no clients were present. Is starting the scheduler after onMissionDownloadComplete() a good spot? I figure I'll be adding more schedulers soon for things like AI and other fun stuff. So its good to put it in a place that makes sense.
Thanks for the helpful ideas everyone.
#5
GameConnection::onClientEnterGame() // for time cycle scheduling
AIPlayer::OnAdd() // for AI stuff
11/19/2007 (12:42 pm)
Some other possibilities:GameConnection::onClientEnterGame() // for time cycle scheduling
AIPlayer::OnAdd() // for AI stuff
#6
11/19/2007 (11:34 pm)
I was starting it in OnMissionDownloadComplete... but I guess that function gets called at the end of the relighting code. Created one nasty recursive loop that had me scratching my head for a while haha! I'll try one of those other two methods.
#7
$gMyScheduleID = 0;
11/20/2007 (9:21 am)
When i have a schedule which i want to happen repeatedly, i generally do something like the following:$gMyScheduleID = 0;
function foo()
{
if ($gMyScheduleID != 0)
cancel($gMyScheduleID);
$gMyScheduleID = 0;
// do stuff
$gMyScheduleID = schedule(args);
}
Associate James Ford
Sickhead Games
Also, relighting the TGE scene is not a quick thing to do ... If you are in the mission editor and change, say, the sunlight color, you will see no immediate change, you must tell it to "relight scene" first, and this doesn't happen very quickly either.
I'm not sure if you already have a conceptual idea of how you will accomplish this but I don't think it is supported by default and you will likely need to make C++ changes to the engine.