Skip to content

Commit 87c34b5

Browse files
committed
CnCNet#352: Add custom map file watcher
- Address review feedback - Use safe path everywhere - Remove maps if they are renamed and their file extension changes - Remove unnecessary file watcher filters - sha1 -> SHA-1 Issue: CnCNet#352 PR: CnCNet#358
1 parent 96d0a2e commit 87c34b5

File tree

2 files changed

+33
-22
lines changed

2 files changed

+33
-22
lines changed

DXMainClient/DXGUI/Multiplayer/GameLobby/MultiplayerGameLobby.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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($"{MapLoader.CustomMapsDirectory}{mapName}", out string resultMessage);
490+
Map map = MapLoader.LoadCustomMap(SafePath.CombineFilePath(MapLoader.CustomMapsDirectory, mapName), out string resultMessage);
491491
if (map != null)
492492
{
493493
AddNotice(resultMessage);

DXMainClient/Domain/Multiplayer/MapLoader.cs

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class MapLoader
2323

2424
/// <summary>
2525
/// The relative path to the folder where custom maps are stored.
26-
/// This is the public version of CUSTOM_MAPS_DIRECTORY ending in a slash for convenience.
26+
/// This is the public version of CUSTOM_MAPS_DIRECTORY with a "/" added for convenience.
2727
/// </summary>
2828
public const string CustomMapsDirectory = CUSTOM_MAPS_DIRECTORY + "/";
2929

@@ -60,7 +60,7 @@ public class MapLoader
6060
private FileSystemWatcher customMapFileWatcher;
6161

6262
/// <summary>
63-
/// Check to see if a map matching the sha1 ID is already loaded.
63+
/// Check to see if a map matching the SHA-1 ID is already loaded.
6464
/// </summary>
6565
/// <param name="sha1">The map ID to search the loaded maps for.</param>
6666
/// <returns></returns>
@@ -70,10 +70,10 @@ public bool IsMapAlreadyLoaded(string sha1)
7070
}
7171

7272
/// <summary>
73-
/// Search the loaded maps for the sha1, return the map if a match is found.
73+
/// Search the loaded maps for the SHA-1, return the map if a match is found.
7474
/// </summary>
7575
/// <param name="sha1">The map ID to search the loaded maps for.</param>
76-
/// <returns>The map matching the sha1 if one was found.</returns>
76+
/// <returns>The map matching the SHA-1 if one was found.</returns>
7777
public GameModeMap GetLoadedMapBySha1(string sha1)
7878
{
7979
return GameModeMaps.Find(gmm => gmm.Map.SHA1 == sha1);
@@ -95,17 +95,9 @@ public void LoadMapsAsync()
9595
/// </summary>
9696
public void StartCustomMapFileWatcher()
9797
{
98-
customMapFileWatcher = new FileSystemWatcher($"{ProgramConstants.GamePath}{CustomMapsDirectory}");
98+
customMapFileWatcher = new FileSystemWatcher(SafePath.CombineDirectoryPath(ProgramConstants.GamePath, CustomMapsDirectory));
9999

100100
customMapFileWatcher.Filter = $"*{MAP_FILE_EXTENSION}";
101-
customMapFileWatcher.NotifyFilter = NotifyFilters.Attributes
102-
| NotifyFilters.CreationTime
103-
| NotifyFilters.DirectoryName
104-
| NotifyFilters.FileName
105-
| NotifyFilters.LastAccess
106-
| NotifyFilters.LastWrite
107-
| NotifyFilters.Security
108-
| NotifyFilters.Size;
109101

110102
customMapFileWatcher.Created += HandleCustomMapFolder_Created;
111103
customMapFileWatcher.Deleted += HandleCustomMapFolder_Deleted;
@@ -127,8 +119,11 @@ public void HandleCustomMapFolder_Created(object sender, FileSystemEventArgs e)
127119
{
128120
// Get the map filename without the extension.
129121
// The extension gets added in LoadCustomMap so we need to excise it to avoid "file.map.map".
130-
string name = e.Name.EndsWith(MAP_FILE_EXTENSION) ? e.Name.Remove(e.Name.Length - MAP_FILE_EXTENSION.Length) : e.Name;
131-
string relativeMapPath = $"{CustomMapsDirectory}{name}";
122+
string name = Path.GetFileNameWithoutExtension(e.Name);
123+
124+
if (name.StartsWith())
125+
126+
string relativeMapPath = SafePath.CombineFilePath(CustomMapsDirectory, name);
132127
Map map = LoadCustomMap(relativeMapPath, out string result);
133128

134129
if (map == null)
@@ -147,11 +142,13 @@ public void HandleCustomMapFolder_Created(object sender, FileSystemEventArgs e)
147142
public void HandleCustomMapFolder_Deleted(object sender, FileSystemEventArgs e)
148143
{
149144
Logger.Log($"Map was deleted: map={e.Name}");
145+
// Use the filename without the extension so we can remove maps that had their extension changed.
146+
string name = Path.GetFileNameWithoutExtension(e.Name);
150147
// The way we're detecting the loaded map is hacky, but we don't
151-
// have the sha1 to work with.
148+
// have the SHA-1 to work with.
152149
foreach (GameMode gameMode in GameModes)
153150
{
154-
gameMode.Maps.RemoveAll(map => map.CompleteFilePath.EndsWith(e.Name));
151+
gameMode.Maps.RemoveAll(map => Path.GetFileNameWithoutExtension(map.CompleteFilePath).EndsWith(name));
155152
}
156153

157154
RemoveEmptyGameModesAndUpdateGameModeMaps();
@@ -170,15 +167,29 @@ public void HandleCustomMapFolder_Deleted(object sender, FileSystemEventArgs e)
170167
/// <param name="e"></param>
171168
public void HandleCustomMapFolder_Renamed(object sender, RenamedEventArgs e)
172169
{
173-
string name = e.Name.EndsWith(MAP_FILE_EXTENSION) ? e.Name.Remove(e.Name.Length - MAP_FILE_EXTENSION.Length) : e.Name;
174-
string relativeMapPath = $"{CustomMapsDirectory}{name}";
170+
string name = Path.GetFileNameWithoutExtension(e.Name);
171+
string relativeMapPath = SafePath.CombineFilePath(CustomMapsDirectory, name);
172+
bool oldPathIsMap = Path.GetExtension(e.OldName) == MAP_FILE_EXTENSION;
173+
bool newPathIsMap = Path.GetExtension(e.Name) == MAP_FILE_EXTENSION;
175174

176175
// Check if the user is renaming a non ".map" file.
177176
// This is just for logging to help debug.
178-
if (!e.OldName.EndsWith(MAP_FILE_EXTENSION))
177+
if (!oldPathIsMap && newPathIsMap)
179178
{
180179
Logger.Log($"Renaming file changed the file extension. User is likely renaming a '.yrm' from Final Alert 2: old={e.OldName}, new={e.Name}");
181180
}
181+
else if (oldPathIsMap && !newPathIsMap)
182+
{
183+
// A bit hacky, but this is a rare case.
184+
Logger.Log($"Renaming file changed the file extension to no longer be '.map' for some reason, removing from map list: old={e.OldName}, new={e.Name}");
185+
HandleCustomMapFolder_Deleted(sender, e);
186+
}
187+
188+
if (!newPathIsMap)
189+
{
190+
Logger.Log($"Renaming file. New extension is not '{MAP_FILE_EXTENSION}', moving on: file={e.Name}");
191+
return;
192+
}
182193

183194
Map map = LoadCustomMap(relativeMapPath, out string result);
184195

@@ -431,7 +442,7 @@ public Map LoadCustomMap(string mapPath, out string resultMessage)
431442
}
432443

433444
// Make sure we don't accidentally load the same map twice.
434-
// This checks the sha1, so duplicate maps in two .map files with different filenames can still be detected.
445+
// This checks the SHA-1, so duplicate maps in two .map files with different filenames can still be detected.
435446
if (IsMapAlreadyLoaded(map.SHA1))
436447
{
437448
Logger.Log("LoadCustomMap: Custom map " + customMapFile.FullName + " is already loaded!");

0 commit comments

Comments
 (0)