BOOL C4ComponentHost::Load(const char *szName, C4Group &hGroup, const char *szFilename, const char *szLanguage) { // Clear any old stuff Clear(); // Store name & filename SCopy(szName, Name); SCopy(szFilename, Filename); // Load component - try all segmented filenames char strEntry[_MAX_FNAME + 1], strEntryWithLanguage[_MAX_FNAME + 1]; for (int iFilename = 0; SCopySegment(Filename, iFilename, strEntry, '|', _MAX_FNAME); iFilename++) { // Try to insert all language codes provided into the filename char strCode[3] = ""; for (int iLang = 0; SCopySegment(szLanguage ? szLanguage : "", iLang, strCode, ',', 2); iLang++) { // Insert language code sprintf(strEntryWithLanguage, strEntry, strCode); if (hGroup.LoadEntryString(strEntryWithLanguage, Data)) { if (pConfig->General.fUTF8) Data.EnsureUnicode(); // Store actual filename hGroup.FindEntry(strEntryWithLanguage, Filename); CopyFilePathFromGroup(hGroup); // Got it return TRUE; } // Couldn't insert language code anyway - no point in trying other // languages if (!SSearch(strEntry, "%s")) break; } } // Truncate any additional segments from stored filename SReplaceChar(Filename, '|', 0); CopyFilePathFromGroup(hGroup); // Not loaded return FALSE; }
C4ScenarioSection::C4ScenarioSection(char *szName) { // copy name if (szName && !SEqualNoCase(szName, C4ScenSect_Main) && *szName) { this->szName = new char[strlen(szName) + 1]; SCopy(szName, this->szName); } else this->szName = const_cast<char *>(C4ScenSect_Main); // zero fields szTempFilename = szFilename = 0; fModified = false; // link into main list pNext = Game.pScenarioSections; Game.pScenarioSections = this; }
C4DefGraphicsPtrBackupEntry::C4DefGraphicsPtrBackupEntry(C4DefGraphics *pSourceGraphics): pMeshUpdate(NULL) { // assign graphics + def pGraphicsPtr = pSourceGraphics; pDef = pSourceGraphics->pDef; // assign name const char *szName = pGraphicsPtr->GetName(); if (szName) SCopy(szName, Name, C4MaxName); else *Name=0; // assign mesh update if(pSourceGraphics->Type == C4DefGraphics::TYPE_Mesh) pMeshUpdate = new StdMeshUpdate(*pSourceGraphics->Mesh); }
void C4GraphicsOverlay::Set(Mode aMode, C4DefGraphics *pGfx, const char *szAction, DWORD dwBMode, C4Object *pOvrlObj) { // set values eMode = aMode; pSourceGfx = pGfx; if (szAction) SCopy(szAction, Action, C4MaxName); else *Action=0; dwBlitMode = dwBMode; OverlayObj = pOvrlObj; // (keep transform) // reset phase iPhase = 0; // update used facet UpdateFacet(); }
void C4Region::Set(int iX, int iY, int iWdt, int iHgt, const char *szCaption, int iCom, int iMoveOverCom, int iHoldCom, int iData, C4Object *pTarget) { X = iX; Y = iY; Wdt = iWdt; Hgt = iHgt; SCopy(szCaption, Caption, C4RGN_MaxCaption); Com = iCom; MoveOverCom = iMoveOverCom; HoldCom = iHoldCom; Data = iData; Target = pTarget; }
BOOL C4SoundEffect::Load(const char *szFileName, C4Group &hGroup, BOOL fStatic) { // Sound check if (!Config.Sound.RXSound) return FALSE; // Locate sound in file StdBuf WaveBuffer; if (!hGroup.LoadEntry(szFileName, WaveBuffer)) return FALSE; // load it from mem if (!Load((BYTE *)WaveBuffer.getData(), WaveBuffer.getSize(), fStatic)) return FALSE; // Set name SCopy(szFileName, Name, C4MaxSoundName); return TRUE; }
C4Group *C4GroupSet::FindSuitableFile(const char *szName, const char * const extensions[], char *szFileName, int32_t *pID) { C4Group *pGrp = nullptr; C4Group *pGrp2; int iPrio = -1; int32_t iPrio2; int32_t GroupID; char FileName[_MAX_FNAME]; SCopy(szName, FileName); for (int i = 0; extensions[i]; ++i) { EnforceExtension(FileName, extensions[i]); pGrp2=FindEntry(FileName, &iPrio2, &GroupID); if ((!pGrp || iPrio2 >= iPrio) && pGrp2) { if (pID) *pID = GroupID; pGrp = pGrp2; SCopy(FileName, szFileName); } } // return found group, if any return pGrp; }
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; } } } }
void C4GraphicsOverlay::Write(char *szOutput) { // deprecated assert(false && "C4GraphicsOverlay::Write: deprecated"); #if 0 // safety: Don't save invalid if (!pSourceGfx) return; C4Def *pDef = pSourceGfx->pDef; assert(pDef); // get to end of buffer szOutput += strlen(szOutput); // store ID sprintf(OSTR, "%i", iID); SCopy(OSTR, szOutput); szOutput += strlen(szOutput); *szOutput = ','; ++szOutput; // append C4ID::Graphicsname (or C4ID:: for def graphics) SCopy(pDef->id.ToString(), szOutput); szOutput += strlen(szOutput); SCopy("::", szOutput); szOutput += strlen(szOutput); const char *szGrpName = pSourceGfx->GetName(); if (szGrpName) { SCopy(szGrpName, szOutput); szOutput += strlen(szOutput); } *szOutput = ','; ++szOutput; // store mode DWORD dwMode = eMode; sprintf(OSTR, "%i", dwMode); SCopy(OSTR, szOutput); szOutput += strlen(OSTR); // store action *szOutput = ','; ++szOutput; SCopy(Action, szOutput); szOutput += strlen(szOutput); // store blit mode *szOutput = ','; ++szOutput; sprintf(OSTR, "%i", dwBlitMode); SCopy(OSTR, szOutput); szOutput += strlen(szOutput); // store phase *szOutput = ','; ++szOutput; sprintf(OSTR, "%i", iPhase); SCopy(OSTR, szOutput); szOutput += strlen(szOutput); // store transform *szOutput = ','; ++szOutput; sprintf(OSTR, "(%f,%f,%f,%f,%f,%f,%d)", Transform.mat[0], Transform.mat[1], Transform.mat[2], Transform.mat[3], Transform.mat[4], Transform.mat[5], Transform.FlipDir); SCopy(OSTR, szOutput); szOutput += strlen(szOutput); // terminate string *szOutput=0; #endif }
C4SoundInstance *C4SoundSystem::FindInstance(const char *szSndName, C4Object *pObj) { char szName[C4MaxSoundName + 4 + 1]; // Evaluate sound name (see GetEffect) SCopy(szSndName, szName, C4MaxSoundName); DefaultExtension(szName, "wav"); SReplaceChar(szName, '*', '?'); // Find an effect with a matching instance for (C4SoundEffect *csfx = FirstSound; csfx; csfx = csfx->Next) if (WildcardMatch(szName, csfx->Name)) { C4SoundInstance *pInst = csfx->GetInstance(pObj); if (pInst) return pInst; } return NULL; }
void C4SHead::Default() { Origin.Clear(); Icon=18; *Title = *Loader = *Font = *Engine = *MissionAccess = '\0'; Secret = false; C4XVer[0] = C4XVer[1] = 0; Difficulty = RandomSeed = 0; SaveGame = Replay = NoInitialize = false; Film = 0; NetworkGame = NetworkRuntimeJoin = false; MaxPlayer=MaxPlayerLeague=C4S_MaxPlayerDefault; MinPlayer=0; // auto-determine by mode SCopy("Default Title",Title,C4MaxTitle); }
void C4GameOptionButtons::OnPasswordSet(const StdStrBuf &rsNewPassword) { // password input dialog answered with OK: Set/clear network password const char *szPass; ::Network.SetPassword(szPass=rsNewPassword.getData()); // update icon to reflect if a password is set UpdatePasswordBtn(); // remember password for next round bool fHasPassword = (szPass && *szPass); if (fHasPassword) { SCopy(szPass, Config.Network.LastPassword, CFG_MaxString); } // acoustic feedback C4GUI::GUISound("UI::Confirmed"); }
bool EraseItemSafe(const char *szFilename) { char Filename[_MAX_PATH+1]; SCopy(szFilename, Filename, _MAX_PATH); Filename[SLen(Filename)+1]=0; SHFILEOPSTRUCTW shs; shs.hwnd=0; shs.wFunc=FO_DELETE; shs.pFrom=GetWideChar(Filename); shs.pTo=NULL; shs.fFlags=FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT; shs.fAnyOperationsAborted=false; shs.hNameMappings=0; shs.lpszProgressTitle=NULL; return !SHFileOperationW(&shs); }
bool C4Network2ResList::CreateNetworkFolder() { // get network path without trailing backslash char szNetworkPath[_MAX_PATH+1]; SCopy(Config.AtNetworkPath(""), szNetworkPath, _MAX_PATH); TruncateBackslash(szNetworkPath); // but make sure that the configured path has one AppendBackslash(Config.Network.WorkPath); // does not exist? if (!DirectoryExists(szNetworkPath)) { if (!CreatePath(szNetworkPath)) { LogFatal("Network: could not create network path!"); return false; } return true; } return true; }
bool C4Network2Res::CalculateSHA() { // already present? if (Core.hasFileSHA()) return true; // get the file char szStandalone[_MAX_PATH + 1]; if (!GetStandalone(szStandalone, _MAX_PATH, false)) SCopy(szFile, szStandalone, _MAX_PATH); // get the hash BYTE hash[SHA_DIGEST_LENGTH]; if (!GetFileSHA1(szStandalone, hash)) return false; // save it back Core.SetFileSHA(hash); // okay return true; }
QLineEdit *C4ConsoleQtLocalizeStringDlg::AddEditor(const char *language, const char *language_name) { assert(!GetEditorByLanguage(language)); // Add editor widgets int32_t row = edited_languages.size(); QString language_label_text(language); if (language_name) language_label_text.append(FormatString(" (%s)", language_name).getData()); QLabel *language_label = new QLabel(language_label_text, this); ui.mainGrid->addWidget(language_label, row, 0); QLineEdit *value_editor = new QLineEdit(this); ui.mainGrid->addWidget(value_editor, row, 1); // Add to list EditedLanguage new_editor; SCopy(language, new_editor.language, 2); new_editor.value_editor = value_editor; edited_languages.push_back(new_editor); return value_editor; }
void C4GraphicsSystem::FlashMessage(const char *szMessage) { // Store message SCopy(szMessage, FlashMessageText, C4MaxTitle); // Calculate message time FlashMessageTime = SLen(FlashMessageText) * 2; // Initial position FlashMessageX = -1; FlashMessageY = 10; // Upper board active: stay below upper board if (Config.Graphics.UpperBoard) FlashMessageY += C4UpperBoardHeight; // More than one viewport: try to stay below portraits etc. if (GetViewportCount() > 1) FlashMessageY += 64; // New flash message: redraw background (might be drawing one message on top of another) InvalidateBg(); }
int C4LoaderScreen::SeekLoaderScreens(C4Group &rFromGrp, const char *szWildcard, int iLoaderCount, char *szDstName, C4Group **ppDestGrp) { BOOL fFound; int iLocalLoaders=0; char Filename[_MAX_PATH+1]; for (fFound=rFromGrp.FindEntry(szWildcard, Filename); fFound; fFound=rFromGrp.FindNextEntry(szWildcard, Filename)) { // loader found; choose it, if Daniel wants it that way ++iLocalLoaders; if (!SafeRandom(++iLoaderCount)) { // copy group and path *ppDestGrp=&rFromGrp; SCopy(Filename, szDstName, _MAX_PATH); } } return iLocalLoaders; }
bool C4ScenarioSection::EnsureTempStore(bool fExtractLandscape, bool fExtractObjects) { // if it's temp store already, don't do anything if (szTempFilename) return true; // make temp filename char *szTmp = const_cast<char *>( Config.AtTempPath(szFilename ? GetFilename(szFilename) : szName)); MakeTempFilename(szTmp); // main section: extract section files from main scenario group (create group // as open dir) if (!szFilename) { if (!CreateDirectory(szTmp, NULL)) return false; C4Group hGroup; if (!hGroup.Open(szTmp, TRUE)) { EraseItem(szTmp); return false; } // extract all desired section files Game.ScenarioFile.ResetSearch(); char fn[_MAX_FNAME + 1]; *fn = 0; while (Game.ScenarioFile.FindNextEntry(C4FLS_Section, fn)) if (fExtractLandscape || !WildcardMatch(C4FLS_SectionLandscape, fn)) if (fExtractObjects || !WildcardMatch(C4FLS_SectionObjects, fn)) Game.ScenarioFile.ExtractEntry(fn, szTmp); hGroup.Close(); } else { // subsection: simply extract section from main group if (!Game.ScenarioFile.ExtractEntry(szFilename, szTmp)) return false; // delete undesired landscape/object files if (!fExtractLandscape || !fExtractObjects) { C4Group hGroup; if (hGroup.Open(szFilename)) { if (!fExtractLandscape) hGroup.Delete(C4FLS_SectionLandscape); if (!fExtractObjects) hGroup.Delete(C4FLS_SectionObjects); } } } // copy temp filename szTempFilename = new char[strlen(szTmp) + 1]; SCopy(szTmp, szTempFilename, _MAX_PATH); // done, success return true; }
bool C4MainMenu::ActivateNewPlayer(int32_t iPlayer) { // league or replay game if (Game.Parameters.isLeague() || Game.C4S.Head.Replay) return false; // Max player limit if (::Players.GetCount() >= Game.Parameters.MaxPlayers) return false; // Menu symbol/init if (GfxR->fctPlayerClr.Surface) GfxR->fctPlayerClr.Surface->SetClr(0xff); InitRefSym(GfxR->fctPlayerClr, LoadResStr("IDS_MENU_NOPLRFILES"), iPlayer); for (DirectoryIterator iter(Config.General.UserDataPath); *iter; ++iter) if (WildcardMatch("*.ocp", *iter)) { char szFilename[_MAX_PATH+1], szCommand[_MAX_PATH+30+1]; SCopy(*iter, szFilename, _MAX_PATH); if (DirectoryExists(szFilename)) continue; if (::Players.FileInUse(szFilename)) continue; // Open group C4Group hGroup; if (!hGroup.Open(szFilename)) continue; // Load player info C4PlayerInfoCore C4P; if (!C4P.Load(hGroup)) { hGroup.Close(); continue; } // Close group hGroup.Close(); // Add player item sprintf(szCommand, "JoinPlayer:%s", szFilename); StdStrBuf sItemText; sItemText.Format(LoadResStr("IDS_MENU_NEWPLAYER"), C4P.PrefName); C4FacetSurface fctSymbol; // Add menu item Add(sItemText.getData(), fctSymbol, szCommand); // Reset symbol facet (menu holds on to the surface) fctSymbol.Default(); } // Alignment SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom); // Go back to options menu on close SetCloseCommand("ActivateMenu:Main"); return true; }
void C4ValueMapNames::ChangeNameList(const char **pnNames, int32_t *pnExtra, int32_t nSize) { // safe old name list char **pOldNames = pNames; int32_t *pOldExtra = pExtra; int32_t iOldSize = iSize; // create new lists pNames = new char *[nSize]; pExtra = new int32_t [nSize]; // copy names int32_t i; for(i = 0; i < nSize; i++) { pNames[i] = new char [SLen(pnNames[i]) + 1]; SCopy(pnNames[i], pNames[i], SLen(pnNames[i]) + 1); if(pnExtra) pExtra[i] = pnExtra[i]; } if(!pnExtra) ZeroMem(pExtra, sizeof (*pExtra) * nSize); // set new size iSize = nSize; // call OnNameListChanged list for all "child" lists C4ValueMapData *pAktData = pFirst; while(pAktData) { pAktData->OnNameListChanged(const_cast<const char **>(pOldNames), iOldSize); pAktData = pAktData->pNext; } // delete old list for(i = 0; i < iOldSize; i++) delete[] pOldNames[i]; delete[] pOldNames; delete[] pOldExtra; // ok. }
bool C4PlayerList::FileInUse(const char *szFilename) const { // Check original player files C4Player *cPlr=First; for (; cPlr; cPlr=cPlr->Next) if (ItemIdentical(cPlr->Filename,szFilename)) return true; // Compare to any network path player files with prefix (hack) if (::Network.isEnabled()) { char szWithPrefix[_MAX_PATH+1]; SCopy(GetFilename(szFilename),szWithPrefix); SetClientPrefix(szWithPrefix, Game.Clients.getLocalName()); for (cPlr=First; cPlr; cPlr=cPlr->Next) if (SEqualNoCase(GetFilename(cPlr->Filename),szWithPrefix)) return true; } // Not in use return false; }
C4Application::~C4Application() { // clear gamepad if (pGamePadControl) delete pGamePadControl; // Close log CloseLog(); // Launch editor if (launchEditor) { #ifdef _WIN32 char strCommandLine[_MAX_PATH + 1]; SCopy(Config.AtExePath(C4CFN_Editor), strCommandLine); STARTUPINFO StartupInfo; ZeroMemory(&StartupInfo, sizeof StartupInfo); StartupInfo.cb = sizeof StartupInfo; PROCESS_INFORMATION ProcessInfo; ZeroMemory(&ProcessInfo, sizeof ProcessInfo); CreateProcess(NULL, strCommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo); #endif } }
bool C4Network2Res::SetDerived(const char *strName, const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iDResID) { Clear(); CStdLock FileLock(&FileCSec); // set core Core.Set(eType, C4NetResIDAnonymous, strName, ~0); Core.SetDerived(iDResID); // save file path SCopy(strFilePath, szFile, _MAX_PATH); *szStandalone = '\0'; // set flags fDirty = false; fTempFile = fTemp; fStandaloneFailed = false; fRemoved = false; iLastReqTime = time(NULL); fLoading = false; // Do not set any chunk data - anonymous resources are very likely to change. // Wait for FinishDerived()-call. return true; }
bool C4NameList::Set(const char *szName, int32_t iCount) { int32_t cnt; // Find existing name, set count for (cnt=0; cnt<C4MaxNameList; cnt++) if (SEqual(Name[cnt],szName)) { Count[cnt]=iCount; return true; } // Find empty spot, set name and count for (cnt=0; cnt<C4MaxNameList; cnt++) if (Name[cnt][0]==0) { SCopy(szName,Name[cnt],C4MaxName); Count[cnt]=iCount; return true; } // No empty spots return false; }
bool C4Menu::InitMenu(const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle) { SCopy(szEmpty,Caption,C4MaxTitle); Extra=iExtra; ExtraData=iExtraData; Identification=iId; if (*Caption || iStyle == C4MN_Style_Dialog) SetTitle(Caption, HasMouse()); else SetTitle(" ", HasMouse()); if (pTitle) pTitle->SetIcon(Symbol); Style=iStyle & C4MN_Style_BaseMask; // Menus are synchronous to allow COM_MenuUp/Down to be converted to movements at the clients if (Style == C4MN_Style_Normal) Columns = 5; else // in reality, Dialog menus may have two coloumns (first for the portrait) // however, they are not uniformly spaced and stuff; so they are better just ignored and handled by the drawing routine Columns=1; if (iStyle & C4MN_Style_EqualItemHeight) SetEqualItemHeight(true); if (Style == C4MN_Style_Dialog) Alignment = C4MN_Align_Top; ::pGUI->ShowDialog(this, false); fTextProgressing = false; fActive = true; return true; }
bool C4StartupNetDlg::DoOK() { // OK in chat mode? Forward to chat control if (GetDlgMode() == SNDM_Chat) return pChatCtrl->DlgEnter(); // OK on editbox with text enetered: Add the specified IP for reference retrieval if (GetFocus() == pJoinAddressEdt) { const char *szDirectJoinAddress = pJoinAddressEdt->GetText(); if (szDirectJoinAddress && *szDirectJoinAddress) { // First do some acrobatics to avoid trying to resolve addresses with leading // or trailing whitespace, which is easily pasted in with an IP address. // We can trivially skip whitespace at the beginning, but we need a copy to // omit whitespace at the end. while (std::isspace(*szDirectJoinAddress)) // skip whitespace at the beginning ++szDirectJoinAddress; if (!*szDirectJoinAddress) // entry empty, apart from whitespace return true; const char *szDirectJoinAddressEnd = szDirectJoinAddress + std::strlen(szDirectJoinAddress) - 1; while (std::isspace(*szDirectJoinAddressEnd)) // skip whitespace at the end --szDirectJoinAddressEnd; if (*++szDirectJoinAddressEnd) { // Make a temporary copy of the part that is not trailing whitespace, if any std::string strDirectJoinAddressStripped(szDirectJoinAddress, szDirectJoinAddressEnd - szDirectJoinAddress); AddReferenceQuery(strDirectJoinAddressStripped.c_str(), C4StartupNetListEntry::NRQT_DirectJoin); } else AddReferenceQuery(szDirectJoinAddress, C4StartupNetListEntry::NRQT_DirectJoin); // Switch focus to list so another OK joins the specified address SetFocus(pGameSelList, true); return true; } } if (GetFocus() == pSearchFieldEdt) { UpdateList(); return true; } // get currently selected item C4GUI::Element *pSelection = pGameSelList->GetSelectedItem(); StdCopyStrBuf strNoJoin(LoadResStr("IDS_NET_NOJOIN")); if (!pSelection) { // no ref selected: Oh noes! ::pGUI->ShowMessageModal( LoadResStr("IDS_NET_NOJOIN_NOREF"), strNoJoin.getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error); return true; } C4StartupNetListEntry *pRefEntry = static_cast<C4StartupNetListEntry *>(pSelection); const char *szError; if ((szError = pRefEntry->GetError())) { // erroneous ref selected: Oh noes! ::pGUI->ShowMessageModal( FormatString(LoadResStr("IDS_NET_NOJOIN_BADREF"), szError).getData(), strNoJoin.getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error); return true; } C4Network2Reference *pRef = pRefEntry->GetReference(); const char *szDirectJoinAddress = pRefEntry->GetJoinAddress(); if (!pRef && !(szDirectJoinAddress && *szDirectJoinAddress)) { // something strange has been selected (e.g., a masterserver entry). Error. ::pGUI->ShowMessageModal( LoadResStr("IDS_NET_NOJOIN_NOREF"), strNoJoin.getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error); return true; } // check if join to this reference is possible at all if (pRef) { // version mismatch C4GameVersion verThis; if (!(pRef->getGameVersion() == verThis)) { ::pGUI->ShowMessageModal( FormatString(LoadResStr("IDS_NET_NOJOIN_BADVER"), pRef->getGameVersion().GetString().getData(), verThis.GetString().getData()).getData(), strNoJoin.getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error); return true; } if (pRef->getGameStatus().isPastLobby()) { // no runtime join if (!pRef->isJoinAllowed()) { if (!::pGUI->ShowMessageModal( LoadResStr("IDS_NET_NOJOIN_NORUNTIME"), strNoJoin.getData(), C4GUI::MessageDialog::btnYes | C4GUI::MessageDialog::btnNo, C4GUI::Ico_Error)) { return true; } } else { if (!::pGUI->ShowMessageModal( LoadResStr("IDS_NET_NOJOIN_RUNTIMEBROKEN"), strNoJoin.getData(), C4GUI::MessageDialog::btnYes | C4GUI::MessageDialog::btnNo, C4GUI::Ico_Error)) { return true; } } } } // OK; joining! if (pRef->isEditor()) { bool success = false; // Editor mode join: Serialize reference to temp file and join on that // (could pass through environment, but that's hard to do platform-independent // (QProcessEnvironment? But then there's a Qt dependency in the network init code)) StdStrBuf tmpfn(Config.AtTempPath("ocjoin"), true); MakeTempFilename(&tmpfn); StdStrBuf join_data = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(*pRef, "Reference")); if (join_data.getSize()) { if (join_data.SaveToFile(tmpfn.getData())) { if (RestartApplication({"--editor", FormatString("--join=%s%s", C4Game::DirectJoinFilePrefix, tmpfn.getData()).getData()})) // hope for no " in temp path { // Application.Quit() has been called. Will quit after returning from this callback. // The temp file will be deleted by the new instance success = true; } else { EraseFile(tmpfn.getData()); } } } if (!success) { C4GUI::TheScreen.ShowErrorMessage(LoadResStr("IDS_ERR_STARTEDITOR")); } return true; } else { // Player mode join // Take over reference pRefEntry->GrabReference(); // Set join parameters *Game.ScenarioFilename = '\0'; if (szDirectJoinAddress) SCopy(szDirectJoinAddress, Game.DirectJoinAddress, _MAX_PATH); else *Game.DirectJoinAddress = '\0'; SCopy("Objects.ocd", Game.DefinitionFilenames); Game.NetworkActive = true; Game.fObserve = false; Game.pJoinReference.reset(pRef); // start with this set! Application.OpenGame(); return true; } }
C4AdditionalDefGraphics::C4AdditionalDefGraphics(C4Def *pOwnDef, const char *szName) : C4DefGraphics(pOwnDef) { // store name SCopy(szName, Name, C4MaxName); }
bool C4DefGraphics::Load(C4Group &hGroup, StdMeshSkeletonLoader &loader, bool fColorByOwner) { char Filename[_MAX_PATH+1]; *Filename=0; // load skeletons hGroup.ResetSearch(); while (hGroup.FindNextEntry("*", Filename, NULL, !!*Filename)) { if (!WildcardMatch(C4CFN_DefSkeleton, Filename) && !WildcardMatch(C4CFN_DefSkeletonXml, Filename)) continue; LoadSkeleton(hGroup, Filename, loader); } // Try from Mesh first if (!LoadMesh(hGroup, C4CFN_DefMesh, loader)) if(!LoadMesh(hGroup, C4CFN_DefMeshXml, loader)) LoadBitmap(hGroup, C4CFN_DefGraphics, C4CFN_ClrByOwner, C4CFN_NormalMap, fColorByOwner); // load additional graphics C4DefGraphics *pLastGraphics = this; const int32_t iOverlayWildcardPos = SCharPos('*', C4CFN_ClrByOwnerEx); hGroup.ResetSearch(); *Filename=0; const char* const AdditionalGraphics[] = { C4CFN_DefGraphicsEx, C4CFN_DefGraphicsExMesh, C4CFN_DefGraphicsExMeshXml, NULL }; while (hGroup.FindNextEntry("*", Filename, NULL, !!*Filename)) { for(const char* const* szWildcard = AdditionalGraphics; *szWildcard != NULL; ++szWildcard) { if(!WildcardMatch(*szWildcard, Filename)) continue; // skip def graphics if (SEqualNoCase(Filename, C4CFN_DefGraphics) || SEqualNoCase(Filename, C4CFN_DefMesh) || SEqualNoCase(Filename, C4CFN_DefMeshXml)) continue; // skip scaled def graphics if (WildcardMatch(C4CFN_DefGraphicsScaled, Filename)) continue; // get name char GrpName[_MAX_PATH+1]; const int32_t iWildcardPos = SCharPos('*', *szWildcard); SCopy(Filename + iWildcardPos, GrpName, _MAX_PATH); RemoveExtension(GrpName); // remove trailing number for scaled graphics int32_t extpos; int scale; if ((extpos = SCharLastPos('.', GrpName)) > -1) if (sscanf(GrpName+extpos+1, "%d", &scale) == 1) GrpName[extpos] = '\0'; // clip to max length GrpName[C4MaxName]=0; // create new graphics pLastGraphics->pNext = new C4AdditionalDefGraphics(pDef, GrpName); pLastGraphics = pLastGraphics->pNext; if(*szWildcard == AdditionalGraphics[0]) { // create overlay-filename char OverlayFn[_MAX_PATH+1]; if(fColorByOwner) { // GraphicsX.png -> OverlayX.png SCopy(C4CFN_ClrByOwnerEx, OverlayFn, _MAX_PATH); OverlayFn[iOverlayWildcardPos]=0; SAppend(Filename + iWildcardPos, OverlayFn); EnforceExtension(OverlayFn, GetExtension(C4CFN_ClrByOwnerEx)); } // create normal filename char NormalFn[_MAX_PATH+1]; SCopy(C4CFN_NormalMapEx, NormalFn, _MAX_PATH); NormalFn[iOverlayWildcardPos]=0; SAppend(Filename + iWildcardPos, NormalFn); EnforceExtension(NormalFn, GetExtension(C4CFN_NormalMapEx)); // load them if (!pLastGraphics->LoadBitmap(hGroup, Filename, fColorByOwner ? OverlayFn : NULL, NormalFn, fColorByOwner)) return false; } else { if (!pLastGraphics->LoadMesh(hGroup, Filename, loader)) return false; } } } // done, success return true; }
void C4Application::ParseCommandLine(int argc, char * argv[]) { StdStrBuf CmdLine("Command line:"); for(int i = 0; i < argc; ++i) { CmdLine.Append(" "); CmdLine.Append(argv[i]); } Log(CmdLine.getData()); ClearCommandLine(); Game.NetworkActive = false; isEditor = 2; int c; while (1) { static struct option long_options[] = { // option, w/ argument?, set directly, set to... {"editor", no_argument, &isEditor, 1}, {"fullscreen", no_argument, &isEditor, 0}, {"debugwait", no_argument, &Game.DebugWait, 1}, {"update", no_argument, &CheckForUpdates, 1}, {"noruntimejoin", no_argument, &Config.Network.NoRuntimeJoin, 1}, {"runtimejoin", no_argument, &Config.Network.NoRuntimeJoin, 0}, {"noleague", no_argument, &Config.Network.LeagueServerSignUp, 0}, {"league", no_argument, &Config.Network.LeagueServerSignUp, 1}, {"nosignup", no_argument, &Config.Network.MasterServerSignUp, 0}, {"signup", no_argument, &Config.Network.MasterServerSignUp, 1}, {"debugrecread", required_argument, 0, 'K'}, {"debugrecwrite", required_argument, 0, 'w'}, {"client", required_argument, 0, 'c'}, {"host", no_argument, 0, 'h'}, {"debughost", required_argument, 0, 'H'}, {"debugpass", required_argument, 0, 'P'}, {"debug", required_argument, 0, 'D'}, {"data", required_argument, 0, 'd'}, {"startup", required_argument, 0, 's'}, {"stream", required_argument, 0, 'e'}, {"recdump", required_argument, 0, 'R'}, {"comment", required_argument, 0, 'm'}, {"pass", required_argument, 0, 'p'}, {"udpport", required_argument, 0, 'u'}, {"tcpport", required_argument, 0, 't'}, {"join", required_argument, 0, 'j'}, {"language", required_argument, 0, 'L'}, {"scenpar", required_argument, 0, 'S'}, {"observe", no_argument, 0, 'o'}, {"nonetwork", no_argument, 0, 'N'}, {"network", no_argument, 0, 'n'}, {"record", no_argument, 0, 'r'}, {"lobby", required_argument, 0, 'l'}, {"debug-opengl", no_argument, &Config.Graphics.DebugOpenGL, 1}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "abc:d:f:", long_options, &option_index); // no more options if (c == -1) break; switch (c) { case 0: // Signup if (SEqualNoCase(long_options[option_index].name, "signup")) { Game.NetworkActive = true; } // League if (SEqualNoCase(long_options[option_index].name, "league")) { Game.NetworkActive = true; Config.Network.MasterServerSignUp = true; } break; // Lobby case 'l': Game.fLobby = true; // lobby timeout specified? (e.g. --lobby=120) if (optarg) { Game.iLobbyTimeout = atoi(optarg); if (Game.iLobbyTimeout < 0) Game.iLobbyTimeout = 0; } break; case 'o': Game.fObserve = true; break; // Direct join case 'j': Game.NetworkActive = true; SCopy(optarg, Game.DirectJoinAddress, _MAX_PATH); break; case 'K': if (optarg && optarg[0]) { LogF("Reading from DebugRec file '%s'", optarg); SCopy(optarg, Config.General.DebugRecExternalFile, _MAX_PATH); } else Log("Reading DebugRec from CtrlRec file in scenario record"); Config.General.DebugRec = 1; Config.General.DebugRecWrite = 0; break; case 'w': if (optarg && optarg[0]) { LogF("Writing to DebugRec file '%s'", optarg); SCopy(optarg, Config.General.DebugRecExternalFile, _MAX_PATH); } else Log("Writing DebugRec to CtrlRec file in scenario record"); Config.General.DebugRec = 1; Config.General.DebugRecWrite = 1; break; case 'r': Game.Record = true; break; case 'n': Game.NetworkActive = true; break; case 'N': Game.NetworkActive = false; break; // Language override by parameter case 'L': SCopy(optarg, Config.General.LanguageEx, CFG_MaxString); // port overrides case 't': Config.Network.PortTCP = atoi(optarg); break; case 'u': Config.Network.PortUDP = atoi(optarg); break; // network game password case 'p': Network.SetPassword(optarg); break; // network game comment case 'm': Config.Network.Comment.CopyValidated(optarg); break; // record dump case 'R': Game.RecordDumpFile.Copy(optarg); break; // record stream case 'e': Game.RecordStream.Copy(optarg); break; // startup start screen case 's': C4Startup::SetStartScreen(optarg); break; // additional read-only data path case 'd': Reloc.AddPath(optarg); break; // debug options case 'D': Game.DebugPort = atoi(optarg); break; case 'P': Game.DebugPassword = optarg; break; case 'H': Game.DebugHost = optarg; break; // set custom scenario parameter by command line case 'S': { StdStrBuf sopt, soptval; sopt.Copy(optarg); int32_t val=1; if (sopt.SplitAtChar('=', &soptval)) val=atoi(soptval.getData()); Game.StartupScenarioParameters.SetValue(sopt.getData(), val, false); } break; // debug configs case 'h': Game.NetworkActive = true; Game.fLobby = true; Config.Network.PortTCP = 11112; Config.Network.PortUDP = 11113; Config.Network.MasterServerSignUp = Config.Network.LeagueServerSignUp = false; break; case 'c': Game.NetworkActive = true; SCopy("localhost", Game.DirectJoinAddress, _MAX_PATH); Game.fLobby = true; Config.Network.PortTCP = 11112 + 2*(atoi(optarg)+1); Config.Network.PortUDP = 11113 + 2*(atoi(optarg)+1); break; case '?': /* getopt_long already printed an error message. */ break; default: assert(!"unexpected getopt_long return value"); } } if (!Config.Network.MasterServerSignUp) Config.Network.LeagueServerSignUp = false; if (Game.fObserve || Game.fLobby) Game.NetworkActive = true; while (optind < argc) { char * szParameter = argv[optind++]; { // Strip trailing / that result from tab-completing unpacked c4groups int iLen = SLen(szParameter); if (iLen > 5 && szParameter[iLen-1] == '/' && szParameter[iLen-5] == '.' && szParameter[iLen-4] == 'o' && szParameter[iLen-3] == 'c') { szParameter[iLen-1] = '\0'; } } // Scenario file if (SEqualNoCase(GetExtension(szParameter),"ocs")) { if(IsGlobalPath(szParameter)) Game.SetScenarioFilename(szParameter); else Game.SetScenarioFilename((std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str()); continue; } if (SEqualNoCase(GetFilename(szParameter),"scenario.txt")) { Game.SetScenarioFilename(szParameter); continue; } // Player file if (SEqualNoCase(GetExtension(szParameter),"ocp")) { if(IsGlobalPath(szParameter)) SAddModule(Game.PlayerFilenames, szParameter); else SAddModule(Game.PlayerFilenames, (std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str()); continue; } // Definition file if (SEqualNoCase(GetExtension(szParameter),"ocd")) { SAddModule(Game.DefinitionFilenames,szParameter); continue; } // Key file if (SEqualNoCase(GetExtension(szParameter),"c4k")) { Application.IncomingKeyfile.Copy(szParameter); continue; } // Update file if (SEqualNoCase(GetExtension(szParameter),"ocu")) { Application.IncomingUpdate.Copy(szParameter); continue; } // record stream if (SEqualNoCase(GetExtension(szParameter),"c4r")) { Game.RecordStream.Copy(szParameter); } // Direct join by URL if (SEqual2NoCase(szParameter, "clonk:")) { // Store address SCopy(szParameter + 6, Game.DirectJoinAddress, _MAX_PATH); SClearFrontBack(Game.DirectJoinAddress, '/'); // Special case: if the target address is "update" then this is used for update initiation by url if (SEqualNoCase(Game.DirectJoinAddress, "update")) { Application.CheckForUpdates = true; Game.DirectJoinAddress[0] = 0; continue; } // Self-enable network Game.NetworkActive = true; continue; } } #ifdef _WIN32 // Clean up some forward/backward slach confusion since many internal OC file functions cannot handle both SReplaceChar(Game.ScenarioFilename, AltDirectorySeparator, DirectorySeparator); SReplaceChar(Game.PlayerFilenames, AltDirectorySeparator, DirectorySeparator); SReplaceChar(Game.DefinitionFilenames, AltDirectorySeparator, DirectorySeparator); Application.IncomingKeyfile.ReplaceChar(AltDirectorySeparator, DirectorySeparator); Application.IncomingUpdate.ReplaceChar(AltDirectorySeparator, DirectorySeparator); Game.RecordStream.ReplaceChar(AltDirectorySeparator, DirectorySeparator); #endif // Default to editor if scenario given, player mode otherwise if (isEditor == 2) isEditor = !!*Game.ScenarioFilename && !Config.General.OpenScenarioInGameMode; // record? Game.Record = Game.Record || (Config.Network.LeagueServerSignUp && Game.NetworkActive); // startup dialog required? QuitAfterGame = !isEditor && Game.HasScenario(); }