| 1 | cycrow | 1 |   | 
        
           |  |  | 2 | #include "ModDiff.h"
 | 
        
           |  |  | 3 | #include "File_IO.h"
 | 
        
           |  |  | 4 | #include "CatFile.h"
 | 
        
           |  |  | 5 |   | 
        
           | 58 | cycrow | 6 | CModDiff::CModDiff(const Utils::String &dir, const Utils::String &sAddon, int maxPatch) : m_pCatFile(NULL), m_sAddon(sAddon), m_sTempDir("."), m_iMaxPatch(maxPatch)
 | 
        
           | 1 | cycrow | 7 | {
 | 
        
           | 58 | cycrow | 8 | 	m_bLoaded = this->LoadDirectory(dir);
 | 
        
           | 1 | cycrow | 9 | }
 | 
        
           |  |  | 10 |   | 
        
           |  |  | 11 | CModDiff::~CModDiff(void)
 | 
        
           |  |  | 12 | {
 | 
        
           | 58 | cycrow | 13 | 	delete m_pCatFile;
 | 
        
           | 1 | cycrow | 14 | }
 | 
        
           |  |  | 15 |   | 
        
           | 58 | cycrow | 16 | bool CModDiff::LoadDirectory(const Utils::String &dir)
 | 
        
           | 1 | cycrow | 17 | {
 | 
        
           |  |  | 18 | 	m_sCurrentDir = dir;
 | 
        
           | 101 | cycrow | 19 | 	m_fileSystem.setAddon(m_sAddon);
 | 
        
           | 58 | cycrow | 20 | 	return m_fileSystem.LoadFilesystem(dir, m_iMaxPatch);
 | 
        
           | 1 | cycrow | 21 | }
 | 
        
           |  |  | 22 |   | 
        
           | 58 | cycrow | 23 | bool CModDiff::startDiff(const Utils::String &sModFile)
 | 
        
           | 1 | cycrow | 24 | {
 | 
        
           |  |  | 25 | 	ClearError();
 | 
        
           | 58 | cycrow | 26 | 	if ( !CFileIO::Exists(sModFile) ) { m_iError = MDERR_FILENOTFOUND; return false; }
 | 
        
           | 1 | cycrow | 27 |   | 
        
           | 58 | cycrow | 28 | 	delete m_pCatFile;
 | 
        
           |  |  | 29 | 	m_pCatFile = new CCatFile;
 | 
        
           |  |  | 30 |   | 
        
           |  |  | 31 | 	if ( m_pCatFile->Open(sModFile, m_sAddon, CATREAD_CATDECRYPT, false) != CATERR_NONE ) { 
 | 
        
           |  |  | 32 | 		delete m_pCatFile;
 | 
        
           |  |  | 33 | 		m_pCatFile = NULL;
 | 
        
           |  |  | 34 | 		m_iError = MDERR_CANTOPENMOD; 
 | 
        
           |  |  | 35 | 		return false; 
 | 
        
           |  |  | 36 | 	}
 | 
        
           |  |  | 37 |   | 
        
           |  |  | 38 | 	return true;
 | 
        
           |  |  | 39 | }
 | 
        
           |  |  | 40 |   | 
        
           |  |  | 41 | Utils::String CModDiff::_extractFile(const Utils::String &sFile, const Utils::String &sTo)
 | 
        
           |  |  | 42 | {
 | 
        
           |  |  | 43 | 	SInCatFile *c = m_pCatFile->FindData(sFile);
 | 
        
           |  |  | 44 | 	if ( !c ) c = m_pCatFile->FindData(m_sAddon + "/" + sFile);
 | 
        
           |  |  | 45 | 	if ( !c ) return m_fileSystem.ExtractGameFile(sFile, sTo);
 | 
        
           |  |  | 46 | 	if ( m_pCatFile->ExtractFile(c, sTo) ) return sTo;
 | 
        
           |  |  | 47 | 	return "";
 | 
        
           |  |  | 48 | }
 | 
        
           |  |  | 49 |   | 
        
           |  |  | 50 | bool CModDiff::doDiff(const Utils::String &sModFile)
 | 
        
           |  |  | 51 | {
 | 
        
           |  |  | 52 | 	// find the file in the loaded cat
 | 
        
           |  |  | 53 | 	SInCatFile *c = m_pCatFile->FindData(sModFile);
 | 
        
           |  |  | 54 | 	if ( !c ) c = m_pCatFile->FindData(m_sAddon + "/" + sModFile);
 | 
        
           |  |  | 55 | 	if ( !c ) return false;
 | 
        
           |  |  | 56 |   | 
        
           |  |  | 57 | 	// extract the matching file
 | 
        
           |  |  | 58 | 	Utils::String sToFile = CFileIO(m_sTempDir + "/" + CFileIO(c->sFile).filename()).fullFilename();
 | 
        
           |  |  | 59 | 	if ( !m_pCatFile->ExtractFile(sModFile, sToFile) ) return false;
 | 
        
           |  |  | 60 |   | 
        
           |  |  | 61 | 	// create a diff
 | 
        
           | 124 | cycrow | 62 | 	Utils::String to = m_fileSystem.ExtractGameFile(c->sFile, sToFile + ".compare");
 | 
        
           | 58 | cycrow | 63 | 	if ( !to.empty() ) {
 | 
        
           | 124 | cycrow | 64 | 		SDiffFile *diff = diffFile(to, sToFile, c->sFile);
 | 
        
           | 58 | cycrow | 65 | 		if ( diff ) { 
 | 
        
           |  |  | 66 | 			this->_adjustFile(sModFile, diff, false);
 | 
        
           |  |  | 67 | 		}
 | 
        
           |  |  | 68 | 		CFileIO::Remove(to);
 | 
        
           |  |  | 69 | 	}
 | 
        
           |  |  | 70 |   | 
        
           |  |  | 71 | 	CFileIO::Remove(sToFile);
 | 
        
           |  |  | 72 |   | 
        
           |  |  | 73 | 	return true;
 | 
        
           |  |  | 74 | }
 | 
        
           |  |  | 75 |   | 
        
           |  |  | 76 |   | 
        
           |  |  | 77 | bool CModDiff::_adjustTShips(SDiffFile *pDiff, bool bReverse)
 | 
        
           |  |  | 78 | {
 | 
        
           |  |  | 79 | 	// need to read TCockpits
 | 
        
           |  |  | 80 | 	Utils::String sTo = this->_extractFile("types/TCockpits.pck", "TCockpits.xml");
 | 
        
           |  |  | 81 | 	if ( sTo.empty() ) return false;
 | 
        
           |  |  | 82 | 	CFileIO TCockpits("TCockpits.xml");
 | 
        
           |  |  | 83 | 	if ( !TCockpits.exists() ) return false;
 | 
        
           |  |  | 84 | 	CyStringList *pFiles = TCockpits.ReadLinesStr();
 | 
        
           |  |  | 85 | 	if ( !pFiles ) return false;
 | 
        
           |  |  | 86 |   | 
        
           |  |  | 87 | 	// remove all the comments
 | 
        
           |  |  | 88 | 	for ( SStringList *str = pFiles->Head(); str; str = str->next ) {
 | 
        
           |  |  | 89 | 		if ( str->str[0] == '/' ) str->remove = true;
 | 
        
           |  |  | 90 | 	}
 | 
        
           |  |  | 91 | 	pFiles->RemoveMarked();
 | 
        
           |  |  | 92 | 	pFiles->PopFront();
 | 
        
           |  |  | 93 |   | 
        
           | 84 | cycrow | 94 | 	std::map<Utils::String, int> fileSet;
 | 
        
           | 58 | cycrow | 95 | 	int iPos = 0;
 | 
        
           |  |  | 96 | 	for ( SStringList *str = pFiles->Head(); str; str = str->next ) fileSet[Utils::String(str->str.ToString()).token(";", -2)] = iPos++;
 | 
        
           |  |  | 97 |   | 
        
           |  |  | 98 | 	// now cycle through ships and adjust the cockpits
 | 
        
           |  |  | 99 | 	int iCount = -1;
 | 
        
           |  |  | 100 | 	for ( SDiffEntry *pEntry = pDiff->m_lEntries.First(); pEntry; pEntry = pDiff->m_lEntries.Next() ) {
 | 
        
           |  |  | 101 | 		switch (pEntry->iType) {
 | 
        
           |  |  | 102 | 			case DIFFTYPE_ADDITION:
 | 
        
           |  |  | 103 | 				{
 | 
        
           |  |  | 104 | 					SDiffEntryAddition *pAddition = static_cast<SDiffEntryAddition *>(pEntry);
 | 
        
           |  |  | 105 | 					if ( pAddition ) {
 | 
        
           |  |  | 106 | 						for ( int t = 0; t < 6; t++ ) {
 | 
        
           |  |  | 107 | 							Utils::String sE = pAddition->sEntry.token(";", 32 + (t * 2));
 | 
        
           |  |  | 108 | 							if ( !bReverse && sE.isNumber() ) {
 | 
        
           |  |  | 109 | 								int iTurret = sE;
 | 
        
           |  |  | 110 | 								if ( iTurret && iTurret < pFiles->Count() ) {
 | 
        
           |  |  | 111 | 									Utils::String sCockpit = pFiles->GetAt(iTurret)->str.ToString();
 | 
        
           |  |  | 112 | 									pAddition->sEntry = pAddition->sEntry.replaceToken(";", 32 + (t * 2), sCockpit.token(";", -2) + ":" + static_cast<long>(iTurret));
 | 
        
           |  |  | 113 | 								}
 | 
        
           |  |  | 114 | 							}
 | 
        
           |  |  | 115 | 							else if ( bReverse && !sE.isNumber() ) {
 | 
        
           |  |  | 116 | 								int iUnfound = 0;
 | 
        
           |  |  | 117 | 								if ( sE.isin(":") ) {
 | 
        
           |  |  | 118 | 									iUnfound = sE.token(":", 2);
 | 
        
           |  |  | 119 | 									sE = sE.token(":", 1);
 | 
        
           |  |  | 120 | 								}
 | 
        
           |  |  | 121 | 								int iEntry = (fileSet.find(sE) == fileSet.end()) ? iUnfound : fileSet[sE];
 | 
        
           |  |  | 122 | 								pAddition->sEntry = pAddition->sEntry.replaceToken(";", 32 + (t * 2), static_cast<long>(iEntry));
 | 
        
           |  |  | 123 | 							}
 | 
        
           |  |  | 124 | 						}
 | 
        
           |  |  | 125 | 					}
 | 
        
           |  |  | 126 | 				}
 | 
        
           |  |  | 127 | 				break;
 | 
        
           |  |  | 128 | 			case DIFFTYPE_CHANGE:
 | 
        
           |  |  | 129 | 				{
 | 
        
           |  |  | 130 | 					SDiffEntryChange *pChange = static_cast<SDiffEntryChange *>(pEntry);
 | 
        
           |  |  | 131 | 					if ( pChange->iPos >= 32 && pChange->iPos <= 42 && (pChange->iPos % 2) && pChange->sEntry.isNumber() ) {
 | 
        
           |  |  | 132 | 						Utils::String sCockpit = pFiles->GetAt(pChange->sEntry)->str.ToString();
 | 
        
           |  |  | 133 | 						pChange->sEntry = sCockpit.token(";", -2) + ":" + pChange->sEntry;
 | 
        
           |  |  | 134 | 					}
 | 
        
           |  |  | 135 | 				}
 | 
        
           |  |  | 136 | 				break;
 | 
        
           |  |  | 137 | 		}
 | 
        
           |  |  | 138 | 	}
 | 
        
           |  |  | 139 |   | 
        
           |  |  | 140 | 	delete pFiles;
 | 
        
           |  |  | 141 |   | 
        
           |  |  | 142 | 	return true;
 | 
        
           |  |  | 143 | }
 | 
        
           |  |  | 144 |   | 
        
           |  |  | 145 | int CModDiff::_specialType(const Utils::String &sFile)
 | 
        
           |  |  | 146 | {
 | 
        
           |  |  | 147 | 	if ( sFile.Compare("TShips") ) return MERGETYPE_TSHIPS;
 | 
        
           |  |  | 148 | 	return MERGETYPE_NONE;
 | 
        
           |  |  | 149 | }
 | 
        
           |  |  | 150 |   | 
        
           |  |  | 151 | void CModDiff::_adjustFile(const Utils::String &sFile, SDiffFile *pDiff, bool bReverse)
 | 
        
           |  |  | 152 | {
 | 
        
           |  |  | 153 | 	// check if we need to adjust the file
 | 
        
           |  |  | 154 | 	CFileIO File(sFile);
 | 
        
           |  |  | 155 | 	int iType = _specialType(File.baseName());
 | 
        
           |  |  | 156 | 	if ( iType == MERGETYPE_NONE ) return;
 | 
        
           |  |  | 157 |   | 
        
           |  |  | 158 | 	// read in the file data
 | 
        
           |  |  | 159 | 	switch(iType) {
 | 
        
           |  |  | 160 | 		case MERGETYPE_TSHIPS:
 | 
        
           |  |  | 161 | 			this->_adjustTShips(pDiff, bReverse);
 | 
        
           |  |  | 162 | 			break;
 | 
        
           |  |  | 163 | 	}
 | 
        
           |  |  | 164 | }
 | 
        
           |  |  | 165 |   | 
        
           |  |  | 166 | bool CModDiff::CreateDiff(const Utils::String &modfile)
 | 
        
           |  |  | 167 | {
 | 
        
           |  |  | 168 | 	ClearError();
 | 
        
           |  |  | 169 |   | 
        
           | 1 | cycrow | 170 | 	//check for valid parameters
 | 
        
           | 52 | cycrow | 171 | 	if ( !CFileIO(modfile).ExistsOld() ) { m_iError = MDERR_FILENOTFOUND; return false; }
 | 
        
           | 1 | cycrow | 172 |   | 
        
           | 58 | cycrow | 173 | 	Utils::String addonDir = "";
 | 
        
           |  |  | 174 | 	int addonSize = addonDir.length() + 1;
 | 
        
           | 1 | cycrow | 175 |   | 
        
           |  |  | 176 | 	// try and open the mod file
 | 
        
           |  |  | 177 | 	CCatFile cat;
 | 
        
           |  |  | 178 | 	if ( cat.Open(modfile, addonDir, CATREAD_DAT, false) != CATERR_NONE ) { m_iError = MDERR_CANTOPENMOD; return false; }
 | 
        
           |  |  | 179 |   | 
        
           |  |  | 180 | 	// we'll need to read in all the types/text files
 | 
        
           |  |  | 181 | 	for ( int i = 0; i < cat.GetNumFiles(); i++ )
 | 
        
           |  |  | 182 | 	{
 | 
        
           |  |  | 183 | 		SInCatFile *f = cat.GetFile(i);
 | 
        
           | 124 | cycrow | 184 | 		Utils::String checkFile = f->sFile.findReplace("\\", "/");
 | 
        
           | 58 | cycrow | 185 | 		if ( (checkFile.left(6).Compare("types/") || checkFile.left(2).Compare("t/") || checkFile.left(6 + addonSize).Compare(addonDir + "/types/") || checkFile.left(2 + addonSize).Compare(addonDir + "/t/")) && _validFile(checkFile) )
 | 
        
           | 1 | cycrow | 186 | 		{
 | 
        
           |  |  | 187 | 			// extract the file to the temp dir
 | 
        
           | 58 | cycrow | 188 | 			Utils::String toFile = CFileIO(m_sTempDir + "/" + CFileIO(f->sFile).filename()).fullFilename();
 | 
        
           | 1 | cycrow | 189 | 			if ( cat.ExtractFile(f, toFile ) )
 | 
        
           |  |  | 190 | 			{
 | 
        
           |  |  | 191 | 				// now extract the matching file from the game dir
 | 
        
           | 124 | cycrow | 192 | 				if ( m_fileSystem.ExtractGameFile(f->sFile, toFile + ".compare") )
 | 
        
           | 1 | cycrow | 193 | 				{
 | 
        
           | 124 | cycrow | 194 | 					diffFile(toFile + ".compare", toFile, f->sFile);
 | 
        
           | 58 | cycrow | 195 | 					CFileIO::Remove(toFile + ".compare");
 | 
        
           | 1 | cycrow | 196 | 				}
 | 
        
           |  |  | 197 | 				// make sure we clear up afterwards
 | 
        
           | 58 | cycrow | 198 | 				CFileIO::Remove(toFile);
 | 
        
           | 1 | cycrow | 199 | 			}
 | 
        
           |  |  | 200 | 		}
 | 
        
           |  |  | 201 | 	}
 | 
        
           |  |  | 202 |   | 
        
           |  |  | 203 | 	return true;
 | 
        
           |  |  | 204 | }
 | 
        
           |  |  | 205 |   | 
        
           | 58 | cycrow | 206 | SDiffFile *CModDiff::diffFile(const Utils::String &baseFile, const Utils::String &modFile, const Utils::String &fileType)
 | 
        
           | 1 | cycrow | 207 | {
 | 
        
           |  |  | 208 | 	int type = 0;
 | 
        
           |  |  | 209 |   | 
        
           |  |  | 210 | 	SDiffFile *diffFile = new SDiffFile;
 | 
        
           |  |  | 211 | 	diffFile->sFile = fileType;
 | 
        
           |  |  | 212 |   | 
        
           |  |  | 213 | 	// read both files and compare them
 | 
        
           |  |  | 214 | 	CFileIO Base(baseFile);
 | 
        
           |  |  | 215 | 	CyStringList *baseLines = Base.ReadLinesStr();
 | 
        
           |  |  | 216 | 	if ( baseLines )
 | 
        
           |  |  | 217 | 	{
 | 
        
           |  |  | 218 | 		CFileIO Mod(modFile);
 | 
        
           |  |  | 219 | 		CyStringList *lines = Mod.ReadLinesStr();
 | 
        
           |  |  | 220 | 		if ( lines )
 | 
        
           |  |  | 221 | 		{
 | 
        
           |  |  | 222 | 			int id = -1;
 | 
        
           |  |  | 223 | 			SStringList *node[2];
 | 
        
           |  |  | 224 | 			node[0] = baseLines->Head();
 | 
        
           |  |  | 225 | 			node[1] = lines->Head();
 | 
        
           |  |  | 226 |   | 
        
           | 58 | cycrow | 227 | 			Utils::String prev[2];
 | 
        
           | 1 | cycrow | 228 |   | 
        
           |  |  | 229 | 			while ( node[0] || node[1] )
 | 
        
           |  |  | 230 | 			{
 | 
        
           | 58 | cycrow | 231 | 				Utils::String str[2];
 | 
        
           | 1 | cycrow | 232 |   | 
        
           |  |  | 233 | 				for ( int i = 0; i < 2; i++ )
 | 
        
           |  |  | 234 | 				{
 | 
        
           |  |  | 235 | 					while (node[i])
 | 
        
           |  |  | 236 | 					{
 | 
        
           | 58 | cycrow | 237 | 						Utils::String l = node[i]->str.ToString();
 | 
        
           | 1 | cycrow | 238 | 						node[i] = node[i]->next;
 | 
        
           |  |  | 239 |   | 
        
           | 58 | cycrow | 240 | 						l.removeFirstSpace();
 | 
        
           |  |  | 241 | 						l.removeChar('\r');
 | 
        
           |  |  | 242 | 						if ( !l.empty() && l.left(1) != "/") {
 | 
        
           | 1 | cycrow | 243 | 							str[i] += l;
 | 
        
           | 58 | cycrow | 244 | 							if ( _isLineComplete(str[i], fileType, (id == -1) ? true : false) ) 
 | 
        
           | 1 | cycrow | 245 | 								break;
 | 
        
           |  |  | 246 | 						}
 | 
        
           |  |  | 247 | 					}
 | 
        
           |  |  | 248 | 				}
 | 
        
           |  |  | 249 |   | 
        
           |  |  | 250 | 				if ( id == -1 )
 | 
        
           |  |  | 251 | 					id = 0;
 | 
        
           |  |  | 252 | 				else
 | 
        
           |  |  | 253 | 				{
 | 
        
           |  |  | 254 | 					// first check for mismatch amount, one of the nodes will be empty
 | 
        
           | 58 | cycrow | 255 | 					if ( str[0].empty() && !str[1].empty() ) // mod file has more entries (these must be additions)
 | 
        
           | 1 | cycrow | 256 | 					{
 | 
        
           |  |  | 257 | 						SDiffEntryAddition *entry = new SDiffEntryAddition;
 | 
        
           |  |  | 258 | 						entry->iID = id;
 | 
        
           |  |  | 259 | 						entry->sEntry = str[1];
 | 
        
           |  |  | 260 | 						diffFile->m_lEntries.push_back(entry);
 | 
        
           |  |  | 261 | 					}
 | 
        
           | 58 | cycrow | 262 | 					else if ( str[1].empty() && !str[0].empty() ) // mod file has less entries (must have removed some)
 | 
        
           | 1 | cycrow | 263 | 					{
 | 
        
           |  |  | 264 | 						SDiffEntry *entry = new SDiffEntryRemoval;
 | 
        
           |  |  | 265 | 						entry->iID = id;
 | 
        
           |  |  | 266 | 						diffFile->m_lEntries.push_back(entry);
 | 
        
           |  |  | 267 | 					}
 | 
        
           |  |  | 268 | 					else // we have a line for both, we need to compare them
 | 
        
           |  |  | 269 | 					{
 | 
        
           |  |  | 270 | 						// we migth have multiple entries to add when changed
 | 
        
           | 58 | cycrow | 271 | 						if ( str[0].empty() || str[1].empty() ) continue;
 | 
        
           |  |  | 272 | 						_compareLine(str[0], str[1], type, id, diffFile);						
 | 
        
           | 1 | cycrow | 273 | 					}
 | 
        
           |  |  | 274 |   | 
        
           |  |  | 275 | 					++id;
 | 
        
           |  |  | 276 | 				}
 | 
        
           |  |  | 277 | 			}
 | 
        
           |  |  | 278 |   | 
        
           |  |  | 279 | 			delete lines;
 | 
        
           |  |  | 280 | 		}
 | 
        
           |  |  | 281 | 		delete baseLines;
 | 
        
           |  |  | 282 | 	}
 | 
        
           |  |  | 283 |   | 
        
           | 58 | cycrow | 284 | 	if ( diffFile->m_lEntries.empty() ) {
 | 
        
           | 1 | cycrow | 285 | 		delete diffFile;
 | 
        
           | 58 | cycrow | 286 | 		return NULL;
 | 
        
           |  |  | 287 | 	}
 | 
        
           |  |  | 288 | 	else {
 | 
        
           | 1 | cycrow | 289 | 		m_lFiles.push_back(diffFile);
 | 
        
           | 58 | cycrow | 290 | 		return diffFile;
 | 
        
           |  |  | 291 | 	}
 | 
        
           | 1 | cycrow | 292 | }
 | 
        
           |  |  | 293 |   | 
        
           | 58 | cycrow | 294 | int CModDiff::_amountPosition(const Utils::String &fileType)
 | 
        
           | 1 | cycrow | 295 | {
 | 
        
           |  |  | 296 | 	return 2;
 | 
        
           |  |  | 297 | }
 | 
        
           |  |  | 298 |   | 
        
           | 58 | cycrow | 299 | bool CModDiff::_isLineComplete(const Utils::String &line, const Utils::String &fileType, bool first)
 | 
        
           | 1 | cycrow | 300 | {
 | 
        
           |  |  | 301 | 	if ( first )
 | 
        
           |  |  | 302 | 	{
 | 
        
           | 58 | cycrow | 303 | 		if ( line.countToken(";") > _amountPosition(fileType) ) return true;
 | 
        
           | 1 | cycrow | 304 | 		return false;
 | 
        
           |  |  | 305 | 	}
 | 
        
           |  |  | 306 |   | 
        
           |  |  | 307 | 	return true;
 | 
        
           |  |  | 308 | }
 | 
        
           |  |  | 309 |   | 
        
           | 58 | cycrow | 310 | void CModDiff::_compareLine(const Utils::String &line1, const Utils::String &line2, int type, int id, SDiffFile *diffFile)
 | 
        
           | 1 | cycrow | 311 | {
 | 
        
           |  |  | 312 | 	int max1, max2;
 | 
        
           | 58 | cycrow | 313 | 	Utils::String *str1 = line1.tokenise(";", &max1);
 | 
        
           |  |  | 314 | 	Utils::String *str2 = line2.tokenise(";", &max2);
 | 
        
           | 1 | cycrow | 315 |   | 
        
           |  |  | 316 | 	if ( !str1 || !str2 ) return;
 | 
        
           |  |  | 317 |   | 
        
           |  |  | 318 | 	int max = ((max1 > max2) ? max2 : max1);
 | 
        
           |  |  | 319 | 	for ( int i = 0; i < max; i++ )
 | 
        
           |  |  | 320 | 	{
 | 
        
           |  |  | 321 | 		if ( str1[i] == str2[i] ) continue;
 | 
        
           |  |  | 322 | 		if ( str1[i].Compare(str2[i]) ) continue;
 | 
        
           | 58 | cycrow | 323 | 		if ( str1[i].empty() && str2[i].empty() ) continue;
 | 
        
           |  |  | 324 | 		if ( str1[i].length() && str1[i][0] == '\0' && str2[i].length() && str2[i][0] == '\0' ) continue;
 | 
        
           | 1 | cycrow | 325 | 		SDiffEntryChange *diff = new SDiffEntryChange;
 | 
        
           |  |  | 326 | 		diff->iID = id;
 | 
        
           |  |  | 327 | 		diff->iPos = i;
 | 
        
           |  |  | 328 | 		diff->sEntry = str2[i];
 | 
        
           |  |  | 329 | 		diff->sFrom = str1[i];
 | 
        
           |  |  | 330 | 		diffFile->m_lEntries.push_back(diff);
 | 
        
           |  |  | 331 | 	}
 | 
        
           |  |  | 332 | }
 | 
        
           |  |  | 333 |   | 
        
           |  |  | 334 | void CModDiff::Clean()
 | 
        
           |  |  | 335 | {
 | 
        
           |  |  | 336 | 	for ( CListNode<SDiffFile> *node = m_lFiles.Front(); node; node = node->next() )
 | 
        
           |  |  | 337 | 	{
 | 
        
           |  |  | 338 | 		node->Data()->m_lEntries.clear();
 | 
        
           |  |  | 339 | 		node->DeleteData();
 | 
        
           |  |  | 340 | 	}
 | 
        
           |  |  | 341 | 	m_lFiles.clear();
 | 
        
           |  |  | 342 | }
 | 
        
           |  |  | 343 |   | 
        
           | 58 | cycrow | 344 | bool CModDiff::WriteDiff(const Utils::String &file)
 | 
        
           | 1 | cycrow | 345 | {
 | 
        
           |  |  | 346 | 	if ( m_lFiles.empty() ) return false;
 | 
        
           |  |  | 347 |   | 
        
           |  |  | 348 | 	CyStringList lines;
 | 
        
           |  |  | 349 |   | 
        
           |  |  | 350 | 	for ( CListNode<SDiffFile> *node = m_lFiles.Front(); node; node = node->next() )
 | 
        
           |  |  | 351 | 	{
 | 
        
           |  |  | 352 | 		lines.PushBack(CyString("$$") + node->Data()->sFile);
 | 
        
           |  |  | 353 | 		for ( CListNode<SDiffEntry> *node2 = node->Data()->m_lEntries.Front(); node2; node2 = node2->next() )
 | 
        
           |  |  | 354 | 		{
 | 
        
           |  |  | 355 | 			switch(node2->Data()->iType)
 | 
        
           |  |  | 356 | 			{
 | 
        
           |  |  | 357 | 				case DIFFTYPE_ADDITION:
 | 
        
           |  |  | 358 | 					lines.PushBack(CyString("+++:") + (long)node2->Data()->iID + ":" + ((SDiffEntryAddition *)node2->Data())->sEntry);
 | 
        
           |  |  | 359 | 					break;
 | 
        
           |  |  | 360 | 				case DIFFTYPE_REMOVAL:
 | 
        
           |  |  | 361 | 					lines.PushBack(CyString("---:") + (long)node2->Data()->iID);
 | 
        
           |  |  | 362 | 					break;
 | 
        
           |  |  | 363 | 				case DIFFTYPE_CHANGE:
 | 
        
           |  |  | 364 | 					lines.PushBack(CyString("///:") + (long)node2->Data()->iID + ":" + (long)((SDiffEntryChange *)node2->Data())->iPos + ":" + ((SDiffEntryChange *)node2->Data())->sEntry);
 | 
        
           |  |  | 365 | 					break;
 | 
        
           |  |  | 366 | 			}
 | 
        
           |  |  | 367 | 		}
 | 
        
           |  |  | 368 | 	}
 | 
        
           |  |  | 369 |   | 
        
           |  |  | 370 |   | 
        
           |  |  | 371 | 	CFileIO File(file);
 | 
        
           |  |  | 372 | 	return File.WriteFile(&lines);
 | 
        
           |  |  | 373 | }
 | 
        
           |  |  | 374 |   | 
        
           | 58 | cycrow | 375 | bool CModDiff::ReadDiff(const Utils::String &file)
 | 
        
           | 1 | cycrow | 376 | {
 | 
        
           |  |  | 377 | 	Clean();
 | 
        
           |  |  | 378 |   | 
        
           |  |  | 379 | 	CFileIO File(file);
 | 
        
           | 52 | cycrow | 380 | 	if ( !File.exists() ) return false;
 | 
        
           | 1 | cycrow | 381 |   | 
        
           |  |  | 382 | 	CyStringList *lines = File.ReadLinesStr();
 | 
        
           |  |  | 383 |   | 
        
           |  |  | 384 | 	if ( lines )
 | 
        
           |  |  | 385 | 	{
 | 
        
           |  |  | 386 | 		SDiffFile *diffFile = NULL;
 | 
        
           |  |  | 387 | 		for ( SStringList *str = lines->Head(); str; str = str->next )
 | 
        
           |  |  | 388 | 		{
 | 
        
           |  |  | 389 | 			if ( str->str.Left(2).Compare("$$") )
 | 
        
           |  |  | 390 | 			{
 | 
        
           |  |  | 391 | 				diffFile = new SDiffFile;
 | 
        
           |  |  | 392 | 				m_lFiles.push_back(diffFile);
 | 
        
           | 58 | cycrow | 393 | 				diffFile->sFile = str->str.Right(-2).ToString();
 | 
        
           | 1 | cycrow | 394 | 			}
 | 
        
           |  |  | 395 | 			else if ( diffFile )
 | 
        
           |  |  | 396 | 			{
 | 
        
           |  |  | 397 | 				if ( str->str.Left(4).Compare("+++:") )
 | 
        
           |  |  | 398 | 				{
 | 
        
           |  |  | 399 | 					SDiffEntryAddition *addition = new SDiffEntryAddition;
 | 
        
           |  |  | 400 | 					addition->iID = str->str.GetToken(":", 2, 2).ToInt();
 | 
        
           | 58 | cycrow | 401 | 					addition->sEntry = str->str.GetToken(":", 3).ToString();
 | 
        
           | 1 | cycrow | 402 | 					diffFile->m_lEntries.push_back(addition);
 | 
        
           |  |  | 403 | 				}
 | 
        
           |  |  | 404 | 				else if ( str->str.Left(4).Compare("---:") )
 | 
        
           |  |  | 405 | 				{
 | 
        
           |  |  | 406 | 					SDiffEntryRemoval *entry = new SDiffEntryRemoval;
 | 
        
           |  |  | 407 | 					entry->iID = str->str.GetToken(":", 2, 2).ToInt();
 | 
        
           |  |  | 408 | 					diffFile->m_lEntries.push_back(entry);
 | 
        
           |  |  | 409 | 				}
 | 
        
           |  |  | 410 | 				else if ( str->str.Left(4).Compare("///:") )
 | 
        
           |  |  | 411 | 				{
 | 
        
           |  |  | 412 | 					SDiffEntryChange *entry = new SDiffEntryChange;
 | 
        
           |  |  | 413 | 					entry->iID = str->str.GetToken(":", 2, 2).ToInt();
 | 
        
           |  |  | 414 | 					entry->iPos = str->str.GetToken(":", 3, 3).ToInt();
 | 
        
           | 58 | cycrow | 415 | 					entry->sEntry = str->str.GetToken(":", 4).ToString();
 | 
        
           | 1 | cycrow | 416 | 					diffFile->m_lEntries.push_back(entry);
 | 
        
           |  |  | 417 | 				}
 | 
        
           |  |  | 418 | 			}
 | 
        
           |  |  | 419 | 		}
 | 
        
           |  |  | 420 |   | 
        
           |  |  | 421 | 		delete lines;
 | 
        
           |  |  | 422 |   | 
        
           |  |  | 423 | 		return true;
 | 
        
           |  |  | 424 | 	}
 | 
        
           |  |  | 425 |   | 
        
           |  |  | 426 | 	return false;
 | 
        
           |  |  | 427 | }
 | 
        
           |  |  | 428 |   | 
        
           | 58 | cycrow | 429 | bool CModDiff::ApplyMod(const Utils::String &mod)
 | 
        
           | 1 | cycrow | 430 | {
 | 
        
           | 58 | cycrow | 431 | 	return m_fileSystem.addMod(mod);
 | 
        
           | 1 | cycrow | 432 | }
 | 
        
           |  |  | 433 |   | 
        
           | 58 | cycrow | 434 | bool CModDiff::ApplyDiff(const Utils::String &mod)
 | 
        
           | 1 | cycrow | 435 | {
 | 
        
           |  |  | 436 | 	if ( m_lFiles.empty() ) return false;
 | 
        
           |  |  | 437 |   | 
        
           | 58 | cycrow | 438 | 	this->ApplyMod(mod);
 | 
        
           |  |  | 439 |   | 
        
           | 1 | cycrow | 440 | 	bool ret = false;
 | 
        
           |  |  | 441 |   | 
        
           |  |  | 442 | 	CyString addonDir = "";
 | 
        
           |  |  | 443 |   | 
        
           |  |  | 444 | 	CCatFile cat;
 | 
        
           | 58 | cycrow | 445 | 	if ( !CCatFile::Opened(cat.Open(mod, addonDir, CATREAD_CATDECRYPT, true)) )
 | 
        
           | 1 | cycrow | 446 | 		return false;
 | 
        
           |  |  | 447 |   | 
        
           |  |  | 448 | 	for ( CListNode<SDiffFile> *node = m_lFiles.Front(); node; node = node->next() )
 | 
        
           |  |  | 449 | 	{
 | 
        
           |  |  | 450 | 		// extract the file from the game
 | 
        
           |  |  | 451 | 		SDiffFile *f = node->Data();
 | 
        
           |  |  | 452 |   | 
        
           |  |  | 453 | 		CyStringList writeLines;
 | 
        
           |  |  | 454 | 		int id;
 | 
        
           | 58 | cycrow | 455 | 		if ( _readGameFile(f->sFile, &writeLines, &id) )
 | 
        
           | 1 | cycrow | 456 | 		{
 | 
        
           |  |  | 457 | 			// now apply the diff
 | 
        
           | 58 | cycrow | 458 | 			this->_adjustFile(f->sFile, f, true);
 | 
        
           | 1 | cycrow | 459 | 			for ( CListNode<SDiffEntry> *eNode = f->m_lEntries.Front(); eNode; eNode = eNode->next() )
 | 
        
           |  |  | 460 | 			{
 | 
        
           |  |  | 461 | 				switch ( eNode->Data()->iType )
 | 
        
           |  |  | 462 | 				{
 | 
        
           |  |  | 463 | 					case DIFFTYPE_ADDITION:
 | 
        
           | 58 | cycrow | 464 | 						writeLines.PushBack(CyString(((SDiffEntryAddition *)eNode->Data())->sEntry));
 | 
        
           | 1 | cycrow | 465 | 						break;
 | 
        
           |  |  | 466 | 					case DIFFTYPE_REMOVAL:
 | 
        
           |  |  | 467 | 						writeLines.GetAt(eNode->Data()->iID)->remove = true;
 | 
        
           |  |  | 468 | 						break;
 | 
        
           |  |  | 469 | 					case DIFFTYPE_CHANGE:
 | 
        
           |  |  | 470 | 						{
 | 
        
           |  |  | 471 | 							SStringList *strAt = writeLines.GetAt(eNode->Data()->iID);
 | 
        
           |  |  | 472 | 							if ( strAt )
 | 
        
           |  |  | 473 | 								strAt->str.RepToken(";", ((SDiffEntryChange *)eNode->Data())->iPos, ((SDiffEntryChange *)eNode->Data())->sEntry);
 | 
        
           |  |  | 474 | 						}
 | 
        
           |  |  | 475 | 						break;
 | 
        
           |  |  | 476 | 				}
 | 
        
           |  |  | 477 | 			}
 | 
        
           |  |  | 478 |   | 
        
           |  |  | 479 | 			// add our comments and info
 | 
        
           |  |  | 480 | 			writeLines.PushFront(CyString((long)id) + ";" + (long)writeLines.Count() + ";");
 | 
        
           |  |  | 481 | 			writeLines.PushFront(CyString("// Generated by ModDiff (SPK Version: ") + CyString::CreateFromFloat(GetLibraryVersion(), 2) + ")");
 | 
        
           |  |  | 482 |   | 
        
           |  |  | 483 | 			// now write the file
 | 
        
           | 58 | cycrow | 484 | 			CFileIO WriteFile(m_sTempDir + "/" + CFileIO(f->sFile).filename());
 | 
        
           | 1 | cycrow | 485 | 			if ( WriteFile.WriteFile(&writeLines) )
 | 
        
           |  |  | 486 | 			{
 | 
        
           | 58 | cycrow | 487 | 				if ( cat.AppendFile(m_sTempDir + "/" + CFileIO(f->sFile).filename(), f->sFile) )
 | 
        
           | 1 | cycrow | 488 | 				{
 | 
        
           |  |  | 489 | 					ret = true;
 | 
        
           |  |  | 490 | 				}
 | 
        
           | 58 | cycrow | 491 | 				WriteFile.remove();
 | 
        
           | 1 | cycrow | 492 | 			}
 | 
        
           |  |  | 493 | 		}
 | 
        
           |  |  | 494 | 	}
 | 
        
           |  |  | 495 |   | 
        
           |  |  | 496 | 	if ( ret )
 | 
        
           |  |  | 497 | 		cat.WriteCatFile();
 | 
        
           |  |  | 498 |   | 
        
           |  |  | 499 | 	return ret;
 | 
        
           |  |  | 500 | }
 | 
        
           |  |  | 501 |   | 
        
           | 58 | cycrow | 502 | bool CModDiff::_readGameFile(const Utils::String &file, CyStringList *writeLines, int *id)
 | 
        
           | 1 | cycrow | 503 | {
 | 
        
           |  |  | 504 | 	bool ret = false;
 | 
        
           |  |  | 505 |   | 
        
           | 58 | cycrow | 506 | 	Utils::String sTo = m_fileSystem.ExtractGameFile(file, m_sTempDir + "/" + CFileIO(file).filename());
 | 
        
           |  |  | 507 | 	if ( !sTo.empty() ) {
 | 
        
           |  |  | 508 | 		CFileIO File(sTo);
 | 
        
           | 1 | cycrow | 509 |   | 
        
           |  |  | 510 | 		CyStringList *lines = File.ReadLinesStr();
 | 
        
           |  |  | 511 | 		if ( lines )
 | 
        
           |  |  | 512 | 		{
 | 
        
           |  |  | 513 | 			int entries = -1;
 | 
        
           |  |  | 514 | 			for ( SStringList *str = lines->Head(); str; str = str->next )
 | 
        
           |  |  | 515 | 			{
 | 
        
           |  |  | 516 | 				CyString l = str->str;
 | 
        
           |  |  | 517 | 				l.RemoveFirstSpace();
 | 
        
           |  |  | 518 | 				if ( l.Empty() ) continue;
 | 
        
           |  |  | 519 | 				if ( l.Left(1) == "/" ) continue;
 | 
        
           |  |  | 520 |   | 
        
           |  |  | 521 | 				if ( entries == -1 )
 | 
        
           |  |  | 522 | 				{
 | 
        
           |  |  | 523 | 					entries = l.GetToken(":", 2, 2).ToInt();
 | 
        
           |  |  | 524 | 					if ( id )
 | 
        
           |  |  | 525 | 						(*id) = l.GetToken(":", 1, 1).ToInt();
 | 
        
           |  |  | 526 | 				}
 | 
        
           |  |  | 527 | 				else
 | 
        
           |  |  | 528 | 					writeLines->PushBack(l);
 | 
        
           |  |  | 529 | 			}
 | 
        
           |  |  | 530 | 			delete lines;
 | 
        
           |  |  | 531 | 			ret = true;
 | 
        
           |  |  | 532 | 		}
 | 
        
           | 58 | cycrow | 533 | 		File.close();
 | 
        
           | 52 | cycrow | 534 | 		File.remove();
 | 
        
           | 1 | cycrow | 535 | 	}
 | 
        
           |  |  | 536 |   | 
        
           |  |  | 537 | 	return ret;
 | 
        
           |  |  | 538 | }
 | 
        
           |  |  | 539 |   | 
        
           |  |  | 540 |   | 
        
           | 58 | cycrow | 541 | bool CModDiff::_validFile(const Utils::String &file)
 | 
        
           | 1 | cycrow | 542 | {
 | 
        
           |  |  | 543 | 	return CModDiff::CanBeDiffed(file);
 | 
        
           |  |  | 544 | }
 | 
        
           |  |  | 545 |   | 
        
           | 58 | cycrow | 546 | bool CModDiff::CanBeDiffed(const Utils::String &file)
 | 
        
           | 1 | cycrow | 547 | {
 | 
        
           | 58 | cycrow | 548 | 	Utils::String checkFile = file;
 | 
        
           | 102 | cycrow | 549 | 	checkFile = CFileIO(file).dir() + "/" + CFileIO(file).baseName();
 | 
        
           | 1 | cycrow | 550 |   | 
        
           |  |  | 551 | 	// all t files are the same format
 | 
        
           | 58 | cycrow | 552 | 	if ( checkFile.left(7).Compare("types/T") )
 | 
        
           | 1 | cycrow | 553 | 		return true;
 | 
        
           |  |  | 554 |   | 
        
           |  |  | 555 | 	return false;
 | 
        
           | 35 | cycrow | 556 | }
 |