Skip to content

Commit 7ca0eb9

Browse files
committed
Edt find/load/create changes
- edt file is now parsed only once per map load, this should improve perf - ability to create default map config on missing edt - added convar sourcecoop_default_config, sourcecoop_default_config_dest - added command sc_mkconfigs
1 parent e82e58d commit 7ca0eb9

File tree

5 files changed

+175
-42
lines changed

5 files changed

+175
-42
lines changed

scripting/include/srccoop/commands.inc

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,79 @@ public Action Command_DumpMapEntities(int iArgs)
8484
MsgSrv("Failed opening file for writing: %s", szDumpPath);
8585
}
8686
return Plugin_Handled;
87+
}
88+
89+
public Action Command_MakeConfigs(int iArgs)
90+
{
91+
char szBuffer[PLATFORM_MAX_PATH];
92+
ServerExecute();
93+
94+
g_pConvarDefaultMapConfig.GetString(szBuffer, 2);
95+
if (szBuffer[0] == EOS)
96+
{
97+
g_pConvarDefaultMapConfig.GetName(szBuffer, sizeof(szBuffer));
98+
MsgSrv("Set \"%s\" before running this command.", szBuffer);
99+
return Plugin_Handled;
100+
}
101+
102+
g_pConvarDefaultMapConfigDest.GetString(szBuffer, 2);
103+
if (szBuffer[0] == EOS)
104+
{
105+
g_pConvarDefaultMapConfigDest.GetName(szBuffer, sizeof(szBuffer));
106+
MsgSrv("Set \"%s\" before running this command.", szBuffer);
107+
return Plugin_Handled;
108+
}
109+
110+
DirectoryListing dir = OpenDirectory("maps", true);
111+
if (!dir)
112+
{
113+
MsgSrv("Unable to enumerate maps folder.");
114+
return Plugin_Handled;
115+
}
116+
117+
bool bDryRun = !GetCmdArgInt(1);
118+
int count;
119+
FileType ft;
120+
CoopConfigLocation ccl;
121+
char szConfigPath[PLATFORM_MAX_PATH];
122+
123+
while (dir.GetNext(szBuffer, sizeof(szBuffer), ft))
124+
{
125+
int len = strlen(szBuffer);
126+
if (ft == FileType_File && StrEndsWithEx(szBuffer, len, ".bsp", false))
127+
{
128+
szBuffer[len - 4] = EOS;
129+
if (!CoopManager.FindMapConfig(szBuffer, szConfigPath, ccl, false))
130+
{
131+
if (!bDryRun)
132+
{
133+
if (!CoopManager.CreateDefaultConfig(szBuffer, szConfigPath))
134+
{
135+
dir.Close();
136+
MsgSrv("Aborted processing.");
137+
return Plugin_Handled;
138+
}
139+
}
140+
count++;
141+
}
142+
}
143+
}
144+
dir.Close();
145+
146+
if (bDryRun)
147+
{
148+
char szTemplate[PLATFORM_MAX_PATH], szDest[PLATFORM_MAX_PATH];
149+
g_pConvarDefaultMapConfig.GetString(szTemplate, sizeof(szTemplate));
150+
g_pConvarDefaultMapConfigDest.GetString(szDest, sizeof(szDest));
151+
GetCmdArg(0, szBuffer, sizeof(szBuffer));
152+
153+
PrintToServer("");
154+
MsgSrv("You are about to create %d new map configs.\n Template: %s\n Destination dir: %s\nType %s 1 to continue...\n",
155+
count, szTemplate, szDest, szBuffer);
156+
}
157+
else
158+
{
159+
MsgSrv("Success. Created %d configs.", count);
160+
}
161+
return Plugin_Handled;
87162
}

scripting/include/srccoop/globals.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ ConVar g_pConvarEndWaitFactor;
1717
ConVar g_pConvarHomeMap;
1818
ConVar g_pConvarEndWaitDisplayMode;
1919
ConVar g_pConvarValidateSteamIds;
20+
ConVar g_pConvarDefaultMapConfig;
21+
ConVar g_pConvarDefaultMapConfigDest;
2022

2123
#if defined GAMEPATCH_TEAMSELECT_UI
2224
ConVar g_pConvarDisableTeamSelect;

scripting/include/srccoop/manager.inc

Lines changed: 80 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
enum struct CoopManagerData
1414
{
15+
KeyValues kv;
1516
ChangeLevelManager m_pChangeLevelMgr;
1617
int m_iEnabledFeatures;
1718
bool m_bIsCoopMap;
@@ -45,6 +46,7 @@ methodmap CoopManager
4546

4647
public static bool OnLevelInit(char szMapEntities[ENTITYSTRING_LENGTH])
4748
{
49+
delete data.kv;
4850
data.m_pDelayedOutputs.Clear();
4951
data.m_pStartTimer = null;
5052
data.m_pChangeLevelTimer = null;
@@ -61,9 +63,9 @@ methodmap CoopManager
6163
g_pLevelLump.Clear();
6264
SurvivalManager.Clear(true);
6365

64-
KeyValues kv = CoopManager.LoadMapConfig(g_szMapName, data.m_mapConfigLoc);
66+
data.kv = CoopManager.LoadMapConfig(g_szMapName, data.m_mapConfigLoc);
6567

66-
if ((data.m_bIsCoopMap = kv != null))
68+
if ((data.m_bIsCoopMap = data.kv != null))
6769
{
6870
if (CoopManager.IsNewMapSeries())
6971
{
@@ -72,41 +74,37 @@ methodmap CoopManager
7274
EquipmentManager.ClearAll();
7375
}
7476
g_pLevelLump.ParseMapEntities(szMapEntities);
75-
g_pLevelLump.ParseConfigFile(kv);
77+
g_pLevelLump.ParseConfigFile(data.kv);
7678
g_pLevelLump.ToString(szMapEntities);
77-
delete kv;
7879
return true;
7980
}
8081
return false;
8182
}
8283

8384
public static void OnMapStart()
8485
{
85-
if (data.m_bIsCoopMap)
86-
{
87-
PrecacheSound(Conf.SND_TICK);
88-
PrecacheSound(Conf.SND_3);
89-
PrecacheSound(Conf.SND_2);
90-
PrecacheSound(Conf.SND_1);
91-
PrecacheSound(Conf.SND_CHANGELEVEL);
92-
PrecacheSound(Conf.SND_CHANGELEVEL_TICK);
93-
94-
#if defined SRCCOOP_BLACKMESA
95-
CBM_MP_GameRules.SetStateEndTime(STATE_WARMUP, GetGameTime() + 60 * 60 * 24 * 7);
96-
#endif
97-
98-
KeyValues kv = CoopManager.LoadMapConfig(g_szMapName, data.m_mapConfigLoc);
99-
if (kv != null)
100-
{
101-
CCoopSpawnSystem.ParseConfigFile(kv);
102-
103-
Call_StartForward(g_CoopMapConfigLoadedFwd);
104-
Call_PushCell(kv);
105-
Call_PushCell(data.m_mapConfigLoc);
106-
Call_Finish();
107-
delete kv;
108-
}
109-
}
86+
if (!data.kv)
87+
return;
88+
89+
PrecacheSound(Conf.SND_TICK);
90+
PrecacheSound(Conf.SND_3);
91+
PrecacheSound(Conf.SND_2);
92+
PrecacheSound(Conf.SND_1);
93+
PrecacheSound(Conf.SND_CHANGELEVEL);
94+
PrecacheSound(Conf.SND_CHANGELEVEL_TICK);
95+
96+
#if defined SRCCOOP_BLACKMESA
97+
CBM_MP_GameRules.SetStateEndTime(STATE_WARMUP, GetGameTime() + 60 * 60 * 24 * 7);
98+
#endif
99+
100+
data.kv.Rewind();
101+
CCoopSpawnSystem.ParseConfigFile(data.kv);
102+
103+
Call_StartForward(g_CoopMapConfigLoadedFwd);
104+
Call_PushCell(data.kv);
105+
Call_PushCell(data.m_mapConfigLoc);
106+
Call_Finish();
107+
delete data.kv;
110108
}
111109

112110
public static void OnClientPutInServer(CBasePlayer pPlayer)
@@ -439,28 +437,72 @@ methodmap CoopManager
439437
{
440438
return data.m_bIsCoopMap;
441439
}
442-
440+
443441
public static KeyValues LoadMapConfig(const char[] szMapName, CoopConfigLocation &src)
444442
{
445443
char szConfigPath[PLATFORM_MAX_PATH];
444+
if (!CoopManager.FindMapConfig(szMapName, szConfigPath, src, true))
445+
return null;
446+
447+
KeyValues kv = new KeyValues(szMapName);
448+
kv.SetEscapeSequences(true);
449+
char szRoot[16];
450+
if (!(kv.ImportFromFile(szConfigPath) && kv.GetSectionName(szRoot, sizeof(szRoot)) && strcmp(szRoot, "config", false) == 0))
451+
ThrowError("Couldn't import \"%s\" into KeyValues", szConfigPath);
452+
453+
return kv;
454+
}
455+
456+
public static bool FindMapConfig(const char[] szMapName, char szConfigPath[PLATFORM_MAX_PATH], CoopConfigLocation &src, bool bCreateDefault)
457+
{
446458
BuildPath(Path_SM, szConfigPath, sizeof(szConfigPath), "data/srccoop/%s.edt", szMapName);
447459
if (!FileExists(szConfigPath))
448460
{
449461
Format(szConfigPath, sizeof(szConfigPath), "maps/%s.edt", szMapName);
450462
if (!FileExists(szConfigPath, true))
451463
{
452-
return null;
464+
if (!bCreateDefault || !CoopManager.CreateDefaultConfig(szMapName, szConfigPath))
465+
{
466+
return false;
467+
}
468+
else src = CCL_MAPS;
453469
}
454470
else src = CCL_MAPS;
455471
}
456472
else src = CCL_SM_DATA;
457-
458-
KeyValues kv = new KeyValues(szMapName);
459-
kv.SetEscapeSequences(true);
460-
char szRoot[16];
461-
if (!(kv.ImportFromFile(szConfigPath) && kv.GetSectionName(szRoot, sizeof(szRoot)) && strcmp(szRoot, "config", false) == 0))
462-
ThrowError("Couldn't import %s into KeyValues", szConfigPath);
463-
return kv;
473+
return true;
474+
}
475+
476+
public static bool CreateDefaultConfig(const char[] szMapName, char szConfigPath[PLATFORM_MAX_PATH])
477+
{
478+
g_pConvarDefaultMapConfig.GetString(szConfigPath, sizeof(szConfigPath));
479+
if (szConfigPath[0] != EOS)
480+
{
481+
if (FileExists(szConfigPath))
482+
{
483+
char szDest[PLATFORM_MAX_PATH];
484+
485+
g_pConvarDefaultMapConfigDest.GetString(szDest, sizeof(szDest));
486+
Format(szDest, sizeof(szDest), "%s/%s.edt", szDest, szMapName);
487+
488+
if (FileCopy(szConfigPath, szDest))
489+
{
490+
LogMessage("Created default map config \"%s\"", szDest);
491+
szConfigPath = szDest;
492+
return true;
493+
}
494+
else
495+
{
496+
LogError("Failed to create default map config \"%s\" !", szDest);
497+
}
498+
}
499+
else
500+
{
501+
g_pConvarDefaultMapConfig.GetName(szConfigPath, sizeof(szConfigPath));
502+
LogError("Default config file is missing. Please fix \"%s\" !", szConfigPath);
503+
}
504+
}
505+
return false;
464506
}
465507

466508
}

scripting/include/srccoop/utils.inc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,17 @@ stock void UpperCaseString(const char[] szInput, char[] szOutput, int iSize)
469469
szOutput[x] = '\0';
470470
}
471471

472+
stock bool StrEndsWith(const char[] str, const char[] suffix, bool caseSensitive = true)
473+
{
474+
return StrEndsWithEx(str, strlen(str), suffix, caseSensitive);
475+
}
476+
477+
stock bool StrEndsWithEx(const char[] str, int realLen, const char[] suffix, bool caseSensitive = true)
478+
{
479+
int suffixLen = strlen(suffix);
480+
return (realLen >= suffixLen && StrEqual(str[realLen - suffixLen], suffix, caseSensitive));
481+
}
482+
472483
stock bool IsAddSynonym(const char[] str)
473484
{
474485
return (strcmp(str, "add", false) == 0 || strcmp(str, "create", false) == 0);
@@ -931,17 +942,17 @@ stock bool FileCopy(const char[] source, const char[] destination, bool use_valv
931942

932943
if (file_destination == null)
933944
{
934-
delete file_source;
945+
file_source.Close();
935946
return false;
936947
}
937948

938949
int buffer[32];
939950
int cache;
940951

941-
while (!IsEndOfFile(file_source))
952+
while (!file_source.EndOfFile())
942953
{
943-
cache = ReadFile(file_source, buffer, sizeof(buffer), 1);
944-
WriteFile(file_destination, buffer, cache, 1);
954+
cache = file_source.Read(buffer, sizeof(buffer), 1);
955+
file_destination.Write(buffer, cache, 1);
945956
}
946957

947958
delete file_source;

scripting/srccoop.sp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ public void OnPluginStart()
211211
g_pConvarHomeMap = CreateConVar("sourcecoop_homemap", "", "The map to return to after finishing a campaign/map.");
212212
g_pConvarEndWaitDisplayMode = CreateConVar("sourcecoop_end_wait_display_mode", "1", "Sets which method to show countdown. 0 is panel, 1 is hud text.", _, true, 0.0, true, 1.0);
213213
g_pConvarValidateSteamIds = CreateConVar("sourcecoop_validate_steamids", "0", "Validate players steam id's? Increases security at the cost of some functionality breakage when Steam goes down.\n At the time of writing this includes survival mode and equipment persistence.", _, true, 0.0, true, 1.0);
214+
g_pConvarDefaultMapConfig = CreateConVar("sourcecoop_default_config", "", "Default edt file, relative to game folder. This file is copied when starting a map with missing config as \"<sourcecoop_default_config_dest>/<mapname>.edt\". Useful for rapid development, or to enforce sourcecoop on all maps on the server.");
215+
g_pConvarDefaultMapConfigDest = CreateConVar("sourcecoop_default_config_dest", "maps", "Destination folder for \"sourcecoop_default_config\", relative to game folder. Should be a one of edt scan paths!");
214216

215217
mp_friendlyfire = FindConVar("mp_friendlyfire");
216218
mp_flashlight = FindConVar("mp_flashlight");
@@ -220,6 +222,7 @@ public void OnPluginStart()
220222
RegAdminCmd("sc_ft", Command_SetFeature, ADMFLAG_ROOT, "Command for toggling plugin features on/off");
221223
RegServerCmd("sourcecoop_dump", Command_DumpMapEntities, "Command for dumping map entities to a file");
222224
RegServerCmd("sc_dump", Command_DumpMapEntities, "Command for dumping map entities to a file");
225+
RegServerCmd("sc_mkconfigs", Command_MakeConfigs, "Creates default edt configs for all maps in the maps directory which are missing one");
223226

224227
g_pLevelLump.Initialize();
225228
CCoopSpawnSystem.Initialize();

0 commit comments

Comments
 (0)