00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "clipboard.h"
00027 #include "vehicle.h"
00028 #include "buildings.h"
00029 #include "gamemap.h"
00030 #include "spfst.h"
00031 #include "dlg_box.h"
00032 #include "statistics.h"
00033 #include "spfst-legacy.h"
00034
00035
00036 const char* clipboardFileExtension = "*.asc2clipboard";
00037 const char* oldClipboardFileExtension = "*.ascclipboard";
00038
00039
00040 ClipBoardBase::ClipBoardBase()
00041 {
00042 objectNum = 0;
00043
00044 }
00045
00046 void ClipBoardBase::clear()
00047 {
00048 buf.clear();
00049 properties.clear();
00050 objectNum = 0;
00051 }
00052
00053
00054
00055
00056 static int clipboardVersion = 1;
00057
00058 static const int clipboardToken = 0x574f0769;
00059
00060 void ClipBoardBase::setProperties( const ContainerBase* unit )
00061 {
00062 properties["strength"] = ASCString::toString( StatisticsCalculator::strength( unit, true ) );
00063 properties["materialindex"] = ASCString::toString( StatisticsCalculator::resource( unit, true ).material / 1000 );
00064 properties["productioncost"] = ASCString::toString( StatisticsCalculator::unitCost( unit, true ));
00065 properties["unitcount"] = ASCString::toString( StatisticsCalculator::unitCount( unit, true ));
00066 properties["name"] = unit->getName();
00067 properties["player"] = unit->getMap()->getPlayer( unit ).getName();
00068 properties["turn"] = ASCString::toString( unit->getMap()->time.turn() );
00069 properties["map"] = unit->getMap()->maptitle;
00070
00071
00072 ASCIIEncodingStream outerStream;
00073 {
00074 StreamCompressionFilter stream( &outerStream );
00075 stream.writeInt( clipboardToken );
00076 write( stream );
00077 }
00078 properties["data"] = outerStream.getResult();
00079 }
00080
00081 void ClipBoardBase::addUnit ( const Vehicle* unit )
00082 {
00083 MemoryStream stream ( &buf, tnstream::appending );
00084 stream.writeInt( ClipVehicle );
00085 unit->write ( stream );
00086 objectNum++;
00087
00088 setProperties( unit );
00089 }
00090
00091 void ClipBoardBase::addBuilding ( const Building* bld )
00092 {
00093 MemoryStream stream ( &buf, tnstream::appending );
00094 stream.writeInt( ClipBuilding );
00095 bld->write ( stream );
00096 objectNum++;
00097
00098 setProperties( bld );
00099
00100 }
00101
00102
00103 Vehicle* ClipBoardBase::pasteUnit( tnstream& stream )
00104 {
00105 Vehicle* veh = Vehicle::newFromStream( actmap, stream );
00106
00107
00108
00109 return veh;
00110 }
00111
00112 Vehicle* ClipBoardBase::pasteUnit( )
00113 {
00114 if ( !objectNum )
00115 return NULL;
00116
00117 MemoryStream stream ( &buf, tnstream::reading );
00118 Type type = Type(stream.readInt());
00119 if ( type == ClipVehicle )
00120 return pasteUnit ( stream );
00121
00122 return NULL;
00123 }
00124
00125
00126 void ClipBoardBase::place ( const MapCoordinate& pos )
00127 {
00128 if ( !objectNum )
00129 return;
00130
00131 MemoryStream stream ( &buf, tnstream::reading );
00132 Type type = Type(stream.readInt());
00133 if ( type == ClipVehicle ) {
00134 MapField* fld = actmap->getField ( pos );
00135 Vehicle* veh = pasteUnit ( stream );
00136
00137 if ( !fieldAccessible ( fld, veh, -2, NULL, true ) && !actmap->getgameparameter( cgp_movefrominvalidfields) ) {
00138 delete veh;
00139 return;
00140 }
00141
00142 if ( fld->vehicle )
00143 delete fld->vehicle;
00144 fld->vehicle = veh;
00145 veh->setnewposition( pos.x, pos.y );
00146 }
00147 if ( type == ClipBuilding ) {
00148 Building* bld = Building::newFromStream ( actmap, stream, false );
00149
00150 for ( int x = 0; x < 4; x++ )
00151 for ( int y = 0; y < 6; y++ )
00152 if ( bld->typ->fieldExists ( BuildingType::LocalCoordinate( x , y ) )) {
00153 MapField* field = actmap->getField( bld->typ->getFieldCoordinate( pos, BuildingType::LocalCoordinate( x, y) ));
00154 if ( !field ) {
00155 delete bld;
00156 displaymessage("building does not fit here", 1 );
00157 return;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 if ( field->vehicle ) {
00170 delete field->vehicle;
00171 field->vehicle = NULL;
00172 }
00173 if ( field->building ) {
00174 delete field->building;
00175 field->building = NULL;
00176 }
00177 }
00178
00179
00180 bld->chainbuildingtofield( pos );
00181 }
00182 }
00183
00184
00185 void ClipBoardBase::write( tnstream& stream )
00186 {
00187 stream.writeInt( clipboardVersion );
00188 stream.writeInt( objectNum );
00189 buf.writetostream ( &stream );
00190 }
00191
00192 void ClipBoardBase::read( tnstream& stream )
00193 {
00194 stream.readInt();
00195 objectNum = stream.readInt();
00196 buf.readfromstream ( &stream );
00197 }
00198
00199 void ClipBoardBase::writeProperties( PropertyContainer& pc ) const
00200 {
00201 for ( map<ASCString,ASCString>::const_iterator i = properties.begin(); i != properties.end(); ++i ) {
00202 ASCString temp = i->second;
00203 pc.addString( i->first, temp );
00204 }
00205 }
00206
00207 void ClipBoardBase::readProperties( PropertyContainer& pc )
00208 {
00209 ASCString data;
00210 pc.addString("data", data);
00211
00212 ASCIIDecodingStream outerStream ( data );
00213 StreamDecompressionFilter stream( &outerStream );
00214
00215 int token = stream.readInt();
00216 if ( token != clipboardToken )
00217 throw ASCmsgException("Invalid clipboard file");
00218
00219 read( stream );
00220 }
00221