fix: Hair and facial hair "teleporting" when mobile dies several times (#1901)

### Summary

* Added World.NewVirtual for creating virtual serial numbers
* Reserved range 0x7EEEEEEE to 0x7FFFFFFF for virtual serials
* Hair and Facial hair (for mobiles) now use virtual serials instead of FakeSerial() functions
* Consolidated virtual hair to a single `VirtualHairInfo` class.

Corpse hair and facial hair now persists across save/load and hair and facial hair no longer teleport to newest corpse.
This commit is contained in:
mdodkins 2024-08-08 04:10:23 +01:00 committed by GitHub
parent 883d873c1c
commit 91e37fb8d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 548 additions and 357 deletions

View file

@ -53,13 +53,37 @@ public static class World
public const bool DirtyTrackingEnabled = false;
public const uint ItemOffset = 0x40000000;
public const uint MaxItemSerial = 0x7FFFFFFF;
public const uint MaxItemSerial = 0x7EEEEEEE;
public const uint MaxMobileSerial = ItemOffset - 1;
public const uint ResetVirtualSerial = MaxItemSerial;
public const uint MaxVirtualSerial = 0x7FFFFFFF;
private static uint _nextVirtualSerial = ResetVirtualSerial;
public static Serial NewMobile => _mobilePersistence.NewEntity;
public static Serial NewItem => _itemPersistence.NewEntity;
public static Serial NewGuild => _guildPersistence.NewEntity;
// Virtual things don't persist across saves
public static Serial NewVirtual
{
get
{
#if THREADGUARD
if (Thread.CurrentThread != Core.Thread)
{
logger.Error(
"Attempted to get a new virtual serial from the wrong thread!\n{StackTrace}",
new StackTrace()
);
}
#endif
var value = _nextVirtualSerial > MaxVirtualSerial ? ResetVirtualSerial : _nextVirtualSerial;
_nextVirtualSerial = value + 1;
return (Serial)value;
}
}
public static Dictionary<Serial, Item> Items => _itemPersistence.EntitiesBySerial;
public static Dictionary<Serial, Mobile> Mobiles => _mobilePersistence.EntitiesBySerial;
public static Dictionary<Serial, BaseGuild> Guilds => _guildPersistence.EntitiesBySerial;