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

110 lines
2.9 KiB
C#

using MMOserver.Game.Channel.Maps.ZoneData;
using MMOserver.Game.Engine;
namespace MMOserver.Game.Channel.Maps;
/*
* 게임 맵
* - 각 존 관리
* - 맵의 유저 관리
*/
public abstract class AMap : UserContainer
{
public abstract EnumMap GetMapType();
public abstract int GetMapId();
// 존 그리드 설정 (MapLoader에서 주입)
public int Rows { get; private set; }
public int Cols { get; private set; }
public int ZoneSize { get; private set; }
// 존 관리
private readonly Dictionary<int, Zone> zones = new();
public void SetZoneConfig(int rows, int cols, int zoneSize)
{
Rows = rows;
Cols = cols;
ZoneSize = zoneSize;
}
// 존 생성
public void CreateZones(List<ZoneConfigData> zoneConfigs)
{
foreach (ZoneConfigData config in zoneConfigs)
{
Vector3 position = new Vector3(config.CenterX, 0, config.CenterZ);
Vector3 size = new Vector3(ZoneSize, 0, ZoneSize);
Zone zone = new Zone(this, config.ZoneId, config.Row, config.Col, position, size);
AddZone(zone);
}
}
public void AddZone(Zone zone)
{
zones[zone.ZoneId] = zone;
}
public Zone? GetZone(int zoneId)
{
zones.TryGetValue(zoneId, out Zone? zone);
return zone;
}
// 현재 맵의 근처 존 가져오기
public virtual (int, int, int, int) GetNearZone(int zoneId, Vector3? position)
{
return (zoneId, -1, -1, -1);
}
// 좌상단/우상단/우하단/좌하단 판정
public int ZoneAt(int row, int col)
{
return (row >= 0 && row < Rows && col >= 0 && col < Cols) ? row * Cols + col : -1;
}
// 맵 입장 시 0번 존에 자동 배치
public override void AddUser(int userId, Player player)
{
base.AddUser(userId, player);
player.CurrentZoneId = 0;
GetZone(0)?.AddUser(userId, player);
}
// 맵 퇴장 시 현재 존에서 자동 제거
public override void RemoveUser(int userId)
{
if (users.TryGetValue(userId, out Player? player))
{
GetZone(player.CurrentZoneId)?.RemoveUser(userId);
}
base.RemoveUser(userId);
}
// 이동시 zone업데이트
public bool UpdatePlayerZone(int userId, Player player)
{
// 플레이어의 위치는 이동한 상태
int col = (int)(player.Position.X / ZoneSize);
int row = (int)(player.Position.Z / ZoneSize);
int newZoneId = ZoneAt(row, col);
if (newZoneId == player.CurrentZoneId)
{
return true;
}
// 범위 밖으로 이동한 상태 일단 존은 그대로 둔다.
if (newZoneId < 0)
{
return false;
}
GetZone(player.CurrentZoneId)?.RemoveUser(userId);
GetZone(newZoneId)!.AddUser(userId, player);
player.CurrentZoneId = newZoneId;
return true;
}
}