diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs new file mode 100644 index 0000000000..7e7978a7ff --- /dev/null +++ b/EXILED/Exiled.API/Features/Workstation.cs @@ -0,0 +1,167 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.API.Features +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + + using Exiled.API.Enums; + using Exiled.API.Interfaces; + using InventorySystem.Items.Firearms.Attachments; + using Mirror; + using UnityEngine; + + /// + /// A wrapper class for . + /// + public class Workstation : IWrapper, IWorldSpace + { + /// + /// A dictionary mapping to . + /// + internal static readonly Dictionary WorkstationControllerToWorkstation = new(new ComponentsEqualityComparer()); + + /// + /// Initializes a new instance of the class. + /// + /// The to wrap. + internal Workstation(WorkstationController workstationController) + { + WorkstationControllerToWorkstation.Add(workstationController, this); + Base = workstationController; + } + + /// + /// Gets a read-only collection of all instances. + /// + public static IReadOnlyCollection List => WorkstationControllerToWorkstation.Values; + + /// + /// Gets the underlying instance. + /// + public WorkstationController Base { get; } + + /// + /// Gets the of the workstation. + /// + public GameObject GameObject => Base.gameObject; + + /// + /// Gets the of the workstation. + /// + public Transform Transform => Base.transform; + + /// + /// Gets the the workstation is located in. + /// + public Room Room => Room.Get(Position); + + /// + /// Gets the of the workstation's room. + /// + public ZoneType Zone => Room.Zone; + + /// + /// Gets or sets the position of the workstation. + /// + public Vector3 Position + { + get => Transform.position; + set + { + NetworkServer.UnSpawn(GameObject); + Transform.position = value; + NetworkServer.Spawn(GameObject); + } + } + + /// + /// Gets or sets the rotation of the workstation. + /// + public Quaternion Rotation + { + get => Transform.rotation; + set + { + NetworkServer.UnSpawn(GameObject); + Transform.rotation = value; + NetworkServer.Spawn(GameObject); + } + } + + /// + /// Gets or sets the status of the workstation. + /// + public WorkstationController.WorkstationStatus Status + { + get => (WorkstationController.WorkstationStatus)Base.Status; + set => Base.NetworkStatus = (byte)value; + } + + /// + /// Gets the used by the workstation. + /// + public Stopwatch Stopwatch => Base.ServerStopwatch; + + /// + /// Gets or sets the player known to be using the workstation. + /// + public Player KnownUser + { + get => Player.Get(Base.KnownUser); + set => Base.KnownUser = value.ReferenceHub; + } + + /// + /// Gets a given a instance. + /// + /// The instance. + /// The instance. + public static Workstation Get(WorkstationController workstationController) => WorkstationControllerToWorkstation.TryGetValue(workstationController, out Workstation workstation) ? workstation : new(workstationController); + + /// + /// Gets all instances that match the specified predicate. + /// + /// The predicate to filter workstations. + /// An of matching workstations. + public static IEnumerable Get(Func predicate) => List.Where(predicate); + + /// + /// Tries to get all instances that match the specified predicate. + /// + /// The predicate to filter workstations. + /// The matching workstations, if any. + /// true if any workstations were found; otherwise, false. + public static bool TryGet(Func predicate, out IEnumerable workstations) + { + workstations = Get(predicate); + return workstations.Any(); + } + + /// + /// Determines whether the specified player is in range of the workstation. + /// + /// The player to check. + /// true if the player is in range; otherwise, false. + public bool IsInRange(Player player) => Base.IsInRange(player.ReferenceHub); + + /// + /// Interacts with the workstation as the specified player. + /// + /// The player to interact as. + public void Interact(Player player) => Base.ServerInteract(player.ReferenceHub, Base.ActivateCollider.ColliderId); + + /// + /// Returns the Room in a human-readable format. + /// + /// A string containing Workstation-related data. + public override string ToString() => $"{GameObject.name} ({Zone}) [{Room}]"; + } +} \ No newline at end of file diff --git a/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs b/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs new file mode 100644 index 0000000000..544ef5086e --- /dev/null +++ b/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs @@ -0,0 +1,39 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.Patches.Generic +{ +#pragma warning disable SA1313 +#pragma warning disable SA1402 + + using HarmonyLib; + using InventorySystem.Items.Firearms.Attachments; + + /// + /// Patch for adding to list. + /// + [HarmonyPatch(typeof(WorkstationController), nameof(WorkstationController.Start))] + internal class WorkstationListAdd + { + private static void Postfix(WorkstationController __instance) + { + API.Features.Workstation.Get(__instance); + } + } + + /// + /// Patch for removing to list. + /// + [HarmonyPatch(typeof(WorkstationController), nameof(WorkstationController.OnDestroy))] + internal class WorkstationListRemove + { + private static void Postfix(WorkstationController __instance) + { + API.Features.Workstation.WorkstationControllerToWorkstation.Remove(__instance); + } + } +} \ No newline at end of file