replay.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           replay.cpp  -  description
00003                              -------------------
00004     begin                : Sun Jan 21 2001
00005     copyright            : (C) 2001 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00016 /***************************************************************************
00017  *                                                                         *
00018  *   This program is free software; you can redistribute it and/or modify  *
00019  *   it under the terms of the GNU General Public License as published by  *
00020  *   the Free Software Foundation; either version 2 of the License, or     *
00021  *   (at your option) any later version.                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #include <stdarg.h>
00026 #include "replay.h"
00027 #include "typen.h"
00028 #include "buildingtype.h"
00029 #include "vehicletype.h"
00030 #include "spfst.h"
00031 #include "controls.h"
00032 #include "dialog.h"
00033 #include "gameoptions.h"
00034 #include "viewcalculation.h"
00035 #include "itemrepository.h"
00036 #include "containercontrols.h"
00037 #include "resourcenet.h"
00038 #include "guiiconhandler.h"
00039 #include "guifunctions.h"
00040 #include "cannedmessages.h"
00041 #include "spfst-legacy.h"
00042 #include "replaymapdisplay.h"
00043 #include "asc-mainscreen.h"
00044 #include "loaders.h"
00045 #include "turncontrol.h"
00046 #include "widgets/textrenderer.h"
00047 #include "actions/jumpdrivecommand.h"
00048 #include "reactionfire.h"
00049 #include "gameeventsystem.h"
00050 #include "sdl/graphicsqueue.h"
00051 #include "video/videorecorder.h"
00052 #include "iconrepository.h"
00053 #include "dialogs/replayrecorder.h"
00054 #include "sg.h"
00055 #include "actions/action.h"
00056 #include "actions/cargomovecommand.h"
00057 #include "actions/constructbuildingcommand.h"
00058 #include "actions/destructbuildingcommand.h"
00059 #include "actions/destructunitcommand.h"
00060 #include "actions/recycleunitcommand.h"
00061 #include "actions/trainunitcommand.h"
00062 #include "actions/moveunitcommand.h"
00063 #include "actions/consumeammo.h"
00064 #include "actions/consumeresource.h"
00065 #include "actions/buildproductionlinecommand.h"
00066 #include "actions/removeproductionlinecommand.h"
00067 #include "actions/cancelresearchcommand.h"
00068 #include "researchexecution.h"
00069 
00070 trunreplay runreplay;
00071 
00072 int startreplaylate = 0;
00073 
00074 
00075 enum trpl_actions { rpl_attack,
00076    rpl_move, 
00077    rpl_changeheight, 
00078    rpl_convert, 
00079    rpl_remobj, 
00080    rpl_buildobj, 
00081    rpl_putbuilding,
00082    rpl_removebuilding, 
00083    rpl_putmine, 
00084    rpl_removemine,
00085    rpl_produceunit, 
00086    rpl_removeunit,
00087    rpl_trainunit,
00088    rpl_reactionfire, 
00089    rpl_finished, 
00090    rpl_shareviewchange, 
00091    rpl_alliancechange,
00092    rpl_move2, 
00093    rpl_buildtnk,
00094    rpl_refuel, 
00095    rpl_bldrefuel, 
00096    rpl_move3, 
00097    rpl_changeheight2,
00098    rpl_buildtnk2,
00099    rpl_moveUnitUpDown,
00100    rpl_move4,
00101    rpl_productionResourceUsage,
00102    rpl_buildtnk3,
00103    rpl_refuel2,
00104    rpl_buildobj2,
00105    rpl_remobj2,
00106    rpl_repairUnit,
00107    rpl_repairUnit2,
00108    rpl_refuel3,
00109    rpl_produceAmmo,
00110    rpl_buildtnk4,
00111    rpl_buildProdLine,
00112    rpl_removeProdLine,
00113    rpl_setResearch,
00114    rpl_techResearched,
00115    rpl_putbuilding2,
00116    rpl_setGeneratorStatus,
00117    rpl_cutFromGame,
00118    rpl_removebuilding2,
00119    rpl_setResourceProcessingAmount,
00120    rpl_removebuilding3,
00121    rpl_netcontrol,
00122    rpl_move5,
00123    rpl_alliancechange2,
00124    rpl_moveUnitUp,
00125    rpl_jump,
00126    rpl_repairBuilding,
00127    rpl_recycleUnit,
00128    rpl_convert2,
00129    rpl_putmine2,
00130    rpl_repairUnit3,
00131    rpl_transferTribute,
00132    rpl_reactionFireOn,
00133    rpl_reactionFireOff,
00134    rpl_selfdestruct,
00135    rpl_cancelResearch,
00136    rpl_runCommandAction };
00137 
00138 
00139 
00140 class ReplayRecorder;
00141 
00142 class ReplayRecorderWatcherGlobal {
00143       ReplayRecorder* recorder;
00144    public:
00145       ReplayRecorderWatcherGlobal()  : recorder( NULL ) {};
00146       void set(  ReplayRecorder* rec  ) {
00147          recorder = rec;
00148       }
00149       
00150       ~ReplayRecorderWatcherGlobal() ;
00151 } replayRecorderWatcherGlobal;
00152 
00153 
00154  class ReplayRecorder : public SigC::Object {
00155    
00156    VideoRecorder* rec;
00157    SigC::Connection connection;
00158    bool movieModeStorage;
00159    ASCString lastFilename;
00160    
00161    public:
00162       ReplayRecorder() : rec (NULL)
00163       {
00164          movieModeStorage = CGameOptions::Instance()->replayMovieMode;
00165          replayRecorderWatcherGlobal.set( this );
00166       }
00167       
00168       void start( const ASCString& filename, bool append, int framerate, int ascFramerateLimit, int quality )
00169       {
00170          lastFilename = filename;
00171          movieModeStorage = CGameOptions::Instance()->replayMovieMode;
00172          CGameOptions::Instance()->replayMovieMode = true;
00173          ASCString newFilename = constructFileName( 0, "", filename );
00174          if ( !rec || !append || newFilename != rec->getFilename()  ) {
00175             delete rec;
00176             rec = new VideoRecorder( newFilename, PG_Application::GetScreen(), framerate, ascFramerateLimit, quality );
00177          }
00178          
00179          if ( !connection.connected() )
00180             connection = postScreenUpdate.connect( SigC::slot( *this, &ReplayRecorder::screenUpdate ));
00181       }
00182       
00183       void pause()
00184       {
00185          if ( connection.connected() )
00186             connection.disconnect();
00187          CGameOptions::Instance()->replayMovieMode = movieModeStorage;
00188       }
00189       
00190       void close()
00191       {
00192          pause();
00193          delete rec;
00194          rec = NULL;
00195       }
00196       
00197       bool isRunning()
00198       {
00199          return connection.connected() && rec;
00200       }
00201       
00202       bool isOpen()
00203       {
00204          return rec != NULL;  
00205       }
00206       
00207       ASCString getLastFilename()
00208       {
00209          return lastFilename;
00210       }
00211    
00212    private:
00213       void screenUpdate( const SDL_Surface* surf )
00214       {
00215          if ( rec )
00216             rec->storeFrame( surf );
00217       }
00218 };
00219 
00220 class ReplayRecorderWatcherLocal {
00221       ReplayRecorder* recorder;
00222    public:
00223       ReplayRecorderWatcherLocal( ReplayRecorder* rec )  : recorder( rec ) {};
00224       ~ReplayRecorderWatcherLocal() 
00225       { 
00226          if ( recorder ) 
00227             recorder->pause();
00228       }
00229 };
00230 
00231 
00232 ReplayRecorderWatcherGlobal::~ReplayRecorderWatcherGlobal() 
00233 { 
00234    if ( recorder ) 
00235       recorder->pause();
00236 }
00237 
00238 
00239 ReplayRecorder* replayRecorder = NULL;
00240 
00241  
00242 
00243 namespace ReplayGuiFunctions {
00244 
00245 class ReplayPlay : public GuiFunction
00246 {
00247    public:
00248       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00249       {
00250          if ( runreplay.status == 1 )
00251             return true;
00252 
00253          return false;
00254       };
00255 
00256       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00257       {
00258         runreplay.status = 2;
00259         updateFieldInfo();
00260       }
00261 
00262       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00263       {
00264          return IconRepository::getIcon("replay-play.png");
00265       };
00266 
00267       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00268       {
00269          return "start re~p~lay";
00270       };
00271 
00272       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00273       {
00274          return ( key->keysym.unicode == 'p' );
00275       };
00276       
00277 };
00278 
00279 
00280 class ReplayPause : public GuiFunction
00281 {
00282    public:
00283       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00284       {
00285          if ( runreplay.status == 2 )
00286             return true;
00287 
00288          return false;
00289       };
00290 
00291       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00292       {
00293         runreplay.status = 1;
00294         updateFieldInfo();
00295       }
00296 
00297       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00298       {
00299          return IconRepository::getIcon("replay-pause.png");
00300       };
00301 
00302       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00303       {
00304          return "~p~ause replay";
00305       };
00306       
00307       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00308       {
00309          return ( key->keysym.unicode == 'p' );
00310       };
00311       
00312 };
00313 
00314 
00315 
00316 class ReplayFaster : public GuiFunction
00317 {
00318    public:
00319       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00320       {
00321          if ( runreplay.status == 2 )
00322             if ( CGameOptions::Instance()->replayspeed > 0 )
00323               return true;
00324 
00325          return false;
00326       };
00327 
00328       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00329       {
00330          if ( CGameOptions::Instance()->replayspeed > 20 )
00331             CGameOptions::Instance()->replayspeed -= 20;
00332          else
00333             CGameOptions::Instance()->replayspeed = 0;
00334 
00335          CGameOptions::Instance()->setChanged ( 1 );
00336          displaymessage2 ( "delay set to %d / 100 sec", CGameOptions::Instance()->replayspeed );
00337          updateFieldInfo();
00338       }
00339 
00340       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00341       {
00342          return IconRepository::getIcon("replay-faster.png");
00343       };
00344 
00345       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00346       {
00347          return "increase replay speed (~+~)";
00348       };
00349 
00350       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00351       {
00352          return ( key->keysym.unicode == '+' || key->keysym.sym == SDLK_KP_PLUS);
00353       };
00354       
00355 };
00356 
00357 
00358 class ReplaySlower : public GuiFunction
00359 {
00360    public:
00361       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00362       {
00363          if ( runreplay.status == 2 )
00364             return true;
00365 
00366          return false;
00367       };
00368 
00369       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00370       {
00371          CGameOptions::Instance()->replayspeed += 20;
00372          CGameOptions::Instance()->setChanged ( 1 );
00373          displaymessage2 ( "delay set to %d / 100 sec", CGameOptions::Instance()->replayspeed );
00374          updateFieldInfo();
00375       }
00376 
00377       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00378       {
00379          return IconRepository::getIcon("replay-slow.png");
00380       };
00381 
00382       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00383       {
00384          return "decrease replay speed (~-~)";
00385       };
00386 
00387       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00388       {
00389          return ( key->keysym.unicode == '-' || key->keysym.sym == SDLK_KP_MINUS);
00390       };
00391       
00392 };
00393 
00394 
00395 class ReplayRewind : public GuiFunction
00396 {
00397    public:
00398       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00399       {
00400          if ( runreplay.status == 1  ||  runreplay.status == 10 )
00401               return true;
00402 
00403          return false;
00404       };
00405 
00406       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00407       {
00408          runreplay.status = 101;
00409          updateFieldInfo();
00410       }
00411 
00412       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00413       {
00414          return IconRepository::getIcon("replay-back.png");
00415       };
00416 
00417       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00418       {
00419          return "~r~estart replay";
00420       };
00421 
00422       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00423       {
00424          return ( key->keysym.unicode == 'r' );
00425       };
00426       
00427 };
00428 
00429 
00430 class ReplayExit : public GuiFunction
00431 {
00432    public:
00433       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00434       {
00435          if ( runreplay.status == 1 || runreplay.status == 10 || runreplay.status == 11 )
00436               return true;
00437 
00438          return false;
00439       };
00440 
00441       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00442       {
00443          runreplay.status = 100;
00444          updateFieldInfo();
00445       }
00446 
00447       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00448       {
00449          return IconRepository::getIcon("replay-exit.png");
00450       };
00451 
00452       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00453       {
00454          return "e~x~it replay";
00455       };
00456 
00457       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00458       {
00459          return ( key->keysym.unicode == 'x' );
00460       };
00461       
00462 };
00463 
00464 class ReplayRecord : public GuiFunction
00465 {
00466    public:
00467       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00468       {
00469          if ( runreplay.status == 1 )
00470             return true;
00471 
00472          return false;
00473       };
00474 
00475       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00476       {
00477         ASCString filename;
00478         bool open = false;
00479         if ( replayRecorder ) {
00480            filename = replayRecorder->getLastFilename();
00481            open = replayRecorder->isOpen();
00482         }
00483         
00484         ReplayRecorderDialog rrd( filename, open );
00485         rrd.Show();
00486         rrd.RunModal();
00487         rrd.Hide();
00488          
00489         if ( !replayRecorder )
00490            replayRecorder = new ReplayRecorder();
00491         replayRecorder->start( rrd.getFilename(), rrd.getAppend(), rrd.getFramerate(), rrd.getASCFramerateLimit(),  rrd.getQuality() );
00492         
00493         runreplay.status = 2;
00494         updateFieldInfo();
00495       }
00496 
00497       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00498       {
00499          return IconRepository::getIcon("replay-record.png");
00500       };
00501 
00502       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00503       {
00504          return "record to ~v~ideo";
00505       };
00506 
00507       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00508       {
00509          return ( key->keysym.unicode == 'v' );
00510       };
00511       
00512 };
00513 
00514 class ReplayRecordExit : public GuiFunction
00515 {
00516    public:
00517       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00518       {
00519          if ( replayRecorder && replayRecorder->isOpen() && (runreplay.status == 1 || runreplay.status == 10 || runreplay.status == 11) )
00520               return true;
00521 
00522          return false;
00523       };
00524 
00525       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00526       {
00527          replayRecorder->close();
00528          runreplay.status = 100;
00529          updateFieldInfo();
00530       }
00531 
00532       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00533       {
00534          return IconRepository::getIcon("replay-record-stop.png");
00535       };
00536 
00537       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00538       {
00539          return "exit replay and ~c~lose recording";
00540       };
00541 
00542       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00543       {
00544          return ( key->keysym.unicode == 'c' );
00545       };
00546       
00547 };
00548 
00549 
00550 }
00551 
00552 void registerReplayGuiFunctions( GuiIconHandler& handler )
00553 {
00554    handler.registerUserFunction( new ReplayGuiFunctions::ReplayPlay() );
00555 #ifdef XVIDEXPORT   
00556    handler.registerUserFunction( new ReplayGuiFunctions::ReplayRecord() );
00557 #endif   
00558    handler.registerUserFunction( new ReplayGuiFunctions::ReplayPause() );
00559    handler.registerUserFunction( new ReplayGuiFunctions::ReplayFaster() );
00560    handler.registerUserFunction( new ReplayGuiFunctions::ReplaySlower() );
00561    handler.registerUserFunction( new ReplayGuiFunctions::ReplayRewind() );
00562 #ifdef XVIDEXPORT   
00563    handler.registerUserFunction( new ReplayGuiFunctions::ReplayRecordExit() );
00564 #endif
00565    handler.registerUserFunction( new ReplayGuiFunctions::ReplayExit() );
00566 }
00567 
00568 
00569 
00570 class ReplayGuiIconHandleHandler {
00571    static GuiIconHandler* replayIconHandler;
00572    bool active;
00573    public:
00574       ReplayGuiIconHandleHandler()
00575       {
00576          if ( !replayIconHandler ) {
00577             replayIconHandler = new GuiIconHandler();
00578             registerReplayGuiFunctions( *replayIconHandler );
00579          }
00580          
00581          if ( NewGuiHost::getIconHandler() != replayIconHandler ) {
00582             active = true;
00583             NewGuiHost::pushIconHandler( replayIconHandler );
00584          } else
00585             active = false;
00586       };
00587 
00588       ~ReplayGuiIconHandleHandler()
00589       {
00590          if ( active )
00591             NewGuiHost::popIconHandler();
00592       };
00593 };
00594 GuiIconHandler* ReplayGuiIconHandleHandler::replayIconHandler = NULL;
00595 
00596 
00597 
00598 
00599 
00600 void runSpecificReplay( int player, int viewingplayer, bool performEndTurnOperations )
00601 {
00602     if ( actmap->replayinfo->map[player] && actmap->replayinfo->guidata[player] ) {
00603        try {
00604          int t;
00605          do {
00606             t = runreplay.run ( player, viewingplayer, performEndTurnOperations );
00607          } while ( t ); /* enddo */
00608        }
00609 
00610        catch ( ActionResult res ) {
00611           // displayActionError( res );
00612           delete actmap;
00613           actmap = NULL;
00614           throw NoMapLoaded();
00615        }
00616        
00617 #ifndef ASC_DEBUG
00618        catch ( ... ) {     // this will catch NullPointer-Exceptions and stuff like that, which we want to pass to the debugger  in debug mode
00619 #else
00620        catch ( GameMap m ) {  // will never be thrown, but we need catch statement for the try block
00621 #endif
00622           errorMessage("An unrecognized error occured during the replay");
00623           delete actmap;
00624           actmap = NULL;
00625           throw NoMapLoaded();
00626        }
00627     }
00628 }
00629 
00630 void viewOwnReplay( Player& player )
00631 {
00632    if ( player.stat == Player::human || player.stat == Player::supervisor )
00633       if ( CGameOptions::Instance()->debugReplay && player.getParentMap()->replayinfo )
00634          if (choice_dlg("run replay of your turn ?","~y~es","~n~o") == 1) {
00635             // cursor.gotoxy( actmap->cursorpos.position[oldplayer].cx, actmap->cursorpos.position[oldplayer].cy );
00636             runSpecificReplay ( player.getPosition(), player.getPosition(), false );
00637          }
00638 }
00639 
00640 
00641 void checkforreplay ( void )
00642 {
00643    if ( !actmap->replayinfo )
00644       return;
00645 
00646    int rpnum  = 0;
00647    int s = actmap->actplayer + 1;
00648    if ( s >= 8 )
00649        s = 0;
00650    while ( s != actmap->actplayer ) {
00651        if ( actmap->replayinfo->map[s] && actmap->replayinfo->guidata[s] )
00652           rpnum++;
00653 
00654        if ( s < 7 )
00655           s++;
00656        else
00657           s = 0;
00658    }
00659 
00660 
00661    if ( actmap->replayinfo  &&  rpnum  &&  (actmap->player[ actmap->actplayer ].stat == Player::human || actmap->player[ actmap->actplayer ].stat == Player::supervisor) )
00662       if (choice_dlg("run replay of last turn ?","~y~es","~n~o") == 1) {
00663       
00664          MainScreenWidget::StandardActionLocker locker( mainScreenWidget, MainScreenWidget::LockOptions::Menu );
00665          ReplayGuiIconHandleHandler guiIconHandler;
00666          
00667          int s = actmap->actplayer + 1;
00668          if ( s >= 8 )
00669             s = 0;
00670          while ( s != actmap->actplayer ) {
00671             if ( s >= 8 )
00672                s = 0;
00673 
00674              runSpecificReplay(s, actmap->actplayer );
00675 
00676              if ( s < 7 )
00677                  s++;
00678               else
00679                  s = 0;
00680           }
00681 
00682 
00683       }
00684 }
00685 
00686 
00687 void initReplayLogging( Player& player )
00688 {
00689    GameMap* gamemap = player.getParentMap();
00690    
00691    if ( startreplaylate ) {
00692       gamemap->replayinfo = new GameMap::ReplayInfo;
00693       startreplaylate = 0;
00694    }
00695 
00696    if ( gamemap->replayinfo && player.stat != Player::off ) {
00697       if ( gamemap->replayinfo->actmemstream )
00698          fatalError( "actmemstream already open at begin of turn " );
00699 
00700       if ( gamemap->replayinfo->guidata[ player.getPosition() ] ) {
00701          delete gamemap->replayinfo->guidata[ player.getPosition() ];
00702          gamemap->replayinfo->guidata[ player.getPosition() ] = NULL;
00703       }
00704 
00705       savereplay ( gamemap, player.getPosition() );
00706 
00707       gamemap->replayinfo->guidata[ player.getPosition() ] = new MemoryStreamStorage;
00708       gamemap->replayinfo->actmemstream = new MemoryStream ( gamemap->replayinfo->guidata[ player.getPosition() ], tnstream::writing );
00709    }
00710 }
00711 
00712 
00713 LockReplayRecording::LockReplayRecording( GameMap::ReplayInfo& _ri )
00714                     : ri ( _ri )
00715 {
00716    ri.stopRecordingActions++;
00717 }
00718 
00719 LockReplayRecording::~LockReplayRecording()
00720 {
00721    ri.stopRecordingActions--;
00722 }
00723 
00724 
00725 Resources getUnitResourceCargo ( Vehicle* veh )
00726 {
00727    Resources res = veh->getTank();
00728    for ( ContainerBase::Cargo::const_iterator i = veh->getCargo().begin(); i != veh->getCargo().end(); ++i )
00729       if ( *i )
00730          res += getUnitResourceCargo ( *i );
00731    return res;
00732 }
00733 
00734 class LogActionIntoReplayInfo  {
00735       GameMap* gamemap;
00736    public:
00737       LogActionIntoReplayInfo( GameMap* map ) : gamemap( map ) {
00738 
00739       };
00740 
00741       void saveCommand( const Command& cmd )
00742       {
00743          if ( gamemap->replayinfo && gamemap->replayinfo->actmemstream && !gamemap->replayinfo->stopRecordingActions) {
00744             tnstream* stream = gamemap->replayinfo->actmemstream;
00745          
00746             stream->writeChar( rpl_runCommandAction );
00747             
00748             MemoryStreamStorage buff;
00749             {
00750                MemoryStream stream2( &buff, tnstream::writing );
00751                cmd.write( stream2 );
00752             }
00753             
00754             // size is counted in 4 Byte chunks, so we need padding bytes
00755             int size = (buff.getSize()+3)/4;
00756             stream->writeInt( size + 1 );
00757             
00758             int padding = size*4 - buff.getSize();
00759             stream->writeInt( padding );
00760             
00761             buff.writetostream( stream );
00762             for ( int i = 0; i < padding;++i )
00763                stream->writeChar( 255-i );
00764          }
00765       }
00766 };
00767 
00768 static void logActionToReplay( GameMap* map, Command& command)
00769 {
00770    LogActionIntoReplayInfo lairi( map );
00771    lairi.saveCommand( command );
00772 }
00773 
00774 
00775 Context trunreplay::createReplayContext()
00776 {
00777    Context context;
00778    
00779    context.gamemap = actmap;
00780    context.actingPlayer = &actmap->getPlayer( actmap->actplayer );
00781    context.parentAction = NULL;
00782    
00783    if ( !replayMapDisplay ) 
00784       replayMapDisplay = new ReplayMapDisplay( &getDefaultMapDisplay() );
00785    
00786    context.display = replayMapDisplay;
00787    context.viewingPlayer = actmap->getPlayerView(); 
00788    context.actionContainer = &actmap->actions;
00789    return context;   
00790 }
00791 
00792 
00793 
00794 
00795 trunreplay :: trunreplay ()  
00796 {
00797    replayMapDisplay = NULL;
00798    status = -1;
00799    movenum = 0;
00800 }
00801 
00802 trunreplay :: ~trunreplay()
00803 {
00804    delete replayMapDisplay;  
00805 }
00806 
00807 void trunreplay::error( const ActionResult& res )
00808 {
00809    error( ASCString(getmessage(res.getCode() )) + res.getMessage() );
00810 }
00811 
00812 void trunreplay::error( const MapCoordinate& pos, const ASCString& message )
00813 {
00814    error( message );
00815 }
00816 
00817 
00818 void trunreplay::error( const MapCoordinate& pos, const char* message, ... )
00819 {
00820    if ( CGameOptions::Instance()->replayMovieMode )
00821       return;
00822    
00823    va_list paramlist;
00824    va_start ( paramlist, message );
00825    char tempbuf[1000];
00826    int lng = vsprintf( tempbuf, message, paramlist );
00827 
00828    assert(lng < 1000);
00829    error( tempbuf );
00830    // error( message + "\nPosition: " + pos.toString() );
00831 }
00832 
00833 void trunreplay::error( const char* message, ... )
00834 {
00835    if ( CGameOptions::Instance()->replayMovieMode )
00836       return;
00837    
00838    if ( message != lastErrorMessage ) {
00839       va_list paramlist;
00840       va_start ( paramlist, message );
00841 
00842       char tempbuf[1000];
00843 
00844       int lng = vsprintf( tempbuf, message, paramlist );
00845       if ( lng >= 1000 )
00846          displaymessage ( "trunreplay::error: String to long !\nPlease report this error", 1 );
00847 
00848       va_end ( paramlist );
00849       
00850       displaymessage(tempbuf, 1 );
00851       lastErrorMessage = message;
00852    }
00853 }
00854 
00855 void trunreplay::error( const ASCString& message )
00856 {
00857    if ( CGameOptions::Instance()->replayMovieMode )
00858       return;
00859 
00860    if ( message != lastErrorMessage ) {
00861       displaymessage(message.c_str(), 1 );
00862       lastErrorMessage = message;
00863    }
00864 }
00865 
00866 
00867 
00868 
00869 void trunreplay :: wait ( int t )
00870 {
00871 //   if ( fieldvisiblenow ( getactfield(), actmap->playerView ))
00872     while ( ticker < t + CGameOptions::Instance()->replayspeed  && !keypress()) {
00873        /*
00874        tkey input;
00875        while (keypress ()) {
00876            input = r_key ( );
00877            if ( input == ct_'+' )
00878        }
00879        */
00880        releasetimeslice();
00881     }
00882 }
00883 
00884 void trunreplay :: wait ( MapCoordinate pos, int t )
00885 {
00886    if ( fieldvisiblenow ( actmap->getField ( pos ), actmap->getPlayerView() ))
00887       wait();
00888 }
00889 
00890 void trunreplay :: wait ( MapCoordinate pos1, MapCoordinate pos2, int t )
00891 {
00892    if ( fieldvisiblenow ( actmap->getField ( pos1 ), actmap->getPlayerView() ) || fieldvisiblenow ( actmap->getField ( pos2 ), actmap->getPlayerView() ))
00893       wait();
00894 }
00895 
00896 
00897 /*
00898 void trunreplay :: setcursorpos ( int x, int y )
00899 {
00900    int i = fieldvisiblenow ( getfield ( x, y ), actmap->playerview );
00901    cursor.gotoxy ( x, y, i );
00902    if( i ) {
00903       lastvisiblecursorpos.x = x;
00904       lastvisiblecursorpos.y = y;
00905    }
00906 }
00907 */
00908 
00909 
00910 void trunreplay :: displayActionCursor ( int x1, int y1, int x2, int y2, int secondWait )
00911 {
00912     ReplayMapDisplay rmd( &getDefaultMapDisplay() );
00913     rmd.setCursorDelay ( CGameOptions::Instance()->replayspeed );
00914     rmd.displayActionCursor ( x1, y1, x2, y2, secondWait );
00915 }
00916 
00917 void trunreplay :: removeActionCursor ( void )
00918 {
00919     ReplayMapDisplay rmd( &getDefaultMapDisplay() );
00920     rmd.removeActionCursor (  );
00921 }
00922 
00923 
00924 void trunreplay :: execnextreplaymove ( void )
00925 {
00926    
00927    static int lastTicker = ticker;
00928    
00929    if ( lastTicker + 10 < ticker ) {
00930       displayLogMessage( 8, "executing replay move %d\n", movenum );
00931       lastTicker = ticker;
00932    }
00933 
00934    if ( !replayRecorder || !replayRecorder->isRunning())
00935       displaymessage2("executing replay move %d\n", movenum );
00936    
00937    movenum++;
00938    int actaction = nextaction;
00939    if ( nextaction != rpl_finished ) {
00940       switch ( nextaction ) {
00941       case rpl_move: {
00942                         stream->readInt(); // size
00943                         int x1 = stream->readInt();
00944                         int y1 = stream->readInt();
00945                         int x2 = stream->readInt();
00946                         int y2 = stream->readInt();
00947                         int nwid = stream->readInt();
00948                         readnextaction();
00949 
00950                         Vehicle* eht = actmap->getUnit ( x1, y1, nwid );
00951                         if ( eht ) {
00952                            ReplayMapDisplay rmd ( &getDefaultMapDisplay() );
00953                            
00954                            
00955                            auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( eht ));
00956                            muc->setDestination( MapCoordinate(x2,y2) );
00957 
00958                            int t = ticker;
00959                            wait( MapCoordinate(x1,y1), MapCoordinate(x2,y2), t );
00960                            
00961                            ActionResult res = muc->execute( createReplayContext() );
00962                            if ( res.successful() )
00963                               muc.release();
00964                            else
00965                               error("severe replay inconsistency:\nerror for move1 command at " + MapCoordinate(x1,y1).toString() );
00966                         }
00967 
00968                         if ( !eht )
00969                            error("severe replay inconsistency:\nno vehicle for move1 command at " + MapCoordinate(x1,y1).toString() );
00970                      }
00971          break;
00972       case rpl_move5:
00973       case rpl_move4:
00974       case rpl_move3:
00975       case rpl_move2: {
00976                         stream->readInt(); // size
00977                         int x1 = stream->readInt();
00978                         int y1  = stream->readInt();
00979                         int x2 = stream->readInt();
00980                         int y2 = stream->readInt();
00981                         int nwid = stream->readInt();
00982                         int height = stream->readInt();
00983                         int noInterrupt;
00984                         if ( nextaction == rpl_move3 || nextaction == rpl_move4 || nextaction == rpl_move5 )
00985                            noInterrupt = stream->readInt();
00986                         else
00987                            noInterrupt = -1;
00988 
00989                         int destDamage;
00990                         if ( nextaction == rpl_move5 )
00991                            destDamage = stream->readInt();
00992                         else
00993                            destDamage = -1;
00994 
00995                         readnextaction();
00996 
00997                         Vehicle* eht = actmap->getUnit ( x1, y1, nwid );
00998                         if ( eht ) {
00999                            auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( eht ));
01000                            
01001                            int t = ticker;
01002                            wait( MapCoordinate(x1,y1), MapCoordinate(x2,y2), t );
01003                            
01004                            MapCoordinate3D dest ( x2,y2, 0 );
01005                            dest.setNumericalHeight(height);
01006                            muc->setDestination( dest );
01007                            
01008                            ActionResult res = muc->execute( createReplayContext());
01009                            if ( res.successful() )
01010                               muc.release();
01011                            else {
01012                               if ( CGameOptions::Instance()->replayMovieMode ) {
01013 
01014                                  MapField* fld = eht->getMap()->getField(x1,y1);
01015                                  if ( fld->vehicle == eht ) {
01016                                     fld->vehicle = NULL;
01017                                  } else {
01018                                     if ( fld->getContainer() )
01019                                        fld->getContainer()->removeUnitFromCargo( eht, true );
01020                                  }
01021 
01022                                  if ( eht->isViewing() )
01023                                     eht->removeview();
01024 
01025                                  
01026                                  eht->setnewposition(x2,y2);
01027                                  if ( height >= 0 )
01028                                     eht->height = 1 << height;
01029 
01030                                  MapField* fld2 = eht->getMap()->getField(x2,y2);
01031                                  if ( !fld2->getContainer() ) {
01032                                     fld2->vehicle = eht;
01033                                     eht->addview();
01034                                  } else
01035                                     fld2->getContainer()->addToCargo( eht );
01036                               }
01037                               eht = NULL;
01038 
01039                            }
01040 
01041                            if ( destDamage >= 0 ) {
01042                               int realDamage;
01043                               Vehicle* veh = actmap->getUnit( nwid );
01044                               if ( veh )
01045                                  realDamage = veh->damage;
01046                               else
01047                                  realDamage = 100;
01048 
01049                               if ( destDamage != realDamage )
01050                                  error( MapCoordinate(x1,y1), "severe replay inconsistency:\ndamage after movement differs: recorded=%d, actual=%d", destDamage, realDamage );
01051                            }
01052                         }
01053 
01054                         if ( !eht )
01055                            error("severe replay inconsistency:\nno vehicle for move2 command at " + MapCoordinate(x1,y1).toString() );
01056                      }
01057          break;
01058       case rpl_attack: {
01059                            stream->readInt();  // size
01060                            int x1 = stream->readInt();
01061                            int y1 = stream->readInt();
01062                            int x2 = stream->readInt();
01063                            int y2 = stream->readInt();
01064                            int ad1 = stream->readInt();
01065                            int ad2 = stream->readInt();
01066                            int dd1 = stream->readInt();
01067                            int dd2 = stream->readInt();
01068                            int wpnum = stream->readInt();
01069                            readnextaction();
01070 
01071                            MapField* fld = getfield ( x1, y1 );
01072                            MapField* targ = getfield ( x2, y2 );
01073                            int attackvisible = fieldvisiblenow ( fld, actmap->getPlayerView() ) || fieldvisiblenow ( targ, actmap->getPlayerView() );
01074                            if ( fld && targ && fld->vehicle ) {
01075                               if ( fieldvisiblenow ( targ, fld->vehicle->getOwner() )) {
01076                                  if ( targ->vehicle ) {
01077                                     tunitattacksunit battle ( fld->vehicle, targ->vehicle, 1, wpnum );
01078                                     battle.av.damage = ad1;
01079                                     battle.dv.damage = dd1;
01080                                     if ( attackvisible ) {
01081                                        displayActionCursor ( x1, y1, x2, y2, 0 );
01082                                        ReplayMapDisplay rmd( &getDefaultMapDisplay() );
01083                                        rmd.showBattle( battle );
01084                                        removeActionCursor();
01085                                     } else {
01086                                        battle.calc ();
01087                                     }
01088                                     if ( battle.av.damage < ad2 || battle.dv.damage > dd2 )
01089                                        error(MapCoordinate(x2,y2), "severe replay inconsistency:\nresult of attack differ !\nexpected target damage: %d ; recorded target damage: %d\nexpected attacker damage: %d ; recorded attacker damage: %d", battle.av.damage,ad2 ,battle.dv.damage, dd2);
01090                                     battle.setresult( createReplayContext() );
01091 
01092                                     if ( battle.av.damage >= 100 || battle.dv.damage >= 100 )
01093                                        computeview( actmap );
01094 
01095                                     updateFieldInfo();
01096 
01097                                  } else
01098                                  if ( targ->building ) {
01099                                     tunitattacksbuilding battle ( fld->vehicle, x2, y2 , wpnum );
01100                                     battle.av.damage = ad1;
01101                                     battle.dv.damage = dd1;
01102                                     if ( attackvisible ) {
01103                                        displayActionCursor ( x1, y1, x2, y2, 0 );
01104                                        ReplayMapDisplay rmd( &getDefaultMapDisplay() );
01105                                        rmd.showBattle( battle );
01106                                        removeActionCursor();
01107                                     } else {
01108                                        battle.calc ();
01109                                        /*battle.av.damage = ad2;
01110                                        battle.dv.damage = dd2; */
01111                                     }
01112                                     if ( battle.av.damage != ad2 || battle.dv.damage != dd2 )
01113                                        error(MapCoordinate(x2,y2), "severe replay inconsistency:\nresult of attack differ !\nexpected target damage: %d ; recorded target damage: %d\nexpected attacker damage: %d ; recorded attacker damage: %d", battle.av.damage,ad2 ,battle.dv.damage, dd2);
01114                                     battle.setresult( createReplayContext() );
01115 
01116                                     if ( battle.av.damage >= 100 || battle.dv.damage >= 100 )
01117                                        computeview( actmap );
01118                                     updateFieldInfo();
01119                                  } else
01120                                  if ( !targ->objects.empty() ) {
01121                                     tunitattacksobject battle ( fld->vehicle, x2, y2, wpnum );
01122                                     if ( attackvisible ) {
01123                                        displayActionCursor ( x1, y1, x2, y2, 0 );
01124                                        ReplayMapDisplay rmd( &getDefaultMapDisplay() );
01125                                        rmd.showBattle( battle );
01126                                        removeActionCursor();
01127                                     } else {
01128                                        battle.calc ();
01129                                        //battle.av.damage = ad2;
01130                                        //battle.dv.damage = dd2;
01131                                     }
01132                                     if ( battle.av.damage != ad2 || battle.dv.damage != dd2 )
01133                                        error(MapCoordinate(x2,y2), "severe replay inconsistency:\nresult of attack differ !\nexpected target damage: %d ; recorded target damage: %d\nexpected attacker damage: %d ; recorded attacker damage: %d", battle.av.damage,ad2 ,battle.dv.damage, dd2);
01134                                     battle.setresult( createReplayContext() );
01135 
01136                                     if ( battle.av.damage >= 100 || battle.dv.damage >= 100 )
01137                                        computeview( actmap );
01138 
01139                                     updateFieldInfo();
01140                                  }
01141                                  displaymap();
01142                              } else
01143                                 error(MapCoordinate(x2,y2), "severe replay inconsistency:\nthe attacking unit can't view the target field!" );
01144 
01145                            } else
01146                               error(MapCoordinate(x1,y1), "severe replay inconsistency:\nno vehicle for attack command !" );
01147 
01148                       }
01149          break;
01150       case rpl_changeheight2:
01151       case rpl_changeheight: {
01152                         stream->readInt();  // size
01153                         int x1 = stream->readInt();
01154                         int y1 = stream->readInt();
01155                         int x2 = stream->readInt();
01156                         int y2 = stream->readInt();
01157                         int nwid = stream->readInt();
01158                         stream->readInt(); // oldheight
01159                         int newheight = stream->readInt();
01160                         int noInterrupt = -1;
01161 
01162                         if ( nextaction == rpl_changeheight2 )
01163                            noInterrupt = stream->readInt();
01164 
01165 
01166                         readnextaction();
01167 
01168                         Vehicle* eht = actmap->getUnit ( x1, y1, nwid );
01169                         if ( eht ) {
01170                            ReplayMapDisplay rmd( &getDefaultMapDisplay() );
01171                            
01172                            auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( eht ));
01173                            muc->setDestination( MapCoordinate3D( x2,y2, newheight ));
01174                            
01175                            wait( MapCoordinate(x1,y1), MapCoordinate(x2,y2) );
01176                            
01177                            ActionResult res = muc->execute( createReplayContext() );
01178                            
01179                            if ( res.successful() )
01180                               muc.release();
01181                            else
01182                               eht = NULL;
01183                            
01184                         }
01185 
01186                         if ( !eht )
01187                            error(MapCoordinate(x1,y1), "severe replay inconsistency:\nno vehicle for changeheight command !");
01188 
01189 
01190                      }
01191          break;
01192       case rpl_convert: 
01193       case rpl_convert2: {
01194                            stream->readInt();  // size
01195                            int x = stream->readInt();
01196                            int y = stream->readInt();
01197                            int col = stream->readInt();
01198                            if ( nextaction == rpl_convert2 ) {
01199                               int nwid = stream->readInt();
01200                               readnextaction();
01201 
01202                               Vehicle* veh = actmap->getUnit( x,y, nwid );
01203                               if ( veh ) 
01204                                  veh->convert(col);
01205                               else
01206                                  error(MapCoordinate(x,y), "severe replay inconsistency:\nno vehicle for convert command !");
01207                            } else {
01208                               readnextaction();
01209 
01210                               MapField* fld = getfield ( x, y );
01211                               if ( fld ) {
01212                                  displayActionCursor ( x, y );
01213                                  if ( fld->vehicle )
01214                                     fld->vehicle->convert ( col );
01215                                  else
01216                                     if ( fld->building )
01217                                        fld->building->convert ( col );
01218 
01219                                  computeview( actmap );
01220                                  displaymap();
01221                                  wait( MapCoordinate(x,y) );
01222                                  removeActionCursor();
01223                               } else
01224                                  error(MapCoordinate(x,y), "severe replay inconsistency:\nno vehicle for convert command !");
01225                            }
01226                        }
01227          break;
01228       case rpl_remobj:
01229       case rpl_buildobj: 
01230       case rpl_remobj2:
01231       case rpl_buildobj2: {
01232                            stream->readInt();  // size
01233                            int x = stream->readInt();
01234                            int y = stream->readInt();
01235                            int id = stream->readInt();
01236                            int unit = -1;
01237                            if ( actaction == rpl_remobj2 || actaction == rpl_buildobj2 )
01238                               unit = stream->readInt();
01239 
01240                            readnextaction();
01241 
01242                            ObjectType* obj = objectTypeRepository.getObject_byID ( id );
01243 
01244                            MapField* fld = getfield ( x, y );
01245                            if ( obj && fld ) {
01246                               displayActionCursor ( x, y );
01247 
01248                               Resources cost;
01249                               int movecost;
01250 
01251                               RecalculateAreaView rav ( actmap, MapCoordinate(x,y), maxViewRange / maxmalq + 1, NULL );
01252                               
01253                               bool objectAffectsVisibility = obj->basicjamming_plus || obj->viewbonus_plus || obj->viewbonus_abs != -1 || obj->basicjamming_abs != -1;
01254                               if ( objectAffectsVisibility )
01255                                  rav.removeView();
01256 
01257 
01258                               if ( actaction == rpl_remobj || actaction == rpl_remobj2 ) {
01259                                  cost = obj->removecost;
01260                                  fld->removeObject ( obj );
01261                                  movecost = obj->remove_movecost;
01262                               } else {
01263                                  cost = obj->buildcost;
01264                                  fld->addobject ( obj );
01265                                  movecost = obj->build_movecost;
01266                               }
01267 
01268                               if ( objectAffectsVisibility )
01269                                  rav.addView();
01270 
01271 
01272                               if ( unit > 0 ) {
01273                                  Vehicle* veh = actmap->getUnit(unit);
01274                                  if ( veh ) {
01275                                     if ( veh->getMovement() < movecost )
01276                                        error(MapCoordinate(x,y), "not enough movement to construct/remove object !");
01277                                     veh->decreaseMovement( movecost );
01278                                     Resources res2 =  static_cast<ContainerBase*>(veh)->getResource( cost, 0, 1  );
01279                                     for ( int r = 0; r < 3; r++ )
01280                                        if ( res2.resource(r) < cost.resource(r)  && cost.resource(r) > 0 )
01281                                           error("Resource mismatch: not enough resources to construct/remove object !\nPosition: " + MapCoordinate(x,y).toString());
01282 
01283                                  } else
01284                                     error(MapCoordinate(x,y), "replay inconsistency:\nCannot find Unit to build/remove Object !");
01285                               }
01286 
01287                               if ( fieldvisiblenow ( fld, actmap->getPlayerView() ))
01288                                  displaymap();
01289                               
01290                               wait(MapCoordinate(x,y));
01291                               removeActionCursor();
01292                            } else
01293                               error(MapCoordinate(x,y), "severe replay inconsistency:\nCannot find Object to build/remove !");
01294 
01295                        }
01296          break;
01297       case rpl_buildtnk:
01298       case rpl_buildtnk2:
01299       case rpl_buildtnk3:
01300       case rpl_buildtnk4: {
01301                            stream->readInt();  // size
01302                            int x = stream->readInt();
01303                            int y = stream->readInt();
01304                            int id = stream->readInt();
01305                            int col = stream->readInt();
01306                            int nwid = -1;
01307                            int constx = -1;
01308                            int consty = -1;
01309                            int height = -1;
01310                            if ( nextaction == rpl_buildtnk2 )
01311                               nwid = stream->readInt();
01312 
01313                            if ( nextaction == rpl_buildtnk3 || nextaction == rpl_buildtnk4 ) {
01314                               constx = stream->readInt();
01315                               consty = stream->readInt();
01316                               if ( nextaction == rpl_buildtnk4 )
01317                                  height = stream->readInt();
01318                            }
01319 
01320                            readnextaction();
01321 
01322                            MapField* fld = getfield ( x, y );
01323 
01324                            VehicleType* tnk = vehicleTypeRepository.getObject_byID ( id );
01325 
01326                            if ( fld && tnk && !fld->vehicle ) {
01327                               displayActionCursor ( x, y );
01328                               Vehicle* v = new Vehicle ( tnk, actmap, col );
01329                               v->xpos = x;
01330                               v->ypos = y;
01331                               fld->vehicle = v;
01332                               if ( height >= 0 )
01333                                  v->height = height;
01334 
01335                               if ( constx >= 0 && consty >= 0 ) {
01336                                  MapField* constructorField = getfield(constx, consty );
01337                                  if ( constructorField->vehicle ) {
01338                                     Resources r ( 0, tnk->productionCost.material, tnk->productionCost.energy ); //  = constructorField->vehicle->getProductionCost(tnk );
01339                                     Resources rr = constructorField->getContainer()->getResource( r, 0 );
01340                                     if ( rr < r ) {
01341                                        displayActionCursor ( x, y );
01342                                        error(MapCoordinate(x,y), "severe replay inconsistency: \nNot enough resources to produce unit %s !\nRequired: %d/%d/%d ; Available: %d/%d/%d", v->typ->description.c_str(), r.energy, r.material, r.fuel, rr.energy, rr.material, rr.fuel);
01343                                     }
01344                                  } else
01345                                     error(MapCoordinate(x,y), "severe replay inconsistency: could not find constructor !");
01346 
01347                               }
01348 
01349                               computeview( actmap );
01350                               displaymap();
01351                               wait(MapCoordinate(x,y) );
01352                               removeActionCursor();
01353                            } else
01354                               error(MapCoordinate(x,y), "severe replay inconsistency:\nCannot find Vehicle to build !");
01355 
01356                        }
01357          break;
01358       case rpl_putbuilding2:
01359       case rpl_putbuilding : {
01360                                int size = stream->readInt();  // size
01361                                int x = stream->readInt();
01362                                int y = stream->readInt();
01363                                int id = stream->readInt();
01364                                stream->readInt(); // color ; we are using the vehicle's color
01365                                int networkid = 0;
01366                                if ( size == 5 )
01367                                    networkid = stream->readInt();
01368 
01369                                readnextaction();
01370 
01371                                MapField* fld = getfield ( x, y );
01372 
01373                                BuildingType* bld = buildingTypeRepository.getObject_byID ( id );
01374 
01375                                if ( bld && fld && networkid && actmap->getUnit( networkid ) ) {
01376                                   displayActionCursor ( x, y );
01377                                   auto_ptr<ConstructBuildingCommand> cbc ( new ConstructBuildingCommand( actmap->getUnit( networkid ) ));
01378                                   cbc->setBuildingType( bld );
01379                                   cbc->setTargetPosition( MapCoordinate(x,y));
01380                                   ActionResult res = cbc->execute( createReplayContext());
01381                                   if ( res.successful() )
01382                                      cbc.release();
01383                                   else
01384                                      error( MapCoordinate(x,y), "severe replay inconsistency, could not construct building; Code=" + ASCString::toString( res.getCode() ));
01385                                   
01386                                   wait(MapCoordinate(x,y));
01387                                   removeActionCursor();
01388                                } else
01389                                   error(MapCoordinate(x,y), "severe replay inconsistency:\nCannot find building to build/remove building!" );
01390                             }
01391          break;
01392       case rpl_putmine:
01393       case rpl_putmine2: {
01394                            stream->readInt();  // size
01395                            int x = stream->readInt();
01396                            int y = stream->readInt();
01397                            int col = stream->readInt();
01398                            int typ = stream->readInt();
01399                            int strength = stream->readInt();
01400                            int nwid = -1;
01401                            if ( nextaction == rpl_putmine2) 
01402                               nwid = stream->readInt();
01403 
01404                            readnextaction();
01405 
01406                            MapField* fld = getfield ( x, y );
01407                            if ( fld ) {
01408                               displayActionCursor ( x, y );
01409                               fld -> putmine ( col, MineTypes(typ), strength );
01410                               if ( nwid >= 0 ) {
01411                                  Vehicle* veh = actmap->getUnit( nwid );
01412                                  if ( veh ) {
01413                                     ConsumeAmmo ca ( veh, cwminen, -1, 1 );
01414                                     ActionResult res = ca.execute( createReplayContext());
01415                                     if ( !res.successful() )
01416                                        error(MapCoordinate(x,y), "could not obtain ammo for mine placement");
01417 
01418                                  } else 
01419                                     error(MapCoordinate(x,y), "could not find unit for mine placement");
01420                               }
01421                               computeview( actmap );
01422                               if ( fieldvisiblenow ( actmap->getField(x,y), actmap->getPlayerView() )) {
01423                                  displaymap();
01424                                  wait();
01425                               }
01426                               removeActionCursor();
01427                            } else
01428                               error(MapCoordinate(x,y), "severe replay inconsistency:\nno field for putmine command !");
01429 
01430                        }
01431          break;
01432       case rpl_removemine: {
01433                            stream->readInt();  // size
01434                            int x = stream->readInt();
01435                            int y = stream->readInt();
01436                            readnextaction();
01437 
01438                            MapField* fld = getfield ( x, y );
01439                            if ( fld ) {
01440                               displayActionCursor ( x, y );
01441                               fld -> removemine ( -1 );
01442                               computeview( actmap );
01443                               if ( fieldvisiblenow ( actmap->getField(x,y), actmap->getPlayerView() )) {
01444                                  displaymap();
01445                                  wait();
01446                               }
01447                               removeActionCursor ( );
01448                            } else
01449                               error(MapCoordinate(x,y), "severe replay inconsistency:\nno field for remove mine command !");
01450 
01451                        }
01452          break;
01453       case rpl_removebuilding2:
01454       case rpl_removebuilding3:
01455       case rpl_removebuilding: {
01456                            stream->readInt();  // size
01457                            int x = stream->readInt();
01458                            int y = stream->readInt();
01459                            int nwid = -1;
01460                            if ( nextaction == rpl_removebuilding2 || nextaction == rpl_removebuilding3 )
01461                               nwid = stream->readInt();
01462 
01463                            Resources res;
01464                            if ( nextaction == rpl_removebuilding3 ) {
01465                               res.energy = stream->readInt();
01466                               res.material = stream->readInt();
01467                               res.fuel = stream->readInt();
01468                            }
01469 
01470                            readnextaction();
01471 
01472                            MapField* fld = getfield ( x, y );
01473                            if ( fld && fld->building ) {
01474                               displayActionCursor ( x, y );
01475                               if ( nwid >= 0 ) {
01476                                  Vehicle* veh = actmap->getUnit( nwid );
01477                                  if ( veh ) {
01478                                     DestructBuildingCommand* dbc = new DestructBuildingCommand( veh );
01479                                     dbc->setTargetPosition( MapCoordinate( x,y ));
01480                                     dbc->execute( createReplayContext());
01481                                     
01482                                  } else
01483                                    error(MapCoordinate(x,y), "severe replay inconsistency:\nfailed to obtain vehicle for removebuilding command !");
01484                               } else
01485                                  error(MapCoordinate(x,y), "no vehicle for removebuilding command !");
01486 
01487                               computeview( actmap );
01488                               displaymap();
01489                               wait();
01490                               removeActionCursor();
01491                            } else
01492                               error(MapCoordinate(x,y), "severe replay inconsistency:\nno building for removebuilding command !");
01493 
01494                        }
01495          break;
01496       case  rpl_produceunit : {
01497                                  stream->readInt();  // size
01498                                  int id = stream->readInt();
01499                                  int col = stream->readInt();
01500                                  int x = stream->readInt();
01501                                  int y = stream->readInt();
01502                                  stream->readInt(); // class
01503                                  int nwid = stream->readInt();
01504                                  readnextaction();
01505 
01506                                  MapField* fld = getfield ( x, y );
01507 
01508                                  VehicleType* tnk = vehicleTypeRepository.getObject_byID ( id );
01509                                  if ( tnk && fld) {
01510                                  
01511                                     #if 0
01512                                     printf("produced unit: pos %d / %d; nwid %d; typ id %d; typ %s \n", x,y,nwid,id,tnk->description.c_str() );
01513                                     #endif
01514 
01515                                     Vehicle* eht = new Vehicle ( tnk, actmap, col / 8 );
01516                                     eht->xpos = x;
01517                                     eht->ypos = y;
01518                                     eht->networkid = nwid;
01519 
01520                                     if ( fld->building ) {
01521                                        Resources cost  = fld->building->getProductionCost(tnk);
01522                                        Resources r = fld->building->getResource( cost, 0 );
01523                                        if ( r < cost ) {
01524                                           displayActionCursor ( x, y );
01525                                           error(MapCoordinate(x,y), "severe replay inconsistency: \nNot enough resources to produce unit %s !\nRequired: %d/%d/%d ; Available: %d/%d/%d", eht->typ->description.c_str(), cost.energy, cost.material, cost.fuel, r.energy, r.material, r.fuel);
01526                                        }
01527                                        fld->building->addToCargo( eht );
01528                                     } else {
01529                                        displayActionCursor ( x, y );
01530                                        fld->vehicle = eht;
01531                                        computeview( actmap );
01532                                        displaymap();
01533                                        wait( MapCoordinate(x,y) );
01534                                        removeActionCursor();
01535                                     }
01536                                  } else
01537                                     error(MapCoordinate(x,y), "severe replay inconsistency:\nCannot find vehicle to build/remove !");
01538 
01539                               }
01540          break;
01541       case rpl_removeunit : {
01542                                  stream->readInt();  // size
01543                                  int x = stream->readInt();
01544                                  int y = stream->readInt();
01545                                  int nwid = stream->readInt();
01546                                  readnextaction();
01547                                  MapField* fld = getfield(x,y);
01548                                  if ( (!fld->vehicle || fld->vehicle->networkid != nwid) && fld->building ) {
01549                                     auto_ptr<RecycleUnitCommand> ruc ( new RecycleUnitCommand( fld->building ));
01550                                     ruc->setUnit( actmap->getUnit( nwid ) );
01551                                     ActionResult res = ruc->execute( createReplayContext());
01552                                     if ( res.successful() )
01553                                        ruc.release();
01554                                     else
01555                                        displayActionError(res);
01556                                  } else
01557                                     if ( !fld->getContainer() || !fld->getContainer()->removeUnitFromCargo ( nwid, true ))
01558                                        displaymessage ( "severe replay inconsistency:\nCould not remove unit %d!", 1, nwid );
01559                               }
01560          break;
01561       case rpl_trainunit:{
01562                                  stream->readInt();  // size
01563                                  int x = stream->readInt();
01564                                  int y = stream->readInt();
01565                                  stream->readInt(); // experience
01566                                  int nwid = stream->readInt();
01567                                  readnextaction();
01568 
01569                                  Vehicle* eht = actmap->getUnit ( x, y, nwid );
01570                                  Building* bld = actmap->getField ( x, y )->building;
01571                                  if ( eht && bld ) {
01572                                     auto_ptr<TrainUnitCommand> tuc ( new TrainUnitCommand( bld ));
01573                                     tuc->setUnit( eht );
01574                                     ActionResult res = tuc->execute( createReplayContext());
01575                                     if ( res.successful())
01576                                        tuc.release();
01577                                     else
01578                                        displayActionError(res);
01579                                  } else
01580                                     error(MapCoordinate(x,y), "severe replay inconsistency:\nno vehicle for trainunit command !");
01581 
01582 
01583                               }
01584          break;
01585          /*
01586       case rpl_shareviewchange: {
01587                                  int size = stream->readInt();
01588                                  GameMap::Shareview* sv = new GameMap::Shareview;
01589                                  if ( size ) {
01590                                     for ( int a = 0; a < 8; a++ )
01591                                        for ( int b = 0; b < 8; b++)
01592                                            sv->mode[a][b] = stream->readChar();
01593                                     sv->recalculateview = stream->readInt();
01594 
01595                                     if ( actmap->shareview )
01596                                        delete actmap->shareview;
01597                                     actmap->shareview = sv;
01598                                     actmap->shareview->recalculateview = 0;
01599                                  } else
01600                                     if ( actmap->shareview ) {
01601                                        delete actmap->shareview;
01602                                        actmap->shareview = NULL;
01603                                     }
01604 
01605                                  readnextaction();
01606                                  computeview( actmap );
01607                                  displaymap();
01608                               }
01609          break;
01610          */
01611       case rpl_alliancechange2: {
01612                                  stream->readInt();  // size
01613                                  int actingPlayer = stream->readInt();
01614                                  int targetPlayer = stream->readInt();
01615                                  int state = stream->readInt();
01616                                  actmap->player[actingPlayer].diplomacy.setState( targetPlayer, DiplomaticStates( state ));
01617                                  
01618                                  readnextaction();
01619                               }
01620          break;
01621       case rpl_refuel :
01622       case rpl_refuel2 : {
01623                                  stream->readInt();  // size
01624                                  int x = stream->readInt();
01625                                  int y = stream->readInt();
01626                                  int nwid = stream->readInt();
01627                                  int pos = stream->readInt();
01628                                  int amnt = stream->readInt();
01629                                  int old = -2;
01630                                  if ( nextaction == rpl_refuel2 )
01631                                     old = stream->readInt();
01632 
01633                                  readnextaction();
01634 
01635                                  Vehicle* eht = actmap->getUnit ( x, y, nwid );
01636                                  if ( eht ) {
01637                                     if ( pos < 16 ) {
01638                                        if ( old >= 0 && old != eht->ammo[pos] )
01639                                           error(MapCoordinate(x,y), "severe replay inconsistency:\nthe ammo of unit not matching. \nrecorded: %d , expected: %d !", old, eht->ammo[pos] );
01640                                        eht->ammo[pos] = amnt;
01641                                     } else {
01642                                         int res = pos - 1000;
01643                                         int avl = eht->getTank().resource(res);
01644                                         if ( avl != old && old >= 0 )
01645                                             error(MapCoordinate(x,y), "severe replay inconsistency:\nthe resources of unit not matching. \nrecorded: %d , expected: %d !", old, avl);
01646                                         eht->getResource ( avl - amnt, res, false );
01647                                      }
01648                                  } else
01649                                     error(MapCoordinate(x,y), "severe replay inconsistency:\nno vehicle for refuel-unit command !");
01650                               }
01651          break;
01652       case rpl_refuel3 : {
01653                                  stream->readInt();  // size
01654                                  int id = stream->readInt();
01655                                  int type = stream->readInt();
01656                                  int delta = stream->readInt();
01657                                  readnextaction();
01658 
01659                                  ContainerBase* cb = actmap->getContainer ( id );
01660                                  if ( cb ) {
01661                                     if ( type >= 1000 ) {
01662                                        Resources res;
01663                                        res.resource(type-1000) = delta;
01664                                        ConsumeResource cr ( cb, res );
01665                                        ActionResult result = cr.execute( createReplayContext() );
01666                                        if ( !result.successful())
01667                                           error("severe replay inconsistency:\nthe resources of container not matching. ");
01668                                           
01669                                     } else {
01670                                        ConsumeAmmo ca ( cb, type, -1, delta );
01671                                        ActionResult result = ca.execute( createReplayContext() );
01672                                        if ( !result.successful())
01673                                           error("severe replay inconsistency:\nthe resources of container not matching. ");
01674                                     }
01675                                  } else
01676                                     error("severe replay inconsistency:\nno vehicle for refuel3 command !");
01677                               }
01678          break;
01679       case rpl_bldrefuel : {
01680                                  stream->readInt();  // size
01681                                  int x = stream->readInt();
01682                                  int y = stream->readInt();
01683                                  int pos = stream->readInt();
01684                                  int amnt = stream->readInt();
01685                                  readnextaction();
01686 
01687                                  Building* bld = actmap->getField(x,y)->building;
01688                                  if ( bld ) {
01689                                     if ( pos < 16 )
01690                                         bld->ammo[pos] = amnt;
01691                                      else
01692                                         bld->getResource ( amnt, pos-1000, 0 );
01693                                  } else
01694                                     error(MapCoordinate(x,y), "severe replay inconsistency:\nno building for refuel-unit command !");
01695                               }
01696          break;
01697          case rpl_moveUnitUpDown: {
01698             stream->readInt();  // size
01699             int x =  stream->readInt();
01700             int y =  stream->readInt();
01701             stream->readInt(); // dummy(basegfx_0)
01702             int nwid_to = stream->readInt();
01703             int nwid_moving = stream->readInt();
01704 
01705             readnextaction();
01706 
01707             ContainerBase* b = actmap->getField(x,y)->getContainer();
01708             if ( b ) {
01709                b->removeUnitFromCargo( nwid_moving, true );
01710 
01711                Vehicle* veh_targ = actmap->getUnit( nwid_to );
01712                Vehicle* veh_moving = actmap->getUnit( nwid_moving );
01713                if ( veh_targ && veh_moving )
01714                   veh_targ->addToCargo( veh_moving );
01715                else
01716                   error ( MapCoordinate(x,y), "Could not locate unit for MoveToInnerTransport");
01717             } else
01718                error( MapCoordinate(x,y), "severe replay inconsistency in MoveUnitUp !");
01719                                  
01720          }
01721          break;
01722          case rpl_moveUnitUp: {
01723                                  stream->readInt();  // size
01724                                  int x =  stream->readInt();
01725                                  int y =  stream->readInt();
01726                                  int nwid = stream->readInt();
01727 
01728                                  readnextaction();
01729 
01730                                  Vehicle* eht = actmap->getUnit ( x, y, nwid );
01731                                  if ( eht ) {
01732                                     CargoMoveCommand* cmc = new CargoMoveCommand( eht );
01733                                     cmc->setMode( CargoMoveCommand::moveOutwards );
01734                                     ActionResult res = cmc->execute( createReplayContext() );
01735                                     if ( !res.successful())
01736                                        error(MapCoordinate(x,y), "severe replay inconsistency in MoveUnitUp !");
01737                                  } else
01738                                     error(MapCoordinate(x,y), "Unit not found for MoveUnitUp !");
01739                                  
01740                               }
01741                               break;
01742       case rpl_repairUnit : {
01743                                  stream->readInt();  // size
01744                                  int nwid = stream->readInt();
01745                                  int destnwid = stream->readInt();
01746                                  int amount = stream->readInt();
01747                                  int matremain  = stream->readInt();
01748                                  int fuelremain = stream->readInt();
01749 
01750                                  readnextaction();
01751 
01752                                  Vehicle* eht = actmap->getUnit ( nwid );
01753                                  Vehicle* dest = actmap->getUnit ( destnwid );
01754                                  if ( eht && dest ) {
01755                                     eht->repairItem ( dest, amount );
01756                                     if ( eht->getTank().fuel != fuelremain || eht->getTank().material != matremain )
01757                                          error("severe replay inconsistency:\nthe resources of unit not matching for repair operation!");
01758                                  } else
01759                                     error("severe replay inconsistency:\nno vehicle for repair-unit command !");
01760                               }
01761          break;
01762       case rpl_repairUnit2 : {
01763                                  stream->readInt();  // size
01764                                  int x = stream->readInt();
01765                                  int y = stream->readInt();
01766                                  int destnwid = stream->readInt();
01767                                  int amount = stream->readInt();
01768 
01769                                  readnextaction();
01770 
01771                                  ContainerBase* bld = getfield(x,y)->getContainer();
01772                                  Vehicle* dest = actmap->getUnit ( destnwid );
01773                                  if ( bld && dest ) {
01774                                     bld->repairItem ( dest, amount );
01775                                  } else
01776                                     error(MapCoordinate(x,y), "severe replay inconsistency:\nno vehicle for repair-unit command !");
01777                               }
01778          break;
01779       case rpl_repairUnit3 : {
01780                                  stream->readInt();  // size
01781                                  int serviceNWID = stream->readInt();
01782                                  int destnwid = stream->readInt();
01783                                  int amount = stream->readInt();
01784 
01785                                  readnextaction();
01786 
01787                                  ContainerBase* bld = actmap->getContainer( serviceNWID );
01788                                  Vehicle* dest = actmap->getUnit ( destnwid );
01789                                  if ( bld && dest ) {
01790                                     bld->repairItem ( dest, amount );
01791                                  } else
01792                                     error("severe replay inconsistency:\nno vehicle for repair-unit command !");
01793                               }
01794          break;
01795       case rpl_repairBuilding : {
01796                                  stream->readInt();  // size
01797                                  int x = stream->readInt();
01798                                  int y = stream->readInt();
01799                                  stream->readInt(); // int destnwid = 
01800                                  int amount = stream->readInt();
01801 
01802                                  readnextaction();
01803 
01804                                  ContainerBase* bld = getfield(x,y)->getContainer();
01805                                  if ( bld ) {
01806                                     bld->repairItem ( bld, amount );
01807                                  } else
01808                                     error(MapCoordinate(x,y), "severe replay inconsistency:\nno building for repair-building command !");
01809                               }
01810          break;
01811       case rpl_produceAmmo : {
01812                                  stream->readInt();  // size
01813                                  int x = stream->readInt();
01814                                  int y = stream->readInt();
01815                                  int weaptype = stream->readInt();
01816                                  int n = stream->readInt();
01817                                  readnextaction();
01818                                  Building* bld = getfield(x,y)->building;
01819                                  if ( bld ) {
01820                                     
01821                                     bld->getResource ( Resources( ammoProductionCost[weaptype][0] * n, ammoProductionCost[weaptype][1] * n, ammoProductionCost[weaptype][2] * n ), false );
01822                                     bld->putAmmo ( weaptype, n, false );
01823                                     
01824                                  } else
01825                                     error(MapCoordinate(x,y), "severe replay inconsistency:\nno building for produce ammo command !");
01826 
01827                               }
01828          break;
01829       case rpl_buildProdLine : {
01830                                  stream->readInt();  // size
01831                                  int building = stream->readInt();
01832                                  int vehicleid = stream->readInt();
01833                                  readnextaction();
01834                                  Building* bld = dynamic_cast<Building*>( actmap->getContainer(building));
01835                                  VehicleType* veh = actmap->getvehicletype_byid ( vehicleid );
01836                                  if ( bld && veh ) {
01837                                     if ( veh->techDependency.available( actmap->player[ bld->getOwner()].research )) {
01838                                        auto_ptr<BuildProductionLineCommand> bplc ( new BuildProductionLineCommand( bld ));
01839                                        bplc->setProduction( veh );
01840                                        ActionResult res = bplc->execute( createReplayContext() );
01841                                        if ( res.successful() )
01842                                           bplc.release();
01843                                        else
01844                                           error("severe replay inconsistency:\ncould not build production line!");
01845                                     } else
01846                                        error("severe replay inconsistency:\ntechnology for building production line not available!");
01847 
01848                                  } else
01849                                     error("severe replay inconsistency:\nno building for build production line command !");
01850 
01851                               }
01852          break;
01853       case rpl_removeProdLine : {
01854                                  stream->readInt();  // size
01855                                  int building = stream->readInt();
01856                                  int vehicleid = stream->readInt();
01857                                  readnextaction();
01858                                  Building* bld = dynamic_cast<Building*>( actmap->getContainer(building));
01859                                  VehicleType* veh = actmap->getvehicletype_byid ( vehicleid );
01860                                  if ( bld && veh ) {
01861                                     auto_ptr<RemoveProductionLineCommand> rplc ( new RemoveProductionLineCommand( bld ));
01862                                     rplc->setRemoval( veh );
01863                                     ActionResult res = rplc->execute( createReplayContext());
01864                                     if ( res.successful()) 
01865                                        rplc.release();
01866                                     else
01867                                        error("severe replay inconsistency:\ncould not remove production line!");
01868 
01869                                  } else
01870                                     error("severe replay inconsistency:\nno building for remove production line command !");
01871 
01872                               }
01873          break;
01874       case rpl_setResearch : {
01875                                  stream->readInt();  // size
01876                                  int building = stream->readInt();
01877                                  int amount = stream->readInt();
01878                                  readnextaction();
01879                                  Building* bld = dynamic_cast<Building*>( actmap->getContainer(building));
01880                                  if ( bld )
01881                                     bld->researchpoints = amount;
01882                                  else
01883                                     error("severe replay inconsistency:\nno building for set research command !");
01884 
01885                               }
01886          break;
01887       case rpl_techResearched: {
01888                                  stream->readInt();  // size
01889                                  int techID = stream->readInt();
01890                                  int player = stream->readInt();
01891                                  readnextaction();
01892                                  Technology* tech = technologyRepository.getObject_byID( techID );
01893                                  if ( tech ) {
01894                                     actmap->player[player].research.addanytechnology( tech );
01895                                     actmap->player[player].research.progress -= tech->researchpoints;
01896                                  } else
01897                                     error("severe replay inconsistency:\nno technology for tech researched command !");
01898                                 }
01899          break;
01900       case rpl_setGeneratorStatus : {
01901                                  stream->readInt();
01902                                  int nwid = stream->readInt();
01903                                  int status = stream->readInt();
01904 
01905                                  readnextaction();
01906 
01907                                  Vehicle* eht = actmap->getUnit ( nwid );
01908                                  if ( eht )
01909                                     eht->setGeneratorStatus( status );
01910                                  else
01911                                     error("severe replay inconsistency:\nvehicle for generator switching not found !");
01912                               }
01913 
01914 
01915          break;
01916          case rpl_cutFromGame: {
01917                               stream->readInt();
01918                               int vehid = stream->readInt();
01919                               Vehicle* veh = actmap->getUnit ( vehid );
01920                               Resources res;
01921                               res.energy = stream->readInt();
01922                               res.material = stream->readInt();
01923                               res.fuel = stream->readInt();
01924 
01925                               readnextaction();
01926 
01927                               if ( veh && res == getUnitResourceCargo ( veh )) {
01928                                  veh->prepareForCleanRemove();
01929                                  delete veh;
01930                                  computeview( actmap );
01931                                  displaymap();
01932                               } else
01933                                  error ( "resource mismatch at cut unit operation! ");
01934                            }
01935          break;
01936          case rpl_setResourceProcessingAmount: {
01937                  stream->readInt();
01938                  int x = stream->readInt();
01939                  int y = stream->readInt();
01940                  Resources p;
01941                  p.energy = stream->readInt();
01942                  p.material = stream->readInt();
01943                  p.fuel = stream->readInt();
01944                  readnextaction();
01945                  Building* bld = actmap->getField(x,y)->building;
01946                  if ( bld ) {
01947                     for ( int r = 0; r< 3; ++r )
01948                        if ( abs(p.resource(r)) > abs(bld->typ->maxplus.resource(r)) )
01949                           error (MapCoordinate(x,y), "Building can not produ ");
01950                      bld->plus = p;
01951                  } else
01952                     error (MapCoordinate(x,y), "Building not found on for rpl_setResourceProcessingAmount ");
01953          }
01954          break;
01955          case rpl_netcontrol: {
01956                  stream->readInt();
01957                  int x = stream->readInt();
01958                  int y = stream->readInt();
01959                  stream->readInt(); // int cat = 
01960                  stream->readInt(); // int stat = 
01961                  readnextaction();
01962 
01963                  Building* bld = actmap->getField(x,y)->building;
01964                  if ( bld ) {
01965                     // not supported
01966                     /*
01967                     cbuildingcontrols bc;
01968                     bc.init( bld );
01969                     bc.netcontrol.setnetmode( cat, stat );
01970                     bld->execnetcontrol();
01971                     */
01972                  } else
01973                     error (MapCoordinate(x,y), "Building not found on for rpl_setResourceProcessingAmount ");
01974          }
01975          break;
01976          case rpl_jump: {
01977             stream->readInt();
01978             int nwid = stream->readInt();
01979             int x = stream->readInt();
01980             int y = stream->readInt();
01981             readnextaction();
01982 
01983             Vehicle* veh = actmap->getUnit(nwid);
01984             if ( veh ) {
01985                if ( JumpDriveCommand::available( veh ).ready()) {
01986                   auto_ptr<JumpDriveCommand> jd( new JumpDriveCommand(veh) );
01987                   displayActionCursor ( veh->getPosition().x , veh->getPosition().x, x, y, 0 );
01988                   jd->setDestination( MapCoordinate(x,y));
01989                   ActionResult res = jd->execute( createReplayContext() );
01990                   if ( !res.successful() )
01991                      error(MapCoordinate(x,y), "Unit cannot jump to this position");
01992                   else
01993                      jd.release();
01994                   
01995                } else
01996                   error(MapCoordinate(x,y), "Unit cannot jump");
01997             } else
01998                error (MapCoordinate(x,y), "Unit not found for Jump ");
01999             
02000             
02001          }
02002          break;
02003       case rpl_recycleUnit : {
02004                                  stream->readInt();  // size
02005                                  int building = stream->readInt();
02006                                  int vehicleid = stream->readInt();
02007                                  readnextaction();
02008                                  Building* bld = dynamic_cast<Building*>( actmap->getContainer(building));
02009                                  Vehicle* veh = actmap->getUnit ( vehicleid );
02010                                  if ( bld && veh ) {
02011                                     auto_ptr<RecycleUnitCommand> ruc ( new RecycleUnitCommand( bld ));
02012                                     ruc->setUnit( veh  );
02013                                     ActionResult res = ruc->execute( createReplayContext() );
02014                                     if ( res.successful() )
02015                                        ruc.release();
02016                                     else
02017                                        displayActionError(res);
02018                                  } else
02019                                     error("severe replay inconsistency:\nno unit for recycle command !");
02020                               }
02021          break;
02022       case rpl_transferTribute: {
02023          stream->readInt();
02024          int player = stream->readInt();
02025          readnextaction();
02026          transfer_all_outstanding_tribute( actmap->getPlayer( player ) );
02027                                 }
02028          break;
02029 
02030       case rpl_reactionFireOn: 
02031       case rpl_reactionFireOff: {
02032             stream->readInt();
02033             int nwid = stream->readInt();
02034             readnextaction();
02035             Vehicle* v = actmap->getUnit( nwid );
02036             if ( v ) {
02037                if ( actaction == rpl_reactionFireOn ) {
02038                   int res = v->reactionfire.enable();
02039                   if ( res < 0 )
02040                      error("severe enabling reactionfire for unit !");
02041                } else
02042                   v->reactionfire.disable();
02043             } else
02044                error("severe replay inconsistency:\nno unit for reactionfire command !");
02045          }
02046          break;
02047       case rpl_selfdestruct: {
02048              stream->readInt();
02049              int nwid = stream->readInt();
02050              readnextaction();
02051              ContainerBase* c = actmap->getContainer( nwid );
02052              if ( DestructUnitCommand::avail( c )) {
02053                 auto_ptr<DestructUnitCommand> duc ( new DestructUnitCommand( c ));
02054                 ActionResult res = duc->execute( createReplayContext() );
02055                 if ( !res.successful() )
02056                    error("severe replay inconsistency:\nno container for selfdestruct command !");
02057                 else
02058                    duc.release();
02059              } else
02060                 error("severe replay inconsistency:\nno container for selfdestruct command !");
02061             }
02062             break;
02063       case rpl_cancelResearch : 
02064             {
02065                stream->readInt();
02066                readnextaction();
02067                
02068                auto_ptr<CancelResearchCommand> crc ( new CancelResearchCommand( actmap ));
02069                crc->setPlayer( actmap->player[actmap->actplayer] );
02070                ActionResult res = crc->execute( createReplayContext() );
02071                if ( res.successful() )
02072                   crc.release();
02073                else
02074                   error( res );
02075             }
02076             break;
02077 
02078       case rpl_runCommandAction:
02079          {
02080             stream->readInt();
02081             int padding = stream->readInt();
02082             MemoryStreamStorage buffer;
02083             buffer.readfromstream( stream );
02084             
02085             MemoryStream memstream( &buffer, tnstream::reading );
02086             
02087             auto_ptr<GameAction> readaction ( GameAction::readFromStream( memstream, actmap ));
02088             
02089             Command* a = dynamic_cast<Command*> ( readaction.get() );
02090             
02091             for ( int i = 0; i < padding;++i ) {
02092                char c = stream->readChar();
02093                if ( c != 255-i )
02094                   error("invalid padding bytes in command action storage buffer");
02095             }
02096             readnextaction();
02097             
02098             if ( a ) {
02099                try {
02100                ActionResult res = a->redo( createReplayContext() );
02101                if ( !res.successful() )
02102                   error("action " + a->getDescription() + " failed\n" + getmessage(res.getCode()));
02103                } catch ( ActionResult res ) {
02104                   error("action " + a->getDescription() + " failed\n" + getmessage(res.getCode()));
02105                   throw res;
02106                }
02107 
02108             } else
02109                error("could not read Command action from replay stream" );
02110          }
02111          break;
02112                
02113       default:{
02114                  int size = stream->readInt();
02115                  for ( int i = 0; i< size; i++ )
02116                     stream->readInt();
02117 
02118                  readnextaction();
02119 
02120               }
02121         break;
02122       } /* endswitch */
02123 
02124    } else {
02125       status = 10;
02126       updateFieldInfo();
02127    }
02128 
02129 }
02130 
02131 void trunreplay :: readnextaction ( void )
02132 {
02133       if ( stream->dataavail () )
02134          nextaction = stream->readChar();
02135       else
02136          nextaction = rpl_finished;
02137 }
02138 
02139 
02140 
02141 int  trunreplay :: run ( int player, int viewingplayer, bool performEndTurnOperations )
02142 {
02143    ReplayRecorderWatcherLocal rrw( replayRecorder );
02144   
02145    if ( status < 0 )
02146       firstinit ( );
02147 
02148    lastErrorMessage = "";
02149 
02150    movenum = 0;
02151 
02152    actplayer = actmap->actplayer;
02153 
02154    orgmap = actmap;
02155    actmap = loadreplay ( orgmap->replayinfo->map[player]  );
02156    if ( !actmap ) {
02157       displaymessage("error loading replay", 1 );
02158       actmap = orgmap;
02159       return 0;
02160    }
02161    actmap->state = GameMap::Replay;
02162 
02163    actmap->setPlayerView ( viewingplayer );
02164    actmap->getCursor() = orgmap->getCursor();
02165 
02166    SuppressTechPresentation stp;
02167    actmap->sigPlayerTurnBegins( actmap->getPlayer( player ));
02168    
02169    MemoryStream guidatastream ( orgmap->replayinfo->guidata [ player ], tnstream::reading );
02170    stream = &guidatastream;
02171 
02172    if ( stream->dataavail () )
02173       nextaction = stream->readChar();
02174    else
02175       nextaction = rpl_finished;
02176 
02177 //   orgmap.replayinfo->actmemstream = stream;
02178 
02179 
02180    ReplayGuiIconHandleHandler guiIconHandler;
02181 
02182    if ( stream->dataavail () ) {
02183       if ( CGameOptions::Instance()->replayMovieMode ) 
02184          status = 2;
02185       else
02186          status = 1;
02187    } else
02188       status = 11;
02189 
02190    // force completion of overview map rendering
02191    actmap->overviewMapHolder.getOverviewMap( );
02192 
02193    computeview( actmap );
02194    displaymap ();
02195 
02196    updateFieldInfo();
02197 
02198    MainScreenWidget::StandardActionLocker locker( mainScreenWidget, MainScreenWidget::LockOptions::Menu );
02199    
02200 //   cursor.show();
02201 
02202 //   cursor.checkposition( getxpos(), getypos() );
02203 
02204    bool resourcesCompared = false;
02205    do {
02206        if ( status == 2 ) {
02207           execnextreplaymove ( );
02208           checktimedevents( actmap, &getDefaultMapDisplay() );
02209          /*
02210           if ( getxpos () != lastvisiblecursorpos.x || getypos () != lastvisiblecursorpos.y )
02211              setcursorpos ( lastvisiblecursorpos.x, lastvisiblecursorpos.y );
02212          */
02213        }  else {
02214           PG_Application::GetApp()->sigAppIdle( PG_Application::GetApp() );
02215           releasetimeslice();
02216        }
02217 
02218        if (nextaction == rpl_finished  || status != 2 ) {
02219           if ( CGameOptions::Instance()->replayMovieMode && status != 1 && !(replayRecorder && replayRecorder->isRunning()) ) 
02220              status = 100;
02221           else {
02222             if ( nextaction == rpl_finished && !resourcesCompared ) {
02223 
02224                if ( replayRecorder )
02225                   replayRecorder->pause();
02226                
02227                displaymessage2("running final comparison" );
02228 
02229                int replayedplayer  = actmap->actplayer; 
02230                actmap->endTurn();
02231                int nextplayer = findNextPlayer( actmap );
02232                if ( nextplayer < actmap->actplayer && performEndTurnOperations )
02233                   actmap->endRound();
02234                 
02235                actmap->getCursor() = orgmap->getCursor();
02236                
02237                resourcesCompared = true;
02238                ASCString resourceComparisonResult;
02239                GameMap* comparisonMap = NULL;
02240                GameMap* nextPlayerMap = NULL;
02241 
02242                if ( replayedplayer == orgmap->actplayer )
02243                   comparisonMap = orgmap;
02244                else
02245                   comparisonMap = nextPlayerMap = loadreplay ( orgmap->replayinfo->map[nextplayer]  );
02246 
02247                if ( !CGameOptions::Instance()->replayMovieMode ) {
02248                   if ( comparisonMap ) {
02249                      if ( compareMapResources( comparisonMap, actmap, player, &resourceComparisonResult)) {
02250                         ViewFormattedText vft( "warning", resourceComparisonResult, PG_Rect( -1, -1, 500, 550 ) );
02251                         vft.Show();
02252                         vft.RunModal();
02253                      }
02254 
02255                   } else
02256                      error("Replay: no map to compare to!");
02257                }
02258 
02259                delete nextPlayerMap;
02260             }
02261           }
02262        }
02263 
02264        for ( int i = 0; i < 5; ++i )
02265           getPGApplication().processEvent();
02266 
02267    } while ( status > 0  &&  status < 100 ) ;
02268 
02269    delete actmap;
02270    actmap = orgmap;
02271 
02272    int st = status;
02273    status = 0;
02274 
02275    updateFieldInfo();
02276 
02277    if ( st == 101 )
02278       return 1;
02279    else
02280       return 0;
02281 }
02282 
02283 void trunreplay :: firstinit ( void )
02284 {
02285     status = 0;
02286 }
02287 
02288 
02289 void hookReplayToSystem()
02290 {
02291    ActionContainer::commitCommand.connect( SigC::slot( &logActionToReplay ));
02292 }

Generated on Mon May 21 01:26:36 2012 for Advanced Strategic Command by  doxygen 1.5.1