00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00025 #include "SimpleGameClient.h"
00026
00027 Define_Module(SimpleGameClient);
00028
00029 void SimpleGameClient::initializeApp(int stage)
00030 {
00031
00032 if (stage != MIN_STAGE_APP) {
00033 return;
00034 }
00035
00036
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
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
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
00148 cancelEvent(move_timer);
00149 if(overlayReady) {
00150 scheduleAt(simTime() + movementDelay, msg);
00151 }
00152
00153 updatePosition();
00154 }
00155 else if(msg->isName("packetNotification")) {
00156 while(packetBuffer.size() > 0) {
00157
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
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
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
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
00439 cancelAndDelete(move_timer);
00440 cancelAndDelete(packetNotification);
00441 delete Generator;
00442 }