SimMud Class Reference

#include <SimMud.h>

Inheritance diagram for SimMud:

BaseApp BaseRpc RpcListener

List of all members.

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< OverlayKeysubscribedRegions
int fieldSize
int numSubspaces
int regionSize
int AOIWidth
int receivedMovementLists
int lostMovementLists
int maxMoveDelay
int playerTimeout
cMessage * playerTimer
std::map< NodeHandle, PlayerInfoplayerMap

Classes

struct  PlayerInfo


Constructor & Destructor Documentation

SimMud::SimMud (  ) 

00034 {
00035     currentRegionX = currentRegionY = INT_MIN;
00036     currentRegionID = OverlayKey::UNSPECIFIED_KEY;
00037     playerTimer = new cMessage("playerTimeout");
00038 }

SimMud::~SimMud (  ) 

00041 {
00042     cancelAndDelete(playerTimer);
00043 }


Member Function Documentation

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

Parameters:
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)

Parameters:
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

Parameters:
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

Parameters:
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.

Returns:
true, if rpc has been handled

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.

Parameters:
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.

00091 {
00092 //    RPC_SWITCH_START(msg);
00093 //    RPC_SWITCH_END( );
00094 }

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 }


Member Data Documentation

int SimMud::currentRegionX [private]

Referenced by handleMove(), initializeApp(), and SimMud().

int SimMud::currentRegionY [private]

Referenced by handleMove(), initializeApp(), and SimMud().

Referenced by handleMove(), initializeApp(), and SimMud().

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::maxMoveDelay [private]

int SimMud::playerTimeout [private]

cMessage* SimMud::playerTimer [private]

std::map<NodeHandle, PlayerInfo> SimMud::playerMap [private]


The documentation for this class was generated from the following files:

Generated on Fri Sep 19 13:05:08 2008 for ITM OverSim by  doxygen 1.5.5