feat(ui): port retail item interaction policy

This commit is contained in:
Erik 2026-07-11 01:23:31 +02:00
parent 0cf780478a
commit a8da4fd05a
20 changed files with 1110 additions and 104 deletions

View file

@ -68,7 +68,8 @@ public static class GameEventWiring
Action<IReadOnlyList<PlayerDescriptionParser.ShortcutEntry>>? onShortcuts = null,
// B-Wire: the local player's server guid. When provided, the PD handler upserts
// the player's own PropertyBundle (EncumbranceVal etc.) into the player ClientObject.
Func<uint>? playerGuid = null)
Func<uint>? playerGuid = null,
Action<uint /*weenieError*/>? onUseDone = null)
{
ArgumentNullException.ThrowIfNull(dispatcher);
ArgumentNullException.ThrowIfNull(items);
@ -316,6 +317,7 @@ public static class GameEventWiring
uint? err = GameEvents.ParseUseDone(e.Payload.Span);
if (err is null) return;
Console.WriteLine($"[use-done] err=0x{err.Value:X4}");
onUseDone?.Invoke(err.Value);
if (err.Value != 0)
chat.OnSystemMessage(WeenieErrorText.For(err.Value), chatType: 0);
});

View file

@ -193,7 +193,8 @@ public static class CreateObject
// Nullable preserves the wire distinction between an absent flag and
// an explicitly transmitted zero (the enum's undefined/default value).
byte? RadarBlipColor = null,
byte? RadarBehavior = null);
byte? RadarBehavior = null,
byte? CombatUse = null);
/// <summary>
/// The relevant subset of the server-sent <c>MovementData</c> /
@ -750,6 +751,7 @@ public static class CreateObject
uint? targetType = null;
byte? radarBlipColor = null;
byte? radarBehavior = null;
byte? combatUse = null;
uint iconOverlayId = 0;
uint iconUnderlayId = 0;
uint uiEffects = 0;
@ -822,7 +824,7 @@ public static class CreateObject
if ((weenieFlags & 0x00000200u) != 0) // CombatUse sbyte (1 byte)
{
if (body.Length - pos < 1) throw new FormatException("trunc CombatUse");
pos += 1;
combatUse = body[pos]; pos += 1;
}
if ((weenieFlags & 0x00000400u) != 0) // Structure u16
{
@ -966,7 +968,8 @@ public static class CreateObject
ValidLocations: wValidLocations, CurrentWieldedLocation: wCurrentWieldedLocation,
Priority: wPriority, Structure: wStructure, MaxStructure: wMaxStructure,
Workmanship: wWorkmanship,
RadarBlipColor: radarBlipColor, RadarBehavior: radarBehavior);
RadarBlipColor: radarBlipColor, RadarBehavior: radarBehavior,
CombatUse: combatUse);
// Local helper: if we ran out of fields past PhysicsData, still
// return the useful prefix (guid/position/setup/animParts/textures/palettes/scale/motion).

View file

@ -85,5 +85,7 @@ public static class ObjectTableWiring
Useability: s.Useability,
TargetType: s.TargetType,
RadarBlipColor: s.RadarBlipColor,
RadarBehavior: s.RadarBehavior);
RadarBehavior: s.RadarBehavior,
PublicWeenieBitfield: s.ObjectDescriptionFlags,
CombatUse: s.CombatUse);
}

View file

@ -121,7 +121,8 @@ public sealed class WorldSession : IDisposable
// flag was absent; zero means the server explicitly sent the enum's
// undefined/default value.
byte? RadarBlipColor = null,
byte? RadarBehavior = null);
byte? RadarBehavior = null,
byte? CombatUse = null);
/// <summary>
/// Projects the wire-level CreateObject result into the stable session
@ -172,7 +173,8 @@ public sealed class WorldSession : IDisposable
MovementSequence: parsed.MovementSequence,
ServerControlSequence: parsed.ServerControlSequence,
RadarBlipColor: parsed.RadarBlipColor,
RadarBehavior: parsed.RadarBehavior);
RadarBehavior: parsed.RadarBehavior,
CombatUse: parsed.CombatUse);
/// <summary>Fires when the session finishes parsing a CreateObject.</summary>
public event Action<EntitySpawn>? EntitySpawned;