AdvCam integration with RTSCam
by Stephen Zepp · in RTS Starter Kit · 12/11/2004 (7:11 pm) · 12 replies
Vijay, this question is specifically aimed at you, since you appear to have already finished all this! Sorry to cross post, but I had some specific RTSCam questions:
1) It sounds as if you've integrated the advCam to (possibly) use the input techniques that the RTSCam uses. One of the sloppiest things about the advCam orbit mode (which I wrote, so I know how sloppy it is!) is how input was handled--the whole bit about requiring "screen edge" guis, and calling onEnter/onExit to send a cmdToServer change to the server side cam.
--did you wind up making your camera completely client side, or did you use the techniques the RTSCam uses for camera inputs adapted to the advCam Orbit mode? Or did you do something completely different?
2) Did you actually fully integrate the two cameras, or are you allowing a "camera mode switch" between the two? (Or, are you using just one mode). If you're using a mode switch of some sort, did you have any "gotchas" you found that we can avoid?
I understand that your team is pretty strict on what they want you to post here and all, you need to get them into the collaboration spirit and realize that the incremental benefit you return to possible competitors is a lot less than the benefit you gain from sharing information/code! /soapbox off.
1) It sounds as if you've integrated the advCam to (possibly) use the input techniques that the RTSCam uses. One of the sloppiest things about the advCam orbit mode (which I wrote, so I know how sloppy it is!) is how input was handled--the whole bit about requiring "screen edge" guis, and calling onEnter/onExit to send a cmdToServer change to the server side cam.
--did you wind up making your camera completely client side, or did you use the techniques the RTSCam uses for camera inputs adapted to the advCam Orbit mode? Or did you do something completely different?
2) Did you actually fully integrate the two cameras, or are you allowing a "camera mode switch" between the two? (Or, are you using just one mode). If you're using a mode switch of some sort, did you have any "gotchas" you found that we can avoid?
I understand that your team is pretty strict on what they want you to post here and all, you need to get them into the collaboration spirit and realize that the incremental benefit you return to possible competitors is a lot less than the benefit you gain from sharing information/code! /soapbox off.
#2
12/14/2004 (3:03 am)
Sounds pretty interesting. I can't help but wonder how you plan on handling hacks to your executable giving players complete knowledge over everything sent down the wire--since your camera is client side only, that would imply that you have to send all the objects down the wire ahead of time (again, assuming you even -have- a wire, but it sounds like you do), and that means that hackers have the data whenever they want it, even if game mechanics wouldn't let them "see" it unhacked.
#3
12/14/2004 (10:27 pm)
I don't understand what data you're talking about here. The client already has access to all the information it needs to display ghosts, regardless of whether the camera is on the server or not, right? I may be misunderstanding what a potential hacker can do, but I'm not sure how processing the camera on the client executable matters. The code is the same way it would have been if I'd left the server in the loop, except I'm not sending an update event to the server-side camera. How could that affect hacking? Sure, a potential hacker can use the lack of server regulation to put the camera anywhere, but that's okay in my game, he can do that anyways.
#4
In other words no, not all server objects must be sent to the client all the time when the camera is server side. Normally, for bandwidth optimization as well as hack protection, you write scoping rules that make sense for your game.
With your camera only operating client side, you'll have to handle scoping in a different manner, or send all your objects to all your clients all the time. That's a lot of bandwidth and a lot of processing for a decently large game.
Note: I've been assuming here that your project is at least multi-player, and probably some form of remote hosting (either dedicated or peer to peer). If it's single player only, none of the above matter since the client and server processes are "coexecuted" (in the same process).
12/15/2004 (3:29 am)
Unless objects are ScopeAlways, they are only sent to the client when the camera is in "range" of them (assuming you use on onCameraScopeQuery--you can of course use whatever scoping rules you want).In other words no, not all server objects must be sent to the client all the time when the camera is server side. Normally, for bandwidth optimization as well as hack protection, you write scoping rules that make sense for your game.
With your camera only operating client side, you'll have to handle scoping in a different manner, or send all your objects to all your clients all the time. That's a lot of bandwidth and a lot of processing for a decently large game.
Note: I've been assuming here that your project is at least multi-player, and probably some form of remote hosting (either dedicated or peer to peer). If it's single player only, none of the above matter since the client and server processes are "coexecuted" (in the same process).
#5
12/15/2004 (7:11 am)
Well, they sort of do as the networking system is active even in loopback games, but it's not as big a deal as it would otherwise be.
#6
EDIT: Keep in mind that nothing is required in TGE either. You're obviously a pretty experienced developer that happens to be new to TGE (I've been amazed by how quickly you've picked up on stuff since you started posting), and I'm sure that you can come up with solutions to what you need to do!
For what it's worth, I'm pretty certain that WoW implements a client side only camera in a dedicated server setup--the camera is just too damned smooth even when other things are lagging badly in the game, so my guess is that they found an acceptable compromise for object security vs camera performance, enough to go gold with. Blizzard is just too professional an organization to leave themselves open to huge hack vulnerabilities in their object management model to not protect the data somehow.
12/15/2004 (7:43 am)
Good point Ben...I really don't know too much about "standalone" runs of the game (not that I know -that- much about dedicated setups either, but we're learning!)EDIT: Keep in mind that nothing is required in TGE either. You're obviously a pretty experienced developer that happens to be new to TGE (I've been amazed by how quickly you've picked up on stuff since you started posting), and I'm sure that you can come up with solutions to what you need to do!
For what it's worth, I'm pretty certain that WoW implements a client side only camera in a dedicated server setup--the camera is just too damned smooth even when other things are lagging badly in the game, so my guess is that they found an acceptable compromise for object security vs camera performance, enough to go gold with. Blizzard is just too professional an organization to leave themselves open to huge hack vulnerabilities in their object management model to not protect the data somehow.
#7
The rationale I've been able to come up with is this. Correct me if I'm wrong. When my camera is the control object, it's processing input events on both the server and the client, even though they are not communicating with each other. The server-side camera does its onCameraScopeQuery and sends scoped ghost packet updates to the client. This should be the right information, since the client-side camera should be where the server thinks it is (unlike players, the camera is completely driven by input moves, no other forces/collisions/etc... can affect its position). Same moves, same end position for both cameras.
When my camers is not the control object, its position is 100% determined by the target player, who is correctly ghosted from the server. So again, the server camera is going to be where the client camera is going to be.
In this way, although I'm never sending net traffic concerning my camera position, both the server and client cameras should always be in the same place. All this, assuming the "moves" make it to the server. Perhaps I'll schedule periodic updates to account for the scenario in which occasional move packets get lost in transmission.
Does that make sense? Am I potentially missing something?
12/16/2004 (5:10 pm)
Hey Stephen. I've been thinking about this a lot since you originally posted it, since you're absolutely right in what you're saying, yet my camera seems to be scoping correctly, even with a dedicated server. Yes, our game is multi-player and yes we need a dedicated stand-alone server remotely hosting, so this is definitely important to me. The rationale I've been able to come up with is this. Correct me if I'm wrong. When my camera is the control object, it's processing input events on both the server and the client, even though they are not communicating with each other. The server-side camera does its onCameraScopeQuery and sends scoped ghost packet updates to the client. This should be the right information, since the client-side camera should be where the server thinks it is (unlike players, the camera is completely driven by input moves, no other forces/collisions/etc... can affect its position). Same moves, same end position for both cameras.
When my camers is not the control object, its position is 100% determined by the target player, who is correctly ghosted from the server. So again, the server camera is going to be where the client camera is going to be.
In this way, although I'm never sending net traffic concerning my camera position, both the server and client cameras should always be in the same place. All this, assuming the "moves" make it to the server. Perhaps I'll schedule periodic updates to account for the scenario in which occasional move packets get lost in transmission.
Does that make sense? Am I potentially missing something?
#8
However, what happens if you try a setTransform on the camera client side, in the console? At that point, if my understanding of how you are seeing things is correct, your server camera and client camera will be in different positions, and while they both will still follow user inputs, they will continue to be in different positions.
This doesn't sound so bad, since you can disable console, etc., but consider if/when your client gets hacked (and it will by the time your game becomes played, it's almost a certainty), and part of the hack is being able to move the client's camera anywhere the player wants.
Since you are tying the camera's positions between client and server (other than faithfully accepting that they both process inputs, and both started in the same place, therefore both should always be in synch).
I admit however that:
1) I'm not really positive, hehe..this is almost over my head myself, and
2) This brings up some intriguing ideas about how to make a "mostly client side" camera that could isolate camera manipulations from lag...
P.S.: I can think of a couple of other scenarios where you would want to move the camera position server side where your setup would need tweaking to operate properly, but it's not insurmountable. Of course, you would have to do some huge test case/suites to make sure the parallel processing stays in synch, especially in lag situations.
12/16/2004 (5:25 pm)
I would tend to agree that what you are saying appears correct!However, what happens if you try a setTransform on the camera client side, in the console? At that point, if my understanding of how you are seeing things is correct, your server camera and client camera will be in different positions, and while they both will still follow user inputs, they will continue to be in different positions.
This doesn't sound so bad, since you can disable console, etc., but consider if/when your client gets hacked (and it will by the time your game becomes played, it's almost a certainty), and part of the hack is being able to move the client's camera anywhere the player wants.
Since you are tying the camera's positions between client and server (other than faithfully accepting that they both process inputs, and both started in the same place, therefore both should always be in synch).
I admit however that:
1) I'm not really positive, hehe..this is almost over my head myself, and
2) This brings up some intriguing ideas about how to make a "mostly client side" camera that could isolate camera manipulations from lag...
P.S.: I can think of a couple of other scenarios where you would want to move the camera position server side where your setup would need tweaking to operate properly, but it's not insurmountable. Of course, you would have to do some huge test case/suites to make sure the parallel processing stays in synch, especially in lag situations.
#9
1. a setTransform on the camera wouldn't accomplish anything, because the next processTick would set it back to where it should be (my camera's pos is set every tick based on state variables manipulated by inputs, but these state variables are not exposed to the console, it's all done in engine code). The only way to move my camera through the console is to change the $mv variables, but doing this will cause a server side change as well.
2. even if a hacker comes up with a way to move the camera anywhere, as I mentioned before that is already possible in my game in the RTS cam mode. so the hacker would achieve nothing. in fact, hacking his camera to be out of synch with the server will only mess up the game for the hacker, since scoping will be messed up and he won't see anything
3. you're right, i will have scenarios where i will want to force camera movement on the client, but it's purely for cinematic effect, so I can parallel process that stuff as well without worrying too much about them staying in synch. as long as it's deterministic processing (and not based on anything random or system-dependent), it should work. I think.
This is all based on my impressions so far. I wouldn't be surprised to find myself eating my words somewhere down the line. :)
12/16/2004 (5:54 pm)
Well, 1. a setTransform on the camera wouldn't accomplish anything, because the next processTick would set it back to where it should be (my camera's pos is set every tick based on state variables manipulated by inputs, but these state variables are not exposed to the console, it's all done in engine code). The only way to move my camera through the console is to change the $mv variables, but doing this will cause a server side change as well.
2. even if a hacker comes up with a way to move the camera anywhere, as I mentioned before that is already possible in my game in the RTS cam mode. so the hacker would achieve nothing. in fact, hacking his camera to be out of synch with the server will only mess up the game for the hacker, since scoping will be messed up and he won't see anything
3. you're right, i will have scenarios where i will want to force camera movement on the client, but it's purely for cinematic effect, so I can parallel process that stuff as well without worrying too much about them staying in synch. as long as it's deterministic processing (and not based on anything random or system-dependent), it should work. I think.
This is all based on my impressions so far. I wouldn't be surprised to find myself eating my words somewhere down the line. :)
#10
--However, if they've hacked the client to the point where they can actually cause a transform to be applied to the cam, their next step will be to change the state variables directly. Which, as you said, would probably change the server side as well.
2) Yeah, I can see that as well :) It will really come down to how you scope things to the client--stock RTS, everything is based on the visManager (server side imp), which actually has nothing to do with the camera's position in the mission space in any case.
3) Agree!
As I said, you've gotten me a bit intrigued actually...I'm not real excited about having the camera so dependent on the connectivity myself, and may experiment along the lines you went as well--it would certainly make the camera smoother! I can't see any major issues other than the ones we've discussed so far..maybe someone else can chime in and bang us both back into reality with something we never thought of...
12/16/2004 (7:08 pm)
1) Ok, sounds like you've pretty heavily modified the internal workings of the camera then (at least how the RTS cam works--I know I have a setTransform op client side to synch up the client's cam in my imp).--However, if they've hacked the client to the point where they can actually cause a transform to be applied to the cam, their next step will be to change the state variables directly. Which, as you said, would probably change the server side as well.
2) Yeah, I can see that as well :) It will really come down to how you scope things to the client--stock RTS, everything is based on the visManager (server side imp), which actually has nothing to do with the camera's position in the mission space in any case.
3) Agree!
As I said, you've gotten me a bit intrigued actually...I'm not real excited about having the camera so dependent on the connectivity myself, and may experiment along the lines you went as well--it would certainly make the camera smoother! I can't see any major issues other than the ones we've discussed so far..maybe someone else can chime in and bang us both back into reality with something we never thought of...
#11
2) I actually abandoned stock RTS and went back to FPS. Not because I don't like stock RTS, but because it made more sense for my game design.
If you really want to make your camera (any camera) client side only, as far as I can see, all you have to do is tell the server and the client to stop updating each other. This can be accomplished simply by not doing anything in read/writePacketData and pack/unpackUpdate, and by also not sending any other kind of net event. And if you're concerned about losing scoping accuracy, maybe have the client send an update to the server every second or something. Better for the client to be in charge of the camera position, in my opinion (RTSCam uses this approach, as far as I can see). As opposed to everything else, where the server is in charge, which is why the client experiences lag.
I agree, I would love for someone else to chime in here and verify or debunk our thinking.
12/17/2004 (3:30 pm)
1) Ya, I've pretty much moved all the internal workings of the camera into the code. Which is another reason why I don't think it would be much of a plug-and-play solution for anyone else. It's all hardcoded to act a very specific way, and none of it is manipulatable through script. It doesn't even have its own datablock. :) 2) I actually abandoned stock RTS and went back to FPS. Not because I don't like stock RTS, but because it made more sense for my game design.
If you really want to make your camera (any camera) client side only, as far as I can see, all you have to do is tell the server and the client to stop updating each other. This can be accomplished simply by not doing anything in read/writePacketData and pack/unpackUpdate, and by also not sending any other kind of net event. And if you're concerned about losing scoping accuracy, maybe have the client send an update to the server every second or something. Better for the client to be in charge of the camera position, in my opinion (RTSCam uses this approach, as far as I can see). As opposed to everything else, where the server is in charge, which is why the client experiences lag.
I agree, I would love for someone else to chime in here and verify or debunk our thinking.
#12
I've been following this but haven't had anything to add. My needs are a mix of both of yours I think. My clients are more just observers where I could do without the lag but at the same time I need the scoping. Unlike Vijay's camera mine needs to be limited to moving only where units are.
Everything you're both saying makes sense so far.
12/18/2004 (4:21 am)
Guys,I've been following this but haven't had anything to add. My needs are a mix of both of yours I think. My clients are more just observers where I could do without the lag but at the same time I need the scoping. Unlike Vijay's camera mine needs to be limited to moving only where units are.
Everything you're both saying makes sense so far.
Torque Owner Vijay Myneni
Sorry, I don't look at this forum as often, otherwise I would've responded sooner.
1) I fully understand and agree with what you're saying about the collaborative spirit. I am completely okay with posting code and answering all questions to the best of my ability. The only thing I can't do is post entire code files. But I will do my best to share as much as I can.
2) I'm actually using an input technique that is entirely client-side and entirely mouse movement driven. In those respects it's not really like either of the other two cameras. My networking model is this:
a. User holds down the middle mouse button (this sets a script variable)
b. User moves the mouse (this sends a move event via $mvYaw and $mvPitch) or user uses the mouse wheel (I use $mvRoll for that, since I don't need it for anything else)
c. in my camera's processTick, I use the move info to update my camera's target state (position, angles, distance)
d. also in processTick, I update the current state to move closer to the target state.
e. I do absolutely nothing in any of the network-related functions (read/writePacketData and pack/unpackUpdate) except send back and forth the targetPlayer object, if any. And unlike the rtsCam, I also don't send client->server updates (they use update events in the rtsCam).
f. when I'm tracking a target player object, the player is the control object and the camera just uses his state and move processing to decide where to be (except in the case of $mvRoll for zooming. in this case, I have the player update the camera's zoom distance directly.)
So yes, completely client-side (except to keep track of the target player object, which is probably not even necessary if I just use commands to keep the client and server in synch).
I think the best code to look at is the way the RTSCam handles translating the camera, in the situation where you use the arrow keys to move it. What it's doing there is pretty much exactly what I'm doing, except that once it updates itself, it sends a message to the server, which is what I'm not doing.
3. I do employ two different modes based on whether or not the camera or the player is the control object. This is because our game is a hybrid RTS/FPS. The main gotcha's I came across have to do with the cursor. We want a cursor in RTS mode, but not in FPS mode. Getting this to work involved some hacking into guiCanvas.cc, to get around the fact that when there is a cursor, the canvas handles all mouse events before the bindings get a chance to.
Because this is all client-side, I've been able to avoid some of these tricky networking issues you guys seem to be considering.
I hope that answers your questions, if not, let me know. I'm monitoring this thread now.