From f2bc3d7924036b25a5b81093edacc3522f00f27d Mon Sep 17 00:00:00 2001 From: qornwh1 Date: Mon, 16 Mar 2026 11:14:38 +0900 Subject: [PATCH] =?UTF-8?q?fix=20:=20=EC=84=9C=EB=B2=84=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=ED=8C=8C=EC=9D=BC=20=EB=B9=BC=EA=B8=B0=20=EC=9E=91?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MMOTestServer/MMOserver/Api/RestApi.cs | 7 +-- MMOTestServer/MMOserver/Config/AppConfig.cs | 62 +++++++++++++++++++ MMOTestServer/MMOserver/Game/GameServer.cs | 36 ++++++----- .../MMOserver/Game/Party/PartyManager.cs | 3 +- MMOTestServer/MMOserver/Program.cs | 5 +- MMOTestServer/MMOserver/config.json | 10 ++- 6 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 MMOTestServer/MMOserver/Config/AppConfig.cs diff --git a/MMOTestServer/MMOserver/Api/RestApi.cs b/MMOTestServer/MMOserver/Api/RestApi.cs index cd24bf4..998b425 100644 --- a/MMOTestServer/MMOserver/Api/RestApi.cs +++ b/MMOTestServer/MMOserver/Api/RestApi.cs @@ -1,6 +1,7 @@ using System.Net; using System.Net.Http.Json; using System.Text.Json.Serialization; +using MMOserver.Config; using MMOserver.Utils; using Serilog; @@ -8,8 +9,6 @@ namespace MMOserver.Api; public class RestApi : Singleton { - private const string VERIFY_URL = "https://a301.api.tolelom.xyz"; - private const string INTERNAL_API_KEY = "017f15b28143fc67d2e5bed283c37d2da858b9f294990a5334238e055e3f5425"; private readonly HttpClient httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; private const int MAX_RETRY = 3; @@ -17,7 +16,7 @@ public class RestApi : Singleton public RestApi() { - httpClient.DefaultRequestHeaders.Add("X-API-Key", INTERNAL_API_KEY); + httpClient.DefaultRequestHeaders.Add("X-API-Key", AppConfig.RestApi.ApiKey); } // 토큰 검증 - 성공 시 username 반환 @@ -25,7 +24,7 @@ public class RestApi : Singleton // 타임아웃/네트워크 오류 → 최대 MAX_RETRY회 재시도 후 null 반환 public async Task VerifyTokenAsync(string token) { - string url = VERIFY_URL + "/api/internal/auth/verify"; + string url = AppConfig.RestApi.BaseUrl + AppConfig.RestApi.VerifyToken; for (int attempt = 1; attempt <= MAX_RETRY; attempt++) { try diff --git a/MMOTestServer/MMOserver/Config/AppConfig.cs b/MMOTestServer/MMOserver/Config/AppConfig.cs new file mode 100644 index 0000000..f93fad7 --- /dev/null +++ b/MMOTestServer/MMOserver/Config/AppConfig.cs @@ -0,0 +1,62 @@ +using Microsoft.Extensions.Configuration; + +namespace MMOserver.Config; + +public static class AppConfig +{ + public static ServerConfig Server + { + get; + private set; + } = null!; + + public static RestApiConfig RestApi + { + get; + private set; + } = null!; + + public static void Initialize(IConfiguration config) + { + Server = new ServerConfig(config.GetSection("Server")); + RestApi = new RestApiConfig(config.GetSection("RestApi")); + } +} + +public sealed class ServerConfig +{ + public int Port + { + get; + } + + public ServerConfig(IConfigurationSection section) + { + Port = int.Parse(section["Port"] ?? throw new InvalidOperationException("Server:Port is required in config.json")); + } +} + +public sealed class RestApiConfig +{ + public string BaseUrl + { + get; + } + + public string VerifyToken + { + get; + } + + public string ApiKey + { + get; + } + + public RestApiConfig(IConfigurationSection section) + { + 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"); + ApiKey = section["ApiKey"] ?? throw new InvalidOperationException("RestApi:ApiKey is required in config.json"); + } +} diff --git a/MMOTestServer/MMOserver/Game/GameServer.cs b/MMOTestServer/MMOserver/Game/GameServer.cs index 8aec1e8..bf2e173 100644 --- a/MMOTestServer/MMOserver/Game/GameServer.cs +++ b/MMOTestServer/MMOserver/Game/GameServer.cs @@ -457,7 +457,7 @@ public class GameServer : ServerBase newParty.DeepCopySemi(preParty); // 최대 인원 체크 - if (newChannel.UserCount + newParty.PartyMemberIds.Count >= newChannel.UserCountMax) + if (newChannel.UserCount + preParty.PartyMemberIds.Count >= newChannel.UserCountMax) { Log.Warning("[GameServer] INTO_CHANNEL_PARTY 채널 인원 초과 HashKey={Key} ChannelId={ChannelId} UserCount={Count}/{Max}", hashKey, packet.ChannelId, newChannel.UserCount, newChannel.UserCountMax); @@ -497,8 +497,9 @@ public class GameServer : ServerBase Type = PartyUpdateType.DELETE, LeaderId = preParty.LeaderId, }; - BroadcastToChannel(preChannelId, - PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, notify)); // 채널 전체 파티 목록 갱신 + + // 채널 전체 파티 목록 갱신 + BroadcastToChannel(preChannelId, PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, notify)); // 새로운 채널에 파티원 넣기 foreach (int memberId in newParty.PartyMemberIds) @@ -525,17 +526,22 @@ public class GameServer : ServerBase } // 새로운 채널에 파티를 추가한다. - newChannel.GetPartyManager().CreateParty(newParty.LeaderId, newParty.PartyName, out newParty, newParty.PartyMemberIds); - - // 새 채널 기존 유저들에게 파티 생성 알림 - UpdatePartyPacket createNotify = new UpdatePartyPacket + if (newChannel.GetPartyManager().CreateParty(newParty.LeaderId, newParty.PartyName, out PartyInfo? createdParty, newParty.PartyMemberIds) && createdParty != null) { - PartyId = newParty.PartyId, - Type = PartyUpdateType.CREATE, - LeaderId = newParty.LeaderId, - PartyName = newParty.PartyName, - }; - BroadcastToChannel(packet.ChannelId, PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, createNotify)); + // 새 채널 기존 유저들에게 파티 생성 알림 + UpdatePartyPacket createNotify = new UpdatePartyPacket + { + PartyId = createdParty.PartyId, + Type = PartyUpdateType.CREATE, + LeaderId = createdParty.LeaderId, + PartyName = createdParty.PartyName, + }; + BroadcastToChannel(packet.ChannelId, PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, createNotify)); + } + else + { + Log.Warning("[GameServer] 파티생성 실패 !!!"); + } } private void OnExitChannel(NetPeer peer, int hashKey, byte[] payload) @@ -688,7 +694,7 @@ public class GameServer : ServerBase } case PartyUpdateType.LEAVE: { - if (!pm.LeaveParty(hashKey, out PartyInfo? party)) + if (!pm.LeaveParty(hashKey, out PartyInfo? party) || party == null) { SendError(peer, ErrorCode.PARTY_NOT_IN_PARTY); return; @@ -696,7 +702,7 @@ public class GameServer : ServerBase UpdatePartyPacket notify = new UpdatePartyPacket { - PartyId = party.PartyId, Type = PartyUpdateType.DELETE, LeaderId = party?.LeaderId ?? 0, PlayerId = hashKey, + PartyId = party.PartyId, Type = PartyUpdateType.DELETE, LeaderId = party.LeaderId, PlayerId = hashKey, }; // 파티가 남아있으면 살린다. diff --git a/MMOTestServer/MMOserver/Game/Party/PartyManager.cs b/MMOTestServer/MMOserver/Game/Party/PartyManager.cs index 857e020..7dca0b9 100644 --- a/MMOTestServer/MMOserver/Game/Party/PartyManager.cs +++ b/MMOTestServer/MMOserver/Game/Party/PartyManager.cs @@ -15,10 +15,9 @@ public class PartyManager // 파티 생성 public bool CreateParty(int leaderId, string partyName, out PartyInfo? party, List? memeberIds = null) { - party = null; - if (playerPartyMap.ContainsKey(leaderId)) { + party = null; return false; // 이미 파티에 속해있음 } diff --git a/MMOTestServer/MMOserver/Program.cs b/MMOTestServer/MMOserver/Program.cs index cfc08b5..3145cde 100644 --- a/MMOTestServer/MMOserver/Program.cs +++ b/MMOTestServer/MMOserver/Program.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Configuration; +using MMOserver.Config; using MMOserver.Game; using MMOserver.RDB; using Serilog; @@ -21,6 +22,8 @@ class Program .AddEnvironmentVariables() // 도커 배포용 .Build(); + AppConfig.Initialize(config); + // DB 연결 // DbConnectionFactory dbFactory = new DbConnectionFactory(config); @@ -34,7 +37,7 @@ class Program Log.Information("Write Log Started"); - int port = 9500; + int port = AppConfig.Server.Port; string connectionString = "test"; GameServer gameServer = new GameServer(port, connectionString); diff --git a/MMOTestServer/MMOserver/config.json b/MMOTestServer/MMOserver/config.json index 9b09330..569a4d8 100644 --- a/MMOTestServer/MMOserver/config.json +++ b/MMOTestServer/MMOserver/config.json @@ -1,4 +1,12 @@ -{ +{ + "Server": { + "Port": 9500 + }, + "RestApi": { + "BaseUrl": "https://a301.api.tolelom.xyz", + "VerifyToken": "/api/internal/auth/verify", + "ApiKey": "017f15b28143fc67d2e5bed283c37d2da858b9f294990a5334238e055e3f5425" + }, "Database": { "Host": "localhost", "Port": "0000",