Precipitation On Clients Only????
by DALO · in Technical Issues · 09/19/2008 (7:01 am) · 35 replies
Hello,
I have been on a quest to try and figure out a way to have precipitation on multiplayer games where only the client will see there own precipitation. Why? well me thinks that it will first of minimize network traffic and it will increase the dynamics of your levels. I need that option where it will be on only 1 client, where as right now if precipitation is started all clients see it. Well what if your level, for example, has an area where a client is in a burnt forest and there are ashes flying around, and in another part of the level a different client is in a rainy swamp? As soon as you start one precipitation the other client will see it and then you'll have 2 different precipitations mixing......Not Good.
I have attempted to send a list of datablock id's of all the necessary precipitation datablocks to all clients that join and create the precipitation using that specific id that was sent from the server. I had no such luck. Any clients that start the precipitation with the keyword 'new' then the object is created but is not found, the client can not see the precipitation. However, using the exact same method the client that was hosting the game, the server, would create the precipitation object when they enter a certain area and when they do, everyone else would then see that precipitation.......
Any other suggestions, thoughts on how to achieve this???
Thx.
I have been on a quest to try and figure out a way to have precipitation on multiplayer games where only the client will see there own precipitation. Why? well me thinks that it will first of minimize network traffic and it will increase the dynamics of your levels. I need that option where it will be on only 1 client, where as right now if precipitation is started all clients see it. Well what if your level, for example, has an area where a client is in a burnt forest and there are ashes flying around, and in another part of the level a different client is in a rainy swamp? As soon as you start one precipitation the other client will see it and then you'll have 2 different precipitations mixing......Not Good.
I have attempted to send a list of datablock id's of all the necessary precipitation datablocks to all clients that join and create the precipitation using that specific id that was sent from the server. I had no such luck. Any clients that start the precipitation with the keyword 'new' then the object is created but is not found, the client can not see the precipitation. However, using the exact same method the client that was hosting the game, the server, would create the precipitation object when they enter a certain area and when they do, everyone else would then see that precipitation.......
Any other suggestions, thoughts on how to achieve this???
Thx.
#2
09/19/2008 (10:05 am)
Yes, I've looked that one over and it's a good find. The only thing is that if I wanted let's say 5 precipitations going then wouldn't that be intense on the network, particularly the client who is the server? If there were only 1 or 2 then this could be very useful........especially if it's single player. It's a good resource ;-)
#3
but i would expect that precipitation has very low network cost.
it's not actually networking each particle,
it's just telling each client to render local precipitation or not.
09/19/2008 (10:18 am)
I'm not super familiar w/ it,but i would expect that precipitation has very low network cost.
it's not actually networking each particle,
it's just telling each client to render local precipitation or not.
#4
09/19/2008 (12:22 pm)
Hmm, that's good to know. But what I'm mostly concerned with, and maybe this is already handled somehow? Is that if I use the localized precipitation and there are many areas using it, let's say 5 for example, then each client will be rendering 5 precip's when they they only need to be doing possibly 1. Just having a quick glance at the precipitation.cc code, maybe if once we get the client's game connection in the processTick function, we can get the distance and if it's greater than X then return. Maybe that'd work IF the localized version is used. Thoughts?
#5
09/19/2008 (1:29 pm)
More importantly, the lighting is not updated when precipitation changes. Your ash area and your swamp area "in different parts of the level" are going to look wierd with the same lighting. Even changing the lighting when it starts to rain isn't trivial.
#6
so having 5 different precipitation areas should be fine.
09/19/2008 (2:36 pm)
Precipitation uses a trick where it only renders around the camera,so having 5 different precipitation areas should be fine.
#7
BTW, your Happy Fun Squiggle Ball was really cool.
09/19/2008 (3:13 pm)
In the resource that you provided above it actually dislodges the precipitation rendering box from the camera's position and is a stand alone box. Hence the "limit rain to an area". I've set this up once before and had several different precipitations going for different areas and it worked, but if you start adding more than probably 3 or 4, depending on your computer, lag starts to be a factor. So when my character is in a building or X units away but still within draw distance, these precipitation boxes became unnecessary rendering objects for that client. So the goal is to come up with a way where different areas will create new precipitations that will only render 1 needed precipitation object for that client. BTW, your Happy Fun Squiggle Ball was really cool.
#8
sounds like you're on the right track, you definitely have a better understanding of that guy than i do.
i'd be interested to hear what you find out.
squiggleball! not to taunt! ;)
09/19/2008 (3:50 pm)
Huh, interesting.sounds like you're on the right track, you definitely have a better understanding of that guy than i do.
i'd be interested to hear what you find out.
squiggleball! not to taunt! ;)
#9
Thx.
09/19/2008 (10:05 pm)
Any suggestions as to how you would make it a non networkable object? What would you need to disable so the network doesn't treat it as a object that is across all clients, but an independant object per client......did that make sense? Can anyone at GG give some insight?Thx.
#10
Ok I just looked at GameBase::onAdd and it looks like GameBaseData has a field "clientOnly" that you need to set true on the PrecipitationData, hopefully that fixes the issue when creating Precipitation on the client who is also the server.
09/19/2008 (10:17 pm)
If you do a commandToClient and create the precipitation inside that, it will only be created for that client. Ok I just looked at GameBase::onAdd and it looks like GameBaseData has a field "clientOnly" that you need to set true on the PrecipitationData, hopefully that fixes the issue when creating Precipitation on the client who is also the server.
#11
Thx.
09/19/2008 (10:28 pm)
Lost me there James, I did a text search in the entire solution and found no text strings as "clientOnly". Is this something you may have added? What essentially would that variable be controlling?Thx.
#12
Here might be the simplest thing to do, if you don't ever need Precipitation object's on the server or to auto-ghost, goto Precipiation::onAdd,
It looks like there is a possibility that onNewDatablock might not get called in this case, so make sure that it is, if not might need to work something out.
09/19/2008 (10:51 pm)
Wasn't something I added, Bah, there I go assuming things are in other versions of the engine. In the future you might also post the engine & version you are working with in forum questions, especially when you post in a non-descript forum like this.Here might be the simplest thing to do, if you don't ever need Precipitation object's on the server or to auto-ghost, goto Precipiation::onAdd,
// change this... mNetFlags.set( Ghostable | ScopeAlways ); // to this... mNetFlags.set( IsGhost );
It looks like there is a possibility that onNewDatablock might not get called in this case, so make sure that it is, if not might need to work something out.
#13
Ok, now that I have sorted out a few audio issues, back to the precip on local clients only. James, I have tried your method as well as trying:
// the book indicates that clients that create the object will render the object only for that client.
mNetFlags.set(Ghostable | LocalOnly)
I think it's LocalOnly, whatever is in that Multiplayer book that Edward M. has released. The precip still does not show? If I call the function that starts the precip in the console, it will then work, which tells me that the function does work. So it seems that creating a new Precipitation on the client side of scripts will not work, unless I'm doing something wrong?.
Is there a way to create a precipitation for a client maybe on the server side? Ideally if a client can invoke the the call then the above code snippet should work only on that particlular client......right?
Any thoughts?
Thx.
10/03/2008 (7:27 am)
Hey All,Ok, now that I have sorted out a few audio issues, back to the precip on local clients only. James, I have tried your method as well as trying:
// the book indicates that clients that create the object will render the object only for that client.
mNetFlags.set(Ghostable | LocalOnly)
I think it's LocalOnly, whatever is in that Multiplayer book that Edward M. has released. The precip still does not show? If I call the function that starts the precip in the console, it will then work, which tells me that the function does work. So it seems that creating a new Precipitation on the client side of scripts will not work, unless I'm doing something wrong?.
Is there a way to create a precipitation for a client maybe on the server side? Ideally if a client can invoke the the call then the above code snippet should work only on that particlular client......right?
Any thoughts?
Thx.
#14
10/03/2008 (8:48 am)
I don't know... Probably you want to just allocate one on the client, and step through its onAdd in C++, and probably have a breakpoint in its render methods as well.
#15
I also tried cutting that code bit and putting it in the processTick function. So everytime it's gonna be rendered check to see if client id's match, if not, don't render.......it crashes as well.
Is there anyway to stop the engine from creating a ghost object for client's who should't have that object?
10/09/2008 (12:31 pm)
Ok, so I've tried a few things and I think I'm getting close.........maybe? When I create a new precip object on the server I also pass the client's id, who calls it, to a Console Method function in engine. There it sets a variable in the engine's precip object of the client (gameConnection id) who called it. What would I want that for you ask??? Well, I was thinking maybe when the engine calls the onAdd() function in the precip code, then I'll compare the Id that is stored for that object to the client that wants to create it, if id's don't match, don't create it. This does work in single player mode.GameConnection* con = GameConnection::getLocalClientConnection(); if(con->getId() != this->precipOwner) return;Additional code was added to the pack/unpack functions so all clients have access to the precipOwner(client who needs the precip). Now from what I understand, onAdd get's called once for the server object and x number of times for the clients, ghost objects, is this a wrong assumption? Anyways, all in all it crashes the client and not the client who is also the server.
I also tried cutting that code bit and putting it in the processTick function. So everytime it's gonna be rendered check to see if client id's match, if not, don't render.......it crashes as well.
Is there anyway to stop the engine from creating a ghost object for client's who should't have that object?
#16
I still think you are better off creating it on the client side in the first place though. That's why I recommended setting the IsGhost flag and then ( if precip is still not working for some reason, eg, failing onAdd or not getting added to the right sceneGraph, etc.. ) step through onAdd to address any problems.
10/09/2008 (1:30 pm)
There is a method in either NetObject or GameConnection like scopeToClient, something like that, which should give you an example of how to ghost a server object to a particular client.I still think you are better off creating it on the client side in the first place though. That's why I recommended setting the IsGhost flag and then ( if precip is still not working for some reason, eg, failing onAdd or not getting added to the right sceneGraph, etc.. ) step through onAdd to address any problems.
#17
I pass in the server id of the object to the above client function to try and obtain the ghost Id so that it can be used in the new precipitation object. BTW, this was compiled as Ghostable and ScopeAlways in precipitation.cc.
Next test, create both precip and precipData on the client, it creates an object and spits out an Id number hooray.....but doesn't render the precip on the client...ah crap......?
The funny thing is is that now the person who is the server/client does exactly what I want perfectly. Just not the clients.
Next test, try to scope the newly created datablock precipitation(specks) to the client
.....
.....
scoping this to a client spits out a Unknown command scopeToClient.
Object specks(1407) specks -> PrecipitationData->GameBaseData->SimDataBlock->SimObject...
Next test, try and get the ghost Id for the client on the server side,.........same thing happens, all I get is 0's and -1's. It's as if the getGhostId stuff doesn't work worth beans..... :-(
Does anyone know how to properly create an object on the client and have it render only on that client??????
Thanks again for any suggestions......
10/12/2008 (8:55 pm)
Ok, I've been experimenting with the different scopes and trying to acquire ghost Id's and resolving ghost id's for networking purposes. As of now, I send a command to the client to create the precip and the precip object doesn't get created as it always spits outQuote:Register object failed for object (null) of class PrecipitationNow I think the problem is is that it doesn't know or have the right datablock to start the object on the client side. I have tried passing the server Id of the precipdata to the client to obtain the ghostId from the server but it always returns 0 or -1. If I use a string such as "specks" for the datablock, it's the same result. Do precipitationData datablocks get ghosted to clients? Why can I not get the ghost Id and create a precipitation on the client side? Here's an example of what my code looks like on the client side:
function clientCmdsetPrecipForThisLevel(%objIndex, %level){
%clientObject11 = ServerConnection.resolveGhostID(%objIndex);
%clientObject22 = ServerConnection.getGhostID(%objIndex);
%clientObject55 = ServerConnection.GetGhostIndex(%objIndex); // modified console object
// all spit out either -1 or 0
...
...I pass in the server id of the object to the above client function to try and obtain the ghost Id so that it can be used in the new precipitation object. BTW, this was compiled as Ghostable and ScopeAlways in precipitation.cc.
Next test, create both precip and precipData on the client, it creates an object and spits out an Id number hooray.....but doesn't render the precip on the client...ah crap......?
The funny thing is is that now the person who is the server/client does exactly what I want perfectly. Just not the clients.
Next test, try to scope the newly created datablock precipitation(specks) to the client
.....
.....
// when the client needs the precip (on server side)
%temp = nameToId("specks")
%temp.scopeToClient(%this)
commandToClient(%this, 'setPrecipForThisLevel', %temp, 2)scoping this to a client spits out a Unknown command scopeToClient.
Object specks(1407) specks -> PrecipitationData->GameBaseData->SimDataBlock->SimObject...
Next test, try and get the ghost Id for the client on the server side,.........same thing happens, all I get is 0's and -1's. It's as if the getGhostId stuff doesn't work worth beans..... :-(
Does anyone know how to properly create an object on the client and have it render only on that client??????
Thanks again for any suggestions......
#18
10/12/2008 (9:32 pm)
Datablock's are already ghosted to clients, however they do not have a 'name' on the client side, BUT they will have the same id! So you should be able to send the id from the server and use it without any ghost-id hooey.
#19
10/12/2008 (10:00 pm)
Hey James, thanks for the quick response. Yeah, tried that already, every client get's a list of all the precip id's from the server and it gives me the same result, object is created but no rendering is done. I've even tried stepping through the precip code in the engine and can't seem to notice anything different? Correct me if I'm wrong but I thought all client's had their own list of Id's for objects that MAY be different from the server's Id list, hence the whole reason why they use the getGhostID and resolveGhostID functions. Anyways, thanks for your input, I'll just have to keep hacking at it until I get lucky.........if that's possible....... ;-)
#20
1. not being added to the client scenegraph ... when i glanced at the code i think it looks at the IsGhost flag ( or your version equivalent ) to see if it should add to the client scene or the server, and since newly allocated precip objects do NOT have that flag (probably need to find a way to set it) it isn't added to the client sceneGraph even though it really IS on the client side.
2. not in view
3. bad world box or other setting that would cause it to have nothing to render.
10/12/2008 (10:09 pm)
You are correct, that's how it works for every ghosted object 'except' datablocks. Their id's are guaranteed to be be same server/client. If its not rendering then that could be any number of things, but I suspect either its either 1. not being added to the client scenegraph ... when i glanced at the code i think it looks at the IsGhost flag ( or your version equivalent ) to see if it should add to the client scene or the server, and since newly allocated precip objects do NOT have that flag (probably need to find a way to set it) it isn't added to the client sceneGraph even though it really IS on the client side.
2. not in view
3. bad world box or other setting that would cause it to have nothing to render.
Associate Orion Elenzil
Real Life Plus