Thread: Re: [Opentnl-general] Server vs Client objects
Brought to you by:
mark_frohnmayer,
s_alanet
From: boB G. <boB@Gage.net> - 2005-05-24 11:39:07
|
Mark, Thanks for many good comments and excellent responses! But you're only encouraging me to ask more. :-) I coulda sworn I'd tried that, but I did have several other issues going on at the time and may have made some bad assumptions as to what was causing which problem. When I made that test I was still launching a "game thread" on the server that ticks the game class -- which was one of my big threading issues. I've since moved the game's tick() call into the server's main loop, which gets us past the multi-threading issue (for now at least). So maybe it's time to try the different classes again. :-) You said having a common Player & descending PlayerServer and PlayerClient is not recommended... does that imply that having two classes named Player but implemented differently is the preferred method? Also, in the PlayerClient/PlayerServer method, you mention the alphabetical sorting, does that mean if there's a PlayerDeath object, for example, that it would cause problems because it would land between PlayerClient & PlayerServer when sorted? Going back to your earlier comment: >Simply fixing setMaskBits is not going to be enough to make TNL threadsafe I have to agree. I mutexed (is that a word?) netObject.cpp to ensure no multiple call issues existed within that object and my test still Seg Faulted -- though it took well over 28 hours to do it. I think I've combined our two topics now.... Our designers have decided against a "zone" server solution because of the player's perceived "bounce" at zone edges, so we're locked into a single server handling the entire world (ie one NetInterface). Our plan is to have one or more AI threads, a physics thread, a weather thread, a decay thread, yadda yadda... Each of these threads will need to access data within the various objects that define the things in our world. But I'm not sure I understand how to handle the situation when one of these threads needs to reposition an object, or record damage, or just about anything else that requires mucking around with the object's data... I can mutex every object to allow only one of the server threads access at a time. But, what's to stop OpenTNL from changing things that I'm also changing ( like clearing dirty bits because it just sent an update ). Wait.....an epiphany! Since OpenTNL is not multi-threaded it will only update net object classes during, what, the interface->tick() call? I can mutex around that call to ensure I'm not mucking with data at the same time as OpenTNL . Will that do the trick?? :-) Thanks again! boB >Mark Frohnmayer wrote: > >It would be possible to have > > >Player > PlayerServer > PlayerClient > > >If the client executable does a TNL_IMPLEMENT_NETOBJECT of the >PlayerClient class and the server does a TNL_IMPLEMENT_NETOBJECT of the >PlayerServer class, then ghosts of PlayerServer objects will be >constructed on the client as PlayerClient objects. This is NOT >recommended - it merely takes advantage of the knowledge that all class >names are sorted alphabetically in order to generate mapping ids. > > >You could also have a class named Player in the client executable, and >one in the server and just have different definitions for each class. > > >boB Gage wrote: > > > > I'm having some issues with ghosted objects. In all the examples a > > world object, say a Player class that has TNL::NetObject at the base > > of its inheritance tree, has the same object on both server & client > > sides, meaning that the client has local methods that do server > > operations and vice-versa. > > > > This results in a lot of methods of the form { if (isServer) { ... } > > else { ... } } Since we have separate teams developing server and > > client code it also means that both teams are inside the same files a > > lot, leading to a lot more CVS conflicts than "normal." ( whatever > > that is :) It would be preferable for us to have TNL play with > > abstract classes, with each application defining a final descendant, > > including all server|client-specific code at that level. > > > > By default, TNL appears to require the same object on both sides of > > the connection, but is there a way to allow each application to have > > their own class that TNL plays with as the parent class?? ( much like > > the masterserver example uses an 'interface' class that each side > > descends it's own connection class from ). > > > > Or did I have something completely different going on when I decided > > we couldn't define both ServerGame and ClientGame descended from a > > common Game object that TNL does all its magic on? :-) > > > > > > Thanks in advance! > > boB |
From: Mark F. <ma...@ga...> - 2005-05-24 14:49:16
|
boB Gage wrote: > Mark, > > You said having a common Player & descending PlayerServer and > PlayerClient is not recommended... does that imply that having two > classes named Player but implemented differently is the preferred > method? Also, in the PlayerClient/PlayerServer method, you mention > the alphabetical sorting, does that mean if there's a PlayerDeath > object, for example, that it would cause problems because it would > land between PlayerClient & PlayerServer when sorted? Yes, this is the problem with that approach. Which is why having 2 Player classes (one on the client, one on the server) is the preferred way to do it. > > But I'm not sure I understand how to handle the situation when one of > these threads needs to reposition an object, or record damage, or just > about anything else that requires mucking around with the object's > data... I can mutex every object to allow only one of the server > threads access at a time. But, what's to stop OpenTNL from changing > things that I'm also changing ( like clearing dirty bits because it > just sent an update ). > > Wait.....an epiphany! Since OpenTNL is not multi-threaded it will > only update net object classes during, what, the interface->tick() > call? I can mutex around that call to ensure I'm not mucking with > data at the same time as OpenTNL . Will that do the trick?? :-) This will work, but you may end up blocking for a long time waiting for the network interface to process all the incoming packets, etc. A more optimal solution would involve message passing from the background (non-network) threads that update the state on the object in predictable ways. You could use the TNL ThreadQueue class to pass messages back to objects on the main thread. Another solution would involve using a zone type system where zone processes ghost objects to the main process, and the main process ghosts all objects to players, as well as border objects between zones. |