diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index 80bce7a01..9415ff7f3 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -216,7 +216,6 @@ public abstract class Entity // item). Written only by RecordReveal (an act enters) and EndReveals (an end the observer perceives, or a departed // subject's entries aged past BearingMemory), cleared by Deactivate (ruling reveal-ends-on-perception). private readonly Dictionary> _reveals = new Dictionary>(); - private readonly List _endedItems = new List(); private readonly List _agedSubjects = new List(); public ReactiveProperty CurrentSecurityLevel = new ReactiveProperty(SecurityLevel.Open); public ReadOnlyReactiveProperty PresencePermitted; @@ -915,10 +914,9 @@ public abstract class Entity // What this observer has seen `subject`'s items do: each item's latest act, and nothing the subject's present // gear or Durability says (ruling contact-reads-book-aim-reads-live). A reveal ends only on what this observer - // perceives (ruling reveal-ends-on-perception): the destruction of an item of a ship it identifies, the death, - // dock or warp of a subject its instruments could see leave, or, for a subject that has left the zone, the - // freshest entry aging past BearingMemory; Deactivate clears it all. Whether an item can be aimed at now is - // FireControl.IsRevealed's question, not this one. + // perceives (ruling reveal-ends-on-perception): the death, dock or warp of a subject its instruments could see + // leave, or, for a subject that has left the zone, the freshest entry aging past BearingMemory; Deactivate + // clears it all. Whether an item can be aimed at now is FireControl.IsRevealed's question, not this one. public IEnumerable RevealsOf(Entity subject) => _reveals.TryGetValue(subject, out var book) ? book.Values : Enumerable.Empty(); @@ -964,16 +962,6 @@ public abstract class Entity if (perSignature < 0f) perSignature = PassiveInfo(other.Position.xz, 1f); if (signature.Strength * perSignature > threshold) RecordReveal(other, signature.Item, signature.Channel); } - // The observer resolves this ship's gear (ContactOf's own Identified gate), so it perceives an item of it - // destroyed. Ending after recording: a destroyed item's lingering flash cannot re-enter the book. - if (EntityInfoGathered.TryGetValue(other, out var info) && info >= ItemManager.GameplaySettings.TargetGearInfoThreshold - && _reveals.TryGetValue(other, out var book)) - { - _endedItems.Clear(); - foreach (var item in book.Keys) - if (item.EquippableItem.Durability < .01f) _endedItems.Add(item); - for (var j = 0; j < _endedItems.Count; j++) EndReveals(other, _endedItems[j]); - } } // A subject that left the zone (death, dock, warp, any removal) is perceived gone under the light-act gate: as // bright as its non-Emission signature was at removal, from where it was. A re-admitted subject did not leave. diff --git a/tests/Aetheria.Shared.Tests/ContactRevealTests.cs b/tests/Aetheria.Shared.Tests/ContactRevealTests.cs index 1c36f7a7a..3a214b888 100644 --- a/tests/Aetheria.Shared.Tests/ContactRevealTests.cs +++ b/tests/Aetheria.Shared.Tests/ContactRevealTests.cs @@ -687,9 +687,7 @@ public sealed class ContactRevealTests : IDisposable // Ruling contact-reads-book-aim-reads-live: what an observer knows of a ship comes from its own book. A gun // destroyed by a third party out of its sight changes none of its levels and stays in its reveal list, while - // the aiming read, which asks about the item now, refuses the dead gun and still serves the live one. No Sense - // runs after the destruction here (the aiming read needs info 1, at which a Sense would perceive it); the - // unseen case with a Sense is AnIdentifiedObserverSeesGearDestroyed's below-threshold case. + // the aiming read, which asks about the item now, refuses the dead gun and still serves the live one. [Fact] public void GearDestroyedOutOfSightLeavesWhatTheObserverKnowsAlone() { @@ -721,58 +719,6 @@ public sealed class ContactRevealTests : IDisposable Assert.True(o.ContactOf(e).Classified); } - // Ruling reveal-ends-on-perception: an observer that resolves a ship's gear (its track at TargetGearInfoThreshold) - // perceives an item of it destroyed, and the reveal of that item ends in the same Sense pass. One that does not - // resolve it perceives nothing. - [Theory] - [InlineData(.8f, 1, 1, 1)] - [InlineData(.8f, 2, 0, 0)] - [InlineData(.79f, 1, 2, 1)] - [InlineData(.79f, 2, 2, 1)] - public void AnIdentifiedObserverSeesGearDestroyed(float info, int destroyed, int remaining, int classifiedKeys) - { - var e = Add(float3(0, 0, 100), new[] { "Gun", "Gun" }); - var o = Add(float3(0, 0, 0), new[] { "Eye" }); - var guns = Guns(e); - Fire(e, guns[0]); - Fire(e, guns[1]); - o.VisibleEntities.Add(e); // tracked, so what the track holds is not the question - o.EntityInfoGathered[e] = info; - var sense = SenseOf(o); - for (var i = 0; i < destroyed; i++) guns[i].EquippableItem.Durability = 0f; - - sense(); - - Assert.Equal(remaining, o.RevealsOf(e).Count()); - var contact = o.ContactOf(e); - Assert.True(contact.Detected); - Assert.Equal(remaining > 0, contact.Classified); - Assert.Equal(remaining > 0 ? classifiedKeys : 0, RevealBookSubjects(o)); - if (remaining == 1 && info >= .8f) Assert.Same(guns[1], o.RevealsOf(e).Single().Item); - } - - // The same through a real tick: a gun destroyed while its flash still shows, seen by an observer that identifies - // the ship, is not in the book after the tick. - [Fact] - public void ADestroyedGunStillFlashingIsNotRecordedByAnIdentifyingObserver() - { - var e = Add(float3(0, 0, 60), new[] { "Gun", "Gun" }); - var o = Add(float3(0, 0, 0), new[] { "Eye" }); - var guns = Guns(e); - Fire(e, guns[0]); - Fire(e, guns[1]); - e.SetSignature(new object(), SignatureChannel.Reflection, 1000f, guns[0]); // the dying gun's glare outlasts the tick - guns[0].EquippableItem.Durability = 0f; - o.EntityInfoGathered[e] = 1f; // o's sensor keeps it at about 1 across the tick (decay .5 x dt) - - Tick(.01f); - - Assert.True(Track(o, e) >= .8f, "fixture: o still identifies e"); - - Assert.DoesNotContain(o.RevealsOf(e), r => r.Item == guns[0]); - Assert.Contains(o.RevealsOf(e), r => r.Item == guns[1]); - } - // A paint inboxed in the tick its emitter leaves the zone is published the next tick, and is no longer the act of // a subject in the zone: it warns for its tick and neither creates nor refreshes a reveal. The reveal the // locker's earlier paint made stays what it was, as a departure out of sight (below the observer's gate) leaves it. @@ -961,10 +907,7 @@ public sealed class ContactRevealTests : IDisposable var sense = SenseOf(o); for (var i = 0; i < 10; i++) sense(); Assert.Equal(19, _zone.Entities.Where(x => x != o).Count(x => o.RevealsOf(x).Any())); // fixture: every ship is revealed - // One of them is identified by o (its destroyed gun is ended in the pass), and one has left, quiet, so its - // entries await the prune and its departure sits in the zone's list. - var identified = gunItems.Select(g => _zone.Entities.Single(x => x.Equipment.Contains(g))).First(); - o.EntityInfoGathered[identified] = 1f; + // One of them has left, quiet, so its entries await the prune and its departure sits in the zone's list. var departed = _zone.Entities.Single(x => x.Equipment.Contains(gunItems[18])); foreach (var source in departed.VisibilitySources.Keys.ToArray()) departed.SetSignature(source, SignatureChannel.Reflection, 0f, gunItems[18]); _zone.Entities.Remove(departed);