Merge branch 'master' into 2020-08-19-firelocks
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Serialization;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Disposal
|
||||
{
|
||||
public class SharedDisposalRouterComponent : Component
|
||||
{
|
||||
public override string Name => "DisposalRouter";
|
||||
|
||||
public static readonly Regex TagRegex = new Regex("^[a-zA-Z0-9, ]*$", RegexOptions.Compiled);
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class DisposalRouterUserInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public readonly string Tags;
|
||||
|
||||
public DisposalRouterUserInterfaceState(string tags)
|
||||
{
|
||||
Tags = tags;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class UiActionMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly UiAction Action;
|
||||
public readonly string Tags = "";
|
||||
|
||||
public UiActionMessage(UiAction action, string tags)
|
||||
{
|
||||
Action = action;
|
||||
|
||||
if (Action == UiAction.Ok)
|
||||
{
|
||||
Tags = tags.Substring(0, Math.Min(tags.Length, 150));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum UiAction
|
||||
{
|
||||
Ok
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DisposalRouterUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#nullable enable
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Serialization;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Disposal
|
||||
{
|
||||
public class SharedDisposalTaggerComponent : Component
|
||||
{
|
||||
public override string Name => "DisposalTagger";
|
||||
|
||||
public static readonly Regex TagRegex = new Regex("^[a-zA-Z0-9 ]*$", RegexOptions.Compiled);
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class DisposalTaggerUserInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public readonly string Tag;
|
||||
|
||||
public DisposalTaggerUserInterfaceState(string tag)
|
||||
{
|
||||
Tag = tag;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class UiActionMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly UiAction Action;
|
||||
public readonly string Tag = "";
|
||||
|
||||
public UiActionMessage(UiAction action, string tag)
|
||||
{
|
||||
Action = action;
|
||||
|
||||
if (Action == UiAction.Ok)
|
||||
{
|
||||
Tag = tag.Substring(0, Math.Min(tag.Length, 30));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum UiAction
|
||||
{
|
||||
Ok
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DisposalTaggerUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,15 +17,18 @@ namespace Content.Shared.GameObjects.Components.Medical
|
||||
public readonly EntityUid? Entity;
|
||||
public readonly Dictionary<DamageClass, int> DamageClasses;
|
||||
public readonly Dictionary<DamageType, int> DamageTypes;
|
||||
public readonly bool IsScanned;
|
||||
|
||||
public MedicalScannerBoundUserInterfaceState(
|
||||
EntityUid? entity,
|
||||
Dictionary<DamageClass, int> damageClasses,
|
||||
Dictionary<DamageType, int> damageTypes)
|
||||
Dictionary<DamageType, int> damageTypes,
|
||||
bool isScanned)
|
||||
{
|
||||
Entity = entity;
|
||||
DamageClasses = damageClasses;
|
||||
DamageTypes = damageTypes;
|
||||
IsScanned = isScanned;
|
||||
}
|
||||
|
||||
public bool HasDamage()
|
||||
@@ -56,5 +59,24 @@ namespace Content.Shared.GameObjects.Components.Medical
|
||||
Green,
|
||||
Yellow,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum UiButton
|
||||
{
|
||||
ScanDNA,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class UiButtonPressedMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly UiButton Button;
|
||||
|
||||
public UiButtonPressedMessage(UiButton button)
|
||||
{
|
||||
Button = button;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Movement
|
||||
{
|
||||
public interface IClimbable { };
|
||||
|
||||
public class SharedClimbableComponent : Component, IClimbable
|
||||
{
|
||||
public sealed override string Name => "Climbable";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
using System;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Movement
|
||||
{
|
||||
public abstract class SharedClimbingComponent : Component, IActionBlocker, ICollideSpecial
|
||||
{
|
||||
public sealed override string Name => "Climbing";
|
||||
public sealed override uint? NetID => ContentNetIDs.CLIMBING;
|
||||
|
||||
protected ICollidableComponent Body;
|
||||
protected bool IsOnClimbableThisFrame = false;
|
||||
|
||||
protected bool OwnerIsTransitioning
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Body.TryGetController<ClimbController>(out var controller))
|
||||
{
|
||||
return controller.IsActive;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool IsClimbing { get; set; }
|
||||
|
||||
bool IActionBlocker.CanMove() => !OwnerIsTransitioning;
|
||||
bool IActionBlocker.CanChangeDirection() => !OwnerIsTransitioning;
|
||||
|
||||
bool ICollideSpecial.PreventCollide(IPhysBody collided)
|
||||
{
|
||||
if (((CollisionGroup)collided.CollisionLayer).HasFlag(CollisionGroup.VaultImpassable) && collided.Entity.HasComponent<IClimbable>())
|
||||
{
|
||||
IsOnClimbableThisFrame = true;
|
||||
return IsClimbing;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
Owner.TryGetComponent(out Body);
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class ClimbModeComponentState : ComponentState
|
||||
{
|
||||
public ClimbModeComponentState(bool climbing) : base(ContentNetIDs.CLIMBING)
|
||||
{
|
||||
Climbing = climbing;
|
||||
}
|
||||
|
||||
public bool Climbing { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ namespace Content.Shared.GameObjects.Components.Movement
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent component))
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent? component))
|
||||
{
|
||||
return component.CurrentWalkSpeed;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ namespace Content.Shared.GameObjects.Components.Movement
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent component))
|
||||
if (Owner.TryGetComponent(out MovementSpeedModifierComponent? component))
|
||||
{
|
||||
return component.CurrentSprintSpeed;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -108,7 +108,7 @@ namespace Content.Shared.GameObjects.Components.PDA
|
||||
[NetSerializable, Serializable]
|
||||
public enum PDAVisuals
|
||||
{
|
||||
ScreenLit,
|
||||
FlashlightLit,
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
public const uint STUNNABLE = 1048;
|
||||
public const uint HUNGER = 1049;
|
||||
public const uint THIRST = 1050;
|
||||
|
||||
public const uint FLASHABLE = 1051;
|
||||
public const uint BUCKLE = 1052;
|
||||
public const uint PROJECTILE = 1053;
|
||||
@@ -65,6 +64,7 @@
|
||||
public const uint DO_AFTER = 1058;
|
||||
public const uint RADIATION_PULSE = 1059;
|
||||
public const uint BODY_MANAGER = 1060;
|
||||
public const uint CLIMBING = 1061;
|
||||
|
||||
// Net IDs for integration tests.
|
||||
public const uint PREDICTION_TEST = 10001;
|
||||
|
||||
@@ -10,21 +10,13 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
public interface IActionBlocker
|
||||
{
|
||||
bool CanMove() => true;
|
||||
|
||||
bool CanInteract() => true;
|
||||
|
||||
bool CanUse() => true;
|
||||
|
||||
bool CanThrow() => true;
|
||||
|
||||
bool CanSpeak() => true;
|
||||
|
||||
bool CanDrop() => true;
|
||||
|
||||
bool CanPickup() => true;
|
||||
|
||||
bool CanEmote() => true;
|
||||
|
||||
bool CanAttack() => true;
|
||||
|
||||
bool CanEquip() => true;
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
private static bool TryGetAttachedComponent<T>(ICommonSession? session, [MaybeNullWhen(false)] out T component)
|
||||
where T : IComponent
|
||||
where T : class, IComponent
|
||||
{
|
||||
component = default;
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace Content.Shared.GameObjects.EntitySystems
|
||||
if (ent == null || !ent.IsValid())
|
||||
return false;
|
||||
|
||||
if (!ent.TryGetComponent(out T comp))
|
||||
if (!ent.TryGetComponent(out T? comp))
|
||||
return false;
|
||||
|
||||
component = comp;
|
||||
|
||||
@@ -12,20 +12,8 @@ namespace Content.Shared.GameObjects.Verbs
|
||||
/// To add a global verb to all entities,
|
||||
/// define it and mark it with <see cref="GlobalVerbAttribute"/>
|
||||
/// </remarks>
|
||||
public abstract class GlobalVerb
|
||||
public abstract class GlobalVerb : VerbBase
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, this verb requires the user to be within
|
||||
/// <see cref="VerbUtility.InteractionRange"/> meters from the entity on which this verb resides.
|
||||
/// </summary>
|
||||
public virtual bool RequireInteractionRange => true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this verb requires both the user and the entity on which
|
||||
/// this verb resides to be in the same container or no container.
|
||||
/// </summary>
|
||||
public virtual bool BlockedByContainers => true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,21 +12,8 @@ namespace Content.Shared.GameObjects.Verbs
|
||||
/// and mark it with <see cref="VerbAttribute"/>
|
||||
/// </remarks>
|
||||
[UsedImplicitly]
|
||||
public abstract class Verb
|
||||
public abstract class Verb : VerbBase
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, this verb requires the user to be inside within
|
||||
/// <see cref="VerbUtility.InteractionRange"/> meters from the entity on which this verb resides.
|
||||
/// </summary>
|
||||
public virtual bool RequireInteractionRange => true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this verb requires both the user and the entity on which
|
||||
/// this verb resides to be in the same container or no container.
|
||||
/// OR the user can be the entity's container
|
||||
/// </summary>
|
||||
public virtual bool BlockedByContainers => true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
|
||||
18
Content.Shared/GameObjects/Verbs/VerbBase.cs
Normal file
18
Content.Shared/GameObjects/Verbs/VerbBase.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace Content.Shared.GameObjects.Verbs
|
||||
{
|
||||
public abstract class VerbBase
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, this verb requires the user to be inside within
|
||||
/// <see cref="VerbUtility.InteractionRange"/> meters from the entity on which this verb resides.
|
||||
/// </summary>
|
||||
public virtual bool RequireInteractionRange => true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this verb requires both the user and the entity on which
|
||||
/// this verb resides to be in the same container or no container.
|
||||
/// OR the user can be the entity's container
|
||||
/// </summary>
|
||||
public virtual bool BlockedByContainers => true;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -50,6 +51,21 @@ namespace Content.Shared.GameObjects.Verbs
|
||||
}
|
||||
}
|
||||
|
||||
public static bool VerbAccessChecks(IEntity user, IEntity target, VerbBase verb)
|
||||
{
|
||||
if (verb.RequireInteractionRange && !InVerbUseRange(user, target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (verb.BlockedByContainers && !VerbContainerCheck(user, target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool InVerbUseRange(IEntity user, IEntity target)
|
||||
{
|
||||
var distanceSquared = (user.Transform.WorldPosition - target.Transform.WorldPosition)
|
||||
@@ -60,5 +76,19 @@ namespace Content.Shared.GameObjects.Verbs
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool VerbContainerCheck(IEntity user, IEntity target)
|
||||
{
|
||||
if (!user.IsInSameOrNoContainer(target))
|
||||
{
|
||||
if (!ContainerHelpers.TryGetContainer(target, out var container) ||
|
||||
container.Owner != user)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
89
Content.Shared/Physics/ClimbController.cs
Normal file
89
Content.Shared/Physics/ClimbController.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
#nullable enable
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Shared.Physics
|
||||
{
|
||||
/// <summary>
|
||||
/// Movement controller used by the climb system. Lerps the player from A to B.
|
||||
/// Also does checks to make sure the player isn't blocked.
|
||||
/// </summary>
|
||||
public class ClimbController : VirtualController
|
||||
{
|
||||
private Vector2? _movingTo = null;
|
||||
private Vector2 _lastKnownPosition = default;
|
||||
private int _numTicksBlocked = 0;
|
||||
|
||||
/// <summary>
|
||||
/// If 5 ticks have passed and our position has not changed then something is blocking us.
|
||||
/// </summary>
|
||||
public bool IsBlocked => _numTicksBlocked > 5 || _isMovingWrongDirection;
|
||||
|
||||
/// <summary>
|
||||
/// If the controller is currently moving the player somewhere, it is considered active.
|
||||
/// </summary>
|
||||
public bool IsActive => _movingTo.HasValue;
|
||||
|
||||
private float _initialDist = default;
|
||||
private bool _isMovingWrongDirection = false;
|
||||
|
||||
public void TryMoveTo(Vector2 from, Vector2 to)
|
||||
{
|
||||
if (ControlledComponent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_initialDist = (from - to).Length;
|
||||
_numTicksBlocked = 0;
|
||||
_lastKnownPosition = from;
|
||||
_movingTo = to;
|
||||
_isMovingWrongDirection = false;
|
||||
}
|
||||
|
||||
public override void UpdateAfterProcessing()
|
||||
{
|
||||
base.UpdateAfterProcessing();
|
||||
|
||||
if (ControlledComponent == null || _movingTo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ControlledComponent.WakeBody();
|
||||
|
||||
if ((ControlledComponent.Owner.Transform.WorldPosition - _lastKnownPosition).Length <= 0.05f)
|
||||
{
|
||||
_numTicksBlocked++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_numTicksBlocked = 0;
|
||||
}
|
||||
|
||||
_lastKnownPosition = ControlledComponent.Owner.Transform.WorldPosition;
|
||||
|
||||
if ((ControlledComponent.Owner.Transform.WorldPosition - _movingTo.Value).Length <= 0.1f)
|
||||
{
|
||||
_movingTo = null;
|
||||
}
|
||||
|
||||
if (_movingTo.HasValue)
|
||||
{
|
||||
var dist = (_lastKnownPosition - _movingTo.Value).Length;
|
||||
|
||||
if (dist > _initialDist)
|
||||
{
|
||||
_isMovingWrongDirection = true;
|
||||
}
|
||||
|
||||
var diff = _movingTo.Value - ControlledComponent.Owner.Transform.WorldPosition;
|
||||
LinearVelocity = diff.Normalized * 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
LinearVelocity = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,31 @@ namespace Content.Shared
|
||||
}
|
||||
}
|
||||
|
||||
protected class MsgTickerLateJoinStatus : NetMessage
|
||||
{
|
||||
#region REQUIRED
|
||||
|
||||
public const MsgGroups GROUP = MsgGroups.Command;
|
||||
public const string NAME = nameof(MsgTickerLateJoinStatus);
|
||||
|
||||
public bool Disallowed { get; set; }
|
||||
|
||||
public MsgTickerLateJoinStatus(INetChannel channel) : base(NAME, GROUP) { }
|
||||
|
||||
#endregion
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer)
|
||||
{
|
||||
Disallowed = buffer.ReadBoolean();
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer)
|
||||
{
|
||||
buffer.Write(Disallowed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected class MsgTickerLobbyStatus : NetMessage
|
||||
{
|
||||
#region REQUIRED
|
||||
@@ -166,13 +191,13 @@ namespace Content.Shared
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The Players Ready (SessionID:ready)
|
||||
/// The Status of the Player in the lobby (ready, observer, ...)
|
||||
/// </summary>
|
||||
public Dictionary<NetSessionId, bool> PlayerReady { get; set; }
|
||||
public Dictionary<NetSessionId, PlayerStatus> PlayerStatus { get; set; }
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer)
|
||||
{
|
||||
PlayerReady = new Dictionary<NetSessionId, bool>();
|
||||
PlayerStatus = new Dictionary<NetSessionId, PlayerStatus>();
|
||||
var length = buffer.ReadInt32();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
@@ -183,16 +208,16 @@ namespace Content.Shared
|
||||
{
|
||||
serializer.DeserializeDirect(stream, out sessionID);
|
||||
}
|
||||
var ready = buffer.ReadBoolean();
|
||||
PlayerReady.Add(sessionID, ready);
|
||||
var status = (PlayerStatus)buffer.ReadByte();
|
||||
PlayerStatus.Add(sessionID, status);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer)
|
||||
{
|
||||
var serializer = IoCManager.Resolve<IRobustSerializer>();
|
||||
buffer.Write(PlayerReady.Count);
|
||||
foreach (var p in PlayerReady)
|
||||
buffer.Write(PlayerStatus.Count);
|
||||
foreach (var p in PlayerStatus)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
@@ -201,7 +226,7 @@ namespace Content.Shared
|
||||
stream.TryGetBuffer(out var segment);
|
||||
buffer.Write(segment);
|
||||
}
|
||||
buffer.Write(p.Value);
|
||||
buffer.Write((byte)p.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +238,6 @@ namespace Content.Shared
|
||||
public string PlayerICName;
|
||||
public string Role;
|
||||
public bool Antag;
|
||||
|
||||
}
|
||||
|
||||
protected class MsgRoundEndMessage : NetMessage
|
||||
@@ -228,6 +252,7 @@ namespace Content.Shared
|
||||
#endregion
|
||||
|
||||
public string GamemodeTitle;
|
||||
public string RoundEndText;
|
||||
public TimeSpan RoundDuration;
|
||||
|
||||
|
||||
@@ -238,6 +263,7 @@ namespace Content.Shared
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer)
|
||||
{
|
||||
GamemodeTitle = buffer.ReadString();
|
||||
RoundEndText = buffer.ReadString();
|
||||
|
||||
var hours = buffer.ReadInt32();
|
||||
var mins = buffer.ReadInt32();
|
||||
@@ -264,6 +290,7 @@ namespace Content.Shared
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer)
|
||||
{
|
||||
buffer.Write(GamemodeTitle);
|
||||
buffer.Write(RoundEndText);
|
||||
buffer.Write(RoundDuration.Hours);
|
||||
buffer.Write(RoundDuration.Minutes);
|
||||
buffer.Write(RoundDuration.Seconds);
|
||||
@@ -280,6 +307,13 @@ namespace Content.Shared
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum PlayerStatus : byte
|
||||
{
|
||||
NotReady = 0,
|
||||
Ready,
|
||||
Observer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user