feat : 맵관리 코드 추가 작업
This commit is contained in:
@@ -1,27 +1,45 @@
|
|||||||
using LiteNetLib;
|
using LiteNetLib;
|
||||||
using MMOserver.Game.Channel.Maps;
|
using MMOserver.Game.Channel.Maps;
|
||||||
|
using MMOserver.Game.Channel.Maps.InstanceDungeun;
|
||||||
using MMOserver.Game.Party;
|
using MMOserver.Game.Party;
|
||||||
|
|
||||||
namespace MMOserver.Game.Channel;
|
namespace MMOserver.Game.Channel;
|
||||||
|
|
||||||
public class Channel
|
public class Channel
|
||||||
{
|
{
|
||||||
// 로비
|
// 채널 내 유저 NetPeer (hashKey → NetPeer) — BroadcastToChannel 교차 조회 제거용
|
||||||
private Robby robby = new Robby();
|
private readonly Dictionary<int, NetPeer> connectPeers = new();
|
||||||
|
|
||||||
// 파티
|
|
||||||
private PartyManager partyManager = new PartyManager();
|
|
||||||
|
|
||||||
// 채널 내 유저 상태 (hashKey → Player)
|
// 채널 내 유저 상태 (hashKey → Player)
|
||||||
private Dictionary<int, Player> connectUsers = new Dictionary<int, Player>();
|
private readonly Dictionary<int, Player> connectUsers = new();
|
||||||
|
|
||||||
// 채널 내 유저 NetPeer (hashKey → NetPeer) — BroadcastToChannel 교차 조회 제거용
|
// 채널 맵 관리
|
||||||
private Dictionary<int, NetPeer> connectPeers = new Dictionary<int, NetPeer>();
|
private readonly Dictionary<int, AMap> maps = new();
|
||||||
|
|
||||||
|
// 파티
|
||||||
|
private readonly PartyManager partyManager = new();
|
||||||
|
|
||||||
|
public Channel(int channelId)
|
||||||
|
{
|
||||||
|
ChannelId = channelId;
|
||||||
|
|
||||||
|
// 일단 하드코딩으로 맵 생성
|
||||||
|
{
|
||||||
|
// 로비
|
||||||
|
maps.Add(1, new Robby(1));
|
||||||
|
|
||||||
|
// 인던
|
||||||
|
int defaultValue = 10;
|
||||||
|
for (int i = 1; i <= 10; i++)
|
||||||
|
{
|
||||||
|
maps.Add(i + defaultValue, new BossInstance(i + defaultValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int ChannelId
|
public int ChannelId
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
private set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int UserCount
|
public int UserCount
|
||||||
@@ -36,25 +54,48 @@ public class Channel
|
|||||||
private set;
|
private set;
|
||||||
} = 100;
|
} = 100;
|
||||||
|
|
||||||
public Channel(int channelId)
|
|
||||||
{
|
|
||||||
ChannelId = channelId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddUser(int userId, Player player, NetPeer peer)
|
public void AddUser(int userId, Player player, NetPeer peer)
|
||||||
{
|
{
|
||||||
connectUsers[userId] = player;
|
connectUsers[userId] = player;
|
||||||
connectPeers[userId] = peer;
|
connectPeers[userId] = peer;
|
||||||
UserCount++;
|
UserCount++;
|
||||||
|
|
||||||
|
// 처음 접속 시 1번 맵(로비)으로 입장
|
||||||
|
ChangeMap(userId, player, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveUser(int userId)
|
public void RemoveUser(int userId)
|
||||||
{
|
{
|
||||||
|
// 현재 맵에서도 제거
|
||||||
|
if (connectUsers.TryGetValue(userId, out Player? player))
|
||||||
|
{
|
||||||
|
maps[player.CurrentMapId].RemoveUser(userId);
|
||||||
|
}
|
||||||
|
|
||||||
connectUsers.Remove(userId);
|
connectUsers.Remove(userId);
|
||||||
connectPeers.Remove(userId);
|
connectPeers.Remove(userId);
|
||||||
UserCount--;
|
UserCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 맵 이동 (현재 맵 제거 → 새 맵 추가 → CurrentMapId 갱신)
|
||||||
|
public bool ChangeMap(int userId, Player player, int mapId)
|
||||||
|
{
|
||||||
|
if (!maps.TryGetValue(mapId, out AMap? newMap))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기존 맵에서 제거
|
||||||
|
if (maps.TryGetValue(player.CurrentMapId, out AMap? oldMap))
|
||||||
|
{
|
||||||
|
oldMap.RemoveUser(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
newMap.AddUser(userId, player);
|
||||||
|
player.CurrentMapId = mapId;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 재연결(WiFi→LTE 등) 시 동일 유저의 peer 교체
|
// 재연결(WiFi→LTE 등) 시 동일 유저의 peer 교체
|
||||||
public void UpdatePeer(int userId, NetPeer peer)
|
public void UpdatePeer(int userId, NetPeer peer)
|
||||||
{
|
{
|
||||||
@@ -96,10 +137,18 @@ public class Channel
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 로비 가져옴
|
// 맵들 가져옴
|
||||||
public Robby GetRobby()
|
public Dictionary<int, AMap> GetMaps()
|
||||||
{
|
{
|
||||||
return robby;
|
return maps;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 맵 가져옴
|
||||||
|
public AMap? GetMap(int mapId)
|
||||||
|
{
|
||||||
|
AMap? map = null;
|
||||||
|
maps.TryGetValue(mapId, out map);
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 파티매니저 가져옴
|
// 파티매니저 가져옴
|
||||||
|
|||||||
24
MMOTestServer/MMOserver/Game/Channel/Maps/AMap.cs
Normal file
24
MMOTestServer/MMOserver/Game/Channel/Maps/AMap.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace MMOserver.Game.Channel.Maps;
|
||||||
|
|
||||||
|
public abstract class AMap
|
||||||
|
{
|
||||||
|
private Dictionary<int, Player> users = new Dictionary<int, Player>();
|
||||||
|
|
||||||
|
public abstract EnumMap GetMapType();
|
||||||
|
public abstract int GetMapId();
|
||||||
|
|
||||||
|
public void AddUser(int userId, Player player)
|
||||||
|
{
|
||||||
|
users[userId] = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveUser(int userId)
|
||||||
|
{
|
||||||
|
users.Remove(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<int, Player> GetUsers()
|
||||||
|
{
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
MMOTestServer/MMOserver/Game/Channel/Maps/EunmMap.cs
Normal file
8
MMOTestServer/MMOserver/Game/Channel/Maps/EunmMap.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace MMOserver.Game.Channel.Maps;
|
||||||
|
|
||||||
|
public enum EnumMap : int
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
ROBBY = 1,
|
||||||
|
INSTANCE = 10,
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using MMOserver.Game.Channel.Maps;
|
||||||
|
using MMOserver.Game.Engine;
|
||||||
|
|
||||||
|
namespace MMOserver.Game.Channel.Maps.InstanceDungeun;
|
||||||
|
|
||||||
|
// 인스턴스 보스 맵에 들어갈때 쓰는 것
|
||||||
|
public class BossInstance : AMap
|
||||||
|
{
|
||||||
|
private EnumMap enumMap;
|
||||||
|
private int mapId;
|
||||||
|
|
||||||
|
// 마을 시작 지점 넣어 둔다.
|
||||||
|
public static Vector3 StartPosition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
} = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
public BossInstance(int mapId, EnumMap enumMap = EnumMap.INSTANCE)
|
||||||
|
{
|
||||||
|
this.enumMap = enumMap;
|
||||||
|
this.mapId = mapId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override EnumMap GetMapType()
|
||||||
|
{
|
||||||
|
return enumMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetMapId()
|
||||||
|
{
|
||||||
|
return mapId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
namespace MMOserver.Game.Channel.Maps;
|
namespace MMOserver.Game.Channel.Maps;
|
||||||
|
|
||||||
public class Robby
|
public class Robby : AMap
|
||||||
{
|
{
|
||||||
|
private EnumMap enumMap;
|
||||||
|
private int mapId;
|
||||||
|
|
||||||
// 마을 시작 지점 넣어 둔다.
|
// 마을 시작 지점 넣어 둔다.
|
||||||
public static Vector3 StartPosition
|
public static Vector3 StartPosition
|
||||||
{
|
{
|
||||||
@@ -11,7 +14,19 @@ public class Robby
|
|||||||
set;
|
set;
|
||||||
} = new Vector3(0, 0, 0);
|
} = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
public Robby()
|
public Robby(int mapId, EnumMap enumMap = EnumMap.ROBBY)
|
||||||
{
|
{
|
||||||
|
this.enumMap = enumMap;
|
||||||
|
this.mapId = mapId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override EnumMap GetMapType()
|
||||||
|
{
|
||||||
|
return enumMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetMapId()
|
||||||
|
{
|
||||||
|
return mapId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ public class GameServer : ServerBase
|
|||||||
[(ushort)PacketCode.TRANSFORM_PLAYER] = OnTransformPlayer,
|
[(ushort)PacketCode.TRANSFORM_PLAYER] = OnTransformPlayer,
|
||||||
[(ushort)PacketCode.ACTION_PLAYER] = OnActionPlayer,
|
[(ushort)PacketCode.ACTION_PLAYER] = OnActionPlayer,
|
||||||
[(ushort)PacketCode.STATE_PLAYER] = OnStatePlayer,
|
[(ushort)PacketCode.STATE_PLAYER] = OnStatePlayer,
|
||||||
|
[(ushort)PacketCode.CHANGE_MAP] = OnChangeMap,
|
||||||
|
[(ushort)PacketCode.PARTY_CHANGE_MAP] = OnPartyChangeMap,
|
||||||
[(ushort)PacketCode.REQUEST_PARTY] = OnRequestParty,
|
[(ushort)PacketCode.REQUEST_PARTY] = OnRequestParty,
|
||||||
[(ushort)PacketCode.CHAT] = OnChat,
|
[(ushort)PacketCode.CHAT] = OnChat,
|
||||||
};
|
};
|
||||||
@@ -78,7 +80,8 @@ public class GameServer : ServerBase
|
|||||||
{
|
{
|
||||||
HashKey = hashKey,
|
HashKey = hashKey,
|
||||||
PlayerId = hashKey,
|
PlayerId = hashKey,
|
||||||
Nickname = hashKey.ToString()
|
Nickname = hashKey.ToString(),
|
||||||
|
CurrentMapId = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
cm.AddUser(1, hashKey, newPlayer, peer);
|
cm.AddUser(1, hashKey, newPlayer, peer);
|
||||||
@@ -421,9 +424,11 @@ public class GameServer : ServerBase
|
|||||||
{
|
{
|
||||||
HashKey = hashKey,
|
HashKey = hashKey,
|
||||||
PlayerId = hashKey,
|
PlayerId = hashKey,
|
||||||
Nickname = hashKey.ToString()
|
Nickname = hashKey.ToString(),
|
||||||
|
CurrentMapId = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 채널에 추가
|
||||||
cm.AddUser(packet.ChannelId, hashKey, newPlayer, peer);
|
cm.AddUser(packet.ChannelId, hashKey, newPlayer, peer);
|
||||||
Log.Debug("[GameServer] INTO_CHANNEL HashKey={Key} ChannelId={ChannelId}", hashKey, packet.ChannelId);
|
Log.Debug("[GameServer] INTO_CHANNEL HashKey={Key} ChannelId={ChannelId}", hashKey, packet.ChannelId);
|
||||||
|
|
||||||
@@ -828,6 +833,84 @@ public class GameServer : ServerBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnChangeMap(NetPeer peer, int hashKey, byte[] payload)
|
||||||
|
{
|
||||||
|
ChangeMapPacket packet = Serializer.Deserialize<ChangeMapPacket>(new ReadOnlyMemory<byte>(payload));
|
||||||
|
|
||||||
|
ChannelManager cm = ChannelManager.Instance;
|
||||||
|
int channelId = cm.HasUser(hashKey);
|
||||||
|
if (channelId < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Channel.Channel channel = cm.GetChannel(channelId);
|
||||||
|
Player? player = channel.GetPlayer(hashKey);
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
if (!channel.ChangeMap(hashKey, player, packet.MapId))
|
||||||
|
{
|
||||||
|
// 맵이 없으면 무효
|
||||||
|
Log.Warning("[GameServer] CHANGE_MAP 유효하지 않은 맵 HashKey={Key} MapId={MapId}", hashKey, packet.MapId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이동 완료 알림
|
||||||
|
byte[] data = PacketSerializer.Serialize<ChangeMapPacket>((ushort)PacketCode.CHANGE_MAP, packet);
|
||||||
|
SendTo(peer, data);
|
||||||
|
Log.Debug("[GameServer] CHANGE_MAP HashKey={Key} MapId={MapId}", hashKey, packet.MapId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPartyChangeMap(NetPeer peer, int hashKey, byte[] payload)
|
||||||
|
{
|
||||||
|
PartyChangeMapPacket packet = Serializer.Deserialize<PartyChangeMapPacket>(new ReadOnlyMemory<byte>(payload));
|
||||||
|
|
||||||
|
ChannelManager cm = ChannelManager.Instance;
|
||||||
|
int channelId = cm.HasUser(hashKey);
|
||||||
|
if (channelId < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Channel.Channel channel = cm.GetChannel(channelId);
|
||||||
|
|
||||||
|
// 맵 유효성 체크
|
||||||
|
if (channel.GetMap(packet.MapId) == null)
|
||||||
|
{
|
||||||
|
Log.Warning("[GameServer] PARTY_CHANGE_MAP 유효하지 않은 맵 HashKey={Key} MapId={MapId}", hashKey, packet.MapId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 파티 확인
|
||||||
|
PartyInfo? party = channel.GetPartyManager().GetParty(packet.PartyId);
|
||||||
|
if (party == null)
|
||||||
|
{
|
||||||
|
Log.Warning("[GameServer] PARTY_CHANGE_MAP 파티 없음 HashKey={Key} PartyId={PartyId}", hashKey, packet.PartyId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 파티원 전체 맵 이동 + 각자에게 알림
|
||||||
|
byte[] data = PacketSerializer.Serialize<PartyChangeMapPacket>((ushort)PacketCode.PARTY_CHANGE_MAP, packet);
|
||||||
|
foreach (int memberId in party.PartyMemberIds)
|
||||||
|
{
|
||||||
|
Player? memberPlayer = channel.GetPlayer(memberId);
|
||||||
|
if (memberPlayer == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel.ChangeMap(memberId, memberPlayer, packet.MapId);
|
||||||
|
|
||||||
|
if (sessions.TryGetValue(memberId, out NetPeer? memberPeer))
|
||||||
|
{
|
||||||
|
SendTo(memberPeer, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Debug("[GameServer] PARTY_CHANGE_MAP HashKey={Key} PartyId={PartyId} MapId={MapId}", hashKey, packet.PartyId, packet.MapId);
|
||||||
|
}
|
||||||
|
|
||||||
// 채널 퇴장/연결 해제 시 파티 자동 탈퇴 처리
|
// 채널 퇴장/연결 해제 시 파티 자동 탈퇴 처리
|
||||||
private void HandlePartyLeaveOnExit(int channelId, int hashKey)
|
private void HandlePartyLeaveOnExit(int channelId, int hashKey)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,4 +74,11 @@ public class Player
|
|||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 현재 위치한 맵 ID
|
||||||
|
public int CurrentMapId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -709,6 +709,41 @@ public class ChatPacket
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ============================================================
|
||||||
|
// 맵 이동
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// CHANGE_MAP (클라 -> 서버 & 서버 -> 클라)
|
||||||
|
[ProtoContract]
|
||||||
|
public class ChangeMapPacket
|
||||||
|
{
|
||||||
|
[ProtoMember(1)]
|
||||||
|
public int MapId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PARTY_CHANGE_MAP (클라 -> 서버 & 서버 -> 클라)
|
||||||
|
[ProtoContract]
|
||||||
|
public class PartyChangeMapPacket
|
||||||
|
{
|
||||||
|
[ProtoMember(1)]
|
||||||
|
public int MapId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ProtoMember(2)]
|
||||||
|
public int PartyId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 파티
|
// 파티
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ public enum PacketCode : ushort
|
|||||||
// 채널 나가기 (클라 -> 서버)
|
// 채널 나가기 (클라 -> 서버)
|
||||||
EXIT_CHANNEL,
|
EXIT_CHANNEL,
|
||||||
|
|
||||||
|
// 맵 이동
|
||||||
|
CHANGE_MAP,
|
||||||
|
|
||||||
|
// 단체로 맵 이동
|
||||||
|
PARTY_CHANGE_MAP,
|
||||||
|
|
||||||
// 플레이어 위치, 방향 (서버 -> 클라 \ 클라 -> 서버)
|
// 플레이어 위치, 방향 (서버 -> 클라 \ 클라 -> 서버)
|
||||||
TRANSFORM_PLAYER,
|
TRANSFORM_PLAYER,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user