示例#1
0
文件: esmtool.cpp 项目: eroen/openmw
int clone(Arguments& info)
{
    if (info.outname.empty())
    {
        std::cout << "You need to specify an output name" << std::endl;
        return 1;
    }

    if (load(info) != 0)
    {
        std::cout << "Failed to load, aborting." << std::endl;
        return 1;
    }

    int recordCount = info.data.mRecords.size();

    int digitCount = 1; // For a nicer output
    if (recordCount > 9) ++digitCount;
    if (recordCount > 99) ++digitCount;
    if (recordCount > 999) ++digitCount;
    if (recordCount > 9999) ++digitCount;
    if (recordCount > 99999) ++digitCount;
    if (recordCount > 999999) ++digitCount;

    std::cout << "Loaded " << recordCount << " records:" << std::endl << std::endl;

    ESM::NAME name;

    int i = 0;
    typedef std::map<int, int> Stats;
    Stats &stats = info.data.mRecordStats;
    for (Stats::iterator it = stats.begin(); it != stats.end(); ++it)
    {
        name.val = it->first;
        float amount = it->second;
        std::cout << std::setw(digitCount) << amount << " " << name.toString() << "  ";

        if (++i % 3 == 0)
            std::cout << std::endl;
    }

    if (i % 3 != 0)
        std::cout << std::endl;

    std::cout << std::endl << "Saving records to: " << info.outname << "..." << std::endl;

    ESM::ESMWriter& esm = info.writer;
    ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding));
    esm.setEncoder(&encoder);
    esm.setAuthor(info.data.author);
    esm.setDescription(info.data.description);
    esm.setVersion(info.data.version);
    esm.setRecordCount (recordCount);

    for (std::vector<ESM::Header::MasterData>::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
        esm.addMaster(it->name, it->size);

    std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);
    esm.save(save);

    int saved = 0;
    typedef std::deque<EsmTool::RecordBase *> Records;
    Records &records = info.data.mRecords;
    for (Records::iterator it = records.begin(); it != records.end() && i > 0; ++it)
    {
        EsmTool::RecordBase *record = *it;

        name.val = record->getType().val;

        esm.startRecord(name.toString(), record->getFlags());

        // TODO wrap this with std::set
        if (ESMData::sLabeledRec.count(name.val) > 0) {
            esm.writeHNCString("NAME", record->getId());
        } else {
            esm.writeHNOString("NAME", record->getId());
        }

        record->save(esm);

        if (name.val == ESM::REC_CELL) {
            ESM::Cell *ptr = &record->cast<ESM::Cell>()->get();
            if (!info.data.mCellRefs[ptr].empty()) {
                typedef std::deque<ESM::CellRef> RefList;
                RefList &refs = info.data.mCellRefs[ptr];
                for (RefList::iterator it = refs.begin(); it != refs.end(); ++it)
                {
                    it->save(esm);
                }
            }
        }

        esm.endRecord(name.toString());

        saved++;
        int perc = (saved / (float)recordCount)*100;
        if (perc % 10 == 0)
        {
            std::cerr << "\r" << perc << "%";
        }
    }

    std::cout << "\rDone!" << std::endl;

    esm.close();
    save.close();

    return 0;
}
示例#2
0
int load(Arguments& info)
{
    ESM::ESMReader& esm = info.reader;
    ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding));
    esm.setEncoder(&encoder);

    std::string filename = info.filename;
    std::cout << "Loading file: " << filename << std::endl;

    std::list<int> skipped;

    try {

        if(info.raw_given && info.mode == "dump")
        {
            std::cout << "RAW file listing:\n";

            esm.openRaw(filename);

            printRaw(esm);

            return 0;
        }

        bool quiet = (info.quiet_given || info.mode == "clone");
        bool loadCells = (info.loadcells_given || info.mode == "clone");
        bool save = (info.mode == "clone");

        esm.open(filename);

        info.data.author = esm.getAuthor();
        info.data.description = esm.getDesc();
        info.data.masters = esm.getGameFiles();

        if (!quiet)
        {
            std::cout << "Author: " << esm.getAuthor() << std::endl
                 << "Description: " << esm.getDesc() << std::endl
                 << "File format version: " << esm.getFVer() << std::endl;
            std::vector<ESM::Header::MasterData> m = esm.getGameFiles();
            if (!m.empty())
            {
                std::cout << "Masters:" << std::endl;
                for(unsigned int i=0;i<m.size();i++)
                    std::cout << "  " << m[i].name << ", " << m[i].size << " bytes" << std::endl;
            }
        }

        // Loop through all records
        while(esm.hasMoreRecs())
        {
            ESM::NAME n = esm.getRecName();
            uint32_t flags;
            esm.getRecHeader(flags);

            EsmTool::RecordBase *record = EsmTool::RecordBase::create(n);
            if (record == 0) 
            {
                if (std::find(skipped.begin(), skipped.end(), n.val) == skipped.end())
                {
                    std::cout << "Skipping " << n.toString() << " records." << std::endl;
                    skipped.push_back(n.val);
                }

                esm.skipRecord();
                if (quiet) break;
                std::cout << "  Skipping\n";

                continue;
            }

            record->setFlags(static_cast<int>(flags));
            record->setPrintPlain(info.plain_given);
            record->load(esm);

            // Is the user interested in this record type?
            bool interested = true;
            if (!info.types.empty())
            {
                std::vector<std::string>::iterator match;
                match = std::find(info.types.begin(), info.types.end(), n.toString());
                if (match == info.types.end()) interested = false;
            }

            if (!info.name.empty() && !Misc::StringUtils::ciEqual(info.name, record->getId()))
                interested = false;

            if(!quiet && interested)
            {
                std::cout << "\nRecord: " << n.toString() << " '" << record->getId() << "'\n";
                record->print();
            }

            if (record->getType().val == ESM::REC_CELL && loadCells && interested) 
            {
                loadCell(record->cast<ESM::Cell>()->get(), esm, info);
            }

            if (save) 
            {
                info.data.mRecords.push_back(record);
            } 
            else 
            {
                delete record;
            }
            ++info.data.mRecordStats[n.val];
        }

    } catch(std::exception &e) {
        std::cout << "\nERROR:\n\n  " << e.what() << std::endl;

        typedef std::deque<EsmTool::RecordBase *> RecStore;
        RecStore &store = info.data.mRecords;
        for (RecStore::iterator it = store.begin(); it != store.end(); ++it)
        {
            delete *it;
        }
        store.clear();
        return 1;
    }

    return 0;
}