Add dynamic map refresh
This commit is contained in:
committed by
Matthias Mailänder
parent
61df7974b0
commit
b254eb0f3d
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
* available to you under the terms of the GNU General Public License
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation, either version 3 of
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
@@ -39,6 +39,14 @@ namespace OpenRA
|
|||||||
|
|
||||||
public Dictionary<string, string> StringPool { get; } = new Dictionary<string, string>();
|
public Dictionary<string, string> StringPool { get; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
readonly List<MapDirectoryTracker> mapDirectoryTrackers = new List<MapDirectoryTracker>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If a map was added oldUID will be null, if updated oldUId will point to the outdated map
|
||||||
|
/// Event is not called when map is deleted
|
||||||
|
/// </summary>
|
||||||
|
public event Action<string, string> MapUpdated = (oldUID, newUID) => { };
|
||||||
|
|
||||||
public MapCache(ModData modData)
|
public MapCache(ModData modData)
|
||||||
{
|
{
|
||||||
this.modData = modData;
|
this.modData = modData;
|
||||||
@@ -48,12 +56,20 @@ namespace OpenRA
|
|||||||
sheetBuilder = new SheetBuilder(SheetType.BGRA);
|
sheetBuilder = new SheetBuilder(SheetType.BGRA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateMaps()
|
||||||
|
{
|
||||||
|
foreach (var tracker in mapDirectoryTrackers)
|
||||||
|
tracker.UpdateMaps(this);
|
||||||
|
}
|
||||||
|
|
||||||
public void LoadMaps()
|
public void LoadMaps()
|
||||||
{
|
{
|
||||||
// Utility mod that does not support maps
|
// Utility mod that does not support maps
|
||||||
if (!modData.Manifest.Contains<MapGrid>())
|
if (!modData.Manifest.Contains<MapGrid>())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var mapGrid = modData.Manifest.Get<MapGrid>();
|
||||||
|
|
||||||
// Enumerate map directories
|
// Enumerate map directories
|
||||||
foreach (var kv in modData.Manifest.MapFolders)
|
foreach (var kv in modData.Manifest.MapFolders)
|
||||||
{
|
{
|
||||||
@@ -85,36 +101,42 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapLocations.Add(package, classification);
|
mapLocations.Add(package, classification);
|
||||||
|
mapDirectoryTrackers.Add(new MapDirectoryTracker(mapGrid, package, classification));
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapGrid = modData.Manifest.Get<MapGrid>();
|
|
||||||
foreach (var kv in MapLocations)
|
foreach (var kv in MapLocations)
|
||||||
{
|
{
|
||||||
foreach (var map in kv.Key.Contents)
|
foreach (var map in kv.Key.Contents)
|
||||||
{
|
LoadMap(map, kv.Key, kv.Value, mapGrid, null);
|
||||||
IReadOnlyPackage mapPackage = null;
|
}
|
||||||
try
|
}
|
||||||
{
|
|
||||||
using (new Support.PerfTimer(map))
|
|
||||||
{
|
|
||||||
mapPackage = kv.Key.OpenPackage(map, modData.ModFiles);
|
|
||||||
if (mapPackage == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var uid = Map.ComputeUID(mapPackage);
|
public void LoadMap(string map, IReadOnlyPackage package, MapClassification classification, MapGrid mapGrid, string oldMap)
|
||||||
previews[uid].UpdateFromMap(mapPackage, kv.Key, kv.Value, modData.Manifest.MapCompatibility, mapGrid.Type);
|
{
|
||||||
}
|
IReadOnlyPackage mapPackage = null;
|
||||||
}
|
try
|
||||||
catch (Exception e)
|
{
|
||||||
|
using (new Support.PerfTimer(map))
|
||||||
|
{
|
||||||
|
mapPackage = package.OpenPackage(map, modData.ModFiles);
|
||||||
|
if (mapPackage != null)
|
||||||
{
|
{
|
||||||
mapPackage?.Dispose();
|
var uid = Map.ComputeUID(mapPackage);
|
||||||
Console.WriteLine("Failed to load map: {0}", map);
|
previews[uid].UpdateFromMap(mapPackage, package, classification, modData.Manifest.MapCompatibility, mapGrid.Type);
|
||||||
Console.WriteLine("Details: {0}", e);
|
|
||||||
Log.Write("debug", "Failed to load map: {0}", map);
|
if (oldMap != uid)
|
||||||
Log.Write("debug", "Details: {0}", e);
|
MapUpdated(oldMap, uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
mapPackage?.Dispose();
|
||||||
|
Console.WriteLine("Failed to load map: {0}", map);
|
||||||
|
Console.WriteLine("Details: {0}", e);
|
||||||
|
Log.Write("debug", "Failed to load map: {0}", map);
|
||||||
|
Log.Write("debug", "Details: {0}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IReadWritePackage> EnumerateMapDirPackages(MapClassification classification = MapClassification.System)
|
public IEnumerable<IReadWritePackage> EnumerateMapDirPackages(MapClassification classification = MapClassification.System)
|
||||||
@@ -345,10 +367,18 @@ namespace OpenRA
|
|||||||
return initialUid;
|
return initialUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapPreview this[string key] => previews[key];
|
public MapPreview this[string key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
UpdateMaps();
|
||||||
|
return previews[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerator<MapPreview> GetEnumerator()
|
public IEnumerator<MapPreview> GetEnumerator()
|
||||||
{
|
{
|
||||||
|
UpdateMaps();
|
||||||
return previews.Values.GetEnumerator();
|
return previews.Values.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,6 +398,9 @@ namespace OpenRA
|
|||||||
foreach (var p in previews.Values)
|
foreach (var p in previews.Values)
|
||||||
p.Dispose();
|
p.Dispose();
|
||||||
|
|
||||||
|
foreach (var t in mapDirectoryTrackers)
|
||||||
|
t.Dispose();
|
||||||
|
|
||||||
// We need to let the loader thread exit before we can dispose our sheet builder.
|
// We need to let the loader thread exit before we can dispose our sheet builder.
|
||||||
// Ideally we should dispose our resources before returning, but we don't to block waiting on the loader thread to exit.
|
// Ideally we should dispose our resources before returning, but we don't to block waiting on the loader thread to exit.
|
||||||
// Instead, we'll queue disposal to be run once it has exited.
|
// Instead, we'll queue disposal to be run once it has exited.
|
||||||
|
|||||||
129
OpenRA.Game/Map/MapDirectoryTracker.cs
Normal file
129
OpenRA.Game/Map/MapDirectoryTracker.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileSystem;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public sealed class MapDirectoryTracker : IDisposable
|
||||||
|
{
|
||||||
|
readonly FileSystemWatcher watcher;
|
||||||
|
readonly MapGrid mapGrid;
|
||||||
|
readonly IReadOnlyPackage package;
|
||||||
|
readonly MapClassification classification;
|
||||||
|
|
||||||
|
enum MapAction { Add, Delete, Update }
|
||||||
|
readonly Dictionary<string, MapAction> mapActionQueue = new Dictionary<string, MapAction>();
|
||||||
|
|
||||||
|
bool dirty = false;
|
||||||
|
|
||||||
|
public MapDirectoryTracker(MapGrid mapGrid, IReadOnlyPackage package, MapClassification classification)
|
||||||
|
{
|
||||||
|
this.mapGrid = mapGrid;
|
||||||
|
this.package = package;
|
||||||
|
this.classification = classification;
|
||||||
|
|
||||||
|
watcher = new FileSystemWatcher(package.Name);
|
||||||
|
watcher.Changed += (object sender, FileSystemEventArgs e) => AddMapAction(MapAction.Update, e.FullPath);
|
||||||
|
watcher.Created += (object sender, FileSystemEventArgs e) => AddMapAction(MapAction.Add, e.FullPath);
|
||||||
|
watcher.Deleted += (object sender, FileSystemEventArgs e) => AddMapAction(MapAction.Delete, e.FullPath);
|
||||||
|
watcher.Renamed += (object sender, RenamedEventArgs e) => AddMapAction(MapAction.Add, e.FullPath, e.OldFullPath);
|
||||||
|
|
||||||
|
watcher.IncludeSubdirectories = true;
|
||||||
|
watcher.EnableRaisingEvents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
watcher.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddMapAction(MapAction mapAction, string fullpath, string oldFullPath = null)
|
||||||
|
{
|
||||||
|
lock (mapActionQueue)
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
|
||||||
|
// if path is not root, update map instead
|
||||||
|
var path = RemoveSubDirs(fullpath);
|
||||||
|
if (fullpath == path)
|
||||||
|
mapActionQueue[path] = mapAction;
|
||||||
|
else
|
||||||
|
mapActionQueue[path] = MapAction.Update;
|
||||||
|
|
||||||
|
// called when file has been renamed / changed location
|
||||||
|
if (oldFullPath != null)
|
||||||
|
{
|
||||||
|
var oldpath = RemoveSubDirs(oldFullPath);
|
||||||
|
if (oldpath != null)
|
||||||
|
if (oldFullPath == oldpath)
|
||||||
|
mapActionQueue[oldpath] = MapAction.Delete;
|
||||||
|
else
|
||||||
|
mapActionQueue[oldpath] = MapAction.Update;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMaps(MapCache mapcache)
|
||||||
|
{
|
||||||
|
lock (mapActionQueue)
|
||||||
|
{
|
||||||
|
if (!dirty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dirty = false;
|
||||||
|
foreach (var mapAction in mapActionQueue)
|
||||||
|
{
|
||||||
|
var map = mapcache.FirstOrDefault(x => x.Package?.Name == mapAction.Key && x.Status == MapStatus.Available);
|
||||||
|
if (map != null)
|
||||||
|
{
|
||||||
|
if (mapAction.Value == MapAction.Delete)
|
||||||
|
{
|
||||||
|
Console.WriteLine(mapAction.Key + " was deleted");
|
||||||
|
map.Invalidate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(mapAction.Key + " was updated");
|
||||||
|
map.Invalidate();
|
||||||
|
mapcache.LoadMap(mapAction.Key.Replace(package.Name + Path.DirectorySeparatorChar, ""), package, classification, mapGrid, map.Uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mapAction.Value != MapAction.Delete)
|
||||||
|
{
|
||||||
|
Console.WriteLine(mapAction.Key + " was added");
|
||||||
|
mapcache.LoadMap(mapAction.Key.Replace(package?.Name + Path.DirectorySeparatorChar, ""), package, classification, mapGrid, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapActionQueue.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string RemoveSubDirs(string path)
|
||||||
|
{
|
||||||
|
var endPath = path.Replace(package.Name + Path.DirectorySeparatorChar, "");
|
||||||
|
|
||||||
|
// if file moved from out outside directory, ignore it
|
||||||
|
if (path == endPath)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return package.Name + Path.DirectorySeparatorChar + endPath.Split(Path.DirectorySeparatorChar)[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
* available to you under the terms of the GNU General Public License
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation, either version 3 of
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
@@ -178,10 +178,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
var combinedPath = Platform.ResolvePath(Path.Combine(selectedDirectory.Folder.Name, filename.Text + fileTypes[fileType].Extension));
|
var combinedPath = Platform.ResolvePath(Path.Combine(selectedDirectory.Folder.Name, filename.Text + fileTypes[fileType].Extension));
|
||||||
|
|
||||||
// Invalidate the old map metadata
|
|
||||||
if (map.Uid != null && map.Package != null && map.Package.Name == combinedPath)
|
|
||||||
modData.MapCache[map.Uid].Invalidate();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!(map.Package is IReadWritePackage package) || package.Name != combinedPath)
|
if (!(map.Package is IReadWritePackage package) || package.Name != combinedPath)
|
||||||
@@ -195,9 +191,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
map.Save(package);
|
map.Save(package);
|
||||||
|
|
||||||
// Update the map cache so it can be loaded without restarting the game
|
|
||||||
modData.MapCache[map.Uid].UpdateFromMap(map.Package, selectedDirectory.Folder, selectedDirectory.Classification, null, map.Grid.Type);
|
|
||||||
|
|
||||||
Console.WriteLine("Saved current map at {0}", combinedPath);
|
Console.WriteLine("Saved current map at {0}", combinedPath);
|
||||||
Ui.CloseWindow();
|
Ui.CloseWindow();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
* available to you under the terms of the GNU General Public License
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation, either version 3 of
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
@@ -59,6 +59,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
MapPreview map;
|
MapPreview map;
|
||||||
Session.MapStatus mapStatus;
|
Session.MapStatus mapStatus;
|
||||||
|
string oldMapUid;
|
||||||
|
string newMapUid;
|
||||||
|
string lastUpdatedUid;
|
||||||
|
|
||||||
bool chatEnabled;
|
bool chatEnabled;
|
||||||
bool addBotOnMapLoad;
|
bool addBotOnMapLoad;
|
||||||
@@ -129,6 +132,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Game.LobbyInfoChanged += UpdateSpawnOccupants;
|
Game.LobbyInfoChanged += UpdateSpawnOccupants;
|
||||||
Game.BeforeGameStart += OnGameStart;
|
Game.BeforeGameStart += OnGameStart;
|
||||||
Game.ConnectionStateChanged += ConnectionStateChanged;
|
Game.ConnectionStateChanged += ConnectionStateChanged;
|
||||||
|
modData.MapCache.MapUpdated += TrackRelevantMapUpdates;
|
||||||
|
|
||||||
var name = lobby.GetOrNull<LabelWidget>("SERVER_NAME");
|
var name = lobby.GetOrNull<LabelWidget>("SERVER_NAME");
|
||||||
if (name != null)
|
if (name != null)
|
||||||
@@ -182,20 +186,26 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
var onSelect = new Action<string>(uid =>
|
var onSelect = new Action<string>(uid =>
|
||||||
{
|
{
|
||||||
// Don't select the same map again
|
// Don't select the same map again, and handle map becoming unavailable
|
||||||
if (uid == map.Uid)
|
if (uid == map.Uid && modData.MapCache[uid].Status != MapStatus.Available)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
orderManager.IssueOrder(Order.Command("map " + uid));
|
orderManager.IssueOrder(Order.Command("map " + uid));
|
||||||
Game.Settings.Server.Map = uid;
|
Game.Settings.Server.Map = uid;
|
||||||
Game.Settings.Save();
|
Game.Settings.Save();
|
||||||
|
newMapUid = null;
|
||||||
|
oldMapUid = null;
|
||||||
|
lastUpdatedUid = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check for updated maps, if the user has edited a map we'll preselect it for them
|
||||||
|
modData.MapCache.UpdateMaps();
|
||||||
|
|
||||||
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||||
{
|
{
|
||||||
{ "initialMap", map.Uid },
|
{ "initialMap", lastUpdatedUid ?? map.Uid },
|
||||||
{ "initialTab", MapClassification.System },
|
{ "initialTab", MapClassification.System },
|
||||||
{ "onExit", DoNothing },
|
{ "onExit", Game.IsHost ? new Action(() => UpdateSelectedMap()) : null },
|
||||||
{ "onSelect", Game.IsHost ? onSelect : null },
|
{ "onSelect", Game.IsHost ? onSelect : null },
|
||||||
{ "filter", MapVisibility.Lobby },
|
{ "filter", MapVisibility.Lobby },
|
||||||
});
|
});
|
||||||
@@ -364,8 +374,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
// Force start panel
|
// Force start panel
|
||||||
Action startGame = () =>
|
Action startGame = () =>
|
||||||
{
|
{
|
||||||
gameStarting = true;
|
// Refresh MapCache and check if the selected map is available before attempting to start the game
|
||||||
orderManager.IssueOrder(Order.Command("startgame"));
|
if (modData.MapCache[map.Uid].Status == MapStatus.Available)
|
||||||
|
{
|
||||||
|
gameStarting = true;
|
||||||
|
orderManager.IssueOrder(Order.Command("startgame"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
UpdateSelectedMap();
|
||||||
};
|
};
|
||||||
|
|
||||||
var startGameButton = lobby.GetOrNull<ButtonWidget>("START_GAME_BUTTON");
|
var startGameButton = lobby.GetOrNull<ButtonWidget>("START_GAME_BUTTON");
|
||||||
@@ -484,6 +500,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Game.LobbyInfoChanged -= UpdateSpawnOccupants;
|
Game.LobbyInfoChanged -= UpdateSpawnOccupants;
|
||||||
Game.BeforeGameStart -= OnGameStart;
|
Game.BeforeGameStart -= OnGameStart;
|
||||||
Game.ConnectionStateChanged -= ConnectionStateChanged;
|
Game.ConnectionStateChanged -= ConnectionStateChanged;
|
||||||
|
modData.MapCache.MapUpdated -= TrackRelevantMapUpdates;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
@@ -822,6 +839,36 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
onStart();
|
onStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrackRelevantMapUpdates(string oldUid, string newUid)
|
||||||
|
{
|
||||||
|
// We need to handle map being updated multiple times without a refresh
|
||||||
|
if (map.Uid == oldUid || oldUid == newMapUid)
|
||||||
|
{
|
||||||
|
if (oldMapUid == null)
|
||||||
|
oldMapUid = oldUid;
|
||||||
|
newMapUid = newUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newUid != null)
|
||||||
|
lastUpdatedUid = newUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateSelectedMap()
|
||||||
|
{
|
||||||
|
if (modData.MapCache[map.Uid].Status == MapStatus.Available)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (oldMapUid == map.Uid && modData.MapCache[newMapUid].Status == MapStatus.Available)
|
||||||
|
{
|
||||||
|
orderManager.IssueOrder(Order.Command("map " + newMapUid));
|
||||||
|
Game.Settings.Server.Map = newMapUid;
|
||||||
|
Game.Settings.Save();
|
||||||
|
newMapUid = null;
|
||||||
|
oldMapUid = null;
|
||||||
|
lastUpdatedUid = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LobbyFaction
|
public class LobbyFaction
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
* available to you under the terms of the GNU General Public License
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation, either version 3 of
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
@@ -158,7 +158,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
// Loading into the map editor
|
// Loading into the map editor
|
||||||
Game.BeforeGameStart += RemoveShellmapUI;
|
Game.BeforeGameStart += RemoveShellmapUI;
|
||||||
|
|
||||||
var onSelect = new Action<string>(uid => LoadMapIntoEditor(modData.MapCache[uid].Uid));
|
var onSelect = new Action<string>(uid =>
|
||||||
|
{
|
||||||
|
if (modData.MapCache[uid].Status != MapStatus.Available)
|
||||||
|
SwitchMenu(MenuType.Extras);
|
||||||
|
else
|
||||||
|
LoadMapIntoEditor(modData.MapCache[uid].Uid);
|
||||||
|
});
|
||||||
|
|
||||||
var newMapButton = widget.Get<ButtonWidget>("NEW_MAP_BUTTON");
|
var newMapButton = widget.Get<ButtonWidget>("NEW_MAP_BUTTON");
|
||||||
newMapButton.OnClick = () =>
|
newMapButton.OnClick = () =>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
* available to you under the terms of the GNU General Public License
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation, either version 3 of
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
if (previews.Any())
|
if (previews.Any())
|
||||||
{
|
{
|
||||||
CreateMissionGroup(kv.Key, previews);
|
CreateMissionGroup(kv.Key, previews, onExit);
|
||||||
allPreviews.AddRange(previews);
|
allPreviews.AddRange(previews);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
if (loosePreviews.Any())
|
if (loosePreviews.Any())
|
||||||
{
|
{
|
||||||
CreateMissionGroup("Missions", loosePreviews);
|
CreateMissionGroup("Missions", loosePreviews, onExit);
|
||||||
allPreviews.AddRange(loosePreviews);
|
allPreviews.AddRange(loosePreviews);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
}).Start();
|
}).Start();
|
||||||
|
|
||||||
var startButton = widget.Get<ButtonWidget>("STARTGAME_BUTTON");
|
var startButton = widget.Get<ButtonWidget>("STARTGAME_BUTTON");
|
||||||
startButton.OnClick = StartMissionClicked;
|
startButton.OnClick = () => StartMissionClicked(onExit);
|
||||||
startButton.IsDisabled = () => selectedMap == null;
|
startButton.IsDisabled = () => selectedMap == null;
|
||||||
|
|
||||||
widget.Get<ButtonWidget>("BACK_BUTTON").OnClick = () =>
|
widget.Get<ButtonWidget>("BACK_BUTTON").OnClick = () =>
|
||||||
@@ -179,7 +179,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateMissionGroup(string title, IEnumerable<MapPreview> previews)
|
void CreateMissionGroup(string title, IEnumerable<MapPreview> previews, Action onExit)
|
||||||
{
|
{
|
||||||
var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });
|
var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });
|
||||||
header.Get<LabelWidget>("LABEL").GetText = () => title;
|
header.Get<LabelWidget>("LABEL").GetText = () => title;
|
||||||
@@ -190,7 +190,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var item = ScrollItemWidget.Setup(template,
|
var item = ScrollItemWidget.Setup(template,
|
||||||
() => selectedMap != null && selectedMap.Uid == preview.Uid,
|
() => selectedMap != null && selectedMap.Uid == preview.Uid,
|
||||||
() => SelectMap(preview),
|
() => SelectMap(preview),
|
||||||
StartMissionClicked);
|
() => StartMissionClicked(onExit));
|
||||||
|
|
||||||
var label = item.Get<LabelWithTooltipWidget>("TITLE");
|
var label = item.Get<LabelWithTooltipWidget>("TITLE");
|
||||||
WidgetUtils.TruncateLabelToTooltip(label, preview.Title);
|
WidgetUtils.TruncateLabelToTooltip(label, preview.Title);
|
||||||
@@ -365,10 +365,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
playingVideo = PlayingVideo.None;
|
playingVideo = PlayingVideo.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartMissionClicked()
|
void StartMissionClicked(Action onExit)
|
||||||
{
|
{
|
||||||
StopVideo(videoPlayer);
|
StopVideo(videoPlayer);
|
||||||
|
|
||||||
|
// If selected mission becomes unavailable, exit MissionBrowser to refresh
|
||||||
|
if (modData.MapCache[selectedMap.Uid].Status != MapStatus.Available)
|
||||||
|
{
|
||||||
|
Game.Disconnect();
|
||||||
|
Ui.CloseWindow();
|
||||||
|
onExit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var orders = new List<Order>();
|
var orders = new List<Order>();
|
||||||
if (difficulty != null)
|
if (difficulty != null)
|
||||||
orders.Add(Order.Command($"option difficulty {difficulty}"));
|
orders.Add(Order.Command($"option difficulty {difficulty}"));
|
||||||
|
|||||||
Reference in New Issue
Block a user