OpenClonk
C4MessageInput Class Reference

#include <C4MessageInput.h>

Public Member Functions

 C4MessageInput ()
 
 ~C4MessageInput ()
 
void Default ()
 
void Clear ()
 
bool Init ()
 
void AddCommand (const char *strCommand, const char *strScript)
 
class C4MessageBoardCommandGetCommand (const char *strName)
 
bool CloseTypeIn ()
 
bool StartTypeIn (bool fObjInput=false, C4Object *pObj=nullptr, bool fUpperCase=false, bool fTeam=false, int32_t iPlr=-1, const StdStrBuf &rsInputQuery=StdStrBuf())
 
bool KeyStartTypeIn (bool fTeam)
 
bool ToggleTypeIn ()
 
bool IsTypeIn ()
 
C4ChatInputDialogGetTypeIn ()
 
void StoreBackBuffer (const char *szMessage)
 
const char * GetBackBuffer (int32_t iIndex)
 
bool ProcessInput (const char *szText)
 
bool ProcessCommand (const char *szCommand)
 
void ClearPointers (C4Object *pObj)
 
void AbortMsgBoardQuery (C4Object *pObj, int32_t iPlr)
 

Friends

class C4ChatInputDialog
 

Detailed Description

Definition at line 106 of file C4MessageInput.h.

Constructor & Destructor Documentation

◆ C4MessageInput()

C4MessageInput::C4MessageInput ( )
inline

Definition at line 109 of file C4MessageInput.h.

109 { Default(); }

References Default().

Here is the call graph for this function:

◆ ~C4MessageInput()

C4MessageInput::~C4MessageInput ( )
inline

Definition at line 110 of file C4MessageInput.h.

110 { Clear(); }

References Clear().

Here is the call graph for this function:

Member Function Documentation

◆ AbortMsgBoardQuery()

void C4MessageInput::AbortMsgBoardQuery ( C4Object pObj,
int32_t  iPlr 
)

Definition at line 859 of file C4MessageInput.cpp.

860 {
861  // close typein if it is used for the given parameters
862  C4ChatInputDialog *pDlg = GetTypeIn();
863  if (pDlg && pDlg->IsScriptQueried() && pDlg->GetScriptTargetObject() == pObj && pDlg->GetScriptTargetPlayer() == iPlr) CloseTypeIn();
864 }
class C4Object * GetScriptTargetObject() const
int32_t GetScriptTargetPlayer() const
bool IsScriptQueried() const
C4ChatInputDialog * GetTypeIn()

References CloseTypeIn(), C4ChatInputDialog::GetScriptTargetObject(), C4ChatInputDialog::GetScriptTargetPlayer(), GetTypeIn(), and C4ChatInputDialog::IsScriptQueried().

Here is the call graph for this function:

◆ AddCommand()

void C4MessageInput::AddCommand ( const char *  strCommand,
const char *  strScript 
)

Definition at line 833 of file C4MessageInput.cpp.

834 {
835  if (GetCommand(strCommand)) return;
836  // create entry
838  SCopy(strCommand, pCmd->Name, C4MaxName);
839  SCopy(strScript, pCmd->Script, _MAX_FNAME+30);
840  // add to list
841  pCmd->Next = pCommands; pCommands = pCmd;
842 }
const unsigned int C4MaxName
#define _MAX_FNAME
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:152
char Name[C4MaxName+1]
char Script[_MAX_FNAME_LEN+30]
C4MessageBoardCommand * Next
class C4MessageBoardCommand * GetCommand(const char *strName)

References _MAX_FNAME, C4MaxName, GetCommand(), C4MessageBoardCommand::Name, C4MessageBoardCommand::Next, SCopy(), and C4MessageBoardCommand::Script.

Referenced by Init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Clear()

void C4MessageInput::Clear ( )

Definition at line 253 of file C4MessageInput.cpp.

254 {
255  // close any dialog
256  CloseTypeIn();
257  // free messageboard-commands
258  C4MessageBoardCommand *pCmd;
259  while ((pCmd = pCommands))
260  {
261  pCommands = pCmd->Next;
262  delete pCmd;
263  }
264 }

References CloseTypeIn(), and C4MessageBoardCommand::Next.

Referenced by C4Game::Clear(), and ~C4MessageInput().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ClearPointers()

void C4MessageInput::ClearPointers ( C4Object pObj)

Definition at line 852 of file C4MessageInput.cpp.

853 {
854  // target object loose? stop input
855  C4ChatInputDialog *pDlg = GetTypeIn();
856  if (pDlg && pDlg->GetScriptTargetObject() == pObj) CloseTypeIn();
857 }

References CloseTypeIn(), C4ChatInputDialog::GetScriptTargetObject(), and GetTypeIn().

Referenced by C4Game::ClearPointers().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CloseTypeIn()

bool C4MessageInput::CloseTypeIn ( )

Definition at line 266 of file C4MessageInput.cpp.

267 {
268  // close dialog if present and valid
269  C4ChatInputDialog *pDlg = GetTypeIn();
270  if (!pDlg) return false;
271  pDlg->Close(false);
272  return true;
273 }
void Close(bool fOK)

References C4GUI::Dialog::Close(), and GetTypeIn().

Referenced by AbortMsgBoardQuery(), Clear(), ClearPointers(), StartTypeIn(), and ToggleTypeIn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Default()

void C4MessageInput::Default ( )

Definition at line 247 of file C4MessageInput.cpp.

248 {
249  // clear backlog
250  for (auto & cnt : BackBuffer) cnt[0]=0;
251 }

Referenced by C4MessageInput(), and C4Game::Default().

Here is the caller graph for this function:

◆ GetBackBuffer()

const char * C4MessageInput::GetBackBuffer ( int32_t  iIndex)

Definition at line 880 of file C4MessageInput.cpp.

881 {
882  if (!Inside<int32_t>(iIndex, 0, C4MSGB_BackBufferMax-1)) return nullptr;
883  return BackBuffer[iIndex];
884 }
const int32_t C4MSGB_BackBufferMax

References C4MSGB_BackBufferMax.

Referenced by C4GameLobby::MainDlg::KeyHistoryUpDown().

Here is the caller graph for this function:

◆ GetCommand()

C4MessageBoardCommand * C4MessageInput::GetCommand ( const char *  strName)

Definition at line 844 of file C4MessageInput.cpp.

845 {
846  for (C4MessageBoardCommand *pCmd = pCommands; pCmd; pCmd = pCmd->Next)
847  if (SEqual(pCmd->Name, strName))
848  return pCmd;
849  return nullptr;
850 }
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93

References C4MessageBoardCommand::Next, and SEqual().

Referenced by AddCommand(), and ProcessCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTypeIn()

C4ChatInputDialog* C4MessageInput::GetTypeIn ( )
inline

Definition at line 133 of file C4MessageInput.h.

133 { return C4ChatInputDialog::GetInstance(); }
static C4ChatInputDialog * GetInstance()

References C4ChatInputDialog::GetInstance().

Referenced by AbortMsgBoardQuery(), ClearPointers(), CloseTypeIn(), and ToggleTypeIn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Init()

bool C4MessageInput::Init ( )

Definition at line 237 of file C4MessageInput.cpp.

238 {
239  // add default commands
240  if (!pCommands)
241  {
242  AddCommand("speed", "SetGameSpeed(%d)");
243  }
244  return true;
245 }
void AddCommand(const char *strCommand, const char *strScript)

References AddCommand().

Referenced by C4Game::PreInit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsTypeIn()

bool C4MessageInput::IsTypeIn ( )

Definition at line 305 of file C4MessageInput.cpp.

306 {
307  // check GUI and dialog
309 }
static bool IsShown()

References C4ChatInputDialog::IsShown().

Referenced by C4MessageBoard::Execute(), StartTypeIn(), and ToggleTypeIn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ KeyStartTypeIn()

bool C4MessageInput::KeyStartTypeIn ( bool  fTeam)

Definition at line 283 of file C4MessageInput.cpp.

284 {
285  // fullscreen only
286  if (Application.isEditor) return false;
287  // OK, start typing
288  return StartTypeIn(false, nullptr, false, fTeam);
289 }
C4Application Application
Definition: C4Globals.cpp:44
bool StartTypeIn(bool fObjInput=false, C4Object *pObj=nullptr, bool fUpperCase=false, bool fTeam=false, int32_t iPlr=-1, const StdStrBuf &rsInputQuery=StdStrBuf())

References Application, C4Application::isEditor, and StartTypeIn().

Referenced by C4Game::InitKeyboard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessCommand()

bool C4MessageInput::ProcessCommand ( const char *  szCommand)

Definition at line 426 of file C4MessageInput.cpp.

427 {
429  // command
430  // must be 1 char longer than the longest command only. If given commands are longer, they will be truncated, and such a command won't exist anyway
431  const int32_t MaxCommandLen = 20;
432  char szCmdName[MaxCommandLen + 1];
433  SCopyUntil(szCommand + 1, szCmdName, ' ', MaxCommandLen);
434  // parameter
435  const char *pCmdPar = SSearch(szCommand, " ");
436  if (!pCmdPar) pCmdPar = "";
437 
438  // CAUTION when implementing special commands (like /quit) here:
439  // those must not be executed when text is pasted, because that could crash the GUI system
440  // when there are additional lines to paste, but the edit field is destructed by the command
441 
442  // lobby-only commands
443  if (!Game.IsRunning && SEqualNoCase(szCmdName, "joinplr"))
444  {
445  // compose path from given filename
446  StdStrBuf plrPath;
447  plrPath.Format("%s%s", Config.General.UserDataPath, pCmdPar);
448  // player join - check filename
449  if (!ItemExists(plrPath.getData()))
450  {
451  C4GameLobby::LobbyError(FormatString(LoadResStr("IDS_MSG_CMD_JOINPLR_NOFILE"), plrPath.getData()).getData());
452  }
453  else
455  return true;
456  }
457  if (!Game.IsRunning && SEqualNoCase(szCmdName, "plrclr"))
458  {
459  // get player name from input text
460  int iSepPos = SCharPos(' ', pCmdPar, 0);
461  C4PlayerInfo *pNfo=nullptr;
462  int32_t idLocalClient = -1;
463  if (::Network.Clients.GetLocal()) idLocalClient = ::Network.Clients.GetLocal()->getID();
464  if (iSepPos>0)
465  {
466  // a player name is given: Parse it
467  StdStrBuf sPlrName;
468  sPlrName.Copy(pCmdPar, iSepPos);
469  pCmdPar += iSepPos+1; int32_t id=0;
470  while ((pNfo = Game.PlayerInfos.GetNextPlayerInfoByID(id)))
471  {
472  id = pNfo->GetID();
473  if (WildcardMatch(sPlrName.getData(), pNfo->GetName())) break;
474  }
475  }
476  else
477  // no player name: Set local player
478  pNfo = Game.PlayerInfos.GetPrimaryInfoByClientID(idLocalClient);
479  C4ClientPlayerInfos *pCltNfo=nullptr;
480  if (pNfo) pCltNfo = Game.PlayerInfos.GetClientInfoByPlayerID(pNfo->GetID());
481  if (!pCltNfo)
482  {
483  C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_NOPLAYER"));
484  }
485  else
486  {
487  // may color of this client be set?
488  if (pCltNfo->GetClientID() != idLocalClient && !::Network.isHost())
489  {
490  C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_NOACCESS"));
491  }
492  else
493  {
494  // get color to set
495  uint32_t dwNewClr;
496  if (sscanf(pCmdPar, "%x", &dwNewClr) != 1)
497  {
498  C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_USAGE"));
499  }
500  else
501  {
502  // color validation
503  dwNewClr |= 0xff000000;
504  if (!dwNewClr) ++dwNewClr;
505  // request a color change to this color
506  C4ClientPlayerInfos LocalInfoRequest = *pCltNfo;
507  C4PlayerInfo *pPlrInfo = LocalInfoRequest.GetPlayerInfoByID(pNfo->GetID());
508  assert(pPlrInfo);
509  if (pPlrInfo)
510  {
511  pPlrInfo->SetOriginalColor(dwNewClr); // set this as a new color wish
512  ::Network.Players.RequestPlayerInfoUpdate(LocalInfoRequest);
513  }
514  }
515  }
516  }
517  return true;
518  }
519  if (!Game.IsRunning && SEqualNoCase(szCmdName, "start"))
520  {
521  // timeout given?
522  int32_t iTimeout = Config.Lobby.CountdownTime;
523  if (!::Network.isHost())
524  C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_HOSTONLY"));
525  else if (pCmdPar && *pCmdPar && (!sscanf(pCmdPar, "%d", &iTimeout) || iTimeout<0))
526  C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_START_USAGE"));
527  else if (pLobby)
528  {
529  // abort previous countdown
531  // start new countdown (aborts previous if necessary)
532  pLobby->Start(iTimeout);
533  }
534  else
535  {
536  if (iTimeout)
537  ::Network.StartLobbyCountdown(iTimeout);
538  else
539  ::Network.Start();
540  }
541  return true;
542  }
543  if (!Game.IsRunning && SEqualNoCase(szCmdName, "abort"))
544  {
545  if (!::Network.isHost())
546  C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_HOSTONLY"));
547  else if (::Network.isLobbyCountDown())
549  else
550  C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_ABORT_NOCOUNTDOWN"));
551  return true;
552  }
553 
554  if (SEqual(szCmdName, "help"))
555  {
556  Log(LoadResStr(pLobby ? "IDS_TEXT_COMMANDSAVAILABLEDURINGLO" : "IDS_TEXT_COMMANDSAVAILABLEDURINGGA"));
557  if (!Game.IsRunning)
558  {
559  LogF("/start [time] - %s", LoadResStr("IDS_TEXT_STARTTHEROUNDWITHSPECIFIE"));
560  LogF("/abort - %s", LoadResStr("IDS_TEXT_ABORTSTARTCOUNTDOWN"));
561  LogF("/alert - %s", LoadResStr("IDS_TEXT_ALERTTHEHOSTIFTHEHOSTISAW"));
562  LogF("/joinplr [filename] - %s", LoadResStr("IDS_TEXT_JOINALOCALPLAYERFROMTHESP"));
563  LogF("/plrclr [player] [RGB] - %s", LoadResStr("IDS_TEXT_CHANGETHECOLOROFTHESPECIF"));
564  LogF("/plrclr [RGB] - %s", LoadResStr("IDS_TEXT_CHANGEYOUROWNPLAYERCOLOR"));
565  }
566  else
567  {
568  LogF("/fast [x] - %s", LoadResStr("IDS_TEXT_SETTOFASTMODESKIPPINGXFRA"));
569  LogF("/slow - %s", LoadResStr("IDS_TEXT_SETTONORMALSPEEDMODE"));
570  LogF("/chart - %s", LoadResStr("IDS_TEXT_DISPLAYNETWORKSTATISTICS"));
571  LogF("/nodebug - %s", LoadResStr("IDS_TEXT_PREVENTDEBUGMODEINTHISROU"));
572  LogF("/script [script] - %s", LoadResStr("IDS_TEXT_EXECUTEASCRIPTCOMMAND"));
573  LogF("/screenshot [zoom] - %s", LoadResStr("IDS_TEXT_SAFEZOOMEDFULLSCREENSHOT"));
574  }
575  LogF("/kick [client] - %s", LoadResStr("IDS_TEXT_KICKTHESPECIFIEDCLIENT"));
576  LogF("/observer [client] - %s", LoadResStr("IDS_TEXT_SETTHESPECIFIEDCLIENTTOOB"));
577  LogF("/me [action] - %s", LoadResStr("IDS_TEXT_PERFORMANACTIONINYOURNAME"));
578  LogF("/sound [sound] - %s", LoadResStr("IDS_TEXT_PLAYASOUNDFROMTHEGLOBALSO"));
579  if (Game.IsRunning) LogF("/private [player] [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOTHES"));
580  LogF("/team [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOYOUR"));
581  LogF("/set comment [comment] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKCOMMENT"));
582  LogF("/set password [password] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKPASSWORD"));
583  LogF("/set maxplayer [number] - %s", LoadResStr("IDS_TEXT_SETANEWMAXIMUMNUMBEROFPLA"));
584  LogF("/todo [text] - %s", LoadResStr("IDS_TEXT_ADDTODO"));
585  LogF("/clear - %s", LoadResStr("IDS_MSG_CLEARTHEMESSAGEBOARD"));
586  return true;
587  }
588  // dev-scripts
589  if (SEqual(szCmdName, "script"))
590  {
591  if (!Game.IsRunning) return false;
592  if (!Game.DebugMode) return false;
593 
595  return true;
596  }
597  // set runtime properties
598  if (SEqual(szCmdName, "set"))
599  {
600  if (SEqual2(pCmdPar, "maxplayer "))
601  {
602  if (::Control.isCtrlHost())
603  {
604  if (atoi(pCmdPar+10) == 0 && !SEqual(pCmdPar+10, "0"))
605  {
606  Log("Syntax: /set maxplayer count");
607  return false;
608  }
610  new C4ControlSet(C4CVT_MaxPlayer, atoi(pCmdPar+10)),
611  CDT_Decide);
612  return true;
613  }
614  }
615  if (SEqual2(pCmdPar, "comment ") || SEqual(pCmdPar, "comment"))
616  {
617  if (!::Network.isEnabled() || !::Network.isHost()) return false;
618  // Set in configuration, update reference
619  Config.Network.Comment.CopyValidated(pCmdPar[7] ? (pCmdPar+8) : "");
621  Log(LoadResStr("IDS_NET_COMMENTCHANGED"));
622  return true;
623  }
624  if (SEqual2(pCmdPar, "password ") || SEqual(pCmdPar, "password"))
625  {
626  if (!::Network.isEnabled() || !::Network.isHost()) return false;
627  ::Network.SetPassword(pCmdPar[8] ? (pCmdPar+9) : nullptr);
628  if (pLobby) pLobby->UpdatePassword();
629  return true;
630  }
631  // unknown property
632  return false;
633  }
634  // get szen from network folder - not in lobby; use res tab there
635  if (SEqual(szCmdName, "netgetscen"))
636  {
637  if (::Network.isEnabled() && !::Network.isHost() && !pLobby)
638  {
639  const C4Network2ResCore *pResCoreScen = Game.Parameters.Scenario.getResCore();
640  if (pResCoreScen)
641  {
642  C4Network2Res::Ref pScenario = ::Network.ResList.getRefRes(pResCoreScen->getID());
643  if (pScenario)
645  {
646  LogF(LoadResStr("IDS_MSG_CMD_NETGETSCEN_SAVED"), Config.AtUserDataPath(GetFilename(Game.ScenarioFilename)));
647  return true;
648  }
649  }
650  }
651  return false;
652  }
653  // clear message board
654  if (SEqual(szCmdName, "clear"))
655  {
656  // lobby
657  if (pLobby)
658  {
659  pLobby->ClearLog();
660  }
661  // fullscreen
662  else if (::GraphicsSystem.MessageBoard)
663  ::GraphicsSystem.MessageBoard->ClearLog();
664  else
665  {
666  // EM mode
667  Console.ClearLog();
668  }
669  return true;
670  }
671  // kick client
672  if (SEqual(szCmdName, "kick"))
673  {
674  if (::Network.isEnabled() && ::Network.isHost())
675  {
676  // find client
677  C4Client *pClient = Game.Clients.getClientByName(pCmdPar);
678  if (!pClient)
679  {
680  LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar);
681  return false;
682  }
683  // league: Kick needs voting
684  if (Game.Parameters.isLeague() && ::Players.GetAtClient(pClient->getID()))
685  ::Network.Vote(VT_Kick, true, pClient->getID());
686  else
687  // add control
688  Game.Clients.CtrlRemove(pClient, LoadResStr("IDS_MSG_KICKFROMMSGBOARD"));
689  }
690  return true;
691  }
692  // set fast mode
693  if (SEqual(szCmdName, "fast"))
694  {
695  if (!Game.IsRunning) return false;
696  int32_t iFS;
697  if ((iFS=atoi(pCmdPar)) == 0) return false;
698  // set frameskip and fullspeed flag
699  Game.FrameSkip=Clamp<int32_t>(iFS,1,500);
700  Game.FullSpeed=true;
701  // start calculation immediatly
703  return true;
704  }
705  // reset fast mode
706  if (SEqual(szCmdName, "slow"))
707  {
708  if (!Game.IsRunning) return false;
709  Game.FullSpeed=false;
710  Game.FrameSkip=1;
711  return true;
712  }
713 
714  if (SEqual(szCmdName, "nodebug"))
715  {
716  if (!Game.IsRunning) return false;
718  return true;
719  }
720 
721  // kick/activate/deactivate/observer
722  if (SEqual(szCmdName, "activate") || SEqual(szCmdName, "deactivate") || SEqual(szCmdName, "observer"))
723  {
724  if (!::Network.isEnabled() || !::Network.isHost())
725  { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return false; }
726  // search for client
727  C4Client *pClient = Game.Clients.getClientByName(pCmdPar);
728  if (!pClient)
729  {
730  LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar);
731  return false;
732  }
733  // what to do?
734  C4ControlClientUpdate *pCtrl = nullptr;
735  if (szCmdName[0] == 'a') // activate
736  pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, true);
737  else if (szCmdName[0] == 'd' && !Game.Parameters.isLeague()) // deactivate
738  pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, false);
739  else if (szCmdName[0] == 'o' && !Game.Parameters.isLeague()) // observer
740  pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_SetObserver);
741  // perform it
742  if (pCtrl)
744  else
745  Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE"));
746  return true;
747  }
748 
749  // control mode
750  if (SEqual(szCmdName, "centralctrl") || SEqual(szCmdName, "decentralctrl") || SEqual(szCmdName, "asyncctrl"))
751  {
752  if (!::Network.isEnabled() || !::Network.isHost())
753  { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return false; }
754  ::Network.SetCtrlMode(*szCmdName == 'c' ? CNM_Central : *szCmdName == 'd' ? CNM_Decentral : CNM_Async);
755  return true;
756  }
757 
758  // show chart
759  if (Game.IsRunning)
760  if (SEqual(szCmdName, "chart"))
761  return Game.ToggleChart();
762 
763  // whole map screenshot
764  if (SEqual(szCmdName, "screenshot"))
765  {
766  double zoom = atof(pCmdPar);
767  if (zoom<=0) zoom = 2;
768  ::GraphicsSystem.SaveScreenshot(true, zoom);
769  return true;
770  }
771 
772  // add to TODO list
773  if (SEqual(szCmdName, "todo"))
774  {
775  // must add something
776  if (!pCmdPar || !*pCmdPar) return false;
777  // try writing main file (usually {SCENARIO}/TODO.txt); if access is not possible, e.g. because scenario is packed, write to alternate file
778  const char *todo_filenames[] = { ::Config.Developer.TodoFilename, ::Config.Developer.AltTodoFilename };
779  bool success = false;
780  for (auto & i : todo_filenames)
781  {
782  StdCopyStrBuf todo_filename(i);
783  todo_filename.Replace("{USERPATH}", Config.General.UserDataPath);
784  int replacements = todo_filename.Replace("{SCENARIO}", Game.ScenarioFile.GetFullName().getData());
785  // sanity checks for writing scenario TODO file
786  if (replacements)
787  {
788  // entered in editor with no file open?
789  if (!::Game.ScenarioFile.IsOpen()) continue;
790  // not into packed
791  if (::Game.ScenarioFile.IsPacked()) continue;
792  // not into temp network file
793  if (::Control.isNetwork() && !::Control.isCtrlHost()) continue;
794  }
795  // try to append. May fail e.g. on packed scenario file, name getting too long, etc. Then fallback to alternate location.
796  CStdFile todo_file;
797  if (!todo_file.Append(todo_filename.getData())) continue;
798  if (!todo_file.WriteString(pCmdPar)) continue;
799  // check on file close because CStdFile may do a delayed write
800  if (!todo_file.Close()) continue;
801  success = true;
802  break;
803  }
804  // no message on success to avoid cluttering the chat during debug sessions
805  if (!success) Log(LoadResStr("IDS_ERR_TODO"));
806  return true;
807  }
808 
809  // custom command
810  C4MessageBoardCommand *pCmd;
811  if (Game.IsRunning)
812  if ((pCmd = GetCommand(szCmdName)))
813  {
814  // get player number of first local player; if multiple players
815  // share one computer, we can't distinguish between them anyway
816  int32_t player_num = NO_OWNER;
818  if (player) player_num = player->Number;
819 
820  // send command to network
821  ::Control.DoInput(CID_MsgBoardCmd, new C4ControlMsgBoardCmd(szCmdName, pCmdPar, player_num), CDT_Decide);
822 
823  // ok
824  return true;
825  }
826 
827  // unknown command
828  StdStrBuf sErr; sErr.Format(LoadResStr("IDS_ERR_UNKNOWNCMD"), szCmdName);
829  if (pLobby) pLobby->OnError(sErr.getData()); else Log(sErr.getData());
830  return false;
831 }
C4Config Config
Definition: C4Config.cpp:930
const int NO_OWNER
Definition: C4Constants.h:137
@ C4CVT_MaxPlayer
Definition: C4Control.h:105
@ C4CVT_DisableDebug
Definition: C4Control.h:104
@ CUT_SetObserver
Definition: C4Control.h:367
@ CUT_Activate
Definition: C4Control.h:367
@ VT_Kick
Definition: C4Control.h:563
C4GameControl Control
@ CDT_Decide
Definition: C4GameControl.h:39
@ CDT_Sync
Definition: C4GameControl.h:35
@ CNM_Async
@ CNM_Decentral
@ CNM_Central
C4Game Game
Definition: C4Globals.cpp:52
C4Console Console
Definition: C4Globals.cpp:45
C4Network2 Network
Definition: C4Globals.cpp:53
C4GraphicsSystem GraphicsSystem
Definition: C4Globals.cpp:51
bool C4Group_CopyItem(const char *source, const char *target, bool no_sorting, bool reset_attributes)
Definition: C4Group.cpp:115
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool Log(const char *szMessage)
Definition: C4Log.cpp:204
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:262
@ CID_MsgBoardCmd
Definition: C4PacketBase.h:156
@ CID_Script
Definition: C4PacketBase.h:154
@ CID_Set
Definition: C4PacketBase.h:153
@ CID_ClientUpdate
Definition: C4PacketBase.h:145
C4PlayerList Players
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:369
int SCharPos(char cTarget, const char *szInStr, int iIndex)
Definition: Standard.cpp:239
bool SEqual2(const char *szStr1, const char *szStr2)
Definition: Standard.cpp:204
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:213
void SCopyUntil(const char *szSource, char *sTarget, char cUntil, int iMaxL, int iIndex)
Definition: Standard.cpp:172
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
bool WildcardMatch(const char *szWildcard, const char *szString)
Definition: StdFile.cpp:396
char * GetFilename(char *szPath)
Definition: StdFile.cpp:42
bool ItemExists(const char *szItemName)
Definition: StdFile.h:75
int32_t getID() const
Definition: C4Client.h:105
void CtrlRemove(const C4Client *pClient, const char *szReason)
Definition: C4Client.cpp:333
C4Client * getClientByName(const char *szName) const
Definition: C4Client.cpp:216
int32_t GetClientID() const
Definition: C4PlayerInfo.h:257
C4PlayerInfo * GetPlayerInfoByID(int32_t id) const
char AltTodoFilename[CFG_MaxString+1]
Definition: C4Config.h:86
char TodoFilename[CFG_MaxString+1]
Definition: C4Config.h:85
char UserDataPath[CFG_MaxString+1]
Definition: C4Config.h:56
C4ConfigGeneral General
Definition: C4Config.h:255
C4ConfigNetwork Network
Definition: C4Config.h:259
const char * AtUserDataPath(const char *filename)
Definition: C4Config.cpp:586
C4ConfigLobby Lobby
Definition: C4Config.h:260
C4ConfigDeveloper Developer
Definition: C4Config.h:256
int32_t CountdownTime
Definition: C4Config.h:201
ValidatedStdCopyStrBuf< C4InVal::VAL_Comment > Comment
Definition: C4Config.h:146
bool ClearLog()
Definition: C4Console.cpp:667
bool isCtrlHost() const
Definition: C4GameControl.h:99
void DoInput(C4PacketType eCtrlType, C4ControlPacket *pPkt, C4ControlDeliveryType eDelivery)
bool isNetwork() const
Definition: C4GameControl.h:97
bool FullSpeed
Definition: C4Game.h:137
bool IsRunning
Definition: C4Game.h:140
bool ToggleChart()
Definition: C4Game.cpp:4540
char ScenarioFilename[_MAX_PATH_LEN]
Definition: C4Game.h:102
C4ClientList & Clients
Definition: C4Game.h:69
C4PlayerInfoList & PlayerInfos
Definition: C4Game.h:71
int32_t FrameSkip
Definition: C4Game.h:138
C4GameParameters & Parameters
Definition: C4Game.h:67
bool DebugMode
Definition: C4Game.h:145
C4Group ScenarioFile
Definition: C4Game.h:86
void Start(int32_t iCountdownTime)
void OnError(const char *szErrMsg)
bool isLeague() const
const C4Network2ResCore * getResCore() const
bool SaveScreenshot(bool save_all, float zoom_factor_all)
std::unique_ptr< C4MessageBoard > MessageBoard
bool IsPacked() const
Definition: C4Group.cpp:2541
StdStrBuf GetFullName() const
Definition: C4Group.cpp:2638
bool IsOpen() const
Definition: C4Group.cpp:2373
int32_t getID() const
C4Network2Client * GetLocal() const
C4Network2Players Players
Definition: C4Network2.h:119
C4Network2ResList ResList
Definition: C4Network2.h:113
void AbortLobbyCountdown()
class C4GameLobby::MainDlg * GetLobby() const
Definition: C4Network2.h:216
void InvalidateReference()
bool isEnabled() const
Definition: C4Network2.h:203
bool isHost() const
Definition: C4Network2.h:209
void Vote(C4ControlVoteType eType, bool fApprove=true, int32_t iData=0)
void SetCtrlMode(int32_t iCtrlMode)
Definition: C4Network2.cpp:819
void SetPassword(const char *szToPassword)
Definition: C4Network2.cpp:772
bool isLobbyCountDown()
Definition: C4Network2.h:297
C4Network2ClientList Clients
Definition: C4Network2.h:116
bool Start()
Definition: C4Network2.cpp:506
void StartLobbyCountdown(int32_t iCountdownTime)
bool JoinLocalPlayer(const char *szLocalPlayerFilename, bool initial=false)
void RequestPlayerInfoUpdate(const class C4ClientPlayerInfos &rRequest)
int32_t getID() const
Definition: C4Network2Res.h:86
const char * getFile() const
C4Network2Res::Ref getRefRes(int32_t iResID)
void SetOriginalColor(DWORD dwUseClr)
Definition: C4PlayerInfo.h:116
int32_t GetID() const
Definition: C4PlayerInfo.h:194
const char * GetName() const
Definition: C4PlayerInfo.h:157
C4PlayerInfo * GetPrimaryInfoByClientID(int32_t iClientID) const
Definition: C4PlayerInfo.h:376
C4PlayerInfo * GetNextPlayerInfoByID(int32_t id) const
C4ClientPlayerInfos * GetClientInfoByPlayerID(int32_t id) const
C4Player * GetAtClient(int iClient, int iIndex=0) const
C4Player * GetLocalByIndex(int iIndex) const
bool Close(StdBuf **ppMemory=nullptr)
Definition: CStdFile.cpp:151
bool WriteString(const char *szStr)
Definition: CStdFile.cpp:264
bool Append(const char *szFilename, bool text=false)
Definition: CStdFile.cpp:132
const char * getData() const
Definition: StdBuf.h:442
void Copy()
Definition: StdBuf.h:467
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
void LobbyError(const char *szErrorMsg)
void CopyValidated(const char *szFromVal)

References C4Network2::AbortLobbyCountdown(), C4ConfigDeveloper::AltTodoFilename, CStdFile::Append(), Application, C4Config::AtUserDataPath(), C4CVT_DisableDebug, C4CVT_MaxPlayer, C4Group_CopyItem(), CDT_Decide, CDT_Sync, CID_ClientUpdate, CID_MsgBoardCmd, CID_Script, CID_Set, C4ConsoleGUI::ClearLog(), C4GameLobby::MainDlg::ClearLog(), C4Game::Clients, C4Network2::Clients, CStdFile::Close(), CNM_Async, CNM_Central, CNM_Decentral, C4ConfigNetwork::Comment, Config, Console, Control, StdStrBuf::Copy(), ValidatedStdCopyStrBufBase::CopyValidated(), C4ConfigLobby::CountdownTime, C4ClientList::CtrlRemove(), CUT_Activate, CUT_SetObserver, C4Game::DebugMode, C4Config::Developer, C4GameControl::DoInput(), StdStrBuf::Format(), FormatString(), C4Game::FrameSkip, C4Game::FullSpeed, Game, C4Config::General, C4PlayerList::GetAtClient(), C4ClientList::getClientByName(), C4ClientPlayerInfos::GetClientID(), C4PlayerInfoList::GetClientInfoByPlayerID(), GetCommand(), StdStrBuf::getData(), C4Network2Res::getFile(), GetFilename(), C4Group::GetFullName(), C4PlayerInfo::GetID(), C4Client::getID(), C4Network2Client::getID(), C4Network2ResCore::getID(), C4Network2::GetLobby(), C4Network2ClientList::GetLocal(), C4PlayerList::GetLocalByIndex(), C4PlayerInfo::GetName(), C4PlayerInfoList::GetNextPlayerInfoByID(), C4ClientPlayerInfos::GetPlayerInfoByID(), C4PlayerInfoList::GetPrimaryInfoByClientID(), C4Network2ResList::getRefRes(), C4GameRes::getResCore(), GraphicsSystem, C4Network2::InvalidateReference(), C4GameControl::isCtrlHost(), C4Network2::isEnabled(), C4Network2::isHost(), C4GameParameters::isLeague(), C4Network2::isLobbyCountDown(), C4GameControl::isNetwork(), C4Group::IsOpen(), C4Group::IsPacked(), C4Game::IsRunning, ItemExists(), C4Network2Players::JoinLocalPlayer(), LoadResStr(), C4Config::Lobby, C4GameLobby::LobbyError(), Log(), LogF(), C4GraphicsSystem::MessageBoard, Network, C4Config::Network, C4Application::NextTick(), NO_OWNER, C4GameLobby::MainDlg::OnError(), C4Game::Parameters, C4ScriptGuiWindowPropertyName::player, C4Game::PlayerInfos, C4Network2::Players, Players, StdStrBuf::Replace(), C4Network2Players::RequestPlayerInfoUpdate(), C4Network2::ResList, C4GraphicsSystem::SaveScreenshot(), C4GameParameters::Scenario, C4Game::ScenarioFile, C4Game::ScenarioFilename, SCharPos(), C4ControlScript::SCOPE_Console, SCopyUntil(), SEqual(), SEqual2(), SEqualNoCase(), C4Network2::SetCtrlMode(), C4PlayerInfo::SetOriginalColor(), C4Network2::SetPassword(), SSearch(), C4Network2::Start(), C4GameLobby::MainDlg::Start(), C4Network2::StartLobbyCountdown(), C4ConfigDeveloper::TodoFilename, C4Game::ToggleChart(), C4GameLobby::MainDlg::UpdatePassword(), C4ConfigGeneral::UserDataPath, C4Network2::Vote(), VT_Kick, WildcardMatch(), and CStdFile::WriteString().

Referenced by C4Console::In(), and ProcessInput().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessInput()

bool C4MessageInput::ProcessInput ( const char *  szText)

Definition at line 311 of file C4MessageInput.cpp.

312 {
313  // helper variables
314  char OSTR[402]; // cba
315  C4ControlMessageType eMsgType;
316  const char *szMsg = nullptr;
317  int32_t iToPlayer = -1;
318 
319  // Starts with '^', "team:" or "/team ": Team message
320  if (szText[0] == '^' || SEqual2NoCase(szText, "team:") || SEqual2NoCase(szText, "/team "))
321  {
322  if (!Game.Teams.IsTeamVisible())
323  {
324  // team not known; can't send!
325  Log(LoadResStr("IDS_MSG_CANTSENDTEAMMESSAGETEAMSN"));
326  return false;
327  }
328  else
329  {
330  eMsgType = C4CMT_Team;
331  szMsg = szText[0] == '^' ? szText+1 :
332  szText[0] == '/' ? szText+6 : szText+5;
333  }
334  }
335  // Starts with "/private ": Private message (running game only)
336  else if (Game.IsRunning && SEqual2NoCase(szText, "/private "))
337  {
338  // get target name
339  char szTargetPlr[C4MaxName + 1];
340  SCopyUntil(szText + 9, szTargetPlr, ' ', C4MaxName);
341  // search player
342  C4Player *pToPlr = ::Players.GetByName(szTargetPlr);
343  if (!pToPlr) return false;
344  // set
345  eMsgType = C4CMT_Private;
346  iToPlayer = pToPlr->Number;
347  szMsg = szText + 10 + SLen(szText);
348  if (szMsg > szText + SLen(szText)) return false;
349  }
350  // Starts with "/me ": Me-Message
351  else if (SEqual2NoCase(szText, "/me "))
352  {
353  eMsgType = C4CMT_Me;
354  szMsg = szText+4;
355  }
356  // Starts with "/sound ": Sound-Message
357  else if (SEqual2NoCase(szText, "/sound "))
358  {
359  eMsgType = C4CMT_Sound;
360  szMsg = szText+7;
361  }
362  // Disabled due to spamming
363  // Starts with "/alert": Taskbar flash (message optional)
364  else if (SEqual2NoCase(szText, "/alert ") || SEqualNoCase(szText, "/alert"))
365  {
366  eMsgType = C4CMT_Alert;
367  szMsg = szText+6;
368  if (*szMsg) ++szMsg;
369  }
370  // Starts with '"': Let the clonk say it
371  else if (Game.IsRunning && szText[0] == '"')
372  {
373  eMsgType = C4CMT_Say;
374  // Append '"', if neccessary
375  StdStrBuf text(szText);
376  SCopy(szText, OSTR, 400);
377  char *pEnd = OSTR + SLen(OSTR) - 1;
378  if (*pEnd != '"') { *++pEnd = '"'; *++pEnd = 0; }
379  szMsg = OSTR;
380  }
381  // Starts with '/': Command
382  else if (szText[0] == '/')
383  return ProcessCommand(szText);
384  // Regular message
385  else
386  {
387  eMsgType = C4CMT_Normal;
388  szMsg = szText;
389  }
390 
391  // message?
392  if (szMsg)
393  {
394  char szMessage[C4MaxMessage + 1];
395  // go over whitespaces, check empty message
396  while (IsWhiteSpace(*szMsg)) szMsg++;
397  if (!*szMsg)
398  {
399  if (eMsgType != C4CMT_Alert) return true;
400  *szMessage = '\0';
401  }
402  else
403  {
404  // trim right
405  const char *szEnd = szMsg + SLen(szMsg) - 1;
406  while (IsWhiteSpace(*szEnd) && szEnd >= szMsg) szEnd--;
407  // Say: Strip quotation marks in cinematic film mode
409  {
410  if (eMsgType == C4CMT_Say) { ++szMsg; szEnd--; }
411  }
412  // get message
413  SCopy(szMsg, szMessage, std::min<ptrdiff_t>(C4MaxMessage, szEnd - szMsg + 1));
414  }
415  // get sending player (if any)
416  C4Player *pPlr = Game.IsRunning ? ::Players.GetLocalByIndex(0) : nullptr;
417  // send
419  new C4ControlMessage(eMsgType, szMessage, pPlr ? pPlr->Number : -1, iToPlayer),
420  CDT_Private);
421  }
422 
423  return true;
424 }
const int C4MaxMessage
Definition: C4Constants.h:28
C4ControlMessageType
Definition: C4Control.h:506
@ C4CMT_Normal
Definition: C4Control.h:507
@ C4CMT_Sound
Definition: C4Control.h:512
@ C4CMT_Say
Definition: C4Control.h:509
@ C4CMT_Alert
Definition: C4Control.h:513
@ C4CMT_Team
Definition: C4Control.h:510
@ C4CMT_Me
Definition: C4Control.h:508
@ C4CMT_Private
Definition: C4Control.h:511
@ CDT_Private
Definition: C4GameControl.h:37
@ CID_Message
Definition: C4PacketBase.h:165
@ C4SFilm_Cinematic
Definition: C4Scenario.h:57
bool SEqual2NoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:226
bool IsWhiteSpace(char cChar)
Definition: Standard.h:72
size_t SLen(const char *sptr)
Definition: Standard.h:74
C4TeamList & Teams
Definition: C4Game.h:70
C4Scenario C4S
Definition: C4Game.h:74
bool ProcessCommand(const char *szCommand)
int32_t Number
Definition: C4Player.h:86
C4Player * GetByName(const char *szName, int iExcluding=NO_OWNER) const
int32_t Film
Definition: C4Scenario.h:73
C4SHead Head
Definition: C4Scenario.h:232
bool IsTeamVisible() const
Definition: C4Teams.cpp:454

References C4CMT_Alert, C4CMT_Me, C4CMT_Normal, C4CMT_Private, C4CMT_Say, C4CMT_Sound, C4CMT_Team, C4MaxMessage, C4MaxName, C4Game::C4S, C4SFilm_Cinematic, CDT_Private, CID_Message, Control, C4GameControl::DoInput(), C4SHead::Film, Game, C4PlayerList::GetByName(), C4PlayerList::GetLocalByIndex(), C4Scenario::Head, C4Game::IsRunning, C4TeamList::IsTeamVisible(), IsWhiteSpace(), LoadResStr(), Log(), C4Player::Number, Players, ProcessCommand(), SCopy(), SCopyUntil(), SEqual2NoCase(), SEqualNoCase(), SLen(), C4Game::Teams, and C4ScriptGuiWindowPropertyName::text.

Referenced by C4Console::In(), C4GameLobby::MainDlg::OnChatInput(), C4ChatInputDialog::OnChatInput(), and C4Application::OnCommand().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StartTypeIn()

bool C4MessageInput::StartTypeIn ( bool  fObjInput = false,
C4Object pObj = nullptr,
bool  fUpperCase = false,
bool  fTeam = false,
int32_t  iPlr = -1,
const StdStrBuf rsInputQuery = StdStrBuf() 
)

Definition at line 275 of file C4MessageInput.cpp.

276 {
277  // close any previous
278  if (IsTypeIn()) CloseTypeIn();
279  // start new
280  return ::pGUI->ShowRemoveDlg(new C4ChatInputDialog(fObjInput, pObj, fUpperCase, fTeam, iPlr, rsInputQuery));
281 }
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
bool ShowRemoveDlg(Dialog *pDlg)
friend class C4ChatInputDialog

References C4ChatInputDialog, CloseTypeIn(), IsTypeIn(), pGUI, and C4GUI::Screen::ShowRemoveDlg().

Referenced by KeyStartTypeIn(), and ToggleTypeIn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StoreBackBuffer()

void C4MessageInput::StoreBackBuffer ( const char *  szMessage)

Definition at line 866 of file C4MessageInput.cpp.

867 {
868  if (!szMessage || !szMessage[0]) return;
869  int32_t i,cnt;
870  // Check: Remove doubled buffer
871  for (i=0; i<C4MSGB_BackBufferMax-1; ++i)
872  if (SEqual(BackBuffer[i], szMessage))
873  break;
874  // Move up buffers
875  for (cnt=i; cnt>0; cnt--) SCopy(BackBuffer[cnt-1],BackBuffer[cnt]);
876  // Add message
877  SCopy(szMessage,BackBuffer[0], C4MaxMessage);
878 }

References C4MaxMessage, C4MSGB_BackBufferMax, SCopy(), and SEqual().

Referenced by C4GameLobby::MainDlg::OnChatInput(), and C4ChatInputDialog::OnChatInput().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ToggleTypeIn()

bool C4MessageInput::ToggleTypeIn ( )

Definition at line 291 of file C4MessageInput.cpp.

292 {
293  // toggle off?
294  if (IsTypeIn())
295  {
296  // no accidental close of script queried dlgs by chat request
297  if (GetTypeIn()->IsScriptQueried()) return false;
298  return CloseTypeIn();
299  }
300  else
301  // toggle on!
302  return StartTypeIn();
303 }

References CloseTypeIn(), GetTypeIn(), IsTypeIn(), and StartTypeIn().

Here is the call graph for this function:

Friends And Related Function Documentation

◆ C4ChatInputDialog

friend class C4ChatInputDialog
friend

Definition at line 143 of file C4MessageInput.h.

Referenced by StartTypeIn().


The documentation for this class was generated from the following files: