Files
a301_mmo_game_server/MMOTestServer/MMOserver/Game/Channel/Channel.cs

208 lines
5.4 KiB
C#

using LiteNetLib;
using MMOserver.Game.Channel.Maps;
using MMOserver.Game.Channel.Maps.InstanceDungeun;
using MMOserver.Game.Party;
namespace MMOserver.Game.Channel;
/*
* Channel 클래스
* - 채널 내 Peer 관리
* - 채널 내 유저관리
* - 맵 관리
* - 인스턴스 던전 관리
* - 동적 맵 id 생성
*/
public class Channel : UserContainer
{
// 채널 내 유저 NetPeer (hashKey → NetPeer) — BroadcastToChannel 교차 조회 제거용
private readonly Dictionary<int, NetPeer> connectPeers = new();
// 채널 맵 관리
private readonly Dictionary<int, AMap> maps = new();
// 진행중 채널 맵 관리
private readonly Dictionary<int, AMap> useInstanceMaps = new();
// 동적 레이드 맵 할당용 ID 카운터 (사전 생성 10개 이후부터 시작)
private int nextDynamicRaidMapId = 1011;
// 파티
private readonly PartyManager partyManager = new();
public Channel(int channelId)
{
ChannelId = channelId;
foreach (MapConfigData config in MapLoader.Data.Maps)
{
AMap? map = MapLoader.ParseMapType(config.MapType) switch
{
EnumMap.ROBBY => new Robby(config.MapId),
EnumMap.DUNGEON => new BossInstance(config.MapId),
_ => null
};
if (map == null)
{
continue;
}
// 맵정보
map.SetZoneConfig(config.Rows, config.Cols, config.ZoneSize);
// 맵내에 존 생성
map.CreateZones(config.Zones);
maps.Add(config.MapId, map);
}
// 인던은 동적 생성 유지
int defaultValue = 1000;
for (int i = 1; i <= 10; i++)
{
maps.Add(i + defaultValue, new BossInstance(i + defaultValue));
}
}
public int ChannelId
{
get;
}
public int UserCountMax
{
get;
private set;
} = 100;
public void AddUser(int userId, Player player, NetPeer peer)
{
base.AddUser(userId, player);
users[userId] = player;
connectPeers[userId] = peer;
// 처음 접속 시 1번 맵(로비)으로 입장
ChangeMap(userId, player, 1);
}
public override void RemoveUser(int userId)
{
// 현재 맵에서 제거 (AMap.RemoveUser가 존까지 처리)
if (users.TryGetValue(userId, out Player? player))
{
if (maps.TryGetValue(player.CurrentMapId, out AMap? currentMap))
{
currentMap.RemoveUser(userId);
}
}
base.RemoveUser(userId);
connectPeers.Remove(userId);
}
// 맵 이동 (현재 맵 제거 → 새 맵 추가 → 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);
}
// AMap.AddUser가 존 0 배치 + CurrentZoneId = 0 처리
newMap.AddUser(userId, player);
player.CurrentMapId = mapId;
return true;
}
// 재연결(WiFi→LTE 등) 시 동일 유저의 peer 교체
public void UpdatePeer(int userId, NetPeer peer)
{
connectPeers[userId] = peer;
}
// 채널 내 모든 NetPeer 반환 — BroadcastToChannel 전용 (sessions 교차 조회 불필요)
public IEnumerable<NetPeer> GetConnectPeers()
{
return connectPeers.Values;
}
// 특정 유저의 NetPeer 반환
public NetPeer? GetPeer(int userId)
{
connectPeers.TryGetValue(userId, out NetPeer? peer);
return peer;
}
// 유저가 존재하면 채널id를 넘긴다
public override int HasUser(int userId)
{
if (users.ContainsKey(userId))
{
return ChannelId;
}
return -1;
}
// 맵들 가져옴
public Dictionary<int, AMap> GetMaps()
{
return maps;
}
// 맵 가져옴
public AMap? GetMap(int mapId)
{
AMap? map = null;
maps.TryGetValue(mapId, out map);
return map;
}
// 사용 가능한 레이드 맵 ID 반환
// 기존 맵(1001~) 중 미사용 탐색 → 없으면 동적 생성 후 반환
public int GetOrCreateAvailableRaidMap()
{
// 기존 맵 중 미사용 탐색
foreach (int mapId in maps.Keys)
{
if (mapId >= 1001 && !useInstanceMaps.ContainsKey(mapId))
{
return mapId;
}
}
// 모두 사용 중 → 동적 생성
int newMapId = nextDynamicRaidMapId++;
BossInstance newMap = new(newMapId);
maps.Add(newMapId, newMap);
return newMapId;
}
// 레이드 맵 사용 시작 (진행중 목록에 등록)
public void AddInstanceMap(int mapId)
{
if (maps.TryGetValue(mapId, out AMap? map))
{
useInstanceMaps[mapId] = map;
}
}
// 레이드 맵 사용 종료 (진행중 목록에서 제거)
public void RemoveInstanceMap(int mapId)
{
useInstanceMaps.Remove(mapId);
}
// 파티매니저 가져옴
public PartyManager GetPartyManager()
{
return partyManager;
}
}