From aeb582d61ed75a8cefb9a24af5ead58c072857b0 Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Mon, 20 Jan 2025 10:29:51 +0100 Subject: [PATCH] safeguard pose/world data generation loops --- .../CharaDataGposeTogetherManager.cs | 192 ++++++++++-------- 1 file changed, 103 insertions(+), 89 deletions(-) diff --git a/MareSynchronos/Services/CharaData/CharaDataGposeTogetherManager.cs b/MareSynchronos/Services/CharaData/CharaDataGposeTogetherManager.cs index 3d13987..8f0d5db 100644 --- a/MareSynchronos/Services/CharaData/CharaDataGposeTogetherManager.cs +++ b/MareSynchronos/Services/CharaData/CharaDataGposeTogetherManager.cs @@ -370,34 +370,41 @@ public class CharaDataGposeTogetherManager : DisposableMediatorSubscriberBase if (!_dalamudUtil.IsInGpose) continue; if (_usersInLobby.Count == 0) continue; - var chara = await _dalamudUtil.GetPlayerCharacterAsync().ConfigureAwait(false); - if (_dalamudUtil.IsInGpose) + try { - chara = (IPlayerCharacter?)(await _dalamudUtil.GetGposeCharacterFromObjectTableByNameAsync(chara.Name.TextValue, _dalamudUtil.IsInGpose).ConfigureAwait(false)); + var chara = await _dalamudUtil.GetPlayerCharacterAsync().ConfigureAwait(false); + if (_dalamudUtil.IsInGpose) + { + chara = (IPlayerCharacter?)(await _dalamudUtil.GetGposeCharacterFromObjectTableByNameAsync(chara.Name.TextValue, _dalamudUtil.IsInGpose).ConfigureAwait(false)); + } + if (chara == null || chara.Address == nint.Zero) continue; + + var poseJson = await _brio.GetPoseAsync(chara.Address).ConfigureAwait(false); + if (string.IsNullOrEmpty(poseJson)) continue; + + var poseData = CreatePoseDataFromJson(poseJson, _poseGenerationExecutions++ >= 12 ? null : _lastFullPoseData); + if (!poseData.IsDelta) + { + _lastFullPoseData = poseData; + _lastDeltaPoseData = null; + _poseGenerationExecutions = 0; + } + + bool deltaIsSame = _lastDeltaPoseData != null && + (poseData.Bones.Keys.All(k => _lastDeltaPoseData.Value.Bones.ContainsKey(k) + && poseData.Bones.Values.All(k => _lastDeltaPoseData.Value.Bones.ContainsValue(k)))); + + if ((poseData.Bones.Any() || poseData.MainHand.Any() || poseData.OffHand.Any()) + && (!poseData.IsDelta || (poseData.IsDelta && !deltaIsSame))) + await _apiController.GposeLobbyPushPoseData(poseData).ConfigureAwait(false); + + if (poseData.IsDelta) + _lastDeltaPoseData = poseData; } - if (chara == null || chara.Address == nint.Zero) continue; - - var poseJson = await _brio.GetPoseAsync(chara.Address).ConfigureAwait(false); - if (string.IsNullOrEmpty(poseJson)) continue; - - var poseData = CreatePoseDataFromJson(poseJson, _poseGenerationExecutions++ >= 12 ? null : _lastFullPoseData); - if (!poseData.IsDelta) + catch (Exception ex) { - _lastFullPoseData = poseData; - _lastDeltaPoseData = null; - _poseGenerationExecutions = 0; + Logger.LogWarning(ex, "Error during Pose Data Generation"); } - - bool deltaIsSame = _lastDeltaPoseData != null && - (poseData.Bones.Keys.All(k => _lastDeltaPoseData.Value.Bones.ContainsKey(k) - && poseData.Bones.Values.All(k => _lastDeltaPoseData.Value.Bones.ContainsValue(k)))); - - if ((poseData.Bones.Any() || poseData.MainHand.Any() || poseData.OffHand.Any()) - && (!poseData.IsDelta || (poseData.IsDelta && !deltaIsSame))) - await _apiController.GposeLobbyPushPoseData(poseData).ConfigureAwait(false); - - if (poseData.IsDelta) - _lastDeltaPoseData = poseData; } } @@ -410,78 +417,85 @@ public class CharaDataGposeTogetherManager : DisposableMediatorSubscriberBase // if there are no players in lobby, don't do anything if (_usersInLobby.Count == 0) continue; - // get own player data - var player = (Dalamud.Game.ClientState.Objects.Types.ICharacter?)(await _dalamudUtil.GetPlayerCharacterAsync().ConfigureAwait(false)); - if (player == null) continue; - WorldData worldData; - if (_dalamudUtil.IsInGpose) + try { - player = await _dalamudUtil.GetGposeCharacterFromObjectTableByNameAsync(player.Name.TextValue, true).ConfigureAwait(false); + // get own player data + var player = (Dalamud.Game.ClientState.Objects.Types.ICharacter?)(await _dalamudUtil.GetPlayerCharacterAsync().ConfigureAwait(false)); if (player == null) continue; - worldData = (await _brio.GetTransformAsync(player.Address).ConfigureAwait(false)); - } - else - { - var rotQuaternion = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), player.Rotation); - worldData = new() + WorldData worldData; + if (_dalamudUtil.IsInGpose) { - PositionX = player.Position.X, - PositionY = player.Position.Y, - PositionZ = player.Position.Z, - RotationW = rotQuaternion.W, - RotationX = rotQuaternion.X, - RotationY = rotQuaternion.Y, - RotationZ = rotQuaternion.Z, - ScaleX = 1, - ScaleY = 1, - ScaleZ = 1 - }; - } - - var loc = await _dalamudUtil.GetMapDataAsync().ConfigureAwait(false); - worldData.LocationInfo = loc; - - if (worldData != _lastWorldData) - { - await _apiController.GposeLobbyPushWorldData(worldData).ConfigureAwait(false); - _lastWorldData = worldData; - Logger.LogTrace("WorldData (gpose: {gpose}): {data}", _dalamudUtil.IsInGpose, worldData); - } - - foreach (var entry in _usersInLobby) - { - if (!entry.Value.HasWorldDataUpdate || _dalamudUtil.IsInGpose) continue; - - var entryWorldData = entry.Value.WorldData!.Value; - - if (worldData.LocationInfo.MapId == entryWorldData.LocationInfo.MapId && worldData.LocationInfo.DivisionId == entryWorldData.LocationInfo.DivisionId - && (worldData.LocationInfo.HouseId != entryWorldData.LocationInfo.HouseId - || worldData.LocationInfo.WardId != entryWorldData.LocationInfo.WardId - || entryWorldData.LocationInfo.ServerId != worldData.LocationInfo.ServerId)) - { - if (entry.Value.SpawnedVfxId == null) - { - // spawn if it doesn't exist yet - entry.Value.LastWorldPosition = new Vector3(entryWorldData.PositionX, entryWorldData.PositionY, entryWorldData.PositionZ); - entry.Value.SpawnedVfxId = await _dalamudUtil.RunOnFrameworkThread(() => _vfxSpawnManager.SpawnObject(entry.Value.LastWorldPosition.Value, - Quaternion.Identity, Vector3.One, 0.5f, 0.1f, 0.5f, 0.9f)).ConfigureAwait(false); - } - else - { - // move object via lerp if it does exist - var newPosition = new Vector3(entryWorldData.PositionX, entryWorldData.PositionY, entryWorldData.PositionZ); - if (newPosition != entry.Value.LastWorldPosition) - { - entry.Value.UpdateStart = DateTime.UtcNow; - entry.Value.TargetWorldPosition = newPosition; - } - } + player = await _dalamudUtil.GetGposeCharacterFromObjectTableByNameAsync(player.Name.TextValue, true).ConfigureAwait(false); + if (player == null) continue; + worldData = (await _brio.GetTransformAsync(player.Address).ConfigureAwait(false)); } else { - await _dalamudUtil.RunOnFrameworkThread(() => _vfxSpawnManager.DespawnObject(entry.Value.SpawnedVfxId)).ConfigureAwait(false); - entry.Value.SpawnedVfxId = null; + var rotQuaternion = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), player.Rotation); + worldData = new() + { + PositionX = player.Position.X, + PositionY = player.Position.Y, + PositionZ = player.Position.Z, + RotationW = rotQuaternion.W, + RotationX = rotQuaternion.X, + RotationY = rotQuaternion.Y, + RotationZ = rotQuaternion.Z, + ScaleX = 1, + ScaleY = 1, + ScaleZ = 1 + }; } + + var loc = await _dalamudUtil.GetMapDataAsync().ConfigureAwait(false); + worldData.LocationInfo = loc; + + if (worldData != _lastWorldData) + { + await _apiController.GposeLobbyPushWorldData(worldData).ConfigureAwait(false); + _lastWorldData = worldData; + Logger.LogTrace("WorldData (gpose: {gpose}): {data}", _dalamudUtil.IsInGpose, worldData); + } + + foreach (var entry in _usersInLobby) + { + if (!entry.Value.HasWorldDataUpdate || _dalamudUtil.IsInGpose) continue; + + var entryWorldData = entry.Value.WorldData!.Value; + + if (worldData.LocationInfo.MapId == entryWorldData.LocationInfo.MapId && worldData.LocationInfo.DivisionId == entryWorldData.LocationInfo.DivisionId + && (worldData.LocationInfo.HouseId != entryWorldData.LocationInfo.HouseId + || worldData.LocationInfo.WardId != entryWorldData.LocationInfo.WardId + || entryWorldData.LocationInfo.ServerId != worldData.LocationInfo.ServerId)) + { + if (entry.Value.SpawnedVfxId == null) + { + // spawn if it doesn't exist yet + entry.Value.LastWorldPosition = new Vector3(entryWorldData.PositionX, entryWorldData.PositionY, entryWorldData.PositionZ); + entry.Value.SpawnedVfxId = await _dalamudUtil.RunOnFrameworkThread(() => _vfxSpawnManager.SpawnObject(entry.Value.LastWorldPosition.Value, + Quaternion.Identity, Vector3.One, 0.5f, 0.1f, 0.5f, 0.9f)).ConfigureAwait(false); + } + else + { + // move object via lerp if it does exist + var newPosition = new Vector3(entryWorldData.PositionX, entryWorldData.PositionY, entryWorldData.PositionZ); + if (newPosition != entry.Value.LastWorldPosition) + { + entry.Value.UpdateStart = DateTime.UtcNow; + entry.Value.TargetWorldPosition = newPosition; + } + } + } + else + { + await _dalamudUtil.RunOnFrameworkThread(() => _vfxSpawnManager.DespawnObject(entry.Value.SpawnedVfxId)).ConfigureAwait(false); + entry.Value.SpawnedVfxId = null; + } + } + } + catch (Exception ex) + { + Logger.LogWarning(ex, "Error during World Data Generation"); } } }