feat(D.5.2): thread UiEffects through EntitySpawn + route 0x02CE PublicUpdatePropertyInt
- EntitySpawn record: add UiEffects = 0 field (after IconUnderlayId) - EntitySpawn construction site: thread parsed.Value.UiEffects as the new tail arg - WorldSession: declare ObjectIntPropertyUpdate payload record + ObjectIntPropertyUpdated event (after StateUpdated) - Message loop: add else-if branch for PublicUpdatePropertyInt.Opcode (0x02CE), parses + fires ObjectIntPropertyUpdated Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
242bc9286d
commit
e7b6e83cf8
1 changed files with 27 additions and 2 deletions
|
|
@ -88,7 +88,10 @@ public sealed class WorldSession : IDisposable
|
||||||
// (0x40000000) and WeenieHeaderFlag2.IconUnderlay (0x01) respectively.
|
// (0x40000000) and WeenieHeaderFlag2.IconUnderlay (0x01) respectively.
|
||||||
// Zero when the server did not send the field (common for most entities).
|
// Zero when the server did not send the field (common for most entities).
|
||||||
uint IconOverlayId = 0,
|
uint IconOverlayId = 0,
|
||||||
uint IconUnderlayId = 0);
|
uint IconUnderlayId = 0,
|
||||||
|
// D.5.2 (2026-06-17): UiEffects bitfield (weenieFlags 0x80) — drives the icon's
|
||||||
|
// effect recolor. CreateObject-only; 0 = no effect.
|
||||||
|
uint UiEffects = 0);
|
||||||
|
|
||||||
/// <summary>Fires when the session finishes parsing a CreateObject.</summary>
|
/// <summary>Fires when the session finishes parsing a CreateObject.</summary>
|
||||||
public event Action<EntitySpawn>? EntitySpawned;
|
public event Action<EntitySpawn>? EntitySpawned;
|
||||||
|
|
@ -161,6 +164,20 @@ public sealed class WorldSession : IDisposable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<SetState.Parsed>? StateUpdated;
|
public event Action<SetState.Parsed>? StateUpdated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Payload for <see cref="ObjectIntPropertyUpdated"/>: a single PropertyInt change on
|
||||||
|
/// a visible object (from PublicUpdatePropertyInt 0x02CE). Subscribers map the
|
||||||
|
/// property to typed state (e.g. UiEffects → the item's icon effect).
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct ObjectIntPropertyUpdate(uint Guid, uint Property, int Value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires when the session parses a PublicUpdatePropertyInt (0x02CE) — one
|
||||||
|
/// PropertyInt updated on a visible object. D.5.2 routes UiEffects (18) to the
|
||||||
|
/// item repository so the icon re-composites live.
|
||||||
|
/// </summary>
|
||||||
|
public event Action<ObjectIntPropertyUpdate>? ObjectIntPropertyUpdated;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fires when the server sends a PlayerTeleport (0xF751) game message,
|
/// Fires when the server sends a PlayerTeleport (0xF751) game message,
|
||||||
/// signalling that the player is entering portal space. The uint payload
|
/// signalling that the player is entering portal space. The uint payload
|
||||||
|
|
@ -727,7 +744,8 @@ public sealed class WorldSession : IDisposable
|
||||||
parsed.Value.UseRadius,
|
parsed.Value.UseRadius,
|
||||||
parsed.Value.IconId,
|
parsed.Value.IconId,
|
||||||
parsed.Value.IconOverlayId,
|
parsed.Value.IconOverlayId,
|
||||||
parsed.Value.IconUnderlayId));
|
parsed.Value.IconUnderlayId,
|
||||||
|
parsed.Value.UiEffects));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (op == DeleteObject.Opcode)
|
else if (op == DeleteObject.Opcode)
|
||||||
|
|
@ -901,6 +919,13 @@ public sealed class WorldSession : IDisposable
|
||||||
if (parsed is not null)
|
if (parsed is not null)
|
||||||
VitalCurrentUpdated?.Invoke(parsed.Value);
|
VitalCurrentUpdated?.Invoke(parsed.Value);
|
||||||
}
|
}
|
||||||
|
else if (op == PublicUpdatePropertyInt.Opcode)
|
||||||
|
{
|
||||||
|
var p = PublicUpdatePropertyInt.TryParse(body);
|
||||||
|
if (p is not null)
|
||||||
|
ObjectIntPropertyUpdated?.Invoke(
|
||||||
|
new ObjectIntPropertyUpdate(p.Value.Guid, p.Value.Property, p.Value.Value));
|
||||||
|
}
|
||||||
else if (op == GameEventEnvelope.Opcode)
|
else if (op == GameEventEnvelope.Opcode)
|
||||||
{
|
{
|
||||||
// Phase F.1: 0xF7B0 is the GameEvent envelope. Parse the
|
// Phase F.1: 0xF7B0 is the GameEvent envelope. Parse the
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue