Make doors event-based rather than EntityQuery based (#2195)

* Event-based door updates

Slight perf increase

* Optimise CheckCrush too

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
metalgearsloth
2020-10-10 22:33:56 +11:00
committed by GitHub
parent fe39b5fb71
commit 7bf28ff3d5
2 changed files with 64 additions and 30 deletions

View File

@@ -43,7 +43,14 @@ namespace Content.Server.GameObjects.Components.Doors
public virtual DoorState State public virtual DoorState State
{ {
get => _state; get => _state;
protected set => _state = value; protected set
{
if (_state == value)
return;
_state = value;
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new DoorStateMessage(this, State));
}
} }
[ViewVariables] [ViewVariables]
@@ -291,17 +298,10 @@ namespace Content.Server.GameObjects.Components.Doors
private void CheckCrush() private void CheckCrush()
{ {
if (!Owner.TryGetComponent(out ICollidableComponent? body)) if (!Owner.TryGetComponent(out ICollidableComponent? body))
{
return; return;
}
// Check if collides with something
var collidesWith = body.GetCollidingEntities(Vector2.Zero, false);
if (collidesWith.Count() != 0)
{
// Crush // Crush
bool hitSomeone = false; foreach (var e in body.GetCollidingEntities(Vector2.Zero, false))
foreach (var e in collidesWith)
{ {
if (!e.TryGetComponent(out StunnableComponent? stun) if (!e.TryGetComponent(out StunnableComponent? stun)
|| !e.TryGetComponent(out IDamageableComponent? damage) || !e.TryGetComponent(out IDamageableComponent? damage)
@@ -315,14 +315,10 @@ namespace Content.Server.GameObjects.Components.Doors
damage.ChangeDamage(DamageType.Blunt, DoorCrushDamage, false, Owner); damage.ChangeDamage(DamageType.Blunt, DoorCrushDamage, false, Owner);
stun.Paralyze(DoorStunTime); stun.Paralyze(DoorStunTime);
hitSomeone = true;
}
// If we hit someone, open up after stun (opens right when stun ends) // If we hit someone, open up after stun (opens right when stun ends)
if (hitSomeone) Timer.Spawn(TimeSpan.FromSeconds(DoorStunTime) - OpenTimeOne - OpenTimeTwo, Open);
{ break;
Timer.Spawn(TimeSpan.FromSeconds(DoorStunTime) - OpenTimeOne - OpenTimeTwo, () => Open());
}
} }
} }
@@ -428,9 +424,7 @@ namespace Content.Server.GameObjects.Components.Doors
public virtual void Deny() public virtual void Deny()
{ {
if (State == DoorState.Open || _isWeldedShut) if (State == DoorState.Open || _isWeldedShut)
{
return; return;
}
SetAppearance(DoorVisualState.Deny); SetAppearance(DoorVisualState.Deny);
Timer.Spawn(DenyTime, () => Timer.Spawn(DenyTime, () =>
@@ -499,4 +493,16 @@ namespace Content.Server.GameObjects.Components.Doors
return true; return true;
} }
} }
public sealed class DoorStateMessage : EntitySystemMessage
{
public ServerDoorComponent Component { get; }
public ServerDoorComponent.DoorState State { get; }
public DoorStateMessage(ServerDoorComponent component, ServerDoorComponent.DoorState state)
{
Component = component;
State = state;
}
}
} }

View File

@@ -1,6 +1,9 @@
using Content.Server.GameObjects.Components.Doors; using System;
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Doors;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.EntitySystems namespace Content.Server.GameObjects.EntitySystems
{ {
@@ -32,18 +35,43 @@ namespace Content.Server.GameObjects.EntitySystems
AllowAll AllowAll
} }
private List<ServerDoorComponent> _activeDoors = new List<ServerDoorComponent>();
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
AccessType = AccessTypes.Id; AccessType = AccessTypes.Id;
SubscribeLocalEvent<DoorStateMessage>(HandleDoorState);
}
private void HandleDoorState(DoorStateMessage message)
{
switch (message.State)
{
case ServerDoorComponent.DoorState.Closed:
_activeDoors.Remove(message.Component);
break;
case ServerDoorComponent.DoorState.Open:
_activeDoors.Add(message.Component);
break;
case ServerDoorComponent.DoorState.Closing:
case ServerDoorComponent.DoorState.Opening:
break;
default:
throw new ArgumentOutOfRangeException();
}
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
foreach (var comp in ComponentManager.EntityQuery<ServerDoorComponent>()) for (var i = _activeDoors.Count - 1; i >= 0; i--)
{ {
var comp = _activeDoors[i];
if (comp.Deleted)
_activeDoors.RemoveAt(i);
comp.OnUpdate(frameTime); comp.OnUpdate(frameTime);
} }
} }