mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-11-03 23:56:47 +00:00 
			
		
		
		
	Working on making output identical to input.
This commit is contained in:
		
							parent
							
								
									290d09de64
								
							
						
					
					
						commit
						f16a9ce5ed
					
				
					 7 changed files with 150 additions and 70 deletions
				
			
		| 
						 | 
					@ -19,13 +19,13 @@ namespace bpo = boost::program_options;
 | 
				
			||||||
struct ESMData
 | 
					struct ESMData
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::string author;
 | 
					    std::string author;
 | 
				
			||||||
    std::string description;
 | 
					    string description;
 | 
				
			||||||
    int version;
 | 
					    int version;
 | 
				
			||||||
    int type;
 | 
					    int type;
 | 
				
			||||||
    ESMReader::MasterList masters;
 | 
					    ESMReader::MasterList masters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::list<Record*> records;
 | 
					    list<Record*> records;
 | 
				
			||||||
    std::map<Record*, std::list<CellRef> > cellRefs;
 | 
					    map<Record*, list<CellRef> > cellRefs;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Based on the legacy struct
 | 
					// Based on the legacy struct
 | 
				
			||||||
| 
						 | 
					@ -35,17 +35,17 @@ struct Arguments
 | 
				
			||||||
    unsigned int quiet_given;
 | 
					    unsigned int quiet_given;
 | 
				
			||||||
    unsigned int loadcells_given;
 | 
					    unsigned int loadcells_given;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string mode;
 | 
					    string mode;
 | 
				
			||||||
    std::string encoding;
 | 
					    string encoding;
 | 
				
			||||||
    std::string filename;
 | 
					    string filename;
 | 
				
			||||||
    std::string outname;
 | 
					    string outname;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
    ESMData data;
 | 
					    ESMData data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool parseOptions (int argc, char** argv, Arguments &info)
 | 
					bool parseOptions (int argc, char** argv, Arguments &info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bpo::options_description desc("Inspect and extract from Morrowind ES files (ESM, ESP, ESS)\nSyntax: esmtool [options] mode infile [outfile]\nAllowed modes:\n  dump\t Dumps all readable data from the input file\n  clone\t Clones the input file to the output file.\n\nAllowed options");
 | 
					    bpo::options_description desc("Inspect and extract from Morrowind ES files (ESM, ESP, ESS)\nSyntax: esmtool [options] mode infile [outfile]\nAllowed modes:\n  dump\t Dumps all readable data from the input file.\n  clone\t Clones the input file to the output file.\n  comp\t Compares the given files.\n\nAllowed options");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    desc.add_options()
 | 
					    desc.add_options()
 | 
				
			||||||
        ("help,h", "print help message.")
 | 
					        ("help,h", "print help message.")
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ bool parseOptions (int argc, char** argv, Arguments &info)
 | 
				
			||||||
        ("quiet,q", "Supress all record information. Useful for speed tests.")
 | 
					        ("quiet,q", "Supress all record information. Useful for speed tests.")
 | 
				
			||||||
        ("loadcells,C", "Browse through contents of all cells.")
 | 
					        ("loadcells,C", "Browse through contents of all cells.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ( "encoding,e", bpo::value<std::string>(&(info.encoding))->
 | 
					        ( "encoding,e", bpo::value<string>(&(info.encoding))->
 | 
				
			||||||
          default_value("win1252"),
 | 
					          default_value("win1252"),
 | 
				
			||||||
          "Character encoding used in ESMTool:\n"
 | 
					          "Character encoding used in ESMTool:\n"
 | 
				
			||||||
          "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n"
 | 
					          "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n"
 | 
				
			||||||
| 
						 | 
					@ -62,14 +62,14 @@ bool parseOptions (int argc, char** argv, Arguments &info)
 | 
				
			||||||
          "\n\twin1252 - Western European (Latin) alphabet, used by default")
 | 
					          "\n\twin1252 - Western European (Latin) alphabet, used by default")
 | 
				
			||||||
        ;
 | 
					        ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string finalText = "\nIf no option is given, the default action is to parse all records in the archive\nand display diagnostic information.";
 | 
					    string finalText = "\nIf no option is given, the default action is to parse all records in the archive\nand display diagnostic information.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // input-file is hidden and used as a positional argument
 | 
					    // input-file is hidden and used as a positional argument
 | 
				
			||||||
    bpo::options_description hidden("Hidden Options");
 | 
					    bpo::options_description hidden("Hidden Options");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hidden.add_options()
 | 
					    hidden.add_options()
 | 
				
			||||||
        ( "mode,m", bpo::value<std::string>(), "esmtool mode")
 | 
					        ( "mode,m", bpo::value<string>(), "esmtool mode")
 | 
				
			||||||
        ( "input-file,i", bpo::value< vector<std::string> >(), "input file")
 | 
					        ( "input-file,i", bpo::value< vector<string> >(), "input file")
 | 
				
			||||||
        ;
 | 
					        ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bpo::positional_options_description p;
 | 
					    bpo::positional_options_description p;
 | 
				
			||||||
| 
						 | 
					@ -87,70 +87,70 @@ bool parseOptions (int argc, char** argv, Arguments &info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (variables.count ("help"))
 | 
					    if (variables.count ("help"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << desc << finalText << std::endl;
 | 
					        cout << desc << finalText << endl;
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (variables.count ("version"))
 | 
					    if (variables.count ("version"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "ESMTool version " << ESMTOOL_VERSION << std::endl;
 | 
					        cout << "ESMTool version " << ESMTOOL_VERSION << endl;
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!variables.count("mode"))
 | 
					    if (!variables.count("mode"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "No mode specified!" << std::endl << std::endl
 | 
					        cout << "No mode specified!" << endl << endl
 | 
				
			||||||
                  << desc << finalText << std::endl;
 | 
					                  << desc << finalText << endl;
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info.mode = variables["mode"].as<std::string>();
 | 
					    info.mode = variables["mode"].as<string>();
 | 
				
			||||||
    if (!(info.mode == "dump" || info.mode == "clone"))
 | 
					    if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << std::endl << "ERROR: invalid mode \"" << info.mode << "\"" << std::endl << std::endl
 | 
					        cout << endl << "ERROR: invalid mode \"" << info.mode << "\"" << endl << endl
 | 
				
			||||||
                  << desc << finalText << std::endl;
 | 
					                  << desc << finalText << endl;
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( !variables.count("input-file") )
 | 
					    if ( !variables.count("input-file") )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "\nERROR: missing ES file\n\n";
 | 
					        cout << "\nERROR: missing ES file\n\n";
 | 
				
			||||||
        std::cout << desc << finalText << std::endl;
 | 
					        cout << desc << finalText << endl;
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // handling gracefully the user adding multiple files
 | 
					    // handling gracefully the user adding multiple files
 | 
				
			||||||
/*    if (variables["input-file"].as< vector<std::string> >().size() > 1)
 | 
					/*    if (variables["input-file"].as< vector<string> >().size() > 1)
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
      std::cout << "\nERROR: more than one ES file specified\n\n";
 | 
					      cout << "\nERROR: more than one ES file specified\n\n";
 | 
				
			||||||
      std::cout << desc << finalText << std::endl;
 | 
					      cout << desc << finalText << endl;
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
      }*/
 | 
					      }*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info.filename = variables["input-file"].as< vector<std::string> >()[0];
 | 
					    info.filename = variables["input-file"].as< vector<string> >()[0];
 | 
				
			||||||
    if (variables["input-file"].as< vector<std::string> >().size() > 1)
 | 
					    if (variables["input-file"].as< vector<string> >().size() > 1)
 | 
				
			||||||
        info.outname = variables["input-file"].as< vector<std::string> >()[1];
 | 
					        info.outname = variables["input-file"].as< vector<string> >()[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info.raw_given = variables.count ("raw");
 | 
					    info.raw_given = variables.count ("raw");
 | 
				
			||||||
    info.quiet_given = variables.count ("quiet");
 | 
					    info.quiet_given = variables.count ("quiet");
 | 
				
			||||||
    info.loadcells_given = variables.count ("loadcells");
 | 
					    info.loadcells_given = variables.count ("loadcells");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Font encoding settings
 | 
					    // Font encoding settings
 | 
				
			||||||
    info.encoding = variables["encoding"].as<std::string>();
 | 
					    info.encoding = variables["encoding"].as<string>();
 | 
				
			||||||
    if (info.encoding == "win1250")
 | 
					    if (info.encoding == "win1250")
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "Using Central and Eastern European font encoding." << std::endl;
 | 
					        cout << "Using Central and Eastern European font encoding." << endl;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (info.encoding == "win1251")
 | 
					    else if (info.encoding == "win1251")
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "Using Cyrillic font encoding." << std::endl;
 | 
					        cout << "Using Cyrillic font encoding." << endl;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if(info.encoding != "win1252")
 | 
					        if(info.encoding != "win1252")
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::cout << info.encoding << " is not a valid encoding option." << std::endl;
 | 
					            cout << info.encoding << " is not a valid encoding option." << endl;
 | 
				
			||||||
            info.encoding = "win1252";
 | 
					            info.encoding = "win1252";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        std::cout << "Using default (English) font encoding." << std::endl;
 | 
					        cout << "Using default (English) font encoding." << endl;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
| 
						 | 
					@ -161,6 +161,7 @@ void loadCell(Cell &cell, ESMReader &esm, Arguments& info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int load(Arguments& info);
 | 
					int load(Arguments& info);
 | 
				
			||||||
int clone(Arguments& info);
 | 
					int clone(Arguments& info);
 | 
				
			||||||
 | 
					int comp(Arguments& info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char**argv)
 | 
					int main(int argc, char**argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -172,6 +173,8 @@ int main(int argc, char**argv)
 | 
				
			||||||
        return load(info);
 | 
					        return load(info);
 | 
				
			||||||
    else if (info.mode == "clone")
 | 
					    else if (info.mode == "clone")
 | 
				
			||||||
        return clone(info);
 | 
					        return clone(info);
 | 
				
			||||||
 | 
					    else if (info.mode == "comp")
 | 
				
			||||||
 | 
					        return comp(info);
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        cout << "Invalid or no mode specified, dying horribly. Have a nice day." << endl;
 | 
					        cout << "Invalid or no mode specified, dying horribly. Have a nice day." << endl;
 | 
				
			||||||
| 
						 | 
					@ -231,9 +234,9 @@ int load(Arguments& info)
 | 
				
			||||||
    esm.setEncoding(info.encoding);
 | 
					    esm.setEncoding(info.encoding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    string filename = info.filename;
 | 
					    string filename = info.filename;
 | 
				
			||||||
    cout << "\nFile: " << filename << endl;
 | 
					    cout << "Loading file: " << filename << endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::list<int> skipped;
 | 
					    list<int> skipped;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -734,7 +737,7 @@ int load(Arguments& info)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        cout << "\nERROR:\n\n  " << e.what() << endl;
 | 
					        cout << "\nERROR:\n\n  " << e.what() << endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (std::list<Record*>::iterator it = info.data.records.begin(); it != info.data.records.end();)
 | 
					        for (list<Record*>::iterator it = info.data.records.begin(); it != info.data.records.end();)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            delete *it;
 | 
					            delete *it;
 | 
				
			||||||
            info.data.records.erase(it++);
 | 
					            info.data.records.erase(it++);
 | 
				
			||||||
| 
						 | 
					@ -773,9 +776,9 @@ int clone(Arguments& info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cout << "Loaded " << recordCount << " records:" << endl << endl;
 | 
					    cout << "Loaded " << recordCount << " records:" << endl << endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::map<std::string, int> records;
 | 
					    map<string, int> records;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (std::list<Record*>::iterator it = info.data.records.begin(); it != info.data.records.end(); ++it)
 | 
					    for (list<Record*>::iterator it = info.data.records.begin(); it != info.data.records.end(); ++it)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Record* rec = *it;
 | 
					        Record* rec = *it;
 | 
				
			||||||
        NAME n;
 | 
					        NAME n;
 | 
				
			||||||
| 
						 | 
					@ -784,9 +787,9 @@ int clone(Arguments& info)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int i = 0;
 | 
					    int i = 0;
 | 
				
			||||||
    for (std::map<std::string,int>::iterator it = records.begin(); it != records.end(); ++it)
 | 
					    for (map<string,int>::iterator it = records.begin(); it != records.end(); ++it)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::string n = it->first;
 | 
					        string n = it->first;
 | 
				
			||||||
        float amount = it->second;
 | 
					        float amount = it->second;
 | 
				
			||||||
        cout << setw(digitCount) << amount << " " << n << "  ";
 | 
					        cout << setw(digitCount) << amount << " " << n << "  ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -808,11 +811,11 @@ int clone(Arguments& info)
 | 
				
			||||||
    for (ESMReader::MasterList::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
 | 
					    for (ESMReader::MasterList::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
 | 
				
			||||||
        esm.addMaster(it->name, it->size);
 | 
					        esm.addMaster(it->name, it->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);
 | 
					    fstream save(info.outname.c_str(), fstream::out | fstream::binary);
 | 
				
			||||||
    esm.save(save);
 | 
					    esm.save(save);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int saved = 0;
 | 
					    int saved = 0;
 | 
				
			||||||
    for (std::list<Record*>::iterator it = info.data.records.begin(); it != info.data.records.end() && i > 0; ++it)
 | 
					    for (list<Record*>::iterator it = info.data.records.begin(); it != info.data.records.end() && i > 0; ++it)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Record* rec = *it;
 | 
					        Record* rec = *it;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -820,14 +823,18 @@ int clone(Arguments& info)
 | 
				
			||||||
        n.val = rec->getName();
 | 
					        n.val = rec->getName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        esm.startRecord(n.toString(), 0);
 | 
					        esm.startRecord(n.toString(), 0);
 | 
				
			||||||
        std::string id = rec->getId();
 | 
					        string id = rec->getId();
 | 
				
			||||||
        esm.writeHNOString("NAME", id);
 | 
					
 | 
				
			||||||
 | 
					        if (n.val == REC_GLOB || n.val == REC_CLAS || n.val == REC_FACT || n.val == REC_RACE)
 | 
				
			||||||
 | 
					            esm.writeHNCString("NAME", id);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            esm.writeHNOString("NAME", id);
 | 
				
			||||||
        rec->save(esm);
 | 
					        rec->save(esm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (n.val == REC_CELL && !info.data.cellRefs[rec].empty())
 | 
					        if (n.val == REC_CELL && !info.data.cellRefs[rec].empty())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::list<CellRef>& refs = info.data.cellRefs[rec];
 | 
					            list<CellRef>& refs = info.data.cellRefs[rec];
 | 
				
			||||||
            for (std::list<CellRef>::iterator it = refs.begin(); it != refs.end(); ++it)
 | 
					            for (list<CellRef>::iterator it = refs.begin(); it != refs.end(); ++it)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                it->save(esm);
 | 
					                it->save(esm);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -848,5 +855,52 @@ int clone(Arguments& info)
 | 
				
			||||||
    esm.close();
 | 
					    esm.close();
 | 
				
			||||||
    save.close();
 | 
					    save.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int comp(Arguments& info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (info.filename.empty() || info.outname.empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cout << "You need to specify two input files" << endl;
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Arguments fileOne;
 | 
				
			||||||
 | 
					    Arguments fileTwo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fileOne.raw_given = 0;
 | 
				
			||||||
 | 
					    fileTwo.raw_given = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fileOne.mode = "clone";
 | 
				
			||||||
 | 
					    fileTwo.mode = "clone";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fileOne.encoding = info.encoding;
 | 
				
			||||||
 | 
					    fileTwo.encoding = info.encoding;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    fileOne.filename = info.filename;
 | 
				
			||||||
 | 
					    fileTwo.filename = info.outname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (load(fileOne) != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cout << "Failed to load " << info.filename << ", aborting comparison." << endl;
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (load(fileTwo) != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cout << "Failed to load " << info.outname << ", aborting comparison." << endl;
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (fileOne.data.records.size() != fileTwo.data.records.size())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cout << "Not equal, different amount of records." << endl;
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,12 +53,14 @@ void ESMWriter::save(const std::string& file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ESMWriter::save(std::ostream& file)
 | 
					void ESMWriter::save(std::ostream& file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    m_recordCount = 0;
 | 
				
			||||||
    m_stream = &file;
 | 
					    m_stream = &file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    startRecord("TES3", 0);
 | 
					    startRecord("TES3", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_header.records = 0;
 | 
					    m_header.records = 0;
 | 
				
			||||||
    writeHNT("HEDR", m_header, 300);
 | 
					    writeHNT("HEDR", m_header, 300);
 | 
				
			||||||
 | 
					    m_headerPos = m_stream->tellp() - (std::streampos)4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (std::list<MasterData>::iterator it = m_masters.begin(); it != m_masters.end(); ++it)
 | 
					    for (std::list<MasterData>::iterator it = m_masters.begin(); it != m_masters.end(); ++it)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -71,6 +73,10 @@ void ESMWriter::save(std::ostream& file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ESMWriter::close()
 | 
					void ESMWriter::close()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    std::cout << "Writing amount of saved records (" << m_recordCount - 1 << ")" << std::endl;
 | 
				
			||||||
 | 
					    m_stream->seekp(m_headerPos);
 | 
				
			||||||
 | 
					    writeT<int>(m_recordCount-1);
 | 
				
			||||||
 | 
					    m_stream->seekp(0, std::ios::end);
 | 
				
			||||||
    m_stream->flush();
 | 
					    m_stream->flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!m_records.empty())
 | 
					    if (!m_records.empty())
 | 
				
			||||||
| 
						 | 
					@ -79,6 +85,8 @@ void ESMWriter::close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
 | 
					void ESMWriter::startRecord(const std::string& name, uint32_t flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    m_recordCount++;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    writeName(name);
 | 
					    writeName(name);
 | 
				
			||||||
    RecordData rec;
 | 
					    RecordData rec;
 | 
				
			||||||
    rec.name = name;
 | 
					    rec.name = name;
 | 
				
			||||||
| 
						 | 
					@ -128,6 +136,21 @@ void ESMWriter::writeHNString(const std::string& name, const std::string& data)
 | 
				
			||||||
    endRecord(name);
 | 
					    endRecord(name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void ESMWriter::writeHNString(const std::string& name, const std::string& data, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    assert(data.size() <= size);
 | 
				
			||||||
 | 
					    startSubRecord(name);
 | 
				
			||||||
 | 
					    writeHString(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (data.size() < size)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = data.size(); i < size; ++i)
 | 
				
			||||||
 | 
					            write("\0",1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    endRecord(name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ESMWriter::writeHString(const std::string& data)
 | 
					void ESMWriter::writeHString(const std::string& data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (data.size() == 0)
 | 
					    if (data.size() == 0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,15 @@ public:
 | 
				
			||||||
    void close();
 | 
					    void close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void writeHNString(const std::string& name, const std::string& data);
 | 
					    void writeHNString(const std::string& name, const std::string& data);
 | 
				
			||||||
 | 
					    void writeHNString(const std::string& name, const std::string& data, int size);
 | 
				
			||||||
 | 
					    void writeHNCString(const std::string& name, const std::string& data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        startSubRecord(name);
 | 
				
			||||||
 | 
					        writeHString(data);
 | 
				
			||||||
 | 
					        if (data.size() > 0 && data[data.size()-1] != '\0')
 | 
				
			||||||
 | 
					            write("\0", 1);
 | 
				
			||||||
 | 
					        endRecord(name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    void writeHNOString(const std::string& name, const std::string& data)
 | 
					    void writeHNOString(const std::string& name, const std::string& data)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!data.empty())
 | 
					        if (!data.empty())
 | 
				
			||||||
| 
						 | 
					@ -56,20 +65,6 @@ public:
 | 
				
			||||||
        endRecord(name);
 | 
					        endRecord(name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*template<typename T>
 | 
					 | 
				
			||||||
    void writeHT(const T& data)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        writeT((unsigned int)sizeof(T));
 | 
					 | 
				
			||||||
        writeT(data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    template<typename T>
 | 
					 | 
				
			||||||
    void writeHT(const T& data, int size)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        assert(sizeof(T) == size);
 | 
					 | 
				
			||||||
        writeHT(data);
 | 
					 | 
				
			||||||
        }*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    template<typename T>
 | 
					    template<typename T>
 | 
				
			||||||
    void writeT(const T& data)
 | 
					    void writeT(const T& data)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -93,6 +88,8 @@ private:
 | 
				
			||||||
    std::list<MasterData> m_masters;
 | 
					    std::list<MasterData> m_masters;
 | 
				
			||||||
    std::list<RecordData> m_records;
 | 
					    std::list<RecordData> m_records;
 | 
				
			||||||
    std::ostream* m_stream;
 | 
					    std::ostream* m_stream;
 | 
				
			||||||
 | 
					    std::streampos m_headerPos;
 | 
				
			||||||
 | 
					    int m_recordCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    HEDRstruct m_header;
 | 
					    HEDRstruct m_header;
 | 
				
			||||||
    SaveData m_saveData;
 | 
					    SaveData m_saveData;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ void Class::load(ESMReader &esm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void Class::save(ESMWriter &esm)
 | 
					void Class::save(ESMWriter &esm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    esm.writeHNString("FNAM", name);
 | 
					    esm.writeHNCString("FNAM", name);
 | 
				
			||||||
    esm.writeHNT("CLDT", data, 60);
 | 
					    esm.writeHNT("CLDT", data, 60);
 | 
				
			||||||
    esm.writeHNOString("DESC", description);
 | 
					    esm.writeHNOString("DESC", description);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,11 +29,14 @@ void Faction::load(ESMReader &esm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void Faction::save(ESMWriter &esm)
 | 
					void Faction::save(ESMWriter &esm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    esm.writeHNString("FNAM", name);
 | 
					    esm.writeHNCString("FNAM", name);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for (int i = 0; i < 10; i++)
 | 
					    for (int i = 0; i < 10; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        esm.writeHNString("RNAM", ranks[i]);
 | 
					        if (ranks[i].empty())
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        esm.writeHNString("RNAM", ranks[i], 32);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    esm.writeHNT("FADT", data, 240);
 | 
					    esm.writeHNT("FADT", data, 240);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ void Race::load(ESMReader &esm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void Race::save(ESMWriter &esm)
 | 
					void Race::save(ESMWriter &esm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    esm.writeHNString("FNAM", name);
 | 
					    esm.writeHNCString("FNAM", name);
 | 
				
			||||||
    esm.writeHNT("RADT", data, 140);
 | 
					    esm.writeHNT("RADT", data, 140);
 | 
				
			||||||
    powers.save(esm);
 | 
					    powers.save(esm);
 | 
				
			||||||
    esm.writeHNOString("DESC", description);
 | 
					    esm.writeHNOString("DESC", description);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,19 +40,22 @@ void Script::load(ESMReader &esm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void Script::save(ESMWriter &esm)
 | 
					void Script::save(ESMWriter &esm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    esm.writeHNT("SCHD", data, 52);
 | 
					    std::string varNameString;
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (!varNames.empty())
 | 
					    if (!varNames.empty())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        esm.startSubRecord("SCVR");
 | 
					 | 
				
			||||||
        for (std::vector<std::string>::iterator it = varNames.begin(); it != varNames.end(); ++it)
 | 
					        for (std::vector<std::string>::iterator it = varNames.begin(); it != varNames.end(); ++it)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            esm.writeT(it->c_str(), it->size());
 | 
					            varNameString.append(*it);
 | 
				
			||||||
            esm.writeT('\0');
 | 
					            //varNameString.append("\0");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        esm.endRecord("SCVR");
 | 
					
 | 
				
			||||||
 | 
					        data.stringTableSize = varNameString.size();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    esm.writeHNT("SCHD", data, 52);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    esm.writeHNOString("SCVR", varNameString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    esm.writeHNString("SCDT", std::string(&scriptData[0], scriptData.size()));
 | 
					    esm.writeHNString("SCDT", std::string(&scriptData[0], scriptData.size()));
 | 
				
			||||||
    esm.writeHNOString("SCTX", scriptText);
 | 
					    esm.writeHNOString("SCTX", scriptText);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue