feat(ui): port retail radar and compass

This commit is contained in:
Erik 2026-07-10 16:14:37 +02:00
parent c4af181b92
commit 3cbe4b00a1
43 changed files with 2882 additions and 262 deletions

View file

@ -116,7 +116,63 @@ public sealed class WorldSession : IDisposable
// MOVEMENT_TS / SERVER_CONTROLLED_MOVE_TS).
ushort InstanceSequence = 0,
ushort MovementSequence = 0,
ushort ServerControlSequence = 0);
ushort ServerControlSequence = 0,
// PublicWeenieDesc optional-tail bytes. null means the corresponding
// flag was absent; zero means the server explicitly sent the enum's
// undefined/default value.
byte? RadarBlipColor = null,
byte? RadarBehavior = null);
/// <summary>
/// Projects the wire-level CreateObject result into the stable session
/// event payload. Kept as a focused seam so every optional field's
/// absent-versus-explicit-default semantics can be tested without a UDP
/// session.
/// </summary>
internal static EntitySpawn ToEntitySpawn(CreateObject.Parsed parsed) => new(
parsed.Guid,
parsed.Position,
parsed.SetupTableId,
parsed.AnimPartChanges,
parsed.TextureChanges,
parsed.SubPalettes,
parsed.BasePaletteId,
parsed.ObjScale,
parsed.Name,
parsed.ItemType,
parsed.MotionState,
parsed.MotionTableId,
parsed.PhysicsState,
parsed.ObjectDescriptionFlags,
parsed.Friction,
parsed.Elasticity,
parsed.Useability,
parsed.UseRadius,
parsed.TargetType,
parsed.IconId,
parsed.IconOverlayId,
parsed.IconUnderlayId,
parsed.UiEffects,
parsed.WeenieClassId,
parsed.Value,
parsed.StackSize,
parsed.StackSizeMax,
parsed.Burden,
parsed.ItemsCapacity,
parsed.ContainersCapacity,
parsed.ContainerId,
parsed.WielderId,
parsed.ValidLocations,
parsed.CurrentWieldedLocation,
parsed.Priority,
parsed.Structure,
parsed.MaxStructure,
parsed.Workmanship,
InstanceSequence: parsed.InstanceSequence,
MovementSequence: parsed.MovementSequence,
ServerControlSequence: parsed.ServerControlSequence,
RadarBlipColor: parsed.RadarBlipColor,
RadarBehavior: parsed.RadarBehavior);
/// <summary>Fires when the session finishes parsing a CreateObject.</summary>
public event Action<EntitySpawn>? EntitySpawned;
@ -799,48 +855,7 @@ public sealed class WorldSession : IDisposable
_forcePositionSequence = parsed.Value.ForcePositionSequence;
}
EntitySpawned?.Invoke(new EntitySpawn(
parsed.Value.Guid,
parsed.Value.Position,
parsed.Value.SetupTableId,
parsed.Value.AnimPartChanges,
parsed.Value.TextureChanges,
parsed.Value.SubPalettes,
parsed.Value.BasePaletteId,
parsed.Value.ObjScale,
parsed.Value.Name,
parsed.Value.ItemType,
parsed.Value.MotionState,
parsed.Value.MotionTableId,
parsed.Value.PhysicsState,
parsed.Value.ObjectDescriptionFlags,
parsed.Value.Friction,
parsed.Value.Elasticity,
parsed.Value.Useability,
parsed.Value.UseRadius,
parsed.Value.TargetType,
parsed.Value.IconId,
parsed.Value.IconOverlayId,
parsed.Value.IconUnderlayId,
parsed.Value.UiEffects,
parsed.Value.WeenieClassId,
parsed.Value.Value,
parsed.Value.StackSize,
parsed.Value.StackSizeMax,
parsed.Value.Burden,
parsed.Value.ItemsCapacity,
parsed.Value.ContainersCapacity,
parsed.Value.ContainerId,
parsed.Value.WielderId,
parsed.Value.ValidLocations,
parsed.Value.CurrentWieldedLocation,
parsed.Value.Priority,
parsed.Value.Structure,
parsed.Value.MaxStructure,
parsed.Value.Workmanship,
InstanceSequence: parsed.Value.InstanceSequence,
MovementSequence: parsed.Value.MovementSequence,
ServerControlSequence: parsed.Value.ServerControlSequence));
EntitySpawned?.Invoke(ToEntitySpawn(parsed.Value));
}
}
else if (op == DeleteObject.Opcode)