refactor(runtime): own canonical entity and object lifetime
Introduce one presentation-free RuntimeEntityObjectLifetime for the exact entity directory and ClientObjectTable. Make GameWindow, graphical projections, retained UI, interaction, session routing, create/delete integration, and reset borrow that owner while preserving synchronous retail ordering, dormant retention, and retry semantics. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
d9bf4c4960
commit
5ef8b5371d
40 changed files with 712 additions and 170 deletions
|
|
@ -25,6 +25,7 @@ using AcDream.Core.Rendering;
|
||||||
using AcDream.Core.Selection;
|
using AcDream.Core.Selection;
|
||||||
using AcDream.Core.Vfx;
|
using AcDream.Core.Vfx;
|
||||||
using AcDream.Core.World;
|
using AcDream.Core.World;
|
||||||
|
using AcDream.Runtime.Entities;
|
||||||
using DatReaderWriter;
|
using DatReaderWriter;
|
||||||
using DatReaderWriter.DBObjs;
|
using DatReaderWriter.DBObjs;
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
|
|
@ -44,7 +45,7 @@ internal sealed record LivePresentationDependencies(
|
||||||
WorldGameState WorldGameState,
|
WorldGameState WorldGameState,
|
||||||
WorldEvents WorldEvents,
|
WorldEvents WorldEvents,
|
||||||
SelectionState Selection,
|
SelectionState Selection,
|
||||||
ClientObjectTable Objects,
|
RuntimeEntityObjectLifetime EntityObjects,
|
||||||
LiveEntityRuntimeSlot RuntimeSlot,
|
LiveEntityRuntimeSlot RuntimeSlot,
|
||||||
DeferredLiveEntityMotionRuntimeBindings MotionBindings,
|
DeferredLiveEntityMotionRuntimeBindings MotionBindings,
|
||||||
DeferredEntityEffectAdvanceSource EffectAdvance,
|
DeferredEntityEffectAdvanceSource EffectAdvance,
|
||||||
|
|
@ -377,7 +378,8 @@ internal sealed class LivePresentationCompositionPhase
|
||||||
worldState,
|
worldState,
|
||||||
new CompositeLiveEntityResourceLifecycle(
|
new CompositeLiveEntityResourceLifecycle(
|
||||||
[.. resourceOwners]),
|
[.. resourceOwners]),
|
||||||
componentLifecycle);
|
componentLifecycle,
|
||||||
|
d.EntityObjects);
|
||||||
var liveRuntimeLease = scope.Own(
|
var liveRuntimeLease = scope.Own(
|
||||||
"canonical live-entity runtime",
|
"canonical live-entity runtime",
|
||||||
liveEntities,
|
liveEntities,
|
||||||
|
|
@ -487,7 +489,7 @@ internal sealed class LivePresentationCompositionPhase
|
||||||
() => new EquippedChildRenderController(
|
() => new EquippedChildRenderController(
|
||||||
content.Dats,
|
content.Dats,
|
||||||
d.DatLock,
|
d.DatLock,
|
||||||
d.Objects,
|
d.EntityObjects.Objects,
|
||||||
liveEntities,
|
liveEntities,
|
||||||
d.EffectPoses,
|
d.EffectPoses,
|
||||||
parentAcceptance.TryAccept,
|
parentAcceptance.TryAccept,
|
||||||
|
|
@ -675,7 +677,7 @@ internal sealed class LivePresentationCompositionPhase
|
||||||
static value => value.Dispose());
|
static value => value.Dispose());
|
||||||
var selectionQuery = new WorldSelectionQuery(
|
var selectionQuery = new WorldSelectionQuery(
|
||||||
liveEntities,
|
liveEntities,
|
||||||
d.Objects,
|
d.EntityObjects.Objects,
|
||||||
selectionScene,
|
selectionScene,
|
||||||
() => d.PlayerIdentity.ServerGuid,
|
() => d.PlayerIdentity.ServerGuid,
|
||||||
interaction.LateBindings.SelectionCamera.Snapshot,
|
interaction.LateBindings.SelectionCamera.Snapshot,
|
||||||
|
|
@ -699,7 +701,7 @@ internal sealed class LivePresentationCompositionPhase
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var radarSnapshotProvider = new RadarSnapshotProvider(
|
var radarSnapshotProvider = new RadarSnapshotProvider(
|
||||||
d.Objects,
|
d.EntityObjects.Objects,
|
||||||
liveEntities,
|
liveEntities,
|
||||||
() => liveEntities.Snapshots,
|
() => liveEntities.Snapshots,
|
||||||
playerGuid: () => d.PlayerIdentity.ServerGuid,
|
playerGuid: () => d.PlayerIdentity.ServerGuid,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ using AcDream.Core.Player;
|
||||||
using AcDream.Core.Social;
|
using AcDream.Core.Social;
|
||||||
using AcDream.Core.Spells;
|
using AcDream.Core.Spells;
|
||||||
using AcDream.Core.World;
|
using AcDream.Core.World;
|
||||||
|
using AcDream.Runtime.Entities;
|
||||||
using AcDream.Runtime.Session;
|
using AcDream.Runtime.Session;
|
||||||
using Silk.NET.Windowing;
|
using Silk.NET.Windowing;
|
||||||
|
|
||||||
|
|
@ -47,7 +48,7 @@ internal sealed record SessionPlayerDependencies(
|
||||||
WorldGameState WorldGameState,
|
WorldGameState WorldGameState,
|
||||||
WorldEvents WorldEvents,
|
WorldEvents WorldEvents,
|
||||||
SelectionState Selection,
|
SelectionState Selection,
|
||||||
ClientObjectTable Objects,
|
RuntimeEntityObjectLifetime EntityObjects,
|
||||||
EntityClassificationCache ClassificationCache,
|
EntityClassificationCache ClassificationCache,
|
||||||
LiveEntityRuntimeSlot RuntimeSlot,
|
LiveEntityRuntimeSlot RuntimeSlot,
|
||||||
LiveEntityAnimationRuntimeView<LiveEntityAnimationState> AnimatedEntities,
|
LiveEntityAnimationRuntimeView<LiveEntityAnimationState> AnimatedEntities,
|
||||||
|
|
@ -475,14 +476,14 @@ internal sealed class SessionPlayerCompositionPhase
|
||||||
var dormantLiveEntities = new DormantLiveEntityStore();
|
var dormantLiveEntities = new DormantLiveEntityStore();
|
||||||
var deletion = new LiveEntityDeletionController(
|
var deletion = new LiveEntityDeletionController(
|
||||||
live.LiveEntities,
|
live.LiveEntities,
|
||||||
d.Objects,
|
d.EntityObjects,
|
||||||
teardown,
|
teardown,
|
||||||
d.PlayerIdentity,
|
d.PlayerIdentity,
|
||||||
dormantLiveEntities,
|
dormantLiveEntities,
|
||||||
d.Options.DumpLiveSpawns ? d.Log : null);
|
d.Options.DumpLiveSpawns ? d.Log : null);
|
||||||
var hydration = new LiveEntityHydrationController(
|
var hydration = new LiveEntityHydrationController(
|
||||||
live.LiveEntities,
|
live.LiveEntities,
|
||||||
d.Objects,
|
d.EntityObjects,
|
||||||
d.DatLock,
|
d.DatLock,
|
||||||
projectionMaterializer,
|
projectionMaterializer,
|
||||||
new LiveEntityRelationshipProjection(live.EquippedChildren),
|
new LiveEntityRelationshipProjection(live.EquippedChildren),
|
||||||
|
|
@ -505,7 +506,7 @@ internal sealed class SessionPlayerCompositionPhase
|
||||||
|
|
||||||
var networkUpdates = new LiveEntityNetworkUpdateController(
|
var networkUpdates = new LiveEntityNetworkUpdateController(
|
||||||
live.LiveEntities,
|
live.LiveEntities,
|
||||||
d.Objects,
|
d.EntityObjects.Objects,
|
||||||
hydration,
|
hydration,
|
||||||
live.EntityEffects,
|
live.EntityEffects,
|
||||||
live.Presentation,
|
live.Presentation,
|
||||||
|
|
@ -574,7 +575,7 @@ internal sealed class SessionPlayerCompositionPhase
|
||||||
new CombatAttackTargetSource(
|
new CombatAttackTargetSource(
|
||||||
d.Selection,
|
d.Selection,
|
||||||
live.LiveEntities,
|
live.LiveEntities,
|
||||||
d.Objects,
|
d.EntityObjects.Objects,
|
||||||
d.PlayerIdentity),
|
d.PlayerIdentity),
|
||||||
d.Settings,
|
d.Settings,
|
||||||
d.PlayerController,
|
d.PlayerController,
|
||||||
|
|
@ -809,7 +810,7 @@ internal sealed class SessionPlayerCompositionPhase
|
||||||
d.Shortcuts,
|
d.Shortcuts,
|
||||||
d.DesiredComponents),
|
d.DesiredComponents),
|
||||||
new LiveSessionDomainRuntime(
|
new LiveSessionDomainRuntime(
|
||||||
d.Objects,
|
d.EntityObjects,
|
||||||
d.LocalPlayer,
|
d.LocalPlayer,
|
||||||
d.Spellbook,
|
d.Spellbook,
|
||||||
d.Combat,
|
d.Combat,
|
||||||
|
|
@ -873,7 +874,7 @@ internal sealed class SessionPlayerCompositionPhase
|
||||||
var combatCommand = new LiveCombatModeCommandController(
|
var combatCommand = new LiveCombatModeCommandController(
|
||||||
new LiveSessionCombatModeAuthority(sessionHost),
|
new LiveSessionCombatModeAuthority(sessionHost),
|
||||||
new LocalPlayerCombatEquipmentSource(
|
new LocalPlayerCombatEquipmentSource(
|
||||||
d.Objects,
|
d.EntityObjects.Objects,
|
||||||
d.PlayerIdentity),
|
d.PlayerIdentity),
|
||||||
d.Combat,
|
d.Combat,
|
||||||
new ItemInteractionCombatModeIntentSink(
|
new ItemInteractionCombatModeIntentSink(
|
||||||
|
|
@ -890,7 +891,7 @@ internal sealed class SessionPlayerCompositionPhase
|
||||||
liveSessionCommands,
|
liveSessionCommands,
|
||||||
d.PlayerIdentity,
|
d.PlayerIdentity,
|
||||||
live.LiveEntities,
|
live.LiveEntities,
|
||||||
d.Objects,
|
d.EntityObjects.Objects,
|
||||||
d.Chat,
|
d.Chat,
|
||||||
d.PlayerController,
|
d.PlayerController,
|
||||||
worldReveal,
|
worldReveal,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ using AcDream.Core.Social;
|
||||||
using AcDream.Core.Spells;
|
using AcDream.Core.Spells;
|
||||||
using AcDream.Core.World;
|
using AcDream.Core.World;
|
||||||
using AcDream.Content;
|
using AcDream.Content;
|
||||||
|
using AcDream.Runtime.Entities;
|
||||||
using AcDream.Runtime.Session;
|
using AcDream.Runtime.Session;
|
||||||
using AcDream.UI.Abstractions.Panels.Chat;
|
using AcDream.UI.Abstractions.Panels.Chat;
|
||||||
using AcDream.UI.Abstractions.Panels.Vitals;
|
using AcDream.UI.Abstractions.Panels.Vitals;
|
||||||
|
|
@ -41,7 +42,7 @@ internal sealed record LiveSessionPlayerRuntime(
|
||||||
DesiredComponentSnapshotState DesiredComponents);
|
DesiredComponentSnapshotState DesiredComponents);
|
||||||
|
|
||||||
internal sealed record LiveSessionDomainRuntime(
|
internal sealed record LiveSessionDomainRuntime(
|
||||||
ClientObjectTable Objects,
|
RuntimeEntityObjectLifetime EntityObjects,
|
||||||
LocalPlayerState LocalPlayer,
|
LocalPlayerState LocalPlayer,
|
||||||
Spellbook Spellbook,
|
Spellbook Spellbook,
|
||||||
CombatState Combat,
|
CombatState Combat,
|
||||||
|
|
@ -173,7 +174,7 @@ internal sealed class LiveSessionRuntimeFactory
|
||||||
ExternalContainer = () => _domain.ExternalContainers.Reset(),
|
ExternalContainer = () => _domain.ExternalContainers.Reset(),
|
||||||
InteractionAndSelection = _interaction.SelectionInteractions.ResetSession,
|
InteractionAndSelection = _interaction.SelectionInteractions.ResetSession,
|
||||||
SelectionPresentation = _world.SelectionScene.Reset,
|
SelectionPresentation = _world.SelectionScene.Reset,
|
||||||
ObjectTable = _domain.Objects.Clear,
|
ObjectTable = _domain.EntityObjects.ClearObjects,
|
||||||
Spellbook = _domain.Spellbook.Clear,
|
Spellbook = _domain.Spellbook.Clear,
|
||||||
MagicRuntime = () => _ui.Magic?.Reset(),
|
MagicRuntime = () => _ui.Magic?.Reset(),
|
||||||
CombatAttack = _interaction.CombatAttack.ResetSession,
|
CombatAttack = _interaction.CombatAttack.ResetSession,
|
||||||
|
|
@ -260,7 +261,7 @@ internal sealed class LiveSessionRuntimeFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private LiveInventorySessionBindings CreateInventoryBindings() => new(
|
private LiveInventorySessionBindings CreateInventoryBindings() => new(
|
||||||
_domain.Objects,
|
_domain.EntityObjects.Objects,
|
||||||
_domain.LocalPlayer,
|
_domain.LocalPlayer,
|
||||||
PlayerGuid: () => _player.Identity.ServerGuid,
|
PlayerGuid: () => _player.Identity.ServerGuid,
|
||||||
OnShortcuts: list => _player.Shortcuts.Items = list,
|
OnShortcuts: list => _player.Shortcuts.Items = list,
|
||||||
|
|
@ -333,7 +334,7 @@ internal sealed class LiveSessionRuntimeFactory
|
||||||
ShowSystemMessage: text => _domain.Chat.OnSystemMessage(text, 0u),
|
ShowSystemMessage: text => _domain.Chat.OnSystemMessage(text, 0u),
|
||||||
ShowWeenieError: code => _domain.Chat.OnWeenieError(code, null),
|
ShowWeenieError: code => _domain.Chat.OnWeenieError(code, null),
|
||||||
PlayerPublicWeenieBitfield: () =>
|
PlayerPublicWeenieBitfield: () =>
|
||||||
_domain.Objects.Get(_player.Identity.ServerGuid)?
|
_domain.EntityObjects.Objects.Get(_player.Identity.ServerGuid)?
|
||||||
.PublicWeenieBitfield,
|
.PublicWeenieBitfield,
|
||||||
ClientVersion: () =>
|
ClientVersion: () =>
|
||||||
typeof(LiveSessionRuntimeFactory).Assembly
|
typeof(LiveSessionRuntimeFactory).Assembly
|
||||||
|
|
@ -351,7 +352,7 @@ internal sealed class LiveSessionRuntimeFactory
|
||||||
SaveAutoUi: () => _ui.RetailUi?.SaveLayout(),
|
SaveAutoUi: () => _ui.RetailUi?.SaveLayout(),
|
||||||
LoadAutoUi: () => _ui.RetailUi?.RestoreLayout(),
|
LoadAutoUi: () => _ui.RetailUi?.RestoreLayout(),
|
||||||
IsAway: () =>
|
IsAway: () =>
|
||||||
_domain.Objects.Get(_player.Identity.ServerGuid)?
|
_domain.EntityObjects.Objects.Get(_player.Identity.ServerGuid)?
|
||||||
.Properties.GetBool(0x6Eu) == true,
|
.Properties.GetBool(0x6Eu) == true,
|
||||||
SetAway: session.SendSetAfkMode,
|
SetAway: session.SendSetAfkMode,
|
||||||
SetAwayMessage: session.SendSetAfkMessage,
|
SetAwayMessage: session.SendSetAfkMessage,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using AcDream.App.Rendering.Wb;
|
||||||
using AcDream.App.Settings;
|
using AcDream.App.Settings;
|
||||||
using AcDream.App.World;
|
using AcDream.App.World;
|
||||||
using AcDream.Content;
|
using AcDream.Content;
|
||||||
|
using AcDream.Runtime.Entities;
|
||||||
using AcDream.Runtime.Session;
|
using AcDream.Runtime.Session;
|
||||||
using DatReaderWriter;
|
using DatReaderWriter;
|
||||||
using Silk.NET.Input;
|
using Silk.NET.Input;
|
||||||
|
|
@ -340,7 +341,7 @@ public sealed class GameWindow :
|
||||||
// installs that immutable table once DatCollection opens in OnLoad.
|
// installs that immutable table once DatCollection opens in OnLoad.
|
||||||
public AcDream.Core.Spells.SpellTable SpellTable => SpellBook.Metadata;
|
public AcDream.Core.Spells.SpellTable SpellTable => SpellBook.Metadata;
|
||||||
public readonly AcDream.Core.Spells.Spellbook SpellBook = null!;
|
public readonly AcDream.Core.Spells.Spellbook SpellBook = null!;
|
||||||
public readonly AcDream.Core.Items.ClientObjectTable Objects = new();
|
private readonly RuntimeEntityObjectLifetime _runtimeEntityObjects = new();
|
||||||
/// <summary>Persisted hotbar shortcuts from the last PlayerDescription (D.5.1 toolbar source).</summary>
|
/// <summary>Persisted hotbar shortcuts from the last PlayerDescription (D.5.1 toolbar source).</summary>
|
||||||
private readonly ShortcutSnapshotState _shortcutSnapshots = new();
|
private readonly ShortcutSnapshotState _shortcutSnapshots = new();
|
||||||
public IReadOnlyList<AcDream.Core.Items.ShortcutEntry> Shortcuts
|
public IReadOnlyList<AcDream.Core.Items.ShortcutEntry> Shortcuts
|
||||||
|
|
@ -1260,7 +1261,7 @@ public sealed class GameWindow :
|
||||||
_combatAttackOperations,
|
_combatAttackOperations,
|
||||||
_selection,
|
_selection,
|
||||||
_externalContainers,
|
_externalContainers,
|
||||||
Objects,
|
_runtimeEntityObjects.Objects,
|
||||||
contentEffectsAudio.MagicCatalog,
|
contentEffectsAudio.MagicCatalog,
|
||||||
SpellBook,
|
SpellBook,
|
||||||
Chat,
|
Chat,
|
||||||
|
|
@ -1314,7 +1315,7 @@ public sealed class GameWindow :
|
||||||
_worldGameState,
|
_worldGameState,
|
||||||
_worldEvents,
|
_worldEvents,
|
||||||
_selection,
|
_selection,
|
||||||
Objects,
|
_runtimeEntityObjects,
|
||||||
_liveEntityRuntimeSlot,
|
_liveEntityRuntimeSlot,
|
||||||
_liveEntityMotionBindings,
|
_liveEntityMotionBindings,
|
||||||
_entityEffectAdvance,
|
_entityEffectAdvance,
|
||||||
|
|
@ -1372,7 +1373,7 @@ public sealed class GameWindow :
|
||||||
_worldGameState,
|
_worldGameState,
|
||||||
_worldEvents,
|
_worldEvents,
|
||||||
_selection,
|
_selection,
|
||||||
Objects,
|
_runtimeEntityObjects,
|
||||||
_classificationCache,
|
_classificationCache,
|
||||||
_liveEntityRuntimeSlot,
|
_liveEntityRuntimeSlot,
|
||||||
_animatedEntities,
|
_animatedEntities,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using AcDream.App.Input;
|
using AcDream.App.Input;
|
||||||
using AcDream.Core.Items;
|
|
||||||
using AcDream.Core.Net;
|
using AcDream.Core.Net;
|
||||||
using AcDream.Core.Net.Messages;
|
using AcDream.Core.Net.Messages;
|
||||||
|
using AcDream.Runtime.Entities;
|
||||||
|
|
||||||
namespace AcDream.App.World;
|
namespace AcDream.App.World;
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ internal interface ILiveEntityPruneSink
|
||||||
internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
|
internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
|
||||||
{
|
{
|
||||||
private readonly LiveEntityRuntime _runtime;
|
private readonly LiveEntityRuntime _runtime;
|
||||||
private readonly ClientObjectTable _objects;
|
private readonly RuntimeEntityObjectLifetime _entityObjects;
|
||||||
private readonly ILiveEntityTeardownCoordinator _teardown;
|
private readonly ILiveEntityTeardownCoordinator _teardown;
|
||||||
private readonly ILocalPlayerIdentitySource _identity;
|
private readonly ILocalPlayerIdentitySource _identity;
|
||||||
private readonly DormantLiveEntityStore _dormant;
|
private readonly DormantLiveEntityStore _dormant;
|
||||||
|
|
@ -25,14 +25,15 @@ internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
|
||||||
|
|
||||||
public LiveEntityDeletionController(
|
public LiveEntityDeletionController(
|
||||||
LiveEntityRuntime runtime,
|
LiveEntityRuntime runtime,
|
||||||
ClientObjectTable objects,
|
RuntimeEntityObjectLifetime entityObjects,
|
||||||
ILiveEntityTeardownCoordinator teardown,
|
ILiveEntityTeardownCoordinator teardown,
|
||||||
ILocalPlayerIdentitySource identity,
|
ILocalPlayerIdentitySource identity,
|
||||||
DormantLiveEntityStore? dormant = null,
|
DormantLiveEntityStore? dormant = null,
|
||||||
Action<string>? diagnostic = null)
|
Action<string>? diagnostic = null)
|
||||||
{
|
{
|
||||||
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
||||||
_objects = objects ?? throw new ArgumentNullException(nameof(objects));
|
_entityObjects = entityObjects
|
||||||
|
?? throw new ArgumentNullException(nameof(entityObjects));
|
||||||
_teardown = teardown ?? throw new ArgumentNullException(nameof(teardown));
|
_teardown = teardown ?? throw new ArgumentNullException(nameof(teardown));
|
||||||
_identity = identity ?? throw new ArgumentNullException(nameof(identity));
|
_identity = identity ?? throw new ArgumentNullException(nameof(identity));
|
||||||
_dormant = dormant ?? new DormantLiveEntityStore();
|
_dormant = dormant ?? new DormantLiveEntityStore();
|
||||||
|
|
@ -56,11 +57,10 @@ internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
|
||||||
bool removed = _runtime.UnregisterLiveEntity(
|
bool removed = _runtime.UnregisterLiveEntity(
|
||||||
delete,
|
delete,
|
||||||
isLocalPlayer: false,
|
isLocalPlayer: false,
|
||||||
beforeTeardown: () =>
|
removeRetainedObject: true);
|
||||||
ObjectTableWiring.ApplyEntityDelete(_objects, delete));
|
|
||||||
bool removedDormant = _dormant.RemoveExact(delete);
|
bool removedDormant = _dormant.RemoveExact(delete);
|
||||||
if (!removed && removedDormant)
|
if (!removed && removedDormant)
|
||||||
ObjectTableWiring.ApplyEntityDelete(_objects, delete);
|
_entityObjects.ApplyAcceptedDormantDelete(delete);
|
||||||
if (removed)
|
if (removed)
|
||||||
{
|
{
|
||||||
_dormant.RemoveExact(delete);
|
_dormant.RemoveExact(delete);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using AcDream.App.Rendering;
|
using AcDream.App.Rendering;
|
||||||
using AcDream.App.Input;
|
using AcDream.App.Input;
|
||||||
using AcDream.Core.Items;
|
|
||||||
using AcDream.Core.Net;
|
using AcDream.Core.Net;
|
||||||
using AcDream.Core.Net.Messages;
|
using AcDream.Core.Net.Messages;
|
||||||
using AcDream.Core.World;
|
using AcDream.Core.World;
|
||||||
|
|
@ -169,7 +168,7 @@ internal interface ILiveEntityWorldOriginCoordinator
|
||||||
internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoadedSink
|
internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoadedSink
|
||||||
{
|
{
|
||||||
private readonly LiveEntityRuntime _runtime;
|
private readonly LiveEntityRuntime _runtime;
|
||||||
private readonly ClientObjectTable _objects;
|
private readonly RuntimeEntityObjectLifetime _entityObjects;
|
||||||
private readonly object _datLock;
|
private readonly object _datLock;
|
||||||
private readonly ILiveEntityProjectionMaterializer _materializer;
|
private readonly ILiveEntityProjectionMaterializer _materializer;
|
||||||
private readonly ILiveEntityRelationshipProjection _relationships;
|
private readonly ILiveEntityRelationshipProjection _relationships;
|
||||||
|
|
@ -193,7 +192,7 @@ internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoaded
|
||||||
|
|
||||||
public LiveEntityHydrationController(
|
public LiveEntityHydrationController(
|
||||||
LiveEntityRuntime runtime,
|
LiveEntityRuntime runtime,
|
||||||
ClientObjectTable objects,
|
RuntimeEntityObjectLifetime entityObjects,
|
||||||
object datLock,
|
object datLock,
|
||||||
ILiveEntityProjectionMaterializer materializer,
|
ILiveEntityProjectionMaterializer materializer,
|
||||||
ILiveEntityRelationshipProjection relationships,
|
ILiveEntityRelationshipProjection relationships,
|
||||||
|
|
@ -207,7 +206,8 @@ internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoaded
|
||||||
Action<string>? diagnostic = null)
|
Action<string>? diagnostic = null)
|
||||||
{
|
{
|
||||||
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
||||||
_objects = objects ?? throw new ArgumentNullException(nameof(objects));
|
_entityObjects = entityObjects
|
||||||
|
?? throw new ArgumentNullException(nameof(entityObjects));
|
||||||
_datLock = datLock ?? throw new ArgumentNullException(nameof(datLock));
|
_datLock = datLock ?? throw new ArgumentNullException(nameof(datLock));
|
||||||
_materializer = materializer ?? throw new ArgumentNullException(nameof(materializer));
|
_materializer = materializer ?? throw new ArgumentNullException(nameof(materializer));
|
||||||
_relationships = relationships ?? throw new ArgumentNullException(nameof(relationships));
|
_relationships = relationships ?? throw new ArgumentNullException(nameof(relationships));
|
||||||
|
|
@ -285,15 +285,13 @@ internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoaded
|
||||||
if (_runtime.IsCurrentCreateIntegration(
|
if (_runtime.IsCurrentCreateIntegration(
|
||||||
canonical,
|
canonical,
|
||||||
createIntegrationVersion)
|
createIntegrationVersion)
|
||||||
&& ObjectTableWiring.ApplyEntitySpawn(
|
&& _entityObjects.ApplyAcceptedSpawn(
|
||||||
_objects,
|
canonical,
|
||||||
|
createIntegrationVersion,
|
||||||
spawn,
|
spawn,
|
||||||
replaceGeneration: result.Disposition is
|
replaceGeneration: result.Disposition is
|
||||||
AcDream.Core.Physics.CreateObjectTimestampDisposition.NewGeneration
|
AcDream.Core.Physics.CreateObjectTimestampDisposition.NewGeneration
|
||||||
|| dormantDisposition is DormantCreateDisposition.NewGeneration,
|
|| dormantDisposition is DormantCreateDisposition.NewGeneration)
|
||||||
accepting: () => _runtime.IsCurrentCreateIntegration(
|
|
||||||
canonical,
|
|
||||||
createIntegrationVersion))
|
|
||||||
&& _runtime.IsCurrentCreateIntegration(
|
&& _runtime.IsCurrentCreateIntegration(
|
||||||
canonical,
|
canonical,
|
||||||
createIntegrationVersion))
|
createIntegrationVersion))
|
||||||
|
|
|
||||||
|
|
@ -448,6 +448,7 @@ public sealed class LiveEntityRuntime : ILiveEntityRadarSource
|
||||||
private readonly GpuWorldState _spatial;
|
private readonly GpuWorldState _spatial;
|
||||||
private readonly ILiveEntityResourceLifecycle _resources;
|
private readonly ILiveEntityResourceLifecycle _resources;
|
||||||
private readonly ILiveEntityRuntimeComponentLifecycle _runtimeComponentLifecycle;
|
private readonly ILiveEntityRuntimeComponentLifecycle _runtimeComponentLifecycle;
|
||||||
|
private readonly RuntimeEntityObjectLifetime _entityObjects;
|
||||||
private readonly RuntimeEntityDirectory _directory;
|
private readonly RuntimeEntityDirectory _directory;
|
||||||
private readonly LiveEntityProjectionStore _projections;
|
private readonly LiveEntityProjectionStore _projections;
|
||||||
// Logical components survive retail's 25-second leave-visibility lifetime.
|
// Logical components survive retail's 25-second leave-visibility lifetime.
|
||||||
|
|
@ -471,12 +472,12 @@ public sealed class LiveEntityRuntime : ILiveEntityRadarSource
|
||||||
public LiveEntityRuntime(
|
public LiveEntityRuntime(
|
||||||
GpuWorldState spatial,
|
GpuWorldState spatial,
|
||||||
ILiveEntityResourceLifecycle resources,
|
ILiveEntityResourceLifecycle resources,
|
||||||
uint firstLocalEntityId = FirstLiveEntityId)
|
RuntimeEntityObjectLifetime entityObjects)
|
||||||
: this(
|
: this(
|
||||||
spatial,
|
spatial,
|
||||||
resources,
|
resources,
|
||||||
NullLiveEntityRuntimeComponentLifecycle.Instance,
|
NullLiveEntityRuntimeComponentLifecycle.Instance,
|
||||||
firstLocalEntityId)
|
entityObjects)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -484,12 +485,12 @@ public sealed class LiveEntityRuntime : ILiveEntityRadarSource
|
||||||
GpuWorldState spatial,
|
GpuWorldState spatial,
|
||||||
ILiveEntityResourceLifecycle resources,
|
ILiveEntityResourceLifecycle resources,
|
||||||
Action<LiveEntityRecord> tearDownRuntimeComponents,
|
Action<LiveEntityRecord> tearDownRuntimeComponents,
|
||||||
uint firstLocalEntityId = FirstLiveEntityId)
|
RuntimeEntityObjectLifetime entityObjects)
|
||||||
: this(
|
: this(
|
||||||
spatial,
|
spatial,
|
||||||
resources,
|
resources,
|
||||||
new DelegateLiveEntityRuntimeComponentLifecycle(tearDownRuntimeComponents),
|
new DelegateLiveEntityRuntimeComponentLifecycle(tearDownRuntimeComponents),
|
||||||
firstLocalEntityId)
|
entityObjects)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -497,13 +498,15 @@ public sealed class LiveEntityRuntime : ILiveEntityRadarSource
|
||||||
GpuWorldState spatial,
|
GpuWorldState spatial,
|
||||||
ILiveEntityResourceLifecycle resources,
|
ILiveEntityResourceLifecycle resources,
|
||||||
ILiveEntityRuntimeComponentLifecycle? runtimeComponentLifecycle,
|
ILiveEntityRuntimeComponentLifecycle? runtimeComponentLifecycle,
|
||||||
uint firstLocalEntityId = FirstLiveEntityId)
|
RuntimeEntityObjectLifetime entityObjects)
|
||||||
{
|
{
|
||||||
_spatial = spatial ?? throw new ArgumentNullException(nameof(spatial));
|
_spatial = spatial ?? throw new ArgumentNullException(nameof(spatial));
|
||||||
_resources = resources ?? throw new ArgumentNullException(nameof(resources));
|
_resources = resources ?? throw new ArgumentNullException(nameof(resources));
|
||||||
_runtimeComponentLifecycle = runtimeComponentLifecycle
|
_runtimeComponentLifecycle = runtimeComponentLifecycle
|
||||||
?? throw new ArgumentNullException(nameof(runtimeComponentLifecycle));
|
?? throw new ArgumentNullException(nameof(runtimeComponentLifecycle));
|
||||||
_directory = new RuntimeEntityDirectory(firstLocalEntityId);
|
_entityObjects = entityObjects
|
||||||
|
?? throw new ArgumentNullException(nameof(entityObjects));
|
||||||
|
_directory = _entityObjects.Entities;
|
||||||
_projections = new LiveEntityProjectionStore(_directory);
|
_projections = new LiveEntityProjectionStore(_directory);
|
||||||
_spatial.LiveProjectionVisibilityChanged += OnSpatialVisibilityChanged;
|
_spatial.LiveProjectionVisibilityChanged += OnSpatialVisibilityChanged;
|
||||||
}
|
}
|
||||||
|
|
@ -1187,6 +1190,7 @@ public sealed class LiveEntityRuntime : ILiveEntityRadarSource
|
||||||
public bool UnregisterLiveEntity(
|
public bool UnregisterLiveEntity(
|
||||||
DeleteObject.Parsed delete,
|
DeleteObject.Parsed delete,
|
||||||
bool isLocalPlayer,
|
bool isLocalPlayer,
|
||||||
|
bool removeRetainedObject = false,
|
||||||
Action? beforeTeardown = null)
|
Action? beforeTeardown = null)
|
||||||
{
|
{
|
||||||
if (_isRegisteringResources)
|
if (_isRegisteringResources)
|
||||||
|
|
@ -1208,9 +1212,13 @@ public sealed class LiveEntityRuntime : ILiveEntityRadarSource
|
||||||
&& (record.DeleteAcceptedForTeardown
|
&& (record.DeleteAcceptedForTeardown
|
||||||
|| _isClearing
|
|| _isClearing
|
||||||
|| _sessionClearPendingFinalization);
|
|| _sessionClearPendingFinalization);
|
||||||
|
RuntimeEntityDeleteAcceptance? acceptedDelete = null;
|
||||||
if (!retryingAcceptedDelete)
|
if (!retryingAcceptedDelete)
|
||||||
{
|
{
|
||||||
if (!_directory.TryDelete(delete, isLocalPlayer))
|
if (!_entityObjects.TryAcceptDelete(
|
||||||
|
delete,
|
||||||
|
isLocalPlayer,
|
||||||
|
out acceptedDelete))
|
||||||
return false;
|
return false;
|
||||||
AdvanceLifetimeMutation(delete.Guid);
|
AdvanceLifetimeMutation(delete.Guid);
|
||||||
ParentAttachments.DeleteGeneration(delete.Guid, delete.InstanceSequence);
|
ParentAttachments.DeleteGeneration(delete.Guid, delete.InstanceSequence);
|
||||||
|
|
@ -1258,6 +1266,18 @@ public sealed class LiveEntityRuntime : ILiveEntityRadarSource
|
||||||
{
|
{
|
||||||
if (!retryingAcceptedDelete)
|
if (!retryingAcceptedDelete)
|
||||||
{
|
{
|
||||||
|
if (removeRetainedObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_entityObjects.CompleteAcceptedDelete(acceptedDelete!);
|
||||||
|
}
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
(failures ??= new List<Exception>()).Add(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
beforeTeardown?.Invoke();
|
beforeTeardown?.Invoke();
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ namespace AcDream.Core.Net;
|
||||||
/// 64-bit qualities (experience), SetStackSize (0x0197) = stack count,
|
/// 64-bit qualities (experience), SetStackSize (0x0197) = stack count,
|
||||||
/// InventoryRemoveObject (0x0024) = inventory-view removal.
|
/// InventoryRemoveObject (0x0024) = inventory-view removal.
|
||||||
/// CreateObject/DeleteObject application remains exposed as pure helpers so
|
/// CreateObject/DeleteObject application remains exposed as pure helpers so
|
||||||
/// the App live-entity owner can freshness-gate the shared projections first.
|
/// the Runtime entity/object lifetime owner can freshness-gate the canonical
|
||||||
|
/// incarnation before either graphical or retained-object projections mutate.
|
||||||
/// Retail: ACCObjectMaint::CreateObject / DeleteObject (the weenie_object_table side).
|
/// Retail: ACCObjectMaint::CreateObject / DeleteObject (the weenie_object_table side).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ObjectTableWiring
|
public static class ObjectTableWiring
|
||||||
|
|
|
||||||
135
src/AcDream.Runtime/Entities/RuntimeEntityObjectLifetime.cs
Normal file
135
src/AcDream.Runtime/Entities/RuntimeEntityObjectLifetime.cs
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
using AcDream.Core.Items;
|
||||||
|
using AcDream.Core.Net;
|
||||||
|
using AcDream.Core.Net.Messages;
|
||||||
|
|
||||||
|
namespace AcDream.Runtime.Entities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// One exact DeleteObject acceptance issued by a
|
||||||
|
/// <see cref="RuntimeEntityObjectLifetime"/>. The graphical host retires the
|
||||||
|
/// active identity before returning this token to the Runtime owner for the
|
||||||
|
/// retained-object mutation, preserving retail callback order.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RuntimeEntityDeleteAcceptance
|
||||||
|
{
|
||||||
|
internal RuntimeEntityDeleteAcceptance(
|
||||||
|
RuntimeEntityObjectLifetime owner,
|
||||||
|
DeleteObject.Parsed delete)
|
||||||
|
{
|
||||||
|
Owner = owner;
|
||||||
|
Delete = delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal RuntimeEntityObjectLifetime Owner { get; }
|
||||||
|
internal bool Completed { get; set; }
|
||||||
|
public DeleteObject.Parsed Delete { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Presentation-free ownership root for one session's canonical entity and
|
||||||
|
/// retained object lifetimes. Graphical and direct hosts borrow these exact
|
||||||
|
/// instances; they never allocate a second directory or object table.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RuntimeEntityObjectLifetime
|
||||||
|
{
|
||||||
|
public RuntimeEntityObjectLifetime(
|
||||||
|
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
|
||||||
|
{
|
||||||
|
Entities = new RuntimeEntityDirectory(firstLocalEntityId);
|
||||||
|
Objects = new ClientObjectTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeEntityDirectory Entities { get; }
|
||||||
|
public ClientObjectTable Objects { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the retained-object half of an accepted CreateObject while the
|
||||||
|
/// exact canonical incarnation and its integration version remain current.
|
||||||
|
/// Object-table callbacks are synchronous and may re-enter entity lifetime,
|
||||||
|
/// so the acceptance predicate is checked before, during, and after apply.
|
||||||
|
/// </summary>
|
||||||
|
public bool ApplyAcceptedSpawn(
|
||||||
|
RuntimeEntityRecord canonical,
|
||||||
|
ulong expectedCreateIntegrationVersion,
|
||||||
|
WorldSession.EntitySpawn spawn,
|
||||||
|
bool replaceGeneration)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(canonical);
|
||||||
|
if (canonical.ServerGuid != spawn.Guid
|
||||||
|
|| canonical.Incarnation != spawn.InstanceSequence)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCurrent() =>
|
||||||
|
Entities.IsCurrent(canonical)
|
||||||
|
&& canonical.CreateIntegrationVersion
|
||||||
|
== expectedCreateIntegrationVersion;
|
||||||
|
|
||||||
|
return IsCurrent()
|
||||||
|
&& ObjectTableWiring.ApplyEntitySpawn(
|
||||||
|
Objects,
|
||||||
|
spawn,
|
||||||
|
replaceGeneration,
|
||||||
|
IsCurrent)
|
||||||
|
&& IsCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Accepts the exact DeleteObject generation without yet publishing the
|
||||||
|
/// retained-object removal. This split lets the graphical host retire the
|
||||||
|
/// active identity first, matching the established reentrant callback
|
||||||
|
/// order, while Runtime remains the only freshness authority.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryAcceptDelete(
|
||||||
|
DeleteObject.Parsed delete,
|
||||||
|
bool isLocalPlayer,
|
||||||
|
out RuntimeEntityDeleteAcceptance acceptance)
|
||||||
|
{
|
||||||
|
if (!Entities.TryDelete(delete, isLocalPlayer))
|
||||||
|
{
|
||||||
|
acceptance = null!;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptance = new RuntimeEntityDeleteAcceptance(this, delete);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Completes a previously accepted delete exactly once. Marking the token
|
||||||
|
/// complete before synchronous callbacks preserves the current retry rule:
|
||||||
|
/// a throwing observer does not replay an already-committed removal.
|
||||||
|
/// </summary>
|
||||||
|
public void CompleteAcceptedDelete(
|
||||||
|
RuntimeEntityDeleteAcceptance acceptance)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(acceptance);
|
||||||
|
if (!ReferenceEquals(acceptance.Owner, this))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"A delete acceptance belongs to a different Runtime lifetime.");
|
||||||
|
}
|
||||||
|
if (acceptance.Completed)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"A delete acceptance has already been completed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptance.Completed = true;
|
||||||
|
ObjectTableWiring.ApplyEntityDelete(Objects, acceptance.Delete);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies a delete accepted by the dormant exact-incarnation owner after
|
||||||
|
/// the active Runtime directory correctly reports no live record.
|
||||||
|
/// </summary>
|
||||||
|
public void ApplyAcceptedDormantDelete(DeleteObject.Parsed delete) =>
|
||||||
|
ObjectTableWiring.ApplyEntityDelete(Objects, delete);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears retained object state at the Runtime-owned reset stage. App
|
||||||
|
/// projection teardown remains a later acknowledged stage.
|
||||||
|
/// </summary>
|
||||||
|
public void ClearObjects() => Objects.Clear();
|
||||||
|
}
|
||||||
|
|
@ -97,7 +97,7 @@ public sealed class CombatAttackTargetSourceTests
|
||||||
0x0101_FFFFu,
|
0x0101_FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
Runtime = new LiveEntityRuntime(spatial, new Resources());
|
Runtime = LiveEntityRuntimeFixture.Create(spatial, new Resources());
|
||||||
var identity = new LocalPlayerIdentityState { ServerGuid = Player };
|
var identity = new LocalPlayerIdentityState { ServerGuid = Player };
|
||||||
Targets = new CombatAttackTargetSource(
|
Targets = new CombatAttackTargetSource(
|
||||||
Selection,
|
Selection,
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ public sealed class LivePresentationCompositionTests
|
||||||
Assert.Contains("d.PortalTunnelFallback.AcquirePrepared(", phase);
|
Assert.Contains("d.PortalTunnelFallback.AcquirePrepared(", phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LiveEntityRuntime Runtime() => new(
|
private static LiveEntityRuntime Runtime() => LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new DelegateLiveEntityResourceLifecycle(static _ => { }, static _ => { }));
|
new DelegateLiveEntityResourceLifecycle(static _ => { }, static _ => { }));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public sealed class WorldSelectionQueryTests
|
||||||
0x0101_FFFFu,
|
0x0101_FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
Runtime = new LiveEntityRuntime(spatial, new Resources());
|
Runtime = LiveEntityRuntimeFixture.Create(spatial, new Resources());
|
||||||
Scene = new RetailSelectionScene(new GeometrySource(Mesh()));
|
Scene = new RetailSelectionScene(new GeometrySource(Mesh()));
|
||||||
Query = new WorldSelectionQuery(
|
Query = new WorldSelectionQuery(
|
||||||
Runtime,
|
Runtime,
|
||||||
|
|
|
||||||
50
tests/AcDream.App.Tests/LiveEntityRuntimeFixture.cs
Normal file
50
tests/AcDream.App.Tests/LiveEntityRuntimeFixture.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
using AcDream.App.Streaming;
|
||||||
|
using AcDream.App.World;
|
||||||
|
using AcDream.Runtime.Entities;
|
||||||
|
|
||||||
|
namespace AcDream.App.Tests;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Explicit isolated lifetime-group seam for App projection tests. Production
|
||||||
|
/// composition supplies its session-owned group from GameWindow; focused tests
|
||||||
|
/// use a fresh group per runtime so identity never leaks between fixtures.
|
||||||
|
/// </summary>
|
||||||
|
internal static class LiveEntityRuntimeFixture
|
||||||
|
{
|
||||||
|
public static LiveEntityRuntime Create(
|
||||||
|
GpuWorldState spatial,
|
||||||
|
ILiveEntityResourceLifecycle resources,
|
||||||
|
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
|
||||||
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime(firstLocalEntityId);
|
||||||
|
return new LiveEntityRuntime(spatial, resources, lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LiveEntityRuntime Create(
|
||||||
|
GpuWorldState spatial,
|
||||||
|
ILiveEntityResourceLifecycle resources,
|
||||||
|
Action<LiveEntityRecord> tearDownRuntimeComponents,
|
||||||
|
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
|
||||||
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime(firstLocalEntityId);
|
||||||
|
return new LiveEntityRuntime(
|
||||||
|
spatial,
|
||||||
|
resources,
|
||||||
|
tearDownRuntimeComponents,
|
||||||
|
lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LiveEntityRuntime Create(
|
||||||
|
GpuWorldState spatial,
|
||||||
|
ILiveEntityResourceLifecycle resources,
|
||||||
|
ILiveEntityRuntimeComponentLifecycle runtimeComponentLifecycle,
|
||||||
|
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
|
||||||
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime(firstLocalEntityId);
|
||||||
|
return new LiveEntityRuntime(
|
||||||
|
spatial,
|
||||||
|
resources,
|
||||||
|
runtimeComponentLifecycle,
|
||||||
|
lifetime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -210,7 +210,7 @@ public sealed class LiveSessionResetPlanTests
|
||||||
landblock,
|
landblock,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
new List<WorldEntity> { staticEntity }));
|
new List<WorldEntity> { staticEntity }));
|
||||||
var live = new LiveEntityRuntime(spatial, new FailingOnceResources());
|
var live = LiveEntityRuntimeFixture.Create(spatial, new FailingOnceResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(playerA, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(playerA, 1, 1, 0x01010001u);
|
||||||
live.RegisterLiveEntity(spawn);
|
live.RegisterLiveEntity(spawn);
|
||||||
live.MaterializeLiveEntity(
|
live.MaterializeLiveEntity(
|
||||||
|
|
|
||||||
|
|
@ -315,7 +315,7 @@ public sealed class LiveEntityInboundAuthorityGateTests
|
||||||
accepted.VelocityAuthorityVersion));
|
accepted.VelocityAuthorityVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LiveEntityRuntime Runtime() => new(
|
private static LiveEntityRuntime Runtime() => LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
|
||||||
var live = new LiveEntityRuntime(
|
var live = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
||||||
|
|
@ -90,7 +90,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
|
||||||
{
|
{
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
||||||
var live = new LiveEntityRuntime(
|
var live = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
||||||
|
|
|
||||||
|
|
@ -1457,7 +1457,7 @@ public sealed class ProjectileControllerTests
|
||||||
{
|
{
|
||||||
if (loadInitialLandblock)
|
if (loadInitialLandblock)
|
||||||
Spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
Spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
Live = new LiveEntityRuntime(Spatial, Resources);
|
Live = LiveEntityRuntimeFixture.Create(Spatial, Resources);
|
||||||
Engine = physicsEngine ?? new PhysicsEngine();
|
Engine = physicsEngine ?? new PhysicsEngine();
|
||||||
Origin.Recenter(1, 1);
|
Origin.Recenter(1, 1);
|
||||||
Controller = new ProjectileController(
|
Controller = new ProjectileController(
|
||||||
|
|
|
||||||
|
|
@ -692,7 +692,7 @@ public sealed class RemotePhysicsUpdaterTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var live = new LiveEntityRuntime(
|
var live = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
BindHiddenRemote(live, firstGuid);
|
BindHiddenRemote(live, firstGuid);
|
||||||
|
|
@ -840,7 +840,7 @@ public sealed class RemotePhysicsUpdaterTests
|
||||||
0xA9B4FFFFu,
|
0xA9B4FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
Live = new LiveEntityRuntime(
|
Live = LiveEntityRuntimeFixture.Create(
|
||||||
Spatial,
|
Spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
||||||
record =>
|
record =>
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ public sealed class RemoteTeleportControllerTests
|
||||||
const uint destinationCell = 0xAAB40001u;
|
const uint destinationCell = 0xAAB40001u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
||||||
var live = new LiveEntityRuntime(spatial, new Resources());
|
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
|
||||||
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
||||||
WorldEntity entity = live.MaterializeLiveEntity(
|
WorldEntity entity = live.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -228,7 +228,7 @@ public sealed class RemoteTeleportControllerTests
|
||||||
const uint sourceCell = 0xA9B40039u;
|
const uint sourceCell = 0xA9B40039u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
||||||
var live = new LiveEntityRuntime(spatial, new Resources());
|
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
|
||||||
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
||||||
WorldEntity entity = live.MaterializeLiveEntity(
|
WorldEntity entity = live.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -319,7 +319,7 @@ public sealed class RemoteTeleportControllerTests
|
||||||
Vector3 sourcePosition = new(191f, 10f, 50f);
|
Vector3 sourcePosition = new(191f, 10f, 50f);
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
||||||
var live = new LiveEntityRuntime(spatial, new Resources());
|
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
|
||||||
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
||||||
WorldEntity entity = live.MaterializeLiveEntity(
|
WorldEntity entity = live.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -1101,7 +1101,7 @@ public sealed class RemoteTeleportControllerTests
|
||||||
]));
|
]));
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
||||||
var live = new LiveEntityRuntime(spatial, resources);
|
var live = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
||||||
WorldEntity entity = live.MaterializeLiveEntity(
|
WorldEntity entity = live.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -1179,7 +1179,7 @@ public sealed class RemoteTeleportControllerTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
|
||||||
var live = new LiveEntityRuntime(spatial, new Resources());
|
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
|
||||||
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
live.RegisterLiveEntity(Spawn(guid, sourceCell));
|
||||||
WorldEntity entity = live.MaterializeLiveEntity(
|
WorldEntity entity = live.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -1383,7 +1383,7 @@ public sealed class RemoteTeleportControllerTests
|
||||||
internal RollbackFixture(bool celllessSource = false)
|
internal RollbackFixture(bool celllessSource = false)
|
||||||
{
|
{
|
||||||
Spatial.AddLandblock(EmptyLandblock(SourceLandblock));
|
Spatial.AddLandblock(EmptyLandblock(SourceLandblock));
|
||||||
Live = new LiveEntityRuntime(Spatial, new Resources());
|
Live = LiveEntityRuntimeFixture.Create(Spatial, new Resources());
|
||||||
Live.RegisterLiveEntity(Spawn(Guid, SourceCell));
|
Live.RegisterLiveEntity(Spawn(Guid, SourceCell));
|
||||||
Entity = Live.MaterializeLiveEntity(
|
Entity = Live.MaterializeLiveEntity(
|
||||||
Guid,
|
Guid,
|
||||||
|
|
|
||||||
|
|
@ -1161,7 +1161,7 @@ public sealed class EquippedChildProjectionWithdrawalTests
|
||||||
(Cell & 0xFFFF0000u) | 0xFFFFu,
|
(Cell & 0xFFFF0000u) | 0xFFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
Live = new LiveEntityRuntime(
|
Live = LiveEntityRuntimeFixture.Create(
|
||||||
Spatial,
|
Spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
||||||
_lifecycle);
|
_lifecycle);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ public sealed class LiveAppearanceAnimationTests
|
||||||
public void Capture_UsesCanonicalRecordEntityAndAnimationOwner()
|
public void Capture_UsesCanonicalRecordEntityAndAnimationOwner()
|
||||||
{
|
{
|
||||||
const uint guid = 0x70000002u;
|
const uint guid = 0x70000002u;
|
||||||
var runtime = new AcDream.App.World.LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
new AcDream.App.Streaming.GpuWorldState(),
|
new AcDream.App.Streaming.GpuWorldState(),
|
||||||
new AcDream.App.World.DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new AcDream.App.World.DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
var spawn = new AcDream.Core.Net.WorldSession.EntitySpawn(
|
var spawn = new AcDream.Core.Net.WorldSession.EntitySpawn(
|
||||||
|
|
@ -118,7 +118,7 @@ public sealed class LiveAppearanceAnimationTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
WorldSession.EntitySpawn first = Spawn(guid, cell, instance: 1);
|
WorldSession.EntitySpawn first = Spawn(guid, cell, instance: 1);
|
||||||
|
|
|
||||||
|
|
@ -440,7 +440,7 @@ public sealed class LiveEntityAnimationPresenterTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var live = new LiveEntityRuntime(
|
var live = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
return Add(live, guid, partCount, scale, withSequencer);
|
return Add(live, guid, partCount, scale, withSequencer);
|
||||||
|
|
|
||||||
|
|
@ -679,7 +679,7 @@ public sealed class LiveEntityAnimationSchedulerTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var live = new LiveEntityRuntime(
|
var live = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
||||||
|
|
@ -800,7 +800,7 @@ public sealed class LiveEntityAnimationSchedulerTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var live = new LiveEntityRuntime(
|
var live = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ public sealed class LiveEntityCreateSupersessionRecoveryTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new DatReaderWriter.DBObjs.LandBlock(),
|
new DatReaderWriter.DBObjs.LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
return new LiveEntityRuntime(
|
return LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
resources,
|
resources,
|
||||||
new DelegateLiveEntityRuntimeComponentLifecycle(_ => { }));
|
new DelegateLiveEntityRuntimeComponentLifecycle(_ => { }));
|
||||||
|
|
|
||||||
|
|
@ -357,7 +357,7 @@ public sealed class LiveRenderProjectionJournalTests
|
||||||
var resources = new DelegateLiveEntityResourceLifecycle(
|
var resources = new DelegateLiveEntityResourceLifecycle(
|
||||||
static _ => { },
|
static _ => { },
|
||||||
entity => sink?.OnResourceUnregister(entity));
|
entity => sink?.OnResourceUnregister(entity));
|
||||||
var runtime = new LiveEntityRuntime(state, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(state, resources);
|
||||||
var journal = new RenderProjectionJournal(
|
var journal = new RenderProjectionJournal(
|
||||||
RenderSceneGeneration.FromRaw(1));
|
RenderSceneGeneration.FromRaw(1));
|
||||||
var projections = new LiveRenderProjectionJournal(
|
var projections = new LiveRenderProjectionJournal(
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ public sealed class EntityEffectControllerTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
Runtime = new LiveEntityRuntime(
|
Runtime = LiveEntityRuntimeFixture.Create(
|
||||||
Spatial,
|
Spatial,
|
||||||
new NoopResources(),
|
new NoopResources(),
|
||||||
record => _controller?.OnLiveEntityUnregistered(record));
|
record => _controller?.OnLiveEntityUnregistered(record));
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ public sealed class LiveEntityLightControllerTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
Runtime = new LiveEntityRuntime(Spatial, new NoopResources(), _ => { });
|
Runtime = LiveEntityRuntimeFixture.Create(Spatial, new NoopResources(), _ => { });
|
||||||
Sink = new LightingHookSink(Lights, Poses);
|
Sink = new LightingHookSink(Lights, Poses);
|
||||||
Controller = new LiveEntityLightController(
|
Controller = new LiveEntityLightController(
|
||||||
Runtime,
|
Runtime,
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ public sealed class CurrentGameRuntimeAdapterTests
|
||||||
public Harness()
|
public Harness()
|
||||||
{
|
{
|
||||||
Identity = new LocalPlayerIdentityState();
|
Identity = new LocalPlayerIdentityState();
|
||||||
Entities = new LiveEntityRuntime(
|
Entities = LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new NoopEntityResources());
|
new NoopEntityResources());
|
||||||
Objects = new ClientObjectTable();
|
Objects = new ClientObjectTable();
|
||||||
|
|
|
||||||
|
|
@ -579,7 +579,7 @@ public sealed class GpuWorldStateVisibilityTests
|
||||||
const uint landblock = 0x0101FFFFu;
|
const uint landblock = 0x0101FFFFu;
|
||||||
const uint cell = 0x01010001u;
|
const uint cell = 0x01010001u;
|
||||||
var state = new GpuWorldState();
|
var state = new GpuWorldState();
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
state,
|
state,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
WorldSession.EntitySpawn first = Spawn(0x70000011u, cell);
|
WorldSession.EntitySpawn first = Spawn(0x70000011u, cell);
|
||||||
|
|
@ -624,7 +624,7 @@ public sealed class GpuWorldStateVisibilityTests
|
||||||
landblock,
|
landblock,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
state,
|
state,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, cell);
|
WorldSession.EntitySpawn spawn = Spawn(guid, cell);
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ public sealed class LocalPlayerTeleportControllerTests
|
||||||
0x2021FFFFu,
|
0x2021FFFFu,
|
||||||
new DatReaderWriter.DBObjs.LandBlock(),
|
new DatReaderWriter.DBObjs.LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var runtime = new LiveEntityRuntime(world, new NullResources());
|
var runtime = LiveEntityRuntimeFixture.Create(world, new NullResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, cell));
|
runtime.RegisterLiveEntity(Spawn(guid, cell));
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -479,7 +479,7 @@ public sealed class LocalPlayerTeleportControllerTests
|
||||||
destinationCell & 0xFFFF0000u | 0xFFFFu,
|
destinationCell & 0xFFFF0000u | 0xFFFFu,
|
||||||
new DatReaderWriter.DBObjs.LandBlock(),
|
new DatReaderWriter.DBObjs.LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var runtime = new LiveEntityRuntime(world, new NullResources());
|
var runtime = LiveEntityRuntimeFixture.Create(world, new NullResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, sourceCell));
|
runtime.RegisterLiveEntity(Spawn(guid, sourceCell));
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,9 @@ public sealed class StreamingFrameControllerTests
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LiveEntityRuntime Runtime(GpuWorldState state) =>
|
private static LiveEntityRuntime Runtime(GpuWorldState state) =>
|
||||||
new(state, new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
LiveEntityRuntimeFixture.Create(
|
||||||
|
state,
|
||||||
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
|
|
||||||
private static LoadedLandblock EmptyLandblock(uint landblock) =>
|
private static LoadedLandblock EmptyLandblock(uint landblock) =>
|
||||||
new(landblock, new LandBlock(), Array.Empty<WorldEntity>());
|
new(landblock, new LandBlock(), Array.Empty<WorldEntity>());
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ public sealed class DeferredLiveEntityRuntimeComponentLifecycleTests
|
||||||
{
|
{
|
||||||
const uint guid = 0x70000002u;
|
const uint guid = 0x70000002u;
|
||||||
var bridge = new DeferredLiveEntityRuntimeComponentLifecycle();
|
var bridge = new DeferredLiveEntityRuntimeComponentLifecycle();
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
||||||
bridge);
|
bridge);
|
||||||
|
|
@ -136,7 +136,7 @@ public sealed class DeferredLiveEntityRuntimeComponentLifecycleTests
|
||||||
|
|
||||||
private static LiveEntityRecord CreateRecord()
|
private static LiveEntityRecord CreateRecord()
|
||||||
{
|
{
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
return runtime.RegisterAndMaterializeProjection(
|
return runtime.RegisterAndMaterializeProjection(
|
||||||
|
|
|
||||||
|
|
@ -1828,7 +1828,8 @@ public sealed class LiveEntityHydrationControllerTests
|
||||||
private sealed class Fixture : IDisposable
|
private sealed class Fixture : IDisposable
|
||||||
{
|
{
|
||||||
public readonly List<string> Operations = [];
|
public readonly List<string> Operations = [];
|
||||||
public readonly ClientObjectTable Objects = new();
|
public readonly RuntimeEntityObjectLifetime EntityObjects = new();
|
||||||
|
public ClientObjectTable Objects => EntityObjects.Objects;
|
||||||
public readonly RecordingResources Resources;
|
public readonly RecordingResources Resources;
|
||||||
public readonly LiveEntityRuntime Runtime;
|
public readonly LiveEntityRuntime Runtime;
|
||||||
public readonly RecordingMaterializer Materializer;
|
public readonly RecordingMaterializer Materializer;
|
||||||
|
|
@ -1861,7 +1862,8 @@ public sealed class LiveEntityHydrationControllerTests
|
||||||
Runtime = new LiveEntityRuntime(
|
Runtime = new LiveEntityRuntime(
|
||||||
spatial,
|
spatial,
|
||||||
Resources,
|
Resources,
|
||||||
Teardown);
|
Teardown,
|
||||||
|
EntityObjects);
|
||||||
Materializer = new RecordingMaterializer(Runtime, Operations);
|
Materializer = new RecordingMaterializer(Runtime, Operations);
|
||||||
Relationships = new RecordingRelationships(Operations);
|
Relationships = new RecordingRelationships(Operations);
|
||||||
Ready = new RecordingReadyPublisher(Operations);
|
Ready = new RecordingReadyPublisher(Operations);
|
||||||
|
|
@ -1887,13 +1889,13 @@ public sealed class LiveEntityHydrationControllerTests
|
||||||
};
|
};
|
||||||
var deletion = new LiveEntityDeletionController(
|
var deletion = new LiveEntityDeletionController(
|
||||||
Runtime,
|
Runtime,
|
||||||
Objects,
|
EntityObjects,
|
||||||
Teardown,
|
Teardown,
|
||||||
identity,
|
identity,
|
||||||
Dormant);
|
Dormant);
|
||||||
Controller = new LiveEntityHydrationController(
|
Controller = new LiveEntityHydrationController(
|
||||||
Runtime,
|
Runtime,
|
||||||
Objects,
|
EntityObjects,
|
||||||
new object(),
|
new object(),
|
||||||
Materializer,
|
Materializer,
|
||||||
Relationships,
|
Relationships,
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ public sealed class LiveEntityLifecycleStressTests
|
||||||
randomUnit: () => 0.5,
|
randomUnit: () => 0.5,
|
||||||
canAdvanceOwner: ownerId => _effects?.CanAdvanceOwner(ownerId) ?? true);
|
canAdvanceOwner: ownerId => _effects?.CanAdvanceOwner(ownerId) ?? true);
|
||||||
|
|
||||||
Runtime = new LiveEntityRuntime(
|
Runtime = LiveEntityRuntimeFixture.Create(
|
||||||
Spatial,
|
Spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(
|
new DelegateLiveEntityResourceLifecycle(
|
||||||
entity =>
|
entity =>
|
||||||
|
|
@ -489,7 +489,7 @@ public sealed class LiveEntityLifecycleStressTests
|
||||||
EntityEffectController? effects = null;
|
EntityEffectController? effects = null;
|
||||||
LiveEntityPresentationController? presentation = null;
|
LiveEntityPresentationController? presentation = null;
|
||||||
RemoteTeleportController? teleport = null;
|
RemoteTeleportController? teleport = null;
|
||||||
Runtime = new LiveEntityRuntime(
|
Runtime = LiveEntityRuntimeFixture.Create(
|
||||||
Spatial,
|
Spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(
|
new DelegateLiveEntityResourceLifecycle(
|
||||||
entity =>
|
entity =>
|
||||||
|
|
|
||||||
|
|
@ -630,10 +630,10 @@ public sealed class LiveEntityPhysicsHostOwnershipTests
|
||||||
|
|
||||||
private static LiveEntityRuntime Runtime(Action<LiveEntityRecord>? teardown = null) =>
|
private static LiveEntityRuntime Runtime(Action<LiveEntityRecord>? teardown = null) =>
|
||||||
teardown is null
|
teardown is null
|
||||||
? new LiveEntityRuntime(
|
? LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }))
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }))
|
||||||
: new LiveEntityRuntime(
|
: LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
||||||
teardown);
|
teardown);
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,7 @@ public sealed class LiveEntityPresentationControllerTests
|
||||||
const uint pendingCell = 0x02020001u;
|
const uint pendingCell = 0x02020001u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var shadows = new ShadowObjectRegistry();
|
var shadows = new ShadowObjectRegistry();
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
runtime.RegisterLiveEntity(Fixture.Spawn(
|
runtime.RegisterLiveEntity(Fixture.Spawn(
|
||||||
|
|
@ -487,7 +487,7 @@ public sealed class LiveEntityPresentationControllerTests
|
||||||
const uint pendingCell = 0x02020001u;
|
const uint pendingCell = 0x02020001u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var shadows = new ShadowObjectRegistry();
|
var shadows = new ShadowObjectRegistry();
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
runtime.RegisterLiveEntity(Fixture.Spawn(
|
runtime.RegisterLiveEntity(Fixture.Spawn(
|
||||||
|
|
@ -667,7 +667,7 @@ public sealed class LiveEntityPresentationControllerTests
|
||||||
0x0101FFFFu,
|
0x0101FFFFu,
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
Runtime = new LiveEntityRuntime(
|
Runtime = LiveEntityRuntimeFixture.Create(
|
||||||
Spatial,
|
Spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
|
||||||
WorldSession.EntitySpawn spawn = Spawn(initialState);
|
WorldSession.EntitySpawn spawn = Spawn(initialState);
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ public sealed class LiveEntityProjectionWithdrawalControllerTests
|
||||||
new LandBlock(),
|
new LandBlock(),
|
||||||
Array.Empty<WorldEntity>()));
|
Array.Empty<WorldEntity>()));
|
||||||
var lifecycle = new DeferredLiveEntityRuntimeComponentLifecycle();
|
var lifecycle = new DeferredLiveEntityRuntimeComponentLifecycle();
|
||||||
Live = new LiveEntityRuntime(
|
Live = LiveEntityRuntimeFixture.Create(
|
||||||
Spatial,
|
Spatial,
|
||||||
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
|
||||||
lifecycle);
|
lifecycle);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
public void RuntimeSlot_BindsExactlyOnceWithoutOwningEntityState()
|
public void RuntimeSlot_BindsExactlyOnceWithoutOwningEntityState()
|
||||||
{
|
{
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
var slot = new LiveEntityRuntimeSlot();
|
var slot = new LiveEntityRuntimeSlot();
|
||||||
|
|
||||||
Assert.Null(slot.Current);
|
Assert.Null(slot.Current);
|
||||||
|
|
@ -176,7 +176,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x70000001u, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x70000001u, 1, 1, 0x01010001u);
|
||||||
|
|
||||||
LiveEntityRegistrationResult registered = runtime.RegisterLiveEntity(spawn);
|
LiveEntityRegistrationResult registered = runtime.RegisterLiveEntity(spawn);
|
||||||
|
|
@ -213,7 +213,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000071u;
|
const uint guid = 0x70000071u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(
|
WorldSession.EntitySpawn spawn = Spawn(
|
||||||
guid,
|
guid,
|
||||||
instance: 1,
|
instance: 1,
|
||||||
|
|
@ -325,7 +325,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000074u;
|
const uint guid = 0x70000074u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(
|
runtime.RegisterLiveEntity(Spawn(
|
||||||
guid,
|
guid,
|
||||||
instance: 1,
|
instance: 1,
|
||||||
|
|
@ -417,7 +417,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000070u;
|
const uint guid = 0x70000070u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -476,7 +476,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000071u;
|
const uint guid = 0x70000071u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -513,7 +513,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint secondGuid = 0x70000074u;
|
const uint secondGuid = 0x70000074u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
foreach (uint guid in new[] { firstGuid, secondGuid })
|
foreach (uint guid in new[] { firstGuid, secondGuid })
|
||||||
{
|
{
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
|
|
@ -545,7 +545,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000075u;
|
const uint guid = 0x70000075u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -580,7 +580,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000072u;
|
const uint guid = 0x70000072u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity oldEntity = runtime.MaterializeLiveEntity(
|
WorldEntity oldEntity = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -617,7 +617,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000073u;
|
const uint guid = 0x70000073u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -672,7 +672,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 6, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 6, 1, 0x01010001u);
|
||||||
LiveEntityRegistrationResult registration =
|
LiveEntityRegistrationResult registration =
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
|
|
@ -702,7 +702,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
{
|
{
|
||||||
const uint parentGuid = 0x70000020u;
|
const uint parentGuid = 0x70000020u;
|
||||||
const uint childGuid = 0x70000021u;
|
const uint childGuid = 0x70000021u;
|
||||||
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(parentGuid, 9, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(parentGuid, 9, 1, 0x01010001u));
|
||||||
runtime.ParentAttachments.Enqueue(new ParentEvent.Parsed(
|
runtime.ParentAttachments.Enqueue(new ParentEvent.Parsed(
|
||||||
parentGuid, childGuid, 1, 2, 9, 5));
|
parentGuid, childGuid, 1, 2, 9, 5));
|
||||||
|
|
@ -725,7 +725,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
{
|
{
|
||||||
const uint parentGuid = 0x70000022u;
|
const uint parentGuid = 0x70000022u;
|
||||||
const uint childGuid = 0x70000023u;
|
const uint childGuid = 0x70000023u;
|
||||||
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(childGuid, 3, 4, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(childGuid, 3, 4, 0x01010001u));
|
||||||
runtime.ParentAttachments.AcceptCreateObjectRelation(new ParentAttachmentRelation(
|
runtime.ParentAttachments.AcceptCreateObjectRelation(new ParentAttachmentRelation(
|
||||||
parentGuid, childGuid, 1, 2, 9, 4));
|
parentGuid, childGuid, 1, 2, 9, 4));
|
||||||
|
|
@ -743,7 +743,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn first = Spawn(0x70000002u, 4, 10, 0x01010001u);
|
WorldSession.EntitySpawn first = Spawn(0x70000002u, 4, 10, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(first);
|
runtime.RegisterLiveEntity(first);
|
||||||
WorldEntity original = runtime.MaterializeLiveEntity(
|
WorldEntity original = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -771,7 +771,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
int runtimeTearDowns = 0;
|
int runtimeTearDowns = 0;
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
resources,
|
resources,
|
||||||
_ => runtimeTearDowns++);
|
_ => runtimeTearDowns++);
|
||||||
|
|
@ -803,7 +803,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x70000004u, 2, 3, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x70000004u, 2, 3, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -833,7 +833,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
const uint guid = 0x70000005u;
|
const uint guid = 0x70000005u;
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 3, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 3, 1, 0x01010001u));
|
||||||
WorldEntity first = runtime.MaterializeLiveEntity(
|
WorldEntity first = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -863,7 +863,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x70000006u, 3, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x70000006u, 3, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
|
|
||||||
|
|
@ -900,7 +900,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
{
|
{
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x70000007u, 1, 1, 0x01020001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x70000007u, 1, 1, 0x01020001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -929,7 +929,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000025u;
|
const uint guid = 0x70000025u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 2, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 2, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -983,7 +983,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 4, 10, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 4, 10, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1063,7 +1063,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000027u;
|
const uint guid = 0x70000027u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1104,7 +1104,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
LiveEntityRecord record = RegisterProjection(runtime, spawn);
|
LiveEntityRecord record = RegisterProjection(runtime, spawn);
|
||||||
RetailObjectQuantumClock clock = record.ObjectClock;
|
RetailObjectQuantumClock clock = record.ObjectClock;
|
||||||
|
|
@ -1143,7 +1143,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000049u;
|
const uint guid = 0x70000049u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(
|
WorldSession.EntitySpawn spawn = Spawn(
|
||||||
guid,
|
guid,
|
||||||
1,
|
1,
|
||||||
|
|
@ -1166,7 +1166,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint staticGuid = 0x70000051u;
|
const uint staticGuid = 0x70000051u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
|
|
||||||
LiveEntityRecord ordinary = RegisterProjection(
|
LiveEntityRecord ordinary = RegisterProjection(
|
||||||
runtime,
|
runtime,
|
||||||
|
|
@ -1204,7 +1204,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint staticGuid = 0x70000054u;
|
const uint staticGuid = 0x70000054u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
|
|
||||||
LiveEntityRecord ordinary = RegisterProjection(
|
LiveEntityRecord ordinary = RegisterProjection(
|
||||||
runtime,
|
runtime,
|
||||||
|
|
@ -1279,7 +1279,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
{
|
{
|
||||||
const uint parentGuid = 0x50000010u;
|
const uint parentGuid = 0x50000010u;
|
||||||
const uint childGuid = 0x70000055u;
|
const uint childGuid = 0x70000055u;
|
||||||
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(parentGuid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(parentGuid, 1, 1, 0x01010001u));
|
||||||
LiveEntityRecord child = RegisterProjection(
|
LiveEntityRecord child = RegisterProjection(
|
||||||
runtime,
|
runtime,
|
||||||
|
|
@ -1314,7 +1314,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000048u;
|
const uint guid = 0x70000048u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn firstSpawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn firstSpawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
LiveEntityRecord first = RegisterProjection(runtime, firstSpawn);
|
LiveEntityRecord first = RegisterProjection(runtime, firstSpawn);
|
||||||
RetailObjectQuantumClock firstClock = first.ObjectClock;
|
RetailObjectQuantumClock firstClock = first.ObjectClock;
|
||||||
|
|
@ -1341,7 +1341,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
{
|
{
|
||||||
const uint stateBeforeBindGuid = 0x70000037u;
|
const uint stateBeforeBindGuid = 0x70000037u;
|
||||||
const uint bindBeforeStateGuid = 0x70000038u;
|
const uint bindBeforeStateGuid = 0x70000038u;
|
||||||
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(stateBeforeBindGuid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(stateBeforeBindGuid, 1, 1, 0x01010001u));
|
||||||
runtime.RegisterLiveEntity(Spawn(bindBeforeStateGuid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(bindBeforeStateGuid, 1, 1, 0x01010001u));
|
||||||
|
|
||||||
|
|
@ -1381,7 +1381,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
public void ParentDrivenChildNoDrawKeepsBoundBodyInCanonicalState()
|
public void ParentDrivenChildNoDrawKeepsBoundBodyInCanonicalState()
|
||||||
{
|
{
|
||||||
const uint guid = 0x70000039u;
|
const uint guid = 0x70000039u;
|
||||||
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -1401,7 +1401,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
public void InitiallyVisibleCreate_DoesNotManufactureUnHideTransition()
|
public void InitiallyVisibleCreate_DoesNotManufactureUnHideTransition()
|
||||||
{
|
{
|
||||||
const uint guid = 0x70000040u;
|
const uint guid = 0x70000040u;
|
||||||
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
|
||||||
|
|
||||||
LiveEntityRecord record = RegisterProjection(
|
LiveEntityRecord record = RegisterProjection(
|
||||||
runtime,
|
runtime,
|
||||||
|
|
@ -1418,7 +1418,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000041u;
|
const uint guid = 0x70000041u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(
|
runtime.RegisterLiveEntity(Spawn(
|
||||||
guid,
|
guid,
|
||||||
1,
|
1,
|
||||||
|
|
@ -1448,7 +1448,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000042u;
|
const uint guid = 0x70000042u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -1486,7 +1486,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
public void PositionAfterPickup_RequiresTeleportHookEvenWithEqualTeleportStamp()
|
public void PositionAfterPickup_RequiresTeleportHookEvenWithEqualTeleportStamp()
|
||||||
{
|
{
|
||||||
const uint guid = 0x70000043u;
|
const uint guid = 0x70000043u;
|
||||||
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
Assert.True(runtime.TryApplyPickup(
|
Assert.True(runtime.TryApplyPickup(
|
||||||
|
|
@ -1524,7 +1524,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000044u;
|
const uint guid = 0x70000044u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1563,7 +1563,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x70000024u, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x70000024u, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1593,7 +1593,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x70000009u, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x70000009u, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1620,7 +1620,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
int runtimeTearDowns = 0;
|
int runtimeTearDowns = 0;
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources, _ => runtimeTearDowns++);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources, _ => runtimeTearDowns++);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x70000008u, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x70000008u, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1645,7 +1645,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingRegisterResources();
|
var resources = new FailingRegisterResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x7000000Au, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x7000000Au, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
|
|
||||||
|
|
@ -1671,7 +1671,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingRegisterAndRollbackOnceResources();
|
var resources = new FailingRegisterAndRollbackOnceResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
|
|
||||||
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
|
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1709,7 +1709,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingRegisterAndRollbackOnceResources();
|
var resources = new FailingRegisterAndRollbackOnceResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
|
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -1736,7 +1736,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingRegisterAndRollbackOnceResources();
|
var resources = new FailingRegisterAndRollbackOnceResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
|
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1764,7 +1764,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingUnregisterResources(0x7000000Bu);
|
var resources = new FailingUnregisterResources(0x7000000Bu);
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
foreach (uint guid in new[] { 0x7000000Bu, 0x7000000Cu })
|
foreach (uint guid in new[] { 0x7000000Bu, 0x7000000Cu })
|
||||||
{
|
{
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
|
|
@ -1792,7 +1792,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingOnceUnregisterResources(guid);
|
var resources = new FailingOnceUnregisterResources(guid);
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
|
|
@ -1819,7 +1819,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingOnceUnregisterResources(guid);
|
var resources = new FailingOnceUnregisterResources(guid);
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
|
|
@ -1852,7 +1852,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
if (!adapter.OnRemove(entity))
|
if (!adapter.OnRemove(entity))
|
||||||
throw new InvalidOperationException("presentation owner was not registered");
|
throw new InvalidOperationException("presentation owner was not registered");
|
||||||
});
|
});
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.ProjectionVisibilityChanged += (record, visible) =>
|
runtime.ProjectionVisibilityChanged += (record, visible) =>
|
||||||
{
|
{
|
||||||
if (record.WorldEntity is { } entity)
|
if (record.WorldEntity is { } entity)
|
||||||
|
|
@ -1887,7 +1887,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingUnregisterResources(guid);
|
var resources = new FailingUnregisterResources(guid);
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn first = Spawn(guid, 1, 1, 0x01010001u);
|
WorldSession.EntitySpawn first = Spawn(guid, 1, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(first);
|
runtime.RegisterLiveEntity(first);
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
|
|
@ -1918,7 +1918,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010022u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010022u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010022u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010022u, id => Entity(id, guid));
|
||||||
|
|
||||||
|
|
@ -1940,7 +1940,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity attached = runtime.MaterializeLiveEntity(
|
WorldEntity attached = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -1965,7 +1965,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
{
|
{
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(
|
var runtime = LiveEntityRuntimeFixture.Create(
|
||||||
spatial,
|
spatial,
|
||||||
new RecordingResources(),
|
new RecordingResources(),
|
||||||
firstLocalEntityId: LiveEntityRuntime.LastLiveEntityId);
|
firstLocalEntityId: LiveEntityRuntime.LastLiveEntityId);
|
||||||
|
|
@ -1984,7 +1984,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
Assert.NotEqual(0u, secondEntity.Id);
|
Assert.NotEqual(0u, secondEntity.Id);
|
||||||
Assert.True(runtime.TryGetLocalEntityId(second.Guid, out uint resolved));
|
Assert.True(runtime.TryGetLocalEntityId(second.Guid, out uint resolved));
|
||||||
Assert.Equal(secondEntity.Id, resolved);
|
Assert.Equal(secondEntity.Id, resolved);
|
||||||
Assert.Throws<ArgumentOutOfRangeException>(() => new LiveEntityRuntime(
|
Assert.Throws<ArgumentOutOfRangeException>(() => LiveEntityRuntimeFixture.Create(
|
||||||
new GpuWorldState(),
|
new GpuWorldState(),
|
||||||
new RecordingResources(),
|
new RecordingResources(),
|
||||||
firstLocalEntityId: uint.MaxValue));
|
firstLocalEntityId: uint.MaxValue));
|
||||||
|
|
@ -1996,7 +1996,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x7000002Au;
|
const uint guid = 0x7000002Au;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2022,7 +2022,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
public void SessionClear_ForgetsPersistentClassificationWithoutMaterializedRecord()
|
public void SessionClear_ForgetsPersistentClassificationWithoutMaterializedRecord()
|
||||||
{
|
{
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
spatial.MarkPersistent(0x7000002Bu);
|
spatial.MarkPersistent(0x7000002Bu);
|
||||||
|
|
||||||
runtime.Clear();
|
runtime.Clear();
|
||||||
|
|
@ -2037,7 +2037,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x7000002Du;
|
const uint guid = 0x7000002Du;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2067,7 +2067,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000040u;
|
const uint guid = 0x70000040u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity entity = runtime.MaterializeLiveEntity(
|
WorldEntity entity = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2096,7 +2096,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000041u;
|
const uint guid = 0x70000041u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2127,7 +2127,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000044u;
|
const uint guid = 0x70000044u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
|
|
@ -2161,7 +2161,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000045u;
|
const uint guid = 0x70000045u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity original = runtime.MaterializeLiveEntity(
|
WorldEntity original = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2200,7 +2200,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x70000046u;
|
const uint guid = 0x70000046u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
bool reprojected = false;
|
bool reprojected = false;
|
||||||
|
|
@ -2228,7 +2228,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
{
|
{
|
||||||
const uint guid = 0x70000075u;
|
const uint guid = 0x70000075u;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity pending = runtime.MaterializeLiveEntity(
|
WorldEntity pending = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2277,7 +2277,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new FailingOnceUnregisterResources(guid);
|
var resources = new FailingOnceUnregisterResources(guid);
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity? replacementEntity = null;
|
WorldEntity? replacementEntity = null;
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
|
|
@ -2318,7 +2318,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0303FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0303FFFFu));
|
||||||
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity original = runtime.MaterializeLiveEntity(
|
WorldEntity original = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2352,7 +2352,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x7000002Cu;
|
const uint guid = 0x7000002Cu;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2394,7 +2394,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
const uint guid = 0x7000002Eu;
|
const uint guid = 0x7000002Eu;
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2434,7 +2434,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
WorldEntity old = runtime.MaterializeLiveEntity(
|
WorldEntity old = runtime.MaterializeLiveEntity(
|
||||||
guid,
|
guid,
|
||||||
|
|
@ -2477,7 +2477,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
resources.OnUnregister = _ =>
|
resources.OnUnregister = _ =>
|
||||||
|
|
@ -2508,7 +2508,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
resources.OnUnregister = _ =>
|
resources.OnUnregister = _ =>
|
||||||
|
|
@ -2538,7 +2538,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
resources.OnUnregister = _ =>
|
resources.OnUnregister = _ =>
|
||||||
|
|
@ -2568,7 +2568,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
resources.OnUnregister = _ =>
|
resources.OnUnregister = _ =>
|
||||||
|
|
@ -2600,7 +2600,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
resources.OnUnregister = _ =>
|
resources.OnUnregister = _ =>
|
||||||
|
|
@ -2632,7 +2632,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
|
||||||
resources.OnUnregister = _ =>
|
resources.OnUnregister = _ =>
|
||||||
|
|
@ -2660,7 +2660,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
resources.OnRegister = _ =>
|
resources.OnRegister = _ =>
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 2, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 2, 1, 0x01010001u));
|
||||||
|
|
@ -2686,7 +2686,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
|
||||||
resources.OnRegister = _ => runtime.Clear();
|
resources.OnRegister = _ => runtime.Clear();
|
||||||
|
|
||||||
|
|
@ -2711,7 +2711,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(firstGuid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(firstGuid, 1, 1, 0x01010001u));
|
||||||
runtime.RegisterLiveEntity(Spawn(secondGuid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(secondGuid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(firstGuid, 0x01010001u, id => Entity(id, firstGuid));
|
runtime.MaterializeLiveEntity(firstGuid, 0x01010001u, id => Entity(id, firstGuid));
|
||||||
|
|
@ -2744,7 +2744,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new CallbackResources();
|
var resources = new CallbackResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
runtime.RegisterLiveEntity(Spawn(oldGuid, 1, 1, 0x01010001u));
|
runtime.RegisterLiveEntity(Spawn(oldGuid, 1, 1, 0x01010001u));
|
||||||
runtime.MaterializeLiveEntity(oldGuid, 0x01010001u, id => Entity(id, oldGuid));
|
runtime.MaterializeLiveEntity(oldGuid, 0x01010001u, id => Entity(id, oldGuid));
|
||||||
resources.OnUnregister = _ =>
|
resources.OnUnregister = _ =>
|
||||||
|
|
@ -2785,7 +2785,7 @@ public sealed class LiveEntityRuntimeTests
|
||||||
var spatial = new GpuWorldState();
|
var spatial = new GpuWorldState();
|
||||||
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
|
||||||
var resources = new RecordingResources();
|
var resources = new RecordingResources();
|
||||||
var runtime = new LiveEntityRuntime(spatial, resources);
|
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
|
||||||
WorldSession.EntitySpawn spawn = Spawn(0x7000000Du, 4, 1, 0x01010001u);
|
WorldSession.EntitySpawn spawn = Spawn(0x7000000Du, 4, 1, 0x01010001u);
|
||||||
runtime.RegisterLiveEntity(spawn);
|
runtime.RegisterLiveEntity(spawn);
|
||||||
runtime.MaterializeLiveEntity(
|
runtime.MaterializeLiveEntity(
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,19 @@ namespace AcDream.App.Tests.World;
|
||||||
public sealed class RuntimeEntityOwnershipTests
|
public sealed class RuntimeEntityOwnershipTests
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void LiveEntityRuntime_ComposesCanonicalRuntimeDirectory()
|
public void LiveEntityRuntime_BorrowsCanonicalRuntimeDirectory()
|
||||||
{
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime();
|
||||||
|
var runtime = new LiveEntityRuntime(
|
||||||
|
new GpuWorldState(),
|
||||||
|
new DelegateLiveEntityResourceLifecycle(
|
||||||
|
static _ => { },
|
||||||
|
static _ => { }),
|
||||||
|
lifetime);
|
||||||
|
FieldInfo owner = typeof(LiveEntityRuntime).GetField(
|
||||||
|
"_entityObjects",
|
||||||
|
BindingFlags.Instance | BindingFlags.NonPublic)
|
||||||
|
?? throw new InvalidOperationException("Missing Runtime lifetime root.");
|
||||||
FieldInfo directory = typeof(LiveEntityRuntime).GetField(
|
FieldInfo directory = typeof(LiveEntityRuntime).GetField(
|
||||||
"_directory",
|
"_directory",
|
||||||
BindingFlags.Instance | BindingFlags.NonPublic)
|
BindingFlags.Instance | BindingFlags.NonPublic)
|
||||||
|
|
@ -25,9 +36,62 @@ public sealed class RuntimeEntityOwnershipTests
|
||||||
?? throw new InvalidOperationException("Missing App projection sidecar store.");
|
?? throw new InvalidOperationException("Missing App projection sidecar store.");
|
||||||
|
|
||||||
Assert.Equal(typeof(RuntimeEntityDirectory), directory.FieldType);
|
Assert.Equal(typeof(RuntimeEntityDirectory), directory.FieldType);
|
||||||
|
Assert.Same(lifetime, owner.GetValue(runtime));
|
||||||
|
Assert.Same(lifetime.Entities, directory.GetValue(runtime));
|
||||||
Assert.Equal(typeof(LiveEntityProjectionStore), sidecars.FieldType);
|
Assert.Equal(typeof(LiveEntityProjectionStore), sidecars.FieldType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ProductionComposition_HasOneRuntimeEntityObjectConstructionRoot()
|
||||||
|
{
|
||||||
|
string root = FindRepositoryRoot();
|
||||||
|
string appRoot = Path.Combine(root, "src", "AcDream.App");
|
||||||
|
string runtimeRoot = Path.Combine(root, "src", "AcDream.Runtime");
|
||||||
|
string[] appSources = Directory.GetFiles(
|
||||||
|
appRoot,
|
||||||
|
"*.cs",
|
||||||
|
SearchOption.AllDirectories);
|
||||||
|
string[] runtimeSources = Directory.GetFiles(
|
||||||
|
runtimeRoot,
|
||||||
|
"*.cs",
|
||||||
|
SearchOption.AllDirectories);
|
||||||
|
|
||||||
|
string[] appObjectAllocators = appSources
|
||||||
|
.Where(path => !path.Contains(
|
||||||
|
$"{Path.DirectorySeparatorChar}Studio{Path.DirectorySeparatorChar}",
|
||||||
|
StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Where(path => File.ReadAllText(path).Contains(
|
||||||
|
"new ClientObjectTable",
|
||||||
|
StringComparison.Ordinal))
|
||||||
|
.ToArray();
|
||||||
|
string[] appDirectoryAllocators = appSources
|
||||||
|
.Where(path => File.ReadAllText(path).Contains(
|
||||||
|
"new RuntimeEntityDirectory",
|
||||||
|
StringComparison.Ordinal))
|
||||||
|
.ToArray();
|
||||||
|
string[] runtimeObjectAllocators = runtimeSources
|
||||||
|
.Where(path => File.ReadAllText(path).Contains(
|
||||||
|
"new ClientObjectTable",
|
||||||
|
StringComparison.Ordinal))
|
||||||
|
.Select(path => Path.GetFileName(path)!)
|
||||||
|
.ToArray();
|
||||||
|
string[] runtimeDirectoryAllocators = runtimeSources
|
||||||
|
.Where(path => File.ReadAllText(path).Contains(
|
||||||
|
"new RuntimeEntityDirectory",
|
||||||
|
StringComparison.Ordinal))
|
||||||
|
.Select(path => Path.GetFileName(path)!)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
Assert.Empty(appObjectAllocators);
|
||||||
|
Assert.Empty(appDirectoryAllocators);
|
||||||
|
Assert.Equal(
|
||||||
|
["RuntimeEntityObjectLifetime.cs"],
|
||||||
|
runtimeObjectAllocators);
|
||||||
|
Assert.Equal(
|
||||||
|
["RuntimeEntityObjectLifetime.cs"],
|
||||||
|
runtimeDirectoryAllocators);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AppProjectionOwners_UseExactRuntimeKeysAndNoGuidDictionary()
|
public void AppProjectionOwners_UseExactRuntimeKeysAndNoGuidDictionary()
|
||||||
{
|
{
|
||||||
|
|
@ -212,4 +276,18 @@ public sealed class RuntimeEntityOwnershipTests
|
||||||
field.FieldType.IsGenericType
|
field.FieldType.IsGenericType
|
||||||
&& field.FieldType.GetGenericTypeDefinition() == typeof(Dictionary<,>)
|
&& field.FieldType.GetGenericTypeDefinition() == typeof(Dictionary<,>)
|
||||||
&& field.FieldType.GetGenericArguments()[0] == keyType;
|
&& field.FieldType.GetGenericArguments()[0] == keyType;
|
||||||
|
|
||||||
|
private static string FindRepositoryRoot()
|
||||||
|
{
|
||||||
|
DirectoryInfo? directory = new(AppContext.BaseDirectory);
|
||||||
|
while (directory is not null)
|
||||||
|
{
|
||||||
|
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
|
||||||
|
return directory.FullName;
|
||||||
|
directory = directory.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new DirectoryNotFoundException(
|
||||||
|
$"Could not find AcDream.slnx above {AppContext.BaseDirectory}.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,251 @@
|
||||||
|
using AcDream.Core.Net;
|
||||||
|
using AcDream.Core.Net.Messages;
|
||||||
|
using AcDream.Core.Physics;
|
||||||
|
using AcDream.Runtime.Entities;
|
||||||
|
|
||||||
|
namespace AcDream.Runtime.Tests.Entities;
|
||||||
|
|
||||||
|
public sealed class RuntimeEntityObjectLifetimeTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Owner_ConstructsOneExactDirectoryAndObjectTablePerInstance()
|
||||||
|
{
|
||||||
|
var first = new RuntimeEntityObjectLifetime();
|
||||||
|
var second = new RuntimeEntityObjectLifetime();
|
||||||
|
|
||||||
|
Assert.NotSame(first.Entities, second.Entities);
|
||||||
|
Assert.NotSame(first.Objects, second.Objects);
|
||||||
|
Assert.Same(first.Entities, first.Entities);
|
||||||
|
Assert.Same(first.Objects, first.Objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Owner_ConstructionLoadsNoPresentationOrBackendAssembly()
|
||||||
|
{
|
||||||
|
_ = new RuntimeEntityObjectLifetime();
|
||||||
|
|
||||||
|
string[] loaded = AppDomain.CurrentDomain
|
||||||
|
.GetAssemblies()
|
||||||
|
.Select(assembly => assembly.GetName().Name ?? string.Empty)
|
||||||
|
.ToArray();
|
||||||
|
Assert.DoesNotContain(loaded, name =>
|
||||||
|
name.StartsWith("AcDream.App", StringComparison.Ordinal)
|
||||||
|
|| name.StartsWith("AcDream.UI.", StringComparison.Ordinal)
|
||||||
|
|| name.StartsWith("Silk.NET", StringComparison.Ordinal)
|
||||||
|
|| name.StartsWith("OpenAL", StringComparison.Ordinal)
|
||||||
|
|| name.StartsWith("ImGui", StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SeparateOwners_IsolateConflictingGuidsAndContents()
|
||||||
|
{
|
||||||
|
const uint guid = 0x70000001u;
|
||||||
|
var first = new RuntimeEntityObjectLifetime();
|
||||||
|
var second = new RuntimeEntityObjectLifetime();
|
||||||
|
RuntimeEntityRecord firstRecord = Accept(first, Spawn(guid, 1, "first"));
|
||||||
|
RuntimeEntityRecord secondRecord = Accept(second, Spawn(guid, 9, "second"));
|
||||||
|
|
||||||
|
Assert.True(first.ApplyAcceptedSpawn(
|
||||||
|
firstRecord,
|
||||||
|
firstRecord.CreateIntegrationVersion,
|
||||||
|
firstRecord.Snapshot,
|
||||||
|
replaceGeneration: false));
|
||||||
|
Assert.True(second.ApplyAcceptedSpawn(
|
||||||
|
secondRecord,
|
||||||
|
secondRecord.CreateIntegrationVersion,
|
||||||
|
secondRecord.Snapshot,
|
||||||
|
replaceGeneration: false));
|
||||||
|
|
||||||
|
Assert.Equal("first", first.Objects.Get(guid)!.Name);
|
||||||
|
Assert.Equal("second", second.Objects.Get(guid)!.Name);
|
||||||
|
Assert.Equal((ushort)1, firstRecord.Incarnation);
|
||||||
|
Assert.Equal((ushort)9, secondRecord.Incarnation);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AcceptedSpawn_RejectsWrongOrSupersededCanonicalIncarnation()
|
||||||
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime();
|
||||||
|
WorldSession.EntitySpawn spawn = Spawn(0x70000002u, 3, "current");
|
||||||
|
RuntimeEntityRecord canonical = Accept(lifetime, spawn);
|
||||||
|
var wrong = new RuntimeEntityObjectLifetime();
|
||||||
|
RuntimeEntityRecord wrongCanonical = Accept(wrong, spawn);
|
||||||
|
|
||||||
|
Assert.False(lifetime.ApplyAcceptedSpawn(
|
||||||
|
wrongCanonical,
|
||||||
|
wrongCanonical.CreateIntegrationVersion,
|
||||||
|
spawn,
|
||||||
|
replaceGeneration: false));
|
||||||
|
|
||||||
|
ulong expectedVersion = canonical.CreateIntegrationVersion;
|
||||||
|
lifetime.Entities.AdvanceCreateAuthority(canonical);
|
||||||
|
Assert.False(lifetime.ApplyAcceptedSpawn(
|
||||||
|
canonical,
|
||||||
|
expectedVersion,
|
||||||
|
spawn,
|
||||||
|
replaceGeneration: false));
|
||||||
|
Assert.Null(lifetime.Objects.Get(spawn.Guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AcceptedSpawn_RevalidatesAfterSynchronousObjectCallbacks()
|
||||||
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime();
|
||||||
|
WorldSession.EntitySpawn spawn = Spawn(0x70000003u, 4, "reentrant");
|
||||||
|
RuntimeEntityRecord canonical = Accept(lifetime, spawn);
|
||||||
|
ulong expectedVersion = canonical.CreateIntegrationVersion;
|
||||||
|
lifetime.Objects.ObjectAdded += _ =>
|
||||||
|
lifetime.Entities.AdvanceCreateAuthority(canonical);
|
||||||
|
|
||||||
|
Assert.False(lifetime.ApplyAcceptedSpawn(
|
||||||
|
canonical,
|
||||||
|
expectedVersion,
|
||||||
|
spawn,
|
||||||
|
replaceGeneration: false));
|
||||||
|
Assert.NotNull(lifetime.Objects.Get(spawn.Guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AcceptedDelete_RemovesOnlyMatchingLogicalGeneration()
|
||||||
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime();
|
||||||
|
WorldSession.EntitySpawn spawn = Spawn(0x70000004u, 6, "retained");
|
||||||
|
RuntimeEntityRecord canonical = Accept(lifetime, spawn);
|
||||||
|
Assert.True(lifetime.ApplyAcceptedSpawn(
|
||||||
|
canonical,
|
||||||
|
canonical.CreateIntegrationVersion,
|
||||||
|
spawn,
|
||||||
|
replaceGeneration: true));
|
||||||
|
|
||||||
|
Assert.False(lifetime.TryAcceptDelete(
|
||||||
|
new DeleteObject.Parsed(spawn.Guid, 7),
|
||||||
|
isLocalPlayer: false,
|
||||||
|
out _));
|
||||||
|
Assert.NotNull(lifetime.Objects.Get(spawn.Guid));
|
||||||
|
|
||||||
|
Assert.True(lifetime.TryAcceptDelete(
|
||||||
|
new DeleteObject.Parsed(spawn.Guid, 6),
|
||||||
|
isLocalPlayer: false,
|
||||||
|
out RuntimeEntityDeleteAcceptance accepted));
|
||||||
|
lifetime.CompleteAcceptedDelete(accepted);
|
||||||
|
Assert.Null(lifetime.Objects.Get(spawn.Guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DeleteAcceptance_CannotCrossOwnersOrReplay()
|
||||||
|
{
|
||||||
|
var owner = new RuntimeEntityObjectLifetime();
|
||||||
|
var other = new RuntimeEntityObjectLifetime();
|
||||||
|
WorldSession.EntitySpawn spawn = Spawn(0x70000006u, 8, "token");
|
||||||
|
RuntimeEntityRecord canonical = Accept(owner, spawn);
|
||||||
|
Assert.True(owner.ApplyAcceptedSpawn(
|
||||||
|
canonical,
|
||||||
|
canonical.CreateIntegrationVersion,
|
||||||
|
spawn,
|
||||||
|
replaceGeneration: true));
|
||||||
|
Assert.True(owner.TryAcceptDelete(
|
||||||
|
new DeleteObject.Parsed(spawn.Guid, spawn.InstanceSequence),
|
||||||
|
isLocalPlayer: false,
|
||||||
|
out RuntimeEntityDeleteAcceptance acceptance));
|
||||||
|
|
||||||
|
Assert.Throws<InvalidOperationException>(
|
||||||
|
() => other.CompleteAcceptedDelete(acceptance));
|
||||||
|
owner.CompleteAcceptedDelete(acceptance);
|
||||||
|
Assert.Throws<InvalidOperationException>(
|
||||||
|
() => owner.CompleteAcceptedDelete(acceptance));
|
||||||
|
Assert.Null(owner.Objects.Get(spawn.Guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ClearObjects_DoesNotResetCanonicalEntityIdentity()
|
||||||
|
{
|
||||||
|
var lifetime = new RuntimeEntityObjectLifetime();
|
||||||
|
WorldSession.EntitySpawn spawn = Spawn(0x70000005u, 2, "clear");
|
||||||
|
RuntimeEntityRecord canonical = Accept(lifetime, spawn);
|
||||||
|
Assert.True(lifetime.ApplyAcceptedSpawn(
|
||||||
|
canonical,
|
||||||
|
canonical.CreateIntegrationVersion,
|
||||||
|
spawn,
|
||||||
|
replaceGeneration: false));
|
||||||
|
|
||||||
|
lifetime.ClearObjects();
|
||||||
|
|
||||||
|
Assert.Null(lifetime.Objects.Get(spawn.Guid));
|
||||||
|
Assert.True(lifetime.Entities.TryGetActive(spawn.Guid, out var retained));
|
||||||
|
Assert.Same(canonical, retained);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RuntimeEntityRecord Accept(
|
||||||
|
RuntimeEntityObjectLifetime lifetime,
|
||||||
|
WorldSession.EntitySpawn spawn)
|
||||||
|
{
|
||||||
|
InboundCreateResult accepted = lifetime.Entities.AcceptCreate(spawn);
|
||||||
|
return lifetime.Entities.AddActive(accepted.Snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WorldSession.EntitySpawn Spawn(
|
||||||
|
uint guid,
|
||||||
|
ushort instance,
|
||||||
|
string name)
|
||||||
|
{
|
||||||
|
var position = new CreateObject.ServerPosition(
|
||||||
|
0x0101FFFFu,
|
||||||
|
10f,
|
||||||
|
20f,
|
||||||
|
5f,
|
||||||
|
1f,
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
0f);
|
||||||
|
var timestamps = new PhysicsTimestamps(
|
||||||
|
Position: 1,
|
||||||
|
Movement: 1,
|
||||||
|
State: 1,
|
||||||
|
Vector: 1,
|
||||||
|
Teleport: 0,
|
||||||
|
ServerControlledMove: 1,
|
||||||
|
ForcePosition: 0,
|
||||||
|
ObjDesc: 1,
|
||||||
|
Instance: instance);
|
||||||
|
var physics = new PhysicsSpawnData(
|
||||||
|
RawState: 0x408u,
|
||||||
|
Position: position,
|
||||||
|
Movement: null,
|
||||||
|
AnimationFrame: null,
|
||||||
|
SetupTableId: 0x02000001u,
|
||||||
|
MotionTableId: 0x09000001u,
|
||||||
|
SoundTableId: null,
|
||||||
|
PhysicsScriptTableId: null,
|
||||||
|
Parent: null,
|
||||||
|
Children: null,
|
||||||
|
Scale: null,
|
||||||
|
Friction: null,
|
||||||
|
Elasticity: null,
|
||||||
|
Translucency: null,
|
||||||
|
Velocity: null,
|
||||||
|
Acceleration: null,
|
||||||
|
AngularVelocity: null,
|
||||||
|
DefaultScriptType: null,
|
||||||
|
DefaultScriptIntensity: null,
|
||||||
|
Timestamps: timestamps);
|
||||||
|
return new WorldSession.EntitySpawn(
|
||||||
|
guid,
|
||||||
|
position,
|
||||||
|
0x02000001u,
|
||||||
|
Array.Empty<CreateObject.AnimPartChange>(),
|
||||||
|
Array.Empty<CreateObject.TextureChange>(),
|
||||||
|
Array.Empty<CreateObject.SubPaletteSwap>(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
name,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
0x09000001u,
|
||||||
|
PhysicsState: 0x408u,
|
||||||
|
InstanceSequence: instance,
|
||||||
|
MovementSequence: 1,
|
||||||
|
ServerControlSequence: 1,
|
||||||
|
PositionSequence: 1,
|
||||||
|
Physics: physics);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue