초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

465
GameServer/Map/Grid.cs Normal file
View 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;
}
}

View 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;
}
}

View 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

File diff suppressed because it is too large Load Diff

View 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;
}
}
}

View 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;
}
}