Airlock / firelock code refactor, pseudo-prediction implementation (#3037)

* splits off airlocks, firelocks

* adds airlock prediction. anims broken though

* fixes animation weirdness

* removes opacity prediction because it looked odd

* Now firelocks don't visually start open. Argh.

* Fixes firelock weirdness, saneifies _state var.

* Documentation changes, code shuffle.

* Lets firelocks crush people.

* Stops open-hand opening/closing firelocks.

* updates serializable, netserializable attributes

* Addresses reviews... hopefully.

* updates submodule?

* nullability

* fuck fuck fuck fuck

* fucking finally
This commit is contained in:
tmtmtl30
2021-02-12 07:02:14 -08:00
committed by GitHub
parent 5f15d97940
commit 258fdc10ea
17 changed files with 1248 additions and 733 deletions

View File

@@ -1,4 +1,5 @@
using System;
#nullable enable
using System;
using Content.Client.GameObjects.Components.Wires;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Doors;
@@ -16,9 +17,9 @@ namespace Content.Client.GameObjects.Components.Doors
{
private const string AnimationKey = "airlock_animation";
private Animation CloseAnimation;
private Animation OpenAnimation;
private Animation DenyAnimation;
private Animation CloseAnimation = default!;
private Animation OpenAnimation = default!;
private Animation DenyAnimation = default!;
public override void LoadData(YamlMappingNode node)
{
@@ -113,35 +114,31 @@ namespace Content.Client.GameObjects.Components.Doors
var unlitVisible = true;
var boltedVisible = false;
var weldedVisible = false;
if (animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Stop(AnimationKey);
}
switch (state)
{
case DoorVisualState.Open:
sprite.LayerSetState(DoorVisualLayers.Base, "open");
unlitVisible = false;
break;
case DoorVisualState.Closed:
sprite.LayerSetState(DoorVisualLayers.Base, "closed");
sprite.LayerSetState(DoorVisualLayers.BaseUnlit, "closed_unlit");
sprite.LayerSetState(DoorVisualLayers.BaseBolted, "bolted");
sprite.LayerSetState(WiresVisualizer.WiresVisualLayers.MaintenancePanel, "panel_open");
break;
case DoorVisualState.Closing:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(CloseAnimation, AnimationKey);
}
break;
case DoorVisualState.Opening:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(OpenAnimation, AnimationKey);
}
animPlayer.Play(OpenAnimation, AnimationKey);
break;
case DoorVisualState.Open:
sprite.LayerSetState(DoorVisualLayers.Base, "open");
unlitVisible = false;
case DoorVisualState.Closing:
animPlayer.Play(CloseAnimation, AnimationKey);
break;
case DoorVisualState.Deny:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(DenyAnimation, AnimationKey);
}
animPlayer.Play(DenyAnimation, AnimationKey);
break;
case DoorVisualState.Welded:
weldedVisible = true;

View File

@@ -0,0 +1,102 @@
#nullable enable
using Content.Shared.GameObjects.Components.Doors;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.ViewVariables;
using System;
namespace Content.Client.GameObjects.Components.Doors
{
/// <summary>
/// Bare-bones client-side door component; used to stop door-based mispredicts.
/// </summary>
[UsedImplicitly]
[RegisterComponent]
[ComponentReference(typeof(SharedDoorComponent))]
public class ClientDoorComponent : SharedDoorComponent
{
private bool _stateChangeHasProgressed = false;
private TimeSpan _timeOffset;
public override DoorState State
{
protected set
{
if (State == value)
{
return;
}
base.State = value;
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new DoorStateMessage(this, State));
}
}
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
base.HandleComponentState(curState, nextState);
if (curState is not DoorComponentState doorCompState)
{
return;
}
CurrentlyCrushing = doorCompState.CurrentlyCrushing;
StateChangeStartTime = doorCompState.StartTime;
State = doorCompState.DoorState;
if (StateChangeStartTime == null)
{
return;
}
_timeOffset = State switch
{
DoorState.Opening => OpenTimeOne,
DoorState.Closing => CloseTimeOne,
_ => throw new ArgumentOutOfRangeException(),
};
if (doorCompState.CurTime >= StateChangeStartTime + _timeOffset)
{
_stateChangeHasProgressed = true;
return;
}
_stateChangeHasProgressed = false;
}
public void OnUpdate()
{
if (!_stateChangeHasProgressed)
{
if (GameTiming.CurTime < StateChangeStartTime + _timeOffset) return;
if (State == DoorState.Opening)
{
OnPartialOpen();
}
else
{
OnPartialClose();
}
_stateChangeHasProgressed = true;
Dirty();
}
}
}
public sealed class DoorStateMessage : EntitySystemMessage
{
public ClientDoorComponent Component { get; }
public SharedDoorComponent.DoorState State { get; }
public DoorStateMessage(ClientDoorComponent component, SharedDoorComponent.DoorState state)
{
Component = component;
State = state;
}
}
}