diff --git a/Application/Application.csproj b/Application/Application.csproj
index 4fb7069..81ec46e 100644
--- a/Application/Application.csproj
+++ b/Application/Application.csproj
@@ -22,9 +22,7 @@
-
-
diff --git a/Application/Game/Card/OnlineMatching/StartOnlineMatchingCommand.cs b/Application/Game/Card/OnlineMatching/StartOnlineMatchingCommand.cs
new file mode 100644
index 0000000..15a91b2
--- /dev/null
+++ b/Application/Game/Card/OnlineMatching/StartOnlineMatchingCommand.cs
@@ -0,0 +1,6 @@
+namespace Application.Game.Card.OnlineMatching;
+
+public class StartOnlineMatchingCommand
+{
+
+}
\ No newline at end of file
diff --git a/Application/Game/Card/OnlineMatching/UpdateOnlineMatchingCommand.cs b/Application/Game/Card/OnlineMatching/UpdateOnlineMatchingCommand.cs
new file mode 100644
index 0000000..0893cab
--- /dev/null
+++ b/Application/Game/Card/OnlineMatching/UpdateOnlineMatchingCommand.cs
@@ -0,0 +1,6 @@
+namespace Application.Game.Card.OnlineMatching;
+
+public class UpdateOnlineMatchingCommand
+{
+
+}
\ No newline at end of file
diff --git a/Application/Game/Card/OnlineMatching/UploadOnlineMatchingResultCommand.cs b/Application/Game/Card/OnlineMatching/UploadOnlineMatchingResultCommand.cs
new file mode 100644
index 0000000..00075ee
--- /dev/null
+++ b/Application/Game/Card/OnlineMatching/UploadOnlineMatchingResultCommand.cs
@@ -0,0 +1,6 @@
+namespace Application.Game.Card.OnlineMatching;
+
+public class UploadOnlineMatchingResultCommand
+{
+
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteAvatarCommand.cs b/Application/Game/Card/Write/WriteAvatarCommand.cs
new file mode 100644
index 0000000..fa07503
--- /dev/null
+++ b/Application/Game/Card/Write/WriteAvatarCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteAvatarCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteAvatarCommandHandler : CardRequestHandlerBase
+{
+ public WriteAvatarCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteAvatarCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteCoinCommand.cs b/Application/Game/Card/Write/WriteCoinCommand.cs
new file mode 100644
index 0000000..c3b17ac
--- /dev/null
+++ b/Application/Game/Card/Write/WriteCoinCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteCoinCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteCoinCommandHandler : CardRequestHandlerBase
+{
+ public WriteCoinCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteCoinCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteItemCommand.cs b/Application/Game/Card/Write/WriteItemCommand.cs
new file mode 100644
index 0000000..ee58212
--- /dev/null
+++ b/Application/Game/Card/Write/WriteItemCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteItemCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteItemCommandHandler : CardRequestHandlerBase
+{
+ public WriteItemCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteItemCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteMusicDetailCommand.cs b/Application/Game/Card/Write/WriteMusicDetailCommand.cs
new file mode 100644
index 0000000..346e070
--- /dev/null
+++ b/Application/Game/Card/Write/WriteMusicDetailCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteMusicDetailCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteMusicDetailCommandHandler : CardRequestHandlerBase
+{
+ public WriteMusicDetailCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteMusicDetailCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteNavigatorCommand.cs b/Application/Game/Card/Write/WriteNavigatorCommand.cs
new file mode 100644
index 0000000..0629348
--- /dev/null
+++ b/Application/Game/Card/Write/WriteNavigatorCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteNavigatorCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteNavigatorCommandHandler : CardRequestHandlerBase
+{
+ public WriteNavigatorCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteNavigatorCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteSkinCommand.cs b/Application/Game/Card/Write/WriteSkinCommand.cs
new file mode 100644
index 0000000..ecc1102
--- /dev/null
+++ b/Application/Game/Card/Write/WriteSkinCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteSkinCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteSkinCommandHandler : CardRequestHandlerBase
+{
+ public WriteSkinCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteSkinCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteSoundEffectCommand.cs b/Application/Game/Card/Write/WriteSoundEffectCommand.cs
new file mode 100644
index 0000000..955b8b9
--- /dev/null
+++ b/Application/Game/Card/Write/WriteSoundEffectCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteSoundEffectCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteSoundEffectCommandHandler : CardRequestHandlerBase
+{
+ public WriteSoundEffectCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteSoundEffectCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteTitleCommand.cs b/Application/Game/Card/Write/WriteTitleCommand.cs
new file mode 100644
index 0000000..2b0ccca
--- /dev/null
+++ b/Application/Game/Card/Write/WriteTitleCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteTitleCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteTitleCommandHandler : CardRequestHandlerBase
+{
+ public WriteTitleCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteTitleCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/Application/Game/Card/Write/WriteUnlockKeynumCommand.cs b/Application/Game/Card/Write/WriteUnlockKeynumCommand.cs
new file mode 100644
index 0000000..040399a
--- /dev/null
+++ b/Application/Game/Card/Write/WriteUnlockKeynumCommand.cs
@@ -0,0 +1,17 @@
+using Application.Common.Models;
+using Application.Interfaces;
+
+namespace Application.Game.Card.Write;
+
+public record WriteUnlockKeynumCommand(long CardId, string Data) : IRequestWrapper;
+
+public class WriteUnlockKeynumCommandHandler : CardRequestHandlerBase
+{
+ public WriteUnlockKeynumCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
+
+ public override Task> Handle(WriteUnlockKeynumCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Add proper implementation
+ return Task.FromResult(new ServiceResult(request.Data));
+ }
+}
\ No newline at end of file
diff --git a/GC-local-server-rewrite/common/Configs.cs b/GC-local-server-rewrite/common/Configs.cs
index dc7a7eb..b8bd31e 100644
--- a/GC-local-server-rewrite/common/Configs.cs
+++ b/GC-local-server-rewrite/common/Configs.cs
@@ -141,6 +141,14 @@ public static class Configs
public const int SCORE_PCOL1 = 21;
+ public const string MATCHING_URL_BASE = "Matching";
+
+ public const string START_MATCHING_URL = "Start";
+ public const string UPDATE_MATCHING_URL = "Update";
+ public const string FINISH_MATCHING_URL = "Finish";
+
+
+
public static readonly List DOMAINS = new()
{
"localhost",
@@ -164,6 +172,8 @@ public static class Configs
public const string DEFAULT_RELAY_SERVER = "127.0.0.1";
public const int DEFAULT_RELAY_PORT = 54321;
public const string DEFAULT_EVENT_FOLDER = "event";
+ public const string DEFAULT_MATCHING_SERVER = "127.0.0.1:5000";
+
public static readonly IReadOnlyList DEFAULT_UNLOCKABLE_SONGS = new[]
{
diff --git a/GC-local-server-rewrite/common/Converters.cs b/GC-local-server-rewrite/common/Converters.cs
new file mode 100644
index 0000000..e1d9bbf
--- /dev/null
+++ b/GC-local-server-rewrite/common/Converters.cs
@@ -0,0 +1,61 @@
+using GCLocalServerRewrite.models;
+using SharedProject.models;
+
+namespace GCLocalServerRewrite.common;
+
+public static class Converters
+{
+ public static OnlineMatchingData ConvertFromEntry(OnlineMatchingEntry entry)
+ {
+ return new OnlineMatchingData
+ {
+ AvatarId = entry.AvatarId,
+ CardId = entry.CardId,
+ ClassId = entry.ClassId,
+ EntryNo = entry.EntryNo,
+ EntryStart = entry.EntryStart,
+ EventId = entry.EventId,
+ GroupId = entry.GroupId,
+ MachineId = entry.MachineId,
+ MatchingId = entry.MatchingId,
+ MatchingRemainingTime = entry.MatchingRemainingTime,
+ Pref = entry.Pref,
+ Status = entry.Status,
+ MatchingTimeout = entry.MatchingTimeout,
+ MessageId = entry.MessageId,
+ PlayerName = entry.PlayerName,
+ PrefId = entry.PrefId,
+ TenpoId = entry.TenpoId,
+ TenpoName = entry.TenpoName,
+ TitleId = entry.TitleId,
+ MatchingWaitTime = entry.MatchingWaitTime
+ };
+ }
+
+ public static OnlineMatchingEntry ConvertFromData(OnlineMatchingData entry)
+ {
+ return new OnlineMatchingEntry
+ {
+ AvatarId = entry.AvatarId,
+ CardId = entry.CardId,
+ ClassId = entry.ClassId,
+ EntryNo = entry.EntryNo,
+ EntryStart = entry.EntryStart,
+ EventId = entry.EventId,
+ GroupId = entry.GroupId,
+ MachineId = entry.MachineId,
+ MatchingId = entry.MatchingId,
+ MatchingRemainingTime = entry.MatchingRemainingTime,
+ Pref = entry.Pref,
+ Status = entry.Status,
+ MatchingTimeout = entry.MatchingTimeout,
+ MessageId = entry.MessageId,
+ PlayerName = entry.PlayerName,
+ PrefId = entry.PrefId,
+ TenpoId = entry.TenpoId,
+ TenpoName = entry.TenpoName,
+ TitleId = entry.TitleId,
+ MatchingWaitTime = entry.MatchingWaitTime
+ };
+ }
+}
\ No newline at end of file
diff --git a/GC-local-server-rewrite/common/IAppSettings.cs b/GC-local-server-rewrite/common/IAppSettings.cs
index 31b77a9..250297a 100644
--- a/GC-local-server-rewrite/common/IAppSettings.cs
+++ b/GC-local-server-rewrite/common/IAppSettings.cs
@@ -43,6 +43,9 @@ public interface IAppSettings
[Option(DefaultValue = false)]
bool DownloadEvents { get; }
+ [Option(DefaultValue = Configs.DEFAULT_MATCHING_SERVER)]
+ string MatchingServer { get; }
+
[Option(DefaultValue = null)]
IEnumerable? UnlockableSongIds { get; }
diff --git a/GC-local-server-rewrite/config.json b/GC-local-server-rewrite/config.json
index 14a1bed..0bf89e7 100644
--- a/GC-local-server-rewrite/config.json
+++ b/GC-local-server-rewrite/config.json
@@ -11,7 +11,8 @@
"EventFolder": "event",
"DownloadEvents": false,
"RelayServer": "127.0.0.1",
- "RelayPort": 54321,
+ "RelayPort": 3333,
+ "MatchingServer": "127.0.0.1:5038",
"UnlockableSongIds": [
11,
13,
@@ -68,7 +69,7 @@
"FileName": "/event_103_20201125.evt",
"NotBeforeUnixTime": 1335677127,
"NotAfterUnixTime": 1966397127,
- "Md5": "9ef6c4d5ca381583a2d99b626ce06b5e",
+ "Md5": "27b503145a62e46f5f611b6f8a91e4f3",
"Index": 0
},
{
diff --git a/GC-local-server-rewrite/controllers/CardServiceController.cs b/GC-local-server-rewrite/controllers/CardServiceController.cs
index b279469..f36d411 100644
--- a/GC-local-server-rewrite/controllers/CardServiceController.cs
+++ b/GC-local-server-rewrite/controllers/CardServiceController.cs
@@ -1,4 +1,4 @@
-using System.Collections.Concurrent;
+using System.Net.Http.Json;
using System.Net.Mime;
using System.Text;
using System.Xml.Linq;
@@ -8,9 +8,13 @@ using EmbedIO.Routing;
using EmbedIO.WebApi;
using GCLocalServerRewrite.common;
using GCLocalServerRewrite.models;
+using SharedProject.models;
using SQLite.Net2;
using Swan;
using Swan.Logging;
+using Avatar=GCLocalServerRewrite.models.Avatar;
+using Navigator=GCLocalServerRewrite.models.Navigator;
+using Title=GCLocalServerRewrite.models.Title;
namespace GCLocalServerRewrite.controllers;
@@ -19,13 +23,6 @@ public class CardServiceController : WebApiController
private readonly SQLiteConnection cardSqLiteConnection;
private readonly SQLiteConnection musicSqLiteConnection;
- private static readonly ConcurrentDictionary> OnlineMatchingEntries = new()
- {
- [0xDEADBEEF] = new List(),
- [0xCAFEBABE] = new List(),
- [0xD0D0CACA] = new List()
- };
-
public CardServiceController()
{
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName);
@@ -34,17 +31,17 @@ public class CardServiceController : WebApiController
[Route(HttpVerbs.Post, "/cardn.cgi")]
// ReSharper disable once UnusedMember.Global
- public string CardService([FormField] int gid, [FormField("mac_addr")] string mac, [FormField] int type,
+ public async Task CardService([FormField] int gid, [FormField("mac_addr")] string mac, [FormField] int type,
[FormField("card_no")] long cardId, [FormField("data")] string xmlData, [FormField("cmd_str")] int cmdType)
{
HttpContext.Response.ContentType = MediaTypeNames.Application.Octet;
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
HttpContext.Response.KeepAlive = true;
- return ProcessCommand(cmdType, mac, cardId, xmlData, type);
+ return await ProcessCommand(cmdType, mac, cardId, xmlData, type);
}
- private string ProcessCommand(int cmdType, string mac, long cardId, string xmlData, int type)
+ private async Task ProcessCommand(int cmdType, string mac, long cardId, string xmlData, int type)
{
if (!Enum.IsDefined(typeof(Command), cmdType))
{
@@ -55,7 +52,7 @@ public class CardServiceController : WebApiController
return command switch
{
- Command.CardReadRequest or Command.CardWriteRequest => ProcessCardRequest(mac, cardId, xmlData, type),
+ Command.CardReadRequest or Command.CardWriteRequest => await ProcessCardRequest(mac, cardId, xmlData, type),
Command.ReissueRequest => ProcessReissueRequest(),
Command.RegisterRequest => ProcessRegisterRequest(cardId, xmlData),
_ => throw new ArgumentOutOfRangeException(nameof(command), command, "Command unknown, should never happen!")
@@ -75,7 +72,7 @@ public class CardServiceController : WebApiController
return ConstructResponse("", ReturnCode.NotReissue);
}
- private string ProcessCardRequest(string mac, long cardId, string xmlData, int type)
+ private async Task ProcessCardRequest(string mac, long cardId, string xmlData, int type)
{
if (!Enum.IsDefined(typeof(CardRequestType), type))
{
@@ -230,19 +227,22 @@ public class CardServiceController : WebApiController
case CardRequestType.StartOnlineMatching:
{
$"Start Online Matching, data is {xmlData}".Info();
- return ConstructResponse(StartOnlineMatching(cardId, xmlData));
+ var resultString = await StartOnlineMatching(cardId, xmlData);
+ return ConstructResponse(resultString);
}
case CardRequestType.UpdateOnlineMatching:
{
$"Update Online Matching, data is {xmlData}".Info();
- return ConstructResponse(UpdateOnlineMatching(cardId, xmlData));
+ var resultString = await UpdateOnlineMatching(cardId, xmlData);
+ return ConstructResponse(resultString);
}
case CardRequestType.UploadOnlineMatchingResult:
{
$"Get Online Matching result, data is {xmlData}".Info();
- return ConstructResponse(UploadOnlineMatchingResult(cardId, xmlData));
+ var resultString = await UploadOnlineMatchingResult(cardId, xmlData);
+ return ConstructResponse(resultString);
}
#endregion
@@ -618,67 +618,98 @@ public class CardServiceController : WebApiController
#region OnlineMatchingImplementation
- private static string StartOnlineMatching(long cardId, string xmlData)
+ private static async Task StartOnlineMatching(long cardId, string xmlData)
{
var reader = new ChoXmlReader(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
var entry = reader.Read();
- entry.CardId = cardId;
- entry.MatchingId = 0xDEADBEEF;
- entry.EntryNo = OnlineMatchingEntries[0xDEADBEEF].Count;
- entry.EntryStart = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- entry.MatchingTimeout = 20;
- entry.MatchingRemainingTime = 3;
- entry.MatchingWaitTime = 10;
- entry.Status = 1;
- entry.Dump().Info();
- var entries = OnlineMatchingEntries[0xDEADBEEF];
- var existing = entries.Find(matchingEntry => matchingEntry.CardId == cardId);
- if (existing is not null)
+ var request = Converters.ConvertFromEntry(entry) ;
+ request.CardId = cardId;
+ request.EntryStart = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+ request.MatchingTimeout = 20;
+ request.MatchingRemainingTime = 3;
+ request.MatchingWaitTime = 10;
+ request.Status = 1;
+
+ var client = new HttpClient();
+ var url = $"http://{Configs.SETTINGS.MatchingServer}/{Configs.MATCHING_URL_BASE}/{Configs.START_MATCHING_URL}";
+ try
{
- "Card id already exist in entry! Previous match is not cleaned up! Clearing now".Warn();
- entries.Clear();
+ var response = await client.PostAsJsonAsync(url, request);
+ var dataList = await response.Content.ReadFromJsonAsync>();
+ if (dataList is null)
+ {
+ throw new HttpRequestException("Start matching request fail");
+ }
+ var result = dataList.ConvertAll(input => Converters.ConvertFromData(input));
+ return GenerateRecordsXml(result, Configs.ONLINE_MATCHING_XPATH);
+ }
+ catch (Exception e)
+ {
+ e.Error("", "Http request failed");
+ throw;
}
- OnlineMatchingEntries[0xDEADBEEF].Add(entry);
-
- return GenerateRecordsXml(OnlineMatchingEntries[0xDEADBEEF], Configs.ONLINE_MATCHING_XPATH);
}
- private static string UpdateOnlineMatching(long cardId, string xmlData)
+ private static async Task UpdateOnlineMatching(long cardId, string xmlData)
{
var reader = new ChoXmlReader(new StringReader(xmlData));
var data = reader.Read();
- var entries = OnlineMatchingEntries[0xDEADBEEF];
- var entry = entries.Find(matchingEntry => matchingEntry.CardId == cardId);
- if (entry is null)
+ var request = new OnlineMatchingUpdateRequest
{
- throw new HttpException(400,"Entry for this card id does not exist!");
- }
- if (data.Action != 0)
+ Action = data.Action,
+ CardId = cardId,
+ EventId = data.EventId,
+ MatchingId = data.MatchingId,
+ MessageId = data.MessageId
+ };
+ var client = new HttpClient();
+ var url = $"http://{Configs.SETTINGS.MatchingServer}/{Configs.MATCHING_URL_BASE}/{Configs.UPDATE_MATCHING_URL}";
+ try
{
- $"Action is {data.Action}".Info();
+ var response = await client.PostAsJsonAsync(url, request);
+ var dataList = await response.Content.ReadFromJsonAsync>();
+ if (dataList is null)
+ {
+ throw new HttpRequestException("Update matching request fail");
+ }
+ return GenerateRecordsXml(dataList, Configs.ONLINE_MATCHING_XPATH);
}
-
- entry.MessageId = data.MessageId;
- if (entry.MatchingRemainingTime <= 0)
+ catch (Exception e)
{
- entry.Status = 3;
- entry.Dump().Info();
- return GenerateRecordsXml(OnlineMatchingEntries[0xDEADBEEF], Configs.ONLINE_MATCHING_XPATH);
+ e.Error("", "Http request failed");
+ throw;
}
-
- entry.MatchingRemainingTime--;
- entry.Dump().Info();
-
- return GenerateRecordsXml(OnlineMatchingEntries[0xDEADBEEF], Configs.ONLINE_MATCHING_XPATH);
}
- private static string UploadOnlineMatchingResult(long cardId, string xmlData)
+ private static async Task UploadOnlineMatchingResult(long cardId, string xmlData)
{
var reader = new ChoXmlReader(new StringReader(xmlData));
var data = reader.Read();
-
- var entries = OnlineMatchingEntries[0xDEADBEEF];
+ var request = new OnlineMatchingFinishRequest
+ {
+ CardId = cardId,
+ MatchingId = data.MatchingId
+ };
+ var client = new HttpClient();
+ var url = $"http://{Configs.SETTINGS.MatchingServer}/{Configs.MATCHING_URL_BASE}/{Configs.UPDATE_MATCHING_URL}";
+ try
+ {
+ var response = await client.PostAsJsonAsync(url, request);
+ var success = await response.Content.ReadFromJsonAsync();
+
+ var result = new OnlineMatchingResult
+ {
+ Status = success ? 1:0
+ };
+ return GenerateSingleXml(result, Configs.ONLINE_BATTLE_RESULT_XPATH);
+ }
+ catch (Exception e)
+ {
+ e.Error("", "Http request failed");
+ throw;
+ }
+ /*var entries = OnlineMatchingEntries[0xDEADBEEF];
var entry = entries.Find(matchingEntry => matchingEntry.CardId == cardId);
if (entry is null)
{
@@ -695,7 +726,7 @@ public class CardServiceController : WebApiController
{
Status = 1
};
- return GenerateSingleXml(result, Configs.ONLINE_BATTLE_RESULT_XPATH);
+ return GenerateSingleXml(result, Configs.ONLINE_BATTLE_RESULT_XPATH);*/
}
#endregion
diff --git a/MatchServer/Controllers/MatchingController.cs b/MatchServer/Controllers/MatchingController.cs
new file mode 100644
index 0000000..2acb165
--- /dev/null
+++ b/MatchServer/Controllers/MatchingController.cs
@@ -0,0 +1,131 @@
+using MatchServer.Storage;
+using Microsoft.AspNetCore.Mvc;
+using SharedProject.models;
+
+namespace MatchServer.Controllers;
+
+[ApiController]
+[Route("[controller]")]
+public class MatchingController : ControllerBase
+{
+ private readonly ILogger logger;
+
+
+ public MatchingController(ILogger logger) {
+ this.logger = logger;
+ }
+
+ [HttpPost("Start")]
+ public ActionResult> StartOnlineMatching(OnlineMatchingData startData)
+ {
+ logger.LogInformation("Start matching, card id {CardId}, player name {PlayerName}", startData.CardId, startData.PlayerName);
+ var matchingDb = MatchingDb.GetInstance;
+
+ lock (matchingDb.DbLock)
+ {
+ foreach (var (matchingId, entries) in matchingDb.MatchingDictionary)
+ {
+ if (entries.Count >= 4)
+ {
+ continue;
+ }
+
+ if (entries.Any(data => data.CardId == startData.CardId))
+ {
+ logger.LogWarning("Card id {CardId} already exists in matching id {MatchingId}", startData.CardId, matchingId);
+ continue;
+ }
+
+ entries.Add(startData);
+ startData.MatchingId = matchingId;
+ startData.EntryNo = entries.Count - 1;
+ break;
+ }
+
+ if (startData.MatchingId != 0)
+ {
+ return Ok(matchingDb.MatchingDictionary[startData.MatchingId]);
+ }
+
+ startData.MatchingId = matchingDb.MatchingDictionary.Count + 1;
+ startData.EntryNo = 0;
+ matchingDb.MatchingDictionary[startData.MatchingId] = new List
+ {
+ startData
+ };
+
+ return Ok(matchingDb.MatchingDictionary[startData.MatchingId]);
+ }
+ }
+
+ [HttpPost("Update")]
+ public ActionResult> UpdateOnlineMatching(OnlineMatchingUpdateRequest updateData)
+ {
+ var matchingDb = MatchingDb.GetInstance;
+ var matchingId = updateData.MatchingId;
+
+ logger.LogInformation("Update matching, card id is {CardId}, matching id is {MatchingId}", updateData.CardId, updateData.MatchingId);
+
+ if (!matchingDb.MatchingDictionary.ContainsKey(matchingId))
+ {
+ return BadRequest();
+ }
+
+ var dataList = matchingDb.MatchingDictionary[matchingId];
+
+ var data = dataList.Find(data => data.CardId == updateData.CardId);
+ if (data is null)
+ {
+ return BadRequest();
+ }
+
+ data.MessageId = updateData.MessageId;
+ if (data.MatchingRemainingTime <= 0)
+ {
+ data.Status = 3;
+ return Ok(dataList);
+ }
+
+ data.MatchingRemainingTime--;
+ return Ok(dataList);
+ }
+
+ [HttpPost("Finish")]
+ public ActionResult FinishOnlineMatching(OnlineMatchingFinishRequest request)
+ {
+ var matchingDb = MatchingDb.GetInstance;
+ var matchingId = request.MatchingId;
+
+ lock (matchingDb.DbLock)
+ {
+ if (!matchingDb.MatchingDictionary.ContainsKey(matchingId))
+ {
+ return BadRequest();
+ }
+ var dataList = matchingDb.MatchingDictionary[matchingId];
+
+ var index = dataList.FindIndex(data => data.CardId == request.CardId);
+ dataList.RemoveAt(index);
+ }
+ return Ok(true);
+ }
+
+ [HttpGet("Debug")]
+ public ActionResult>> InspectOnlineMatching()
+ {
+ var matchingDb = MatchingDb.GetInstance;
+
+ return Ok(matchingDb.MatchingDictionary);
+ }
+
+ [HttpGet("Clear")]
+ public ActionResult Clear()
+ {
+ var matchingDb = MatchingDb.GetInstance;
+ lock (matchingDb.DbLock)
+ {
+ matchingDb.MatchingDictionary.Clear();
+ }
+ return Ok(true);
+ }
+}
\ No newline at end of file
diff --git a/MatchServer/MatchServer.csproj b/MatchServer/MatchServer.csproj
new file mode 100644
index 0000000..a40166b
--- /dev/null
+++ b/MatchServer/MatchServer.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MatchServer/Program.cs b/MatchServer/Program.cs
new file mode 100644
index 0000000..6d3cc9c
--- /dev/null
+++ b/MatchServer/Program.cs
@@ -0,0 +1,21 @@
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+
+builder.Services.AddControllers();
+// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.MapControllers();
+
+app.Run();
\ No newline at end of file
diff --git a/MatchServer/Properties/launchSettings.json b/MatchServer/Properties/launchSettings.json
new file mode 100644
index 0000000..22561dc
--- /dev/null
+++ b/MatchServer/Properties/launchSettings.json
@@ -0,0 +1,31 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:45319",
+ "sslPort": 44313
+ }
+ },
+ "profiles": {
+ "MatchServer": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "https://localhost:7023;http://localhost:5038",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/MatchServer/Storage/MatchingDb.cs b/MatchServer/Storage/MatchingDb.cs
new file mode 100644
index 0000000..16656d2
--- /dev/null
+++ b/MatchServer/Storage/MatchingDb.cs
@@ -0,0 +1,22 @@
+using SharedProject.models;
+
+namespace MatchServer.Storage;
+
+public class MatchingDb
+{
+ public Dictionary> MatchingDictionary;
+
+ public object DbLock = new();
+
+ static MatchingDb()
+ {
+ }
+
+ private MatchingDb()
+ {
+ MatchingDictionary = new Dictionary>();
+ }
+
+ public static MatchingDb GetInstance { get; } = new MatchingDb();
+
+}
\ No newline at end of file
diff --git a/MatchServer/appsettings.Development.json b/MatchServer/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/MatchServer/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/MatchServer/appsettings.json b/MatchServer/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/MatchServer/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/SharedProject/models/OnlineMatchingData.cs b/SharedProject/models/OnlineMatchingData.cs
new file mode 100644
index 0000000..4bbd544
--- /dev/null
+++ b/SharedProject/models/OnlineMatchingData.cs
@@ -0,0 +1,44 @@
+namespace SharedProject.models;
+
+public class OnlineMatchingData
+{
+ public long MachineId { get; set; }
+
+ public long EventId { get; set; }
+
+ public long MatchingId { get; set; }
+
+ public long EntryNo { get; set; }
+
+ public string EntryStart { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+
+ public long Status { get; set; } = 1;
+
+ public long CardId { get; set; }
+
+ public string PlayerName { get; set; } = string.Empty;
+
+ public long AvatarId { get; set; }
+
+ public long TitleId { get; set; }
+
+ public long ClassId { get; set; }
+
+ public long GroupId { get; set; }
+
+ public long TenpoId { get; set; }
+
+ public string TenpoName { get; set; } = "1337";
+
+ public long PrefId { get; set; }
+
+ public string Pref { get; set; } = "nesys";
+
+ public long MessageId { get; set; }
+
+ public long MatchingTimeout { get; set; } = 99;
+
+ public long MatchingWaitTime { get; set; } = 10;
+
+ public long MatchingRemainingTime { get; set; } = 3;
+}
\ No newline at end of file
diff --git a/SharedProject/models/OnlineMatchingFinishRequest.cs b/SharedProject/models/OnlineMatchingFinishRequest.cs
new file mode 100644
index 0000000..7213a9a
--- /dev/null
+++ b/SharedProject/models/OnlineMatchingFinishRequest.cs
@@ -0,0 +1,8 @@
+namespace SharedProject.models;
+
+public class OnlineMatchingFinishRequest
+{
+ public long CardId { get; set; }
+
+ public long MatchingId { get; set; }
+}
\ No newline at end of file
diff --git a/SharedProject/models/OnlineMatchingUpdateRequest.cs b/SharedProject/models/OnlineMatchingUpdateRequest.cs
new file mode 100644
index 0000000..3a23d64
--- /dev/null
+++ b/SharedProject/models/OnlineMatchingUpdateRequest.cs
@@ -0,0 +1,14 @@
+namespace SharedProject.models;
+
+public class OnlineMatchingUpdateRequest
+{
+ public long Action { get; set; }
+
+ public long EventId { get; set; }
+
+ public long CardId { get; set; }
+
+ public long MatchingId { get; set; }
+
+ public long MessageId { get; set; }
+}
\ No newline at end of file