00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "action.h"
00023
00024 #include "../vehicle.h"
00025 #include "action-registry.h"
00026 #include "actioncontainer.h"
00027
00028 GameAction::GameAction( GameMap* map )
00029 : gamemap(map)
00030 {
00031 static int counter = 0;
00032 sequenceNumber = ++counter;
00033 }
00034
00035
00036 void GameAction::addChild( GameAction* action )
00037 {
00038 children.push_back ( action );
00039 }
00040
00041 ActionResult GameAction::execute( const Context& context )
00042 {
00043 if ( context.parentAction )
00044 context.parentAction->addChild( this );
00045
00046 Context c ( context, this );
00047
00048 try {
00049 displayLogMessage(4, "executing " + getDescription() + "\n");
00050 ActionResult result = runAction( c );
00051 Command* command = dynamic_cast<Command*>(this);
00052 if ( context.actionContainer && result.successful() && !context.parentAction && command)
00053 context.actionContainer->add( command );
00054 return result;
00055 } catch ( ActionResult res ) {
00056 return res;
00057 }
00058 }
00059
00060 ActionResult GameAction::undoChildren( const Context& context )
00061 {
00062 ActionResult res(0);
00063 for ( Children::reverse_iterator i = children.rbegin(); i != children.rend(); ++i ) {
00064 ActionResult r = (*i)->undo( context );
00065 if ( !r.successful() && res.successful() )
00066 res = r;
00067 }
00068 return res;
00069 }
00070
00071 static void mergeActionFailures( ActionResult& failure, const ActionResult& res )
00072 {
00073 if ( failure.successful() && !res.successful())
00074 failure = res;
00075 }
00076
00077 ActionResult GameAction::undo( const Context& context )
00078 {
00079
00080 ActionResult failure(0);
00081 if ( undoOrderChildFirst() ) {
00082 ActionResult r = undoChildren(context);
00083 mergeActionFailures( failure, r );
00084 }
00085
00086 displayLogMessage(4, "undoing #" + ASCString::toString(sequenceNumber) + " " + getDescription() + "\n");
00087 ActionResult res = undoAction( context );
00088 if ( !res.successful() )
00089 warningMessage("error undoing " + getDescription() + "\n" + res.getMessage() );
00090 mergeActionFailures( failure, res );
00091
00092 if ( !undoOrderChildFirst() ) {
00093 ActionResult r = undoChildren(context);
00094 mergeActionFailures( failure, r );
00095 }
00096
00097 return failure;
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107 const int currentGameActionVersion = 1;
00108 const int gameActionToken = 0x12003496;
00109
00110 void GameAction::read ( tnstream& stream )
00111 {
00112 displayLogMessage(1, "reading " + ASCString::toString(getID()) + "\n");
00113
00114 int version = stream.readInt();
00115 if ( version > currentGameActionVersion )
00116 throw tinvalidversion ( "GameAction", currentGameActionVersion, version );
00117
00118 readData( stream );
00119
00120 int token = stream.readInt();
00121 if ( token != gameActionToken )
00122 throw tinvalidversion ("GameActionToken for id " + ASCString::toString( getID() ), gameActionToken, token );
00123
00124 int childNum = stream.readInt();
00125 for ( int i = 0; i < childNum; i++ ) {
00126 GameAction* child = readFromStream( stream, getMap() );
00127 addChild( child );
00128 }
00129 }
00130
00131 void GameAction::write ( tnstream& stream, bool persistChildren ) const
00132 {
00133 stream.writeInt( getID() );
00134 stream.writeInt( currentGameActionVersion );
00135 writeData( stream );
00136 stream.writeInt( gameActionToken );
00137 if ( persistChildren ) {
00138 stream.writeInt( children.size() );
00139 for ( int i = 0; i < children.size(); ++i )
00140 children[i]->write( stream );
00141 } else
00142 stream.writeInt( 0 );
00143 }
00144
00145 void GameAction::write ( tnstream& stream ) const
00146 {
00147 write( stream, true );
00148 }
00149
00150 GameAction* GameAction::readFromStream( tnstream& stream, GameMap* map )
00151 {
00152 GameActionID id = GameActionID( stream.readInt() );
00153 GameAction* action = gameActionFactory::Instance().createObject( id, map );
00154 action->read( stream );
00155 return action;
00156 }
00157
00158
00159 void GameAction::deleteChildren()
00160 {
00161 for ( Children::iterator i = children.begin(); i != children.end(); ++i )
00162 delete *i;
00163 children.clear();
00164 }