5793: Allow demo/map command line arguments to be relative paths, allow using `play` in command line r=def- a=Robyt3

Closes #5645.

## Checklist

- [X] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2022-08-30 21:10:29 +00:00 committed by GitHub
commit 487d85bdf8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 18 deletions

View file

@ -3198,7 +3198,9 @@ void CClient::Run()
// handle pending demo play
if(m_aCmdPlayDemo[0])
{
const char *pError = DemoPlayer_Play(m_aCmdPlayDemo, IStorage::TYPE_ABSOLUTE);
const char *pError = DemoPlayer_Play(m_aCmdPlayDemo, IStorage::TYPE_ALL);
if(pError && !fs_is_relative_path(m_aCmdPlayDemo))
pError = DemoPlayer_Play(m_aCmdPlayDemo, IStorage::TYPE_ABSOLUTE);
if(pError)
dbg_msg("demo_player", "playing passed demo file '%s' failed: %s", m_aCmdPlayDemo, pError);
m_aCmdPlayDemo[0] = 0;
@ -3207,7 +3209,9 @@ void CClient::Run()
// handle pending map edits
if(m_aCmdEditMap[0])
{
int Result = m_pEditor->Load(m_aCmdEditMap, IStorage::TYPE_ABSOLUTE);
int Result = m_pEditor->Load(m_aCmdEditMap, IStorage::TYPE_ALL);
if(!Result && !fs_is_relative_path(m_aCmdEditMap))
m_pEditor->Load(m_aCmdEditMap, IStorage::TYPE_ABSOLUTE);
if(Result)
g_Config.m_ClEditor = true;
else
@ -3502,7 +3506,7 @@ bool CClient::CtrlShiftKey(int Key, bool &Last)
void CClient::Con_Connect(IConsole::IResult *pResult, void *pUserData)
{
CClient *pSelf = (CClient *)pUserData;
str_copy(pSelf->m_aCmdConnect, pResult->GetString(0));
pSelf->HandleConnectLink(pResult->GetString(0));
}
void CClient::Con_Disconnect(IConsole::IResult *pResult, void *pUserData)
@ -3975,9 +3979,7 @@ const char *CClient::DemoPlayer_Render(const char *pFilename, int StorageType, c
void CClient::Con_Play(IConsole::IResult *pResult, void *pUserData)
{
CClient *pSelf = (CClient *)pUserData;
const char *pError = pSelf->DemoPlayer_Play(pResult->GetString(0), IStorage::TYPE_ALL);
if(pError)
pSelf->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_player", pError);
pSelf->HandleDemoPath(pResult->GetString(0));
}
void CClient::Con_DemoPlay(IConsole::IResult *pResult, void *pUserData)
@ -4531,7 +4533,10 @@ void CClient::HandleConnectAddress(const NETADDR *pAddr)
void CClient::HandleConnectLink(const char *pLink)
{
str_copy(m_aCmdConnect, pLink + sizeof(CONNECTLINK) - 1);
if(str_startswith(pLink, CONNECTLINK))
str_copy(m_aCmdConnect, pLink + sizeof(CONNECTLINK) - 1);
else
str_copy(m_aCmdConnect, pLink);
}
void CClient::HandleDemoPath(const char *pPath)
@ -4544,6 +4549,27 @@ void CClient::HandleMapPath(const char *pPath)
str_copy(m_aCmdEditMap, pPath);
}
static bool UnknownArgumentCallback(const char *pCommand, void *pUser)
{
CClient *pClient = static_cast<CClient *>(pUser);
if(str_startswith(pCommand, CONNECTLINK))
{
pClient->HandleConnectLink(pCommand);
return true;
}
else if(str_endswith(pCommand, ".demo"))
{
pClient->HandleDemoPath(pCommand);
return true;
}
else if(str_endswith(pCommand, ".map"))
{
pClient->HandleMapPath(pCommand);
return true;
}
return false;
}
/*
Server Time
Client Mirror Time
@ -4729,14 +4755,9 @@ int main(int argc, const char **argv)
g_Config.m_ClConfigVersion = 1;
// parse the command line arguments
if(argc == 2 && str_startswith(argv[1], CONNECTLINK))
pClient->HandleConnectLink(argv[1]);
else if(argc == 2 && str_endswith(argv[1], ".demo"))
pClient->HandleDemoPath(argv[1]);
else if(argc == 2 && str_endswith(argv[1], ".map"))
pClient->HandleMapPath(argv[1]);
else if(argc > 1)
pConsole->ParseArguments(argc - 1, (const char **)&argv[1]);
pConsole->SetUnknownCommandCallback(UnknownArgumentCallback, pClient);
pConsole->ParseArguments(argc - 1, (const char **)&argv[1]);
pConsole->SetUnknownCommandCallback(IConsole::EmptyUnknownCommandCallback, nullptr);
if(pSteam->GetConnectAddress())
{

View file

@ -85,8 +85,10 @@ public:
typedef void (*FPossibleCallback)(int Index, const char *pCmd, void *pUser);
typedef void (*FCommandCallback)(IResult *pResult, void *pUserData);
typedef void (*FChainCommandCallback)(IResult *pResult, void *pUserData, FCommandCallback pfnCallback, void *pCallbackUserData);
typedef bool (*FUnknownCommandCallback)(const char *pCommand, void *pUser); // returns true if the callback has handled the argument
static void EmptyPossibleCommandCallback(int Index, const char *pCmd, void *pUser) {}
static bool EmptyUnknownCommandCallback(const char *pCommand, void *pUser) { return false; }
virtual void Init() = 0;
virtual const CCommandInfo *FirstCommandInfo(int AccessLevel, int Flagmask) const = 0;
@ -110,6 +112,7 @@ public:
virtual char *Format(char *pBuf, int Size, const char *pFrom, const char *pStr) = 0;
virtual void Print(int Level, const char *pFrom, const char *pStr, ColorRGBA PrintColor = gs_ConsoleDefaultColor) = 0;
virtual void SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCallback, void *pUser) = 0;
virtual void SetUnknownCommandCallback(FUnknownCommandCallback pfnCallback, void *pUser) = 0;
virtual void InitChecksum(CChecksumData *pData) const = 0;
virtual void SetAccessLevel(int AccessLevel) = 0;

View file

@ -342,6 +342,12 @@ void CConsole::SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCa
m_pTeeHistorianCommandUserdata = pUser;
}
void CConsole::SetUnknownCommandCallback(FUnknownCommandCallback pfnCallback, void *pUser)
{
m_pfnUnknownCommandCallback = pfnCallback;
m_pUnknownCommandUserdata = pUser;
}
void CConsole::InitChecksum(CChecksumData *pData) const
{
pData->m_NumCommands = 0;
@ -542,9 +548,12 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo
}
else if(Stroke)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
Print(OUTPUT_LEVEL_STANDARD, "chatresp", aBuf);
if(!m_pfnUnknownCommandCallback(Result.m_pCommand, m_pUnknownCommandUserdata))
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
Print(OUTPUT_LEVEL_STANDARD, "chatresp", aBuf);
}
}
pStr = pNextPart;

View file

@ -68,6 +68,9 @@ class CConsole : public IConsole
FTeeHistorianCommandCallback m_pfnTeeHistorianCommandCallback;
void *m_pTeeHistorianCommandUserdata;
FUnknownCommandCallback m_pfnUnknownCommandCallback = EmptyUnknownCommandCallback;
void *m_pUnknownCommandUserdata = nullptr;
enum
{
CONSOLE_MAX_STR_LENGTH = 8192,
@ -214,6 +217,7 @@ public:
char *Format(char *pBuf, int Size, const char *pFrom, const char *pStr) override;
void Print(int Level, const char *pFrom, const char *pStr, ColorRGBA PrintColor = gs_ConsoleDefaultColor) override;
void SetTeeHistorianCommandCallback(FTeeHistorianCommandCallback pfnCallback, void *pUser) override;
void SetUnknownCommandCallback(FUnknownCommandCallback pfnCallback, void *pUser) override;
void InitChecksum(CChecksumData *pData) const override;
void SetAccessLevel(int AccessLevel) override { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_USER)); }