Prevent remote map searches overwriting local or generated state.
This commit is contained in:
committed by
Gustas Kažukauskas
parent
4a4217c3b3
commit
e8d710dee4
@@ -235,7 +235,7 @@ namespace OpenRA
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
foreach (var uid in queryUids)
|
foreach (var uid in queryUids)
|
||||||
previews[uid].UpdateRemoteSearch(MapStatus.Searching, null, null);
|
previews[uid].BeginRemoteSearch();
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@@ -251,29 +251,21 @@ namespace OpenRA
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await client.GetStreamAsync(url);
|
var result = await client.GetStreamAsync(url);
|
||||||
var yaml = MiniYaml.FromStream(result, url, stringPool: stringPool);
|
foreach (var kv in MiniYaml.FromStream(result, url, stringPool: stringPool))
|
||||||
foreach (var kv in yaml)
|
previews[kv.Key].CompleteRemoteSearch(kv.Value, mapDetailsReceived);
|
||||||
previews[kv.Key].UpdateRemoteSearch(MapStatus.DownloadAvailable, kv.Value, mapDetailsReceived);
|
|
||||||
|
|
||||||
foreach (var uid in batchUids)
|
|
||||||
{
|
|
||||||
var p = previews[uid];
|
|
||||||
if (p.Status != MapStatus.DownloadAvailable)
|
|
||||||
p.UpdateRemoteSearch(MapStatus.Unavailable, null, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Write("debug", "Remote map query failed with error:");
|
Log.Write("debug", "Remote map query failed with error:");
|
||||||
Log.Write("debug", e);
|
Log.Write("debug", e);
|
||||||
Log.Write("debug", $"URL was: {url}");
|
Log.Write("debug", $"URL was: {url}");
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var uid in batchUids)
|
foreach (var uid in batchUids)
|
||||||
{
|
{
|
||||||
var p = previews[uid];
|
var p = previews[uid];
|
||||||
p.UpdateRemoteSearch(MapStatus.Unavailable, null, null);
|
if (p.Status == MapStatus.Searching)
|
||||||
mapQueryFailed?.Invoke(p);
|
p.CompleteRemoteSearch(null, mapQueryFailed);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
|
|
||||||
static readonly CPos[] NoSpawns = [];
|
static readonly CPos[] NoSpawns = [];
|
||||||
|
readonly object syncRoot = new();
|
||||||
readonly MapCache cache;
|
readonly MapCache cache;
|
||||||
readonly ModData modData;
|
readonly ModData modData;
|
||||||
IReadOnlyPackage package;
|
IReadOnlyPackage package;
|
||||||
@@ -452,28 +453,37 @@ namespace OpenRA
|
|||||||
newData.ModifiedDate = File.GetLastWriteTime(p.Name);
|
newData.ModifiedDate = File.GetLastWriteTime(p.Name);
|
||||||
|
|
||||||
// Assign the new data atomically
|
// Assign the new data atomically
|
||||||
innerData = newData;
|
// Local maps have higher precedence than remote/generated maps,
|
||||||
|
// so should always replace their metadata
|
||||||
|
lock (syncRoot)
|
||||||
|
innerData = newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action<MapPreview> parseMetadata = null)
|
public void BeginRemoteSearch()
|
||||||
{
|
{
|
||||||
var newData = innerData.Clone();
|
var newData = innerData.Clone();
|
||||||
newData.Status = status;
|
|
||||||
newData.Class = MapClassification.Remote;
|
newData.Class = MapClassification.Remote;
|
||||||
|
newData.Status = MapStatus.Searching;
|
||||||
|
|
||||||
if (status == MapStatus.DownloadAvailable)
|
// We may have been resolved to a local/generated map by another
|
||||||
|
// async task. Make sure we don't stomp over their state!
|
||||||
|
lock (syncRoot)
|
||||||
|
if (innerData.Class == MapClassification.Unknown || innerData.Class == MapClassification.Remote)
|
||||||
|
innerData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CompleteRemoteSearch(MiniYaml yaml, Action<MapPreview> parseMetadata = null)
|
||||||
|
{
|
||||||
|
var newData = innerData.Clone();
|
||||||
|
newData.Class = MapClassification.Remote;
|
||||||
|
newData.Status = MapStatus.Unavailable;
|
||||||
|
|
||||||
|
if (yaml != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var r = FieldLoader.Load<RemoteMapData>(yaml);
|
var r = FieldLoader.Load<RemoteMapData>(yaml);
|
||||||
|
newData.Status = r.downloading ? MapStatus.DownloadAvailable : MapStatus.Unavailable;
|
||||||
// Map download has been disabled server side
|
|
||||||
if (!r.downloading)
|
|
||||||
{
|
|
||||||
newData.Status = MapStatus.Unavailable;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
newData.Title = r.title;
|
newData.Title = r.title;
|
||||||
newData.Categories = r.categories;
|
newData.Categories = r.categories;
|
||||||
newData.Author = r.author;
|
newData.Author = r.author;
|
||||||
@@ -520,19 +530,27 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
Log.Write("debug", "Failed parsing mapserver response:");
|
Log.Write("debug", "Failed parsing mapserver response:");
|
||||||
Log.Write("debug", e);
|
Log.Write("debug", e);
|
||||||
|
newData.Status = MapStatus.Unavailable;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Commit updated data before running the callbacks
|
// We may have been resolved to a local/generated map by another
|
||||||
innerData = newData;
|
// async task. Make sure we don't stomp over their state!
|
||||||
|
MapClassification mapClassification;
|
||||||
|
lock (syncRoot)
|
||||||
|
{
|
||||||
|
mapClassification = innerData.Class;
|
||||||
|
if (mapClassification == MapClassification.Remote)
|
||||||
|
innerData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapClassification == MapClassification.Remote)
|
||||||
|
{
|
||||||
if (innerData.Preview != null)
|
if (innerData.Preview != null)
|
||||||
cache.CacheMinimap(this);
|
cache.CacheMinimap(this);
|
||||||
|
|
||||||
parseMetadata?.Invoke(this);
|
parseMetadata?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the status and class unconditionally
|
|
||||||
innerData = newData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Install(string mapRepositoryUrl)
|
public void Install(string mapRepositoryUrl)
|
||||||
@@ -605,7 +623,11 @@ namespace OpenRA
|
|||||||
|
|
||||||
public void Invalidate()
|
public void Invalidate()
|
||||||
{
|
{
|
||||||
innerData.Status = MapStatus.Unavailable;
|
lock (syncRoot)
|
||||||
|
{
|
||||||
|
innerData.Class = MapClassification.Unknown;
|
||||||
|
innerData.Status = MapStatus.Unavailable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
Reference in New Issue
Block a user