Add stubs for online mathcing and writing
This commit is contained in:
parent
aefc9ca326
commit
7093997658
@ -22,9 +22,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Game\Card\OnlineMatching" />
|
|
||||||
<Folder Include="Game\Card\Read" />
|
<Folder Include="Game\Card\Read" />
|
||||||
<Folder Include="Game\Card\Write" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace Application.Game.Card.OnlineMatching;
|
||||||
|
|
||||||
|
public class StartOnlineMatchingCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace Application.Game.Card.OnlineMatching;
|
||||||
|
|
||||||
|
public class UpdateOnlineMatchingCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace Application.Game.Card.OnlineMatching;
|
||||||
|
|
||||||
|
public class UploadOnlineMatchingResultCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteAvatarCommand.cs
Normal file
17
Application/Game/Card/Write/WriteAvatarCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteAvatarCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteAvatarCommandHandler : CardRequestHandlerBase<WriteAvatarCommand, string>
|
||||||
|
{
|
||||||
|
public WriteAvatarCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteAvatarCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteCoinCommand.cs
Normal file
17
Application/Game/Card/Write/WriteCoinCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteCoinCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteCoinCommandHandler : CardRequestHandlerBase<WriteCoinCommand, string>
|
||||||
|
{
|
||||||
|
public WriteCoinCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteCoinCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteItemCommand.cs
Normal file
17
Application/Game/Card/Write/WriteItemCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteItemCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteItemCommandHandler : CardRequestHandlerBase<WriteItemCommand, string>
|
||||||
|
{
|
||||||
|
public WriteItemCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteItemCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteMusicDetailCommand.cs
Normal file
17
Application/Game/Card/Write/WriteMusicDetailCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteMusicDetailCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteMusicDetailCommandHandler : CardRequestHandlerBase<WriteMusicDetailCommand, string>
|
||||||
|
{
|
||||||
|
public WriteMusicDetailCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteMusicDetailCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteNavigatorCommand.cs
Normal file
17
Application/Game/Card/Write/WriteNavigatorCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteNavigatorCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteNavigatorCommandHandler : CardRequestHandlerBase<WriteNavigatorCommand, string>
|
||||||
|
{
|
||||||
|
public WriteNavigatorCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteNavigatorCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteSkinCommand.cs
Normal file
17
Application/Game/Card/Write/WriteSkinCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteSkinCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteSkinCommandHandler : CardRequestHandlerBase<WriteSkinCommand, string>
|
||||||
|
{
|
||||||
|
public WriteSkinCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteSkinCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteSoundEffectCommand.cs
Normal file
17
Application/Game/Card/Write/WriteSoundEffectCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteSoundEffectCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteSoundEffectCommandHandler : CardRequestHandlerBase<WriteSoundEffectCommand, string>
|
||||||
|
{
|
||||||
|
public WriteSoundEffectCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteSoundEffectCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteTitleCommand.cs
Normal file
17
Application/Game/Card/Write/WriteTitleCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteTitleCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteTitleCommandHandler : CardRequestHandlerBase<WriteTitleCommand, string>
|
||||||
|
{
|
||||||
|
public WriteTitleCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteTitleCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
17
Application/Game/Card/Write/WriteUnlockKeynumCommand.cs
Normal file
17
Application/Game/Card/Write/WriteUnlockKeynumCommand.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Application.Common.Models;
|
||||||
|
using Application.Interfaces;
|
||||||
|
|
||||||
|
namespace Application.Game.Card.Write;
|
||||||
|
|
||||||
|
public record WriteUnlockKeynumCommand(long CardId, string Data) : IRequestWrapper<string>;
|
||||||
|
|
||||||
|
public class WriteUnlockKeynumCommandHandler : CardRequestHandlerBase<WriteUnlockKeynumCommand, string>
|
||||||
|
{
|
||||||
|
public WriteUnlockKeynumCommandHandler(ICardDependencyAggregate aggregate) : base(aggregate) {}
|
||||||
|
|
||||||
|
public override Task<ServiceResult<string>> Handle(WriteUnlockKeynumCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// TODO: Add proper implementation
|
||||||
|
return Task.FromResult(new ServiceResult<string>(request.Data));
|
||||||
|
}
|
||||||
|
}
|
@ -141,6 +141,14 @@ public static class Configs
|
|||||||
|
|
||||||
public const int SCORE_PCOL1 = 21;
|
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<string> DOMAINS = new()
|
public static readonly List<string> DOMAINS = new()
|
||||||
{
|
{
|
||||||
"localhost",
|
"localhost",
|
||||||
@ -164,6 +172,8 @@ public static class Configs
|
|||||||
public const string DEFAULT_RELAY_SERVER = "127.0.0.1";
|
public const string DEFAULT_RELAY_SERVER = "127.0.0.1";
|
||||||
public const int DEFAULT_RELAY_PORT = 54321;
|
public const int DEFAULT_RELAY_PORT = 54321;
|
||||||
public const string DEFAULT_EVENT_FOLDER = "event";
|
public const string DEFAULT_EVENT_FOLDER = "event";
|
||||||
|
public const string DEFAULT_MATCHING_SERVER = "127.0.0.1:5000";
|
||||||
|
|
||||||
|
|
||||||
public static readonly IReadOnlyList<int> DEFAULT_UNLOCKABLE_SONGS = new[]
|
public static readonly IReadOnlyList<int> DEFAULT_UNLOCKABLE_SONGS = new[]
|
||||||
{
|
{
|
||||||
|
61
GC-local-server-rewrite/common/Converters.cs
Normal file
61
GC-local-server-rewrite/common/Converters.cs
Normal file
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,9 @@ public interface IAppSettings
|
|||||||
[Option(DefaultValue = false)]
|
[Option(DefaultValue = false)]
|
||||||
bool DownloadEvents { get; }
|
bool DownloadEvents { get; }
|
||||||
|
|
||||||
|
[Option(DefaultValue = Configs.DEFAULT_MATCHING_SERVER)]
|
||||||
|
string MatchingServer { get; }
|
||||||
|
|
||||||
[Option(DefaultValue = null)]
|
[Option(DefaultValue = null)]
|
||||||
IEnumerable<int>? UnlockableSongIds { get; }
|
IEnumerable<int>? UnlockableSongIds { get; }
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
"EventFolder": "event",
|
"EventFolder": "event",
|
||||||
"DownloadEvents": false,
|
"DownloadEvents": false,
|
||||||
"RelayServer": "127.0.0.1",
|
"RelayServer": "127.0.0.1",
|
||||||
"RelayPort": 54321,
|
"RelayPort": 3333,
|
||||||
|
"MatchingServer": "127.0.0.1:5038",
|
||||||
"UnlockableSongIds": [
|
"UnlockableSongIds": [
|
||||||
11,
|
11,
|
||||||
13,
|
13,
|
||||||
@ -68,7 +69,7 @@
|
|||||||
"FileName": "/event_103_20201125.evt",
|
"FileName": "/event_103_20201125.evt",
|
||||||
"NotBeforeUnixTime": 1335677127,
|
"NotBeforeUnixTime": 1335677127,
|
||||||
"NotAfterUnixTime": 1966397127,
|
"NotAfterUnixTime": 1966397127,
|
||||||
"Md5": "9ef6c4d5ca381583a2d99b626ce06b5e",
|
"Md5": "27b503145a62e46f5f611b6f8a91e4f3",
|
||||||
"Index": 0
|
"Index": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Net.Http.Json;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@ -8,9 +8,13 @@ using EmbedIO.Routing;
|
|||||||
using EmbedIO.WebApi;
|
using EmbedIO.WebApi;
|
||||||
using GCLocalServerRewrite.common;
|
using GCLocalServerRewrite.common;
|
||||||
using GCLocalServerRewrite.models;
|
using GCLocalServerRewrite.models;
|
||||||
|
using SharedProject.models;
|
||||||
using SQLite.Net2;
|
using SQLite.Net2;
|
||||||
using Swan;
|
using Swan;
|
||||||
using Swan.Logging;
|
using Swan.Logging;
|
||||||
|
using Avatar=GCLocalServerRewrite.models.Avatar;
|
||||||
|
using Navigator=GCLocalServerRewrite.models.Navigator;
|
||||||
|
using Title=GCLocalServerRewrite.models.Title;
|
||||||
|
|
||||||
namespace GCLocalServerRewrite.controllers;
|
namespace GCLocalServerRewrite.controllers;
|
||||||
|
|
||||||
@ -19,13 +23,6 @@ public class CardServiceController : WebApiController
|
|||||||
private readonly SQLiteConnection cardSqLiteConnection;
|
private readonly SQLiteConnection cardSqLiteConnection;
|
||||||
private readonly SQLiteConnection musicSqLiteConnection;
|
private readonly SQLiteConnection musicSqLiteConnection;
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<long, List<OnlineMatchingEntry>> OnlineMatchingEntries = new()
|
|
||||||
{
|
|
||||||
[0xDEADBEEF] = new List<OnlineMatchingEntry>(),
|
|
||||||
[0xCAFEBABE] = new List<OnlineMatchingEntry>(),
|
|
||||||
[0xD0D0CACA] = new List<OnlineMatchingEntry>()
|
|
||||||
};
|
|
||||||
|
|
||||||
public CardServiceController()
|
public CardServiceController()
|
||||||
{
|
{
|
||||||
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName);
|
cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName);
|
||||||
@ -34,17 +31,17 @@ public class CardServiceController : WebApiController
|
|||||||
|
|
||||||
[Route(HttpVerbs.Post, "/cardn.cgi")]
|
[Route(HttpVerbs.Post, "/cardn.cgi")]
|
||||||
// ReSharper disable once UnusedMember.Global
|
// ReSharper disable once UnusedMember.Global
|
||||||
public string CardService([FormField] int gid, [FormField("mac_addr")] string mac, [FormField] int type,
|
public async Task<string> 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)
|
[FormField("card_no")] long cardId, [FormField("data")] string xmlData, [FormField("cmd_str")] int cmdType)
|
||||||
{
|
{
|
||||||
HttpContext.Response.ContentType = MediaTypeNames.Application.Octet;
|
HttpContext.Response.ContentType = MediaTypeNames.Application.Octet;
|
||||||
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
HttpContext.Response.ContentEncoding = new UTF8Encoding(false);
|
||||||
HttpContext.Response.KeepAlive = true;
|
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<string> ProcessCommand(int cmdType, string mac, long cardId, string xmlData, int type)
|
||||||
{
|
{
|
||||||
if (!Enum.IsDefined(typeof(Command), cmdType))
|
if (!Enum.IsDefined(typeof(Command), cmdType))
|
||||||
{
|
{
|
||||||
@ -55,7 +52,7 @@ public class CardServiceController : WebApiController
|
|||||||
|
|
||||||
return command switch
|
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.ReissueRequest => ProcessReissueRequest(),
|
||||||
Command.RegisterRequest => ProcessRegisterRequest(cardId, xmlData),
|
Command.RegisterRequest => ProcessRegisterRequest(cardId, xmlData),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(command), command, "Command unknown, should never happen!")
|
_ => throw new ArgumentOutOfRangeException(nameof(command), command, "Command unknown, should never happen!")
|
||||||
@ -75,7 +72,7 @@ public class CardServiceController : WebApiController
|
|||||||
return ConstructResponse("", ReturnCode.NotReissue);
|
return ConstructResponse("", ReturnCode.NotReissue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ProcessCardRequest(string mac, long cardId, string xmlData, int type)
|
private async Task<string> ProcessCardRequest(string mac, long cardId, string xmlData, int type)
|
||||||
{
|
{
|
||||||
if (!Enum.IsDefined(typeof(CardRequestType), type))
|
if (!Enum.IsDefined(typeof(CardRequestType), type))
|
||||||
{
|
{
|
||||||
@ -230,19 +227,22 @@ public class CardServiceController : WebApiController
|
|||||||
case CardRequestType.StartOnlineMatching:
|
case CardRequestType.StartOnlineMatching:
|
||||||
{
|
{
|
||||||
$"Start Online Matching, data is {xmlData}".Info();
|
$"Start Online Matching, data is {xmlData}".Info();
|
||||||
return ConstructResponse(StartOnlineMatching(cardId, xmlData));
|
var resultString = await StartOnlineMatching(cardId, xmlData);
|
||||||
|
return ConstructResponse(resultString);
|
||||||
}
|
}
|
||||||
|
|
||||||
case CardRequestType.UpdateOnlineMatching:
|
case CardRequestType.UpdateOnlineMatching:
|
||||||
{
|
{
|
||||||
$"Update Online Matching, data is {xmlData}".Info();
|
$"Update Online Matching, data is {xmlData}".Info();
|
||||||
return ConstructResponse(UpdateOnlineMatching(cardId, xmlData));
|
var resultString = await UpdateOnlineMatching(cardId, xmlData);
|
||||||
|
return ConstructResponse(resultString);
|
||||||
}
|
}
|
||||||
|
|
||||||
case CardRequestType.UploadOnlineMatchingResult:
|
case CardRequestType.UploadOnlineMatchingResult:
|
||||||
{
|
{
|
||||||
$"Get Online Matching result, data is {xmlData}".Info();
|
$"Get Online Matching result, data is {xmlData}".Info();
|
||||||
return ConstructResponse(UploadOnlineMatchingResult(cardId, xmlData));
|
var resultString = await UploadOnlineMatchingResult(cardId, xmlData);
|
||||||
|
return ConstructResponse(resultString);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -618,67 +618,98 @@ public class CardServiceController : WebApiController
|
|||||||
|
|
||||||
#region OnlineMatchingImplementation
|
#region OnlineMatchingImplementation
|
||||||
|
|
||||||
private static string StartOnlineMatching(long cardId, string xmlData)
|
private static async Task<string> StartOnlineMatching(long cardId, string xmlData)
|
||||||
{
|
{
|
||||||
var reader = new ChoXmlReader<OnlineMatchingEntry>(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
|
var reader = new ChoXmlReader<OnlineMatchingEntry>(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
|
||||||
var entry = reader.Read();
|
var entry = reader.Read();
|
||||||
|
|
||||||
entry.CardId = cardId;
|
var request = Converters.ConvertFromEntry(entry) ;
|
||||||
entry.MatchingId = 0xDEADBEEF;
|
request.CardId = cardId;
|
||||||
entry.EntryNo = OnlineMatchingEntries[0xDEADBEEF].Count;
|
request.EntryStart = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
entry.EntryStart = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
request.MatchingTimeout = 20;
|
||||||
entry.MatchingTimeout = 20;
|
request.MatchingRemainingTime = 3;
|
||||||
entry.MatchingRemainingTime = 3;
|
request.MatchingWaitTime = 10;
|
||||||
entry.MatchingWaitTime = 10;
|
request.Status = 1;
|
||||||
entry.Status = 1;
|
|
||||||
entry.Dump().Info();
|
var client = new HttpClient();
|
||||||
var entries = OnlineMatchingEntries[0xDEADBEEF];
|
var url = $"http://{Configs.SETTINGS.MatchingServer}/{Configs.MATCHING_URL_BASE}/{Configs.START_MATCHING_URL}";
|
||||||
var existing = entries.Find(matchingEntry => matchingEntry.CardId == cardId);
|
try
|
||||||
if (existing is not null)
|
|
||||||
{
|
{
|
||||||
"Card id already exist in entry! Previous match is not cleaned up! Clearing now".Warn();
|
var response = await client.PostAsJsonAsync(url, request);
|
||||||
entries.Clear();
|
var dataList = await response.Content.ReadFromJsonAsync<List<OnlineMatchingData>>();
|
||||||
|
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<string> UpdateOnlineMatching(long cardId, string xmlData)
|
||||||
{
|
{
|
||||||
var reader = new ChoXmlReader<OnlineMatchingUpdateData>(new StringReader(xmlData));
|
var reader = new ChoXmlReader<OnlineMatchingUpdateData>(new StringReader(xmlData));
|
||||||
var data = reader.Read();
|
var data = reader.Read();
|
||||||
var entries = OnlineMatchingEntries[0xDEADBEEF];
|
var request = new OnlineMatchingUpdateRequest
|
||||||
var entry = entries.Find(matchingEntry => matchingEntry.CardId == cardId);
|
|
||||||
if (entry is null)
|
|
||||||
{
|
{
|
||||||
throw new HttpException(400,"Entry for this card id does not exist!");
|
Action = data.Action,
|
||||||
}
|
CardId = cardId,
|
||||||
if (data.Action != 0)
|
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<List<OnlineMatchingEntry>>();
|
||||||
|
if (dataList is null)
|
||||||
|
{
|
||||||
|
throw new HttpRequestException("Update matching request fail");
|
||||||
|
}
|
||||||
|
return GenerateRecordsXml(dataList, Configs.ONLINE_MATCHING_XPATH);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
entry.MessageId = data.MessageId;
|
|
||||||
if (entry.MatchingRemainingTime <= 0)
|
|
||||||
{
|
{
|
||||||
entry.Status = 3;
|
e.Error("", "Http request failed");
|
||||||
entry.Dump().Info();
|
throw;
|
||||||
return GenerateRecordsXml(OnlineMatchingEntries[0xDEADBEEF], Configs.ONLINE_MATCHING_XPATH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<string> UploadOnlineMatchingResult(long cardId, string xmlData)
|
||||||
{
|
{
|
||||||
var reader = new ChoXmlReader<OnlineMatchingResultData>(new StringReader(xmlData));
|
var reader = new ChoXmlReader<OnlineMatchingResultData>(new StringReader(xmlData));
|
||||||
var data = reader.Read();
|
var data = reader.Read();
|
||||||
|
var request = new OnlineMatchingFinishRequest
|
||||||
var entries = OnlineMatchingEntries[0xDEADBEEF];
|
{
|
||||||
|
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<bool>();
|
||||||
|
|
||||||
|
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);
|
var entry = entries.Find(matchingEntry => matchingEntry.CardId == cardId);
|
||||||
if (entry is null)
|
if (entry is null)
|
||||||
{
|
{
|
||||||
@ -695,7 +726,7 @@ public class CardServiceController : WebApiController
|
|||||||
{
|
{
|
||||||
Status = 1
|
Status = 1
|
||||||
};
|
};
|
||||||
return GenerateSingleXml(result, Configs.ONLINE_BATTLE_RESULT_XPATH);
|
return GenerateSingleXml(result, Configs.ONLINE_BATTLE_RESULT_XPATH);*/
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
131
MatchServer/Controllers/MatchingController.cs
Normal file
131
MatchServer/Controllers/MatchingController.cs
Normal file
@ -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<MatchingController> logger;
|
||||||
|
|
||||||
|
|
||||||
|
public MatchingController(ILogger<MatchingController> logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("Start")]
|
||||||
|
public ActionResult<IEnumerable<OnlineMatchingData>> 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<OnlineMatchingData>
|
||||||
|
{
|
||||||
|
startData
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(matchingDb.MatchingDictionary[startData.MatchingId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("Update")]
|
||||||
|
public ActionResult<IEnumerable<OnlineMatchingUpdateRequest>> 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<bool> 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<Dictionary<long, List<OnlineMatchingUpdateRequest>>> InspectOnlineMatching()
|
||||||
|
{
|
||||||
|
var matchingDb = MatchingDb.GetInstance;
|
||||||
|
|
||||||
|
return Ok(matchingDb.MatchingDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("Clear")]
|
||||||
|
public ActionResult<bool> Clear()
|
||||||
|
{
|
||||||
|
var matchingDb = MatchingDb.GetInstance;
|
||||||
|
lock (matchingDb.DbLock)
|
||||||
|
{
|
||||||
|
matchingDb.MatchingDictionary.Clear();
|
||||||
|
}
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
17
MatchServer/MatchServer.csproj
Normal file
17
MatchServer/MatchServer.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SharedProject\SharedProject.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
21
MatchServer/Program.cs
Normal file
21
MatchServer/Program.cs
Normal file
@ -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();
|
31
MatchServer/Properties/launchSettings.json
Normal file
31
MatchServer/Properties/launchSettings.json
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
MatchServer/Storage/MatchingDb.cs
Normal file
22
MatchServer/Storage/MatchingDb.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using SharedProject.models;
|
||||||
|
|
||||||
|
namespace MatchServer.Storage;
|
||||||
|
|
||||||
|
public class MatchingDb
|
||||||
|
{
|
||||||
|
public Dictionary<long, List<OnlineMatchingData>> MatchingDictionary;
|
||||||
|
|
||||||
|
public object DbLock = new();
|
||||||
|
|
||||||
|
static MatchingDb()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private MatchingDb()
|
||||||
|
{
|
||||||
|
MatchingDictionary = new Dictionary<long, List<OnlineMatchingData>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MatchingDb GetInstance { get; } = new MatchingDb();
|
||||||
|
|
||||||
|
}
|
8
MatchServer/appsettings.Development.json
Normal file
8
MatchServer/appsettings.Development.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
MatchServer/appsettings.json
Normal file
9
MatchServer/appsettings.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
44
SharedProject/models/OnlineMatchingData.cs
Normal file
44
SharedProject/models/OnlineMatchingData.cs
Normal file
@ -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;
|
||||||
|
}
|
8
SharedProject/models/OnlineMatchingFinishRequest.cs
Normal file
8
SharedProject/models/OnlineMatchingFinishRequest.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace SharedProject.models;
|
||||||
|
|
||||||
|
public class OnlineMatchingFinishRequest
|
||||||
|
{
|
||||||
|
public long CardId { get; set; }
|
||||||
|
|
||||||
|
public long MatchingId { get; set; }
|
||||||
|
}
|
14
SharedProject/models/OnlineMatchingUpdateRequest.cs
Normal file
14
SharedProject/models/OnlineMatchingUpdateRequest.cs
Normal file
@ -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; }
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user