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 #include "config.h" 00029 #include "tSafePTR.h" 00030 #include <string> 00031 #if HAVE_UNISTD_H 00032 #include <unistd.h> 00033 #endif 00034 #include <iostream> 00035 #include "nNetObject.h" 00036 00037 class floattest: public nNetObject{ 00038 public: 00039 REAL x; // our changing state 00040 REAL y; // our fixed state 00041 00042 // normal constructor 00043 floattest():nNetObject(),x(0),y(1.1){ 00044 con << "created floattest.\n"; 00045 } 00046 00047 // remote constructor 00048 floattest(nMessage &m):nNetObject(m){ 00049 m >> y; 00050 con << "created floattest by remote order from " 00051 << owner << " with fixed state " << y << ".\n"; 00052 // as x is changing, it will be read by the following ReadSync() 00053 } 00054 00055 00056 virtual ~floattest(){ 00057 con << "deleting floattest owned by " << owner << ".\n"; 00058 } 00059 00060 // disable security 00061 virtual bool AcceptClientSync() const{ 00062 return true; 00063 } 00064 00065 // synchronisation: just read and write our state x 00066 virtual void WriteSync(nMessage &m){ 00067 nNetObject::WriteSync(m); 00068 m << x; 00069 } 00070 00071 virtual void ReadSync(nMessage &m){ 00072 nNetObject::ReadSync(m); 00073 00074 m >> x; 00075 00076 // print our state 00077 con << "NAO owned by " << owner << " is in state " << x << "\n"; 00078 } 00079 00080 // our creation write saving only the fixed info 00081 virtual void WriteCreate(nMessage &m){ 00082 nNetObject::WriteCreate(m); 00083 m << y; 00084 } 00085 00086 // control messages order the object to change it's state by 00087 // the transferred number: 00088 virtual void ReceiveControl(nMessage &m){ 00089 nNetObject::ReadSync(m); 00090 00091 REAL diff; 00092 m >> diff; 00093 x+=diff; 00094 00095 // print our state 00096 con << "NAO owned by " << owner << " got order to change by " 00097 << diff<< "; state now is " << x << ".\n"; 00098 00099 RequestSync(); 00100 } 00101 00102 // send a control message 00103 void SendControl(REAL diff){ 00104 // create the message 00105 nMessage *m=NewControlMessage(); 00106 00107 // write order 00108 (*m) << diff; 00109 00110 // send message 00111 m->BroadCast(); 00112 } 00113 00114 // identification: 00115 virtual nDescriptor &CreatorDescriptor() const; 00116 }; 00117 00118 nNOInitialisator<floattest> floattest_init(100,"floattest"); 00119 00120 nDescriptor &floattest::CreatorDescriptor() const{ 00121 return floattest_init; 00122 } 00123 // identification end. 00124 00125 00126 00127 00128 // demonstration how to handle pointers to other netobjects: 00129 class deptest: public nNetObject{ 00130 public: 00131 tCONTROLLED_PTR(floattest) dep; 00132 00133 // normal constructor 00134 deptest(floattest *d):nNetObject(),dep(d){ 00135 con << "created deptest.\n"; 00136 } 00137 00138 // remote constructor 00139 deptest(nMessage &m):nNetObject(m){ 00140 00141 // read in dep's id: 00142 unsigned short id; 00143 m >> id; 00144 dep=(floattest *)Object(id); // find the object with the right ID 00145 00146 con << "created deptest by remote order from " 00147 << owner << ".\n"; 00148 } 00149 00150 virtual ~deptest(){ 00151 con << "deleting deptest owned by " << owner << ".\n"; 00152 } 00153 00154 // disable security 00155 virtual bool AcceptClientSync() const{ 00156 return true; 00157 } 00158 00159 // synchronisation: not needed 00160 00161 // our creation write saving only the fixed info 00162 virtual void WriteCreate(nMessage &m){ 00163 nNetObject::WriteCreate(m); 00164 m << dep->ID(); 00165 } 00166 00167 // identification: 00168 virtual nDescriptor &CreatorDescriptor() const; 00169 00170 // transmission clearence: 00171 virtual bool ClearToTransmit(int user) const{ 00172 return nNetObject::ClearToTransmit(user) && 00173 dep->HasBeenTransmitted(user); 00174 } 00175 }; 00176 00177 nNOInitialisator<deptest> deptest_init(101,"deptest"); 00178 00179 nDescriptor &deptest::CreatorDescriptor() const{ 00180 return deptest_init; 00181 } 00182 // identification end. 00183 00184 00185 unsigned short client_gamestate[MAXCLIENTS+2]; 00186 00187 void server(){ 00188 00189 int loop=100000; // a long delay loop 00190 00191 sn_SetNetState(nSERVER); // initialise server mode 00192 00193 while(loop>0 && sn_GetNetState()!=nSTANDALONE){ // and loop a while 00194 sn_Receive(); 00195 nNetObject::SyncAll(); 00196 sn_SendPlanned(); 00197 00198 loop--; 00199 usleep(10000); 00200 } 00201 00202 sn_SetNetState(nSTANDALONE); // exit. 00203 usleep(10000); 00204 sn_Receive(); 00205 sn_SendPlanned(); 00206 } 00207 00208 00209 void client(const tString &serv){ 00210 tCONTROLLED_PTR(floattest) x=new floattest(); 00211 tCONTROLLED_PTR(deptest) y=new deptest(x); 00212 00213 sn_Connect(serv); // initialise client state and connect to the given server 00214 00215 con << "Demo 1: transfering state by sync messages\n"; 00216 00217 int loop=10; // loop only shortly 00218 while(loop>0 && sn_GetNetState()!=nSTANDALONE){ 00219 nNetObject::SyncAll(); 00220 sn_Receive(); 00221 00222 // change x's state and request a sync with the server 00223 con << "new state: " << (x->x+=1) << "\n"; 00224 x->RequestSync(); 00225 00226 nNetObject::SyncAll(); 00227 sn_SendPlanned(); 00228 sn_Receive(); 00229 sn_SendPlanned(); 00230 00231 loop--; 00232 usleep(1000000); 00233 } 00234 00235 if (loop==0){ 00236 00237 con << "Demo 2: sending control messages. Note the delay in the response\n" 00238 << "caused by the network loop functions not beeing called " 00239 "often enough.\n"; 00240 00241 00242 loop=10; 00243 while(loop>0 && sn_GetNetState()!=nSTANDALONE){ 00244 nNetObject::SyncAll(); 00245 sn_Receive(); 00246 00247 // send a control message, decreasing x's value 00248 x->SendControl(-1); 00249 00250 nNetObject::SyncAll(); 00251 sn_Receive(); 00252 sn_SendPlanned(); 00253 00254 loop--; 00255 usleep(1000000); 00256 } 00257 00258 // get rest of messages 00259 loop=100; 00260 while(loop>0 && sn_GetNetState()!=nSTANDALONE){ 00261 sn_Receive(); 00262 nNetObject::SyncAll(); 00263 sn_SendPlanned(); 00264 00265 loop--; 00266 usleep(1000); 00267 } 00268 } 00269 00270 if (loop==0) 00271 con << "Regular logout..\n"; 00272 00273 sn_SetNetState(nSTANDALONE); 00274 usleep(100000); 00275 sn_Receive(); 00276 sn_SendPlanned(); 00277 } 00278 00279 00280 00281 int main(int argnum,char **arglist){ 00282 if (argnum<=1){ 00283 server(); 00284 } 00285 else{ 00286 client(arglist[1]); 00287 } 00288 }