Make network lobby command line processing available to the editor and dedi

Most of the processing was already done by C4MessageInput::ProcessInput and
C4MessageInput::ProcessCommand. Simply move the Lobby-only commands there,
too, and make them work without a Lobby MainDlg. This required almost only
cosmetic changes.
stable-5.3
Günther Brammer 2012-11-30 22:07:08 +01:00
parent acc37860ed
commit d5d72344ef
4 changed files with 151 additions and 175 deletions

View File

@ -446,164 +446,7 @@ namespace C4GameLobby
// store input in backbuffer before processing commands
// because those might kill the edit field
::MessageInput.StoreBackBuffer(szInputText);
bool fProcessed = false;
// CAUTION when implementing special commands (like /quit) here:
// those must not be executed when text is pasted, because that could crash the GUI system
// when there are additional lines to paste, but the edit field is destructed by the command
if (!fProcessed && *szInputText == '/')
{
// 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
const int32_t MaxCommandLen = 20;
char Command[MaxCommandLen+1];
const char *szPar = szInputText;
// parse command until first space
int32_t iParPos = SCharPos(' ', szInputText);
if (iParPos<0)
{
// command w/o par
SCopy(szInputText, Command, MaxCommandLen);
szPar += SLen(szPar);
}
else
{
// command with following par
SCopy(szInputText, Command, Min(MaxCommandLen, iParPos));
szPar += iParPos+1;
}
fProcessed = true;
// evaluate lobby-only commands
// ------------------------------------------------------
if (SEqualNoCase(Command, "/joinplr"))
{
// compose path from given filename
StdStrBuf plrPath;
plrPath.Format("%s%s", Config.General.UserDataPath, szPar);
// player join - check filename
if (!ItemExists(plrPath.getData()))
{
LobbyError(FormatString(LoadResStr("IDS_MSG_CMD_JOINPLR_NOFILE"), plrPath.getData()).getData());
}
else
::Network.Players.JoinLocalPlayer(plrPath.getData(), true);
}
// ------------------------------------------------------
else if (SEqualNoCase(Command, "/plrclr"))
{
// get player name from input text
int iSepPos = SCharPos(' ', szPar, 0);
C4PlayerInfo *pNfo=NULL;
int32_t idLocalClient = -1;
if (::Network.Clients.GetLocal()) idLocalClient = ::Network.Clients.GetLocal()->getID();
if (iSepPos>0)
{
// a player name is given: Parse it
StdStrBuf sPlrName;
sPlrName.Copy(szPar, iSepPos);
szPar += iSepPos+1; int32_t id=0;
while ((pNfo = Game.PlayerInfos.GetNextPlayerInfoByID(id)))
{
id = pNfo->GetID();
if (WildcardMatch(sPlrName.getData(), pNfo->GetName())) break;
}
}
else
// no player name: Set local player
pNfo = Game.PlayerInfos.GetPrimaryInfoByClientID(idLocalClient);
C4ClientPlayerInfos *pCltNfo=NULL;
if (pNfo) pCltNfo = Game.PlayerInfos.GetClientInfoByPlayerID(pNfo->GetID());
if (!pCltNfo)
{
LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_NOPLAYER"));
}
else
{
// may color of this client be set?
if (pCltNfo->GetClientID() != idLocalClient && !::Network.isHost())
{
LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_NOACCESS"));
}
else
{
// get color to set
uint32_t dwNewClr;
if (sscanf(szPar, "%x", &dwNewClr) != 1)
{
LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_USAGE"));
}
else
{
// color validation
dwNewClr |= 0xff000000;
if (!dwNewClr) ++dwNewClr;
// request a color change to this color
C4ClientPlayerInfos LocalInfoRequest = *pCltNfo;
C4PlayerInfo *pPlrInfo = LocalInfoRequest.GetPlayerInfoByID(pNfo->GetID());
assert(pPlrInfo);
if (pPlrInfo)
{
pPlrInfo->SetOriginalColor(dwNewClr); // set this as a new color wish
::Network.Players.RequestPlayerInfoUpdate(LocalInfoRequest);
}
}
}
}
}
// ------------------------------------------------------
else if (SEqualNoCase(Command, "/start"))
{
// timeout given?
int32_t iTimeout = Config.Lobby.CountdownTime;
if (!::Network.isHost())
LobbyError(LoadResStr("IDS_MSG_CMD_HOSTONLY"));
else if (szPar && *szPar && (!sscanf(szPar, "%d", &iTimeout) || iTimeout<0))
LobbyError(LoadResStr("IDS_MSG_CMD_START_USAGE"));
else
{
// abort previous countdown
if (eCountdownState) ::Network.AbortLobbyCountdown();
// start new countdown (aborts previous if necessary)
Start(iTimeout);
}
}
// ------------------------------------------------------
else if (SEqualNoCase(Command, "/abort"))
{
if (!::Network.isHost())
LobbyError(LoadResStr("IDS_MSG_CMD_HOSTONLY"));
else if (eCountdownState)
::Network.AbortLobbyCountdown();
else
LobbyError(LoadResStr("IDS_MSG_CMD_ABORT_NOCOUNTDOWN"));
}
// ------------------------------------------------------
else if (SEqualNoCase(Command, "/help"))
{
Log(LoadResStr("IDS_TEXT_COMMANDSAVAILABLEDURINGLO"));
LogF("/start [time] - %s", LoadResStr("IDS_TEXT_STARTTHEROUNDWITHSPECIFIE"));
LogF("/abort - %s", LoadResStr("IDS_TEXT_ABORTSTARTCOUNTDOWN"));
LogF("/alert - %s", LoadResStr("IDS_TEXT_ALERTTHEHOSTIFTHEHOSTISAW"));
LogF("/joinplr [filename] - %s", LoadResStr("IDS_TEXT_JOINALOCALPLAYERFROMTHESP"));
LogF("/kick [client] - %s", LoadResStr("IDS_TEXT_KICKTHESPECIFIEDCLIENT"));
LogF("/observer [client] - %s", LoadResStr("IDS_TEXT_SETTHESPECIFIEDCLIENTTOOB"));
LogF("/me [action] - %s", LoadResStr("IDS_TEXT_PERFORMANACTIONINYOURNAME"));
LogF("/sound [sound] - %s", LoadResStr("IDS_TEXT_PLAYASOUNDFROMTHEGLOBALSO"));
LogF("/team [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOYOUR"));
LogF("/plrclr [player] [RGB] - %s", LoadResStr("IDS_TEXT_CHANGETHECOLOROFTHESPECIF"));
LogF("/plrclr [RGB] - %s", LoadResStr("IDS_TEXT_CHANGEYOUROWNPLAYERCOLOR"));
LogF("/set comment [comment] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKCOMMENT"));
LogF("/set password [password] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKPASSWORD"));
LogF("/set maxplayer [number] - %s", LoadResStr("IDS_TEXT_SETANEWMAXIMUMNUMBEROFPLA"));
LogF("/clear - %s", LoadResStr("IDS_MSG_CLEARTHEMESSAGEBOARD"));
}
// ------------------------------------------------------
else
{
// command not known or not a specific lobby command - forward to messageinput
fProcessed = false;
}
}
// not processed? Then forward to messageinput, which parses additional commands and sends regular messages
if (!fProcessed) ::MessageInput.ProcessInput(szInputText);
::MessageInput.ProcessInput(szInputText);
}
// clear edit field after text has been processed
pEdt->SelectAll(); pEdt->DeleteSelection();
@ -862,6 +705,7 @@ namespace C4GameLobby
// get lobby
MainDlg *pLobby = ::Network.GetLobby();
if (pLobby) pLobby->OnError(szErrorMsg);
else Log(szErrorMsg);
}

View File

@ -132,7 +132,6 @@ namespace C4GameLobby
private:
void SetCountdownState(CountdownState eToState, int32_t iTimer);
void Start(int32_t iCountdownTime); // host only: Do game start with specified countdown time (forwards to network system)
int32_t ValidatedCountdownTime(int32_t iTimeout); // correct invalid timeout settings
void UpdatePlayerList();
@ -156,6 +155,7 @@ namespace C4GameLobby
void OnCountdownPacket(const C4PacketCountdown &Pkt); // called when a countdown packet is received: Update countdown state
bool IsCountdown();
void Start(int32_t iCountdownTime); // host only: Do game start with specified countdown time (forwards to network system)
void UpdatePassword();
void ClearLog();
};

View File

@ -445,30 +445,159 @@ bool C4MessageInput::ProcessCommand(const char *szCommand)
{
C4GameLobby::MainDlg *pLobby = ::Network.GetLobby();
// command
char szCmdName[C4MaxName + 1];
SCopyUntil(szCommand + 1, szCmdName, ' ', C4MaxName);
// 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
const int32_t MaxCommandLen = 20;
char szCmdName[MaxCommandLen + 1];
SCopyUntil(szCommand + 1, szCmdName, ' ', MaxCommandLen);
// parameter
const char *pCmdPar = SSearch(szCommand, " ");
if (!pCmdPar) pCmdPar = "";
// dev-scripts
// CAUTION when implementing special commands (like /quit) here:
// those must not be executed when text is pasted, because that could crash the GUI system
// when there are additional lines to paste, but the edit field is destructed by the command
// lobby-only commands
if (!Game.IsRunning && SEqualNoCase(szCmdName, "joinplr"))
{
// compose path from given filename
StdStrBuf plrPath;
plrPath.Format("%s%s", Config.General.UserDataPath, pCmdPar);
// player join - check filename
if (!ItemExists(plrPath.getData()))
{
C4GameLobby::LobbyError(FormatString(LoadResStr("IDS_MSG_CMD_JOINPLR_NOFILE"), plrPath.getData()).getData());
}
else
::Network.Players.JoinLocalPlayer(plrPath.getData(), true);
return true;
}
if (!Game.IsRunning && SEqualNoCase(szCmdName, "plrclr"))
{
// get player name from input text
int iSepPos = SCharPos(' ', pCmdPar, 0);
C4PlayerInfo *pNfo=NULL;
int32_t idLocalClient = -1;
if (::Network.Clients.GetLocal()) idLocalClient = ::Network.Clients.GetLocal()->getID();
if (iSepPos>0)
{
// a player name is given: Parse it
StdStrBuf sPlrName;
sPlrName.Copy(pCmdPar, iSepPos);
pCmdPar += iSepPos+1; int32_t id=0;
while ((pNfo = Game.PlayerInfos.GetNextPlayerInfoByID(id)))
{
id = pNfo->GetID();
if (WildcardMatch(sPlrName.getData(), pNfo->GetName())) break;
}
}
else
// no player name: Set local player
pNfo = Game.PlayerInfos.GetPrimaryInfoByClientID(idLocalClient);
C4ClientPlayerInfos *pCltNfo=NULL;
if (pNfo) pCltNfo = Game.PlayerInfos.GetClientInfoByPlayerID(pNfo->GetID());
if (!pCltNfo)
{
C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_NOPLAYER"));
}
else
{
// may color of this client be set?
if (pCltNfo->GetClientID() != idLocalClient && !::Network.isHost())
{
C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_NOACCESS"));
}
else
{
// get color to set
uint32_t dwNewClr;
if (sscanf(pCmdPar, "%x", &dwNewClr) != 1)
{
C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_PLRCLR_USAGE"));
}
else
{
// color validation
dwNewClr |= 0xff000000;
if (!dwNewClr) ++dwNewClr;
// request a color change to this color
C4ClientPlayerInfos LocalInfoRequest = *pCltNfo;
C4PlayerInfo *pPlrInfo = LocalInfoRequest.GetPlayerInfoByID(pNfo->GetID());
assert(pPlrInfo);
if (pPlrInfo)
{
pPlrInfo->SetOriginalColor(dwNewClr); // set this as a new color wish
::Network.Players.RequestPlayerInfoUpdate(LocalInfoRequest);
}
}
}
}
return true;
}
if (!Game.IsRunning && SEqualNoCase(szCmdName, "start"))
{
// timeout given?
int32_t iTimeout = Config.Lobby.CountdownTime;
if (!::Network.isHost())
C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_HOSTONLY"));
else if (pCmdPar && *pCmdPar && (!sscanf(pCmdPar, "%d", &iTimeout) || iTimeout<0))
C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_START_USAGE"));
else if (pLobby)
{
// abort previous countdown
if (::Network.isLobbyCountDown()) ::Network.AbortLobbyCountdown();
// start new countdown (aborts previous if necessary)
pLobby->Start(iTimeout);
}
else
{
if (iTimeout)
::Network.StartLobbyCountdown(iTimeout);
else
::Network.Start();
}
return true;
}
if (!Game.IsRunning && SEqualNoCase(szCmdName, "abort"))
{
if (!::Network.isHost())
C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_HOSTONLY"));
else if (::Network.isLobbyCountDown())
::Network.AbortLobbyCountdown();
else
C4GameLobby::LobbyError(LoadResStr("IDS_MSG_CMD_ABORT_NOCOUNTDOWN"));
return true;
}
if (SEqual(szCmdName, "help"))
{
Log(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"));
Log(LoadResStr(pLobby ? "IDS_TEXT_COMMANDSAVAILABLEDURINGLO" : "IDS_TEXT_COMMANDSAVAILABLEDURINGGA"));
if (!Game.IsRunning)
{
LogF("/start [time] - %s", LoadResStr("IDS_TEXT_STARTTHEROUNDWITHSPECIFIE"));
LogF("/abort - %s", LoadResStr("IDS_TEXT_ABORTSTARTCOUNTDOWN"));
LogF("/alert - %s", LoadResStr("IDS_TEXT_ALERTTHEHOSTIFTHEHOSTISAW"));
LogF("/joinplr [filename] - %s", LoadResStr("IDS_TEXT_JOINALOCALPLAYERFROMTHESP"));
LogF("/plrclr [player] [RGB] - %s", LoadResStr("IDS_TEXT_CHANGETHECOLOROFTHESPECIF"));
LogF("/plrclr [RGB] - %s", LoadResStr("IDS_TEXT_CHANGEYOUROWNPLAYERCOLOR"));
}
else
{
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("/script [script] - %s", LoadResStr("IDS_TEXT_EXECUTEASCRIPTCOMMAND"));
}
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("/me [action] - %s", LoadResStr("IDS_TEXT_PERFORMANACTIONINYOURNAME"));
LogF("/sound [sound] - %s", LoadResStr("IDS_TEXT_PLAYASOUNDFROMTHEGLOBALSO"));
if (Game.IsRunning) LogF("/private [player] [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOTHES"));
LogF("/team [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOYOUR"));
LogF("/set comment [comment] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKCOMMENT"));
LogF("/set password [password] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKPASSWORD"));
LogF("/set maxplayer [4] - %s", LoadResStr("IDS_TEXT_SETANEWMAXIMUMNUMBEROFPLA"));
LogF("/script [script] - %s", LoadResStr("IDS_TEXT_EXECUTEASCRIPTCOMMAND"));
LogF("/set maxplayer [number] - %s", LoadResStr("IDS_TEXT_SETANEWMAXIMUMNUMBEROFPLA"));
LogF("/clear - %s", LoadResStr("IDS_MSG_CLEARTHEMESSAGEBOARD"));
return true;
}
@ -645,12 +774,14 @@ bool C4MessageInput::ProcessCommand(const char *szCommand)
}
// show chart
if (Game.IsRunning) if (SEqual(szCmdName, "chart"))
if (Game.IsRunning)
if (SEqual(szCmdName, "chart"))
return Game.ToggleChart();
// custom command
C4MessageBoardCommand *pCmd;
if (Game.IsRunning) if ((pCmd = GetCommand(szCmdName)))
if (Game.IsRunning)
if ((pCmd = GetCommand(szCmdName)))
{
StdStrBuf Script, CmdScript;
// replace %player% by calling player number

View File

@ -298,6 +298,7 @@ public:
// lobby countdown
void StartLobbyCountdown(int32_t iCountdownTime);
void AbortLobbyCountdown();
bool isLobbyCountDown() { return pLobbyCountdown != 0; }
// streaming
size_t getPendingStreamData() const { return StreamingBuf.getSize() - StreamCompressor.avail_out; }