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
{
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]
@@ -291,17 +298,10 @@ namespace Content.Server.GameObjects.Components.Doors
private void CheckCrush()
{
if (!Owner.TryGetComponent(out ICollidableComponent? body))
{
return;
}
// Check if collides with something
var collidesWith = body.GetCollidingEntities(Vector2.Zero, false);
if (collidesWith.Count() != 0)
{
// Crush
bool hitSomeone = false;
foreach (var e in collidesWith)
foreach (var e in body.GetCollidingEntities(Vector2.Zero, false))
{
if (!e.TryGetComponent(out StunnableComponent? stun)
|| !e.TryGetComponent(out IDamageableComponent? damage)
@@ -315,14 +315,10 @@ namespace Content.Server.GameObjects.Components.Doors
damage.ChangeDamage(DamageType.Blunt, DoorCrushDamage, false, Owner);
stun.Paralyze(DoorStunTime);
hitSomeone = true;
}
// If we hit someone, open up after stun (opens right when stun ends)
if (hitSomeone)
{
Timer.Spawn(TimeSpan.FromSeconds(DoorStunTime) - OpenTimeOne - OpenTimeTwo, () => Open());
}
Timer.Spawn(TimeSpan.FromSeconds(DoorStunTime) - OpenTimeOne - OpenTimeTwo, Open);
break;
}
}
@@ -428,9 +424,7 @@ namespace Content.Server.GameObjects.Components.Doors
public virtual void Deny()
{
if (State == DoorState.Open || _isWeldedShut)
{
return;
}
SetAppearance(DoorVisualState.Deny);
Timer.Spawn(DenyTime, () =>
@@ -499,4 +493,16 @@ namespace Content.Server.GameObjects.Components.Doors
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 Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.EntitySystems
{
@@ -32,18 +35,43 @@ namespace Content.Server.GameObjects.EntitySystems
AllowAll
}
private List<ServerDoorComponent> _activeDoors = new List<ServerDoorComponent>();
public override void Initialize()
{
base.Initialize();
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 />
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);
}
}