unsigned CArchiveBase::GetCrc32(unsigned fid) { CRC crc; std::vector<boost::uint8_t> buffer; if (GetFile(fid, buffer)) crc.Update(&buffer[0], buffer.size()); return crc.GetDigest(); }
unsigned int IArchive::GetCrc32(unsigned int fid) { CRC crc; std::vector<std::uint8_t> buffer; if (GetFile(fid, buffer) && !buffer.empty()) crc.Update(&buffer[0], buffer.size()); return crc.GetDigest(); }
unsigned int CArchiveBase::GetCrc32(const std::string& fileName) { CRC crc; unsigned char buffer [65536]; int handle; int maxRead; int total = 0; handle = this->OpenFile(fileName); if (handle == 0) return crc.GetDigest(); do { maxRead = this->ReadFile(handle, &buffer, sizeof(buffer)); crc.Update(buffer, maxRead); total += maxRead; } while (maxRead == sizeof(buffer)); this->CloseFile(handle); return crc.GetDigest(); };
/** * Get CRC of the data in the specified archive. * Returns 0 if file could not be opened. */ unsigned int CArchiveScanner::GetCRC(const std::string& arcName) { CRC crc; CArchiveBase* ar; std::list<std::string> files; //! Try to open an archive ar = CArchiveFactory::OpenArchive(arcName); if (!ar) { return 0; // It wasn't an archive } //! Load ignore list. IFileFilter* ignore = CreateIgnoreFilter(ar); for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { std::string name; int size; ar->FileInfo(fid, name, size); if (ignore->Match(name)) { continue; } StringToLowerInPlace(name); //! case insensitive hash files.push_back(name); } files.sort(); //! Add all files in sorted order for (std::list<std::string>::iterator i = files.begin(); i != files.end(); ++i) { const unsigned int nameCRC = CRC().Update(i->data(), i->size()).GetDigest(); const unsigned fid = ar->FindFile(*i); const unsigned int dataCRC = ar->GetCrc32(fid); crc.Update(nameCRC); crc.Update(dataCRC); } delete ignore; delete ar; unsigned int digest = crc.GetDigest(); //! A value of 0 is used to indicate no crc.. so never return that //! Shouldn't happen all that often if (digest == 0) { return 4711; } else { return digest; } }
/** Get CRC of the data in the specified archive. Returns 0 if file could not be opened. */ unsigned int CArchiveScanner::GetCRC(const string& arcName) { CRC crc; CArchiveBase* ar; std::list<string> files; // Try to open an archive ar = CArchiveFactory::OpenArchive(arcName); if (!ar) { return 0; // It wasn't an archive } // Load ignore list. IFileFilter* ignore = CreateIgnoreFilter(ar); string name; int size; // Sort all file paths for deterministic behaviour for (int cur = 0; (cur = ar->FindFiles(cur, &name, &size)); /* no-op */) { if (ignore->Match(name)) { continue; } const string lower = StringToLower(name); // case insensitive hash files.push_back(lower); } files.sort(); // Add all files in sorted order for (std::list<string>::iterator i = files.begin(); i != files.end(); i++ ) { const unsigned int nameCRC = CRC().Update(i->data(), i->size()).GetDigest(); const unsigned int dataCRC = ar->GetCrc32(*i); crc.Update(nameCRC); crc.Update(dataCRC); } delete ignore; delete ar; unsigned int digest = crc.GetDigest(); // A value of 0 is used to indicate no crc.. so never return that // Shouldn't happen all that often if (digest == 0) { return 4711; } else { return digest; } }
MoveDefHandler::MoveDefHandler(LuaParser* defsParser) { const LuaTable rootTable = defsParser->GetRoot().SubTable("MoveDefs"); if (!rootTable.IsValid()) throw content_error("Error loading movement definitions"); CRC crc; for (int tt = 0; tt < CMapInfo::NUM_TERRAIN_TYPES; ++tt) { const CMapInfo::TerrainType& terrType = mapInfo->terrainTypes[tt]; crc << terrType.tankSpeed << terrType.kbotSpeed; crc << terrType.hoverSpeed << terrType.shipSpeed; } moveDefs.reserve(rootTable.GetLength()); for (size_t num = 1; /* no test */; num++) { const LuaTable moveDefTable = rootTable.SubTable(num); if (!moveDefTable.IsValid()) { break; } moveDefs.emplace_back(moveDefTable, num); const MoveDef& md = moveDefs.back(); moveDefNames[md.name] = md.pathType; crc << md.GetCheckSum(); } CMoveMath::noHoverWaterMove = (mapInfo->water.damage >= MAX_ALLOWED_WATER_DAMAGE_HMM); CMoveMath::waterDamageCost = (mapInfo->water.damage >= MAX_ALLOWED_WATER_DAMAGE_GMM)? 0.0f: (1.0f / (1.0f + mapInfo->water.damage * 0.1f)); crc << CMoveMath::waterDamageCost; crc << CMoveMath::noHoverWaterMove; checksum = crc.GetDigest(); }
CMoveInfo::CMoveInfo() { const LuaTable rootTable = game->defsParser->GetRoot().SubTable("MoveDefs"); if (!rootTable.IsValid()) { throw content_error("Error loading movement definitions"); } groundMoveMath = new CGroundMoveMath(); hoverMoveMath = new CHoverMoveMath(); seaMoveMath = new CShipMoveMath(); CRC crc; for (int tt = 0; tt < CMapInfo::NUM_TERRAIN_TYPES; ++tt) { const CMapInfo::TerrainType& terrType = mapInfo->terrainTypes[tt]; crc << terrType.tankSpeed << terrType.kbotSpeed; crc << terrType.hoverSpeed << terrType.shipSpeed; } for (size_t num = 1; /* no test */; num++) { const LuaTable moveTable = rootTable.SubTable(num); if (!moveTable.IsValid()) { break; } MoveData* md = new MoveData(NULL); md->name = StringToLower(moveTable.GetString("name", "")); md->pathType = (num - 1); md->crushStrength = moveTable.GetFloat("crushStrength", 10.0f); const float minWaterDepth = moveTable.GetFloat("minWaterDepth", 10.0f); const float maxWaterDepth = moveTable.GetFloat("maxWaterDepth", 0.0f); if ((md->name.find("boat") != string::npos) || (md->name.find("ship") != string::npos)) { md->moveType = MoveData::Ship_Move; md->depth = minWaterDepth; md->moveFamily = MoveData::Ship; md->moveMath = seaMoveMath; md->subMarine = moveTable.GetBool("subMarine", 0); } else if (md->name.find("hover") != string::npos) { md->moveType = MoveData::Hover_Move; md->maxSlope = DegreesToMaxSlope(moveTable.GetFloat("maxSlope", 15.0f)); md->moveFamily = MoveData::Hover; md->moveMath = hoverMoveMath; } else { md->moveType = MoveData::Ground_Move; md->depthMod = moveTable.GetFloat("depthMod", 0.1f); md->depth = maxWaterDepth; md->maxSlope = DegreesToMaxSlope(moveTable.GetFloat("maxSlope", 60.0f)); md->moveMath = groundMoveMath; if (md->name.find("tank") != string::npos) { md->moveFamily = MoveData::Tank; } else { md->moveFamily = MoveData::KBot; } } md->heatMapping = moveTable.GetBool("heatMapping", false); md->heatMod = moveTable.GetFloat("heatMod", 50.0f); md->heatProduced = moveTable.GetInt("heatProduced", 60); // ground units hug the ocean floor when in water, // ships stay at a "fixed" level (their waterline) md->followGround = (md->moveFamily == MoveData::Tank || md->moveFamily == MoveData::KBot); // tank or bot that cannot get its threads / feet // wet, or hovercraft (which doesn't touch ground // or water) const bool b0 = ((md->followGround && maxWaterDepth <= 0.0) || md->moveFamily == MoveData::Hover); // ship (or sub) that cannot crawl onto shore, OR tank or // kbot restricted to snorkling (strange but possible) const bool b1 = ((md->moveFamily == MoveData::Ship && minWaterDepth > 0.0) || ((md->followGround) && minWaterDepth > 0.0)); // tank or kbot that CAN go skinny-dipping (amph.), // or ship that CAN sprout legs when at the beach const bool b2 = ((md->followGround) && maxWaterDepth > 0.0) || (md->moveFamily == MoveData::Ship && minWaterDepth < 0.0); if (b0) { md->terrainClass = MoveData::Land; } if (b1) { md->terrainClass = MoveData::Water; } if (b2) { md->terrainClass = MoveData::Mixed; } const int xsize = std::max(1, moveTable.GetInt("footprintX", 1)); const int zsize = std::max(1, moveTable.GetInt("footprintZ", xsize)); const int scale = 2; // make all mobile footprints point-symmetric in heightmap space // (meaning that only non-even dimensions are possible and each // footprint always has a unique center square) md->xsize = xsize * scale; md->zsize = zsize * scale; md->xsize -= ((md->xsize & 1)? 0: 1); md->zsize -= ((md->zsize & 1)? 0: 1); md->slopeMod = moveTable.GetFloat("slopeMod", 4.0f / (md->maxSlope + 0.001f)); const unsigned int checksum = (md->xsize << 16) + (md->zsize << 8) + (md->followGround << 4) + (md->subMarine << 3) + (b2 << 2) + (b1 << 1) + (b0 << 0); crc << checksum << md->maxSlope << md->slopeMod << md->depth << md->depthMod << md->crushStrength; moveData.push_back(md); name2moveData[md->name] = md->pathType; } const float waterDamage = mapInfo->water.damage; if (waterDamage >= 1000.0f) { CGroundMoveMath::waterDamageCost = 0.0f; //! block water } else { CGroundMoveMath::waterDamageCost = 1.0f / (1.0f + waterDamage * 0.1f); } CHoverMoveMath::noWaterMove = (waterDamage >= 10000.0f); crc << CGroundMoveMath::waterDamageCost; crc << CHoverMoveMath::noWaterMove; moveInfoChecksum = crc.GetDigest(); }
/** * Get CRC of the data in the specified archive. * Returns 0 if file could not be opened. */ unsigned int CArchiveScanner::GetCRC(const std::string& arcName) { CRC crc; std::list<std::string> files; // Try to open an archive boost::scoped_ptr<IArchive> ar(archiveLoader.OpenArchive(arcName)); if (!ar) { return 0; // It wasn't an archive } // Load ignore list. boost::scoped_ptr<IFileFilter> ignore(CreateIgnoreFilter(ar.get())); // Insert all files to check in lowercase format for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { std::string name; int size; ar->FileInfo(fid, name, size); if (ignore->Match(name)) { continue; } StringToLowerInPlace(name); // case insensitive hash files.push_back(name); } // Sort by FileName files.sort(); // Push the filenames into a std::vector, cause OMP can better iterate over those std::vector<CRCPair> crcs; crcs.reserve(files.size()); CRCPair crcp; for (std::string& f: files) { crcp.filename = &f; crcs.push_back(crcp); } // Compute CRCs of the files // Hint: Multithreading only speedups `.sdd` loading. For those the CRC generation is extremely slow - // it has to load the full file to calc it! For the other formats (sd7, sdz, sdp) the CRC is saved // in the metainformation of the container and so the loading is much faster. Neither does any of our // current (2011) packing libraries support multithreading :/ for_mt(0, crcs.size(), [&](const int i) { CRCPair& crcp = crcs[i]; const unsigned int nameCRC = CRC::GetCRC(crcp.filename->data(), crcp.filename->size()); const unsigned fid = ar->FindFile(*crcp.filename); const unsigned int dataCRC = ar->GetCrc32(fid); crcp.nameCRC = nameCRC; crcp.dataCRC = dataCRC; #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(WDT_MAIN); #endif }); // Add file CRCs to the main archive CRC for (CRCPair& crcp: crcs) { crc.Update(crcp.nameCRC); crc.Update(crcp.dataCRC); #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(); #endif } // A value of 0 is used to indicate no crc.. so never return that // Shouldn't happen all that often unsigned int digest = crc.GetDigest(); if (digest == 0) digest = 4711; return digest; }
/** * Get CRC of the data in the specified archive. * Returns 0 if file could not be opened. */ unsigned int CArchiveScanner::GetCRC(const std::string& arcName) { CRC crc; struct CRCPair { std::string* filename; unsigned int nameCRC; unsigned int dataCRC; }; // try to open an archive std::unique_ptr<IArchive> ar(archiveLoader.OpenArchive(arcName)); if (ar == nullptr) return 0; // load ignore list, and insert all files to check in lowercase format std::unique_ptr<IFileFilter> ignore(CreateIgnoreFilter(ar.get())); std::vector<std::string> files; std::vector<CRCPair> crcs; files.reserve(ar->NumFiles()); crcs.reserve(ar->NumFiles()); for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { const std::pair<std::string, int>& info = ar->FileInfo(fid); if (ignore->Match(info.first)) continue; // create case-insensitive hashes files.push_back(StringToLower(info.first)); } // sort by filename std::stable_sort(files.begin(), files.end()); for (std::string& f: files) { crcs.push_back(CRCPair{&f, 0, 0}); } // compute CRCs of the files // Hint: Multithreading only speedups `.sdd` loading. For those the CRC generation is extremely slow - // it has to load the full file to calc it! For the other formats (sd7, sdz, sdp) the CRC is saved // in the metainformation of the container and so the loading is much faster. Neither does any of our // current (2011) packing libraries support multithreading :/ for_mt(0, crcs.size(), [&](const int i) { CRCPair& crcp = crcs[i]; assert(crcp.filename == &files[i]); const unsigned int nameCRC = CRC::GetCRC(crcp.filename->data(), crcp.filename->size()); const unsigned fid = ar->FindFile(*crcp.filename); const unsigned int dataCRC = ar->GetCrc32(fid); crcp.nameCRC = nameCRC; crcp.dataCRC = dataCRC; #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(WDT_MAIN); #endif }); // Add file CRCs to the main archive CRC for (const CRCPair& crcp: crcs) { crc.Update(crcp.nameCRC); crc.Update(crcp.dataCRC); #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(); #endif } // A value of 0 is used to indicate no crc.. so never return that // Shouldn't happen all that often const unsigned int digest = crc.GetDigest(); return (digest == 0)? 4711: digest; }
/** * Get CRC of the data in the specified archive. * Returns 0 if file could not be opened. */ unsigned int CArchiveScanner::GetCRC(const std::string& arcName) { CRC crc; IArchive* ar; std::list<std::string> files; //! Try to open an archive ar = archiveLoader.OpenArchive(arcName); if (!ar) { return 0; // It wasn't an archive } //! Load ignore list. IFileFilter* ignore = CreateIgnoreFilter(ar); //! Insert all files to check in lowercase format for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { std::string name; int size; ar->FileInfo(fid, name, size); if (ignore->Match(name)) { continue; } StringToLowerInPlace(name); //! case insensitive hash files.push_back(name); } //! Sort by FileName files.sort(); //! Push the filenames into a std::vector, cause OMP can better iterate over those std::vector<CRCPair> crcs; crcs.reserve(files.size()); CRCPair crcp; for (std::list<std::string>::iterator it = files.begin(); it != files.end(); ++it) { crcp.filename = &(*it); crcs.push_back(crcp); } //! Compute CRCs of the files //! Hint: Multithreading only speedups `.sdd` loading. For those the CRC generation is extremely slow - //! it has to load the full file to calc it! For the other formats (sd7, sdz, sdp) the CRC is saved //! in the metainformation of the container and so the loading is much faster. Neither does any of our //! current (2011) packing libraries support multithreading :/ int i; #pragma omp parallel for private(i) for (i=0; i<crcs.size(); ++i) { CRCPair& crcp = crcs[i]; const unsigned int nameCRC = CRC().Update(crcp.filename->data(), crcp.filename->size()).GetDigest(); const unsigned fid = ar->FindFile(*crcp.filename); const unsigned int dataCRC = ar->GetCrc32(fid); crcp.nameCRC = nameCRC; crcp.dataCRC = dataCRC; #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(WDT_MAIN); #endif } //! Add file CRCs to the main archive CRC for (std::vector<CRCPair>::iterator it = crcs.begin(); it != crcs.end(); ++it) { crc.Update(it->nameCRC); crc.Update(it->dataCRC); #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(); #endif } delete ignore; delete ar; unsigned int digest = crc.GetDigest(); //! A value of 0 is used to indicate no crc.. so never return that //! Shouldn't happen all that often if (digest == 0) { return 4711; } else { return digest; } }