#include <SimMud.h>
Public Member Functions | |
SimMud () | |
~SimMud () | |
virtual void | initializeApp (int stage) |
Initialize class attributes. | |
virtual void | handleTimerEvent (cMessage *msg) |
processes self-messages | |
virtual void | handleUpperMessage (cMessage *msg) |
handleUpperMessage gets called of handleMessage(cMessage* msg) if msg arrivedOn from_upperTier (currently msg gets deleted in this function) | |
virtual void | handleLowerMessage (cMessage *msg) |
method to handle non-commonAPI messages from the overlay | |
virtual void | handleReadyMessage (CompReadyMessage *msg) |
method to handle ready messages from the overlay | |
virtual bool | handleRpc (BaseCallMessage *msg) |
Processes Remote-Procedure-Call invokation messages. | |
virtual void | handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt) |
This method is called if an RPC response has been received. | |
virtual void | finishApp () |
collect statistical data | |
Protected Member Functions | |
void | handleMove (GameAPIPositionMessage *msg) |
void | handleOtherPlayerMove (SimMudMoveMessage *msg) |
Private Attributes | |
int | currentRegionX |
int | currentRegionY |
OverlayKey | currentRegionID |
std::set< OverlayKey > | subscribedRegions |
int | fieldSize |
int | numSubspaces |
int | regionSize |
int | AOIWidth |
int | receivedMovementLists |
int | lostMovementLists |
int | maxMoveDelay |
int | playerTimeout |
cMessage * | playerTimer |
std::map< NodeHandle, PlayerInfo > | playerMap |
Classes | |
struct | PlayerInfo |
SimMud::SimMud | ( | ) |
00034 { 00035 currentRegionX = currentRegionY = INT_MIN; 00036 currentRegionID = OverlayKey::UNSPECIFIED_KEY; 00037 playerTimer = new cMessage("playerTimeout"); 00038 }
SimMud::~SimMud | ( | ) |
void SimMud::initializeApp | ( | int | stage | ) | [virtual] |
Initialize class attributes.
Reimplemented from BaseApp.
00057 { 00058 if( stage != (numInitStages()-1)) { 00059 return; 00060 } 00061 00062 // FIXME: areaDimension is not used consistently between all overlays! 00063 fieldSize = par("areaDimension"); 00064 numSubspaces = par("numSubspaces"); 00065 regionSize = fieldSize / numSubspaces; 00066 playerTimeout = par("playerTimeout"); 00067 00068 receivedMovementLists = 0; 00069 lostMovementLists = 0; 00070 00071 maxMoveDelay = par("maxMoveDelay"); 00072 AOIWidth = par("AOIWidth"); 00073 00074 WATCH(currentRegionX); 00075 WATCH(currentRegionY); 00076 WATCH(currentRegionID); 00077 // WATCH_MAP( playerMap ); 00078 }
void SimMud::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
processes self-messages
method to handle self-messages should be overwritten in derived application if needed
msg | self-message |
Reimplemented from BaseApp.
00097 { 00098 if( msg == playerTimer ) { 00099 // Check if any player didn't send any updates since last check 00100 map<NodeHandle, PlayerInfo>::iterator it; 00101 list<NodeHandle> erasePlayers; 00102 for( it = playerMap.begin(); it != playerMap.end(); ++it ) { 00103 if( it->second.update == false ) { 00104 erasePlayers.push_back( it->first ); 00105 } 00106 it->second.update = false; 00107 } 00108 for( list<NodeHandle>::iterator it = erasePlayers.begin(); it != erasePlayers.end(); ++it) { 00109 // Delete all neighbors that didn't update (and inform app) 00110 GameAPIListMessage *scMsg = new GameAPIListMessage("NEIGHBOR_UPDATE"); 00111 scMsg->setCommand(NEIGHBOR_UPDATE); 00112 scMsg->setRemoveNeighborArraySize(1); 00113 scMsg->setRemoveNeighbor(0, *it); 00114 send(scMsg, "to_upperTier"); 00115 00116 playerMap.erase( *it ); 00117 } 00118 erasePlayers.clear(); 00119 00120 scheduleAt( simulation.simTime() + playerTimeout, msg ); 00121 } 00122 }
void SimMud::handleUpperMessage | ( | cMessage * | msg | ) | [virtual] |
handleUpperMessage gets called of handleMessage(cMessage* msg) if msg arrivedOn from_upperTier (currently msg gets deleted in this function)
msg | the message to handle |
Reimplemented from BaseApp.
00157 { 00158 if( GameAPIPositionMessage* moveMsg = 00159 dynamic_cast<GameAPIPositionMessage*>(msg) ) { 00160 handleMove( moveMsg ); 00161 delete msg; 00162 } 00163 }
void SimMud::handleLowerMessage | ( | cMessage * | msg | ) | [virtual] |
method to handle non-commonAPI messages from the overlay
msg | message to handle |
Reimplemented from BaseApp.
00125 { 00126 if (ALMMulticastMessage* mcastMsg = 00127 dynamic_cast<ALMMulticastMessage*>(msg) ){ 00128 00129 cMessage* innerMsg = mcastMsg->decapsulate(); 00130 SimMudMoveMessage* moveMsg = NULL; 00131 if( innerMsg ) { 00132 moveMsg = dynamic_cast<SimMudMoveMessage*>(innerMsg); 00133 } 00134 if( moveMsg ) { 00135 handleOtherPlayerMove( moveMsg ); 00136 } 00137 delete innerMsg; 00138 delete mcastMsg; 00139 } 00140 }
void SimMud::handleReadyMessage | ( | CompReadyMessage * | msg | ) | [virtual] |
method to handle ready messages from the overlay
msg | message to handle |
Reimplemented from BaseApp.
00143 { 00144 if( msg->getReady() ) { 00145 // TODO/FIXME: maybe ugly? send CompReadyMessage directly from BaseApp to SimpleGameClient? 00146 send(msg, "to_upperTier"); 00147 00148 if( playerTimeout > 0 ) { 00149 cancelEvent( playerTimer ); 00150 scheduleAt( simulation.simTime() + playerTimeout, playerTimer ); 00151 } 00152 } 00153 //delete msg; 00154 }
bool SimMud::handleRpc | ( | BaseCallMessage * | msg | ) | [virtual] |
Processes Remote-Procedure-Call invokation messages.
This method should be overloaded when the overlay provides RPC functionality.
Reimplemented from BaseRpc.
00081 { 00082 // RPC_SWITCH_START(msg); 00083 // RPC_SWITCH_END( ); 00084 // return RPC_HANDLED; 00085 return false; 00086 }
void SimMud::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [virtual] |
This method is called if an RPC response has been received.
msg | The response message. | |
context | Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code | |
rpcId | The RPC id. | |
rtt | The Round-Trip-Time of this RPC |
Reimplemented from RpcListener.
void SimMud::finishApp | ( | ) | [virtual] |
collect statistical data
Reimplemented from BaseApp.
00046 { 00047 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime); 00048 if(time == 0) return; 00049 00050 globalStatistics->addStdDev("SimMUD: Lost or too long delayed MoveLists/s", 00051 lostMovementLists / time); 00052 globalStatistics->addStdDev("SimMUD: Received valid MoveLists/s", 00053 receivedMovementLists / time); 00054 }
void SimMud::handleMove | ( | GameAPIPositionMessage * | msg | ) | [protected] |
Referenced by handleUpperMessage().
00166 { 00167 if( (int) (msg->getPosition().x/regionSize) != currentRegionX || 00168 (int) (msg->getPosition().y/regionSize) != currentRegionY ) { 00169 // New position is outside of current region; change currentRegion 00170 00171 // get region ID 00172 currentRegionX = (int) (msg->getPosition().x/regionSize); 00173 currentRegionY = (int) (msg->getPosition().y/regionSize); 00174 std::stringstream regionstr; 00175 regionstr << currentRegionX << ":" << currentRegionY; 00176 OverlayKey region = OverlayKey::sha1( BinaryValue(regionstr.str() )); 00177 currentRegionID = region; 00178 } 00179 00180 set<OverlayKey> expectedRegions; 00181 set<OverlayKey> allowedRegions; 00182 int minX = (int) ((msg->getPosition().x - AOIWidth)/regionSize); 00183 if( minX < 0 ) minX = 0; 00184 int maxX = (int) ((msg->getPosition().x + AOIWidth)/regionSize); 00185 if( maxX >= numSubspaces ) maxX = numSubspaces -1; 00186 int minY = (int) ((msg->getPosition().y - AOIWidth)/regionSize); 00187 if( minY < 0 ) minY = 0; 00188 int maxY = (int) ((msg->getPosition().y + AOIWidth)/regionSize); 00189 if( maxY >= numSubspaces ) maxY = numSubspaces -1; 00190 00191 // FIXME: make parameter: unsubscription size 00192 int minUnsubX = (int) ((msg->getPosition().x - 1.5*AOIWidth)/regionSize); 00193 if( minUnsubX < 0 ) minUnsubX = 0; 00194 int maxUnsubX = (int) ((msg->getPosition().x + 1.5*AOIWidth)/regionSize); 00195 if( maxUnsubX >= numSubspaces ) maxUnsubX = numSubspaces -1; 00196 int minUnsubY = (int) ((msg->getPosition().y - 1.5*AOIWidth)/regionSize); 00197 if( minUnsubY < 0 ) minUnsubY = 0; 00198 int maxUnsubY = (int) ((msg->getPosition().y + 1.5+AOIWidth)/regionSize); 00199 if( maxUnsubY >= numSubspaces ) maxUnsubY = numSubspaces -1; 00200 00201 for( int x = minUnsubX; x <= maxUnsubX; ++x ){ 00202 for( int y = minUnsubY; y <= maxUnsubY; ++y ){ 00203 std::stringstream regionstr; 00204 regionstr << x << ":" << y; 00205 if( x >= minX && x <=maxX && y >= minY && y <= maxY ){ 00206 expectedRegions.insert( OverlayKey::sha1( BinaryValue(regionstr.str() ))); 00207 } 00208 allowedRegions.insert( OverlayKey::sha1( BinaryValue(regionstr.str() ))); 00209 } 00210 } 00211 00212 set<OverlayKey>::iterator subIt = subscribedRegions.begin(); 00213 while( subIt != subscribedRegions.end() ){ 00214 00215 expectedRegions.erase( *subIt ); 00216 00217 // unsubscribe region if to far away 00218 if( allowedRegions.find( *subIt ) == allowedRegions.end() ){ 00219 // Inform other players about region leave 00220 SimMudMoveMessage* moveMsg = new SimMudMoveMessage("MOVE/LEAVE_REGION"); 00221 moveMsg->setSrc( overlay->getThisNode() ); 00222 moveMsg->setPosX( msg->getPosition().x ); 00223 moveMsg->setPosY( msg->getPosition().y ); 00224 moveMsg->setTimestamp( simulation.simTime() ); 00225 moveMsg->setLeaveRegion( true ); 00226 ALMMulticastMessage* mcastMsg = new ALMMulticastMessage("MOVE/LEAVE_REGION"); 00227 mcastMsg->setGroupId(*subIt); 00228 mcastMsg->encapsulate( moveMsg ); 00229 00230 send(mcastMsg, "to_lowerTier"); 00231 00232 // leave old region's multicastGroup 00233 ALMLeaveMessage* leaveMsg = new ALMLeaveMessage("LEAVE_REGION_GROUP"); 00234 leaveMsg->setGroupId(*subIt); 00235 send(leaveMsg, "to_lowerTier"); 00236 // TODO: leave old simMud region 00237 00238 // Erase subspace from subscribedList and increase iterator 00239 subscribedRegions.erase( subIt++ ); 00240 } else { 00241 ++subIt; 00242 } 00243 } 00244 00245 // if any "near" region is not yet subscribed, subscribe 00246 for( set<OverlayKey>::iterator regionIt = expectedRegions.begin(); regionIt != expectedRegions.end(); ++regionIt ){ 00247 // join region's multicast group 00248 ALMSubscribeMessage* subMsg = new ALMSubscribeMessage; 00249 subMsg->setGroupId(*regionIt); 00250 send( subMsg, "to_lowerTier" ); 00251 00252 subscribedRegions.insert( *regionIt ); 00253 // TODO: join simMud region 00254 } 00255 00256 // publish movement 00257 SimMudMoveMessage* moveMsg = new SimMudMoveMessage("MOVE"); 00258 moveMsg->setSrc( overlay->getThisNode() ); 00259 moveMsg->setPosX( msg->getPosition().x ); 00260 moveMsg->setPosY( msg->getPosition().y ); 00261 moveMsg->setTimestamp( simulation.simTime() ); 00262 moveMsg->setLength( SIMMUD_MOVE_L( moveMsg )); 00263 ALMMulticastMessage* mcastMsg = new ALMMulticastMessage("MOVE"); 00264 mcastMsg->setGroupId(currentRegionID); 00265 mcastMsg->encapsulate( moveMsg ); 00266 00267 send(mcastMsg, "to_lowerTier"); 00268 }
void SimMud::handleOtherPlayerMove | ( | SimMudMoveMessage * | msg | ) | [protected] |
Referenced by handleLowerMessage().
00271 { 00272 GameAPIListMessage *scMsg = new GameAPIListMessage("NEIGHBOR_UPDATE"); 00273 scMsg->setCommand(NEIGHBOR_UPDATE); 00274 00275 NodeHandle& src = msg->getSrc(); 00276 RECORD_STATS( 00277 if( msg->getTimestamp() < simulation.simTime() - maxMoveDelay ){ 00278 ++lostMovementLists; 00279 } else { 00280 ++receivedMovementLists; 00281 } 00282 00283 if( src != overlay->getThisNode() ){ 00284 globalStatistics->addStdDev("SimMUD: MOVE Delay", 00285 simulation.simTime() - msg->getTimestamp() ); 00286 } 00287 ); 00288 00289 if( msg->getLeaveRegion() ) { 00290 // Player leaves region 00291 scMsg->setRemoveNeighborArraySize(1); 00292 scMsg->setRemoveNeighbor(0, src); 00293 playerMap.erase( src ); 00294 00295 } else { 00296 PlayerInfo player; 00297 player.pos = Vector2D( msg->getPosX(), msg->getPosY() ); 00298 player.update = true; 00299 00300 pair< map<NodeHandle, PlayerInfo>::iterator, bool> inserter = 00301 playerMap.insert( make_pair(src, player) ); 00302 00303 /* if( inserter.second ) { 00304 // new player 00305 00306 } else { 00307 // move player 00308 }*/ 00309 00310 // Ordinary move 00311 scMsg->setAddNeighborArraySize(1); 00312 scMsg->setNeighborPositionArraySize(1); 00313 scMsg->setAddNeighbor(0, src); 00314 scMsg->setNeighborPosition(0, Vector2D(msg->getPosX(), msg->getPosY()) ); 00315 } 00316 send(scMsg, "to_upperTier"); 00317 00318 }
int SimMud::currentRegionX [private] |
Referenced by handleMove(), initializeApp(), and SimMud().
int SimMud::currentRegionY [private] |
Referenced by handleMove(), initializeApp(), and SimMud().
OverlayKey SimMud::currentRegionID [private] |
Referenced by handleMove(), initializeApp(), and SimMud().
std::set<OverlayKey> SimMud::subscribedRegions [private] |
Referenced by handleMove().
int SimMud::fieldSize [private] |
Referenced by initializeApp().
int SimMud::numSubspaces [private] |
Referenced by handleMove(), and initializeApp().
int SimMud::regionSize [private] |
Referenced by handleMove(), and initializeApp().
int SimMud::AOIWidth [private] |
Referenced by handleMove(), and initializeApp().
int SimMud::receivedMovementLists [private] |
Referenced by finishApp(), handleOtherPlayerMove(), and initializeApp().
int SimMud::lostMovementLists [private] |
Referenced by finishApp(), handleOtherPlayerMove(), and initializeApp().
int SimMud::maxMoveDelay [private] |
Referenced by handleOtherPlayerMove(), and initializeApp().
int SimMud::playerTimeout [private] |
Referenced by handleReadyMessage(), handleTimerEvent(), and initializeApp().
cMessage* SimMud::playerTimer [private] |
Referenced by handleReadyMessage(), handleTimerEvent(), SimMud(), and ~SimMud().
std::map<NodeHandle, PlayerInfo> SimMud::playerMap [private] |
Referenced by handleOtherPlayerMove(), and handleTimerEvent().