src/network/nNetObject.h

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023 
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #ifndef ArmageTron_NETOBJECT_H
00029 #define ArmageTron_NETOBJECT_H
00030 
00031 #include "nNetwork.h"
00032 #include "tArray.h"
00033 #include "tConsole.h"
00034 #include <string.h>
00035 
00036 class nObserver;
00037 
00038 // checks whether n is newer than old; if so, old is set to n and
00039 // true is returned.
00040 bool sn_Update(unsigned short &old,unsigned short n);
00041 bool sn_Update(unsigned long &old,unsigned long n);
00042 
00043 // here, the high level network protocol is specified.
00044 // every entity server and client need to constantly exchange
00045 // information about should be a nNetObject.
00046 
00047 typedef unsigned short nNetObjectID;
00048 
00049 struct nNetObjectRegistrar;
00050 
00051 class nNetObject{
00052     friend class nWaitForAckSync;
00053 
00054     bool createdLocally;                 // was the object created on this computer? (alternative: it was created on remote order)
00055     unsigned long int lastSyncID_;  // the extended id of the last accepted sync message
00056 
00057 private:
00058     unsigned short id;  // the global id; this is the same on all
00059     // computers.
00060 
00061     mutable int refCtr_; // how many references from
00062     // other netobjects point to here?
00063 
00064     unsigned short owner; // who owns this object?
00065     // on the server, this is the client number of the computer who
00066     // controls this object; only from this client,
00067     // control messages are accepted.
00068     // On the clients, this is just a bool indicating whether we own it
00069     // or not.
00070 
00071     mutable tCONTROLLED_PTR( nObserver ) observer_;  // this object's observer
00072 
00073     int syncListID_;                                 // ID for the list of objects to sync
00074 public:
00075     class nKnowsAboutInfo{
00076     public:
00077     bool knowsAboutExistence:
00078         1; // is the creation message through?
00079     bool nextSyncAck:
00080         1;         // should the next sync message wait
00081         // for it's ack?
00082     bool syncReq:
00083         1;              // should a sync message be sent?
00084     unsigned int  acksPending:
00085         4;          // how many messages are underway?
00086 
00087         nKnowsAboutInfo(){
00088             memset(this, 0, sizeof(nKnowsAboutInfo) );
00089             Reset();
00090             syncReq=false;
00091         }
00092 
00093         void Reset(){
00094             knowsAboutExistence=false;
00095             nextSyncAck=true;
00096             syncReq=true;
00097             acksPending=0;
00098         }
00099 
00100     };
00101 protected:
00102 
00103     nKnowsAboutInfo knowsAbout[MAXCLIENTS+2];
00104 
00105     nNetObject *Object(int i);
00106     // returns a pointer to the nNetObject
00107     // with id=i. If that does not exist yet, wait for it to spawn,
00108     // or, on the server, kill the person responsible.
00109     // should be only called in constructors.
00110 
00111     void DoBroadcastExistence();
00112 public:
00113     static bool DoDebugPrint(); // tells ClearToTransmit to print reason of failure
00114 
00115     static nNetObject *ObjectDangerous(int i );
00116     // the same thin but returns NULL if the object is not yet available.
00117 
00118     virtual void AddRef(); // call this every time you add a pointer
00119     // to this nNetObject from another nNetObject, so we know when it is
00120     // safe to delete this.
00121     virtual void Release(); // the same if you remove a pointer to this.
00122     // AND: it should be called instead of delete.
00123     int GetRefcount() const; // get refcount. Use only for Debgging purposes, never base any decisions on it.
00124 
00125     virtual void ReleaseOwnership(); // release the object only if it was created on this machine
00126     virtual void TakeOwnership(); // treat an object like it was created locally
00127     bool Owned(){
00128         return createdLocally;    
00129     }
00130 
00131     nObserver& GetObserver() const;    // retunrs the observer of this object
00132 
00133     virtual void Dump( tConsole& con ); // dumps object stats
00134 
00135     unsigned short ID() const{
00136         if (this)
00137             return id;
00138         else
00139             return 0;
00140     }
00141 
00142     unsigned short Owner() const{
00143         if (this)
00144             return owner;
00145         else
00146             return ::sn_myNetID;
00147     }
00148 
00149     inline nMachine & GetMachine() const;  
00150 
00151     virtual nDescriptor& CreatorDescriptor() const=0;
00152 
00153     nNetObject(int owner=-1); // sn_netObjects can be normally created on the server
00154     // and will
00155     // send the clients a notification that
00156     // follows exaclty the same format as the sync command,
00157     // but has a different descriptor (the one from CreatorDescriptor() )
00158     // and the id and owner are sent, too.
00159 
00160     // owner=-1 means: this object belongs to us!
00161 
00162 
00163     nNetObject(nMessage &m); // or, if initially created on the
00164     // server, via a creation nMessage on the client.
00165 
00166     virtual void InitAfterCreation(); // after remote creation,
00167     // this routine is called
00168 
00169     // for the internal works, don't call them
00170     //  static void RegisterRegistrar( nNetObjectRegistrar& r );        // tell the basic nNetObject constructor where to store itself
00171     void Register( const nNetObjectRegistrar& r );    // register with the object database
00172 protected:
00173     virtual ~nNetObject();
00174     // if called on the server, the destructor will send
00175     // destroy messages to the clients.
00176 
00177     // you normally should not call this
00178 
00179     virtual nMachine & DoGetMachine() const;  
00180 public:
00181 
00182     // what shall we do if the owner quits the game?
00183     // return value: should this object be destroyed?
00184     virtual bool ActionOnQuit(){
00185         return true;
00186     }
00187 
00188     // what shall we do if the owner decides to delete the object?
00189     virtual void ActionOnDelete(){
00190     }
00191 
00192     // should every other networked computer be informed about
00193     // this objects existance?
00194     virtual bool BroadcastExistence(){
00195         return true;
00196     }
00197 
00198     // print out an understandable name in to s
00199     virtual void PrintName(tString &s) const;
00200 
00201     // indicates whether this object is created at peer user.
00202     bool HasBeenTransmitted(int user) const;
00203     bool syncRequested(int user) const{
00204         return knowsAbout[user].syncReq;
00205     }
00206 
00207     // we must not transmit an object that contains pointers
00208     // to non-transmitted objects. this function is supposed to check that.
00209     virtual bool ClearToTransmit(int user) const;
00210 
00211     // syncronisation functions (old):
00212     virtual void WriteSync(nMessage &m); // store sync message in m
00213     virtual void ReadSync(nMessage &m); // guess what
00214 
00215     // new
00216     virtual void WriteSync(nMessage &m, int run ); // store sync message in m
00217     virtual void ReadSync(nMessage &m, int run ); // guess what
00218 
00219     virtual bool SyncIsNew(nMessage &m); // is the pure sync message newer than the last accepted sync
00220 
00221     // the extra information sent on creation (old):
00222     virtual void WriteCreate(nMessage &m); // store sync message in m
00223     // the information written by this function should
00224     // be read from the message in the "message"- connstructor
00225 
00226     // new
00227     virtual void WriteCreate(nMessage &m, int run );
00228     virtual void ReadCreate(nMessage &m, int run );
00229 
00230     // the "run" parameter in the new versions is intended to fix the
00231     // compatibility problems when you want to extend the data written in
00232     // WriteCreate(). The old method of writing a creation message was
00233     //
00234     // WriteCreate(m); WriteSync(m);
00235     // and it was read by
00236     // Constructor(m); ReadSync(m);
00237     //
00238     // the new sequence of calls is
00239     // WriteCreate(m,0); WriteSync(m,0); WriteCreate(m,1),WriteSync(m,1)...
00240     // and the new read sequence is
00241     // Constructor(m); ReadSync(m,0), ReadCreate(m,1), ReadSync(m,1)...
00242     // where the write operation continues until no data was written and
00243     // the read operation continues until no data was read.
00244     // the default of the new functions is to call the old ones if "run"
00245     // equals to 0 and do nothing otherwise.
00246 
00247     // these functions handle the process. Note that they are non-virtual.
00248     void WriteAll( nMessage & m, bool create );
00249     void ReadAll ( nMessage & m, bool create );
00250 
00251     // control functions:
00252 
00253 protected:
00255     static int SyncedUser();
00256 
00257     nMessage *NewControlMessage();
00258     // creates a new nMessage that can be used to control other
00259     // copies of this nNetObject; control is received with ReceiveControl();
00260 public:
00261 
00262     virtual void ReceiveControlNet(nMessage &m);
00263     // receives the control message. the data written to the message created
00264     // by *NewControlMessage() can be read directly from m.
00265 
00266     /* old version, not good for other games:
00267     virtual void SendControl(REAL time,uActionPlayer *Act,REAL x);
00268     // is called on the client whenever a control key is pressed. This
00269     // sends a message to the server, who will call
00270     virtual void ReceiveControl(REAL time,uActionPlayer *Act,REAL x);
00271     // on his instance of the nNetObject.
00272     */
00273 
00274     // shall the server accept sync messages from the clients?
00275     virtual bool AcceptClientSync() const;
00276 
00277 
00278     void GetID();                       // get a network ID
00279     void RequestSync(bool ack=true);  // request a sync
00280     void RequestSync(int user,bool ack); // only for a single user
00281 
00282     // global functions:
00283 
00284     static void SyncAll();
00285     // on the server, this will send sync tEvents to all clients
00286     // for as many sn_netObjects as possible (currently: simply all...)
00287 
00288     static void ClearAll();
00289     // this reinits the list of sn_netObjects. If called on the server,
00290     // the clients are cleared, too.
00291 
00292     static void ClearAllDeleted();
00293     // this reinits the list of deleted Objects.
00294 
00295     static void ClearKnows(int user, bool clear);
00296 
00297     //give the sn_netObjects new id's after connecting to a server
00298     static void RelabelOnConnect();
00299 };
00300 
00301 struct nNetObjectRegistrar
00302 {
00303     nNetObject * object;
00304     unsigned short sender;
00305     unsigned short id;
00306     nNetObjectRegistrar* oldRegistrar;
00307 
00308     nNetObjectRegistrar();
00309     ~nNetObjectRegistrar();
00310 };
00311 
00312 // the list of netobjects for better reference
00313 extern tArray<tJUST_CONTROLLED_PTR<nNetObject> > sn_netObjects;
00314 
00315 // deletes the knowleEdge information of all sn_netObjects for user user
00316 void ClearKnows(int user, bool clear = false);
00317 
00318 void Cheater(int user);
00319 
00320 
00321 
00322 
00323 extern tArray<unsigned short> sn_netObjectsOwner;
00324 
00325 
00326 // create one of those for every new class of sn_netObjects you define.
00327 // you can then remotely spawn other T's
00328 // by sending netpackets of type net_initialisator<T>.desc
00329 // (correctly initialised, of course...)
00330 
00331 template<class T> class nNOInitialisator:public nDescriptor{
00332     // create a new nNetObject
00333     static void Init(nMessage &m){
00334 #ifndef NOEXCEPT
00335         try
00336         {
00337 #endif
00338             if (m.DataLen()<2)
00339             {
00340                 nReadError();
00341             }
00342 
00343             unsigned short id=m.Data(0);
00344             //unsigned short owner=m.data(1);
00345 
00346             if (sn_netObjectsOwner[id]!=m.SenderID() || bool(sn_netObjects[id]))
00347             {
00348 #ifdef DEBUG
00349                 st_Breakpoint();
00350                 if (!sn_netObjects[id])
00351                 {
00352                     con << "Netobject " << id << " is already reserved!\n";
00353                 }
00354                 else
00355                 {
00356                     con << "Netobject " << id << " is already defined!\n";
00357                 }
00358 #endif
00359                 if (sn_netObjectsOwner[id]!=m.SenderID())
00360                 {
00361                     Cheater(m.SenderID());
00362                     nReadError();
00363                 }
00364             }
00365             else
00366             {
00367                 nNetObjectRegistrar registrar;
00368                 //                      nNetObject::RegisterRegistrar( registrar );
00369                 tJUST_CONTROLLED_PTR< T > n=new T(m);
00370                 n->InitAfterCreation();
00371                 nNetObject * no = n;
00372                 no->ReadAll(m,true);
00373                 n->Register( registrar );
00374 
00375 #ifdef DEBUG
00376                 /*
00377                 tString str;
00378                 n->PrintName( str );
00379                 con << "Received object " << str << "\n";
00380                 */
00381 #endif
00382 
00383                 if (sn_GetNetState()==nSERVER && !n->AcceptClientSync())
00384                 {
00385                     Cheater(m.SenderID()); // cheater!
00386                     n->Release();
00387                 }
00388                 else if ( static_cast< nNetObject* >( sn_netObjects[ n->ID() ] ) != n )
00389                 {
00390                     // object was unable to be registered
00391                     n->Release(); // silently delete it.
00392                 }
00393             }
00394 #ifndef NOEXCEPT
00395         }
00396         catch (nKillHim)
00397         {
00398             con << "nKillHim signal caught.\n";
00399             Cheater(m.SenderID());
00400         }
00401 #endif
00402     }
00403 
00404 public:
00405     //nDescriptor desc;
00406 
00407     //  nNOInitialisator(const char *name):nDescriptor(init,name){};
00408     nNOInitialisator(unsigned short id,const char *name):nDescriptor(id,Init,name){};
00409 };
00410 
00411 // Z-Man: operators moved here from nNetwork.h. TODO: make them nonmember operators if possible.
00412 template<class T> nMessage& operator >> ( nMessage& m, T*& p )
00413 {
00414     unsigned short id;
00415     m.Read(id);
00416 
00417     if ( 0 != id )
00418         p = dynamic_cast<T*> ( nNetObject::ObjectDangerous(id) );
00419     else
00420         p = NULL;
00421 
00422     return m;
00423 }
00424 
00425 template<class T> nMessage& operator >> ( nMessage& m, tControlledPTR<T>& p )
00426 {
00427     unsigned short id;
00428     m.Read(id);
00429 
00430     if ( 0 != id )
00431         p = dynamic_cast<T*> ( nNetObject::ObjectDangerous(id) );
00432     else
00433         p = NULL;
00434 
00435     return m;
00436 }
00437 
00438 // ************************************************************************************
00439 // *
00440 // *    GetMachine
00441 // *
00442 // ************************************************************************************
00446 // ************************************************************************************
00447 
00448 nMachine & nNetObject::GetMachine( void ) const
00449 {
00450     return DoGetMachine();
00451 }
00452 
00453 #endif
00454 

Generated on Sat Mar 15 22:55:50 2008 for Armagetron Advanced by  doxygen 1.5.4