3
*************************************************************************
5
ArmageTron -- Just another Tron Lightcycle Game in 3D.
6
Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
8
**************************************************************************
10
This program is free software; you can redistribute it and/or
11
modify it under the terms of the GNU General Public License
12
as published by the Free Software Foundation; either version 2
13
of the License, or (at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
***************************************************************************
28
#ifndef ArmageTron_NETOBJECT_H
29
#define ArmageTron_NETOBJECT_H
37
// checks whether n is newer than old; if so, old is set to n and
39
bool sn_Update(unsigned short &old,unsigned short n);
40
bool sn_Update(unsigned long &old,unsigned long n);
42
// here, the high level network protocol is specified.
43
// every entity server and client need to constantly exchange
44
// information about should be a nNetObject.
46
typedef unsigned short nNetObjectID;
48
struct nNetObjectRegistrar;
51
friend class nWaitForAckSync;
53
bool createdLocally; // was the object created on this computer? (alternative: it was created on remote order)
54
unsigned long int lastSyncID_; // the extended id of the last accepted sync message
57
unsigned short id; // the global id; this is the same on all
60
mutable int refCtr_; // how many references from
61
// other netobjects point to here?
63
unsigned short owner; // who owns this object?
64
// on the server, this is the client number of the computer who
65
// controls this object; only from this client,
66
// control messages are accepted.
67
// On the clients, this is just a bool indicating whether we own it
70
mutable tCONTROLLED_PTR( nObserver ) observer_; // this object's observer
72
int syncListID_; // ID for the list of objects to sync
74
class nKnowsAboutInfo{
76
bool knowsAboutExistence:1; // is the creation message through?
77
bool nextSyncAck:1; // should the next sync message wait
79
bool syncReq:1; // should a sync message be sent?
80
int acksPending:4; // how many messages are underway?
83
memset(this, 0, sizeof(nKnowsAboutInfo) );
89
knowsAboutExistence=false;
98
nKnowsAboutInfo knowsAbout[MAXCLIENTS+2];
100
nNetObject *Object(int i);
101
// returns a pointer to the nNetObject
102
// with id=i. If that does not exist yet, wait for it to spawn,
103
// or, on the server, kill the person responsible.
104
// should be only called in constructors.
106
void DoBroadcastExistence();
108
static bool DoDebugPrint(); // tells ClearToTransmit to print reason of failure
110
static nNetObject *ObjectDangerous(int i );
111
// the same thin but returns NULL if the object is not yet available.
113
virtual void AddRef(); // call this every time you add a pointer
114
// to this nNetObject from another nNetObject, so we know when it is
115
// safe to delete this.
116
virtual void Release(); // the same if you remove a pointer to this.
117
// AND: it should be called instead of delete.
118
int GetRefcount() const; // get refcount. Use only for Debgging purposes, never base any decisions on it.
120
virtual void ReleaseOwnership(); // release the object only if it was created on this machine
121
virtual void TakeOwnership(); // treat an object like it was created locally
123
nObserver& GetObserver() const; // retunrs the observer of this object
125
virtual void Dump( tConsole& con ); // dumps object stats
127
unsigned short ID() const{
134
unsigned short Owner() const{
141
inline nMachine & GetMachine() const; //!< returns the machine this object belongs to
143
virtual nDescriptor& CreatorDescriptor() const=0;
145
nNetObject(int owner=-1); // sn_netObjects can be normally created on the server
147
// send the clients a notification that
148
// follows exaclty the same format as the sync command,
149
// but has a different descriptor (the one from CreatorDescriptor() )
150
// and the id and owner are sent, too.
152
// owner=-1 means: this object belongs to us!
155
nNetObject(nMessage &m); // or, if initially created on the
156
// server, via a creation nMessage on the client.
158
virtual void InitAfterCreation(); // after remote creation,
159
// this routine is called
161
// for the internal works, don't call them
162
// static void RegisterRegistrar( nNetObjectRegistrar& r ); // tell the basic nNetObject constructor where to store itself
163
void Register( const nNetObjectRegistrar& r ); // register with the object database
165
virtual ~nNetObject();
166
// if called on the server, the destructor will send
167
// destroy messages to the clients.
169
// you normally should not call this
171
virtual nMachine & DoGetMachine() const; //!< returns the machine this object belongs to
174
// what shall we do if the owner quits the game?
175
// return value: should this object be destroyed?
176
virtual bool ActionOnQuit(){
180
// what shall we do if the owner decides to delete the object?
181
virtual void ActionOnDelete(){
184
// should every other networked computer be informed about
185
// this objects existance?
186
virtual bool BroadcastExistence(){
190
// print out an understandable name in to s
191
virtual void PrintName(tString &s) const;
193
// indicates whether this object is created at peer user.
194
bool HasBeenTransmitted(int user) const;
195
bool syncRequested(int user) const{return knowsAbout[user].syncReq;}
197
// we must not transmit an object that contains pointers
198
// to non-transmitted objects. this function is supposed to check that.
199
virtual bool ClearToTransmit(int user) const;
201
// syncronisation functions:
202
virtual void WriteSync(nMessage &m); // store sync message in m
203
virtual void ReadSync(nMessage &m); // guess what
204
virtual bool SyncIsNew(nMessage &m); // is the message newer
205
// than the last accepted sync
207
// the extra information sent on creation:
208
virtual void WriteCreate(nMessage &m); // store sync message in m
209
// the information written by this function should
210
// be read from the message in the "message"- connstructor
213
// control functions:
216
nMessage *NewControlMessage();
217
// creates a new nMessage that can be used to control other
218
// copies of this nNetObject; control is received with ReceiveControl();
221
virtual void ReceiveControlNet(nMessage &m);
222
// receives the control message. the data written to the message created
223
// by *NewControlMessage() can be read directly from m.
225
/* old version, not good for other games:
226
virtual void SendControl(REAL time,uActionPlayer *Act,REAL x);
227
// is called on the client whenever a control key is pressed. This
228
// sends a message to the server, who will call
229
virtual void ReceiveControl(REAL time,uActionPlayer *Act,REAL x);
230
// on his instance of the nNetObject.
233
// shall the server accept sync messages from the clients?
234
virtual bool AcceptClientSync() const;
237
void GetID(); // get a network ID
238
void RequestSync(bool ack=true); // request a sync
239
void RequestSync(int user,bool ack); // only for a single user
243
static void SyncAll();
244
// on the server, this will send sync tEvents to all clients
245
// for as many sn_netObjects as possible (currently: simply all...)
247
static void ClearAll();
248
// this reinits the list of sn_netObjects. If called on the server,
249
// the clients are cleared, too.
251
static void ClearAllDeleted();
252
// this reinits the list of deleted Objects.
254
static void ClearKnows(int user, bool clear);
256
//give the sn_netObjects new id's after connecting to a server
257
static void RelabelOnConnect();
260
struct nNetObjectRegistrar
263
unsigned short sender;
265
nNetObjectRegistrar* oldRegistrar;
267
nNetObjectRegistrar();
268
~nNetObjectRegistrar();
271
// the list of netobjects for better reference
272
extern tArray<tJUST_CONTROLLED_PTR<nNetObject> > sn_netObjects;
274
// deletes the knowleEdge information of all sn_netObjects for user user
275
void ClearKnows(int user, bool clear = false);
277
void Cheater(int user);
282
extern tArray<unsigned short> sn_netObjectsOwner;
285
// create one of those for every new class of sn_netObjects you define.
286
// you can then remotely spawn other T's
287
// by sending netpackets of type net_initialisator<T>.desc
288
// (correctly initialised, of course...)
290
template<class T> class nNOInitialisator:public nDescriptor{
291
// create a new nNetObject
292
static void Init(nMessage &m){
302
unsigned short id=m.Data(0);
303
//unsigned short owner=m.data(1);
305
if (sn_netObjectsOwner[id]!=m.SenderID() || bool(sn_netObjects[id]))
309
if (!sn_netObjects[id])
311
con << "Netobject " << id << " is already reserved!\n";
315
con << "Netobject " << id << " is already defined!\n";
318
if (sn_netObjectsOwner[id]!=m.SenderID())
320
Cheater(m.SenderID());
326
nNetObjectRegistrar registrar;
327
// nNetObject::RegisterRegistrar( registrar );
328
tJUST_CONTROLLED_PTR< T > n=new T(m);
329
((nNetObject*)n)->ReadSync(m);
330
n->Register( registrar );
336
con << "Received object " << str << "\n";
340
if (sn_GetNetState()==nSERVER && !n->AcceptClientSync())
342
Cheater(m.SenderID()); // cheater!
345
else if ( static_cast< nNetObject* >( sn_netObjects[ n->ID() ] ) != n )
347
// object was unable to be registered
348
n->Release(); // silently delete it.
352
n->InitAfterCreation();
359
con << "nKillHim signal caught.\n";
360
Cheater(m.SenderID());
368
// nNOInitialisator(const char *name):nDescriptor(init,name){};
369
nNOInitialisator(unsigned short id,const char *name):nDescriptor(id,Init,name){};
372
// Z-Man: operators moved here from nNetwork.h. TODO: make them nonmember operators if possible.
373
template<class T> nMessage& operator >> ( nMessage& m, T*& p )
379
p = dynamic_cast<T*> ( nNetObject::ObjectDangerous(id) );
386
template<class T> nMessage& operator >> ( nMessage& m, tControlledPTR<T>& p )
392
p = dynamic_cast<T*> ( nNetObject::ObjectDangerous(id) );
399
// ************************************************************************************
403
// ************************************************************************************
405
//! @return the machine this NetObject belongs to
407
// ************************************************************************************
409
nMachine & nNetObject::GetMachine( void ) const
411
return DoGetMachine();