Skip to content

Commit c3be151

Browse files
committed
Maybe fix crash issue in AtchHook1 / issue with kept draw object links.
1 parent abb4775 commit c3be151

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

Penumbra/Interop/Hooks/Objects/CharacterDestructor.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public enum Priority
1515

1616
/// <seealso cref="PathResolving.IdentifiedCollectionCache"/>
1717
IdentifiedCollectionCache = 0,
18+
19+
/// <seealso cref="PathResolving.DrawObjectState.OnCharacterDestructor"/>
20+
DrawObjectState = 0,
1821
}
1922

2023
public CharacterDestructor(HookManager hooks)

Penumbra/Interop/PathResolving/DrawObjectState.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public sealed class DrawObjectState : IDisposable, IReadOnlyDictionary<nint, (ni
1515
private readonly CreateCharacterBase _createCharacterBase;
1616
private readonly WeaponReload _weaponReload;
1717
private readonly CharacterBaseDestructor _characterBaseDestructor;
18+
private readonly CharacterDestructor _characterDestructor;
1819
private readonly GameState _gameState;
1920

2021
private readonly Dictionary<nint, (nint GameObject, bool IsChild)> _drawObjectToGameObject = [];
@@ -23,21 +24,24 @@ public nint LastGameObject
2324
=> _gameState.LastGameObject;
2425

2526
public unsafe DrawObjectState(ObjectManager objects, CreateCharacterBase createCharacterBase, WeaponReload weaponReload,
26-
CharacterBaseDestructor characterBaseDestructor, GameState gameState, IFramework framework)
27+
CharacterBaseDestructor characterBaseDestructor, GameState gameState, IFramework framework, CharacterDestructor characterDestructor)
2728
{
2829
_objects = objects;
2930
_createCharacterBase = createCharacterBase;
3031
_weaponReload = weaponReload;
3132
_characterBaseDestructor = characterBaseDestructor;
3233
_gameState = gameState;
34+
_characterDestructor = characterDestructor;
3335
framework.RunOnFrameworkThread(InitializeDrawObjects);
3436

3537
_weaponReload.Subscribe(OnWeaponReloading, WeaponReload.Priority.DrawObjectState);
3638
_weaponReload.Subscribe(OnWeaponReloaded, WeaponReload.PostEvent.Priority.DrawObjectState);
3739
_createCharacterBase.Subscribe(OnCharacterBaseCreated, CreateCharacterBase.PostEvent.Priority.DrawObjectState);
3840
_characterBaseDestructor.Subscribe(OnCharacterBaseDestructor, CharacterBaseDestructor.Priority.DrawObjectState);
41+
_characterDestructor.Subscribe(OnCharacterDestructor, CharacterDestructor.Priority.DrawObjectState);
3942
}
4043

44+
4145
public bool ContainsKey(nint key)
4246
=> _drawObjectToGameObject.ContainsKey(key);
4347

@@ -68,6 +72,36 @@ public unsafe void Dispose()
6872
_weaponReload.Unsubscribe(OnWeaponReloaded);
6973
_createCharacterBase.Unsubscribe(OnCharacterBaseCreated);
7074
_characterBaseDestructor.Unsubscribe(OnCharacterBaseDestructor);
75+
_characterDestructor.Unsubscribe(OnCharacterDestructor);
76+
}
77+
78+
/// <remarks>
79+
/// Seems like sometimes the draw object of a game object is destroyed in frames after the original game object is already destroyed.
80+
/// So protect against outdated game object pointers in the dictionary.
81+
/// </remarks>
82+
private unsafe void OnCharacterDestructor(Character* a)
83+
{
84+
if (a is null)
85+
return;
86+
87+
var character = (nint)a;
88+
var delete = stackalloc nint[5];
89+
var current = 0;
90+
foreach (var (drawObject, (gameObject, _)) in _drawObjectToGameObject)
91+
{
92+
if (gameObject != character)
93+
continue;
94+
95+
delete[current++] = drawObject;
96+
if (current is 4)
97+
break;
98+
}
99+
100+
for (var ptr = delete; *ptr != nint.Zero; ++ptr)
101+
{
102+
_drawObjectToGameObject.Remove(*ptr, out var pair);
103+
Penumbra.Log.Excessive($"[DrawObjectState] Removed draw object 0x{*ptr:X} -> 0x{(nint)a:X} (actual: 0x{pair.GameObject:X}, {pair.IsChild}).");
104+
}
71105
}
72106

73107
private unsafe void OnWeaponReloading(DrawDataContainer* _, Character* character, CharacterWeapon* _2)

Penumbra/UI/Changelog.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ private static void Add1_3_6_0(Changelog log)
9090
.RegisterEntry("The EQP entry previously named Unknown 4 was renamed to 'Hide Glove Cuffs'.")
9191
.RegisterEntry("Fixed the changed item identification for EST changes.")
9292
.RegisterEntry("Fixed clipping issues in the changed items panel when no grouping was active.");
93-
9493

9594

9695
private static void Add1_3_5_0(Changelog log)

0 commit comments

Comments
 (0)