C4Network2Res::Ref C4Network2ResList::AddByCore(const C4Network2ResCore &Core, bool fLoad) // by main thread { // already in list? C4Network2Res::Ref pRes = getRefRes(Core.getID()); if (pRes) return pRes; #ifdef C4NET2RES_LOAD_ALL // load without check (if possible) if (Core.isLoadable()) return AddLoad(Core); #endif // create new pRes = new C4Network2Res(this); // try set by core if (!pRes->SetByCore(Core, true)) { pRes.Clear(); // try load (if specified) return fLoad ? AddLoad(Core) : NULL; } // log Application.InteractiveThread.ThreadLogS("Network: Found identical %s. Not loading.", pRes->getCore().getFileName()); // add to list Add(pRes); // ok return pRes; }
C4Network2Res::Ref C4Network2ResList::AddByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName, bool fAllowUnloadable) { // already in list? C4Network2Res::Ref pRes = getRefRes(strFilePath); if (pRes) return pRes; // get resource ID if (iResID < 0) iResID = nextResID(); if (iResID < 0) { Log("AddByFile: no more resource IDs available!"); return NULL; } // create new pRes = new C4Network2Res(this); // initialize if (!pRes->SetByFile(strFilePath, fTemp, eType, iResID, szResName)) { return NULL; } // create standalone for non-system files // system files shouldn't create a standalone; they should never be marked loadable! if (eType != NRT_System) if (!pRes->GetStandalone(NULL, 0, true, fAllowUnloadable)) if (!fAllowUnloadable) { delete pRes; return NULL; } // add to list Add(pRes); return pRes; }
void C4Network2ResDlg::ListItem::LocalSaveResource(bool fDoOverwrite) { // get associated resource C4Network2Res::Ref pRes = GetRefRes(); if (!pRes) return; const char *szResFile = pRes->getFile(); StdCopyStrBuf strErrCopyFile(LoadResStr("IDS_NET_ERR_COPYFILE")); if (!pRes->isTempFile()) { GetScreen()->ShowMessage(LoadResStr("IDS_NET_ERR_COPYFILE_LOCAL"), strErrCopyFile.getData(), C4GUI::Ico_Error); return; } const char *szFilename = GetFilename(pRes->getCore().getFileName()); /* const char *szSpecialPath = ""; if (WildcardMatch(C4CFN_PlayerFiles, szFilename)) // write players to player path szSpecialPath = Config.General.PlayerPath; */ const char *szTarget = Config.AtUserDataPath(szFilename); if (!fDoOverwrite && ItemExists(szTarget)) { // show a confirmation dlg, asking whether the resource should be overwritten GetScreen()->ShowRemoveDlg(new C4GUI::ConfirmationDialog( FormatString(LoadResStr("IDS_NET_RES_SAVE_OVERWRITE"), GetFilename(szTarget)).getData(), LoadResStr("IDS_NET_RES_SAVE"), new C4GUI::CallbackHandler<C4Network2ResDlg::ListItem>(this, &C4Network2ResDlg::ListItem::OnButtonSaveConfirm), C4GUI::MessageDialog::btnYesNo)); return; } if (!C4Group_CopyItem(szResFile, szTarget)) GetScreen()->ShowMessage(strErrCopyFile.getData(), strErrCopyFile.getData(), C4GUI::Ico_Error); else { GetScreen()->ShowMessage(FormatString(LoadResStr("IDS_NET_RES_SAVED_DESC"), GetFilename(szTarget)).getData(), LoadResStr("IDS_NET_RES_SAVED"), C4GUI::Ico_Save); } }
C4Network2Res::Ref C4Network2Res::Derive() { // Called before the file is changed. Rescues all files and creates a // new resource for the file. This resource is flagged as "anonymous", as it // has no official core (no res ID, to be exact). // The resource gets its final core when FinishDerive() is called. // For security: This doesn't make much sense if the resource is currently being // loaded. So better assume the caller doesn't know what he's doing and check. if (isLoading()) return NULL; CStdLock FileLock(&FileCSec); // Save back original file name char szOrgFile[_MAX_PATH+1]; SCopy(szFile, szOrgFile, _MAX_PATH); bool fOrgTempFile = fTempFile; // Create a copy of the file, if neccessary if (!*szStandalone || SEqual(szStandalone, szFile)) { if (!pParent->FindTempResFileName(szOrgFile, szFile)) { Log("Derive: could not find free name for temporary file!"); return NULL; } if (!C4Group_CopyItem(szOrgFile, szFile)) { Log("Derive: could not copy to temporary file!"); return NULL; } // set standalone if (*szStandalone) SCopy(szFile, szStandalone, _MAX_PATH); fTempFile = true; } else { // Standlone exists: Just set szFile to point on the standlone. It's // assumed that the original file isn't of intrest after this point anyway. SCopy(szStandalone, szFile, _MAX_PATH); fTempFile = true; } Application.InteractiveThread.ThreadLogS("Network: Resource: deriving from %d:%s, original at %s", getResID(), Core.getFileName(), szFile); // (note: should remove temp file if something fails after this point) // create new resource C4Network2Res::Ref pDRes = new C4Network2Res(pParent); if (!pDRes) return NULL; // initialize if (!pDRes->SetDerived(Core.getFileName(), szOrgFile, fOrgTempFile, getType(), getResID())) return NULL; // add to list pParent->Add(pDRes); // return new resource return pDRes; }
C4Network2Res::Ref C4Network2ResList::AddLoad(const C4Network2ResCore &Core) // by main thread { // marked unloadable by creator? if (!Core.isLoadable()) { // show error msg Application.InteractiveThread.ThreadLog("Network: Cannot load %s (marked unloadable)", Core.getFileName()); return NULL; } // create new C4Network2Res::Ref pRes = new C4Network2Res(this); // initialize pRes->SetLoad(Core); // log Application.InteractiveThread.ThreadLogS("Network: loading %s...", Core.getFileName()); // add to list Add(pRes); return pRes; }
bool C4Network2ResDlg::ListItem::IsSavePossible() { // check resource bool fCanSave = false; C4Network2Res::Ref pRes = GetRefRes(); if (!pRes) return false; // temp files from network folder only if (pRes->isTempFile()) { // check type C4Network2ResType eType = pRes->getType(); if ((eType == NRT_Player && Config.Lobby.AllowPlayerSave) || eType == NRT_Scenario || eType == NRT_Definitions) // check complete if (!pRes->isLoading()) // save OK fCanSave = true; } return fCanSave; }
C4Network2Res::Ref C4Network2ResList::AddByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName, bool fAllowUnloadable) { // get resource ID if (iResID < 0) iResID = nextResID(); if (iResID < 0) { Log("AddByGroup: no more resource IDs available!"); return NULL; } // create new C4Network2Res::Ref pRes = new C4Network2Res(this); // initialize if (!pRes->SetByGroup(pGrp, fTemp, eType, iResID, szResName)) { delete pRes; return NULL; } // create standalone if (!pRes->GetStandalone(NULL, 0, true, fAllowUnloadable)) if (!fAllowUnloadable) { delete pRes; return NULL; } // add to list Add(pRes); return pRes; }
bool C4MessageInput::ProcessCommand(const char *szCommand) { C4GameLobby::MainDlg *pLobby = Game.Network.GetLobby(); // command char szCmdName[C4MaxName + 1]; SCopyUntil(szCommand + 1, szCmdName, ' ', C4MaxName); // parameter const char *pCmdPar = SSearch(szCommand, " "); if (!pCmdPar) pCmdPar = ""; // dev-scripts if (SEqual(szCmdName, "help")) { LogF(LoadResStr("IDS_TEXT_COMMANDSAVAILABLEDURINGGA")); LogF("/private [player] [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOTHES")); LogF("/team [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOYOUR")); LogF("/me [action] - %s", LoadResStr("IDS_TEXT_PERFORMANACTIONINYOURNAME")); LogF("/sound [sound] - %s", LoadResStr("IDS_TEXT_PLAYASOUNDFROMTHEGLOBALSO")); LogF("/kick [client] - %s", LoadResStr("IDS_TEXT_KICKTHESPECIFIEDCLIENT")); LogF("/observer [client] - %s", LoadResStr("IDS_TEXT_SETTHESPECIFIEDCLIENTTOOB")); LogF("/fast [x] - %s", LoadResStr("IDS_TEXT_SETTOFASTMODESKIPPINGXFRA")); LogF("/slow - %s", LoadResStr("IDS_TEXT_SETTONORMALSPEEDMODE")); LogF("/chart - %s", LoadResStr("IDS_TEXT_DISPLAYNETWORKSTATISTICS")); LogF("/nodebug - %s", LoadResStr("IDS_TEXT_PREVENTDEBUGMODEINTHISROU")); LogF("/set comment [comment] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKCOMMENT")); LogF("/set password [password] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKPASSWORD")); LogF("/set faircrew [on/off] - %s", LoadResStr("IDS_TEXT_ENABLEORDISABLEFAIRCREW")); LogF("/set maxplayer [4] - %s", LoadResStr("IDS_TEXT_SETANEWMAXIMUMNUMBEROFPLA")); LogF("/script [script] - %s", LoadResStr("IDS_TEXT_EXECUTEASCRIPTCOMMAND")); LogF("/clear - %s", LoadResStr("IDS_MSG_CLEARTHEMESSAGEBOARD")); return TRUE; } // dev-scripts if (SEqual(szCmdName, "script")) { if (!Game.IsRunning) return FALSE; if (!Game.DebugMode) return FALSE; if (!Game.Network.isEnabled() && !SEqual(Game.ScenarioFile.GetMaker(), Config.General.Name) && Game.ScenarioFile.GetStatus() != GRPF_Folder) return FALSE; if (Game.Network.isEnabled() && !Game.Network.isHost()) return FALSE; Game.Control.DoInput( CID_Script, new C4ControlScript(pCmdPar, C4ControlScript::SCOPE_Console, false), CDT_Decide); return TRUE; } // set runtimte properties if (SEqual(szCmdName, "set")) { if (SEqual2(pCmdPar, "maxplayer ")) { if (Game.Control.isCtrlHost()) { if (atoi(pCmdPar + 10) == 0 && !SEqual(pCmdPar + 10, "0")) { Log("Syntax: /set maxplayer count"); return FALSE; } Game.Control.DoInput( CID_Set, new C4ControlSet(C4CVT_MaxPlayer, atoi(pCmdPar + 10)), CDT_Decide); return TRUE; } } if (SEqual2(pCmdPar, "comment ") || SEqual(pCmdPar, "comment")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) return FALSE; // Set in configuration, update reference Config.Network.Comment.CopyValidated(pCmdPar[7] ? (pCmdPar + 8) : ""); Game.Network.InvalidateReference(); Log(LoadResStr("IDS_NET_COMMENTCHANGED")); return TRUE; } if (SEqual2(pCmdPar, "password ") || SEqual(pCmdPar, "password")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) return FALSE; Game.Network.SetPassword(pCmdPar[8] ? (pCmdPar + 9) : NULL); if (pLobby) pLobby->UpdatePassword(); return TRUE; } if (SEqual2(pCmdPar, "faircrew ")) { if (!Game.Control.isCtrlHost() || Game.Parameters.isLeague()) return FALSE; C4ControlSet *pSet = NULL; if (SEqual(pCmdPar + 9, "on")) pSet = new C4ControlSet(C4CVT_FairCrew, Config.General.FairCrewStrength); else if (SEqual(pCmdPar + 9, "off")) pSet = new C4ControlSet(C4CVT_FairCrew, -1); else if (isdigit((unsigned char)pCmdPar[9])) pSet = new C4ControlSet(C4CVT_FairCrew, atoi(pCmdPar + 9)); else return FALSE; Game.Control.DoInput(CID_Set, pSet, CDT_Decide); return TRUE; } // unknown property return FALSE; } // get szen from network folder - not in lobby; use res tab there if (SEqual(szCmdName, "netgetscen")) { if (Game.Network.isEnabled() && !Game.Network.isHost() && !pLobby) { const C4Network2ResCore *pResCoreScen = Game.Parameters.Scenario.getResCore(); if (pResCoreScen) { C4Network2Res::Ref pScenario = Game.Network.ResList.getRefRes(pResCoreScen->getID()); if (pScenario) if (C4Group_CopyItem( pScenario->getFile(), Config.AtExePath(GetFilename(Game.ScenarioFilename)))) { LogF(LoadResStr("IDS_MSG_CMD_NETGETSCEN_SAVED"), Config.AtExePath(GetFilename(Game.ScenarioFilename))); return TRUE; } } } return FALSE; } // clear message board if (SEqual(szCmdName, "clear")) { // lobby if (pLobby) { pLobby->ClearLog(); } // fullscreen else if (Game.GraphicsSystem.MessageBoard.Active) Game.GraphicsSystem.MessageBoard.ClearLog(); else { // EM mode Console.ClearLog(); } return TRUE; } // kick client if (SEqual(szCmdName, "kick")) { if (Game.Network.isEnabled() && Game.Network.isHost()) { // find client C4Client *pClient = Game.Clients.getClientByName(pCmdPar); if (!pClient) { LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar); return FALSE; } // league: Kick needs voting if (Game.Parameters.isLeague() && Game.Players.GetAtClient(pClient->getID())) Game.Network.Vote(VT_Kick, true, pClient->getID()); else // add control Game.Clients.CtrlRemove(pClient, LoadResStr("IDS_MSG_KICKFROMMSGBOARD")); } return TRUE; } // set fast mode if (SEqual(szCmdName, "fast")) { if (!Game.IsRunning) return FALSE; if (Game.Parameters.isLeague()) { Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return FALSE; } int32_t iFS; if ((iFS = atoi(pCmdPar)) == 0) return FALSE; // set frameskip and fullspeed flag Game.FrameSkip = BoundBy<int32_t>(iFS, 1, 500); Game.FullSpeed = TRUE; // start calculation immediatly Application.NextTick(false); return TRUE; } // reset fast mode if (SEqual(szCmdName, "slow")) { if (!Game.IsRunning) return FALSE; Game.FullSpeed = FALSE; Game.FrameSkip = 1; return TRUE; } if (SEqual(szCmdName, "nodebug")) { if (!Game.IsRunning) return FALSE; Game.Control.DoInput(CID_Set, new C4ControlSet(C4CVT_AllowDebug, false), CDT_Decide); return TRUE; } if (SEqual(szCmdName, "msgboard")) { if (!Game.IsRunning) return FALSE; // get line cnt int32_t iLineCnt = BoundBy(atoi(pCmdPar), 0, 20); if (iLineCnt == 0) Game.GraphicsSystem.MessageBoard.ChangeMode(2); else if (iLineCnt == 1) Game.GraphicsSystem.MessageBoard.ChangeMode(0); else { Game.GraphicsSystem.MessageBoard.iLines = iLineCnt; Game.GraphicsSystem.MessageBoard.ChangeMode(1); } return TRUE; } // kick/activate/deactivate/observer if (SEqual(szCmdName, "activate") || SEqual(szCmdName, "deactivate") || SEqual(szCmdName, "observer")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return FALSE; } // search for client C4Client *pClient = Game.Clients.getClientByName(pCmdPar); if (!pClient) { LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar); return FALSE; } // what to do? C4ControlClientUpdate *pCtrl = NULL; if (szCmdName[0] == 'a') // activate pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, true); else if (szCmdName[0] == 'd' && !Game.Parameters.isLeague()) // deactivate pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, false); else if (szCmdName[0] == 'o' && !Game.Parameters.isLeague()) // observer pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_SetObserver); // perform it if (pCtrl) Game.Control.DoInput(CID_ClientUpdate, pCtrl, CDT_Sync); else Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return TRUE; } // control mode if (SEqual(szCmdName, "centralctrl") || SEqual(szCmdName, "decentralctrl") || SEqual(szCmdName, "asyncctrl")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return FALSE; } if (Game.Parameters.isLeague() && *szCmdName == 'a') { Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return FALSE; } Game.Network.SetCtrlMode( *szCmdName == 'c' ? CNM_Central : *szCmdName == 'd' ? CNM_Decentral : CNM_Async); return TRUE; } // show chart if (Game.IsRunning) if (SEqual(szCmdName, "chart")) return Game.ToggleChart(); // custom command C4MessageBoardCommand *pCmd; if (Game.IsRunning) if (pCmd = GetCommand(szCmdName)) { StdStrBuf Script, CmdScript; // replace %player% by calling player number if (SSearch(pCmd->Script, "%player%")) { int32_t iLocalPlr = NO_OWNER; C4Player *pLocalPlr = Game.Players.GetLocalByIndex(0); if (pLocalPlr) iLocalPlr = pLocalPlr->Number; StdStrBuf sLocalPlr; sLocalPlr.Format("%d", iLocalPlr); CmdScript.Copy(pCmd->Script); CmdScript.Replace("%player%", sLocalPlr.getData()); } else { CmdScript.Ref(pCmd->Script); } // insert parameters if (SSearch(CmdScript.getData(), "%d")) { // make sure it's a number by converting Script.Format(CmdScript.getData(), (int)atoi(pCmdPar)); } else if (SSearch(CmdScript.getData(), "%s")) { // Unrestricted parameters? // That's kind of a security risk as it will allow anyone to execute // code switch (pCmd->eRestriction) { case C4MessageBoardCommand::C4MSGCMDR_Escaped: { // escape strings StdStrBuf Par; Par.Copy(pCmdPar); Par.EscapeString(); // compose script Script.Format(CmdScript.getData(), Par.getData()); } break; case C4MessageBoardCommand::C4MSGCMDR_Plain: // unescaped Script.Format(CmdScript.getData(), pCmdPar); break; case C4MessageBoardCommand::C4MSGCMDR_Identifier: { // only allow identifier-characters StdStrBuf Par; while (IsIdentifier(*pCmdPar) || isspace((unsigned char)*pCmdPar)) Par.AppendChar(*pCmdPar++); // compose script Script.Format(CmdScript.getData(), Par.getData()); } break; } } else Script = CmdScript.getData(); // add script Game.Control.DoInput(CID_Script, new C4ControlScript(Script.getData()), CDT_Decide); // ok return TRUE; } // unknown command StdStrBuf sErr; sErr.Format(LoadResStr("IDS_ERR_UNKNOWNCMD"), szCmdName); if (pLobby) pLobby->OnError(sErr.getData()); else Log(sErr.getData()); return FALSE; }