#include <SimMud.h>
Classes | |
struct | PlayerInfo |
Public Member Functions | |
SimMud () | |
~SimMud () | |
virtual void | initializeApp (int stage) |
Initialize class attributes. | |
virtual void | handleTimerEvent (cMessage *msg) |
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) |
processes self-messages | |
virtual void | handleReadyMessage (CompReadyMessage *msg) |
method to handle ready messages from the overlay | |
virtual bool | handleRpcCall (BaseCallMessage *msg) |
virtual void | handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt) |
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 |
simtime_t | maxMoveDelay |
int | playerTimeout |
cMessage * | playerTimer |
std::map< NodeHandle, PlayerInfo > | playerMap |
Definition at line 33 of file SimMud.h.
SimMud::SimMud | ( | ) |
Definition at line 33 of file SimMud.cc.
{ currentRegionX = currentRegionY = INT_MIN; currentRegionID = OverlayKey::UNSPECIFIED_KEY; playerTimer = new cMessage("playerTimeout"); }
SimMud::~SimMud | ( | ) |
Definition at line 40 of file SimMud.cc.
{ cancelAndDelete(playerTimer); }
void SimMud::finishApp | ( | ) | [virtual] |
collect statistical data
Reimplemented from BaseApp.
Definition at line 45 of file SimMud.cc.
{ simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime); if (time < GlobalStatistics::MIN_MEASURED) return; globalStatistics->addStdDev("SimMUD: Lost or too long delayed MoveLists/s", lostMovementLists / time); globalStatistics->addStdDev("SimMUD: Received valid MoveLists/s", receivedMovementLists / time); }
void SimMud::handleLowerMessage | ( | cMessage * | msg | ) | [virtual] |
processes self-messages
method to handle self-messages should be overwritten in derived application if needed
msg | self-message method to handle non-commonAPI messages from the overlay | |
msg | message to handle |
Reimplemented from BaseApp.
Definition at line 124 of file SimMud.cc.
{ if (ALMMulticastMessage* mcastMsg = dynamic_cast<ALMMulticastMessage*>(msg) ){ cMessage* innerMsg = mcastMsg->decapsulate(); SimMudMoveMessage* moveMsg = NULL; if( innerMsg ) { moveMsg = dynamic_cast<SimMudMoveMessage*>(innerMsg); } if( moveMsg ) { handleOtherPlayerMove( moveMsg ); } delete innerMsg; delete mcastMsg; } }
void SimMud::handleMove | ( | GameAPIPositionMessage * | msg | ) | [protected] |
Definition at line 175 of file SimMud.cc.
Referenced by handleUpperMessage().
{ if( (int) (msg->getPosition().x/regionSize) != currentRegionX || (int) (msg->getPosition().y/regionSize) != currentRegionY ) { // New position is outside of current region; change currentRegion // get region ID currentRegionX = (int) (msg->getPosition().x/regionSize); currentRegionY = (int) (msg->getPosition().y/regionSize); std::stringstream regionstr; regionstr << currentRegionX << ":" << currentRegionY; OverlayKey region = OverlayKey::sha1( BinaryValue(regionstr.str() )); currentRegionID = region; } set<OverlayKey> expectedRegions; set<OverlayKey> allowedRegions; int minX = (int) ((msg->getPosition().x - AOIWidth)/regionSize); if( minX < 0 ) minX = 0; int maxX = (int) ((msg->getPosition().x + AOIWidth)/regionSize); if( maxX >= numSubspaces ) maxX = numSubspaces -1; int minY = (int) ((msg->getPosition().y - AOIWidth)/regionSize); if( minY < 0 ) minY = 0; int maxY = (int) ((msg->getPosition().y + AOIWidth)/regionSize); if( maxY >= numSubspaces ) maxY = numSubspaces -1; // FIXME: make parameter: unsubscription size int minUnsubX = (int) ((msg->getPosition().x - 1.5*AOIWidth)/regionSize); if( minUnsubX < 0 ) minUnsubX = 0; int maxUnsubX = (int) ((msg->getPosition().x + 1.5*AOIWidth)/regionSize); if( maxUnsubX >= numSubspaces ) maxUnsubX = numSubspaces -1; int minUnsubY = (int) ((msg->getPosition().y - 1.5*AOIWidth)/regionSize); if( minUnsubY < 0 ) minUnsubY = 0; int maxUnsubY = (int) ((msg->getPosition().y + 1.5+AOIWidth)/regionSize); if( maxUnsubY >= numSubspaces ) maxUnsubY = numSubspaces -1; for( int x = minUnsubX; x <= maxUnsubX; ++x ){ for( int y = minUnsubY; y <= maxUnsubY; ++y ){ std::stringstream regionstr; regionstr << x << ":" << y; if( x >= minX && x <=maxX && y >= minY && y <= maxY ){ expectedRegions.insert( OverlayKey::sha1( BinaryValue(regionstr.str() ))); } allowedRegions.insert( OverlayKey::sha1( BinaryValue(regionstr.str() ))); } } set<OverlayKey>::iterator subIt = subscribedRegions.begin(); while( subIt != subscribedRegions.end() ){ expectedRegions.erase( *subIt ); // unsubscribe region if to far away if( allowedRegions.find( *subIt ) == allowedRegions.end() ){ // Inform other players about region leave SimMudMoveMessage* moveMsg = new SimMudMoveMessage("MOVE/LEAVE_REGION"); moveMsg->setSrc( overlay->getThisNode() ); moveMsg->setPosX( msg->getPosition().x ); moveMsg->setPosY( msg->getPosition().y ); moveMsg->setTimestamp( simTime() ); moveMsg->setLeaveRegion( true ); ALMMulticastMessage* mcastMsg = new ALMMulticastMessage("MOVE/LEAVE_REGION"); mcastMsg->setGroupId(*subIt); mcastMsg->encapsulate( moveMsg ); send(mcastMsg, "to_lowerTier"); // leave old region's multicastGroup ALMLeaveMessage* leaveMsg = new ALMLeaveMessage("LEAVE_REGION_GROUP"); leaveMsg->setGroupId(*subIt); send(leaveMsg, "to_lowerTier"); // TODO: leave old simMud region // Erase subspace from subscribedList and increase iterator subscribedRegions.erase( subIt++ ); } else { ++subIt; } } // if any "near" region is not yet subscribed, subscribe for( set<OverlayKey>::iterator regionIt = expectedRegions.begin(); regionIt != expectedRegions.end(); ++regionIt ){ // join region's multicast group ALMSubscribeMessage* subMsg = new ALMSubscribeMessage; subMsg->setGroupId(*regionIt); send( subMsg, "to_lowerTier" ); subscribedRegions.insert( *regionIt ); // TODO: join simMud region } // publish movement SimMudMoveMessage* moveMsg = new SimMudMoveMessage("MOVE"); moveMsg->setSrc( overlay->getThisNode() ); moveMsg->setPosX( msg->getPosition().x ); moveMsg->setPosY( msg->getPosition().y ); moveMsg->setTimestamp( simTime() ); moveMsg->setBitLength( SIMMUD_MOVE_L( moveMsg )); ALMMulticastMessage* mcastMsg = new ALMMulticastMessage("MOVE"); mcastMsg->setGroupId(currentRegionID); mcastMsg->encapsulate( moveMsg ); send(mcastMsg, "to_lowerTier"); }
void SimMud::handleOtherPlayerMove | ( | SimMudMoveMessage * | msg | ) | [protected] |
Definition at line 280 of file SimMud.cc.
Referenced by handleLowerMessage().
{ GameAPIListMessage *scMsg = new GameAPIListMessage("NEIGHBOR_UPDATE"); scMsg->setCommand(NEIGHBOR_UPDATE); NodeHandle& src = msg->getSrc(); RECORD_STATS( if( msg->getTimestamp() < simTime() - maxMoveDelay ){ ++lostMovementLists; globalStatistics->addStdDev("SimMUD: LOST MOVE Delay", SIMTIME_DBL(simTime() - msg->getTimestamp()) ); } else { ++receivedMovementLists; } if( src != overlay->getThisNode() ){ globalStatistics->addStdDev("SimMUD: MOVE Delay", SIMTIME_DBL(simTime() - msg->getTimestamp()) ); } ); if( msg->getLeaveRegion() ) { // Player leaves region scMsg->setRemoveNeighborArraySize(1); scMsg->setRemoveNeighbor(0, src); playerMap.erase( src ); } else { PlayerInfo player; player.pos = Vector2D( msg->getPosX(), msg->getPosY() ); player.update = true; pair< map<NodeHandle, PlayerInfo>::iterator, bool> inserter = playerMap.insert( make_pair(src, player) ); /* if( inserter.second ) { // new player } else { // move player }*/ // Ordinary move scMsg->setAddNeighborArraySize(1); scMsg->setNeighborPositionArraySize(1); scMsg->setAddNeighbor(0, src); scMsg->setNeighborPosition(0, Vector2D(msg->getPosX(), msg->getPosY()) ); } send(scMsg, "to_upperTier"); }
void SimMud::handleReadyMessage | ( | CompReadyMessage * | msg | ) | [virtual] |
method to handle ready messages from the overlay
msg | message to handle |
Reimplemented from BaseApp.
Definition at line 142 of file SimMud.cc.
{ // process only ready messages from the tier below if( getThisCompType() - msg->getComp() == 1 ){ if( msg->getReady() ) { // TODO/FIXME: use overlay->sendMessageToAllComp(msg, getThisCompType())? msg->setComp(getThisCompType()); send(msg, "to_upperTier"); // also send AOI size to SimpleGameClient GameAPIResizeAOIMessage* gameMsg = new GameAPIResizeAOIMessage("RESIZE_AOI"); gameMsg->setCommand(RESIZE_AOI); gameMsg->setAOIsize(AOIWidth); send(gameMsg, "to_upperTier"); if( playerTimeout > 0 ) { cancelEvent( playerTimer ); scheduleAt( simTime() + playerTimeout, playerTimer ); } } } else { delete msg; } }
bool SimMud::handleRpcCall | ( | BaseCallMessage * | msg | ) | [virtual] |
void SimMud::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [virtual] |
void SimMud::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Definition at line 96 of file SimMud.cc.
{ if( msg == playerTimer ) { // Check if any player didn't send any updates since last check map<NodeHandle, PlayerInfo>::iterator it; list<NodeHandle> erasePlayers; for( it = playerMap.begin(); it != playerMap.end(); ++it ) { if( it->second.update == false ) { erasePlayers.push_back( it->first ); } it->second.update = false; } for( list<NodeHandle>::iterator it = erasePlayers.begin(); it != erasePlayers.end(); ++it) { // Delete all neighbors that didn't update (and inform app) GameAPIListMessage *scMsg = new GameAPIListMessage("NEIGHBOR_UPDATE"); scMsg->setCommand(NEIGHBOR_UPDATE); scMsg->setRemoveNeighborArraySize(1); scMsg->setRemoveNeighbor(0, *it); send(scMsg, "to_upperTier"); playerMap.erase( *it ); } erasePlayers.clear(); scheduleAt( simTime() + playerTimeout, msg ); } }
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.
Definition at line 166 of file SimMud.cc.
{ if( GameAPIPositionMessage* moveMsg = dynamic_cast<GameAPIPositionMessage*>(msg) ) { handleMove( moveMsg ); delete msg; } }
void SimMud::initializeApp | ( | int | stage | ) | [virtual] |
Initialize class attributes.
Reimplemented from BaseApp.
Definition at line 56 of file SimMud.cc.
{ if( stage != (numInitStages()-1)) { return; } // FIXME: areaDimension is not used consistently between all overlays! fieldSize = par("areaDimension"); numSubspaces = par("numSubspaces"); regionSize = fieldSize / numSubspaces; playerTimeout = par("playerTimeout"); receivedMovementLists = 0; lostMovementLists = 0; maxMoveDelay = par("maxMoveDelay"); AOIWidth = par("AOIWidth"); WATCH(currentRegionX); WATCH(currentRegionY); WATCH(currentRegionID); // WATCH_MAP( playerMap ); }
int SimMud::AOIWidth [private] |
Definition at line 44 of file SimMud.h.
Referenced by handleMove(), handleReadyMessage(), and initializeApp().
OverlayKey SimMud::currentRegionID [private] |
Definition at line 38 of file SimMud.h.
Referenced by handleMove(), initializeApp(), and SimMud().
int SimMud::currentRegionX [private] |
Definition at line 36 of file SimMud.h.
Referenced by handleMove(), initializeApp(), and SimMud().
int SimMud::currentRegionY [private] |
Definition at line 37 of file SimMud.h.
Referenced by handleMove(), initializeApp(), and SimMud().
int SimMud::fieldSize [private] |
Definition at line 41 of file SimMud.h.
Referenced by initializeApp().
int SimMud::lostMovementLists [private] |
Definition at line 47 of file SimMud.h.
Referenced by finishApp(), handleOtherPlayerMove(), and initializeApp().
simtime_t SimMud::maxMoveDelay [private] |
Definition at line 48 of file SimMud.h.
Referenced by handleOtherPlayerMove(), and initializeApp().
int SimMud::numSubspaces [private] |
Definition at line 42 of file SimMud.h.
Referenced by handleMove(), and initializeApp().
std::map<NodeHandle, PlayerInfo> SimMud::playerMap [private] |
Definition at line 58 of file SimMud.h.
Referenced by handleOtherPlayerMove(), and handleTimerEvent().
int SimMud::playerTimeout [private] |
Definition at line 50 of file SimMud.h.
Referenced by handleReadyMessage(), handleTimerEvent(), and initializeApp().
cMessage* SimMud::playerTimer [private] |
Definition at line 51 of file SimMud.h.
Referenced by handleReadyMessage(), handleTimerEvent(), SimMud(), and ~SimMud().
int SimMud::receivedMovementLists [private] |
Definition at line 46 of file SimMud.h.
Referenced by finishApp(), handleOtherPlayerMove(), and initializeApp().
int SimMud::regionSize [private] |
Definition at line 43 of file SimMud.h.
Referenced by handleMove(), and initializeApp().
std::set<OverlayKey> SimMud::subscribedRegions [private] |
Definition at line 39 of file SimMud.h.
Referenced by handleMove().