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 ent->init();
00358
00359 if(ent->entityType == SCV){
00360 ent->ai->state = NETSLAVE;
00361 }
00362
00363 delete s;
00364 unknows.erase(info->id);
00365 delete info;
00366
00367 std::cout<<"Create Entity from Network: "<< ent->idNumber << ", " << ent->entityType << std::endl;
00368 }
00369 }
00370
00371 void FastEcslent::NetThread::squelchEnts(Message *m){
00372 unsigned int offset = 0;
00373 for(int i=0;i<m->head.numberOfStructs;i++){
00374 SquelchEntity *squelch = new SquelchEntity();
00375 memcpy((void *)squelch, (void*)(m->data + offset), SquelchEntitySize);
00376 offset += SquelchEntitySize;
00377 netIdToEntMap[squelch->id]->netAspect->squalch();
00378 delete squelch;
00379 }
00380 }
00381
00382 void FastEcslent::NetThread::handleMessage(Message *m){
00383 switch((int) m->head.msgType) {
00384 case FastEcslent::REQUESTINFOMESSAGETYPE:
00385 sendInfo(m);
00386 break;
00387 case FastEcslent::COMMANDENTITYMESSAGETYPE:
00388 propagateCommand(m);
00389 break;
00390 case FastEcslent::SQUELCHMESSAGETYPE:
00391
00392 break;
00393 default:
00394 break;
00395
00396 }
00397 }
00398
00399 void FastEcslent::NetThread::sendInfo(Message *m){
00400 Entity *ent;
00401 Info *info;
00402 ptime currentTime = getCurrentTime();
00403 time_duration diff = currentTime - startTime;
00404 Message *sendInfoMessage = makeMessageWithInfoHeader(m->head.numberOfStructs, diff.total_milliseconds());
00405
00406 int offset = HeaderSize;
00407
00408 FastEcslent::printMessageHeader(m->head);
00409 FastEcslent::printMessageData(m);
00410 for(int i = 0; i < m->head.numberOfStructs; i++){
00411 ent = engine->entityMgr->ents[*((int *)m->data + i)];
00412 info = fillInfoFromEnt(ent);
00413 std::cout << "Sending info message about ent with id: " << ent->entityId.id << std::endl;
00414 memcpy((void* ) ((char*)sendInfoMessage + offset), info, InfoSize);
00415 offset += InfoSize;
00416
00417 delete info;
00418 }
00419
00420 sender->addMessage(sendInfoMessage);
00421 }
00422
00423 void FastEcslent::NetThread::propagateCommand(Message *m){
00424 unsigned int offset = 0;
00425 for(int i=0;i<m->head.numberOfStructs;i++){
00426 CommandEntity *cmd = new CommandEntity();
00427 memcpy((void *)cmd, (void*)(m->data + offset), CommandEntitySize);
00428 offset += CommandEntitySize;
00429 Entity* ent = engine->entityMgr->getEntityById(cmd->id);
00430 ent->desiredHeading = cmd->dh;
00431 ent->desiredSpeed = cmd->ds;
00432 ent->ai->state = NETSLAVE;
00433 delete cmd;
00434 }
00435 }
00436
00437 void FastEcslent::NetThread::stop(){
00438 quit = true;
00439 }
00440
00441
00442 void FastEcslent::NetThread::stopAndJoin(){
00443 stop();
00444 std::cout << "NetThread Stopping...Quit = " << std::endl;
00445 boost::this_thread::sleep(boost::posix_time::seconds(2));
00446 sender->stop();
00447 boost::this_thread::sleep(boost::posix_time::seconds(2));
00448 listener->stop();
00449 boost::this_thread::sleep(boost::posix_time::seconds(2));
00450
00451 std::cout << "NetThread Joining..." << std::endl;
00452
00453
00454 sender->join();
00455 boost::this_thread::sleep(boost::posix_time::seconds(2));
00456
00457
00458 listener->kill();
00459 sender->kill();
00460
00461 boost::this_thread::sleep(boost::posix_time::seconds(2));
00462
00463 netThread.join();
00464 }
00465
00466 int FastEcslent::NetThread::getNetId(Entity* ent){
00467 for(std::map<int, Entity*>::iterator i = netIdToEntMap.begin(); i!= netIdToEntMap.end(); i++){
00468 if(i->second == ent)
00469 return i->first;
00470 }
00471 return -1;
00472 }
00473