Skip to content

Commit 96d0a2e

Browse files
committed
- Add a file watcher that will detect when a map is added or deleted, then update the game mode dropdown according to the new map list
- Add and use `CustomMapsDirectory` field to `MapLoader` to avoid hard coded strings. - Add `GetLoadedMapBySha1` to remove some duplicate `GameModeMaps.Find()`. - Add a function `RefreshGameModeDropdown` to modify the dropdown after client is loaded. The function is a bit complicated due to doing inline modifications to the items and keeping the selected mode. Issue: #352 PR: #358
1 parent 6ade1e4 commit 96d0a2e

File tree

6 files changed

+270
-28
lines changed

6 files changed

+270
-28
lines changed

DXMainClient/DXGUI/Generic/LoadingScreen.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ private void LoadMaps()
8181
{
8282
mapLoader = new MapLoader();
8383
mapLoader.LoadMaps();
84+
mapLoader.StartCustomMapFileWatcher();
8485
}
8586

8687
private void Finish()

DXMainClient/DXGUI/Multiplayer/GameLobby/CnCNetGameLobby.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,14 +1595,14 @@ private void MapSharer_HandleMapDownloadComplete(SHA1EventArgs e)
15951595
{
15961596
string mapFileName = MapSharer.GetMapFileName(e.SHA1, e.MapName);
15971597
Logger.Log("Map " + mapFileName + " downloaded, parsing.");
1598-
string mapPath = "Maps/Custom/" + mapFileName;
1598+
string mapPath = MapLoader.CustomMapsDirectory + mapFileName;
15991599
Map map = MapLoader.LoadCustomMap(mapPath, out string returnMessage);
16001600
if (map != null)
16011601
{
16021602
AddNotice(returnMessage);
16031603
if (lastMapSHA1 == e.SHA1)
16041604
{
1605-
GameModeMap = GameModeMaps.Find(gmm => gmm.Map.SHA1 == lastMapSHA1);
1605+
GameModeMap = MapLoader.GetLoadedMapBySha1(lastMapSHA1);
16061606
ChangeMap(GameModeMap);
16071607
}
16081608
}
@@ -1804,7 +1804,7 @@ private void DownloadMapByIdCommand(string parameters)
18041804
sha1 = sha1.Replace("?", "");
18051805

18061806
// See if the user already has this map, with any filename, before attempting to download it.
1807-
GameModeMap loadedMap = GameModeMaps.Find(gmm => gmm.Map.SHA1 == sha1);
1807+
GameModeMap loadedMap = MapLoader.GetLoadedMapBySha1(sha1);
18081808

18091809
if (loadedMap != null)
18101810
{

DXMainClient/DXGUI/Multiplayer/GameLobby/GameLobbyBase.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ DiscordHandler discordHandler
5858
) : base(windowManager)
5959
{
6060
_iniSectionName = iniName;
61+
6162
MapLoader = mapLoader;
63+
MapLoader.GameModeMapsUpdated += MapLoader_GameModeMapsUpdated;
64+
6265
this.isMultiplayer = isMultiplayer;
6366
this.discordHandler = discordHandler;
6467
}
@@ -2318,5 +2321,63 @@ public bool LoadGameOptionPreset(string name)
23182321
}
23192322

23202323
protected abstract bool AllowPlayerOptionsChange();
2324+
2325+
/// <summary>
2326+
/// Handle the GameModeMapsUpdated event from the MapLoader.
2327+
///
2328+
/// Updates the gamemode dropdown for new maps being added while the client is running
2329+
/// </summary>
2330+
/// <param name="sender"></param>
2331+
/// <param name="e"></param>
2332+
private void MapLoader_GameModeMapsUpdated(object sender, MapLoaderEventArgs e)
2333+
{
2334+
RefreshGameModeDropdown();
2335+
}
2336+
2337+
/// <summary>
2338+
/// Update the gamemode dropdown.
2339+
///
2340+
/// Allows us to show gamemodes for maps that were loaded after the client was started.
2341+
/// This function will do in-place modifications to `ddGameModeMapFilter.Items`.
2342+
/// </summary>
2343+
public void RefreshGameModeDropdown()
2344+
{
2345+
// Use a hashset to store the existing gamemodes in the dropdown for instant lookups.
2346+
// This is the set of existing dropdown items. Add anything from GameModeMaps, that isn't in this set, to the dropdown.
2347+
HashSet<string> existingDdGameModes = new HashSet<string>(ddGameModeMapFilter.Items.Select(ddItem => ddItem.Text));
2348+
// This is the updated list of game modes. Anything not in this set, that is in existingDdGameModes, should be removed from the dropdown.
2349+
HashSet<string> gameModeUpdated = new HashSet<string>(GameModeMaps.GameModes.Select(gm => gm.UIName));
2350+
// Don't accidentally remove favorite maps item.
2351+
gameModeUpdated.Add(FavoriteMapsLabel);
2352+
2353+
XNADropDownItem currentItem = ddGameModeMapFilter.SelectedItem;
2354+
2355+
Logger.Log($"Updating game modes dropdown display: lobbyType={this.GetType().Name}");
2356+
2357+
// Add any new game modes.
2358+
foreach (GameMode gm in GameModeMaps.GameModes)
2359+
{
2360+
//skip the game mode if it is already in the dropdown.
2361+
if (existingDdGameModes.Contains(gm.UIName))
2362+
continue;
2363+
2364+
// If the gamemode was not present, then add it.
2365+
ddGameModeMapFilter.AddItem(CreateGameFilterItem(gm.UIName, new GameModeMapFilter(GetGameModeMaps(gm))));
2366+
}
2367+
2368+
// Now remove game modes that should no longer be displayed.
2369+
ddGameModeMapFilter.Items.RemoveAll(ddItem => !gameModeUpdated.Contains(ddItem.Text));
2370+
2371+
// Make sure we keep the same game mode selected after adding or removing game modes.
2372+
// If the game mode is no longer available then switch to 0, aka, favorite maps.
2373+
int newIndex = 0;
2374+
for (int i = 0; i < ddGameModeMapFilter.Items.Count; i++)
2375+
{
2376+
if (ddGameModeMapFilter.Items[i].Text == currentItem.Text)
2377+
newIndex = i;
2378+
}
2379+
2380+
ddGameModeMapFilter.SelectedIndex = newIndex;
2381+
}
23212382
}
23222383
}

DXMainClient/DXGUI/Multiplayer/GameLobby/MultiplayerGameLobby.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public MultiplayerGameLobby(WindowManager windowManager, string iniName,
4444
s => SetMaxAhead(s)),
4545
new ChatBoxCommand("PROTOCOLVERSION", "Change ProtocolVersion (default 2) (game host only)".L10N("UI:Main:ChatboxCommandProtocolVersionHelp"), true,
4646
s => SetProtocolVersion(s)),
47-
new ChatBoxCommand("LOADMAP", "Load a custom map with given filename from /Maps/Custom/ folder.".L10N("UI:Main:ChatboxCommandLoadMapHelp"), true, LoadCustomMap),
47+
new ChatBoxCommand("LOADMAP", $"Load a custom map with given filename from {MapLoader.CustomMapsDirectory} folder.".L10N("UI:Main:ChatboxCommandLoadMapHelp"), true, LoadCustomMap),
4848
new ChatBoxCommand("RANDOMSTARTS", "Enables completely random starting locations (Tiberian Sun based games only).".L10N("UI:Main:ChatboxCommandRandomStartsHelp"), true,
4949
s => SetStartingLocationClearance(s)),
5050
new ChatBoxCommand("ROLL", "Roll dice, for example /roll 3d6".L10N("UI:Main:ChatboxCommandRollHelp"), false, RollDiceCommand),
@@ -487,7 +487,7 @@ private void RollDiceCommand(string dieType)
487487
/// <param name="mapName">Name of the map given as a parameter, without file extension.</param>
488488
private void LoadCustomMap(string mapName)
489489
{
490-
Map map = MapLoader.LoadCustomMap($"Maps/Custom/{mapName}", out string resultMessage);
490+
Map map = MapLoader.LoadCustomMap($"{MapLoader.CustomMapsDirectory}{mapName}", out string resultMessage);
491491
if (map != null)
492492
{
493493
AddNotice(resultMessage);

0 commit comments

Comments
 (0)