SimpleGameClient.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00025 #include "SimpleGameClient.h"
00026 
00027 Define_Module(SimpleGameClient);
00028 
00029 void SimpleGameClient::initializeApp(int stage)
00030 {
00031     // all initialization is done in the first stage
00032     if (stage != MIN_STAGE_APP) {
00033         return;
00034     }
00035 
00036     // fetch parameters
00037     areaDimension = par("areaDimension");
00038     useScenery = par("useScenery");
00039     movementRate = par("movementRate");
00040     movementSpeed = par("movementSpeed");
00041     movementDelay= 1.0 / movementRate;
00042     AOIWidth = 0.0;
00043     logAOI = false;
00044     int groupSize = (int)par("groupSize");
00045     if(groupSize < 1) {
00046         groupSize = 1;
00047     }
00048     GeneratorType = par("movementGenerator").stdstringValue();
00049 
00050     WATCH_MAP(Neighbors);
00051     WATCH_LIST(CollisionRect);
00052     WATCH(position);
00053     WATCH(GeneratorType);
00054     WATCH(overlayReady);
00055 
00056     doRealworld = false;
00057     coordinator = check_and_cast<GlobalCoordinator*>(simulation.getModuleByPath("globalObserver.globalFunctions[0].function.coordinator"));
00058     scheduler = NULL;
00059     packetNotification = NULL;
00060 
00061     frozen = false;
00062 
00063     CollisionList* listPtr = NULL;
00064     if(useScenery == true) {
00065         listPtr = &CollisionRect;
00066     }
00067 
00068     double speed = SIMTIME_DBL(movementDelay) * movementSpeed;
00069     if(strcmp(GeneratorType.c_str(), "greatGathering") == 0) {
00070         if(debugOutput) {
00071             EV << "[SimpleGameClient::initializeApp() @ " << overlay->getThisNode().getAddress()
00072                << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00073                << "    SIMPLECLIENT: Movement generator: greatGathering"
00074                << endl;
00075         }
00076         Generator = new greatGathering(areaDimension, speed, &Neighbors, coordinator, listPtr);
00077     }
00078     else if(strcmp(GeneratorType.c_str(), "groupRoaming") == 0) {
00079         if(debugOutput) {
00080             EV << "[SimpleGameClient::initializeApp() @ " << overlay->getThisNode().getAddress()
00081                << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00082                << "    SIMPLECLIENT: Movement generator: groupRoaming"
00083                << endl;
00084         }
00085         Generator = new groupRoaming(areaDimension, speed, &Neighbors, coordinator, listPtr, groupSize);
00086     }
00087     else if(strcmp(GeneratorType.c_str(), "hotspotRoaming") == 0) {
00088         if(debugOutput) {
00089             EV << "[SimpleGameClient::initializeApp() @ " << overlay->getThisNode().getAddress()
00090                << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00091                << "    SIMPLECLIENT: Movement generator: hotspotRoaming"
00092                << endl;
00093         }
00094         Generator = new hotspotRoaming(areaDimension, speed, &Neighbors, coordinator, listPtr);
00095     }
00096     else if(strcmp(GeneratorType.c_str(), "traverseRoaming") == 0) {
00097         if(debugOutput) {
00098             EV << "[SimpleGameClient::initializeApp() @ " << overlay->getThisNode().getAddress()
00099                << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00100                << "    SIMPLECLIENT: Movement generator: traverseRoaming"
00101                << endl;
00102         }
00103         logAOI = true;
00104         Generator = new traverseRoaming(areaDimension, speed, &Neighbors, coordinator, listPtr);
00105     }
00106     else if(strcmp(GeneratorType.c_str(), "realWorldRoaming") == 0) {
00107         if(debugOutput) {
00108             EV << "[SimpleGameClient::initializeApp() @ " << overlay->getThisNode().getAddress()
00109                << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00110                << "    SIMPLECLIENT: Movement generator: realWorldRoaming"
00111                << endl;
00112         }
00113         Generator = new realWorldRoaming(areaDimension, movementSpeed, &Neighbors, coordinator, listPtr);
00114         mtu = par("mtu");
00115         packetNotification = new cMessage("packetNotification");
00116         scheduler = check_and_cast<RealtimeScheduler*>(simulation.getScheduler());
00117         scheduler->setInterfaceModule(this, packetNotification, &packetBuffer, mtu, true);
00118         appFd = INVALID_SOCKET;
00119     }
00120     else {
00121         // debug output
00122         if(debugOutput) {
00123             if(strcmp(GeneratorType.c_str(), "randomRoaming") == 0) {
00124                 EV << "[SimpleGameClient::initializeApp() @ " << overlay->getThisNode().getAddress()
00125                    << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00126                    << "    SIMPLECLIENT: Movement generator: randomRoaming"
00127                    << endl;
00128             }
00129             else {
00130                 EV << "[SimpleGameClient::initializeApp() @ " << overlay->getThisNode().getAddress()
00131                    << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00132                    << "    SIMPLECLIENT: Movement generator: <unknown>. Defaulting to: randomRoaming"
00133                    << endl;
00134             }
00135         }
00136         Generator = new randomRoaming(areaDimension, speed, &Neighbors, coordinator, listPtr);
00137     }
00138 
00139     // self-messages
00140     move_timer = new cMessage("move_timer");
00141     overlayReady = false;
00142 }
00143 
00144 void SimpleGameClient::handleTimerEvent(cMessage* msg)
00145 {
00146     if(msg->isName("move_timer")) {
00147         //reset timer
00148         cancelEvent(move_timer);
00149         if(overlayReady) {
00150             scheduleAt(simTime() + movementDelay, msg);
00151         }
00152         // handle event
00153         updatePosition();
00154     }
00155     else if(msg->isName("packetNotification")) {
00156         while(packetBuffer.size() > 0) {
00157             // get packet from buffer and parse it
00158             RealtimeScheduler::PacketBufferEntry packet = *(packetBuffer.begin());
00159             packetBuffer.pop_front();
00160             switch (packet.func) {
00161                 case RealtimeScheduler::PacketBufferEntry::PACKET_DATA: {
00162                     if(packet.fd != appFd) {
00163                         error("SimpleClient::handleMessage(): Received packet from unknown socket!");
00164                     }
00165                     handleRealworldPacket(packet.data, packet.length);
00166                 } break;
00167                 case RealtimeScheduler::PacketBufferEntry::PACKET_FD_NEW: {
00168                     if(appFd != INVALID_SOCKET) {
00169                         error("SimpleClient::handleMessage(): Multiple connections not supported yet!");
00170                     }
00171                     if (packet.addr != NULL) {
00172                         delete packet.addr;
00173                         packet.addr = NULL;
00174                     }
00175                     appFd = packet.fd;
00176                 } break;
00177                 case RealtimeScheduler::PacketBufferEntry::PACKET_FD_CLOSE: {
00178                     if(packet.fd != appFd) {
00179                         error("SimpleClient::handleMessage(): Trying to close unknown connection!");
00180                     }
00181                     appFd = INVALID_SOCKET;
00182                 } break;
00183                 default:
00184                     // Unknown socket function, ignore
00185                     break;
00186             }
00187             delete packet.data;
00188         }
00189     }
00190     else if(msg->isName("Snowball landing")) {
00191         SCSnowTimer* snowTimer = check_and_cast<SCSnowTimer*>(msg);
00192         if(!frozen && position.distanceSqr(snowTimer->getPosition() / 32 ) < 2) {
00193             // freeze me!
00194             frozen = true;
00195             cMessage* unfreeze = new cMessage("unfreeze me");
00196             scheduleAt(simTime() + 5, unfreeze);
00197 
00198             GameAPIFrozenMessage* freeze = new GameAPIFrozenMessage("I'm frozen");
00199             freeze->setCommand(GAMEEVENT_FROZEN);
00200             freeze->setSrc(overlay->getThisNode());
00201             freeze->setThrower(snowTimer->getIp());
00202             freeze->setTimeSec(5);
00203             freeze->setTimeUsec(0);
00204             sendMessageToLowerTier(freeze);
00205 
00206             if(doRealworld) {
00207                 SCFrozenPacket scfreeze;
00208                 scfreeze.packetType = SC_EV_FROZEN;
00209                 scfreeze.ip = overlay->getThisNode().getAddress().get4().getInt();
00210                 scfreeze.source = snowTimer->getIp();
00211                 scfreeze.time_sec = 5;
00212                 scfreeze.time_usec = 0;
00213                 int packetlen = sizeof(scfreeze);
00214                 scheduler->sendBytes((const char*)&packetlen, sizeof(int), 0, 0, true, appFd);
00215                 scheduler->sendBytes((const char*)&scfreeze, packetlen, 0, 0, true, appFd);
00216             }
00217         }
00218         delete msg;
00219     }
00220     else if(msg->isName("unfreeze me")) {
00221         frozen = false;
00222         delete msg;
00223     }
00224 }
00225 
00226 void SimpleGameClient::handleLowerMessage(cMessage* msg)
00227 {
00228     if(dynamic_cast<GameAPIMessage*>(msg)) {
00229         GameAPIMessage* gameAPIMsg = check_and_cast<GameAPIMessage*>(msg);
00230         if(gameAPIMsg->getCommand() == MOVEMENT_REQUEST) {
00231             updatePosition();
00232         }
00233         else if(gameAPIMsg->getCommand() == NEIGHBOR_UPDATE) {
00234             GameAPIListMessage* gameAPIListMsg = check_and_cast<GameAPIListMessage*>(msg);
00235             updateNeighbors(gameAPIListMsg);
00236         }
00237         else if(gameAPIMsg->getCommand() == RESIZE_AOI) {
00238             GameAPIResizeAOIMessage* gameAPIResizeMsg = check_and_cast<GameAPIResizeAOIMessage*>(msg);
00239             AOIWidth = gameAPIResizeMsg->getAOIsize();
00240             if( logAOI ){
00241                 GlobalStatisticsAccess().get()->recordOutVector( "SimpleGameClient: AOI width", AOIWidth );
00242             }
00243             if(doRealworld) {
00244                 SCAOIPacket packet;
00245                 packet.packetType = SC_RESIZE_AOI;
00246                 packet.AOI = AOIWidth;
00247                 int packetlen = sizeof(SCAOIPacket);
00248                 scheduler->sendBytes((const char*)&packetlen, sizeof(int), 0, 0, true, appFd);
00249                 scheduler->sendBytes((const char*)&packet, packetlen, 0, 0, true, appFd);
00250             }
00251         }
00252         else if(gameAPIMsg->getCommand() == GAMEEVENT_CHAT) {
00253             if(doRealworld) {
00254                 GameAPIChatMessage* chatMsg = check_and_cast<GameAPIChatMessage*>(msg);
00255                 const char* msg = chatMsg->getMsg();
00256                 int packetlen = sizeof(SCChatPacket) + strlen(msg) + 1;
00257                 SCChatPacket* pack = (SCChatPacket*)malloc(packetlen);
00258                 pack->packetType = SC_EV_CHAT;
00259                 pack->ip = chatMsg->getSrc().getAddress().get4().getInt();
00260                 strcpy(pack->msg, msg);
00261                 scheduler->sendBytes((const char*)&packetlen, sizeof(int), 0, 0, true, appFd);
00262                 scheduler->sendBytes((const char*)pack, packetlen, 0, 0, true, appFd);
00263                 free(pack);
00264             }
00265         }
00266         else if(gameAPIMsg->getCommand() == GAMEEVENT_SNOW) {
00267             GameAPISnowMessage* snowMsg = check_and_cast<GameAPISnowMessage*>(gameAPIMsg);
00268             if(doRealworld) {
00269                 SCSnowPacket packet;
00270                 packet.packetType = SC_EV_SNOWBALL;
00271                 packet.ip = snowMsg->getSrc().getAddress().get4().getInt();
00272                 packet.startX = snowMsg->getStart().x;
00273                 packet.startY = snowMsg->getStart().y;
00274                 packet.endX = snowMsg->getEnd().x;
00275                 packet.endY = snowMsg->getEnd().y;
00276                 packet.time_sec = snowMsg->getTimeSec();
00277                 packet.time_usec = snowMsg->getTimeUsec();
00278                 int packetlen = sizeof(SCSnowPacket);
00279                 scheduler->sendBytes((const char*)&packetlen, sizeof(int), 0, 0, true, appFd);
00280                 scheduler->sendBytes((const char*)&packet, packetlen, 0, 0, true, appFd);
00281             }
00282             SCSnowTimer* snowTimer = new SCSnowTimer("Snowball landing");
00283             snowTimer->setPosition(snowMsg->getEnd());
00284             snowTimer->setIp(snowMsg->getSrc().getAddress().get4().getInt());
00285             timeval snowTime;
00286             snowTime.tv_sec = snowMsg->getTimeSec();
00287             snowTime.tv_usec = snowMsg->getTimeUsec();
00288             simtime_t snow_t = snowTime.tv_sec + snowTime.tv_usec / 1000000.0;
00289             scheduleAt(simTime() + snow_t, snowTimer);
00290         }
00291         else if(gameAPIMsg->getCommand() == GAMEEVENT_FROZEN) {
00292             if(doRealworld) {
00293                 GameAPIFrozenMessage* frozenMsg = check_and_cast<GameAPIFrozenMessage*>(gameAPIMsg);
00294                 SCFrozenPacket scfreeze;
00295                 scfreeze.packetType = SC_EV_FROZEN;
00296                 scfreeze.ip = frozenMsg->getSrc().getAddress().get4().getInt();
00297                 scfreeze.source = frozenMsg->getThrower();
00298                 scfreeze.time_sec = frozenMsg->getTimeSec();
00299                 scfreeze.time_usec = frozenMsg->getTimeUsec();
00300                 int packetlen = sizeof(scfreeze);
00301                 scheduler->sendBytes((const char*)&packetlen, sizeof(int), 0, 0, true, appFd);
00302                 scheduler->sendBytes((const char*)&scfreeze, packetlen, 0, 0, true, appFd);
00303             }
00304         }
00305     }
00306     delete msg;
00307 }
00308 
00309 void SimpleGameClient::handleReadyMessage(CompReadyMessage* msg)
00310 {
00311     // process only ready messages from the tier below
00312     if( getThisCompType() - msg->getComp() == 1 ){
00313         if(msg->getReady()) {
00314             overlayReady = true;
00315             if(!move_timer->isScheduled()) {
00316                 scheduleAt(simTime() + movementDelay, move_timer);
00317             }
00318         }
00319         else {
00320             overlayReady = false;
00321         }
00322     }
00323     delete msg;
00324 }
00325 
00326 void SimpleGameClient::handleRealworldPacket(char *buf, uint32_t len)
00327 {
00328     SCBasePacket *type = (SCBasePacket*)buf;
00329     if(type->packetType == SC_PARAM_REQUEST) {
00330         SCParamPacket packet;
00331         packet.packetType = SC_PARAM_RESPONSE;
00332         packet.speed = movementSpeed;
00333         packet.dimension = areaDimension;
00334         packet.AOI = AOIWidth;
00335         packet.delay = SIMTIME_DBL(movementDelay);
00336         packet.startX = position.x;
00337         packet.startY = position.y;
00338         packet.ip = thisNode.getAddress().get4().getInt();
00339         packet.seed = coordinator->getSeed();
00340         int packetSize = sizeof(packet);
00341         scheduler->sendBytes((const char*)&packetSize, sizeof(int), 0, 0, true, appFd);
00342         scheduler->sendBytes((const char*)&packet, packetSize, 0, 0, true, appFd);
00343         doRealworld = true;
00344     }
00345     else if(type->packetType == SC_MOVE_INDICATION) {
00346         SCMovePacket *packet = (SCMovePacket*)type;
00347         Vector2D temp;
00348         temp.x = packet->posX;
00349         temp.y = packet->posY;
00350         dynamic_cast<realWorldRoaming*>(Generator)->setPosition(temp);
00351     }
00352     else if(type->packetType == SC_EV_CHAT) {
00353         SCChatPacket* packet = (SCChatPacket*)type;
00354         GameAPIChatMessage* chatMsg = new GameAPIChatMessage("ChatMsg");
00355         chatMsg->setCommand(GAMEEVENT_CHAT);
00356         chatMsg->setSrc(thisNode);
00357         chatMsg->setMsg(packet->msg);
00358         sendMessageToLowerTier(chatMsg);
00359     }
00360     else if(type->packetType == SC_EV_SNOWBALL) {
00361         SCSnowPacket* packet = (SCSnowPacket*)type;
00362         GameAPISnowMessage* snowMsg = new GameAPISnowMessage("Throw Snowball");
00363         snowMsg->setCommand(GAMEEVENT_SNOW);
00364         snowMsg->setSrc(thisNode);
00365         snowMsg->setStart(Vector2D(packet->startX, packet->startY));
00366         snowMsg->setEnd(Vector2D(packet->endX, packet->endY));
00367         snowMsg->setTimeSec(packet->time_sec);
00368         snowMsg->setTimeUsec(packet->time_usec);
00369         sendMessageToLowerTier(snowMsg);
00370     }
00371 }
00372 
00373 void SimpleGameClient::updateNeighbors(GameAPIListMessage* sgcMsg)
00374 {
00375     unsigned int i;
00376 
00377     if(doRealworld) {
00378         int packetSize;
00379 
00380         SCRemovePacket removePacket;
00381         removePacket.packetType = SC_REMOVE_NEIGHBOR;
00382         packetSize = sizeof(removePacket);
00383 
00384         for(i=0; i<sgcMsg->getRemoveNeighborArraySize(); ++i) {
00385             removePacket.ip = sgcMsg->getRemoveNeighbor(i).getAddress().get4().getInt();
00386             scheduler->sendBytes((const char*)&packetSize, sizeof(int), 0, 0, true, appFd);
00387             scheduler->sendBytes((const char*)&removePacket, packetSize, 0, 0, true, appFd);
00388         }
00389 
00390         SCAddPacket addPacket;
00391         addPacket.packetType = SC_ADD_NEIGHBOR;
00392         packetSize = sizeof(addPacket);
00393 
00394         for(i=0; i<sgcMsg->getAddNeighborArraySize(); ++i) {
00395             addPacket.ip = sgcMsg->getAddNeighbor(i).getAddress().get4().getInt();
00396             if( addPacket.ip == thisNode.getAddress().get4().getInt() ) continue;
00397             addPacket.posX = sgcMsg->getNeighborPosition(i).x;
00398             addPacket.posY = sgcMsg->getNeighborPosition(i).y;
00399             scheduler->sendBytes((const char*)&packetSize, sizeof(int), 0, 0, true, appFd);
00400             scheduler->sendBytes((const char*)&addPacket, packetSize, 0, 0, true, appFd);
00401         }
00402     }
00403     for(i=0; i<sgcMsg->getRemoveNeighborArraySize(); ++i)
00404         Neighbors.erase(sgcMsg->getRemoveNeighbor(i));
00405 
00406     for(i=0; i<sgcMsg->getAddNeighborArraySize(); ++i) {
00407         Vector2D newPos;
00408         newPos = sgcMsg->getNeighborPosition(i);
00409         itNeighbors = Neighbors.find(sgcMsg->getAddNeighbor(i));
00410         if(itNeighbors != Neighbors.end()) {
00411             Vector2D temp = newPos - itNeighbors->second.position;
00412             temp.normalize();
00413             itNeighbors->second.direction = temp;
00414             itNeighbors->second.position = newPos;
00415         }
00416         else {
00417             NeighborMapEntry entry;
00418             entry.position = newPos;
00419             Neighbors.insert(std::make_pair(sgcMsg->getAddNeighbor(i), entry));
00420         }
00421     }
00422 }
00423 
00424 void SimpleGameClient::updatePosition()
00425 {
00426     if(!frozen) {
00427         Generator->move();
00428     }
00429     position = Generator->getPosition();
00430     GameAPIPositionMessage *posMsg = new GameAPIPositionMessage("MOVEMENT_INDICATION");
00431     posMsg->setCommand(MOVEMENT_INDICATION);
00432     posMsg->setPosition(position);
00433     sendMessageToLowerTier(posMsg);
00434 }
00435 
00436 SimpleGameClient::~SimpleGameClient()
00437 {
00438     // destroy self timer messages
00439     cancelAndDelete(move_timer);
00440     cancelAndDelete(packetNotification);
00441     delete Generator;
00442 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3