BOOL C4Record::Stop(StdStrBuf *pRecordName, BYTE *pRecordSHA1) { // safety if (!fRecording) return FALSE; if (!DirectoryExists(sFilename.getData())) return FALSE; // streaming finished StopStreaming(); // save desc into record group C4GameSaveRecord saveRec(false, Index, Game.Parameters.isLeague()); saveRec.SaveDesc(RecordGrp); // save end player infos into record group Game.PlayerInfos.Save(RecordGrp, C4CFN_RecPlayerInfos); RecordGrp.Close(); // write last entry and close C4RecordChunkHead Head; Head.iFrm = Game.FrameCounter + 37; Head.Type = RCT_End; CtrlRec.Write(&Head, sizeof(Head)); CtrlRec.Close(); // pack group #ifndef DEBUGREC if (!C4Group_PackDirectory(sFilename.getData())) return FALSE; #endif // return record data if (pRecordName) pRecordName->Copy(sFilename); if (pRecordSHA1) if (!C4Group_GetFileSHA1(sFilename.getData(), pRecordSHA1)) return false; // ok fRecording = false; return true; }
bool C4Network2Res::GetStandalone(char *pTo, int32_t iMaxL, bool fSetOfficial, bool fAllowUnloadable, bool fSilent) { // already set? if (szStandalone[0]) { if (pTo) SCopy(szStandalone, pTo, iMaxL); return true; } // already tried and failed? No point in retrying if (fStandaloneFailed) return false; // not loadable? Wo won't be able to check the standalone as the core will lack the needed information. // the standalone won't be interesting in this case, anyway. if (!fSetOfficial && !Core.isLoadable()) return false; // set flag, so failure below will let future calls fail fStandaloneFailed = true; // lock file CStdLock FileLock(&FileCSec); // directory? SCopy(szFile, szStandalone, sizeof(szStandalone)-1); if (DirectoryExists(szFile)) { // size check for the directory, if allowed if (fAllowUnloadable) { uint32_t iDirSize; if (!DirSizeHelper::GetDirSize(szFile, &iDirSize, Config.Network.MaxLoadFileSize)) { if (!fSilent) LogF("Network: could not get directory size of %s!", szFile); szStandalone[0] = '\0'; return false; } if (iDirSize > uint32_t(Config.Network.MaxLoadFileSize)) { if (!fSilent) LogSilentF("Network: %s over size limit, will be marked unloadable!", szFile); szStandalone[0] = '\0'; return false; } } // log - this may take a few seconds if (!fSilent) LogF(LoadResStr("IDS_PRC_NETPACKING"), GetFilename(szFile)); // pack inplace? if (!fTempFile) { if (!pParent->FindTempResFileName(szFile, szStandalone)) { if (!fSilent) Log("GetStandalone: could not find free name for temporary file!"); szStandalone[0] = '\0'; return false; } if (!C4Group_PackDirectoryTo(szFile, szStandalone)) { if (!fSilent) Log("GetStandalone: could not pack directory!"); szStandalone[0] = '\0'; return false; } } else if (!C4Group_PackDirectory(szStandalone)) { if (!fSilent) Log("GetStandalone: could not pack directory!"); if (!SEqual(szFile, szStandalone)) EraseDirectory(szStandalone); szStandalone[0] = '\0'; return false; } // make sure directory is packed if (DirectoryExists(szStandalone)) { if (!fSilent) Log("GetStandalone: directory hasn't been packed!"); if (!SEqual(szFile, szStandalone)) EraseDirectory(szStandalone); szStandalone[0] = '\0'; return false; } // fallthru } // doesn't exist physically? if (!FileExists(szStandalone)) { // try C4Group (might be packed) if (!pParent->FindTempResFileName(szFile, szStandalone)) { if (!fSilent) Log("GetStandalone: could not find free name for temporary file!"); szStandalone[0] = '\0'; return false; } if (!C4Group_CopyItem(szFile, szStandalone)) { if (!fSilent) Log("GetStandalone: could not copy to temporary file!"); szStandalone[0] = '\0'; return false; } } // remains missing? give up. if (!FileExists(szStandalone)) { if (!fSilent) Log("GetStandalone: file not found!"); szStandalone[0] = '\0'; return false; } // do optimizations (delete unneeded entries) if (!OptimizeStandalone(fSilent)) { if (!SEqual(szFile, szStandalone)) EraseItem(szStandalone); szStandalone[0] = '\0'; return false; } // get file size size_t iSize = FileSize(szStandalone); // size limit if (fAllowUnloadable) if (iSize > uint32_t(Config.Network.MaxLoadFileSize)) { if (!fSilent) LogSilentF("Network: %s over size limit, will be marked unloadable!", szFile); szStandalone[0] = '\0'; return false; } // check if (!fSetOfficial && iSize != Core.getFileSize()) { // remove file if (!SEqual(szFile, szStandalone)) EraseItem(szStandalone); szStandalone[0] = '\0'; // sorry, this version isn't good enough :( return false; } // calc checksum uint32_t iCRC32; if (!GetFileCRC(szStandalone, &iCRC32)) { if (!fSilent) Log("GetStandalone: could not calculate checksum!"); return false; } // set / check if (!fSetOfficial && iCRC32 != Core.getFileCRC()) { // remove file, return if (!SEqual(szFile, szStandalone)) EraseItem(szStandalone); szStandalone[0] = '\0'; return false; } // we didn't fail fStandaloneFailed = false; // mark resource as loadable and safe file information Core.SetLoadable(iSize, iCRC32); // set up chunk data Chunks.SetComplete(Core.getChunkCnt()); // ok return true; }