diff --git a/src/EvoSC.Common/Interfaces/Services/IPlayerManagerService.cs b/src/EvoSC.Common/Interfaces/Services/IPlayerManagerService.cs
index b676ab372..493c6a9c9 100644
--- a/src/EvoSC.Common/Interfaces/Services/IPlayerManagerService.cs
+++ b/src/EvoSC.Common/Interfaces/Services/IPlayerManagerService.cs
@@ -19,6 +19,15 @@ public interface IPlayerManagerService
///
public Task GetOrCreatePlayerAsync(string accountId);
+ ///
+ /// Get a player by their account ID. If the player does not
+ /// exist in the database, create the entry.
+ ///
+ /// Account ID of the player.
+ /// Name of the new player if created.
+ ///
+ public Task GetOrCreatePlayerAsync(string accountId, string? name);
+
///
/// Create a new entry for a player in the database.
///
diff --git a/src/EvoSC.Common/Services/MapService.cs b/src/EvoSC.Common/Services/MapService.cs
index 05cfad607..e1f957807 100644
--- a/src/EvoSC.Common/Services/MapService.cs
+++ b/src/EvoSC.Common/Services/MapService.cs
@@ -6,6 +6,10 @@
using EvoSC.Common.Interfaces.Services;
using EvoSC.Common.Models.Maps;
using EvoSC.Common.Util;
+using GbxRemoteNet;
+using GbxRemoteNet.Interfaces;
+using GbxRemoteNet.Structs;
+using GbxRemoteNet.XmlRpc.ExtraTypes;
using Microsoft.Extensions.Logging;
namespace EvoSC.Common.Services;
@@ -85,9 +89,9 @@ public async Task RemoveMapAsync(long mapId)
public async Task AddCurrentMapListAsync()
{
- var serverMapList = await serverClient.Remote.GetMapListAsync(-1, 0);
+ var maplist = await GetRemoteMapListAsync();
- foreach (var serverMap in serverMapList)
+ foreach (var serverMap in maplist)
{
try
{
@@ -97,9 +101,9 @@ public async Task AddCurrentMapListAsync()
{
continue;
}
-
+
var authorAccountId = PlayerUtils.ConvertLoginToAccountId(serverMap.Author);
- var author = await playerService.GetOrCreatePlayerAsync(authorAccountId);
+ var author = await playerService.GetOrCreatePlayerAsync(authorAccountId, serverMap.AuthorNickname);
var mapMeta = new MapMetadata
{
@@ -115,7 +119,7 @@ public async Task AddCurrentMapListAsync()
logger.LogDebug("Adding map {Name} ({Uid}) to the database", serverMap.Name, serverMap.UId);
var map = await mapRepository.AddMapAsync(mapMeta, author, serverMap.FileName);
- var mapDetails = await FetchMapDetailsAsync(map);
+ var mapDetails = new ParsedMap(serverMap, map);
await mapRepository.AddMapDetailsAsync(mapDetails, map);
}
catch (Exception ex)
@@ -137,8 +141,8 @@ public async Task GetOrAddCurrentMapAsync()
return map;
}
- var mapAuthor =
- await playerService.GetOrCreatePlayerAsync(PlayerUtils.ConvertLoginToAccountId(currentMap.Author));
+ var authorAccountId = PlayerUtils.ConvertLoginToAccountId(currentMap.Author);
+ var mapAuthor = await playerService.GetOrCreatePlayerAsync(authorAccountId, currentMap.AuthorNickname);
var mapMeta = new MapMetadata
{
@@ -235,4 +239,54 @@ private async Task SaveMapFileAsync(Stream mapStream, string filePath)
throw;
}
}
+
+ private async Task> GetRemoteMapListAsync()
+ {
+ var serverMapList = await serverClient.Remote.GetMapListAsync(-1, 0);
+ var calls = new List();
+
+ // server can have more maps than calls allowed in a multicall, so split it up
+ for (var i = 0; i < serverMapList.Length; i++)
+ {
+ if (i % 20 == 0)
+ {
+ calls.Add(new MultiCall());
+ }
+
+ calls.Last().Add("GetMapInfo", serverMapList[i].FileName);
+ }
+
+ var maplist = new List();
+
+ foreach (var call in calls)
+ {
+ var mapsWithDetails = await serverClient.Remote.MultiCallAsync(call);
+
+ foreach (GbxDynamicObject serverMap in mapsWithDetails)
+ {
+ maplist.Add(new TmMapInfo
+ {
+ UId = (string)serverMap["UId"],
+ Name = (string)serverMap["Name"],
+ FileName = (string)serverMap["FileName"],
+ Author = (string)serverMap["Author"],
+ AuthorNickname = (string)serverMap["AuthorNickname"],
+ Environnement = (string)serverMap["Environnement"],
+ Mood = (string)serverMap["Mood"],
+ BronzeTime = (int)serverMap["BronzeTime"],
+ SilverTime = (int)serverMap["SilverTime"],
+ GoldTime = (int)serverMap["GoldTime"],
+ AuthorTime = (int)serverMap["AuthorTime"],
+ CopperPrice = (int)serverMap["CopperPrice"],
+ LapRace = (bool)serverMap["LapRace"],
+ NbLaps = (int)serverMap["NbLaps"],
+ NbCheckpoints = (int)serverMap["NbCheckpoints"],
+ MapType = (string)serverMap["MapType"],
+ MapStyle = (string)serverMap["MapStyle"]
+ });
+ }
+ }
+
+ return maplist;
+ }
}
diff --git a/src/EvoSC.Common/Services/PlayerManagerService.cs b/src/EvoSC.Common/Services/PlayerManagerService.cs
index 325fe73fd..57f8f5192 100644
--- a/src/EvoSC.Common/Services/PlayerManagerService.cs
+++ b/src/EvoSC.Common/Services/PlayerManagerService.cs
@@ -16,7 +16,9 @@ public class PlayerManagerService(IPlayerRepository playerRepository, IPlayerCac
public async Task GetPlayerAsync(string accountId) =>
await playerRepository.GetPlayerByAccountIdAsync(accountId);
- public async Task GetOrCreatePlayerAsync(string accountId)
+ public Task GetOrCreatePlayerAsync(string accountId) => GetOrCreatePlayerAsync(accountId, null);
+
+ public async Task GetOrCreatePlayerAsync(string accountId, string? name)
{
try
{
@@ -34,7 +36,7 @@ public async Task GetOrCreatePlayerAsync(string accountId)
accountId);
}
- return await CreatePlayerAsync(accountId);
+ return await CreatePlayerAsync(accountId, name);
}
public Task CreatePlayerAsync(string accountId) => CreatePlayerAsync(accountId, null);
diff --git a/tests/EvoSC.Common.Tests/Services/MapServiceTests.cs b/tests/EvoSC.Common.Tests/Services/MapServiceTests.cs
index bc05ed42d..fc2ca4cbe 100644
--- a/tests/EvoSC.Common.Tests/Services/MapServiceTests.cs
+++ b/tests/EvoSC.Common.Tests/Services/MapServiceTests.cs
@@ -14,8 +14,10 @@
using EvoSC.Common.Models.Maps;
using EvoSC.Common.Services;
using EvoSC.Testing;
+using GbxRemoteNet;
using GbxRemoteNet.Interfaces;
using GbxRemoteNet.Structs;
+using GbxRemoteNet.XmlRpc.ExtraTypes;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
@@ -370,6 +372,7 @@ public async Task Add_Current_Map_List_Adds_Maplist()
{
Name = "snippens dream",
Author = "0efeba8a-9cda-49fa-ab25-35f1d9218c95",
+ AuthorNickname = "snippen",
AuthorTime = 1337,
BronzeTime = 1337,
CopperPrice = 1337,
@@ -388,10 +391,32 @@ public async Task Add_Current_Map_List_Adds_Maplist()
UpdatedAt = new DateTime(),
LastVisit = new DateTime()
};
-
_server.Remote.Setup(r => r.GetMapListAsync(It.IsAny(), It.IsAny()))
.Returns(Task.FromResult(new[] { tmMapInfo }));
- _playerService.Setup(p => p.GetOrCreatePlayerAsync(It.IsAny()))
+ _server.Remote.Setup(r => r.MultiCallAsync(It.IsAny()))
+ .ReturnsAsync([
+ new GbxDynamicObject()
+ {
+ { "UId", tmMapInfo.UId },
+ { "Name", tmMapInfo.Name },
+ { "FileName", tmMapInfo.FileName },
+ { "Author", tmMapInfo.Author },
+ { "AuthorNickname", tmMapInfo.AuthorNickname },
+ { "Environnement", tmMapInfo.Environnement },
+ { "Mood", tmMapInfo.Mood },
+ { "BronzeTime", tmMapInfo.BronzeTime },
+ { "SilverTime", tmMapInfo.SilverTime },
+ { "GoldTime", tmMapInfo.GoldTime },
+ { "AuthorTime", tmMapInfo.AuthorTime },
+ { "CopperPrice", tmMapInfo.CopperPrice },
+ { "LapRace", tmMapInfo.LapRace },
+ { "NbLaps", tmMapInfo.NbLaps },
+ { "NbCheckpoints", tmMapInfo.NbCheckpoints },
+ { "MapType", tmMapInfo.MapType },
+ { "MapStyle", tmMapInfo.MapStyle }
+ }
+ ]);
+ _playerService.Setup(p => p.GetOrCreatePlayerAsync(It.IsAny(), "snippen"))
.Returns(Task.FromResult((IPlayer)player));
await _mapService.AddCurrentMapListAsync();
@@ -407,6 +432,7 @@ public async Task Get_Or_Add_Current_Map_Returns_Current_Map()
{
Name = "snippens track",
Author = "0efeba8a-9cda-49fa-ab25-35f1d9218c95",
+ AuthorNickname = "snippen",
AuthorTime = 1337,
BronzeTime = 1337,
CopperPrice = 1337,
@@ -452,7 +478,7 @@ public async Task Get_Or_Add_Current_Map_Returns_Current_Map()
.Returns(Task.FromResult((IMap?)null));
_mapRepository.Setup(m => m.AddMapAsync(It.IsAny(), It.IsAny(), It.IsAny()))
.Returns(Task.FromResult((IMap)map));
- _playerService.Setup(p => p.GetOrCreatePlayerAsync(It.IsAny()))
+ _playerService.Setup(p => p.GetOrCreatePlayerAsync(It.IsAny(), "snippen"))
.Returns(Task.FromResult((IPlayer)player));
var retrievedMap = await _mapService.GetOrAddCurrentMapAsync();