Classes | Public Member Functions | Protected Member Functions | Private Attributes

SimMud Class Reference

#include <SimMud.h>

Inheritance diagram for SimMud:
BaseApp BaseRpc BaseTcpSupport RpcListener

List of all members.

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

Detailed Description

Definition at line 33 of file SimMud.h.


Constructor & Destructor Documentation

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);
}


Member Function Documentation

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

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

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

Definition at line 80 of file SimMud.cc.

{
//    RPC_SWITCH_START(msg);
//    RPC_SWITCH_END( );
//    return RPC_HANDLED;
      return false;
}

void SimMud::handleRpcResponse ( BaseResponseMessage msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [virtual]

Definition at line 88 of file SimMud.cc.

{
//    RPC_SWITCH_START(msg);
//    RPC_SWITCH_END( );
}

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)

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


Member Data Documentation

int SimMud::AOIWidth [private]

Definition at line 44 of file SimMud.h.

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

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().

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().

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().

Definition at line 39 of file SimMud.h.

Referenced by handleMove().


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