Route entity destruction through checkpoints
This commit is contained in:
parent
1fadd56464
commit
729ab0e8d8
5 changed files with 111 additions and 25 deletions
Binary file not shown.
|
|
@ -20,6 +20,7 @@ RequireInventoryEntityRenameCommitAuthority(root);
|
|||
RequireWeaponGroupCommitAuthority(root);
|
||||
RequireInventoryDoubleClickTransferCommitAuthority(root);
|
||||
RequireLootPickupCommitAuthority(root);
|
||||
RequireEntityDestroyedCommitAuthority(root);
|
||||
RequireTradePurchaseCommitAuthority(root);
|
||||
RequireInventoryLoadoutRestoreCommitAuthority(root);
|
||||
RequireDockedCurrentShipCommitAuthority(root);
|
||||
|
|
@ -471,6 +472,8 @@ Console.WriteLine("Hull conductivity authority: inventory UI toggles flow throug
|
|||
Console.WriteLine("Inventory entity rename authority: UI rename flows through gameplay checkpoint commits");
|
||||
Console.WriteLine("Weapon group authority: UI assignment flows through gameplay checkpoint commits");
|
||||
Console.WriteLine("Inventory transfer authority: UI transfer and drag/drop requests flow through gameplay checkpoint commits");
|
||||
Console.WriteLine("Loot pickup authority: collision pickup requests flow through gameplay checkpoint commits");
|
||||
Console.WriteLine("Entity destruction authority: hull-death observers flow through gameplay checkpoint commits");
|
||||
Console.WriteLine("Trade purchase authority: UI buy requests flow through gameplay checkpoint commits");
|
||||
Console.WriteLine("Inventory loadout restore authority: UI restore requests flow through gameplay checkpoint commits");
|
||||
Console.WriteLine("Docked current-ship authority: UI selection requests flow through gameplay checkpoint commits");
|
||||
|
|
@ -1162,6 +1165,64 @@ static void RequireLootPickupCommitAuthority(string root)
|
|||
}
|
||||
}
|
||||
|
||||
static void RequireEntityDestroyedCommitAuthority(string root)
|
||||
{
|
||||
var actionGameManagerPath = Path.Combine(root, "Assets", "Scripts", "Gameplay", "ActionGameManager.cs");
|
||||
var actionGameManager = File.Exists(actionGameManagerPath)
|
||||
? File.ReadAllText(actionGameManagerPath)
|
||||
: throw new InvalidOperationException("Cannot verify entity destruction authority; ActionGameManager.cs is missing.");
|
||||
|
||||
var requiredSymbols = new[]
|
||||
{
|
||||
"CommitEntityDestroyed",
|
||||
"QueueRunCheckpoint(\"entity-destroyed\")",
|
||||
"entity.Zone.Entities.Remove(entity)",
|
||||
"zoneRenderer.DropItem("
|
||||
};
|
||||
|
||||
var missingSymbols = requiredSymbols
|
||||
.Where(symbol => !actionGameManager.Contains(symbol, StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
|
||||
if (missingSymbols.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Entity destruction no longer has a gameplay-owned checkpoint commit primitive: " +
|
||||
string.Join(", ", missingSymbols));
|
||||
}
|
||||
|
||||
var entityInstancePath = Path.Combine(root, "Assets", "Scripts", "Gameplay", "EntityInstance.cs");
|
||||
var entityInstance = File.Exists(entityInstancePath)
|
||||
? File.ReadAllText(entityInstancePath)
|
||||
: throw new InvalidOperationException("Cannot verify entity destruction authority; EntityInstance.cs is missing.");
|
||||
|
||||
var forbiddenSymbols = new[]
|
||||
{
|
||||
"ZoneRenderer.DropItem(",
|
||||
"entity.Zone.Entities.Remove(entity)",
|
||||
"Random.onUnitSphere",
|
||||
"LootDropProbability"
|
||||
};
|
||||
|
||||
var hits = File.ReadLines(entityInstancePath)
|
||||
.Select((line, index) => new { LineNumber = index + 1, Line = line })
|
||||
.Where(line => forbiddenSymbols.Any(symbol => line.Line.Contains(symbol, StringComparison.Ordinal)))
|
||||
.Select(line => $"{Path.GetRelativePath(root, entityInstancePath)}:{line.LineNumber}: {line.Line.Trim()}")
|
||||
.ToArray();
|
||||
|
||||
if (hits.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"EntityInstance still owns direct destruction/drop mutation: " +
|
||||
string.Join("; ", hits));
|
||||
}
|
||||
|
||||
if (!entityInstance.Contains("ActionGameManager.Instance?.CommitEntityDestroyed", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException("EntityInstance no longer routes destruction through ActionGameManager.");
|
||||
}
|
||||
}
|
||||
|
||||
static void RequireInventoryLoadoutRestoreCommitAuthority(string root)
|
||||
{
|
||||
var actionGameManagerPath = Path.Combine(root, "Assets", "Scripts", "Gameplay", "ActionGameManager.cs");
|
||||
|
|
|
|||
|
|
@ -1587,6 +1587,43 @@ public class ActionGameManager : MonoBehaviour
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool CommitEntityDestroyed(Entity entity, ZoneRenderer zoneRenderer)
|
||||
{
|
||||
if (entity?.Zone == null)
|
||||
return false;
|
||||
|
||||
if (zoneRenderer != null)
|
||||
{
|
||||
foreach (var gear in entity.Equipment)
|
||||
{
|
||||
if (gear == entity.EquippedHull || Random.value >= zoneRenderer.Settings.LootDropProbability)
|
||||
continue;
|
||||
|
||||
zoneRenderer.DropItem(
|
||||
entity.Position,
|
||||
Random.onUnitSphere * zoneRenderer.Settings.LootDropVelocity,
|
||||
gear.EquippableItem);
|
||||
}
|
||||
|
||||
foreach (var cargo in entity.CargoBays)
|
||||
{
|
||||
foreach (var item in cargo.Cargo.Keys.ToArray())
|
||||
{
|
||||
zoneRenderer.DropItem(
|
||||
entity.Position,
|
||||
Random.onUnitSphere * zoneRenderer.Settings.LootDropVelocity,
|
||||
item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!entity.Zone.Entities.Remove(entity))
|
||||
return false;
|
||||
|
||||
QueueRunCheckpoint("entity-destroyed");
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CommitCargoItemTransfer(
|
||||
EquippedCargoBay origin,
|
||||
EquippedCargoBay destination,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ using UnityEngine;
|
|||
using Unity.Mathematics;
|
||||
using static Unity.Mathematics.math;
|
||||
using float2 = Unity.Mathematics.float2;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class EntityInstance : MonoBehaviour
|
||||
{
|
||||
|
|
@ -421,37 +420,18 @@ public class EntityInstance : MonoBehaviour
|
|||
|
||||
_subscriptions.Add(Entity.HullDamage.Subscribe(_ =>
|
||||
{
|
||||
if (Entity.Hull.Durability < .01f)
|
||||
if (!_destroyed && Entity.Hull.Durability < .01f)
|
||||
{
|
||||
if (!this) return;
|
||||
_destroyed = true;
|
||||
foreach (var gear in Entity.Equipment)
|
||||
{
|
||||
if (gear != Entity.EquippedHull && Random.value < ZoneRenderer.Settings.LootDropProbability)
|
||||
{
|
||||
ZoneRenderer.DropItem(
|
||||
Entity.Position,
|
||||
Random.onUnitSphere * ZoneRenderer.Settings.LootDropVelocity,
|
||||
gear.EquippableItem);
|
||||
}
|
||||
}
|
||||
if (ActionGameManager.Instance?.CommitEntityDestroyed(entity, ZoneRenderer) != true)
|
||||
return;
|
||||
|
||||
foreach (var cargo in Entity.CargoBays)
|
||||
{
|
||||
foreach (var item in cargo.Cargo.Keys)
|
||||
{
|
||||
ZoneRenderer.DropItem(
|
||||
Entity.Position,
|
||||
Random.onUnitSphere * ZoneRenderer.Settings.LootDropVelocity,
|
||||
item);
|
||||
}
|
||||
}
|
||||
_destroyed = true;
|
||||
if (DestroyEffect != null)
|
||||
{
|
||||
var t = Instantiate(DestroyEffect).transform;
|
||||
t.position = transform.position;
|
||||
}
|
||||
entity.Zone.Entities.Remove(entity);
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -1414,6 +1414,12 @@ First Aetheria surfaces to publish:
|
|||
after a successful commit, but it no longer stores items into cargo bays
|
||||
directly; gameplay owns the cargo mutation and queues the typed run
|
||||
checkpoint.
|
||||
- Done: route entity destruction through
|
||||
`ActionGameManager.CommitEntityDestroyed`. `EntityInstance` observes hull
|
||||
death and may spawn the local destruction effect, but gameplay owns
|
||||
equipment/cargo drop decisions, zone entity removal, and the typed run
|
||||
checkpoint. Dropped world pickups are still presentation/runtime objects
|
||||
until the runtime object graph pass gives them typed documents.
|
||||
- Replace the next concrete uGUI screen with an Eve-owned surface.
|
||||
- Move the staged packages into the Eve repo once its worktree is clean, then
|
||||
import them back into Aetheria from Eve instead of carrying a local copy.
|
||||
|
|
@ -1749,7 +1755,9 @@ instantiation, credits, dock assignment, current entity, and checkpoint. Docked
|
|||
current-ship selection follows the same rule: UI requests selection, gameplay
|
||||
owns `CurrentEntity`, `DockingBay.DockedShip`, and checkpoint. Loot pickup
|
||||
follows the same rule: collision code reports the pickup opportunity, gameplay
|
||||
owns cargo storage and checkpoint. Any
|
||||
owns cargo storage and checkpoint. Entity destruction follows the same rule:
|
||||
instance code observes death, gameplay owns drop decisions, zone removal, and
|
||||
checkpoint. Any
|
||||
predicate that still needs legacy DTO objects must earn that dependency by
|
||||
using behavior objects or simulation-only methods that typed facets do not yet
|
||||
expose.
|
||||
|
|
|
|||
Loading…
Reference in a new issue