00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <engine/ModFiles.h>
00022 #include <common/Defines.h>
00023 #include <common/Logger.h>
00024 #include <common/FileList.h>
00025 #include <lang/LangResource.h>
00026 #include <stdio.h>
00027
00028 ModFiles::ModFiles()
00029 {
00030 }
00031
00032 ModFiles::~ModFiles()
00033 {
00034 std::map<std::string, ModFileEntry *>::iterator itor;
00035 for (itor = files_.begin();
00036 itor != files_.end();
00037 itor++)
00038 {
00039 delete (*itor).second;
00040 }
00041 files_.clear();
00042 }
00043
00044 bool ModFiles::fileEnding(const std::string &file, const std::string &ext)
00045 {
00046 int fileLen = file.size();
00047 int extLen = ext.size();
00048 if (fileLen < extLen) return false;
00049
00050 for (int i=0; i<extLen; i++)
00051 {
00052 if (file.c_str()[fileLen - i - 1] != ext.c_str()[extLen - i - 1])
00053 {
00054 return false;
00055 }
00056 }
00057 return true;
00058 }
00059
00060 bool ModFiles::excludeFile(const std::string &file)
00061 {
00062 if (file == "Thumbs.db") return true;
00063 if (file == "CVS") return true;
00064 if (file == "..") return true;
00065
00066 if (!fileEnding(file, ".xml") &&
00067 !fileEnding(file, ".bmp") &&
00068 !fileEnding(file, ".txt") &&
00069 !fileEnding(file, ".png") &&
00070 !fileEnding(file, ".jpg") &&
00071 !fileEnding(file, ".ico") &&
00072 !fileEnding(file, ".ase") &&
00073 !fileEnding(file, ".wav") &&
00074 !fileEnding(file, ".ogg"))
00075 {
00076 Logger::log(S3D::formatStringBuffer("Excluding mod file \"%s\"", file.c_str()));
00077 return true;
00078 }
00079
00080 return false;
00081 }
00082
00083 bool ModFiles::loadModFiles(const std::string &mod,
00084 bool createDir, ProgressCounter *counter)
00085 {
00086 {
00087
00088 std::string modDir = S3D::getModFile(mod);
00089 if (S3D::dirExists(modDir))
00090 {
00091 if (counter) counter->setNewOp(LANG_RESOURCE("LOADING_USER_MODS", "Loading User Mods"));
00092 if (!loadModDir(modDir, mod, counter)) return false;
00093 }
00094 else
00095 {
00096 if (createDir) S3D::dirMake(modDir);
00097 }
00098 }
00099
00100 {
00101
00102 std::string modDir = S3D::getGlobalModFile(mod);
00103 if (S3D::dirExists(modDir))
00104 {
00105 if (counter) counter->setNewOp(LANG_RESOURCE("LOADING_GLOBAL_MODS", "Loading Global Mods"));
00106 if (!loadModDir(modDir, mod, counter)) return false;
00107 }
00108 }
00109
00110
00111
00112 if (mod == "none")
00113 {
00114 loadLocalModFile("data/accessories.xml", mod);
00115 loadLocalModFile("data/modinfo.xml", mod);
00116 loadLocalModFile("data/landscapes.xml", mod);
00117
00118 const char *landscapesBase = "data/landscapes";
00119 std::string dir = S3D::getDataFile(landscapesBase);
00120 FileList fList(dir, "*.xml", true);
00121 std::list<std::string> &files = fList.getFiles();
00122 std::list<std::string>::iterator itor;
00123 for (itor = files.begin();
00124 itor != files.end();
00125 itor++)
00126 {
00127 char *file = (char *) (*itor).c_str();
00128 file += dir.size() - strlen(landscapesBase);
00129 loadLocalModFile(file, mod);
00130 }
00131 }
00132
00133 {
00134 unsigned int totalCompSize = 0, totalSize = 0;
00135 std::map<std::string, ModFileEntry *>::iterator itor;
00136 for (itor = files_.begin();
00137 itor != files_.end();
00138 itor++)
00139 {
00140 ModFileEntry *entry = (*itor).second;
00141 totalCompSize += entry->getCompressedSize();
00142 totalSize += entry->getUncompressedSize();
00143 }
00144
00145 Logger::log(S3D::formatStringBuffer("Loaded mod \"%s\", %u files, space required %u (%u) bytes",
00146 mod.c_str(), files_.size(), totalCompSize, totalSize));
00147
00148 if (!createDir && files_.empty())
00149 {
00150 std::string modFile = S3D::getModFile(mod);
00151 std::string globalModFile = S3D::getGlobalModFile(mod);
00152 S3D::dialogMessage("Mod", S3D::formatStringBuffer(
00153 "Failed to find \"%s\" mod files in directories \"%s\" \"%s\"",
00154 mod.c_str(),
00155 modFile.c_str(),
00156 globalModFile.c_str()));
00157 return false;
00158 }
00159 }
00160
00161 return true;
00162 }
00163
00164 bool ModFiles::loadLocalModFile(const std::string &local,
00165 const std::string &mod)
00166 {
00167 std::string dataFile = S3D::getDataFile(local);
00168 std::string modDirStr(dataFile.c_str());
00169 char *modDir = (char *) modDirStr.c_str();
00170 modDir[dataFile.size() - local.size()] = '\0';
00171
00172 return loadModFile(dataFile, modDir, mod);
00173 }
00174
00175 bool ModFiles::loadModDir(const std::string &modDir,
00176 const std::string &mod, ProgressCounter *counter)
00177 {
00178
00179 FileList allfiles(modDir, "*", true, true);
00180 FileList::ListType &files = allfiles.getFiles();
00181 FileList::ListType::iterator itor;
00182
00183 int i = 0;
00184 for (itor = files.begin();
00185 itor != files.end();
00186 itor++, i++)
00187 {
00188 if (counter) counter->setNewPercentage(float(i)
00189 / float(files.size()) * 100.0f);
00190
00191
00192 std::string &fileName = (*itor);
00193 if (!loadModFile(fileName, modDir, mod))
00194 {
00195 return false;
00196 }
00197 }
00198
00199 return true;
00200 }
00201
00202 bool ModFiles::loadModFile(const std::string &fullFileName,
00203 const std::string &modDir, const std::string &mod)
00204 {
00205 std::string shortFileNameStr(fullFileName.c_str());
00206 S3D::fileDos2Unix(shortFileNameStr);
00207 const char *shortFileName = shortFileNameStr.c_str();
00208
00209
00210 if (excludeFile(fullFileName)) return true;
00211
00212
00213
00214 int modDirLen = modDir.size();
00215 shortFileName += modDirLen;
00216 while (shortFileName[0] == '/') shortFileName++;
00217
00218
00219 std::string oldFileName(shortFileName);
00220 _strlwr((char *) shortFileName);
00221 if (strcmp(oldFileName.c_str(), shortFileName) != 0)
00222 {
00223 S3D::dialogMessage("Mod", S3D::formatStringBuffer(
00224 "ERROR: All mod files must have lower case filenames.\n"
00225 "File \"%s,%s\" has upper case charaters in it",
00226 oldFileName.c_str(),
00227 shortFileName));
00228 return false;
00229 }
00230
00231
00232 if (files_.find(shortFileName) != files_.end()) return true;
00233
00234
00235 ModFileEntry *file = new ModFileEntry();
00236 if (!file->loadModFile(fullFileName))
00237 {
00238 S3D::dialogMessage("Mod", S3D::formatStringBuffer(
00239 "Error: Failed to load file \"%s\" mod directory \"%s\" in the \"%s\" mod",
00240 fullFileName.c_str(),
00241 modDir.c_str(),
00242 mod.c_str()));
00243 return false;
00244 }
00245
00246
00247 file->setFileName(shortFileName);
00248 files_[shortFileName] = file;
00249 return true;
00250 }
00251
00252 bool ModFiles::writeModFiles(const std::string &mod)
00253 {
00254 std::string modDir = S3D::getModFile(mod);
00255 if (!S3D::dirExists(modDir))
00256 {
00257 S3D::dirMake(modDir);
00258 }
00259
00260 std::map<std::string, ModFileEntry *>::iterator itor;
00261 for (itor = files_.begin();
00262 itor != files_.end();
00263 itor++)
00264 {
00265 ModFileEntry *entry = (*itor).second;
00266 if (!entry->writeModFile(entry->getFileName(), mod)) return false;
00267 }
00268 return true;
00269 }
00270
00271 void ModFiles::clearData()
00272 {
00273 std::map<std::string, ModFileEntry *>::iterator itor;
00274 for (itor = files_.begin();
00275 itor != files_.end();
00276 itor++)
00277 {
00278 ModFileEntry *entry = (*itor).second;
00279 entry->getCompressedBuffer().clear();
00280 }
00281 }
00282
00283 bool ModFiles::exportModFiles(const std::string &mod, const std::string &fileName)
00284 {
00285 FILE *out = fopen(fileName.c_str(), "wb");
00286 if (!out) return false;
00287
00288
00289 NetBuffer tmpBuffer;
00290 tmpBuffer.reset();
00291 tmpBuffer.addToBuffer(S3D::ScorchedProtocolVersion);
00292 tmpBuffer.addToBuffer(mod);
00293 fwrite(tmpBuffer.getBuffer(),
00294 sizeof(unsigned char),
00295 tmpBuffer.getBufferUsed(),
00296 out);
00297
00298
00299 std::map<std::string, ModFileEntry *>::iterator itor;
00300 for (itor = files_.begin();
00301 itor != files_.end();
00302 itor++)
00303 {
00304 ModFileEntry *entry = (*itor).second;
00305
00306 tmpBuffer.reset();
00307 tmpBuffer.addToBuffer(entry->getFileName());
00308 tmpBuffer.addToBuffer(entry->getUncompressedSize());
00309 tmpBuffer.addToBuffer(entry->getCompressedBuffer().getBufferUsed());
00310 tmpBuffer.addToBuffer(entry->getCompressedCrc());
00311 tmpBuffer.addDataToBuffer(entry->getCompressedBuffer().getBuffer(),
00312 entry->getCompressedBuffer().getBufferUsed());
00313
00314 fwrite(tmpBuffer.getBuffer(),
00315 sizeof(unsigned char),
00316 tmpBuffer.getBufferUsed(),
00317 out);
00318 }
00319
00320
00321 tmpBuffer.reset();
00322 tmpBuffer.addToBuffer("*");
00323 fwrite(tmpBuffer.getBuffer(),
00324 sizeof(unsigned char),
00325 tmpBuffer.getBufferUsed(),
00326 out);
00327
00328 fclose(out);
00329 return true;
00330 }
00331
00332 bool ModFiles::importModFiles(std::string &mod, const std::string &fileName)
00333 {
00334 FILE *in = fopen(fileName.c_str(), "rb");
00335 if (!in) return false;
00336
00337
00338 NetBuffer tmpBuffer;
00339 unsigned char readBuf[512];
00340 while (unsigned int size = fread(readBuf, sizeof(unsigned char), 512, in))
00341 {
00342 tmpBuffer.addDataToBuffer(readBuf, size);
00343 }
00344 fclose(in);
00345 return importModFiles(mod, tmpBuffer);
00346 }
00347
00348 bool ModFiles::importModFiles(std::string &mod, NetBuffer &tmpBuffer)
00349 {
00350
00351 static std::string modName;
00352 std::string version;
00353 NetBufferReader tmpReader(tmpBuffer);
00354 if (!tmpReader.getFromBuffer(version)) return false;
00355 if (!tmpReader.getFromBuffer(modName)) return false;
00356 mod = modName;
00357
00358 if (version != S3D::ScorchedProtocolVersion)
00359 {
00360 S3D::dialogMessage("Scorched3D", S3D::formatStringBuffer(
00361 "Failed to import mod, scorched version differs.\n"
00362 "Please obtain a newer version of this mod.\n"
00363 "Import version = %s\n"
00364 "Current version = %s\n",
00365 version.c_str(),
00366 S3D::ScorchedProtocolVersion.c_str()));
00367 return false;
00368 }
00369
00370 for (;;)
00371 {
00372
00373 std::string name;
00374 if (!tmpReader.getFromBuffer(name)) return false;
00375 if (0 == strcmp(name.c_str(), "*")) break;
00376
00377
00378 unsigned int unCompressedSize;
00379 unsigned int compressedSize;
00380 unsigned int compressedCrc;
00381 tmpReader.getFromBuffer(unCompressedSize);
00382 tmpReader.getFromBuffer(compressedSize);
00383 tmpReader.getFromBuffer(compressedCrc);
00384
00385
00386 ModFileEntry *entry = new ModFileEntry;
00387 entry->setFileName(name.c_str());
00388 entry->setCompressedCrc(compressedCrc);
00389 entry->setUncompressedSize(unCompressedSize);
00390 entry->getCompressedBuffer().allocate(compressedSize);
00391 entry->getCompressedBuffer().setBufferUsed(compressedSize);
00392 tmpReader.getDataFromBuffer(
00393 entry->getCompressedBuffer().getBuffer(),
00394 compressedSize);
00395 files_[name] = entry;
00396 }
00397
00398 return true;
00399 }