208 lines
5.4 KiB
C#
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;
|
|
}
|
|
}
|