Compare commits
4 Commits
f6b378cad7
...
fix/cross-
| Author | SHA1 | Date | |
|---|---|---|---|
| a5eedb2fb2 | |||
|
|
39ef81d48a | ||
|
|
6faab45ecc | ||
|
|
dd8dcc58d2 |
13
MMOTestServer/MMOserver/Api/BossRaidResult.cs
Normal file
13
MMOTestServer/MMOserver/Api/BossRaidResult.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace MMOserver.Api;
|
||||
|
||||
// RestApi.BossRaidAccesssAsync 반환용 도메인 모델
|
||||
// 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<string> Players { get; init; } = new();
|
||||
public string Status { get; init; } = string.Empty;
|
||||
public Dictionary<string, string> Tokens { get; init; } = new();
|
||||
}
|
||||
@@ -70,8 +70,8 @@ public class RestApi : Singleton<RestApi>
|
||||
}
|
||||
|
||||
// 레이드 채널 접속 여부 체크
|
||||
// 성공 시 sessionName 반환, 실패/거절 시 null 반환
|
||||
public async Task<bool?> BossRaidAccesssAsync(List<string> userNames, int bossId)
|
||||
// 성공 시 BossRaidResult 반환, 실패/거절 시 null 반환
|
||||
public async Task<BossRaidResult?> BossRaidAccesssAsync(List<string> userNames, int bossId)
|
||||
{
|
||||
string url = AppConfig.RestApi.BaseUrl + "/api/internal/bossraid/entry";
|
||||
|
||||
@@ -85,20 +85,41 @@ public class RestApi : Singleton<RestApi>
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
Log.Warning("[RestApi] 보스 레이드 접속 인증 실패 (401)");
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
// 400: 입장 조건 미충족 (레벨 부족, 이미 진행중 등)
|
||||
// 400: 입장 조건 미충족 (레벨 부족 등)
|
||||
if (response.StatusCode == HttpStatusCode.BadRequest)
|
||||
{
|
||||
Log.Warning("[RestApi] 보스 레이드 입장 거절 (400) BossId={BossId}", bossId);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
// 409: 이미 진행 중이거나 슬롯 충돌
|
||||
if (response.StatusCode == HttpStatusCode.Conflict)
|
||||
{
|
||||
Log.Warning("[RestApi] 보스 레이드 충돌 (409) BossId={BossId} - 이미 진행 중이거나 슬롯 없음", bossId);
|
||||
return null;
|
||||
}
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
BossRaidAccessResponse? result = await response.Content.ReadFromJsonAsync<BossRaidAccessResponse>();
|
||||
return result?.BossId > 0 ? true : false;
|
||||
BossRaidAccessResponse? raw = await response.Content.ReadFromJsonAsync<BossRaidAccessResponse>();
|
||||
if (raw == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// API 응답 → 도메인 모델 매핑
|
||||
return new BossRaidResult
|
||||
{
|
||||
RoomId = raw.RoomId,
|
||||
SessionName = raw.SessionName ?? string.Empty,
|
||||
BossId = raw.BossId,
|
||||
Players = raw.Players,
|
||||
Status = raw.Status ?? string.Empty,
|
||||
Tokens = raw.Tokens ?? new()
|
||||
};
|
||||
}
|
||||
catch (Exception ex) when (attempt < MAX_RETRY)
|
||||
{
|
||||
@@ -111,7 +132,7 @@ public class RestApi : Singleton<RestApi>
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
private sealed class BossRaidAccessResponse
|
||||
@@ -152,10 +173,10 @@ public class RestApi : Singleton<RestApi>
|
||||
}
|
||||
|
||||
[JsonPropertyName("tokens")]
|
||||
public Dictionary<string, string> Tokens
|
||||
public Dictionary<string, string>? Tokens
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,7 +406,12 @@ public class GameServer : ServerBase
|
||||
Mp = player.Mp,
|
||||
MaxMp = player.MaxMp,
|
||||
Position = new Position { X = player.PosX, Y = player.PosY, Z = player.PosZ },
|
||||
RotY = player.RotY
|
||||
RotY = player.RotY,
|
||||
Experience = player.Experience,
|
||||
NextExp = player.NextExp,
|
||||
AttackPower = player.AttackPower,
|
||||
AttackRange = player.AttackRange,
|
||||
SprintMultiplier = player.SprintMultiplier
|
||||
};
|
||||
}
|
||||
|
||||
@@ -574,12 +579,17 @@ public class GameServer : ServerBase
|
||||
|
||||
if (memberPeer != null)
|
||||
{
|
||||
// 세션에서 username 조회
|
||||
string nickname = memberPeer.Tag is Session s && !string.IsNullOrEmpty(s.UserName)
|
||||
? s.UserName
|
||||
: memberId.ToString();
|
||||
|
||||
// 새 채널에 유저 추가
|
||||
Player newPlayer = new()
|
||||
{
|
||||
HashKey = memberId,
|
||||
PlayerId = memberId,
|
||||
Nickname = memberId.ToString()
|
||||
Nickname = nickname
|
||||
};
|
||||
cm.AddUser(packet.ChannelId, memberId, newPlayer, memberPeer);
|
||||
|
||||
@@ -1073,13 +1083,19 @@ public class GameServer : ServerBase
|
||||
List<string> userNames = new List<string>();
|
||||
foreach (int memberId in party.PartyMemberIds)
|
||||
{
|
||||
userNames.Add(channel.GetPlayer(memberId).Nickname);
|
||||
Player? member = channel.GetPlayer(memberId);
|
||||
if (member == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
userNames.Add(member.Nickname);
|
||||
}
|
||||
|
||||
bool? result = await RestApi.Instance.BossRaidAccesssAsync(userNames, 1);
|
||||
BossRaidResult? result = await RestApi.Instance.BossRaidAccesssAsync(userNames, packet.RaidId);
|
||||
|
||||
// 입장 실패
|
||||
if (result.Value == false)
|
||||
if (result == null || result.BossId <= 0)
|
||||
{
|
||||
SendTo(peer,
|
||||
PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
@@ -1087,6 +1103,7 @@ public class GameServer : ServerBase
|
||||
|
||||
Log.Debug("[GameServer] INTO_BOSS_RAID HashKey={Key} PartyId={PartyId} AssignedRaidMapId={RaidId} Failed", hashKey,
|
||||
party.PartyId, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
// 레이드 맵 할당 (미사용 맵 탐색 → 없으면 동적 생성)
|
||||
@@ -1141,12 +1158,15 @@ 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 }));
|
||||
// 각 파티원에게 레이드 입장 정보 전달 (본인의 토큰 포함)
|
||||
string? memberToken = null;
|
||||
result.Tokens?.TryGetValue(memberPlayer.Nickname, out memberToken);
|
||||
SendTo(memberPeer,
|
||||
PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
new IntoBossRaidPacket
|
||||
{ RaidId = assignedRaidMapId, IsSuccess = true, Session = result.SessionName, Token = memberToken }));
|
||||
}
|
||||
|
||||
Log.Debug("[GameServer] INTO_BOSS_RAID HashKey={Key} PartyId={PartyId} AssignedRaidMapId={RaidId}", hashKey, party.PartyId,
|
||||
assignedRaidMapId);
|
||||
|
||||
@@ -75,6 +75,38 @@ public class Player
|
||||
set;
|
||||
}
|
||||
|
||||
// 경험치
|
||||
public int Experience
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int NextExp
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
// 전투 스탯
|
||||
public float AttackPower
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public float AttackRange
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public float SprintMultiplier
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
// 현재 위치한 맵 ID
|
||||
public int CurrentMapId
|
||||
{
|
||||
|
||||
@@ -114,6 +114,41 @@ public class PlayerInfo
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ProtoMember(10)]
|
||||
public int Experience
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ProtoMember(11)]
|
||||
public int NextExp
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ProtoMember(12)]
|
||||
public float AttackPower
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ProtoMember(13)]
|
||||
public float AttackRange
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ProtoMember(14)]
|
||||
public float SprintMultiplier
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
@@ -769,6 +804,20 @@ public class IntoBossRaidPacket
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ProtoMember(3)]
|
||||
public string Token
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[ProtoMember(4)]
|
||||
public string Session
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
// PARTY_CHANGE_MAP (클라 -> 서버 전용)
|
||||
|
||||
Reference in New Issue
Block a user