void C4SDefinitions::SetModules(const char *szList, const char *szRelativeToPath, const char *szRelativeToPath2) { int32_t cnt; // Empty list: local only if (!SModuleCount(szList)) { LocalOnly=TRUE; for (cnt=0; cnt<C4S_MaxDefinitions; cnt++) Definition[cnt][0]=0; return; } // Set list LocalOnly=FALSE; for (cnt=0; cnt<C4S_MaxDefinitions; cnt++) { SGetModule(szList,cnt,Definition[cnt],_MAX_PATH); // Make relative path if (szRelativeToPath && *szRelativeToPath) if (SEqualNoCase(Definition[cnt],szRelativeToPath,SLen(szRelativeToPath))) SCopy(Definition[cnt]+SLen(szRelativeToPath),Definition[cnt]); if (szRelativeToPath2 && *szRelativeToPath2) if (SEqualNoCase(Definition[cnt],szRelativeToPath2,SLen(szRelativeToPath2))) SCopy(Definition[cnt]+SLen(szRelativeToPath2),Definition[cnt]); } }
void C4GameSave::WriteDescDefinitions(StdStrBuf &sBuf) { // Definition specs if (Game.DefinitionFilenames[0]) { char szDef[_MAX_PATH+1]; // Desc sBuf.Append(LoadResStr("IDS_DESC_DEFSPECS")); // Get definition modules for (int cnt=0; SGetModule(Game.DefinitionFilenames,cnt,szDef); cnt++) { // Get exe relative path StdStrBuf sDefFilename; sDefFilename.Copy(Config.AtRelativePath(szDef)); // Convert rtf backslashes sDefFilename.Replace("\\", "\\\\"); // Append comma if (cnt>0) sBuf.Append(", "); // Apend to desc sBuf.Append(sDefFilename); } // End of line WriteDescLineFeed(sBuf); } }
void C4SDefinitions::SetModules(const char *szList, const char *szRelativeToPath, const char *szRelativeToPath2) { int32_t cnt; // Empty list: local only if (!SModuleCount(szList)) { LocalOnly=true; for (cnt=0; cnt<C4S_MaxDefinitions; cnt++) Definition[cnt][0]=0; return; } // Set list LocalOnly=false; for (cnt=0; cnt<C4S_MaxDefinitions; cnt++) { SGetModule(szList,cnt,Definition[cnt],_MAX_PATH); // Make relative path if (szRelativeToPath && *szRelativeToPath) { if (GetRelativePathS(Definition[cnt],szRelativeToPath) != Definition[cnt]) { SCopy(GetRelativePathS(Definition[cnt],szRelativeToPath),Definition[cnt]); continue; } } if (szRelativeToPath2 && *szRelativeToPath2) { if (GetRelativePathS(Definition[cnt],szRelativeToPath2) != Definition[cnt]) { SCopy(GetRelativePathS(Definition[cnt],szRelativeToPath2),Definition[cnt]); continue; } } } }
int C4MusicSystem::SetPlayList(const char *szPlayList, bool fForceSwitch, int fadetime_ms, double max_resume_time) { // Shortcut if no change if (playlist_valid && playlist == szPlayList) return 0; // info if (::Config.Sound.Verbose) { LogF("MusicSystem: SetPlayList(\"%s\", %s, %d, %.3lf)", szPlayList ? szPlayList : "(null)", fForceSwitch ? "true" : "false", fadetime_ms, max_resume_time); } // reset C4MusicFile *pFile; for (pFile = Songs; pFile; pFile = pFile->pNext) { pFile->NoPlay = true; } ASongCount = 0; if (szPlayList && *szPlayList) { // match char szFileName[_MAX_FNAME + 1]; for (int cnt = 0; SGetModule(szPlayList, cnt, szFileName, _MAX_FNAME); cnt++) for (pFile = Songs; pFile; pFile = pFile->pNext) if (pFile->NoPlay) if (WildcardMatch(szFileName, GetFilename(pFile->FileName)) || pFile->HasCategory(szFileName)) { ASongCount++; pFile->NoPlay = false; } } else { // default: all files except the ones beginning with an at ('@') // Ignore frontend and credits music for (pFile = Songs; pFile; pFile = pFile->pNext) if (*GetFilename(pFile->FileName) != '@' && !pFile->HasCategory("frontend") && !pFile->HasCategory("credits")) { ASongCount++; pFile->NoPlay = false; } } // Force switch of music if currently playing piece is not in list or idle because no music file matched if (fForceSwitch) { if (PlayMusicFile) { fForceSwitch = PlayMusicFile->NoPlay; } else { fForceSwitch = (!is_waiting || C4TimeMilliseconds::Now() >= wait_time_end); } if (fForceSwitch) { // Switch music. Switching to a break is also allowed, but won't be done if there is a piece to resume // Otherwise breaks would never occur if the playlist changes often. Play(NULL, false, fadetime_ms, max_resume_time, PlayMusicFile != NULL); } } // Remember setting (e.g. to be saved in savegames) playlist.Copy(szPlayList); playlist_valid = true; // do not re-calculate available song if playlist is reset to same value in the future return ASongCount; }
bool C4Group_ApplyUpdate(C4Group &hGroup) { // Process object update group (GRPUP_Entries.txt found) C4UpdatePackage Upd; if (hGroup.FindEntry(C4CFN_UpdateEntries)) if (Upd.Load(&hGroup)) { // Do update check first (ensure packet has everything it needs in order // to perfom the update) int iRes = Upd.Check(&hGroup); switch (iRes) { // Bad version - checks against version of the applying executable // (major version must match, minor version must be equal or higher) case C4UPD_CHK_BAD_VERSION: fprintf(stderr, "This update %s can only be applied using version " "%d.%d.%d.%d or higher.\n", Upd.Name, Upd.RequireVersion[0], Upd.RequireVersion[1], Upd.RequireVersion[2], Upd.RequireVersion[3]); return false; // Target not found: keep going case C4UPD_CHK_NO_SOURCE: fprintf(stderr, "Target %s for update %s not found. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target mismatch: abort updating case C4UPD_CHK_BAD_SOURCE: fprintf(stderr, "Target %s incorrect version for update %s. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target already updated: keep going case C4UPD_CHK_ALREADY_UPDATED: fprintf(stderr, "Target %s already up-to-date at %s.\n", Upd.DestPath, Upd.Name); return true; // Ok to perform update case C4UPD_CHK_OK: printf("Updating %s to %s... ", Upd.DestPath, Upd.Name); // Make sure the user sees the message while the work is in progress fflush(stdout); // Execute update if (Upd.Execute(&hGroup)) { printf("Ok\n"); return true; } else { printf("Failed\n"); return false; } // Unknown return value from update default: fprintf(stderr, "Unknown error while updating.\n"); return false; } } // Process binary update group (AutoUpdate.txt found, additional binary files // found) if (hGroup.EntryCount(C4CFN_UpdateCore)) if (hGroup.EntryCount() - hGroup.EntryCount(C4CFN_UpdateCore) - hGroup.EntryCount("*.c4u") > 0) { // Notice: AutoUpdate.txt is currently not processed... char strEntry[_MAX_FNAME + 1] = ""; StdStrBuf strList; printf("Updating binaries...\n"); hGroup.ResetSearch(); // Look for binaries while (hGroup.FindNextEntry("*", strEntry)) // Accept everything except *.c4u, AutoUpdate.txt, and c4group.exe // (which is assumed not to work under Windows) if (!WildcardMatch("*.c4u", strEntry) && !WildcardMatch(C4CFN_UpdateCore, strEntry) && !WildcardMatch("c4group.exe", strEntry)) { strList += strEntry; strList += ";"; } // Extract binaries to current working directory if (!hGroup.Extract(strList.getData())) return false; // If extracted file is a group, explode it (this is meant for Clonk.app // on Mac) for (int i = 0; SGetModule(strList.getData(), i, strEntry); i++) if (C4Group_IsGroup(strEntry)) { printf("Exploding: %s\n", strEntry); if (!C4Group_ExplodeDirectory(strEntry)) return false; } } // Process any child updates (*.c4u) if (hGroup.FindEntry("*.c4u")) { // Process all children char strEntry[_MAX_FNAME + 1] = ""; C4Group hChild; hGroup.ResetSearch(); while (hGroup.FindNextEntry("*.c4u", strEntry)) if (hChild.OpenAsChild(&hGroup, strEntry)) { bool ok = C4Group_ApplyUpdate(hChild); hChild.Close(); // Failure on child update if (!ok) return false; } } // Success return true; }
bool C4Group_ApplyUpdate(C4Group &hGroup, unsigned long ParentProcessID) { // Wait for parent process to terminate (so we can safely replace the executable) #ifdef _WIN32 if(ParentProcessID) { HANDLE ParentProcess = OpenProcess(SYNCHRONIZE, FALSE, ParentProcessID); if(ParentProcess) { // If we couldn't find a handle then either // a) the process terminated already, which is great. // b) OpenProcess() failed, which is not so great. But let's still try to do // the update. printf("Waiting for parent process to terminate..."); DWORD res = WaitForSingleObject(ParentProcess, 10000); if(res == WAIT_TIMEOUT) fprintf(stderr, "Parent process did not terminate after 10 seconds. Continuing..."); } } #else // We could use waitpid on Unix, but we don't need that functionality there anyway... #endif // Process object update group (GRPUP_Entries.txt found) C4UpdatePackage Upd; if (hGroup.FindEntry(C4CFN_UpdateEntries)) if (Upd.Load(&hGroup)) { // Do update check first (ensure packet has everything it needs in order to perfom the update) int iRes = Upd.Check(&hGroup); switch (iRes) { // Bad version - checks against version of the applying executable (major version must match, minor version must be equal or higher) case C4UPD_CHK_BAD_VERSION: fprintf(stderr, "This update %s can only be applied using version %d.%d.%d.%d or higher.\n", Upd.Name, Upd.RequireVersion[0], Upd.RequireVersion[1], Upd.RequireVersion[2], Upd.RequireVersion[3]); return false; // Target not found: keep going case C4UPD_CHK_NO_SOURCE: fprintf(stderr, "Target %s for update %s not found. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target mismatch: abort updating case C4UPD_CHK_BAD_SOURCE: fprintf(stderr, "Target %s incorrect version for update %s. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target already updated: keep going case C4UPD_CHK_ALREADY_UPDATED: fprintf(stderr,"Target %s already up-to-date at %s.\n", Upd.DestPath, Upd.Name); return true; // Ok to perform update case C4UPD_CHK_OK: printf("Updating %s to %s... ", Upd.DestPath, Upd.Name); // Make sure the user sees the message while the work is in progress fflush(stdout); // Execute update if (Upd.Execute(&hGroup)) { printf("Ok\n"); return true; } else { printf("Failed\n"); return false; } // Unknown return value from update default: fprintf(stderr,"Unknown error while updating.\n"); return false; } } // Process binary update group (AutoUpdate.txt found, additional binary files found) if (hGroup.EntryCount(C4CFN_UpdateCore)) if (hGroup.EntryCount() - hGroup.EntryCount(C4CFN_UpdateCore) - hGroup.EntryCount("*.ocu") > 0) { // Notice: AutoUpdate.txt is currently not processed... char strEntry[_MAX_FNAME + 1] = ""; StdStrBuf strList; printf("Updating binaries...\n"); hGroup.ResetSearch(); // Look for binaries while (hGroup.FindNextEntry("*", strEntry)) // Accept everything except *.ocu, AutoUpdate.txt, and c4group.exe (which is assumed not to work under Windows) if (!WildcardMatch("*.ocu", strEntry) && !WildcardMatch(C4CFN_UpdateCore, strEntry) && !WildcardMatch("c4group.exe", strEntry)) { strList += strEntry; strList += ";"; } // Extract binaries to current working directory if (!hGroup.Extract(strList.getData())) return false; // If extracted file is a group, explode it (this is meant for Clonk.app on Mac) for (int i = 0; SGetModule(strList.getData(), i, strEntry); i++) if (C4Group_IsGroup(strEntry)) { printf("Exploding: %s\n", strEntry); if (!C4Group_ExplodeDirectory(strEntry)) return false; } } // Process any child updates (*.ocu) if (hGroup.FindEntry("*.ocu")) { // Process all children char strEntry[_MAX_FNAME + 1] = ""; C4Group hChild; hGroup.ResetSearch(); while (hGroup.FindNextEntry("*.ocu", strEntry)) if (hChild.OpenAsChild(&hGroup, strEntry)) { bool ok = C4Group_ApplyUpdate(hChild, 0); hChild.Close(); // Failure on child update if (!ok) return false; } } // Success return true; }