00001
00002
00003
00004
00005
00006
00007 #include <boost/thread.hpp>
00008 #include <boost/asio.hpp>
00009
00010 #include <netThread.h>
00011
00012 #include <engine.h>
00013 #include <listener.h>
00014 #include <sender.h>
00015 #include <enums.h>
00016 #include <messages.h>
00017 #include <utils.h>
00018 #include <GraphicsInteractionManager.h>
00019
00020 using boost::asio::ip::udp;
00021
00022
00023 void FastEcslent::NetThread::init() {
00024 std::cout << "Initializing Net before starting thread. Engine instance Id: " << engine->instanceId << std::endl;
00025 netCommon = new NetCommon();
00026 std::pair<udp::endpoint, std::string> ippair = netCommon->getMyIP();
00027 udp::endpoint myIP = ippair.first;
00028 myIPAddress = ippair.second;
00029
00030 listener = new Listener(myIP, engine->options.networkPort, engine->options.isServer);
00031 listener->init(myIPAddress);
00032 sender = new Sender(myIP, engine->options.networkPort, engine->options.isServer);
00033 sender->init();
00034 quit = false;
00035 startTime = getCurrentTime();
00036 TICK_SLEEP_TIME = 10;
00037 sleepTime = new boost::posix_time::milliseconds(20);
00038 insideLobby = false;
00039 }
00040
00041
00042 void FastEcslent::NetThread::run() {
00043 netThread = boost::thread(&FastEcslent::NetThread::runThread, this);
00044 std::cout << "Running thread: " << netThread.get_id() << " Engine instance Id: " << engine->instanceId << std::endl;
00045 }
00046
00047 void FastEcslent::NetThread::runThread(){
00048 listener->run();
00049 sender->run();
00050
00051 while (!quit){
00052 gameTick();
00053 }
00054 }
00055
00056 void FastEcslent::NetThread::gameTick(){
00057 if (engine->options.isServer) {
00058 serverTick();
00059 } else {
00060 clientTick();
00061 }
00062 }
00063
00064 namespace FastEcslent {
00065
00066 State* fillStateFromEnt(FastEcslent::Entity *ent){
00067 State *s = new State();
00068
00069 s->id = ent->entityId.id;
00070
00071 s->px = ent->pos.x;
00072 s->py = ent->pos.y;
00073 s->pz = ent->pos.z;
00074
00075 s->vx = ent->vel.x;
00076 s->vy = ent->vel.y;
00077 s->vz = ent->vel.z;
00078
00079 s->dh = ent->desiredHeading;
00080 s->ds = ent->desiredSpeed;
00081
00082 s->rSpeed = 0.0;
00083 s->yaw = ent->yaw;
00084
00085 s->flag = 0;
00086
00087 return s;
00088 }
00089
00090 Info *fillInfoFromEnt(FastEcslent::Entity *ent){
00091 Info *info = new Info();
00092 char tmp[256];
00093 sprintf(tmp, "%256i", ent->entityType);
00094 strcpy(info->type, tmp);
00095 sprintf(tmp, "%255s", ent->uiname.c_str());
00096 strcpy(info->label, tmp);
00097
00098
00099 info->beam = ent->width;
00100 info->draft = ent->depth;
00101 info->id = ent->entityId.id;
00102 info->length = ent->length;
00103 info->playerId = ent->entityId.player;
00104 info->side = ent->entityId.side;
00105 info->maxSpeed = ent->maxSpeed;
00106 info->maxSpeedReverse = 0.0f;
00107 return info;
00108 }
00109
00110 Message *makeMessageWithStateHeader(int nEnts, long dtime){
00111 Message *m = new Message();
00112 m->head.msgType = STATEMESSAGETYPE;
00113 m->head.millisecondsFromStart = dtime;
00114 m->head.numberOfStructs = nEnts;
00115 m->head.sizeOfStruct = StateSize;
00116 return m;
00117 }
00118
00119 Message *makeMessageWithInfoHeader(int nEnts, long dtime){
00120 Message *m = new Message();
00121 m->head.msgType = INFOMESSAGETYPE;
00122 m->head.millisecondsFromStart = dtime;
00123 m->head.numberOfStructs = nEnts;
00124 m->head.sizeOfStruct = InfoSize;
00125 return m;
00126 }
00127
00128 }
00129
00130 void FastEcslent::NetThread::sendCommands(){
00131 sendUnknownEntQueries();
00132 combineCommandsIntoNetMessage();
00133 combineSquelchesIntoNetMessage();
00134 }
00135
00136 void FastEcslent::NetThread::combineCommandsIntoNetMessage(){
00137 if (commandQueue.size() > 0){
00138 Message *m = new Message();
00139
00140 m->head.msgType = COMMANDENTITYMESSAGETYPE;
00141 m->head.millisecondsFromStart = netCommon->getCurrentTimeLong();
00142 m->head.numberOfStructs = commandQueue.size() ;
00143 m->head.sizeOfStruct = CommandEntitySize;
00144 unsigned int offset = 0;
00145 for(int i=0; i< m->head.numberOfStructs; i++){
00146 CommandEntity* cmd = commandQueue.front();
00147 commandQueue.pop_front();
00148 memcpy((void*)(m->data + offset), (void *)cmd, CommandEntitySize);
00149 offset += CommandEntitySize;
00150 delete cmd;
00151 }
00152
00153 sender->addMessage(m);
00154 }
00155 }
00156
00157 void FastEcslent::NetThread::combineSquelchesIntoNetMessage(){
00158 if (squelchQueue.size() > 0){
00159 Message *m = new Message();
00160
00161 m->head.msgType = SQUELCHMESSAGETYPE;
00162 m->head.millisecondsFromStart = netCommon->getCurrentTimeLong();
00163 m->head.numberOfStructs = squelchQueue.size() ;
00164 m->head.sizeOfStruct = SquelchEntitySize;
00165 unsigned int offset = 0;
00166 for(int i=0; i< m->head.numberOfStructs; i++){
00167 SquelchEntity* squelch = squelchQueue.front();
00168 squelchQueue.pop_front();
00169 memcpy((void*)(m->data + offset), (void *)squelch, SquelchEntitySize);
00170 offset += SquelchEntitySize;
00171 delete squelch;
00172 }
00173
00174 sender->addMessage(m);
00175 }
00176 }
00177
00178
00179 void FastEcslent::NetThread::addCommand(CommandEntity* m){
00180 commandQueue.push_back(m);
00181 }
00182
00183 void FastEcslent::NetThread::addSquelch(SquelchEntity* s){
00184 squelchQueue.push_back(s);
00185 }
00186
00187
00188 void FastEcslent::NetThread::sendUnknownEntQueries(){
00189 if(unknows.size()> 0) {
00190 std::cout<<"Unknowns entity count: "<< unknows.size() <<std::endl;
00191
00192 unsigned int offset = 0;
00193
00194 Message *m = new Message();
00195 m->head.msgType = REQUESTINFOMESSAGETYPE;
00196 m->head.millisecondsFromStart = netCommon->getCurrentTimeLong();
00197 m->head.numberOfStructs = unknows.size();
00198 m->head.sizeOfStruct = ReqInfoSize;
00199
00200 for (std::map<int, State*>::iterator i= unknows.begin(); i!=unknows.end();i++) {
00201 ReqInfo* reqInfo = new ReqInfo();
00202 reqInfo->id = i->first;
00203 memcpy((void*)(m->data + offset), (void *)reqInfo, ReqInfoSize);
00204 offset += ReqInfoSize;
00205 delete reqInfo;
00206 }
00207
00208 sender->addPriorityMessage(m);
00209 }
00210 }
00211
00212 void FastEcslent::NetThread::sendCommand(int id, float dh, float ds){
00213 Message *m = new Message();
00214 m->head.msgType = COMMANDENTITYMESSAGETYPE;
00215 m->head.millisecondsFromStart = (getCurrentTime() - startTime).total_milliseconds();
00216 m->head.numberOfStructs = 1;
00217 m->head.sizeOfStruct = CommandEntitySize;
00218
00219 CommandEntity* cmd = new CommandEntity();
00220 cmd->id = id;
00221 cmd->dh = dh;
00222 cmd->ds = ds;
00223 memcpy((void*)(m->data), (void *)cmd, CommandEntitySize);
00224 delete cmd;
00225
00226 sender->addMessage(m);
00227 }
00228
00229 void FastEcslent::NetThread::serverTick(){
00230 handleClientMessages();
00231 serve();
00232 boost::this_thread::sleep(*sleepTime);
00233 }
00234
00235 void FastEcslent::NetThread::clientTick(){
00236 this->handleServerMessages();
00237 sendCommands();
00238 boost::this_thread::sleep(*sleepTime);
00239 }
00240
00241 void FastEcslent::NetThread::serve(){
00242
00243 Message *message;
00244 State *state;
00245 unsigned int offset = 0;
00246
00247 int n = engine->entityMgr->nEnts;
00248
00249
00250 long dt = netCommon->getCurrentTimeLong();
00251 message = makeMessageWithStateHeader(n, netCommon->getCurrentTimeLong());
00252 offset = 0;
00253 for (int i = 0; i < n; i++) {
00254 state = fillStateFromEnt(engine->entityMgr->ents[i]);
00255
00256 memcpy((void*)(message->data + offset), (void *)state, StateSize);
00257 offset += StateSize;
00258 delete state;
00259 }
00260
00261 sender->addMessage(message);
00262 }
00263
00264 void FastEcslent::NetThread::handleClientMessages(){
00265 Message *m = listener->dequeMessage();
00266 while (m) {
00267 if((int) m->head.msgType != FastEcslent::STATEMESSAGETYPE) {
00268 handleMessage(m);
00269 }
00270 delete m;
00271 m = listener->dequeMessage();
00272 }
00273 }
00274
00275 void FastEcslent::NetThread::handleServerMessages(){
00276 Message *m = listener->dequeMessage();
00277 while (m) {
00278 if((int) m->head.msgType == FastEcslent::STATEMESSAGETYPE) {
00279 updateState(m);
00280 }else if((int) m->head.msgType == FastEcslent::INFOMESSAGETYPE) {
00281 createEnt(m);
00282 }else if ((int) m->head.msgType == FastEcslent::SQUELCHMESSAGETYPE){
00283 squelchEnts(m);
00284 }
00285 delete m;
00286 m = listener->dequeMessage();
00287 }
00288 }
00289
00290 void FastEcslent::NetThread::updateState(Message *m){
00291 unsigned int offset = 0;
00292 for(int i=0;i<m->head.numberOfStructs;i++){
00293 State *state = new State();
00294 memcpy((void *)state, (void*)(m->data + offset), StateSize);
00295 offset += StateSize;
00296 state->flag = m->head.millisecondsFromStart;
00297 updateState(state);
00298
00299 }
00300 }
00301
00302 void FastEcslent::NetThread::updateState(State *s){
00303 if(netIdToEntMap.find(s->id) != netIdToEntMap.end()){
00304 FastEcslent::Entity *ent= netIdToEntMap[s->id];
00305 NetAspect *na = dynamic_cast<NetAspect *> (ent->getAspect(NET));
00306 if(na){
00307 ent->netAspect->updateQueue.push_back(s);
00308 }else{
00309 delete s;
00310 }
00311 }
00312 else{
00313 State *tmp = unknows[s->id];
00314 unknows[s->id] = s;
00315 if (tmp != NULL)
00316 delete tmp;
00317 }
00318 }
00319
00320 void FastEcslent::NetThread::createEnt(Message *m){
00321 unsigned int offset = 0;
00322 for(int i=0;i<m->head.numberOfStructs;i++){
00323 Info *info = new Info();
00324 memcpy((void *)info, (void*)(m->data + offset), InfoSize);
00325 offset += InfoSize;
00326 createEnt(info);
00327 }
00328 }
00329
00330 void FastEcslent::NetThread::createEnt(Info *info){
00331 if(unknows.find(info->id) != unknows.end()){
00332 int type = atoi(info->type);
00333 EntityType et = (EntityType)type;
00334 Side side = (Side)(info->side);
00335 Player player = (Player)(info->playerId);
00336 State *s = unknows[info->id];
00337
00338 Ogre::Vector3 pos(s->px,s->py,s->pz);
00339
00340 Entity* ent = engine->entityMgr->createEntityForPlayerAndSide(et, pos, s->yaw, side, player );
00341 ent->width = info->beam;
00342 ent->depth = info->draft;
00343 ent->uiname = info->label;
00344 ent->length = info->length;
00345 ent->maxSpeed = info->maxSpeed;
00346
00347 netIdToEntMap[info->id] = ent;
00348 netEntToIdMap[ent] = info->id;
00349
00350 ent->vel.x = s->vx;
00351 ent->vel.y = s->vy;
00352 ent->vel.z = s->vz;
00353
00354 ent->desiredHeading = s->dh;
00355 ent->desiredSpeed = s->ds;
00356
00357 if(ent->entityType == SCV){
00358 ent->ai->state = NETSLAVE;
00359 }
00360
00361 delete s;
00362 unknows.erase(info->id);
00363 delete info;
00364
00365 std::cout<<"Create Entity from Network: "<< ent->idNumber << ", " << ent->entityType << std::endl;
00366 }
00367 }
00368
00369 void FastEcslent::NetThread::squelchEnts(Message *m){
00370 unsigned int offset = 0;
00371 for(int i=0;i<m->head.numberOfStructs;i++){
00372 SquelchEntity *squelch = new SquelchEntity();
00373 memcpy((void *)squelch, (void*)(m->data + offset), SquelchEntitySize);
00374 offset += SquelchEntitySize;
00375 netIdToEntMap[squelch->id]->netAspect->squalch();
00376 delete squelch;
00377 }
00378 }
00379
00380 void FastEcslent::NetThread::handleMessage(Message *m){
00381 switch((int) m->head.msgType) {
00382 case FastEcslent::REQUESTINFOMESSAGETYPE:
00383 sendInfo(m);
00384 break;
00385 case FastEcslent::COMMANDENTITYMESSAGETYPE:
00386 propagateCommand(m);
00387 break;
00388 case FastEcslent::SQUELCHMESSAGETYPE:
00389
00390 break;
00391 default:
00392 break;
00393
00394 }
00395 }
00396
00397 void FastEcslent::NetThread::sendInfo(Message *m){
00398 Entity *ent;
00399 Info *info;
00400 ptime currentTime = getCurrentTime();
00401 time_duration diff = currentTime - startTime;
00402 Message *sendInfoMessage = makeMessageWithInfoHeader(m->head.numberOfStructs, diff.total_milliseconds());
00403
00404 int offset = HeaderSize;
00405
00406 FastEcslent::printMessageHeader(m->head);
00407 FastEcslent::printMessageData(m);
00408 for(int i = 0; i < m->head.numberOfStructs; i++){
00409 ent = engine->entityMgr->ents[*((int *)m->data + i)];
00410 info = fillInfoFromEnt(ent);
00411 std::cout << "Sending info message about ent with id: " << ent->entityId.id << std::endl;
00412 memcpy((void* ) ((char*)sendInfoMessage + offset), info, InfoSize);
00413 offset += InfoSize;
00414
00415 delete info;
00416 }
00417
00418 sender->addMessage(sendInfoMessage);
00419 }
00420
00421 void FastEcslent::NetThread::propagateCommand(Message *m){
00422 unsigned int offset = 0;
00423 for(int i=0;i<m->head.numberOfStructs;i++){
00424 CommandEntity *cmd = new CommandEntity();
00425 memcpy((void *)cmd, (void*)(m->data + offset), CommandEntitySize);
00426 offset += CommandEntitySize;
00427 Entity* ent = engine->entityMgr->getEntityById(cmd->id);
00428 ent->desiredHeading = cmd->dh;
00429 ent->desiredSpeed = cmd->ds;
00430 ent->ai->state = NETSLAVE;
00431 delete cmd;
00432 }
00433 }
00434
00435 void FastEcslent::NetThread::stop(){
00436 quit = true;
00437 }
00438
00439
00440 void FastEcslent::NetThread::stopAndJoin(){
00441 stop();
00442 std::cout << "NetThread Stopping...Quit = " << std::endl;
00443 boost::this_thread::sleep(boost::posix_time::seconds(2));
00444 sender->stop();
00445 boost::this_thread::sleep(boost::posix_time::seconds(2));
00446 listener->stop();
00447 boost::this_thread::sleep(boost::posix_time::seconds(2));
00448
00449 std::cout << "NetThread Joining..." << std::endl;
00450
00451
00452 sender->join();
00453 boost::this_thread::sleep(boost::posix_time::seconds(2));
00454
00455
00456 listener->kill();
00457 sender->kill();
00458
00459 boost::this_thread::sleep(boost::posix_time::seconds(2));
00460
00461 netThread.join();
00462 }
00463
00464 int FastEcslent::NetThread::getNetId(Entity* ent){
00465 for(std::map<int, Entity*>::iterator i = netIdToEntMap.begin(); i!= netIdToEntMap.end(); i++){
00466 if(i->second == ent)
00467 return i->first;
00468 }
00469 return -1;
00470 }
00471