초기커밋
This commit is contained in:
465
GameServer/Map/Grid.cs
Normal file
465
GameServer/Map/Grid.cs
Normal file
@@ -0,0 +1,465 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
|
||||
|
||||
using NeoSmart.AsyncLock;
|
||||
using Nettention.Proud;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
using SESSION_ID = System.Int32;
|
||||
using META_ID = System.UInt32;
|
||||
using ENTITY_GUID = System.String;
|
||||
using ANCHOR_GUID = System.String;
|
||||
using USER_GUID = System.String;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
/// <summary>
|
||||
/// Map Class 에서 사용
|
||||
/// </summary>
|
||||
public class AnchorInfo
|
||||
{
|
||||
public string AnchorGuid;
|
||||
public Pos AnchorPos;
|
||||
public AnchorProp AnchorProp;
|
||||
public string OccupyingUserGuid = string.Empty;
|
||||
public PropState PropState = PropState.None;
|
||||
public Timestamp respawnTime = new();
|
||||
|
||||
private AsyncLock m_lock = new();
|
||||
|
||||
public AnchorInfo(string anchorGuid, Pos pos, AnchorProp prop)
|
||||
{
|
||||
AnchorGuid = anchorGuid;
|
||||
AnchorPos = pos;
|
||||
AnchorProp = prop;
|
||||
}
|
||||
|
||||
public AsyncLock getAsyncLock() => m_lock;
|
||||
}
|
||||
|
||||
internal class Cell
|
||||
{
|
||||
/// <summary>
|
||||
/// Grid에서 Cell의 X 좌표
|
||||
/// </summary>
|
||||
int _cellinGridX;
|
||||
/// <summary>
|
||||
/// Grid에서 Cell의 Y 좌표
|
||||
/// </summary>
|
||||
int _cellinGridY;
|
||||
|
||||
ConcurrentDictionary<USER_GUID, Player> _players = new ConcurrentDictionary<string, Player>();
|
||||
|
||||
ConcurrentDictionary<ANCHOR_GUID, AnchorInfo> _anchors = new();
|
||||
ConcurrentDictionary<ENTITY_GUID, UgcNpc> _ugc_npcs = new();
|
||||
|
||||
List<AnchorInfo> _startPoints = new();
|
||||
StartPointType m_stat_point_type = StartPointType.None;
|
||||
public HostID _P2PGroup = HostID.HostID_None;
|
||||
|
||||
public Cell(int cellinGridX, int cellinGridY, StartPointType startPointType)
|
||||
{
|
||||
ByteArray byArray = new ByteArray();
|
||||
P2PGroupType p2PGroupType = new P2PGroupType();
|
||||
p2PGroupType.Type = 1;
|
||||
|
||||
ServerBase.ProudNetHelper.convertP2PGroupToByteArray(byArray, p2PGroupType);
|
||||
|
||||
HostID[] arrHostID = new HostID[0];
|
||||
|
||||
_P2PGroup = GameServerApp.getServerLogic().getProudNetListener().getNetServer().CreateP2PGroup(arrHostID, byArray);
|
||||
if (_P2PGroup == HostID.HostID_None)
|
||||
{
|
||||
Log.getLogger().error($"fail CreateP2PGroup");
|
||||
}
|
||||
|
||||
_cellinGridX = cellinGridX;
|
||||
_cellinGridY = cellinGridY;
|
||||
m_stat_point_type = startPointType;
|
||||
}
|
||||
|
||||
public void addPlayer(Player player)
|
||||
{
|
||||
_players.AddOrUpdate(player.getUserGuid(), player, (key, oldValue) => player);
|
||||
SendP2PGroup(player);
|
||||
}
|
||||
|
||||
public bool removePlayer(Player player)
|
||||
{
|
||||
return _players.TryRemove(player.getUserGuid(), out _);
|
||||
}
|
||||
|
||||
public void AddAnchor(AnchorInfo anchor)
|
||||
{
|
||||
_anchors.AddOrUpdate(anchor.AnchorGuid, anchor, (key, oldValue) => anchor);
|
||||
|
||||
if (MapHelper.isStartPoint(anchor.AnchorGuid, m_stat_point_type))
|
||||
{
|
||||
_startPoints.Add(anchor);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAnchor(AnchorInfo anchor)
|
||||
{
|
||||
_anchors.TryRemove(anchor.AnchorGuid, out _);
|
||||
}
|
||||
|
||||
public void addUgcNpc(UgcNpc ugcNpc)
|
||||
{
|
||||
_ugc_npcs.AddOrUpdate(ugcNpc.getEntityGuid(), ugcNpc, (key, oldValue) => ugcNpc);
|
||||
}
|
||||
|
||||
public bool removeUgcNpc(UgcNpc ugcNpc)
|
||||
{
|
||||
return _ugc_npcs.TryRemove(ugcNpc.getEntityGuid(), out _);
|
||||
}
|
||||
|
||||
public bool GetNearestStartPoint(Pos checkPos, out double nearestPoinstDistance, [MaybeNullWhen(false)] out Pos nearestPoint)
|
||||
{
|
||||
nearestPoinstDistance = -1;
|
||||
Pos? minPos = null;
|
||||
|
||||
foreach (var startPoint in _startPoints)
|
||||
{
|
||||
var distance = Math.Sqrt(Math.Pow(checkPos.X - startPoint.AnchorPos.X, 2) + Math.Pow(checkPos.Y - startPoint.AnchorPos.Y, 2));
|
||||
if (minPos == null || distance < nearestPoinstDistance)
|
||||
{
|
||||
nearestPoinstDistance = distance;
|
||||
minPos = startPoint.AnchorPos.Clone();
|
||||
}
|
||||
}
|
||||
|
||||
if (minPos == null)
|
||||
{
|
||||
nearestPoint = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
nearestPoint = minPos;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Broadcast(ClientToGame message)
|
||||
{
|
||||
HostID[] allClients = _players.Values.Select(x => x.getHostId()).ToArray();
|
||||
|
||||
GameServerApp.getServerLogic().onSendPacketToHosts(allClients, ServerCore.ProudNetHelper.compressRmi(), message);
|
||||
}
|
||||
|
||||
void SendP2PGroup(Player player)
|
||||
{
|
||||
ClientToGame clientToGame = new ClientToGame();
|
||||
clientToGame.Message = new ClientToGameMessage();
|
||||
clientToGame.Message.P2PGroupHostIdNoti = new ClientToGameMessage.Types.P2PGroupHostIdNoti();
|
||||
|
||||
clientToGame.Message.P2PGroupHostIdNoti.P2PGroupHostId = (int)_P2PGroup;
|
||||
|
||||
GameServerApp.getServerLogic().onSendPacket(player, clientToGame);
|
||||
}
|
||||
|
||||
public void CallFunc(Action<Player> action)
|
||||
{
|
||||
foreach (var player in _players.Values)
|
||||
{
|
||||
action(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void CallFunc(Action<UgcNpc> action)
|
||||
{
|
||||
foreach (var ugc_ppc in _ugc_npcs.Values)
|
||||
{
|
||||
action(ugc_ppc);
|
||||
}
|
||||
}
|
||||
|
||||
public void CallFunc(Action<AnchorInfo> action)
|
||||
{
|
||||
foreach (var anchor in _anchors.Values)
|
||||
{
|
||||
action(anchor);
|
||||
}
|
||||
}
|
||||
|
||||
public string toBasicString()
|
||||
{
|
||||
return $"Cell[CellInGridX:{_cellinGridX},CellInGridY:{_cellinGridY}]";
|
||||
}
|
||||
}
|
||||
|
||||
internal class Grid
|
||||
{
|
||||
Cell[,] _cells;
|
||||
/// <summary>
|
||||
/// Map에서 Grid의 X 좌표
|
||||
/// </summary>
|
||||
public int GridX { get; private set; }
|
||||
/// <summary>
|
||||
/// Map에서 Grid의 Y 좌표
|
||||
/// </summary>
|
||||
public int GridY { get; private set; }
|
||||
|
||||
readonly int _maxCellInGrid;
|
||||
|
||||
public Grid(int gridX, int gridY, bool isOneGrid, StartPointType startPointType)
|
||||
{
|
||||
if (isOneGrid)
|
||||
{
|
||||
_cells = new Cell[1, 1];
|
||||
_maxCellInGrid = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cells = new Cell[Map.MAX_CELLS_IN_GRID, Map.MAX_CELLS_IN_GRID];
|
||||
_maxCellInGrid = Map.MAX_CELLS_IN_GRID;
|
||||
}
|
||||
|
||||
GridX = gridX;
|
||||
GridY = gridY;
|
||||
|
||||
for (int cellinGridX = 0; cellinGridX < _cells.GetLength(0); cellinGridX++)
|
||||
{
|
||||
for (int cellinGridY = 0; cellinGridY < _cells.GetLength(1); cellinGridY++)
|
||||
{
|
||||
_cells[cellinGridX, cellinGridY] = new Cell(cellinGridX, cellinGridY, startPointType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Result tryAddPlayer(CellPos cellPos, Player player)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (cellPos.CellinGridX < 0 || cellPos.CellinGridX >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range X Grid Bounds !!! : 0 < {cellPos.CellinGridX} or {cellPos.CellinGridX} < {_maxCellInGrid} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (cellPos.CellinGridY < 0 || cellPos.CellinGridY >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range Y Grid Bounds !!! : 0 < {cellPos.CellinGridY} or {cellPos.CellinGridY} < {_maxCellInGrid} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var found_cell = GetCell(cellPos.CellinGridX, cellPos.CellinGridY);
|
||||
if (null == found_cell)
|
||||
{
|
||||
err_msg = $"Not found Cell !!! : {cellPos.toBasicString()} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridNotFoundCell, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
found_cell.addPlayer(player);
|
||||
|
||||
Log.getLogger().debug($"Player Enter in Cell Grid : {found_cell.toBasicString()}, {cellPos.toBasicString()} - {player.toBasicString()}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result tryRemovePlayer(CellPos cellPos, Player player)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (cellPos.CellinGridX < 0 || cellPos.CellinGridX >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range X Grid Bounds !!! : 0 < {cellPos.CellinGridX} or {cellPos.CellinGridX} < {_maxCellInGrid} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (cellPos.CellinGridY < 0 || cellPos.CellinGridY >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range Y Grid Bounds !!! : 0 < {cellPos.CellinGridY} or {cellPos.CellinGridY} < {_maxCellInGrid} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var found_cell = GetCell(cellPos.CellinGridX, cellPos.CellinGridY);
|
||||
if(null == found_cell)
|
||||
{
|
||||
err_msg = $"Not found Cell !!! : {cellPos.toBasicString()} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridNotFoundCell, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if(false == found_cell.removePlayer(player))
|
||||
{
|
||||
err_msg = $"Failed to RemovePlayer in Cell Grid !!! : {cellPos.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().warn(result.toBasicString());
|
||||
}
|
||||
|
||||
Log.getLogger().debug($"Player Leave in Cell Grid : {found_cell.toBasicString()}, {cellPos.toBasicString()} - {player.toBasicString()}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void AddAnchor(CellPos cellPos, AnchorInfo anchor)
|
||||
{
|
||||
if (cellPos.CellinGridX < 0 || cellPos.CellinGridX >= _maxCellInGrid)
|
||||
return;
|
||||
|
||||
if (cellPos.CellinGridY < 0 || cellPos.CellinGridY >= _maxCellInGrid)
|
||||
return;
|
||||
|
||||
GetCell(cellPos.CellinGridX, cellPos.CellinGridY)?.AddAnchor(anchor);
|
||||
}
|
||||
|
||||
public void RemoveAnchor(CellPos cellPos, AnchorInfo anchor)
|
||||
{
|
||||
if (cellPos.CellinGridX < 0 || cellPos.CellinGridX >= _maxCellInGrid)
|
||||
return;
|
||||
|
||||
if (cellPos.CellinGridY < 0 || cellPos.CellinGridY >= _maxCellInGrid)
|
||||
return;
|
||||
|
||||
GetCell(cellPos.CellinGridX, cellPos.CellinGridY)?.RemoveAnchor(anchor);
|
||||
}
|
||||
|
||||
public Result addUgcNpc(CellPos cellPos, UgcNpc ugcNpc)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (cellPos.CellinGridX < 0 || cellPos.CellinGridX >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range X Grid Bounds !!! : 0 < {cellPos.CellinGridX} or {cellPos.CellinGridX} < {_maxCellInGrid} - {ugcNpc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (cellPos.CellinGridY < 0 || cellPos.CellinGridY >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range Y Grid Bounds !!! : 0 < {cellPos.CellinGridY} or {cellPos.CellinGridY} < {_maxCellInGrid} - {ugcNpc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var found_cell = GetCell(cellPos.CellinGridX, cellPos.CellinGridY);
|
||||
if (null == found_cell)
|
||||
{
|
||||
err_msg = $"Not found Cell !!! : {cellPos.toBasicString()} - {ugcNpc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridNotFoundCell, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
found_cell.addUgcNpc(ugcNpc);
|
||||
|
||||
Log.getLogger().debug($"UgcNpc Enter in Cell Grid : {found_cell.toBasicString()}, {cellPos.toBasicString()} - {ugcNpc.toBasicString()}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result removeUgcNpc(CellPos cellPos, UgcNpc ugcNpc)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (cellPos.CellinGridX < 0 || cellPos.CellinGridX >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range X Grid Bounds !!! : 0 < {cellPos.CellinGridX} or {cellPos.CellinGridX} < {_maxCellInGrid} - {ugcNpc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (cellPos.CellinGridY < 0 || cellPos.CellinGridY >= _maxCellInGrid)
|
||||
{
|
||||
err_msg = $"Position Out of Range Y Grid Bounds !!! : 0 < {cellPos.CellinGridY} or {cellPos.CellinGridY} < {_maxCellInGrid} - {ugcNpc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridBoundOutOfRange, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var found_cell = GetCell(cellPos.CellinGridX, cellPos.CellinGridY);
|
||||
if (null == found_cell)
|
||||
{
|
||||
err_msg = $"Not found Cell !!! : {cellPos.toBasicString()} - {ugcNpc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridNotFoundCell, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (false == found_cell.removeUgcNpc(ugcNpc))
|
||||
{
|
||||
err_msg = $"Failed to RemovePlayer in Cell Grid !!! : {cellPos.toBasicString()} - {ugcNpc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapGridCellNotFoundPlayer, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Log.getLogger().debug($"UgcNpc Leave in Cell Grid : {found_cell.toBasicString()}, {cellPos.toBasicString()} - {ugcNpc.toBasicString()}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public Cell? GetCell(int cellinGridX, int cellinGridY)
|
||||
{
|
||||
if (cellinGridX < 0 || cellinGridX >= _maxCellInGrid)
|
||||
return null;
|
||||
|
||||
if (cellinGridY < 0 || cellinGridY >= _maxCellInGrid)
|
||||
return null;
|
||||
|
||||
return _cells[cellinGridX, cellinGridY];
|
||||
}
|
||||
|
||||
public void DestroyP2PGroup()
|
||||
{
|
||||
foreach(var cell in _cells)
|
||||
{
|
||||
GameServerApp.getServerLogic().getProudNetListener().getNetServer()?.DestroyP2PGroup(cell._P2PGroup);
|
||||
}
|
||||
}
|
||||
|
||||
//instance 내 p2p host 설정을 위한 groupId 가져오는 함수
|
||||
public HostID getP2PGroupId()
|
||||
{
|
||||
foreach(var cell in _cells)
|
||||
{
|
||||
return cell._P2PGroup;
|
||||
}
|
||||
|
||||
Log.getLogger().error("cell._P2PGroup is not exist!!!!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
663
GameServer/Map/Helper/MapHelper.cs
Normal file
663
GameServer/Map/Helper/MapHelper.cs
Normal file
@@ -0,0 +1,663 @@
|
||||
using System.Numerics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public static class MapHelper
|
||||
{
|
||||
public static bool isStartPoint(string anchorGuid, StartPointType startPointType)
|
||||
{
|
||||
if (!MapManager.Instance.getParentMapFileName(anchorGuid, out var parentMapFileName))
|
||||
return false;
|
||||
|
||||
if (!MapDataTable.Instance.getMapData(parentMapFileName, out var mapData))
|
||||
return false;
|
||||
|
||||
if (!MapDataTable.Instance.getAnchor(anchorGuid, out var anchor))
|
||||
return false;
|
||||
|
||||
if (anchor.Type != "AT_StartPos")
|
||||
return false;
|
||||
|
||||
switch (startPointType)
|
||||
{
|
||||
case StartPointType.WorldAccountStartPoint:
|
||||
{
|
||||
if (mapData.MapFileType != MapFileType.World)
|
||||
return false;
|
||||
|
||||
if (!anchor.EditorName.Contains("AccountStartPos"))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StartPointType.WorldContinuedStartPoint:
|
||||
{
|
||||
if (mapData.MapFileType != MapFileType.World)
|
||||
return false;
|
||||
|
||||
if (!anchor.EditorName.Contains("ContinuedStartPos"))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StartPointType.LandStartPoint:
|
||||
{
|
||||
if (mapData.MapFileType != MapFileType.Land)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StartPointType.BuildingStartPoint:
|
||||
{
|
||||
if (mapData.MapFileType != MapFileType.Building)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static MapFileType getMapFileType(string mapFileName)
|
||||
{
|
||||
MapFileType return_value = MapFileType.None;
|
||||
|
||||
switch (Path.GetExtension(mapFileName))
|
||||
{
|
||||
case ".zone":
|
||||
return_value = MapFileType.World;
|
||||
break;
|
||||
case ".land":
|
||||
return_value = MapFileType.Land;
|
||||
break;
|
||||
case ".build":
|
||||
return_value = MapFileType.Building;
|
||||
break;
|
||||
case ".room":
|
||||
return_value = MapFileType.Instance;
|
||||
break;
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
public static bool isUsableAnchorInMapFileType(string anchorGuid, MapFileType mapFileType)
|
||||
{
|
||||
if (false == MapDataTable.Instance.getAnchor(anchorGuid, out var anchor))
|
||||
{
|
||||
var err_msg = $"Not found Anchor in MapFileType !!! : anchourGuid:{anchorGuid} - MapFileType:{mapFileType}";
|
||||
Log.getLogger(err_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return anchor.isUsableAnchorInMapFileType(mapFileType);
|
||||
}
|
||||
|
||||
public static bool isUsableAnchorInMapFileType(this Anchor anchor, MapFileType mapFileType)
|
||||
{
|
||||
if (true == anchor.isFarmingProp())
|
||||
{
|
||||
if (MapFileType.Instance == mapFileType || MapFileType.World == mapFileType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var err_msg = $"Not usable in MapFileType !!! : anchorType:{anchor.Type}, anchourGuid:{anchor.GUID} - MapFileType:{mapFileType}";
|
||||
Log.getLogger(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static bool isRewardProp(string anchorGuid)
|
||||
{
|
||||
if (!MapDataTable.Instance.getAnchor(anchorGuid, out var anchor))
|
||||
return false;
|
||||
|
||||
return anchor.isRewardProp();
|
||||
}
|
||||
|
||||
public static bool isRewardProp(this Anchor anchor)
|
||||
{
|
||||
return isAnchorTypeRewardPorp(anchor.Type);
|
||||
}
|
||||
|
||||
public static bool isRewardProp(this UgcAnchorInfo anchor)
|
||||
{
|
||||
|
||||
return isAnchorTypeRewardPorp(anchor.AnchorType);
|
||||
}
|
||||
|
||||
static bool isAnchorTypeRewardPorp(string anchorType)
|
||||
{
|
||||
return (anchorType == "AT_TreasureBox");
|
||||
}
|
||||
|
||||
public static bool isFarmingProp(string anchorGuid)
|
||||
{
|
||||
if (!MapDataTable.Instance.getAnchor(anchorGuid, out var anchor))
|
||||
return false;
|
||||
|
||||
return anchor.isFarmingProp();
|
||||
}
|
||||
|
||||
public static bool isFarmingProp(this Anchor anchor)
|
||||
{
|
||||
return isAnchorTypeFarming(anchor.Type);
|
||||
}
|
||||
|
||||
static bool isAnchorTypeFarming(string anchorType)
|
||||
{
|
||||
return (anchorType == "AT_Farming");
|
||||
}
|
||||
|
||||
public static bool isGroupProp(string anchorGuid)
|
||||
{
|
||||
if (!MapDataTable.Instance.getAnchor(anchorGuid, out var anchor))
|
||||
return false;
|
||||
|
||||
return anchor.isGroupProp();
|
||||
}
|
||||
|
||||
public static bool isGroupProp(this Anchor anchor)
|
||||
{
|
||||
return isAnchorTypeGroupProp(anchor.Type);
|
||||
}
|
||||
|
||||
public static bool isGroupProp(this UgcAnchorInfo anchor)
|
||||
{
|
||||
return isAnchorTypeGroupProp(anchor.AnchorType);
|
||||
}
|
||||
|
||||
static bool isAnchorTypeGroupProp(string anchorType)
|
||||
{
|
||||
return (anchorType == "AT_TreasureGroupBox");
|
||||
}
|
||||
|
||||
public static bool isNpcProp(string anchorGuid)
|
||||
{
|
||||
if (!MapDataTable.Instance.getAnchor(anchorGuid, out var anchor))
|
||||
return false;
|
||||
|
||||
return anchor.isNpcProp();
|
||||
}
|
||||
|
||||
public static bool isNpcProp(this Anchor anchor)
|
||||
{
|
||||
return isAnchorTypeNpcProp(anchor.Type);
|
||||
}
|
||||
|
||||
public static bool isNpcProp(this UgcAnchorInfo anchor)
|
||||
{
|
||||
return isAnchorTypeNpcProp(anchor.AnchorType);
|
||||
}
|
||||
|
||||
static bool isAnchorTypeNpcProp(string anchorType)
|
||||
{
|
||||
return (anchorType == "AT_Npc");
|
||||
}
|
||||
|
||||
public static bool isProp(this UgcAnchorInfo anchor)
|
||||
{
|
||||
return isAnchorTypeProp(anchor.AnchorType);
|
||||
}
|
||||
|
||||
static bool isAnchorTypeProp(string anchorType)
|
||||
{
|
||||
return (anchorType == "AT_Prop");
|
||||
}
|
||||
|
||||
public static bool isCrafterProp(this UgcAnchorInfo anchor)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (!isAnchorTypeProp(anchor.AnchorType))
|
||||
return false;
|
||||
|
||||
if (!MetaData.Instance._InteriorMetaTable.TryGetValue(anchor.TableId, out var interior_meta_data))
|
||||
{
|
||||
err_msg = $"Failed to TryGetValue() !!! : interiorMetaId:{anchor.TableId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MetaData.Instance._ItemTable.TryGetValue(anchor.TableId, out var item_meta_data))
|
||||
{
|
||||
err_msg = $"Failed to TryGetValue() !!! : itemMetaId:{anchor.TableId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return item_meta_data.isCrafterItem();
|
||||
}
|
||||
|
||||
public static (Result, RoomMapTree?, AddressBusinessLog?) tryGetRoomMapTree(int landMetaId, int floor, int buildingMetaId = 0)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (!MapManager.Instance.GetLandMapTree(landMetaId, out var landMapTree))
|
||||
{
|
||||
err_msg = $"Failed to GetLandMapTree() !!! : LandMetaId:{landMetaId}";
|
||||
result.setFail(ServerErrorCode.LandMapTreeDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
var buildingMapTree = landMapTree.ChildBuildingMapTree;
|
||||
if (buildingMapTree == null)
|
||||
{
|
||||
err_msg = $"Not Exist LandMapTree ChildBuilding !!! : LandMap:{landMapTree.LandMapFileName}";
|
||||
result.setFail(ServerErrorCode.LandMapTreeChildBuildingNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
if (buildingMetaId != 0 && buildingMetaId != buildingMapTree.BuildingMetaId)
|
||||
{
|
||||
err_msg = $"Not Match LandMap ChildBuilding !!! : ChildBuildingMetaId:{buildingMapTree.BuildingMetaId}, inputBuildingMetaId:{buildingMetaId}";
|
||||
result.setFail(ServerErrorCode.LandMapTreeChildBuildingNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
if (!buildingMapTree.ChildRoomMapTrees.TryGetValue(floor, out var roomMapTree))
|
||||
{
|
||||
err_msg = $"Failed to BuildingMapTree.ChildRoomMaps.TryGetValue() !!! : BuildingMap:{buildingMapTree.BuildingMapFileName}, floor:{floor}";
|
||||
result.setFail(ServerErrorCode.WorldMapTreeChildLandNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return (result, null, null);
|
||||
}
|
||||
|
||||
var world_meta_id = landMapTree.ParentWorldMapTree.WorldMetaId;
|
||||
var building_meta_id = buildingMetaId == 0 ? buildingMapTree.BuildingMetaId : buildingMetaId;
|
||||
var instance_meta_id = roomMapTree.InstanceMetaId;
|
||||
var myhome_guid = roomMapTree.MyhomeGuid;
|
||||
var owner_guid = roomMapTree.OwnerGuid;
|
||||
|
||||
var address_log_info = AddressBusinessLogHelper.toAddressLogInfo(world_meta_id, landMetaId, building_meta_id, floor, instance_meta_id, myhome_guid, owner_guid);
|
||||
var address_business_log = new AddressBusinessLog(address_log_info);
|
||||
|
||||
return (result, roomMapTree, address_business_log);
|
||||
}
|
||||
|
||||
public static Pos getWarpPos(ContentsType contentsType)
|
||||
{
|
||||
return getWarpPos(contentsType.toPlaceType());
|
||||
}
|
||||
|
||||
public static Pos getWarpPos(EPlaceType placeType)
|
||||
{
|
||||
var warp_pos = new Pos();
|
||||
|
||||
switch (placeType)
|
||||
{
|
||||
case EPlaceType.MyHome:
|
||||
warp_pos = getWarpPos(WarpType.MYHOME);
|
||||
break;
|
||||
case EPlaceType.DressRoom:
|
||||
warp_pos = getWarpPos(WarpType.FITTINGROOM);
|
||||
break;
|
||||
case EPlaceType.EditRoom:
|
||||
warp_pos = getWarpPos(WarpType.EDITROOM);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return warp_pos;
|
||||
}
|
||||
|
||||
public static Pos getWarpPos(WarpType warpType)
|
||||
{
|
||||
var warp_pos = new Pos();
|
||||
|
||||
switch (warpType)
|
||||
{
|
||||
case WarpType.MYHOME:
|
||||
{
|
||||
if (MetaData.Instance._WarpTable.TryGetValue(ServerCommon.Constant.MYHOME_WARP_ID, out var warpData))
|
||||
{
|
||||
warp_pos.X = warpData.PositionX;
|
||||
warp_pos.Y = warpData.PositionY;
|
||||
warp_pos.Z = warpData.PositionZ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WarpType.FITTINGROOM:
|
||||
{
|
||||
if (MetaData.Instance._WarpTable.TryGetValue(ServerCommon.Constant.DRESSROOM_WARP_ID, out var warpData))
|
||||
{
|
||||
warp_pos.X = warpData.PositionX;
|
||||
warp_pos.Y = warpData.PositionY;
|
||||
warp_pos.Z = warpData.PositionZ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WarpType.EDITROOM:
|
||||
{
|
||||
if (MetaData.Instance._WarpTable.TryGetValue(ServerCommon.Constant.EDITROOM_WARP_ID, out var warpData))
|
||||
{
|
||||
warp_pos.X = warpData.PositionX;
|
||||
warp_pos.Y = warpData.PositionY;
|
||||
warp_pos.Z = warpData.PositionZ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return warp_pos;
|
||||
}
|
||||
|
||||
public static Pos getMyhomeStartPos(Position myhomeStartPosAnchorPosition)
|
||||
{
|
||||
var myhome_start_pos_anchor_pos = myhomeStartPosAnchorPosition.toPos();
|
||||
var myhome_warp_pos = getWarpPos(ContentsType.MyHome);
|
||||
|
||||
var myhome_start_pos = new Pos();
|
||||
|
||||
myhome_start_pos.X = myhome_warp_pos.X + myhome_start_pos_anchor_pos.X;
|
||||
myhome_start_pos.Y = myhome_warp_pos.Y + myhome_start_pos_anchor_pos.Y;
|
||||
myhome_start_pos.Z = myhome_warp_pos.Z + myhome_start_pos_anchor_pos.Z;
|
||||
|
||||
return myhome_start_pos;
|
||||
}
|
||||
|
||||
public static Pos getWorldPosFromMyhomeRelativePos(Pos myhomeRelativePos)
|
||||
{
|
||||
var myhome_warp_pos = getWarpPos(ContentsType.MyHome);
|
||||
|
||||
var world_pos = new Pos();
|
||||
|
||||
world_pos.X = myhome_warp_pos.X + myhomeRelativePos.X;
|
||||
world_pos.Y = myhome_warp_pos.Y + myhomeRelativePos.Y;
|
||||
world_pos.Z = myhome_warp_pos.Z + myhomeRelativePos.Z;
|
||||
|
||||
return world_pos;
|
||||
}
|
||||
|
||||
public static Pos getWorldPosFromMyhomeRelativePos(Coordinate myhomeRelativePos)
|
||||
{
|
||||
var myhome_relative_pos = new Pos
|
||||
{
|
||||
X = myhomeRelativePos.X,
|
||||
Y = myhomeRelativePos.Y,
|
||||
Z = myhomeRelativePos.Z,
|
||||
};
|
||||
|
||||
return getWorldPosFromMyhomeRelativePos(myhome_relative_pos);
|
||||
}
|
||||
|
||||
public static (Result, Pos) getWorldPosFromRoomRelativePos(RoomMapTree roomMapTree, Pos roomRelativePos)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var world_pos = new Pos();
|
||||
|
||||
var building_map_tree = roomMapTree.ParentBuildingMapTree;
|
||||
var land_map_tree = building_map_tree.ParentLandMapTree;
|
||||
|
||||
var room_map_file_name = roomMapTree.RoomMapFileName;
|
||||
var building_map_file_name = building_map_tree.BuildingMapFileName;
|
||||
var land_map_file_name = land_map_tree.LandMapFileName;
|
||||
|
||||
if (!MapDataTable.Instance.getMapData(land_map_file_name, out var land_map_data))
|
||||
{
|
||||
err_msg = $"Not Exist MapData !!! : fileName:{land_map_file_name}";
|
||||
result.setFail(ServerErrorCode.LandMapDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, world_pos);
|
||||
}
|
||||
|
||||
Position? building_position = null;
|
||||
foreach (var building_data in land_map_data.BuildingDatas)
|
||||
{
|
||||
var building_file_name = Path.GetFileName(building_data.BuildingName);
|
||||
if (building_file_name == building_map_file_name)
|
||||
{
|
||||
building_position = building_data.Position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (building_position == null)
|
||||
{
|
||||
err_msg = $"Not Found Building Position !!! : landFileName:{land_map_file_name}, buildingFileName:{building_map_file_name}";
|
||||
result.setFail(ServerErrorCode.BuildingMapDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, world_pos);
|
||||
}
|
||||
|
||||
if (!MapDataTable.Instance.getMapData(building_map_file_name, out var building_map_data))
|
||||
{
|
||||
err_msg = $"Not Exist MapData !!! : fileName:{building_map_file_name} or CHECK BuildingData.xlsx";
|
||||
result.setFail(ServerErrorCode.BuildingMapDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, world_pos);
|
||||
}
|
||||
|
||||
Position? room_position = null;
|
||||
foreach (var room_data in building_map_data.RoomDatas)
|
||||
{
|
||||
var room_file_name = Path.GetFileName(room_data.RoomName);
|
||||
if (room_file_name == room_map_file_name)
|
||||
{
|
||||
room_position = room_data.Position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (room_position == null)
|
||||
{
|
||||
err_msg = $"Not Found Building Position !!! : buildingFileName:{building_map_file_name}, roomFileName:{room_map_file_name}";
|
||||
result.setFail(ServerErrorCode.RoomMapDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, world_pos);
|
||||
}
|
||||
|
||||
if (!MapDataTable.Instance.getMapData(room_map_file_name, out var room_map_data))
|
||||
{
|
||||
err_msg = $"Not Exist MapData !!! : fileName:{room_map_file_name} or CHECK InstanceData.xlsx";
|
||||
result.setFail(ServerErrorCode.RoomMapDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, world_pos);
|
||||
}
|
||||
|
||||
var world_position = roomRelativePos.toPosition();
|
||||
|
||||
world_position = TransformHelper.rotate(world_position, room_map_data.Rotation);
|
||||
|
||||
world_position.X += room_position.X;
|
||||
world_position.Y += room_position.Y;
|
||||
world_position.Z += room_position.Z;
|
||||
|
||||
world_position = TransformHelper.rotate(world_position, building_map_data.Rotation);
|
||||
|
||||
world_position.X += building_position.X;
|
||||
world_position.Y += building_position.Y;
|
||||
world_position.Z += building_position.Z;
|
||||
|
||||
world_position = TransformHelper.rotate(world_position, land_map_data.Rotation);
|
||||
|
||||
world_position.X += land_map_data.Position.X;
|
||||
world_position.Y += land_map_data.Position.Y;
|
||||
world_position.Z += land_map_data.Position.Z;
|
||||
|
||||
world_pos = world_position.toPos();
|
||||
|
||||
return (result, world_pos);
|
||||
}
|
||||
|
||||
public static Position toPosition(this Pos pos)
|
||||
{
|
||||
var position = new Position
|
||||
{
|
||||
X = pos.X,
|
||||
Y = pos.Y,
|
||||
Z = pos.Z
|
||||
};
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
public static Pos toPos(this Position position)
|
||||
{
|
||||
Pos pos = new()
|
||||
{
|
||||
X = (float)position.X,
|
||||
Y = (float)position.Y,
|
||||
Z = (float)position.Z
|
||||
};
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
public static (Result, Map?) getCurrMapOfMaster(this EntityBase owner)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var master = owner.onGetMasterEntity();
|
||||
if (null == master)
|
||||
{
|
||||
err_msg = $"Not found Master !!! - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
var master_game_zone_action = master.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(master_game_zone_action, () => $"master_game_zone_action is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var curr_map = master_game_zone_action.getLinkedToMap();
|
||||
if (null == curr_map)
|
||||
{
|
||||
err_msg = $"Not found Map !!! - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MapIsNull, err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
return (result, curr_map);
|
||||
}
|
||||
|
||||
public static bool getAnchor(string anchorGuid, [MaybeNullWhen(false)] out Anchor anchor)
|
||||
{
|
||||
anchor = null;
|
||||
|
||||
if (false == MapDataTable.Instance.getAnchor(anchorGuid, out var found_anchor))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
anchor = found_anchor;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ModifyFloorLinkedInfo makeModifyFloorLinkedInfo(ModifyType modifyType, int landMetaId, int buildingMetaId, int floor, List<string> ugcNpcGuids)
|
||||
{
|
||||
var modify_floor_linked_info = new ModifyFloorLinkedInfo();
|
||||
|
||||
modify_floor_linked_info.ModifyType = modifyType;
|
||||
modify_floor_linked_info.LandId = landMetaId;
|
||||
modify_floor_linked_info.BuildingId = buildingMetaId;
|
||||
modify_floor_linked_info.Floor = floor;
|
||||
modify_floor_linked_info.FloorLinkedInfo = new FloorLinkedInfo();
|
||||
modify_floor_linked_info.FloorLinkedInfo.UgcNpcGuids.AddRange(ugcNpcGuids);
|
||||
|
||||
return modify_floor_linked_info;
|
||||
}
|
||||
|
||||
public static RoomMapTree makeRoomMapTree(BuildingMapTree buildingMapTree, int instanceMetaId, RentFloorRequestInfo rentFloorRequestInfo, List<string> ugcNpcGuids)
|
||||
{
|
||||
var room_map_tree = new RoomMapTree(instanceMetaId, rentFloorRequestInfo.MyhomeGuid, buildingMapTree);
|
||||
|
||||
room_map_tree.OwnerGuid = rentFloorRequestInfo.OwnerGuid;
|
||||
room_map_tree.MyhomeGuid = rentFloorRequestInfo.MyhomeGuid;
|
||||
room_map_tree.InstanceName = rentFloorRequestInfo.InstanceName;
|
||||
room_map_tree.ThumbnailImageId = rentFloorRequestInfo.ThumbnailImageId;
|
||||
room_map_tree.ListImageId = rentFloorRequestInfo.ListImageId;
|
||||
room_map_tree.EnterPlayerCount = rentFloorRequestInfo.EnterPlayerCount;
|
||||
room_map_tree.UgcNpcs.AddRange(ugcNpcGuids);
|
||||
|
||||
return room_map_tree;
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// X축,Y축,Z축에 대한 회전을 순차적으로 적용하는 함수 - kangms
|
||||
//=========================================================================================
|
||||
public static Vector3 applyRotation(System.Numerics.Vector3 vector, System.Numerics.Vector3 rotation)
|
||||
{
|
||||
// X축 회전
|
||||
Quaternion rotationX = Quaternion.CreateFromAxisAngle(Vector3.UnitX, MathF.PI / 180 * rotation.X);
|
||||
vector = Vector3.Transform(vector, rotationX);
|
||||
|
||||
// Y축 회전
|
||||
Quaternion rotationY = Quaternion.CreateFromAxisAngle(Vector3.UnitY, MathF.PI / 180 * rotation.Y);
|
||||
vector = Vector3.Transform(vector, rotationY);
|
||||
|
||||
// Z축 회전
|
||||
Quaternion rotationZ = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, MathF.PI / 180 * rotation.Z);
|
||||
vector = Vector3.Transform(vector, rotationZ);
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// X축,Y축,Z축에 대한 회전을 순차적으로 적용하는 함수 - kangms
|
||||
//=========================================================================================
|
||||
public static Vector3 applyRotationFromYawPitchRoll(System.Numerics.Vector3 vector, float yaw, float pitch, float roll)
|
||||
{
|
||||
float yaw_rad = yaw * MathHelper.Deg2Rad;
|
||||
float pitch_rad = pitch * MathHelper.Deg2Rad;
|
||||
float roll_rad = roll * MathHelper.Deg2Rad;
|
||||
|
||||
Quaternion rotation = Quaternion.CreateFromYawPitchRoll(yaw_rad, pitch_rad, roll_rad);
|
||||
vector = Vector3.Transform(vector, rotation);
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
// Z축 회전된 벡터를 각도로 반환 해주는 함수 - kangms
|
||||
//=========================================================================================
|
||||
public static float getZRotationAngle(Vector3 vector)
|
||||
{
|
||||
// atan2 함수 사용하여 Z축 회전 각도 계산 (라디안 -> 도)
|
||||
float angleInRadians = MathF.Atan2(vector.Y, vector.X);
|
||||
float angleInDegrees = angleInRadians * (180 / MathF.PI);
|
||||
|
||||
return angleInDegrees;
|
||||
}
|
||||
|
||||
public static Vector3 toUnrealCoordinateVector(System.Numerics.Vector3 vector)
|
||||
{
|
||||
var unreal_vector = new Vector3();
|
||||
unreal_vector.Y = vector.X;
|
||||
unreal_vector.Z = vector.Y;
|
||||
unreal_vector.X = vector.Z;
|
||||
|
||||
return unreal_vector;
|
||||
}
|
||||
}
|
||||
157
GameServer/Map/Helper/MapNotifyHelper.cs
Normal file
157
GameServer/Map/Helper/MapNotifyHelper.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static ClientToGameMessage.Types;
|
||||
using static ServerMessage.Types;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
internal static class MapNotifyHelper
|
||||
{
|
||||
public static bool send_S2C_NTF_MAP_LINKED_INFOS(this Player player)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ntf_packet = new ClientToGame();
|
||||
ntf_packet.Message = new ClientToGameMessage();
|
||||
ntf_packet.Message.NtfMapLinkedInfos = new GS2C_NTF_MAP_LINKED_INFOS();
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
if (server_logic.getServerType().toServerType() == ServerType.Channel)
|
||||
{
|
||||
var world_meta_id = server_logic.getMap().MapMId;
|
||||
|
||||
if (!MetaData.Instance._WorldMetaTable.TryGetValue(world_meta_id, out var world_meta_data))
|
||||
{
|
||||
err_msg = $"Failed to MetaData.TryGetValue() !!! : worldMetaId:{world_meta_id} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.WorldMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MapManager.Instance.GetWorldMapTree(world_meta_data.MapPath, out var world_map_tree))
|
||||
{
|
||||
err_msg = $"Failed to GetWorldMapTree() !!! : MapPath:{world_meta_data.MapPath} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.WorldMapTreeDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var land_map_tree in world_map_tree.ChildLandMapTrees.Values)
|
||||
{
|
||||
if (!MetaData.Instance._LandTable.TryGetValue(land_map_tree.LandId, out var land_meta_data))
|
||||
{
|
||||
err_msg = $"Failed to MetaData.TryGetValue() !!! : landMetaId:{land_map_tree.LandId} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.LandMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (land_meta_data.LandType != MetaAssets.LandType.RENTAL)
|
||||
continue;
|
||||
|
||||
var building_map_tree = land_map_tree.ChildBuildingMapTree;
|
||||
if (building_map_tree == null)
|
||||
continue;
|
||||
|
||||
if (!MetaData.Instance._BuildingTable.TryGetValue(building_map_tree.BuildingMetaId, out var building_meta_data))
|
||||
{
|
||||
err_msg = $"Failed to MetaData.TryGetValue() !!! : buildingMetaId:{building_map_tree.BuildingMetaId} - {player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.BuildingMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var land_linked_info = new LandLinkedInfo();
|
||||
land_linked_info.LandId = land_map_tree.LandId;
|
||||
|
||||
foreach (var (floor, room_map_tree) in building_map_tree.ChildRoomMapTrees)
|
||||
{
|
||||
var floor_linked_info = new FloorLinkedInfo();
|
||||
floor_linked_info.UgcNpcGuids.AddRange(room_map_tree.UgcNpcs);
|
||||
|
||||
land_linked_info.FloorLinkedInfos.TryAdd(floor, floor_linked_info);
|
||||
}
|
||||
|
||||
ntf_packet.Message.NtfMapLinkedInfos.LandLinkedInfos.Add(land_linked_info);
|
||||
}
|
||||
}
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ntf_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool broadcast_S2C_NTF_MODIFY_FLOOR_LINKED_INFOS(List<ModifyFloorLinkedInfo> modifyFloorLinkedInfos)
|
||||
{
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var users = server_logic.getPlayerManager().getUsers();
|
||||
var players = users.Values.ToArray();
|
||||
|
||||
if (players.Length == 0)
|
||||
return true;
|
||||
|
||||
if (modifyFloorLinkedInfos.Count < 1)
|
||||
return true;
|
||||
|
||||
var ntf_packet = new ClientToGame();
|
||||
ntf_packet.Message = new ClientToGameMessage();
|
||||
ntf_packet.Message.NtfModifyFloorLinkedInfos = new GS2C_NTF_MODIFY_FLOOR_LINKED_INFOS();
|
||||
|
||||
ntf_packet.Message.NtfModifyFloorLinkedInfos.ModifyFloorLinkedInfos.AddRange(modifyFloorLinkedInfos);
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(players, ntf_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool send_GS2GS_NTF_MODIFY_FLOOR_LINKED_INFOS(List<ModifyFloorLinkedInfo> modifyFloorLinkedInfos)
|
||||
{
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
if (modifyFloorLinkedInfos.Count < 1)
|
||||
return true;
|
||||
|
||||
var message = new ServerMessage();
|
||||
message.NtfModifyFloorLinkedInfos = new GS2GS_NTF_MODIFY_FLOOR_LINKED_INFOS();
|
||||
|
||||
message.NtfModifyFloorLinkedInfos.ExceptServerName = server_logic.getServerName();
|
||||
message.NtfModifyFloorLinkedInfos.ModifyFloorLinkedInfos.AddRange(modifyFloorLinkedInfos);
|
||||
|
||||
var rabbit_mq = server_logic.getRabbitMqConnector() as RabbitMQ4Game;
|
||||
NullReferenceCheckHelper.throwIfNull(rabbit_mq, () => $"rabbit_mq is null !!!");
|
||||
|
||||
rabbit_mq.sendMessageToExchangeAllGame(message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool sendNtfModifyFloorLinkedInfos(List<ModifyFloorLinkedInfo> modifyFloorLinkedInfos)
|
||||
{
|
||||
// 현재 서버 유저
|
||||
broadcast_S2C_NTF_MODIFY_FLOOR_LINKED_INFOS(modifyFloorLinkedInfos);
|
||||
|
||||
// 다른 서버
|
||||
send_GS2GS_NTF_MODIFY_FLOOR_LINKED_INFOS(modifyFloorLinkedInfos);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
1864
GameServer/Map/Map.cs
Normal file
1864
GameServer/Map/Map.cs
Normal file
File diff suppressed because it is too large
Load Diff
938
GameServer/Map/MapManager.cs
Normal file
938
GameServer/Map/MapManager.cs
Normal file
@@ -0,0 +1,938 @@
|
||||
using Amazon.Runtime.Internal;
|
||||
using Amazon.Runtime.Internal.Transform;
|
||||
using GameServer;
|
||||
using Newtonsoft.Json;
|
||||
using NLog.LayoutRenderers;
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static ClientToGameReq.Types;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class WorldMapTree
|
||||
{
|
||||
public int WorldMetaId { get; }
|
||||
public string WorldMapFileName { get; }
|
||||
|
||||
public Dictionary<int, LandMapTree> ChildLandMapTrees = new();
|
||||
public Dictionary<string, AnchorTree> Anchors = new();
|
||||
|
||||
public WorldMapTree(int worldMetaId, string worldMapFileName)
|
||||
{
|
||||
WorldMetaId = worldMetaId;
|
||||
WorldMapFileName = worldMapFileName;
|
||||
}
|
||||
}
|
||||
|
||||
public class LandMapTree
|
||||
{
|
||||
public int LandId { get; }
|
||||
public string LandMapFileName { get; }
|
||||
public WorldMapTree ParentWorldMapTree { get; }
|
||||
|
||||
public BuildingMapTree? ChildBuildingMapTree;
|
||||
public Dictionary<string, AnchorTree> Anchors = new();
|
||||
|
||||
public LandMapTree(int landMetaId, string landMapFileName, WorldMapTree parentWorldMapTree)
|
||||
{
|
||||
LandId = landMetaId;
|
||||
LandMapFileName = landMapFileName;
|
||||
ParentWorldMapTree = parentWorldMapTree;
|
||||
}
|
||||
}
|
||||
|
||||
public class BuildingMapTree
|
||||
{
|
||||
public int BuildingMetaId { get; }
|
||||
public string BuildingMapFileName { get; }
|
||||
public LandMapTree ParentLandMapTree { get; }
|
||||
|
||||
public Dictionary<int, RoomMapTree> ChildRoomMapTrees = new();
|
||||
public Dictionary<string, AnchorTree> Anchors = new();
|
||||
|
||||
public BuildingMapTree(int buildingMetaId, string buildingMapFileName, LandMapTree parentLandMapTree)
|
||||
{
|
||||
BuildingMetaId = buildingMetaId;
|
||||
BuildingMapFileName = buildingMapFileName;
|
||||
ParentLandMapTree = parentLandMapTree;
|
||||
}
|
||||
}
|
||||
|
||||
public class RoomMapTree
|
||||
{
|
||||
public int InstanceMetaId { get; }
|
||||
public string RoomMapFileName { get; }
|
||||
public BuildingMapTree ParentBuildingMapTree { get; }
|
||||
public string OwnerGuid { get; set; } = string.Empty;
|
||||
public string MyhomeGuid { get; set; } = string.Empty;
|
||||
public string InstanceName { get; set; } = string.Empty;
|
||||
public int ThumbnailImageId { get; set; }
|
||||
public int ListImageId { get; set; }
|
||||
public int EnterPlayerCount { get; set; }
|
||||
|
||||
public Dictionary<string, AnchorTree> Anchors = new();
|
||||
public List<string> UgcNpcs = new();
|
||||
|
||||
public RoomMapTree(int instanceMetaId, string roomMapFileName, BuildingMapTree parentBuildingMapTree)
|
||||
{
|
||||
InstanceMetaId = instanceMetaId;
|
||||
RoomMapFileName = roomMapFileName;
|
||||
ParentBuildingMapTree = parentBuildingMapTree;
|
||||
}
|
||||
}
|
||||
|
||||
public class PersonalRoom
|
||||
{
|
||||
public Dictionary<string, AnchorTree> Anchors = new();
|
||||
}
|
||||
|
||||
public class AnchorTree
|
||||
{
|
||||
public string ParentMapFileName;
|
||||
public string AnchorGuid;
|
||||
public Pos AnchorPos;
|
||||
public AnchorProp AnchorProp = new();
|
||||
|
||||
public AnchorTree(string parentMapFileName, string anchorGuid, Pos anchorPos)
|
||||
{
|
||||
ParentMapFileName = parentMapFileName;
|
||||
AnchorGuid = anchorGuid;
|
||||
AnchorPos = anchorPos;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MapManager
|
||||
{
|
||||
private static readonly MapManager _instance = new();
|
||||
static MapManager() { }
|
||||
private MapManager() { }
|
||||
public static MapManager Instance { get { return _instance; } }
|
||||
|
||||
ConcurrentDictionary<string, WorldMapTree> WorldMapTrees = new();
|
||||
ConcurrentDictionary<string, LandMapTree> LandMapTrees = new();
|
||||
ConcurrentDictionary<string, BuildingMapTree> BuildingMapTrees = new();
|
||||
ConcurrentDictionary<string, RoomMapTree> RoomMapTrees = new();
|
||||
ConcurrentDictionary<string, AnchorTree> AnchorTrees = new();
|
||||
|
||||
ConcurrentDictionary<string, PersonalRoom> PersonalRooms = new();
|
||||
ConcurrentDictionary<string, MyhomeUgcInfo> m_myhome_ugc_infos = new();
|
||||
|
||||
List<Pos> BotStartPos = new();
|
||||
|
||||
public void Load()
|
||||
{
|
||||
foreach (var world_meta_data in MetaData.Instance._WorldMetaTable.Values)
|
||||
{
|
||||
var world_map_file_name = world_meta_data.MapPath;
|
||||
if (!MapDataTable.Instance.getMapData(world_map_file_name, out var world_map_data))
|
||||
{
|
||||
Log.getLogger().error($"Not Exist MapData !!! : fileName:{world_map_file_name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var world_map_tree = new WorldMapTree(world_meta_data.Id, world_map_file_name);
|
||||
if (!WorldMapTrees.TryAdd(world_map_file_name, world_map_tree))
|
||||
{
|
||||
WorldMapTrees.TryGetValue(world_map_file_name, out var duplicate_map_tree);
|
||||
Log.getLogger().error($"Exist WorldMapFile:{world_map_file_name} - WorldMetaId:{world_meta_data.Id}, WorldMetaId:{duplicate_map_tree?.WorldMetaId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var anchor in world_map_data.Anchors)
|
||||
{
|
||||
var new_anchor_pos = anchor.Position.toPos();
|
||||
new_anchor_pos.Angle = (int)(anchor.Rotation.Yaw);
|
||||
|
||||
var anchor_tree = new AnchorTree(world_map_file_name, anchor.GUID, new_anchor_pos);
|
||||
|
||||
anchor_tree.AnchorProp.TableId = anchor.TableID;
|
||||
if (anchor.MannequinItems.Count > 0)
|
||||
anchor_tree.AnchorProp.Mannequins = anchor.MannequinItems.ToList();
|
||||
|
||||
world_map_tree.Anchors.TryAdd(anchor.GUID, anchor_tree);
|
||||
AnchorTrees.TryAdd(anchor.GUID, anchor_tree);
|
||||
}
|
||||
|
||||
// Land
|
||||
foreach (var land_name in world_map_data.LandNames)
|
||||
{
|
||||
var land_map_file_name = $"{land_name}.land";
|
||||
if (!MapDataTable.Instance.getMapData(land_map_file_name, out var land_map_data))
|
||||
{
|
||||
Log.getLogger().error($"Not Exist MapData !!! : fileName:{land_map_file_name} or CHECK LandData.xlsx");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (land_map_data.MapFileType != MapFileType.Land)
|
||||
continue;
|
||||
|
||||
var land_meta_id = land_map_data.MapMetaId;
|
||||
|
||||
var land_map_tree = new LandMapTree(land_meta_id, land_map_file_name, world_map_tree);
|
||||
if (!LandMapTrees.TryAdd(land_map_file_name, land_map_tree))
|
||||
{
|
||||
LandMapTrees.TryGetValue(land_map_file_name, out var duplicate_map_tree);
|
||||
Log.getLogger().error($"Exist LandMapFile:{land_map_file_name} - fileName:{world_map_file_name}, fileName:{duplicate_map_tree?.ParentWorldMapTree.WorldMapFileName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
world_map_tree.ChildLandMapTrees.Add(land_meta_id, land_map_tree);
|
||||
|
||||
foreach (var anchor in land_map_data.Anchors)
|
||||
{
|
||||
var new_anchor_position = TransformHelper.rotate(anchor.Position, land_map_data.Rotation);
|
||||
|
||||
new_anchor_position.X += land_map_data.Position.X;
|
||||
new_anchor_position.Y += land_map_data.Position.Y;
|
||||
new_anchor_position.Z += land_map_data.Position.Z;
|
||||
|
||||
var new_anchor_pos = new_anchor_position.toPos();
|
||||
new_anchor_pos.Angle = (int)(land_map_data.Rotation.Yaw + anchor.Rotation.Yaw);
|
||||
|
||||
var anchor_tree = new AnchorTree(land_map_file_name, anchor.GUID, new_anchor_pos);
|
||||
|
||||
anchor_tree.AnchorProp.TableId = anchor.TableID;
|
||||
if (anchor.MannequinItems.Count > 0)
|
||||
anchor_tree.AnchorProp.Mannequins = anchor.MannequinItems.ToList();
|
||||
|
||||
land_map_tree.Anchors.TryAdd(anchor.GUID, anchor_tree);
|
||||
AnchorTrees.TryAdd(anchor.GUID, anchor_tree);
|
||||
}
|
||||
|
||||
// Building
|
||||
foreach (var building_data in land_map_data.BuildingDatas)
|
||||
{
|
||||
var building_map_file_name = Path.GetFileName(building_data.BuildingName);
|
||||
if (!MapDataTable.Instance.getMapData(building_map_file_name, out var building_map_data))
|
||||
{
|
||||
Log.getLogger().error($"Not Exist MapData !!! : fileName:{building_map_file_name} or CHECK BuildingData.xlsx");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (building_map_data.MapFileType != MapFileType.Building)
|
||||
continue;
|
||||
|
||||
var building_meta_id = building_map_data.MapMetaId;
|
||||
|
||||
var building_map_tree = new BuildingMapTree(building_meta_id, building_map_file_name, land_map_tree);
|
||||
if (!BuildingMapTrees.TryAdd(building_map_file_name, building_map_tree))
|
||||
{
|
||||
BuildingMapTrees.TryGetValue(building_map_file_name, out var duplicate_map_tree);
|
||||
Log.getLogger().error($"Exist BuildingMapFile:{building_map_file_name} - filename:{land_map_file_name}, fileName:{duplicate_map_tree?.ParentLandMapTree.LandMapFileName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
land_map_tree.ChildBuildingMapTree = building_map_tree;
|
||||
|
||||
foreach (var anchor in building_map_data.Anchors)
|
||||
{
|
||||
var new_anchor_position = TransformHelper.rotate(anchor.Position, building_map_data.Rotation);
|
||||
|
||||
new_anchor_position.X += building_data.Position.X;
|
||||
new_anchor_position.Y += building_data.Position.Y;
|
||||
new_anchor_position.Z += building_data.Position.Z;
|
||||
|
||||
new_anchor_position = TransformHelper.rotate(new_anchor_position, land_map_data.Rotation);
|
||||
|
||||
new_anchor_position.X += land_map_data.Position.X;
|
||||
new_anchor_position.Y += land_map_data.Position.Y;
|
||||
new_anchor_position.Z += land_map_data.Position.Z;
|
||||
|
||||
var new_anchor_pos = new_anchor_position.toPos();
|
||||
new_anchor_pos.Angle = (int)(building_map_data.Rotation.Yaw + land_map_data.Rotation.Yaw + anchor.Rotation.Yaw);
|
||||
|
||||
var anchor_tree = new AnchorTree(building_map_file_name, anchor.GUID, new_anchor_pos);
|
||||
|
||||
anchor_tree.AnchorProp.TableId = anchor.TableID;
|
||||
if (anchor.MannequinItems.Count > 0)
|
||||
anchor_tree.AnchorProp.Mannequins = anchor.MannequinItems.ToList();
|
||||
|
||||
building_map_tree.Anchors.TryAdd(anchor.GUID, anchor_tree);
|
||||
AnchorTrees.TryAdd(anchor.GUID, anchor_tree);
|
||||
}
|
||||
|
||||
foreach (var room_data in building_map_data.RoomDatas)
|
||||
{
|
||||
var room_map_file_name = Path.GetFileName(room_data.RoomName);
|
||||
if (!MapDataTable.Instance.getMapData(room_map_file_name, out var room_map_data))
|
||||
{
|
||||
Log.getLogger().error($"Not Exist MapData !!! : fileName:{room_map_file_name} or CHECK InstanceData.xlsx");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (room_map_data.MapFileType != MapFileType.Instance)
|
||||
continue;
|
||||
|
||||
var instance_meta_id = room_map_data.MapMetaId;
|
||||
if (!MetaData.Instance._IndunTable.TryGetValue(instance_meta_id, out var indun_meta_data))
|
||||
{
|
||||
Log.getLogger().error($"Failed to MetaData.TryGetValue() !!! : instanceMetaId:{instance_meta_id}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var room_map_tree = new RoomMapTree(instance_meta_id, room_map_file_name, building_map_tree);
|
||||
if (!RoomMapTrees.TryAdd(room_map_file_name, room_map_tree))
|
||||
{
|
||||
RoomMapTrees.TryGetValue(room_map_file_name, out var duplicate_map_tree);
|
||||
Log.getLogger().error($"Exist RoomMapFile:{room_map_file_name} - fileName:{building_map_file_name}, fileName:{duplicate_map_tree?.ParentBuildingMapTree.BuildingMapFileName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!building_map_tree.ChildRoomMapTrees.TryAdd(indun_meta_data.Building_Socket_, room_map_tree))
|
||||
{
|
||||
building_map_tree.ChildRoomMapTrees.TryGetValue(indun_meta_data.Building_Socket_, out var duplicate_room_map_tree);
|
||||
Log.getLogger().error($"Exist Floor !!! buildingMetaId:{building_meta_id}, floor:{indun_meta_data.Building_Socket_} - fileName:{room_map_tree.RoomMapFileName}, fileName:{duplicate_room_map_tree?.RoomMapFileName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var anchor in room_map_data.Anchors)
|
||||
{
|
||||
var new_anchor_position = TransformHelper.rotate(anchor.Position, room_map_data.Rotation);
|
||||
|
||||
new_anchor_position.X += room_data.Position.X;
|
||||
new_anchor_position.Y += room_data.Position.Y;
|
||||
new_anchor_position.Z += room_data.Position.Z;
|
||||
|
||||
new_anchor_position = TransformHelper.rotate(new_anchor_position, building_map_data.Rotation);
|
||||
|
||||
new_anchor_position.X += building_data.Position.X;
|
||||
new_anchor_position.Y += building_data.Position.Y;
|
||||
new_anchor_position.Z += building_data.Position.Z;
|
||||
|
||||
new_anchor_position = TransformHelper.rotate(new_anchor_position, land_map_data.Rotation);
|
||||
|
||||
new_anchor_position.X += land_map_data.Position.X;
|
||||
new_anchor_position.Y += land_map_data.Position.Y;
|
||||
new_anchor_position.Z += land_map_data.Position.Z;
|
||||
|
||||
var new_anchor_pos = new_anchor_position.toPos();
|
||||
new_anchor_pos.Angle = (int)(room_map_data.Rotation.Yaw + building_map_data.Rotation.Yaw + land_map_data.Rotation.Yaw + anchor.Rotation.Yaw);
|
||||
|
||||
var anchor_tree = new AnchorTree(room_map_file_name, anchor.GUID, new_anchor_pos);
|
||||
|
||||
anchor_tree.AnchorProp.TableId = anchor.TableID;
|
||||
if (anchor.MannequinItems.Count > 0)
|
||||
anchor_tree.AnchorProp.Mannequins = anchor.MannequinItems.ToList();
|
||||
|
||||
room_map_tree.Anchors.TryAdd(anchor.GUID, anchor_tree);
|
||||
AnchorTrees.TryAdd(anchor.GUID, anchor_tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadPersonal(ServerCommon.Constant.DRESS_ROOM_INSTANCE_META_ID);
|
||||
LoadPersonal(ServerCommon.Constant.EDIT_ROOM_INSTANCE_META_ID);
|
||||
|
||||
loadMyhomeUgcInfo();
|
||||
}
|
||||
|
||||
void LoadPersonal(int instanceId)
|
||||
{
|
||||
if (!MetaData.Instance._IndunTable.TryGetValue(instanceId, out var instanceData))
|
||||
{
|
||||
Log.getLogger().error($"Not Found InstanceData:{instanceId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MapDataTable.Instance.getMapData(instanceData.RoomFile, out var personalMapData))
|
||||
{
|
||||
Log.getLogger().error($"Not Exist MapData {instanceData.RoomFile}");
|
||||
return;
|
||||
}
|
||||
|
||||
var warp_pos = MapHelper.getWarpPos(instanceData.ContentsType);
|
||||
|
||||
personalMapData.Position.X = warp_pos.X;
|
||||
personalMapData.Position.Y = warp_pos.Y;
|
||||
personalMapData.Position.Z = warp_pos.Z;
|
||||
|
||||
var personalRoom = new PersonalRoom();
|
||||
|
||||
foreach (var anchor in personalMapData.Anchors)
|
||||
{
|
||||
var newAnchorPosition = TransformHelper.rotate(anchor.Position, personalMapData.Rotation);
|
||||
newAnchorPosition.X += personalMapData.Position.X;
|
||||
newAnchorPosition.Y += personalMapData.Position.Y;
|
||||
newAnchorPosition.Z += personalMapData.Position.Z;
|
||||
|
||||
var new_anchor_pos = newAnchorPosition.toPos();
|
||||
new_anchor_pos.Angle = (int)(personalMapData.Rotation.Yaw + anchor.Rotation.Yaw);
|
||||
|
||||
var anchorTree = new AnchorTree(instanceData.RoomFile, anchor.GUID, new_anchor_pos);
|
||||
anchorTree.AnchorProp.TableId = anchor.TableID;
|
||||
if (anchor.MannequinItems.Count > 0)
|
||||
anchorTree.AnchorProp.Mannequins = anchor.MannequinItems.ToList();
|
||||
|
||||
personalRoom.Anchors.TryAdd(anchor.GUID, anchorTree);
|
||||
AnchorTrees.TryAdd(anchor.GUID, anchorTree);
|
||||
}
|
||||
|
||||
PersonalRooms.TryAdd(instanceData.RoomFile, personalRoom);
|
||||
}
|
||||
|
||||
bool loadMyhomeUgcInfo()
|
||||
{
|
||||
// 기본 마이홈
|
||||
var default_myhome_ugc_info_file_name = MetaHelper.GameConfigMeta.MyHomeDefaultSaveFileName;
|
||||
if (!loadMyhomeFile(default_myhome_ugc_info_file_name))
|
||||
return false;
|
||||
|
||||
// TestUser
|
||||
foreach (var meta_data in MetaData.Instance.m_test_user_initial_meta_datas.Values)
|
||||
{
|
||||
if (meta_data.MyhomeFile == string.Empty)
|
||||
continue;
|
||||
|
||||
if (!loadMyhomeUgcInfoFile(meta_data.MyhomeFile))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadMyhomeFile(string myhomeFileName)
|
||||
{
|
||||
var map_data_folder_path = Path.GetFullPath("resource/map/DefaultMap", Environment.CurrentDirectory);
|
||||
var myhome_file_path = Path.Combine(map_data_folder_path, myhomeFileName);
|
||||
|
||||
if (!File.Exists(myhome_file_path))
|
||||
{
|
||||
Log.getLogger().warn($"{myhome_file_path} not exist !!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
var myhome_file_data = File.ReadAllText(myhome_file_path);
|
||||
var myhome_map_data = JsonConvert.DeserializeObject<MyhomeMapData>(myhome_file_data);
|
||||
if (myhome_map_data == null)
|
||||
{
|
||||
Log.getLogger().warn($"{myhome_file_path} convert fail !!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
var myhome_ugc_info = new MyhomeUgcInfo();
|
||||
|
||||
myhome_ugc_info.RoomType = myhome_map_data.roomtype;
|
||||
|
||||
foreach (var framework in myhome_map_data.Frameworks)
|
||||
{
|
||||
var ugcFrameworkInfo = new UgcFrameworkInfo();
|
||||
|
||||
ugcFrameworkInfo.InteriorItemId = framework.tableid;
|
||||
ugcFrameworkInfo.Floor = framework.Floor;
|
||||
ugcFrameworkInfo.Coordinate = new();
|
||||
ugcFrameworkInfo.Coordinate.X = (float)framework.Position.X;
|
||||
ugcFrameworkInfo.Coordinate.Y = (float)framework.Position.Y;
|
||||
ugcFrameworkInfo.Coordinate.Z = (float)framework.Position.Z;
|
||||
ugcFrameworkInfo.Rotation = new();
|
||||
ugcFrameworkInfo.Rotation.Pitch = (float)framework.Rotation.Pitch;
|
||||
ugcFrameworkInfo.Rotation.Yaw = (float)framework.Rotation.Yaw;
|
||||
ugcFrameworkInfo.Rotation.Roll = (float)framework.Rotation.Roll;
|
||||
|
||||
myhome_ugc_info.FrameworkInfos.Add(ugcFrameworkInfo);
|
||||
}
|
||||
|
||||
foreach (var anchor in myhome_map_data.Anchors)
|
||||
{
|
||||
var ugcAnchorInfo = new UgcAnchorInfo();
|
||||
|
||||
ugcAnchorInfo.AnchorGuid = anchor.GUID;
|
||||
ugcAnchorInfo.AnchorType = anchor.Type;
|
||||
ugcAnchorInfo.TableId = anchor.TableID;
|
||||
ugcAnchorInfo.EntityGuid = anchor.EntityGuid;
|
||||
ugcAnchorInfo.Coordinate = new();
|
||||
ugcAnchorInfo.Coordinate.X = (float)anchor.Position.X;
|
||||
ugcAnchorInfo.Coordinate.Y = (float)anchor.Position.Y;
|
||||
ugcAnchorInfo.Coordinate.Z = (float)anchor.Position.Z;
|
||||
ugcAnchorInfo.Rotation = new();
|
||||
ugcAnchorInfo.Rotation.Pitch = (float)anchor.Rotation.Pitch;
|
||||
ugcAnchorInfo.Rotation.Yaw = (float)anchor.Rotation.Yaw;
|
||||
ugcAnchorInfo.Rotation.Roll = (float)anchor.Rotation.Roll;
|
||||
|
||||
myhome_ugc_info.AnchorInfos.Add(ugcAnchorInfo);
|
||||
}
|
||||
|
||||
if (!m_myhome_ugc_infos.TryAdd(myhomeFileName, myhome_ugc_info))
|
||||
{
|
||||
Log.getLogger().warn($"{myhomeFileName} add fail !!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadMyhomeUgcInfoFile(string myhomeUgcInfoFileName)
|
||||
{
|
||||
var map_data_folder_path = Path.GetFullPath("resource/map/DefaultMap", Environment.CurrentDirectory);
|
||||
var myhome_ugc_info_file_path = Path.Combine(map_data_folder_path, myhomeUgcInfoFileName);
|
||||
|
||||
if (!File.Exists(myhome_ugc_info_file_path))
|
||||
{
|
||||
Log.getLogger().warn($"{myhome_ugc_info_file_path} not exist !!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
var myhome_ugc_info_file_data = File.ReadAllText(myhome_ugc_info_file_path);
|
||||
var myhome_ugc_info = JsonConvert.DeserializeObject<MyhomeUgcInfo>(myhome_ugc_info_file_data);
|
||||
if (myhome_ugc_info == null)
|
||||
{
|
||||
Log.getLogger().warn($"{myhome_ugc_info_file_path} convert fail !!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_myhome_ugc_infos.TryAdd(myhomeUgcInfoFileName, myhome_ugc_info))
|
||||
{
|
||||
Log.getLogger().warn($"{myhomeUgcInfoFileName} add fail !!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateProp(string anchorGuid, AnchorProp prop)
|
||||
{
|
||||
if (!AnchorTrees.TryGetValue(anchorGuid, out var anchorTree))
|
||||
return false;
|
||||
|
||||
anchorTree.AnchorProp.TableId = prop.TableId;
|
||||
anchorTree.AnchorProp.GuidByType = prop.GuidByType;
|
||||
anchorTree.AnchorProp.Mannequins = prop.Mannequins;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void GetMapAnchorList(string mapFileName, out List<AnchorTree> anchorList)
|
||||
{
|
||||
anchorList = new List<AnchorTree>();
|
||||
|
||||
switch (Path.GetExtension(mapFileName))
|
||||
{
|
||||
case ".zone":
|
||||
{
|
||||
if (!WorldMapTrees.TryGetValue(mapFileName, out var worldMapTree))
|
||||
return;
|
||||
|
||||
anchorList = worldMapTree.Anchors.Values.ToList();
|
||||
}
|
||||
break;
|
||||
case ".land":
|
||||
{
|
||||
if (!LandMapTrees.TryGetValue(mapFileName, out var landMapTree))
|
||||
return;
|
||||
|
||||
anchorList = landMapTree.Anchors.Values.ToList();
|
||||
}
|
||||
break;
|
||||
case ".build":
|
||||
{
|
||||
if (!BuildingMapTrees.TryGetValue(mapFileName, out var buildMapTree))
|
||||
return;
|
||||
|
||||
anchorList = buildMapTree.Anchors.Values.ToList();
|
||||
}
|
||||
break;
|
||||
case ".room":
|
||||
{
|
||||
if (!RoomMapTrees.TryGetValue(mapFileName, out var roomMapTree))
|
||||
return;
|
||||
|
||||
anchorList = roomMapTree.Anchors.Values.ToList();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Log.getLogger().error($"{mapFileName} is not map file");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetMapAnchorListForMapCreate(string mapFileName, out List<AnchorTree> anchorList)
|
||||
{
|
||||
anchorList = new List<AnchorTree>();
|
||||
|
||||
switch (Path.GetExtension(mapFileName))
|
||||
{
|
||||
case ".zone":
|
||||
{
|
||||
if (!WorldMapTrees.TryGetValue(mapFileName, out var world))
|
||||
return;
|
||||
|
||||
anchorList.AddRange(world.Anchors.Values);
|
||||
|
||||
foreach (var land in world.ChildLandMapTrees.Values)
|
||||
{
|
||||
anchorList.AddRange(land.Anchors.Values);
|
||||
|
||||
var building = land.ChildBuildingMapTree;
|
||||
if (building == null)
|
||||
continue;
|
||||
|
||||
anchorList.AddRange(building.Anchors.Values);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ".room":
|
||||
{
|
||||
if (PersonalRooms.TryGetValue(mapFileName, out var personalRoom))
|
||||
{
|
||||
anchorList.AddRange(personalRoom.Anchors.Values);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RoomMapTrees.TryGetValue(mapFileName, out var room))
|
||||
return;
|
||||
|
||||
anchorList.AddRange(room.Anchors.Values);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Log.getLogger().error($"{mapFileName} is not map create file");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public Pos GetStartPos(string mapFileName)
|
||||
{
|
||||
Pos startPos = new();
|
||||
|
||||
var startPosAnchorGuid = MapDataTable.Instance.GetRoomStartPosAnchorGuid(mapFileName);
|
||||
|
||||
if (!AnchorTrees.TryGetValue(startPosAnchorGuid, out var startPosAnchor))
|
||||
{
|
||||
return startPos;
|
||||
}
|
||||
|
||||
startPos.X = startPosAnchor.AnchorPos.X;
|
||||
startPos.Y = startPosAnchor.AnchorPos.Y;
|
||||
startPos.Z = startPosAnchor.AnchorPos.Z + 100;
|
||||
|
||||
return startPos;
|
||||
}
|
||||
|
||||
public bool GetWorldMapTree(string mapFileName, [MaybeNullWhen(false)] out WorldMapTree worldMapTree)
|
||||
{
|
||||
return WorldMapTrees.TryGetValue(mapFileName, out worldMapTree);
|
||||
}
|
||||
|
||||
public bool GetLandMapTree(int landMetaId, [MaybeNullWhen(false)] out LandMapTree landMapTree)
|
||||
{
|
||||
landMapTree = null;
|
||||
|
||||
if (!MetaData.Instance._LandTable.TryGetValue(landMetaId, out var landData))
|
||||
{
|
||||
var err_msg = $"Failed to MetaData.TryGetValue() !!! : LandMetaId:{landMetaId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return LandMapTrees.TryGetValue(landData.LandFile, out landMapTree);
|
||||
}
|
||||
|
||||
public bool GetBuildingMapTree(int buildingMetaId, [MaybeNullWhen(false)] out BuildingMapTree buildingMapTree)
|
||||
{
|
||||
buildingMapTree = null;
|
||||
|
||||
if (!MetaData.Instance._BuildingTable.TryGetValue(buildingMetaId, out var buildingData))
|
||||
{
|
||||
var err_msg = $"Failed to MetaData.TryGetValue() !!! : BuildingMetaId:{buildingMetaId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return BuildingMapTrees.TryGetValue(buildingData.BuildingFile, out buildingMapTree);
|
||||
}
|
||||
|
||||
public bool getRoomMapTree(string myhomeGuid, [MaybeNullWhen(false)] out RoomMapTree roomMapTree)
|
||||
{
|
||||
if (!RoomMapTrees.TryGetValue(myhomeGuid, out roomMapTree))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<int> getLandMetaIds()
|
||||
{
|
||||
var land_meta_ids = new List<int>();
|
||||
|
||||
foreach (var land_map_tree in LandMapTrees.Values)
|
||||
{
|
||||
land_meta_ids.Add(land_map_tree.LandId);
|
||||
}
|
||||
|
||||
return land_meta_ids;
|
||||
}
|
||||
|
||||
public List<int> getBuildingMetaIds()
|
||||
{
|
||||
var building_meta_ids = new List<int>();
|
||||
|
||||
foreach (var building_map_tree in BuildingMapTrees.Values)
|
||||
{
|
||||
building_meta_ids.Add(building_map_tree.BuildingMetaId);
|
||||
}
|
||||
|
||||
return building_meta_ids;
|
||||
}
|
||||
|
||||
public bool tryGetLandChildBuildingMetaId(int landMetaId, out int childBuildingMetaId)
|
||||
{
|
||||
childBuildingMetaId = 0;
|
||||
|
||||
if (!GetLandMapTree(landMetaId, out var land_map_tree))
|
||||
return false;
|
||||
|
||||
if (land_map_tree.ChildBuildingMapTree == null)
|
||||
return false;
|
||||
|
||||
childBuildingMetaId = land_map_tree.ChildBuildingMapTree.BuildingMetaId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ExchangeMannequinDisplayItem(string anchorGuid, List<int> displayItemIds)
|
||||
{
|
||||
if (!AnchorTrees.TryGetValue(anchorGuid, out var anchorTree))
|
||||
return;
|
||||
|
||||
anchorTree.AnchorProp.Mannequins = displayItemIds;
|
||||
anchorTree.AnchorProp.IsMannequinsChanged = true;
|
||||
}
|
||||
|
||||
public bool getParentMapFileName(string anchorGuid, [MaybeNullWhen(false)] out string parentMapFileName)
|
||||
{
|
||||
parentMapFileName = null;
|
||||
|
||||
if (!AnchorTrees.TryGetValue(anchorGuid, out var anchorTree))
|
||||
return false;
|
||||
|
||||
parentMapFileName = anchorTree.ParentMapFileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool getDefaultMyhomeUgcInfo(string myhomeUgcInfoFileName, [MaybeNullWhen(false)] out MyhomeUgcInfo myhomeUgcInfo)
|
||||
{
|
||||
return m_myhome_ugc_infos.TryGetValue(myhomeUgcInfoFileName, out myhomeUgcInfo);
|
||||
}
|
||||
|
||||
public void addRoomMaptree(BuildingMapTree buildingMapTree, int floor, RoomMapTree roomMapTree)
|
||||
{
|
||||
buildingMapTree.ChildRoomMapTrees[floor] = roomMapTree;
|
||||
RoomMapTrees[roomMapTree.RoomMapFileName] = roomMapTree;
|
||||
}
|
||||
|
||||
public async Task<Result> tryAddRoomMapTreeFromDb(BuildingFloorDoc buildingFloorDoc)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var building_floor_attrib = buildingFloorDoc.getAttrib<BuildingFloorAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(building_floor_attrib, () => $"building_floor_attrib is null !!!");
|
||||
|
||||
(result, var myhome_attrib) = await MyhomeHelper.getEnterMyhomeAttribFromDynamoDb(building_floor_attrib.OwnerGuid, building_floor_attrib.MyhomeGuid);
|
||||
if (result.isFail() || null == myhome_attrib)
|
||||
{
|
||||
err_msg = $"Failed to getSelectedMyhomeUgcInfoFromDynamoDb() !!! : {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, var myhome_ugc_info) = await MyhomeHelper.getMyhomeUgcInfo(myhome_attrib);
|
||||
if (result.isFail() || null == myhome_ugc_info)
|
||||
{
|
||||
err_msg = $"Failed to getMyhomeUgcInfo() !!! : {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result = MyhomeHelper.getMyhomeInstanceId(myhome_ugc_info.RoomType, out var instance_meta_id);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Fail to getMyhomeInstanceId() !!! : {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!MetaData.Instance._IndunTable.TryGetValue(instance_meta_id, out var indun_meta_data))
|
||||
{
|
||||
err_msg = $"Failed to MetaData.TryGetValue() !!! : instanceMetaId:{instance_meta_id}";
|
||||
result.setFail(ServerErrorCode.InstanceMetaDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!GetBuildingMapTree(building_floor_attrib.BuildingMetaId, out var building_map_tree))
|
||||
{
|
||||
err_msg = $"Failed to GetBuildingMapTree() !!! : BuildingMetaId:{building_floor_attrib.BuildingMetaId}";
|
||||
result.setFail(ServerErrorCode.BuildingMapTreeDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var db_client = server_logic.getDynamoDbClient();
|
||||
NullReferenceCheckHelper.throwIfNull(db_client, () => $"db_client is null !!!");
|
||||
|
||||
var location_unique_id = server_logic.getMap().makeLOCATION_UNIQUE_IDByMetaIdWithLocationTargetType(LocationTargetType.Instance, building_floor_attrib.MyhomeGuid);
|
||||
|
||||
var npc_location_in_target_doc = new NpcLocationInTargetDoc(location_unique_id, building_floor_attrib.MyhomeGuid);
|
||||
var query_config = db_client.makeQueryConfigForReadByPKOnly(npc_location_in_target_doc.getPK());
|
||||
|
||||
(result, var read_docs) = await db_client.simpleQueryDocTypesWithQueryOperationConfig<NpcLocationInTargetDoc>(query_config);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to simpleQueryDocTypesWithQueryOperationConfig() !!! : {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(read_docs, () => $"read_docs is null !!!");
|
||||
|
||||
var ugc_npc_guids = new List<string>();
|
||||
|
||||
foreach (var read_doc in read_docs)
|
||||
{
|
||||
var npc_location_in_target_attrib = read_doc.getAttrib<NpcLocationInTargetAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(npc_location_in_target_attrib, () => $"npc_location_in_target_attrib is null !!!");
|
||||
|
||||
ugc_npc_guids.Add(npc_location_in_target_attrib.NpcUniqueId);
|
||||
}
|
||||
|
||||
var room_map_tree = new RoomMapTree(instance_meta_id, building_floor_attrib.MyhomeGuid, building_map_tree);
|
||||
|
||||
room_map_tree.OwnerGuid = building_floor_attrib.OwnerGuid;
|
||||
room_map_tree.MyhomeGuid = building_floor_attrib.MyhomeGuid;
|
||||
room_map_tree.InstanceName = building_floor_attrib.InstanceName;
|
||||
room_map_tree.ThumbnailImageId = building_floor_attrib.ThumbnailImageId;
|
||||
room_map_tree.ListImageId = building_floor_attrib.ListImageId;
|
||||
room_map_tree.EnterPlayerCount = building_floor_attrib.EnterPlayerCount;
|
||||
room_map_tree.UgcNpcs = ugc_npc_guids;
|
||||
|
||||
building_map_tree.ChildRoomMapTrees[building_floor_attrib.Floor] = room_map_tree;
|
||||
|
||||
RoomMapTrees[room_map_tree.RoomMapFileName] = room_map_tree;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool tryRemoveRoomMapTree(int building_meta_id, int floor, [MaybeNullWhen(false)] out RoomMapTree removedRoomMapTree)
|
||||
{
|
||||
removedRoomMapTree = default;
|
||||
|
||||
if (!GetBuildingMapTree(building_meta_id, out var building_map_tree))
|
||||
return false;
|
||||
|
||||
if (!building_map_tree.ChildRoomMapTrees.Remove(floor, out var room_map_tree))
|
||||
return false;
|
||||
|
||||
return RoomMapTrees.TryRemove(room_map_tree.RoomMapFileName, out removedRoomMapTree);
|
||||
}
|
||||
|
||||
public Result modifyFloorLinkedInfo(ModifyFloorLinkedInfo modifyFloorLinkedInfo)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (!GetBuildingMapTree(modifyFloorLinkedInfo.BuildingId, out var building_map_tree))
|
||||
{
|
||||
err_msg = $"Failed to GetBuildingMapTree() !!! : BuildingMetaId:{modifyFloorLinkedInfo.BuildingId}";
|
||||
result.setFail(ServerErrorCode.BuildingMapTreeDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!building_map_tree.ChildRoomMapTrees.TryGetValue(modifyFloorLinkedInfo.Floor, out var room_map_tree))
|
||||
{
|
||||
err_msg = $"Failed to ChildRoomMapTrees.TryGetValue() !!! : floor:{modifyFloorLinkedInfo.Floor}";
|
||||
result.setFail(ServerErrorCode.BuildingMapTreeChildRoomNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (modifyFloorLinkedInfo.ModifyType)
|
||||
{
|
||||
case ModifyType.Add:
|
||||
{
|
||||
room_map_tree.UgcNpcs.AddRange(modifyFloorLinkedInfo.FloorLinkedInfo.UgcNpcGuids);
|
||||
}
|
||||
break;
|
||||
case ModifyType.Delete:
|
||||
{
|
||||
foreach (var ugc_npc_guid in modifyFloorLinkedInfo.FloorLinkedInfo.UgcNpcGuids)
|
||||
{
|
||||
room_map_tree.UgcNpcs.Remove(ugc_npc_guid);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result tryGetUsingFloorCountByLandMetaId(int landMetaId, out int usingFloorCount)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
usingFloorCount = 0;
|
||||
|
||||
if (!GetLandMapTree(landMetaId, out var land_map_tree))
|
||||
{
|
||||
err_msg = $"Failed to GetLandMapTree() !!! : LandMetaId:{landMetaId}";
|
||||
result.setFail(ServerErrorCode.LandMapTreeDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var building_map_tree = land_map_tree.ChildBuildingMapTree;
|
||||
if (building_map_tree == null)
|
||||
{
|
||||
err_msg = $"Not Exist LandMapTree ChildBuilding !!! : LandMap:{land_map_tree.LandMapFileName}";
|
||||
result.setFail(ServerErrorCode.LandMapTreeChildBuildingNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return tryGetUsingFloorCountByBuildingMetaId(building_map_tree.BuildingMetaId, out usingFloorCount);
|
||||
}
|
||||
|
||||
public Result tryGetUsingFloorCountByBuildingMetaId(int buildingMetaId, out int usingFloorCount)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
usingFloorCount = 0;
|
||||
|
||||
if (!GetBuildingMapTree(buildingMetaId, out var building_map_tree))
|
||||
{
|
||||
err_msg = $"Failed to GetBuildingMapTree() !!! : BuildingMetaId:{buildingMetaId}";
|
||||
result.setFail(ServerErrorCode.BuildingMapTreeDataNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
usingFloorCount = building_map_tree.ChildRoomMapTrees.Count;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
181
GameServer/Map/PropGroupManager.cs
Normal file
181
GameServer/Map/PropGroupManager.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class PropGroup
|
||||
{
|
||||
public int PropGroupId { get; set; }
|
||||
public DateTime LatestRespawnTime { get; set; }
|
||||
public List<string> AnchorGuids { get; set; } = new();
|
||||
|
||||
}
|
||||
|
||||
internal class PropGroupManager
|
||||
{
|
||||
Dictionary<int, PropGroup> m_prop_groups = new();
|
||||
|
||||
public bool init(Map map)
|
||||
{
|
||||
foreach (var prop_group in m_prop_groups.Values)
|
||||
{
|
||||
if (!MetaData.Instance._PropGroupMetaTable.TryGetValue(prop_group.PropGroupId, out var prop_group_data))
|
||||
{
|
||||
Log.getLogger().error($"Failed to MetaData.TryGetValue() !!! : propGroupMetaId:{prop_group.PropGroupId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prop_group_data.prop_order_data.Count <= 0)
|
||||
{
|
||||
Log.getLogger().error($"PropGroupData.prop_order_data.Count <= 0 !!! : {prop_group.PropGroupId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// GroupProp 기본값 세팅
|
||||
foreach (var anchor_guid in prop_group.AnchorGuids)
|
||||
{
|
||||
if (!map.getAnchors().TryGetValue(anchor_guid, out var anchor_info))
|
||||
continue;
|
||||
|
||||
anchor_info.AnchorProp.TableId = prop_group_data.prop_order_data[0].prop_id;
|
||||
}
|
||||
|
||||
int spawn_count = 0;
|
||||
while (spawn_count < prop_group_data.max_spawn_quantity)
|
||||
{
|
||||
var spawn_prop_id = getSpawnPropId(prop_group_data);
|
||||
|
||||
var index = RandomHelper.next(0, prop_group.AnchorGuids.Count);
|
||||
string activation_anchor_guid = prop_group.AnchorGuids[index];
|
||||
|
||||
if (false == map.getAnchors().TryGetValue(activation_anchor_guid, out var activation_anchor_info))
|
||||
return false;
|
||||
|
||||
if (activation_anchor_info.PropState == PropState.Activation)
|
||||
continue;
|
||||
|
||||
activation_anchor_info.AnchorProp.TableId = spawn_prop_id;
|
||||
activation_anchor_info.PropState = PropState.Activation;
|
||||
|
||||
spawn_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int getSpawnPropId(PropGroupData propGroupData)
|
||||
{
|
||||
int spawn_prop_id = -1;
|
||||
int low_spawn_weight = 0;
|
||||
int high_spawn_weight = 0;
|
||||
var prop_spawn_weight = RandomHelper.next(0, propGroupData.max_prop_spawn_weight);
|
||||
foreach (var prop_order in propGroupData.prop_order_data)
|
||||
{
|
||||
low_spawn_weight = high_spawn_weight;
|
||||
high_spawn_weight += prop_order.prop_spawn_weight;
|
||||
|
||||
if (low_spawn_weight <= prop_spawn_weight && prop_spawn_weight < high_spawn_weight)
|
||||
{
|
||||
spawn_prop_id = prop_order.prop_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return spawn_prop_id;
|
||||
}
|
||||
|
||||
public bool addAnchor(AnchorInfo anchorInfo)
|
||||
{
|
||||
if (!MapHelper.isGroupProp(anchorInfo.AnchorGuid))
|
||||
return false;
|
||||
|
||||
if (!MapDataTable.Instance.getAnchor(anchorInfo.AnchorGuid, out var anchor))
|
||||
return false;
|
||||
|
||||
if (!m_prop_groups.TryGetValue(anchor.TableID, out var prop_group))
|
||||
{
|
||||
prop_group = new();
|
||||
prop_group.PropGroupId = anchor.TableID;
|
||||
|
||||
if (!m_prop_groups.TryAdd(anchor.TableID, prop_group))
|
||||
{
|
||||
Log.getLogger().error($"Failed to PropGroup Add !!! : propGroupMetaId:{anchor.TableID}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
prop_group.AnchorGuids.Add(anchorInfo.AnchorGuid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void checkRespawnPropGroup(Map map)
|
||||
{
|
||||
foreach (var prop_group_id in m_prop_groups.Keys)
|
||||
{
|
||||
respawnPropGroup(map, prop_group_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool respawnPropGroup(Map map, int propGroupId)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (!MetaData.Instance._PropGroupMetaTable.TryGetValue(propGroupId, out var prop_group_data))
|
||||
{
|
||||
err_msg = $"Failed to MetaData.TryGetValue() !!! : propGroupMetaId:{propGroupId}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_prop_groups.TryGetValue(propGroupId, out var prop_group))
|
||||
return false;
|
||||
|
||||
int activationAndRespawningCount = 0;
|
||||
List<string> deactivateAnchorGuids = new();
|
||||
foreach (var anchor_guid in prop_group.AnchorGuids)
|
||||
{
|
||||
if (false == map.getAnchors().TryGetValue(anchor_guid, out var anchor_info))
|
||||
continue;
|
||||
|
||||
if (anchor_info.PropState == PropState.Activation || anchor_info.PropState == PropState.Respawning)
|
||||
{
|
||||
activationAndRespawningCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
deactivateAnchorGuids.Add((anchor_guid));
|
||||
}
|
||||
|
||||
if (activationAndRespawningCount >= prop_group_data.max_spawn_quantity)
|
||||
return false;
|
||||
|
||||
|
||||
int respwan_prop_id = getSpawnPropId(prop_group_data);
|
||||
|
||||
var index = RandomHelper.next(0, deactivateAnchorGuids.Count);
|
||||
string respwan_anchor_guid = deactivateAnchorGuids[index];
|
||||
|
||||
if (false == map.getAnchors().TryGetValue(respwan_anchor_guid, out var respwan_anchor_info))
|
||||
return false;
|
||||
|
||||
var respwan_time = prop_group.LatestRespawnTime > DateTime.UtcNow ? prop_group.LatestRespawnTime : DateTime.UtcNow;
|
||||
respwan_time = respwan_time.AddSeconds(prop_group_data.group_respawn_time);
|
||||
prop_group.LatestRespawnTime = respwan_time;
|
||||
|
||||
respwan_anchor_info.AnchorProp.TableId = respwan_prop_id;
|
||||
respwan_anchor_info.PropState = PropState.Respawning;
|
||||
respwan_anchor_info.respawnTime = respwan_time.ToTimestamp();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user