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 connectPeers = new(); // 채널 맵 관리 private readonly Dictionary maps = new(); // 진행중 채널 맵 관리 private readonly Dictionary 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 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 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; } }