This commit is contained in:
Leon Friedrich
2022-01-30 13:49:56 +13:00
committed by GitHub
parent 6fb492aae7
commit c465715273
37 changed files with 1400 additions and 1429 deletions

View File

@@ -0,0 +1,8 @@
using Content.Shared.Doors.Components;
using Robust.Shared.GameObjects;
namespace Content.Client.Doors;
[RegisterComponent]
[ComponentReference(typeof(SharedAirlockComponent))]
public sealed class AirlockComponent : SharedAirlockComponent { }

View File

@@ -0,0 +1,5 @@
using Content.Shared.Doors.Systems;
namespace Content.Client.Doors;
public sealed class AirlockSystem : SharedAirlockSystem { }

View File

@@ -1,6 +1,6 @@
using System;
using Content.Client.Wires.Visualizers;
using Content.Shared.Doors;
using Content.Shared.Doors.Components;
using JetBrains.Annotations;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
@@ -8,6 +8,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Timing;
namespace Content.Client.Doors
{
@@ -15,6 +16,7 @@ namespace Content.Client.Doors
public class AirlockVisualizer : AppearanceVisualizer, ISerializationHooks
{
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
private const string AnimationKey = "airlock_animation";
@@ -122,15 +124,20 @@ namespace Content.Client.Doors
public override void OnChangeData(AppearanceComponent component)
{
// only start playing animations once.
if (!_gameTiming.IsFirstTimePredicted)
return;
base.OnChangeData(component);
var sprite = _entMan.GetComponent<ISpriteComponent>(component.Owner);
var animPlayer = _entMan.GetComponent<AnimationPlayerComponent>(component.Owner);
if (!component.TryGetData(DoorVisuals.VisualState, out DoorVisualState state))
if (!component.TryGetData(DoorVisuals.State, out DoorState state))
{
state = DoorVisualState.Closed;
state = DoorState.Closed;
}
var door = _entMan.GetComponent<DoorComponent>(component.Owner);
var unlitVisible = true;
var boltedVisible = false;
var weldedVisible = false;
@@ -141,7 +148,7 @@ namespace Content.Client.Doors
}
switch (state)
{
case DoorVisualState.Open:
case DoorState.Open:
sprite.LayerSetState(DoorVisualLayers.Base, "open");
unlitVisible = _openUnlitVisible;
if (_openUnlitVisible && !_simpleVisuals)
@@ -149,7 +156,7 @@ namespace Content.Client.Doors
sprite.LayerSetState(DoorVisualLayers.BaseUnlit, "open_unlit");
}
break;
case DoorVisualState.Closed:
case DoorState.Closed:
sprite.LayerSetState(DoorVisualLayers.Base, "closed");
if (!_simpleVisuals)
{
@@ -157,17 +164,19 @@ namespace Content.Client.Doors
sprite.LayerSetState(DoorVisualLayers.BaseBolted, "bolted_unlit");
}
break;
case DoorVisualState.Opening:
case DoorState.Opening:
animPlayer.Play(OpenAnimation, AnimationKey);
break;
case DoorVisualState.Closing:
animPlayer.Play(CloseAnimation, AnimationKey);
case DoorState.Closing:
if (door.CurrentlyCrushing.Count == 0)
animPlayer.Play(CloseAnimation, AnimationKey);
else
sprite.LayerSetState(DoorVisualLayers.Base, "closed");
break;
case DoorVisualState.Deny:
if (!animPlayer.HasRunningAnimation(AnimationKey))
animPlayer.Play(DenyAnimation, AnimationKey);
case DoorState.Denying:
animPlayer.Play(DenyAnimation, AnimationKey);
break;
case DoorVisualState.Welded:
case DoorState.Welded:
weldedVisible = true;
break;
default:
@@ -185,7 +194,7 @@ namespace Content.Client.Doors
if (!_simpleVisuals)
{
sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, unlitVisible && state != DoorVisualState.Closed);
sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, unlitVisible && state != DoorState.Closed && state != DoorState.Welded);
sprite.LayerSetVisible(DoorVisualLayers.BaseWelded, weldedVisible);
sprite.LayerSetVisible(DoorVisualLayers.BaseBolted, unlitVisible && boltedVisible);
}

View File

@@ -1,100 +0,0 @@
using System;
using Content.Shared.Doors;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using DrawDepthTag = Robust.Shared.GameObjects.DrawDepth;
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
namespace Content.Client.Doors
{
/// <summary>
/// Bare-bones client-side door component; used to stop door-based mispredicts.
/// </summary>
[UsedImplicitly]
[RegisterComponent]
[ComponentReference(typeof(SharedDoorComponent))]
public class ClientDoorComponent : SharedDoorComponent
{
[DataField("openDrawDepth", customTypeSerializer: typeof(ConstantSerializer<DrawDepthTag>))]
public int OpenDrawDepth = (int) DrawDepth.Doors;
[DataField("closedDrawDepth", customTypeSerializer: typeof(ConstantSerializer<DrawDepthTag>))]
public int ClosedDrawDepth = (int) DrawDepth.Doors;
private bool _stateChangeHasProgressed = false;
private TimeSpan _timeOffset;
public override DoorState State
{
protected set
{
if (State == value)
{
return;
}
base.State = value;
IoCManager.Resolve<IEntityManager>().EventBus.RaiseLocalEvent(Owner, new DoorStateChangedEvent(State), false);
}
}
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();
}
}
}
}

View File

@@ -1,69 +1,35 @@
using System;
using System.Collections.Generic;
using Content.Shared.Doors;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
using Robust.Client.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using static Content.Shared.Doors.SharedDoorComponent;
using Robust.Shared.Player;
namespace Content.Client.Doors
namespace Content.Client.Doors;
public sealed class DoorSystem : SharedDoorSystem
{
/// <summary>
/// Used by the client to "predict" when doors will change how collideable they are as part of their opening / closing.
/// </summary>
internal sealed class DoorSystem : SharedDoorSystem
// Gotta love it when both the client-side and server-side sprite components both have a draw depth, but for
// whatever bloody reason the shared component doesn't.
protected override void UpdateAppearance(EntityUid uid, DoorComponent? door = null)
{
/// <summary>
/// List of doors that need to be periodically checked.
/// </summary>
private readonly List<ClientDoorComponent> _activeDoors = new();
if (!Resolve(uid, ref door))
return;
public override void Initialize()
base.UpdateAppearance(uid, door);
if (TryComp(uid, out SpriteComponent? sprite))
{
base.Initialize();
UpdatesOutsidePrediction = true;
SubscribeLocalEvent<ClientDoorComponent, DoorStateChangedEvent>(OnDoorStateChanged);
}
private void OnDoorStateChanged(EntityUid uid, ClientDoorComponent door, DoorStateChangedEvent args)
{
switch (args.State)
{
case DoorState.Closed:
case DoorState.Open:
_activeDoors.Remove(door);
break;
case DoorState.Closing:
case DoorState.Opening:
_activeDoors.Add(door);
break;
default:
throw new ArgumentOutOfRangeException();
}
if (!EntityManager.TryGetComponent(uid, out SpriteComponent sprite))
return;
// Update sprite draw depth. If the door is opening or closing, we will use the closed-draw depth.
sprite.DrawDepth = (args.State == DoorState.Open)
sprite.DrawDepth = (door.State == DoorState.Open)
? door.OpenDrawDepth
: door.ClosedDrawDepth;
}
}
/// <inheritdoc />
public override void Update(float frameTime)
{
for (var i = _activeDoors.Count - 1; i >= 0; i--)
{
var comp = _activeDoors[i];
if (comp.Deleted)
{
_activeDoors.RemoveAt(i);
continue;
}
comp.OnUpdate();
}
}
// TODO AUDIO PREDICT see comments in server-side PlaySound()
protected override void PlaySound(EntityUid uid, string sound, AudioParams audioParams, EntityUid? predictingPlayer, bool predicted)
{
if (GameTiming.InPrediction && GameTiming.IsFirstTimePredicted)
SoundSystem.Play(Filter.Local(), sound, uid, audioParams);
}
}

View File

@@ -44,7 +44,6 @@ namespace Content.Client.Entry
"ResearchPointSource",
"ResearchClient",
"IdCardConsole",
"Airlock",
"ThermalRegulator",
"AtmosFixMarker",
"CablePlacer",
@@ -75,7 +74,6 @@ namespace Content.Client.Entry
"Brain",
"CommunicationsConsole",
"BarSign",
"DoorBumpOpener",
"SolarPanel",
"BodyScanner",
"Stunbaton",