Skip to content

Commit

Permalink
sc_importconfigs command WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Alienmario committed May 12, 2024
1 parent c38b5dc commit 17b203d
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 11 deletions.
171 changes: 162 additions & 9 deletions scripting/include/srccoop/commands.inc
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public Action Command_DumpMapEntities(int iArgs)
return Plugin_Handled;
}

public Action Command_MakeConfigs(int iArgs)
bool VerifyDefaultMapConfigCvars()
{
char szBuffer[PLATFORM_MAX_PATH];

Expand All @@ -95,14 +95,31 @@ public Action Command_MakeConfigs(int iArgs)
{
g_pConvarDefaultMapConfig.GetName(szBuffer, sizeof(szBuffer));
MsgSrv("Set \"%s\" before running this command.", szBuffer);
return Plugin_Handled;
return false;
}

g_pConvarDefaultMapConfigDest.GetString(szBuffer, 2);
if (szBuffer[0] == EOS)
{
g_pConvarDefaultMapConfigDest.GetName(szBuffer, sizeof(szBuffer));
MsgSrv("Set \"%s\" before running this command.", szBuffer);
return false;
}

return true;
}

public Action Command_MakeConfigs(int iArgs)
{
if (iArgs < 1)
{
char szCmd[32]; GetCmdArg(0, szCmd, sizeof(szCmd));
ServerCommand("help %s", szCmd);
return Plugin_Handled;
}

if (!VerifyDefaultMapConfigCvars())
{
return Plugin_Handled;
}

Expand All @@ -113,23 +130,30 @@ public Action Command_MakeConfigs(int iArgs)
return Plugin_Handled;
}

bool bDryRun = !GetCmdArgInt(1);
char szBuffer[PLATFORM_MAX_PATH];
char szMapFilter[MAX_MAPNAME * 2];
GetCmdArg(1, szMapFilter, sizeof(szMapFilter));
bool bDryRun = !GetCmdArgInt(2);
int count;
FileType ft;
CoopConfigLocation ccl;
char szConfigPath[PLATFORM_MAX_PATH];
char szSrcCoopConfig[PLATFORM_MAX_PATH];

while (dir.GetNext(szBuffer, sizeof(szBuffer), ft))
{
int len = strlen(szBuffer);
if (ft == FileType_File && StrEndsWithEx(szBuffer, len, ".bsp", false))
{
szBuffer[len - 4] = EOS;
if (!CoopManager.FindMapConfig(szBuffer, szConfigPath, ccl, false))

if (!StrEqualsWildcard(szMapFilter, szBuffer, false))
continue;

if (!CoopManager.FindMapConfig(szBuffer, szSrcCoopConfig, ccl, false))
{
if (!bDryRun)
{
if (!CoopManager.CreateDefaultConfig(szBuffer, szConfigPath))
if (!CoopManager.CreateDefaultConfig(szBuffer, szSrcCoopConfig))
{
dir.Close();
MsgSrv("Aborted processing.");
Expand All @@ -150,12 +174,141 @@ public Action Command_MakeConfigs(int iArgs)
GetCmdArg(0, szBuffer, sizeof(szBuffer));

PrintToServer("");
MsgSrv("You are about to create %d new map configs.\n Template: %s\n Destination dir: %s\nType %s 1 to continue...\n",
count, szTemplate, szDest, szBuffer);
MsgSrv("You are about to create %d new map configs.\n Template: %s\n Destination dir: %s\nExecute \"%s %s 1\" to continue...\n",
count, szTemplate, szDest,
szBuffer, szMapFilter);
}
else
{
MsgSrv("Success. Created %d configs.", count);
if (count)
MsgSrv("Success. Created %d configs.", count);
else
MsgSrv("No new configs were created!");
}
return Plugin_Handled;
}

public Action Command_ImportConfigs(int iArgs)
{
if (iArgs < 3)
{
char szCmd[32]; GetCmdArg(0, szCmd, sizeof(szCmd));
ServerCommand("help %s", szCmd);
return Plugin_Handled;
}

char szType[32];
char szMapFilter[MAX_MAPNAME * 2];
GetCmdArg(1, szType, sizeof(szType));
GetCmdArg(2, szMapFilter, sizeof(szMapFilter));
bool bCreateConfigs = !!GetCmdArgInt(3);
bool bDryRun = !GetCmdArgInt(4);

if (bCreateConfigs && !VerifyDefaultMapConfigCvars())
{
return Plugin_Handled;
}

int count, createdCount, errors;
if (StrEqual(szType, "stripper", false))
{
Command_ImportConfigs_Stripper(szMapFilter, bCreateConfigs, bDryRun, count, createdCount, errors);
}
else
{
MsgSrv("Unsupported import type: \"%s\"", szType);
return Plugin_Handled;
}

if (count < 0)
{
return Plugin_Handled;
}

if (bDryRun)
{
char szCmd[32]; GetCmdArg(0, szCmd, sizeof(szCmd));

PrintToServer("");
MsgSrv("You are about to import %d %s configs (of which %d will be created).\nExecute \"%s %s %s %d 1\" to continue...\n",
count, szType, createdCount,
szCmd, szType, szMapFilter, bCreateConfigs);
}
else
{
MsgSrv("Import finished.\n Total imported: %d\n New configs: %d\n Errors: %d", count, createdCount, errors);
}

return Plugin_Handled;
}

void Command_ImportConfigs_Stripper(const char[] szMapFilter, bool bCreate, bool bDryRun, int &count, int &createdCount, int &errors)
{
static const char szStripperMapsDir[] = "addons/stripper/maps";
DirectoryListing dir = OpenDirectory(szStripperMapsDir, false);
if (!dir)
{
MsgSrv("Unable to enumerate \"%s\" folder.", szStripperMapsDir);
count = -1;
return;
}

FileType ft;
CoopConfigLocation ccl;
char szBuffer[PLATFORM_MAX_PATH];
char szSrcCoopConfig[PLATFORM_MAX_PATH];
char szError[128];

while (dir.GetNext(szBuffer, sizeof(szBuffer), ft))
{
int len = strlen(szBuffer);
if (ft == FileType_File && StrEndsWithEx(szBuffer, len, ".cfg", false))
{
szBuffer[len - 4] = EOS;
if (!StrEqualsWildcard(szMapFilter, szBuffer, false))
continue;

bool bCreatedDefault;
if (!CoopManager.FindMapConfig(szBuffer, szSrcCoopConfig, ccl, false))
{
if (!bCreate)
{
MsgSrv("Found stripper config for \"%s\", but no SourceCoop config. Run with <CREATE> set to 1 to remedy this.", szBuffer);
continue;
}
if (!bDryRun && !CoopManager.CreateDefaultConfig(szBuffer, szSrcCoopConfig))
{
MsgSrv("Aborted processing.");
dir.Close();
count = -1;
return;
}
bCreatedDefault = true;
}

Format(szBuffer, sizeof(szBuffer), "%s/%s.cfg", szStripperMapsDir, szBuffer);
if (bDryRun || ImportStripperConfig(szBuffer, szSrcCoopConfig, szError, sizeof(szError)))
{
count++;
if (bCreatedDefault)
createdCount++;
}
else
{
errors++;
MsgSrv("Error in importing stripper config from \"%s\" to \"%s\":\n%s", szBuffer, szSrcCoopConfig, szError);
if (bCreatedDefault)
{
MsgSrv("Cleaning up.");
DeleteFile(szSrcCoopConfig);
}
}
}
}
dir.Close();
}

bool ImportStripperConfig(const char[] szStripperConfig, const char[] szSrcCoopConfig, char[] szError, int maxErrorLen)
{
return true;
}
42 changes: 41 additions & 1 deletion scripting/include/srccoop/utils.inc
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,47 @@ stock bool StrEqualsRegex(const char[] pattern, const char[] str, bool caseSensi
}
return strcmp(pattern, str, caseSensitive) == 0;
}
#endif

/**
* Simple * wildcard pattern matching. Best for comparing map names, file names (think gitignore), etc.
*/
stock bool StrEqualsWildcard(const char[] pattern, const char[] str, bool caseSensitive = false)
{
int regexLen = strlen(pattern) * 2 + 3;
char[] regex = new char[regexLen];

EscapeRegex(pattern, regex, regexLen, "*");
ReplaceString(regex, regexLen, "*", ".*");
Format(regex, regexLen, "^%s$", regex);

int substrings = SimpleRegexMatch(str, regex, caseSensitive? 0 : PCRE_CASELESS);
return (substrings > 0);
}

/**
* Quotes / escapes all special regex characters in a string.
* @param allowedChars Characters that should not be escaped.
* @return characters written
*/
stock int EscapeRegex(const char[] str, char[] dest, int destLen, const char[] allowedChars = "")
{
static const char specialChars[] = ".\\+*?[^]$(){}=!<>|:-#";
int i, j;
while (str[i] != EOS && (j + 1) < destLen)
{
if (FindCharInString(specialChars, str[i]) != -1 && FindCharInString(allowedChars, str[i]) == -1)
{
if (j + 2 >= destLen)
break;
dest[j++] = '\\';
}
dest[j++] = str[i++];
}
dest[j] = EOS;
return j;
}

#endif // defined _regex_included

stock void FormatTimeLength(int seconds, char[] out, int size)
{
Expand Down
3 changes: 2 additions & 1 deletion scripting/srccoop.sp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ public void OnPluginStart()
RegAdminCmd("sc_ft", Command_SetFeature, ADMFLAG_ROOT, "Command for toggling plugin features on/off");
RegServerCmd("sourcecoop_dump", Command_DumpMapEntities, "Command for dumping map entities to a file");
RegServerCmd("sc_dump", Command_DumpMapEntities, "Command for dumping map entities to a file");
RegServerCmd("sc_mkconfigs", Command_MakeConfigs, "Creates default edt configs for all maps in the maps directory which are missing one");
RegServerCmd("sc_mkconfigs", Command_MakeConfigs, "Creates default SourceCoop configs for maps found in the maps directory, which are missing one.\n - Format: sc_mkconfigs <MAPFILTER> [CONFIRM]\n MAPFILTER: filters the map names to include; use * for all; supports wildcards with * such as coop_*\n CONFIRM: [0 = dry run, 1 = live run]");
RegServerCmd("sc_importconfigs", Command_ImportConfigs, "Imports other formats of map configs into SourceCoop configs.\n - Format: sc_importconfigs <TYPE> <MAPFILTER> <CREATE> [CONFIRM]\n TYPE: The type of config to import, values: [stripper = Stripper:source]\n MAPFILTER: filters the map names to import; use * for all; supports wildcards with * such as coop_*\n CREATE: [1 = attempts to create default SourceCoop config for the map if it's missing, 0 = prints a warning and skips if missing]\n CONFIRM: [0 = dry run, 1 = live run]");

g_pLevelLump.Initialize();
CCoopSpawnSystem.Initialize();
Expand Down

0 comments on commit 17b203d

Please sign in to comment.