00001 #include "MercuryNetClient.h"
00002 #include "MercuryLog.h"
00003 #include "MercuryObject.h"
00004 #include "MercuryODE.h"
00005
00006 #define MSG_SYNCNETTIME 1
00007
00008 MercuryNetClient::MercuryNetClient()
00009 {
00010 m_pSocket = new ezSockets;
00011 m_pNetClass = NULL;
00012 }
00013
00014 MercuryNetClient::~MercuryNetClient()
00015 {
00016 m_thdMain.Halt();
00017 m_thdMain.Close();
00018 delete m_pSocket;
00019 }
00020
00021 bool MercuryNetClient::Connect( const MString & sHost, int iPort )
00022 {
00023 bool bSucess;
00024 m_pSocket->Create();
00025 bSucess = m_pSocket->Connect( sHost, iPort );
00026
00027 if( bSucess )
00028 {
00029 m_thdMain.Create( CoreThreadCaller, this );
00030 RegisterMessage( MSG_SYNCNETTIME, "syncnettime" );
00031 m_delTimeID = 0;
00032 PStack s;
00033 MESSAGEMAN->BroadcastMessage( "syncnettime", s );
00034 return true;
00035 }
00036 else
00037 return false;
00038 }
00039
00040 void MercuryNetClient::Update( const float fDTime )
00041 {
00042 }
00043
00044 void MercuryNetClient::SendCommand( const MString & sCommandName, const PStack & kParameters )
00045 {
00046 ezSocketsPacket p;
00047 p.ClearPacket();
00048 p.Write4( 3 );
00049 p.WriteNT( sCommandName );
00050 NetEncodePStack( p, kParameters );
00051 m_pSocket->SendPack( p );
00052 }
00053
00054 void * MercuryNetClient::CoreThreadCaller( void * NetClient)
00055 {
00056 ((MercuryNetClient*)(NetClient))->CoreThread();
00057 return NULL;
00058 }
00059
00060 void MercuryNetClient::CoreThread( )
00061 {
00062 ezSocketsPacket pack;
00063
00064 m_pSocket->mode = ezSockets::skPackets;
00065 m_pSocket->bBlocking = true;
00066 m_tmrSync.Touch();
00067
00068 while( !m_pSocket->IsError() )
00069 {
00070 if( !m_pSocket->ReadPack( pack ) )
00071 break;
00072
00073 unsigned char cCode = pack.Read4();
00074 switch( cCode )
00075 {
00076 case 0:
00077 break;
00078 case 1:
00079 break;
00080 case 2:
00081 case 3:
00082 {
00083 MString sName = pack.ReadNT();
00084 unsigned long iParameters = pack.Read1();
00085 PStack t;
00086 NetDecodePStack( pack, t );
00087 if( cCode == 2 )
00088 MESSAGEMAN->PostSystemMessage( sName, t );
00089 else if( cCode == 3 )
00090 if( m_pNetClass )
00091 {
00092 PStack ret;
00093 m_pNetClass->Command( ret, sName.c_str(), t );
00094 }
00095 }
00096 break;
00097 case 4:
00098 {
00099 double dCurTime = m_tmrSync.Age();
00100 double dOrigTime;
00101 double dSrvTime;
00102 long delTimeID = pack.Read4();
00103
00104 pack.ReadData( 8, (char*)&dOrigTime );
00105 pack.ReadData( 8, (char*)&dSrvTime );
00106
00107
00108 double dPingTime = ( dCurTime - dOrigTime );
00109
00110
00111
00112
00113
00114
00115
00116 double thisDelTime = ( ( dSrvTime + (dPingTime/2) ) - dCurTime);
00117
00118
00119
00120 if( delTimeID < 2 )
00121 m_delTime = thisDelTime;
00122 else
00123 m_delTime = m_delTime * .9f + thisDelTime * .1f;
00124
00125 LOG.Info( ssprintf( "Time Synchronization: %f %f", dPingTime, m_delTime ) );
00126 }
00127 break;
00128 case 5:
00129 {
00130 if( !m_pWorld )
00131 break;
00132 ODEUnitInfo t;
00133 double dServerTime;
00134 unsigned iNumToReceive;
00135
00136 pack.ReadData( 8, (char*)&dServerTime );
00137 iNumToReceive = pack.Read4();
00138
00139 double dDeltaTime = m_tmrSync.Age() - dServerTime + m_delTime;
00140
00141 MHash<MercuryODEObject *> & AllObjects = m_pWorld->GetAllObjectMap();
00142
00143 for( unsigned i = 0; i < iNumToReceive; i++ )
00144 {
00145 MString sPackName = pack.ReadNT();
00146 pack.ReadData( sizeof(ODEUnitInfo), (char*)&t );
00147 if( !AllObjects.get( sPackName ) )
00148 continue;
00149 dBodyID b = (*AllObjects.get( sPackName ))->m_oBody;
00150 if( !b )
00151 continue;
00152
00153 t.pos = t.pos + t.linvel * dDeltaTime;
00154
00155 dBodySetPosition( b, t.pos.x, t.pos.y, t.pos.z );
00156
00157 dBodyEnable( b );
00158 dQuaternion q;
00159 q[0] = t.rot.w; q[1] = t.rot.x; q[2] = t.rot.y; q[3] = t.rot.z;
00160 dBodySetQuaternion( b, q );
00161 dBodySetLinearVel( b, t.linvel.x, t.linvel.y, t.linvel.z );
00162 dBodySetAngularVel( b, t.angvel.x, t.angvel.y, t.angvel.z );
00163 }
00164 }
00165 break;
00166 }
00167 }
00168 m_pSocket->Close();
00169
00170 }
00171
00172 void MercuryNetClient::Message( int Message, PStack & data, const MString & name )
00173 {
00174 switch( Message )
00175 {
00176 case MSG_SYNCNETTIME:
00177 double dCurrentTime = m_tmrSync.Age();
00178 ezSocketsPacket p;
00179 p.ClearPacket();
00180 p.Write4( 4 );
00181 p.Write4( m_delTimeID++ );
00182
00183 p.WriteData( (char*)&dCurrentTime, 8 );
00184 m_pSocket->SendPack( p );
00185
00186 PStack s;
00187 MESSAGEMAN->PostSystemMessage( "syncnettime", s, 1 );
00188 break;
00189 }
00190 }