Add new function: GetMapDisplayName.

This function will resolve the name of a map using FindMap, then (if applicable), will turn a workshop map name into a nicely formatted name.

Currently only TF2 and CS:GO Map Workshops are supported.  More can be added at a later date.

This function returns false if a map was not found, but true in any other instance even if FindMap could not resolve the map name.

This patch also updates the following core plugins to use this GetMapDisplayName:

BaseTriggers
BaseVotes
MapChooser
NextMap
Nominations
RandomCycle
RockTheVote
This commit is contained in:
Ross Bemrose 2015-09-14 11:21:26 -04:00
parent c6c034f90a
commit 10a95cfdce
13 changed files with 195 additions and 50 deletions

View File

@ -1273,6 +1273,38 @@ SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_
#endif
}
bool CHalfLife2::GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax)
{
SMFindMapResult result = FindMap(pMapName, pDisplayname, nMapNameMax);
if (result == SMFindMapResult::NotFound)
{
return false;
}
#if SOURCE_ENGINE == SE_CSGO
char *lastSlashPos;
// In CSGO, workshop maps show up as workshop/123456789/mapname
if (strncmp(pDisplayname, "workshop/", 9) == 0 && (lastSlashPos = strrchr(pDisplayname, '/')) != NULL)
{
ke::SafeSprintf(pDisplayname, nMapNameMax, "%s", &lastSlashPos[1]);
return true;
}
#elif SOURCE_ENGINE == SE_TF2
char *ugcPos;
// In TF2, workshop maps show up as workshop/mapname.ugc123456789
if (strncmp(pDisplayname, "workshop/", 9) == 0 && (ugcPos = strstr(pDisplayname, ".ugc")) != NULL)
{
// Overwrite the . with a nul and SafeSprintf will handle the rest
ugcPos[0] = '\0';
ke::SafeSprintf(pDisplayname, nMapNameMax, "%s", &pDisplayname[9]);
return true;
}
#endif
return true;
}
bool CHalfLife2::IsMapValid(const char *map)
{
if (!map || !map[0])

View File

@ -187,6 +187,7 @@ public: //IGameHelpers
bool IsMapValid(const char *map);
SMFindMapResult FindMap(char *pMapName, size_t nMapNameMax);
SMFindMapResult FindMap(const char *pMapName, char *pFoundMap = NULL, size_t nMapNameMax = 0);
bool GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax);
#if SOURCE_ENGINE >= SE_ORANGEBOX
string_t AllocPooledString(const char *pszValue);
#endif

View File

@ -82,6 +82,14 @@ static cell_t FindMap(IPluginContext *pContext, const cell_t *params)
return static_cast<cell_t>(g_HL2.FindMap(pMapname, pDestMap, params[3]));
}
static cell_t GetMapDisplayName(IPluginContext *pContext, const cell_t *params)
{
char *pMapname, *pDisplayname;
pContext->LocalToString(params[1], &pMapname);
pContext->LocalToString(params[2], &pDisplayname);
return static_cast<cell_t>(g_HL2.GetMapDisplayName(pMapname, pDisplayname, params[3]));
}
static cell_t IsDedicatedServer(IPluginContext *pContext, const cell_t *params)
{
return engine->IsDedicatedServer();
@ -642,6 +650,7 @@ REGISTER_NATIVES(halflifeNatives)
{"IsDedicatedServer", IsDedicatedServer},
{"IsMapValid", IsMapValid},
{"FindMap", FindMap},
{"GetMapDisplayName", GetMapDisplayName},
{"SetFakeClientConVar", SetFakeClientConVar},
{"SetRandomSeed", SetRandomSeed},
{"PrecacheModel", PrecacheModel},

View File

@ -211,6 +211,7 @@ public Action:Command_Nextmap(client, args)
}
else
{
GetMapDisplayName(map, map, sizeof(map));
ReplyToCommand(client, "[SM] %t", "Next Map", map);
}
@ -291,7 +292,8 @@ public OnClientSayCommand_Post(client, const String:command[], const String:sArg
{
char map[PLATFORM_MAX_PATH];
GetNextMap(map, sizeof(map));
GetMapDisplayName(map, map, sizeof(map));
if (g_Cvar_TriggerShow.IntValue)
{
if (mapchooser && EndOfMapVoteEnabled() && !HasEndOfMapVoteFinished())

View File

@ -116,7 +116,7 @@ public OnPluginStart()
OnAdminMenuReady(topmenu);
}
g_SelectedMaps = CreateArray(33);
g_SelectedMaps = CreateArray(ByteCountToCells(PLATFORM_MAX_PATH));
g_MapList = CreateMenu(MenuHandler_Map, MenuAction_DrawItem|MenuAction_Display);
g_MapList.SetTitle("%T", "Please select a map", LANG_SERVER);
@ -311,8 +311,11 @@ public Handler_VoteCallback(Menu menu, MenuAction action, param1, param2)
case (voteType:map):
{
// single-vote items don't use the display item
char displayName[PLATFORM_MAX_PATH];
GetMapDisplayName(item, displayName, sizeof(displayName));
LogAction(-1, -1, "Changing map to %s due to vote.", item);
PrintToChatAll("[SM] %t", "Changing map", item);
PrintToChatAll("[SM] %t", "Changing map", displayName);
new Handle:dp;
CreateDataTimer(5.0, Timer_ChangeMap, dp);
WritePackString(dp, item);

View File

@ -48,7 +48,7 @@ DisplayVoteMapMenu(client, mapCount, String:maps[5][])
if (mapCount == 1)
{
strcopy(g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]), maps[0]);
GetMapDisplayName(maps[0], g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]));
g_hVoteMenu.SetTitle("Change Map To");
g_hVoteMenu.AddItem(maps[0], "Yes");
@ -61,7 +61,9 @@ DisplayVoteMapMenu(client, mapCount, String:maps[5][])
g_hVoteMenu.SetTitle("Map Vote");
for (new i = 0; i < mapCount; i++)
{
g_hVoteMenu.AddItem(maps[i], maps[i]);
decl String:displayName[PLATFORM_MAX_PATH];
GetMapDisplayName(maps[i], displayName, sizeof(displayName));
g_hVoteMenu.AddItem(maps[i], displayName);
}
}
@ -288,8 +290,10 @@ int LoadMapList(Menu menu)
for (new i = 0; i < map_count; i++)
{
decl String:displayName[PLATFORM_MAX_PATH];
GetArrayString(g_map_array, i, map_name, sizeof(map_name));
menu.AddItem(map_name, map_name);
GetMapDisplayName(map_name, displayName, sizeof(displayName));
menu.AddItem(map_name, displayName);
}
return map_count;

View File

@ -167,6 +167,24 @@ native bool:IsMapValid(const String:map[]);
*/
native FindMapResult FindMap(const char[] map, char[] foundmap, int maxlen);
/**
* Get the display name of a workshop map.
*
* Note: You do not need to call FindMap first. This native will call FindMap internally.
*
* @param map Map name (usually same as map path relative to maps/ dir,
* excluding .bsp extension).
* @param displayName Map's display name, i.e. cp_mymapname or de_mymapname.
* If FindMap returns FindMap_PossiblyAvailable or FindMap_NotFound,
* the map cannot be resolved and this native will return false,
* but displayName will be a copy of map.
* @param maxlen Maximum length to write to displayName var.
* @return true if FindMap returns FindMap_Found, FindMap_FuzzyMatch, or
* FindMap_NonCanonical.
* false if FindMap returns FindMap_PossiblyAvailable or FindMap_NotFound.
*/
native bool GetMapDisplayName(const char[] map, char[] displayName, int maxlen);
/**
* Returns whether the server is dedicated.
*

View File

@ -74,6 +74,8 @@ ConVar g_Cvar_RunOffPercent;
Handle g_VoteTimer = null;
Handle g_RetryTimer = null;
// g_MapList stores unresolved names so we can resolve them after every map change in the workshop updates.
// g_OldMapList and g_NextMapList are resolved. g_NominateList depends on the nominations implementation.
/* Data Handles */
ArrayList g_MapList;
ArrayList g_NominateList;
@ -288,15 +290,18 @@ public Action Command_SetNextmap(int client, int args)
}
char map[PLATFORM_MAX_PATH];
char displayName[PLATFORM_MAX_PATH];
GetCmdArg(1, map, sizeof(map));
if (!IsMapValid(map))
if (FindMap(map, displayName, sizeof(displayName)) == FindMap_NotFound)
{
ReplyToCommand(client, "[SM] %t", "Map was not found", map);
return Plugin_Handled;
}
ShowActivity(client, "%t", "Changed Next Map", map);
GetMapDisplayName(displayName, displayName, sizeof(displayName));
ShowActivity(client, "%t", "Changed Next Map", displayName);
LogAction(client, -1, "\"%L\" changed nextmap to \"%s\"", client, map);
SetNextMap(map);
@ -321,7 +326,7 @@ void SetupTimeleftTimer()
int startTime = g_Cvar_StartTime.IntValue * 60;
if (time - startTime < 0 && g_Cvar_EndOfMapVote.BoolValue && !g_MapVoteCompleted && !g_HasVoteStarted)
{
InitiateVote(MapChange_MapEnd, null);
InitiateVote(MapChange_MapEnd, null);
}
else
{
@ -585,11 +590,12 @@ void InitiateVote(MapChange when, ArrayList inputlist=null)
/* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */
int nominationsToAdd = nominateCount >= voteSize ? voteSize : nominateCount;
for (int i=0; i<nominationsToAdd; i++)
{
char displayName[PLATFORM_MAX_PATH];
g_NominateList.GetString(i, map, sizeof(map));
g_VoteMenu.AddItem(map, map);
GetMapDisplayName(map, displayName, sizeof(displayName));
g_VoteMenu.AddItem(map, displayName);
RemoveStringFromArray(g_NextMapList, map);
/* Notify Nominations that this map is now free */
@ -630,7 +636,9 @@ void InitiateVote(MapChange when, ArrayList inputlist=null)
count++;
/* Insert the map and increment our count */
g_VoteMenu.AddItem(map, map);
char displayName[PLATFORM_MAX_PATH];
GetMapDisplayName(map, displayName, sizeof(displayName));
g_VoteMenu.AddItem(map, displayName);
i++;
}
@ -648,7 +656,9 @@ void InitiateVote(MapChange when, ArrayList inputlist=null)
if (IsMapValid(map))
{
g_VoteMenu.AddItem(map, map);
char displayName[PLATFORM_MAX_PATH];
GetMapDisplayName(map, displayName, sizeof(displayName));
g_VoteMenu.AddItem(map, displayName);
}
}
}
@ -689,7 +699,8 @@ public void Handler_VoteFinishedGeneric(Menu menu,
const int[][] item_info)
{
char map[PLATFORM_MAX_PATH];
menu.GetItem(item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map));
char displayName[PLATFORM_MAX_PATH];
menu.GetItem(item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map), _, displayName, sizeof(displayName));
if (strcmp(map, VOTE_EXTEND, false) == 0)
{
@ -771,7 +782,7 @@ public void Handler_VoteFinishedGeneric(Menu menu,
g_HasVoteStarted = false;
g_MapVoteCompleted = true;
PrintToChatAll("[SM] %t", "Nextmap Voting Finished", map, RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes);
PrintToChatAll("[SM] %t", "Nextmap Voting Finished", displayName, RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes);
LogAction(-1, -1, "Voting for next map has finished. Nextmap: %s.", map);
}
}
@ -940,11 +951,22 @@ bool RemoveStringFromArray(ArrayList array, char[] str)
void CreateNextVote()
{
ClearArray(g_NextMapList);
g_NextMapList.Clear();
char map[PLATFORM_MAX_PATH];
ArrayList tempMaps = g_MapList.Clone();
// tempMaps is a resolved map list
ArrayList tempMaps = new ArrayList(ByteCountToCells(PLATFORM_MAX_PATH));
for (int i = 0; i < g_MapList.Length; i++)
{
g_MapList.GetString(i, map, sizeof(map));
if (FindMap(map, map, sizeof(map)) != FindMap_NotFound)
{
tempMaps.PushString(map);
}
}
//GetCurrentMap always returns a resolved map
GetCurrentMap(map, sizeof(map));
RemoveStringFromArray(tempMaps, map);
@ -954,7 +976,7 @@ void CreateNextVote()
{
g_OldMapList.GetString(i, map, sizeof(map));
RemoveStringFromArray(tempMaps, map);
}
}
}
int limit = (g_Cvar_IncludeMaps.IntValue < tempMaps.Length ? g_Cvar_IncludeMaps.IntValue : tempMaps.Length);

View File

@ -153,7 +153,8 @@ void FindAndSetNextMap()
for (int i = 0; i < mapCount; i++)
{
g_MapList.GetString(i, mapName, sizeof(mapName));
if (strcmp(current, mapName, false) == 0)
if (FindMap(mapName, mapName, sizeof(mapName)) != FindMap_NotFound &&
strcmp(current, mapName, false) == 0)
{
g_MapPos = i;
break;

View File

@ -100,8 +100,11 @@ public void OnNominationRemoved(const char[] map, int owner)
{
int status;
char resolvedMap[PLATFORM_MAX_PATH];
FindMap(map, resolvedMap, sizeof(resolvedMap));
/* Is the map in our list? */
if (!g_mapTrie.GetValue(map, status))
if (!g_mapTrie.GetValue(resolvedMap, status))
{
return;
}
@ -112,7 +115,7 @@ public void OnNominationRemoved(const char[] map, int owner)
return;
}
g_mapTrie.SetValue(map, MAPSTATUS_ENABLED);
g_mapTrie.SetValue(resolvedMap, MAPSTATUS_ENABLED);
}
public Action Command_Addmap(int client, int args)
@ -124,31 +127,41 @@ public Action Command_Addmap(int client, int args)
}
char mapname[PLATFORM_MAX_PATH];
char resolvedMap[PLATFORM_MAX_PATH];
GetCmdArg(1, mapname, sizeof(mapname));
int status;
if (!g_mapTrie.GetValue(mapname, status))
if (FindMap(mapname, resolvedMap, sizeof(resolvedMap)) == FindMap_NotFound)
{
// We couldn't resolve the map entry to a filename, so...
ReplyToCommand(client, "%t", "Map was not found", mapname);
return Plugin_Handled;
}
NominateResult result = NominateMap(mapname, true, 0);
char displayName[PLATFORM_MAX_PATH];
GetMapDisplayName(resolvedMap, displayName, sizeof(displayName));
int status;
if (!g_mapTrie.GetValue(resolvedMap, status))
{
ReplyToCommand(client, "%t", "Map was not found", displayName);
return Plugin_Handled;
}
NominateResult result = NominateMap(resolvedMap, true, 0);
if (result > Nominate_Replaced)
{
/* We assume already in vote is the casue because the maplist does a Map Validity check and we forced, so it can't be full */
ReplyToCommand(client, "%t", "Map Already In Vote", mapname);
ReplyToCommand(client, "%t", "Map Already In Vote", displayName);
return Plugin_Handled;
}
g_mapTrie.SetValue(mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
g_mapTrie.SetValue(resolvedMap, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
ReplyToCommand(client, "%t", "Map Inserted", mapname);
ReplyToCommand(client, "%t", "Map Inserted", displayName);
LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname);
return Plugin_Handled;
@ -187,10 +200,20 @@ public Action Command_Nominate(int client, int args)
char mapname[PLATFORM_MAX_PATH];
GetCmdArg(1, mapname, sizeof(mapname));
if (FindMap(mapname, mapname, sizeof(mapname)) == FindMap_NotFound)
{
// We couldn't resolve the map entry to a filename, so...
ReplyToCommand(client, "%t", "Map was not found", mapname);
return Plugin_Handled;
}
char displayName[PLATFORM_MAX_PATH];
GetMapDisplayName(mapname, displayName, sizeof(displayName));
int status;
if (!g_mapTrie.GetValue(mapname, status))
{
ReplyToCommand(client, "%t", "Map was not found", mapname);
ReplyToCommand(client, "%t", "Map was not found", displayName);
return Plugin_Handled;
}
@ -220,7 +243,7 @@ public Action Command_Nominate(int client, int args)
{
if (result == Nominate_AlreadyInVote)
{
ReplyToCommand(client, "%t", "Map Already In Vote", mapname);
ReplyToCommand(client, "%t", "Map Already In Vote", displayName);
}
else
{
@ -236,7 +259,7 @@ public Action Command_Nominate(int client, int args)
char name[MAX_NAME_LENGTH];
GetClientName(client, name, sizeof(name));
PrintToChatAll("[SM] %t", "Map Nominated", name, mapname);
PrintToChatAll("[SM] %t", "Map Nominated", name, displayName);
return Plugin_Continue;
}
@ -273,13 +296,17 @@ void BuildMapMenu()
GetCurrentMap(currentMap, sizeof(currentMap));
}
for (int i = 0; i < g_MapList.Length; i++)
{
int status = MAPSTATUS_ENABLED;
g_MapList.GetString(i, map, sizeof(map));
FindMap(map, map, sizeof(map));
char displayName[PLATFORM_MAX_PATH];
GetMapDisplayName(map, displayName, sizeof(displayName));
if (g_Cvar_ExcludeCurrent.BoolValue)
{
if (StrEqual(map, currentMap))
@ -297,7 +324,7 @@ void BuildMapMenu()
}
}
g_MapMenu.AddItem(map, map);
g_MapMenu.AddItem(map, displayName);
g_mapTrie.SetValue(map, status);
}
@ -312,8 +339,8 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
{
case MenuAction_Select:
{
char map[PLATFORM_MAX_PATH], name[MAX_NAME_LENGTH];
menu.GetItem(param2, map, sizeof(map));
char map[PLATFORM_MAX_PATH], name[MAX_NAME_LENGTH], displayName[PLATFORM_MAX_PATH];
menu.GetItem(param2, map, sizeof(map), _, displayName, sizeof(displayName));
GetClientName(param1, name, sizeof(name));
@ -335,11 +362,11 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
if (result == Nominate_Replaced)
{
PrintToChatAll("[SM] %t", "Map Nomination Changed", name, map);
PrintToChatAll("[SM] %t", "Map Nomination Changed", name, displayName);
return 0;
}
PrintToChatAll("[SM] %t", "Map Nominated", name, map);
PrintToChatAll("[SM] %t", "Map Nominated", name, displayName);
}
case MenuAction_DrawItem:
@ -366,8 +393,8 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
case MenuAction_DisplayItem:
{
char map[PLATFORM_MAX_PATH];
menu.GetItem(param2, map, sizeof(map));
char map[PLATFORM_MAX_PATH], displayName[PLATFORM_MAX_PATH];
menu.GetItem(param2, map, sizeof(map), _, displayName, sizeof(displayName));
int status;
@ -383,19 +410,19 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
{
if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT)
{
Format(display, sizeof(display), "%s (%T)", map, "Current Map", param1);
Format(display, sizeof(display), "%s (%T)", displayName, "Current Map", param1);
return RedrawMenuItem(display);
}
if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS)
{
Format(display, sizeof(display), "%s (%T)", map, "Recently Played", param1);
Format(display, sizeof(display), "%s (%T)", displayName, "Recently Played", param1);
return RedrawMenuItem(display);
}
if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED)
{
Format(display, sizeof(display), "%s (%T)", map, "Nominated", param1);
Format(display, sizeof(display), "%s (%T)", displayName, "Nominated", param1);
return RedrawMenuItem(display);
}
}

View File

@ -82,6 +82,7 @@ public void OnConfigsExecuted()
public Action Timer_RandomizeNextmap(Handle timer)
{
char map[PLATFORM_MAX_PATH];
char resolvedMap[PLATFORM_MAX_PATH];
bool oldMaps = false;
if (g_Cvar_ExcludeMaps.IntValue && g_MapList.Length > g_Cvar_ExcludeMaps.IntValue)
@ -89,16 +90,14 @@ public Action Timer_RandomizeNextmap(Handle timer)
oldMaps = true;
}
int b = GetRandomInt(0, g_MapList.Length - 1);
g_MapList.GetString(b, map, sizeof(map));
while (oldMaps && g_OldMapList.FindString(map) != -1)
do
{
b = GetRandomInt(0, g_MapList.Length - 1);
int b = GetRandomInt(0, g_MapList.Length - 1);
g_MapList.GetString(b, map, sizeof(map));
}
FindMap(map, resolvedMap, sizeof(resolvedMap));
} while (oldMaps && g_OldMapList.FindString(resolvedMap) != -1);
g_OldMapList.PushString(map);
g_OldMapList.PushString(resolvedMap);
SetNextMap(map);
if (g_OldMapList.Length > g_Cvar_ExcludeMaps.IntValue)

View File

@ -243,6 +243,8 @@ void StartRTV()
char map[PLATFORM_MAX_PATH];
if (GetNextMap(map, sizeof(map)))
{
GetMapDisplayName(map, map, sizeof(map));
PrintToChatAll("[SM] %t", "Changing Maps", map);
CreateTimer(5.0, Timer_ChangeMap, _, TIMER_FLAG_NO_MAPCHANGE);
g_InChange = true;

View File

@ -0,0 +1,25 @@
#include <sourcemod>
public void OnPluginStart()
{
RegServerCmd("test_mapdisplayname", test_mapdisplayname);
}
public Action test_mapdisplayname( int argc )
{
char mapName[PLATFORM_MAX_PATH];
GetCmdArg(1, mapName, sizeof(mapName));
char displayName[PLATFORM_MAX_PATH];
if (GetMapDisplayName(mapName, displayName, sizeof(displayName)))
{
PrintToServer("GetMapDisplayName says \"%s\" for \"%s\"", displayName, mapName);
}
else
{
PrintToServer("GetMapDisplayName says \"%s\" was not found or not resolved", mapName);
}
return Plugin_Handled;
}