From f8fa34edbcd00cc2fccf9f6bf9c42984cdf30ff6 Mon Sep 17 00:00:00 2001 From: qornwh1 Date: Tue, 17 Mar 2026 09:15:41 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat=20:=20=EB=B3=B4=EC=8A=A4=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MMOTestServer/MMOserver/Api/BossRaidResult.cs | 41 ++++++++++++++++--- MMOTestServer/MMOserver/Api/RestApi.cs | 6 +-- MMOTestServer/MMOserver/Game/GameServer.cs | 14 +++++-- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/MMOTestServer/MMOserver/Api/BossRaidResult.cs b/MMOTestServer/MMOserver/Api/BossRaidResult.cs index 4a9c629..fb03ea4 100644 --- a/MMOTestServer/MMOserver/Api/BossRaidResult.cs +++ b/MMOTestServer/MMOserver/Api/BossRaidResult.cs @@ -4,10 +4,39 @@ namespace MMOserver.Api; // API 응답(BossRaidAccessResponse)을 직접 노출하지 않고 이걸로 매핑해서 반환 public sealed class BossRaidResult { - public int RoomId { get; init; } - public string SessionName { get; init; } = string.Empty; - public int BossId { get; init; } - public List Players { get; init; } = new(); - public string Status { get; init; } = string.Empty; - public string? Tokens { get; init; } + public int RoomId + { + get; + init; + } + + public string SessionName + { + get; + init; + } = string.Empty; + + public int BossId + { + get; + init; + } + + public List Players + { + get; + init; + } = new(); + + public string Status + { + get; + init; + } = string.Empty; + + public Dictionary Tokens + { + get; + init; + } = new(); } diff --git a/MMOTestServer/MMOserver/Api/RestApi.cs b/MMOTestServer/MMOserver/Api/RestApi.cs index 7c418ec..c3cefbe 100644 --- a/MMOTestServer/MMOserver/Api/RestApi.cs +++ b/MMOTestServer/MMOserver/Api/RestApi.cs @@ -79,7 +79,7 @@ public class RestApi : Singleton { try { - HttpResponseMessage response = await httpClient.PostAsJsonAsync(url, new { usernames = userNames, bossId }); + HttpResponseMessage response = await httpClient.PostAsJsonAsync(url, new { usernames = userNames, bossId = bossId }); // 401: API 키 인증 실패 if (response.StatusCode == HttpStatusCode.Unauthorized) @@ -166,10 +166,10 @@ public class RestApi : Singleton } [JsonPropertyName("tokens")] - public string? Tokens + public Dictionary Tokens { get; set; - } + } = new(); } } diff --git a/MMOTestServer/MMOserver/Game/GameServer.cs b/MMOTestServer/MMOserver/Game/GameServer.cs index 4318702..f14ddac 100644 --- a/MMOTestServer/MMOserver/Game/GameServer.cs +++ b/MMOTestServer/MMOserver/Game/GameServer.cs @@ -1144,10 +1144,16 @@ public class GameServer : ServerBase SendTo(memberPeer, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, response)); // 모두에게 레이드로 이동 (할당된 실제 레이드 맵 ID 전달) - SendTo(peer, - PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID, - new IntoBossRaidPacket - { RaidId = assignedRaidMapId, IsSuccess = true, Session = result.SessionName, Token = result.Tokens })); + if (result.Tokens.ContainsKey(memberPlayer.Nickname.Trim())) + { + SendTo(peer, + PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID, + new IntoBossRaidPacket + { + RaidId = assignedRaidMapId, IsSuccess = true, Session = result.SessionName, + Token = result.Tokens[memberPlayer.Nickname.Trim()] + })); + } } Log.Debug("[GameServer] INTO_BOSS_RAID HashKey={Key} PartyId={PartyId} AssignedRaidMapId={RaidId}", hashKey, party.PartyId, From fb76f49ec0b36be3e1d82b75c45a263cbe059c50 Mon Sep 17 00:00:00 2001 From: qornwh1 Date: Tue, 17 Mar 2026 10:33:08 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat=20:=20=EB=B3=B4=EC=8A=A4=20=EC=A0=84?= =?UTF-8?q?=EC=9A=A9=EC=B1=84=EB=84=90=20=EC=A0=9C=EA=B1=B0,=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=205=EA=B0=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20config.?= =?UTF-8?q?json=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MMOTestServer/MMOserver/Api/RestApi.cs | 2 +- MMOTestServer/MMOserver/Config/AppConfig.cs | 12 ++++++++++++ .../MMOserver/Game/Channel/ChannelManager.cs | 14 ++------------ MMOTestServer/MMOserver/Game/GameServer.cs | 10 +++++++--- MMOTestServer/MMOserver/config.json | 4 +++- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/MMOTestServer/MMOserver/Api/RestApi.cs b/MMOTestServer/MMOserver/Api/RestApi.cs index c3cefbe..46fe42c 100644 --- a/MMOTestServer/MMOserver/Api/RestApi.cs +++ b/MMOTestServer/MMOserver/Api/RestApi.cs @@ -73,7 +73,7 @@ public class RestApi : Singleton // 성공 시 BossRaidResult 반환, 실패/거절 시 null 반환 public async Task BossRaidAccesssAsync(List userNames, int bossId) { - string url = AppConfig.RestApi.BaseUrl + "/api/internal/bossraid/entry"; + string url = AppConfig.RestApi.BaseUrl + AppConfig.RestApi.BossRaidAccess; for (int attempt = 1; attempt <= MAX_RETRY; attempt++) { diff --git a/MMOTestServer/MMOserver/Config/AppConfig.cs b/MMOTestServer/MMOserver/Config/AppConfig.cs index f93fad7..5009eb0 100644 --- a/MMOTestServer/MMOserver/Config/AppConfig.cs +++ b/MMOTestServer/MMOserver/Config/AppConfig.cs @@ -30,9 +30,15 @@ public sealed class ServerConfig get; } + public int ChannelCount + { + get; + } + public ServerConfig(IConfigurationSection section) { Port = int.Parse(section["Port"] ?? throw new InvalidOperationException("Server:Port is required in config.json")); + ChannelCount = int.Parse(section["ChannelCount"] ?? "1"); } } @@ -48,6 +54,11 @@ public sealed class RestApiConfig get; } + public string BossRaidAccess + { + get; + } + public string ApiKey { get; @@ -57,6 +68,7 @@ public sealed class RestApiConfig { BaseUrl = section["BaseUrl"] ?? throw new InvalidOperationException("RestApi:BaseUrl is required in config.json"); VerifyToken = section["VerifyToken"] ?? throw new InvalidOperationException("RestApi:BaseUrl is required in config.json"); + BossRaidAccess = section["BossRaidAccess"] ?? throw new InvalidOperationException("RestApi:BaseUrl is required in config.json"); ApiKey = section["ApiKey"] ?? throw new InvalidOperationException("RestApi:ApiKey is required in config.json"); } } diff --git a/MMOTestServer/MMOserver/Game/Channel/ChannelManager.cs b/MMOTestServer/MMOserver/Game/Channel/ChannelManager.cs index 3e6e6a8..905535a 100644 --- a/MMOTestServer/MMOserver/Game/Channel/ChannelManager.cs +++ b/MMOTestServer/MMOserver/Game/Channel/ChannelManager.cs @@ -1,4 +1,5 @@ using LiteNetLib; +using MMOserver.Config; using MMOserver.Utils; namespace MMOserver.Game.Channel; @@ -8,16 +9,12 @@ public class ChannelManager : Singleton // 채널 관리 private Dictionary channels = new Dictionary(); - // 보스 레이드 채널 - private readonly int bossChannelStart = 10000; - private readonly int bossChannelSize = 10; - // 채널별 유저 관리 (유저 key, 채널 val) private Dictionary connectUsers = new Dictionary(); public ChannelManager() { - Initializer(); + Initializer(AppConfig.Server.ChannelCount); } public void Initializer(int channelSize = 1) @@ -26,13 +23,6 @@ public class ChannelManager : Singleton { channels.Add(i, new Channel(i)); } - - // 보스 채널 생성 - for (int i = 1; i <= bossChannelSize; i++) - { - int bossChannel = i + bossChannelStart; - channels.Add(bossChannel, new Channel(bossChannel)); - } } public Channel GetChannel(int channelId) diff --git a/MMOTestServer/MMOserver/Game/GameServer.cs b/MMOTestServer/MMOserver/Game/GameServer.cs index f14ddac..f037317 100644 --- a/MMOTestServer/MMOserver/Game/GameServer.cs +++ b/MMOTestServer/MMOserver/Game/GameServer.cs @@ -103,7 +103,7 @@ public class GameServer : ServerBase { AccTokenPacket accTokenPacket = Serializer.Deserialize(new ReadOnlyMemory(payload)); string token = accTokenPacket.Token; - string username = ""; + string? username = ""; tokenHash.TryGetValue(token, out int hashKey); if (hashKey <= 1000) { @@ -122,7 +122,7 @@ public class GameServer : ServerBase { // 신규 연결: 웹서버에 JWT 검증 요청 username = await RestApi.Instance.VerifyTokenAsync(token); - if (username == null) + if (username == null || username.Trim().Length <= 0) { Log.Warning("[Server] 토큰 검증 실패 - 연결 거부 PeerId={Id}", peer.Id); userUuidGenerator.Release(hashKey); @@ -1073,7 +1073,11 @@ public class GameServer : ServerBase List userNames = new List(); foreach (int memberId in party.PartyMemberIds) { - userNames.Add(channel.GetPlayer(memberId).Nickname); + Player? memberPlayer = channel.GetPlayer(memberId); + if (memberPlayer != null) + { + userNames.Add(memberPlayer.Nickname); + } } BossRaidResult? result = await RestApi.Instance.BossRaidAccesssAsync(userNames, 1); diff --git a/MMOTestServer/MMOserver/config.json b/MMOTestServer/MMOserver/config.json index 569a4d8..16f27fd 100644 --- a/MMOTestServer/MMOserver/config.json +++ b/MMOTestServer/MMOserver/config.json @@ -1,10 +1,12 @@ { "Server": { - "Port": 9500 + "Port": 9500, + "ChannelCount": 5 }, "RestApi": { "BaseUrl": "https://a301.api.tolelom.xyz", "VerifyToken": "/api/internal/auth/verify", + "BossRaidAccess": "/api/internal/bossraid/entry", "ApiKey": "017f15b28143fc67d2e5bed283c37d2da858b9f294990a5334238e055e3f5425" }, "Database": {