using RPG.GameCore.Excel; using RPG.GameCore.Level; using RPG.GameCore.Level.Floor; using RPG.GameCore.Level.Group; using RPG.GameCore.Level.Objects; using RPG.GameCore.Util; using RPG.Network.Proto; using RPG.Services.Gameserver.Game.Entity; using RPG.Services.Gameserver.Game.Entity.Factory; using RPG.Services.Gameserver.Game.Team; using MazeInfo = RPG.Network.Proto.Maze; namespace RPG.Services.Gameserver.Game.Maze; internal class MazeManager { private readonly EntityManager _entityManager; private readonly EntityFactory _entityFactory; private readonly ExcelTables _excelTables; private readonly LevelTables _levelTables; private MapEntryRow? _mapEntry; private LevelFloorInfo? _floor; private PlayerTeam? _playerTeam; private uint _uid; public MazeManager(EntityManager entityManager, EntityFactory entityFactory, ExcelTables excelTables, LevelTables levelTables) { _entityManager = entityManager; _entityFactory = entityFactory; _excelTables = excelTables; _levelTables = levelTables; } public EntityBase? GetEntityById(uint entityId) { return _entityManager.GetEntityById(entityId); } public void ResetAvatarPosition() { foreach (TeamMember? member in _playerTeam!.Members) { if (member == null) continue; AvatarEntity? entity = _entityManager.GetAvatar(_uid, member.AvatarId); if (entity != null) { entity.SetMotion(CreateInitialAvatarMotion()); _entityManager.NotifyUpdate(entity); } } } public void RemoveEntities(IEnumerable entities) { _entityManager.RemoveEntities(entities); } public void SetPlayerUid(uint uid) { _uid = uid; } public void EnterMaze(uint entryId, PlayerTeam team) { BeforeEnter(); _playerTeam = team; _mapEntry = _excelTables.GetExcelRow(ExcelType.MapEntry, entryId) ?? throw new ArgumentException("EnterMaze: specified entryId doesn't exist!", nameof(entryId)); _floor = _levelTables.GetFloorInfo(_mapEntry.FloorID); AddTeamMemberEntities(); InitLevelGroups(); } public MazeInfo Maze { get { if (_mapEntry == null) throw new InvalidOperationException("GetMaze: maze not loaded!"); return new() { MapEntryId = _mapEntry.ID, Id = _mapEntry.PlaneID, Floor = new() { FloorId = _mapEntry.FloorID, Scene = SceneInfo } }; } } public SceneInfo SceneInfo { get { if (_mapEntry == null || _playerTeam == null) throw new InvalidOperationException("GetSceneInfo: scene not loaded!"); AvatarEntity? leaderEntity = _entityManager.GetAvatar(_uid, _playerTeam.Leader.AvatarId); SceneInfo info = new() { EntryId = _mapEntry.ID, PlaneId = _mapEntry.PlaneID, FloorId = _mapEntry.FloorID, LeaderEntityId = leaderEntity?.Id ?? 0, }; info.EntityList.AddRange(_entityManager.EntityInfoList); return info; } } private void InitLevelGroups() { foreach (LevelGroupInstanceInfo groupInstanceInfo in _floor!.GroupList) { LevelGroupInfo? levelGroup = _levelTables.GetGroupInfo(groupInstanceInfo.GroupGUID); if (levelGroup == null) continue; foreach (LevelMonsterInfo levelMonster in levelGroup.MonsterList) { if (!levelMonster.CreateOnInitial) continue; NpcMonsterEntity monsterEntity = _entityFactory.CreateNpcMonsterEntity(levelMonster, groupInstanceInfo.ID); monsterEntity.SetMotion(CreateDefaultMotion(levelMonster)); _entityManager.AddEntity(monsterEntity); } } } private void AddTeamMemberEntities() { foreach (TeamMember? member in _playerTeam!.Members) { if (member == null) continue; AvatarEntity entity = _entityFactory.CreateAvatarEntity(member.AvatarId, member.AvatarType, _uid); entity.SetMotion(CreateInitialAvatarMotion()); _entityManager.AddEntity(entity); } } private MotionInfo CreateInitialAvatarMotion() { LevelGroupInfo startGroup = _levelTables.GetGroupInfo(_floor!.StartGroup.GroupGUID)!; LevelAnchorInfo startAnchor = startGroup.AnchorList.First(anchor => anchor.ID == _floor.StartAnchorID); return CreateDefaultMotion(startAnchor); } private static MotionInfo CreateDefaultMotion(NamedLevelObjectInfo info) { return new() { Pos = new() { X = MathUtil.GetLogicCoordValue(info.PosX), Y = MathUtil.GetLogicCoordValue(info.PosY), Z = MathUtil.GetLogicCoordValue(info.PosZ) }, Rot = new() { Y = MathUtil.GetLogicCoordValue(info.RotY) } }; } private void BeforeEnter() { _entityFactory.Reset(); _entityManager.Clear(); } }