00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "eNetGameObject.h"
00029 #include "ePlayer.h"
00030 #include "eLagCompensation.h"
00031 #include "eTimer.h"
00032 #include "uInput.h"
00033 #include "eGrid.h"
00034 #include "eTeam.h"
00035 #include "eTess2.h"
00036
00037
00038
00039 #define MAX_PING_OVERFLOW 3
00040 #define PING_OVERFLOW_TS .1
00041
00042
00043 static REAL se_GetPing( ePlayerNetID * player )
00044 {
00045 REAL peer_ping=0;
00046 REAL my_ping=0;
00047
00048 if (bool(player) && player->Owner()!=::sn_myNetID)
00049 {
00050 if (sn_GetNetState()!=nSERVER)
00051 peer_ping+=player->ping;
00052 else
00053 peer_ping+=sn_Connections[player->Owner()].ping;
00054 }
00055 if (sn_GetNetState()!=nSERVER && (!player || player->Owner()!=::sn_myNetID))
00056 my_ping+=sn_Connections[0].ping;
00057
00058 REAL ping = (peer_ping+my_ping)*.5;
00059
00060 if (ping>my_ping+sn_pingCharityServer*.001)
00061 ping=my_ping+sn_pingCharityServer*.001;
00062
00063 if (ping<my_ping-sn_pingCharityServer*.001)
00064 ping=my_ping-sn_pingCharityServer*.001;
00065
00066 return ping;
00067 }
00068
00069 void eNetGameObject::MyInitAfterCreation(){
00070 laggometer=laggometerSmooth=0;
00071
00072 if (player){
00073 player->ControlObject(this);
00074 }
00075 clientside_action();
00076
00077 pingOverflow=0;
00078 }
00079
00080 void eNetGameObject::InitAfterCreation(){
00081 nNetObject::InitAfterCreation();
00082 MyInitAfterCreation();
00083 }
00084
00085 eNetGameObject::eNetGameObject(eGrid *grid, const eCoord &pos,const eCoord &dir,
00086 ePlayerNetID* p,bool autodelete)
00087 :eGameObject(grid, pos,dir,NULL,autodelete),
00088 nNetObject(p->Owner()),player(p){
00089 lastClientsideAction=0;
00090 if (sn_GetNetState()!=nCLIENT)
00091 RequestSync();
00092 MyInitAfterCreation();
00093 }
00094
00095
00096
00097 eNetGameObject::eNetGameObject(nMessage &m)
00098 :eGameObject(eGrid::CurrentGrid(), eCoord(0,0), eCoord(0,0), NULL),
00099 nNetObject(m){
00100 tASSERT(grid);
00101
00102 lastClientsideAction=0;
00103 unsigned short pid;
00104 m.Read(pid);
00105 player=static_cast<ePlayerNetID *>(Object(pid));
00106 m.Read(pid);
00107 autodelete=pid;
00108
00109 laggometerSmooth=laggometer=0;
00110
00111 pingOverflow=0;
00112 }
00113
00114 void eNetGameObject::DoRemoveFromGame(){
00115
00116 tControlledPTR< eNetGameObject > bounce;
00117 if ( this->GetRefcount() >= 0 )
00118 bounce = this;
00119
00120
00121 if ( player && this == player->object )
00122 {
00123 player->object = NULL;
00124 }
00125
00126 team = NULL;
00127 }
00128
00129 eNetGameObject::~eNetGameObject(){
00130 if (player){
00131 #ifdef DEBUG
00132
00133 #endif
00134 if (player->object==this){
00135 player->object=NULL;
00136 }
00137 }
00138 }
00139
00140
00141
00142 bool eNetGameObject::SyncIsNew(nMessage &m){
00143 bool ret=nNetObject::SyncIsNew(m);
00144 m >> lastAttemptedSyncTime;
00145
00146 #ifdef DEBUG
00147 if (Owner()==::sn_myNetID && lastAttemptedSyncTime>lastClientsideAction+100){
00148 con << "Warning! time overflow!\n";
00149 }
00150 #endif
00151
00152 eCoord dummy;
00153 m >> dummy;
00154 m >> dummy;
00155 return (ret);
00156 }
00157
00158 void eNetGameObject::AddRef()
00159 {
00160 nNetObject::AddRef();
00161 }
00162
00163 void eNetGameObject::Release()
00164 {
00165 nNetObject::Release();
00166 }
00167
00168
00169 void eNetGameObject::ReceiveControlNet(nMessage &m){
00170 REAL time;
00171 unsigned short act_id;
00172 REAL x;
00173
00174 m >> time;
00175 m.Read(act_id);
00176 m >> x;
00177
00178 REAL backdate=Lag();
00179 if (backdate>sn_pingCharityServer*.001)
00180 backdate=sn_pingCharityServer*.001;
00181
00182 REAL mintime=se_GameTime()-backdate*1.5-.1;
00183 if (time<mintime){
00184 con << "mintime\n";
00185 REAL pov_needed=mintime-time;
00186 if (pov_needed+pingOverflow > MAX_PING_OVERFLOW*backdate){
00187 pov_needed = MAX_PING_OVERFLOW*backdate-pingOverflow;
00188 con << "Mintime\n";
00189 }
00190 if (pov_needed<0)
00191 pov_needed=0;
00192
00193 time=mintime-pov_needed;
00194 pingOverflow+=pov_needed;
00195 }
00196
00197 if (time>se_GameTime()+1)
00198 time=se_GameTime()+1;
00199
00200 uActionPlayer *Act=uActionPlayer::Find(act_id);
00201
00202 ReceiveControl(time,Act,x);
00203 }
00204
00205
00206 void eNetGameObject::SetPlayer(ePlayerNetID* a_player)
00207 {
00208 tASSERT( !a_player || Owner() == player->Owner() );
00209 player = a_player;
00210 if ( laggometerSmooth == 0 && sn_GetNetState() != nCLIENT )
00211 laggometerSmooth = laggometer = se_GetPing( player );
00212 }
00213
00214 void eNetGameObject::SendControl(REAL time,uActionPlayer *Act,REAL x){
00215 if (sn_GetNetState()==nCLIENT && Owner()==::sn_myNetID){
00216
00217 nMessage *m=NewControlMessage();
00218 *m << time;
00219 m->Write(Act->ID());
00220 *m << x;
00221 m->BroadCast();
00222 }
00223 }
00224
00225 void eNetGameObject::ReceiveControl(REAL time,uActionPlayer *Act,REAL x){
00226 #ifdef DEBUG
00227 if (sn_GetNetState()==nCLIENT)
00228 tERR_ERROR("rec_cont should not be called client-side!");
00229 #endif
00230
00231
00232
00233
00234 RequestSync();
00235 }
00236
00237
00238 void eNetGameObject::WriteCreate(nMessage &m){
00239 nNetObject::WriteCreate(m);
00240 m.Write(player->ID());
00241 m.Write(autodelete);
00242 }
00243
00244 void eNetGameObject::WriteSync(nMessage &m){
00245 nNetObject::WriteSync(m);
00246
00247 m << lastTime;
00248 m << Direction();
00249 m << Position();
00250 }
00251
00252 void eNetGameObject::ReadSync(nMessage &m){
00253 nNetObject::ReadSync(m);
00254 m >> lastTime;
00255 m >> dir;
00256
00257 m >> pos;
00258 }
00259
00260
00261
00262
00263
00264
00265 bool eNetGameObject::ClearToTransmit(int user) const{
00266 #ifdef DEBUG
00267 if (nNetObject::DoDebugPrint())
00268 {
00269 if (eTransferInhibitor::no_transfer(user))
00270 {
00271 con << "Not transfering eNetGameObject " << ID()
00272 << " for user " << user << " because of some obscure reason.\n";
00273 st_Breakpoint();
00274 eTransferInhibitor::no_transfer(user);
00275 }
00276 else if (!player)
00277 con << "Not transfering eNetGameObject " << ID()
00278 << " for user " << user << " because it has no player!\n";
00279 else if (!player->HasBeenTransmitted(user))
00280 {
00281 tString s;
00282 s << "No transfering eNetGameObject " << ID()
00283 << " for user " << user << " because ";
00284 player->PrintName(s);
00285 s << " has not been transmitted.\n";
00286 con << s;
00287 }
00288 }
00289 #endif
00290
00291
00292 return
00293 nNetObject::ClearToTransmit(user) &&
00294 !eTransferInhibitor::no_transfer(user) &&
00295 (!player ||
00296 player->HasBeenTransmitted(user));
00297 }
00298
00299 bool eNetGameObject::Timestep(REAL currentTime){
00300
00301 if (sn_GetNetState() == nSTANDALONE){
00302 laggometerSmooth=0;
00303 return false;
00304 }
00305
00306 REAL animts=(currentTime-lastTime);
00307 if (animts<0)
00308 animts=0;
00309
00310 if (sn_GetNetState() == nSERVER || Owner() == ::sn_myNetID ||
00311 ( player && laggometer <= 0 ) )
00312 {
00313
00314 laggometer = se_GetPing( player );
00315 }
00316
00317
00318
00319
00320
00321 laggometerSmooth=(laggometerSmooth+laggometer*animts)/(1 + animts);
00322 lastTime=currentTime;
00323
00324
00325 pingOverflow/=(1+animts*PING_OVERFLOW_TS);
00326
00327 return false;
00328 }
00329
00330 REAL eNetGameObject::Lag() const{
00331 return laggometerSmooth;
00332 }
00333
00334 REAL eNetGameObject::LagThreshold() const{
00335
00336 if ( sn_GetNetState() != nSERVER )
00337 return 0;
00338 if ( Owner() == 0 )
00339 return 0;
00340 return eLag::Threshold();
00341 }
00342
00343 static tCallbackOr* transfer_anchor;
00344
00345 eTransferInhibitor::eTransferInhibitor(BOOLRETFUNC *f)
00346 :tCallbackOr(transfer_anchor,f){}
00347
00348 bool eTransferInhibitor::no_transfer(int u){
00349 user = u;
00350 return Exec(transfer_anchor);
00351 }
00352
00353 int eTransferInhibitor::user;
00354
00355 nMessage & operator<< (nMessage &m, const eCoord &x){
00356 m << x.x;
00357 m << x.y;
00358
00359 return m;
00360 }
00361
00362 nMessage & operator>> (nMessage &m, eCoord &x){
00363 m >> x.x;
00364 m >> x.y;
00365
00366 return m;
00367 }
00368
00369
00370
00371
00372
00376
00377
00378 nMachine & eNetGameObject::DoGetMachine( void ) const
00379 {
00380 if ( Player() )
00381 return Player()->GetMachine();
00382 else
00383 return nNetObject::DoGetMachine();
00384 }
00385
00386