Game Development Community

Spawning Scene Objects During Mission

by Charlie Sibbach · in Torque Game Engine · 02/16/2006 (5:02 pm) · 6 replies

It's me again.

I was running a little test, and found that either I assumed wrong or I don't get how this stuff works after all.

What I'm trying to do, is like the subject says; create a new scene object after the mission has been loaded. This seems an obvious enough thing to do- the RTS kit must do it for buildings, right? My test was simple. On the server side I made an extra file, exec'd it, containing this:

function serverCmdTestServer()
{
   echo("Creating new tower!");
   new InteriorInstance(TestTower) {
      position = "0 0 0";
      rotation = "1 0 0 0";
      scale = "4 4 4";
      interiorFile = "EV4 Engine/data/interiors/racing/tower1.dif";
      useGLLighting = "0";
      showTerrainInside = "0";
   };
}


Then, after I've started the mission, I open up the console and type commandToServer('TestServer'); and it seems to work just fine- at least, no complaints, and "Creating new tower!" shows up. The problem happens after I'm flying around for a while and I get close enough to the tower that it needs to render the tower- then I get this error (whole excerpt from console log):

==>commandToServer('TestServer');
Creating new tower!
Fatal: (c:\documents and settings\charlie\desktop\sephil saga\engine\interior\interior.cc @ 2112) Bad texture handle in rebuildVertexColors
DirectInput deactivated.

I'm running a lightly-modified 1.4, using the Racing example kit, in single-player mode. Note again, that the error isn't immediate. If, before the error, I switch to the mission editor and do a manual relight, everything works fine.

Do I really need to relight every time I add an object during game play? Is it only scene objects, like interiors? Could I get away with this with a different type of shapebase? Is it because it's a .dif and not a .dts? How does the RTS handle this? I didn't think this would be a problem; I'm very confused. I'm going to continue testing things, but I'd thought I'd get this question out there so that I know what's going on even if I do find something that works.

Thanks as always, you guys rock.
PS: PeerConnection resource on the way soon. Needs packaging.

#1
02/16/2006 (5:23 pm)
Well, I managed to make it work pretty quickly, by switching to a .dts object and a TSStatic (a tree), but I'd still like to know the root cause of my problem, so if anybody knows the definitive answer, I'd love to know it!

Also, I'd like to just make sure I understand the process I'm working with here. When I create a Net Object on the server, it gets scoped as needed, and eventually packed and sent to the client using packUpdate() with the InitialUpdateMask bits set (all of them, right?). The client creates a new ghost of that object, and adds it into the scene to render and work with. Am I right so far?

Now, something I'm not quite sure of is what, if anything, makes a mission file special, and the whole loading mission bit. When you join a server, it downloads all the netobjects and datablocks from the server- those that exist on the server currently, at least. Like most file endings in Torque, .mis could actually be anything, and are technically not necessary- just a useful general abstraction for creating the objects on the server side, right? The only thing that makes the initial mission join process different or special from normal play time is that that's when the datablocks get transmitted, and mission lighting occurs afterwards, which lets .dif objects get properly handled.

A final general question, about what gets loaded on the Server side- When the server ghosts a scene object of some kind, it doesn't send the data file (.dts, .dif) with it, right? So, on remote machines, both client and server need to have that file available in the same spot, right? The server has to load the data file so it can deal with collisions, right? What other files does the server have to load, ie, which need to be both local and remote? My guess is that no .cs files need to be on the client, but no any texture files (.png, .jpg, etc) need to be on the server side. How far am I off?

Again, thanks for any help. I think I understand how Torque works and thinks, but it's so huge I can't know everything, and I still find myself going around in circles of thinking, over even the little stuff.
#2
02/16/2006 (5:23 pm)
It's due to you using an interior dynamically loaded during runtime. The RTS-SK uses .dts shapes for exactly this reason (could of others as well).

DIF shapes gain benefits in rendering, collision, and general performance (portalling, etc.) due to the fact that they have multiple restrictions--one of which is the inability to dynamically create them in the world post-startup.

In addition, there are some additional things you should be doing as part of this creation of the object--I would suggest you take a look at the functions called when your player first enters the game for comparision: /server/scripts/gameconnection.cs--GameConnection::onClientEnterGame();. You'll see that script method, as wel as what it calls, handles loading a dts shape dynamically (as well as things like tying the camera to this shape, setting it as control object, etc.--things you won't have to do for non-player controlled objects).
#3
02/21/2006 (7:05 pm)
Thanks Stephen.

It seems the only thing that OnClientEnterGame() does when creating the player/camera objects is calls "scopeToClient()" on the objects. For my purposes, I need to create a large number of dynamic, non-player controlled objects- for example, crates placed by other players, that just sit there as otherwise normal, static crates- which will be .dts objects. If I interpret this correctly, all I should need to do is create these objects on the server as needed (new CrateObject()) and call scopeToClient() on the new crate.

Can somebody confirm this? What about my summary of object creation, mission files, and ghosting? Do I have it straight? Thanks for the help!
#4
02/21/2006 (7:24 pm)
You don't want to be using the script based scopeToClient on your new objects--scopeToClient basically makes the objects always in scope--even if you are moving very far away from the objects.

Instead, you want your objects to be instantiated from a class (when you use the new operator in script) that is defined as ghostable (something like Item, although Item has a few properties that you may not like--spinning for example, which you can change as one of the parameters when you create the instance).

Objects like that basically handle all the scoping for you, as long as they are a ghostable class (which item is) you'll be fine.
#5
02/22/2006 (4:34 pm)
Got it. I just looked into scopeToClient a little while ago; it just sets some of the NetFlags IIRC. Seems you only want to use it for objects you know you always want to send updates about- such as the player object and the camera object.

The Ghostable part is interesting, but makes perfect sense- you can create a non-ghostable NetObject, although I'm not sure what the use of one is.

You said: "you want your objects to be instantiated from a class (when you use the new operator in script) that is defined as ghostable"

Just so that we're crystal clear here, did you mean "you want to instantiate objects (when you use the new operator in script) that are defined as ghostable"? Also, just to be sure, straight-up Ghosting is one-way only; server to client. The client side will perform physics and whatnot on ghosted objects independently, but only for prediction purposes, right? [Un]PackUpdate is only used going server to client; the client only sends the server Moves and NetEvents.

Also, I'm using the Lighting Kit, but I'm curious about lighting in general. What is the lighting step actually doing? When I create a bunch of DTS objects after the game is running, will they not be lit correctly/as well/cast shadows/all the cool stuff? Or is the lighting step specific to DIF objects?

Thanks for your patience, Stephen, getting all this straight will make my life much less stressful.
#6
02/22/2006 (6:49 pm)
You and I are saying the same thing, I'm just being more specific: You don't mark objects as ghostable or not ghostable from script--it's done as part of the constructor of objects that inherit from GameBase.

Correct, ghosting itself is one-way only, from server to client. The only traffic (other than low level packet tracking and acknowledgements) that is sent client to server are user input moves, and netevents such as when the "commandToServer" script function is used.

The client does perform collision checks and such, but specifically for the control object itself--not for other objects (for the most part anyway). The purpose for this is so that you can get nearly instantaneous response to user inputs on the object that you are controlling. In fact, every "move" you do is applied directly to your client's version of the control object (the orc, for example), and then sent to the server for the authoritative simulation. Updates based on the authoritative simulation are then returned to the controlling client (as well as other clients) as control object updates (or ghosted object updates) and then compared to the client's predicted position, and adjusted in favor of the server's position. For reference, control object updates use write/readPacketData, while ghosted objects use pack/UnpackUpdate.

And yes, the lighting mission phase simply creates lightmaps for difs and terrain. DTS shape lighting are handled differently, during runtime.