From 825b045f7288adf9b303c960463b6b4d8d4cb50d Mon Sep 17 00:00:00 2001 From: GoldenPig1205 <78902671+GoldenPig1205@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:26:23 +0900 Subject: [PATCH 1/6] Add Exiled.API.Features.Workstation --- EXILED/Exiled.API/Features/Workstation.cs | 158 ++++++++++++++++++ .../Patches/Generic/WorkstationListAdd.cs | 39 +++++ 2 files changed, 197 insertions(+) create mode 100644 EXILED/Exiled.API/Features/Workstation.cs create mode 100644 EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs new file mode 100644 index 0000000000..e8ee24c64c --- /dev/null +++ b/EXILED/Exiled.API/Features/Workstation.cs @@ -0,0 +1,158 @@ +// ----------------------------------------------------------------------- +// +// 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 Interactables.Interobjects.DoorUtils; + using Interactables.Interobjects; + using InventorySystem.Items.Firearms.Attachments; + using LabApi.Features.Wrappers; + 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(Transform.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 => Base.transform.position; + set => Base.transform.position = value; + } + + /// + /// Gets or sets the rotation of the workstation. + /// + public Quaternion Rotation + { + get => Base.transform.rotation; + set => Base.transform.rotation = value; + } + + /// + /// 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 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) + { + return 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..36bb0029e1 --- /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) + { + _ = new API.Features.Workstation(__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 From 6cd8ff03a117f300515feafd9850902c274d5ace Mon Sep 17 00:00:00 2001 From: GoldenPig1205 <78902671+GoldenPig1205@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:32:44 +0900 Subject: [PATCH 2/6] fix --- EXILED/Exiled.API/Features/Workstation.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs index e8ee24c64c..af27eb0a4a 100644 --- a/EXILED/Exiled.API/Features/Workstation.cs +++ b/EXILED/Exiled.API/Features/Workstation.cs @@ -14,10 +14,7 @@ namespace Exiled.API.Features using Exiled.API.Enums; using Exiled.API.Interfaces; - using Interactables.Interobjects.DoorUtils; - using Interactables.Interobjects; using InventorySystem.Items.Firearms.Attachments; - using LabApi.Features.Wrappers; using UnityEngine; /// From e4b77a86c9b6e64b51d4ad503e886beb63e41710 Mon Sep 17 00:00:00 2001 From: GoldenPig1205 <78902671+GoldenPig1205@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:50:35 +0900 Subject: [PATCH 3/6] Approve the feedback --- EXILED/Exiled.API/Features/Workstation.cs | 31 +++++++++++++---------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs index af27eb0a4a..792c0def08 100644 --- a/EXILED/Exiled.API/Features/Workstation.cs +++ b/EXILED/Exiled.API/Features/Workstation.cs @@ -15,6 +15,7 @@ namespace Exiled.API.Features using Exiled.API.Enums; using Exiled.API.Interfaces; using InventorySystem.Items.Firearms.Attachments; + using Mirror; using UnityEngine; /// @@ -72,8 +73,13 @@ internal Workstation(WorkstationController workstationController) /// public Vector3 Position { - get => Base.transform.position; - set => Base.transform.position = value; + get => GameObject.transform.position; + set + { + NetworkServer.UnSpawn(GameObject); + GameObject.transform.position = value; + NetworkServer.Spawn(GameObject); + } } /// @@ -81,8 +87,13 @@ public Vector3 Position /// public Quaternion Rotation { - get => Base.transform.rotation; - set => Base.transform.rotation = value; + get => GameObject.transform.rotation; + set + { + NetworkServer.UnSpawn(GameObject); + GameObject.transform.rotation = value; + NetworkServer.Spawn(GameObject); + } } /// @@ -124,7 +135,7 @@ public Player KnownUser public static bool TryGet(Func predicate, out IEnumerable workstations) { workstations = Get(predicate); - return workstations.Any(); + return Get(predicate).Any(); } /// @@ -132,19 +143,13 @@ public static bool TryGet(Func predicate, out IEnumerable /// The player to check. /// true if the player is in range; otherwise, false. - public bool IsInRange(Player player) - { - return Base.IsInRange(player.ReferenceHub); - } + 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); - } + public void Interact(Player player) => Base.ServerInteract(player.ReferenceHub, Base.ActivateCollider.ColliderId); /// /// Returns the Room in a human-readable format. From 7d147b49b91ca3806b8a69bc428da6b9fad02f1e Mon Sep 17 00:00:00 2001 From: GoldenPig1205 <78902671+GoldenPig1205@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:55:10 +0900 Subject: [PATCH 4/6] omg --- EXILED/Exiled.API/Features/Workstation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs index 792c0def08..61ee3b2d57 100644 --- a/EXILED/Exiled.API/Features/Workstation.cs +++ b/EXILED/Exiled.API/Features/Workstation.cs @@ -135,7 +135,7 @@ public Player KnownUser public static bool TryGet(Func predicate, out IEnumerable workstations) { workstations = Get(predicate); - return Get(predicate).Any(); + return workstations.Any(); } /// From 70d00628e37af77e3a3e28ed4662b0aa66d57c2b Mon Sep 17 00:00:00 2001 From: Yamato Date: Sat, 5 Jul 2025 18:49:53 +0200 Subject: [PATCH 5/6] fix: Workstation ctor could be called twice --- EXILED/Exiled.API/Features/Workstation.cs | 7 +++++++ EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs index 61ee3b2d57..1062027ef8 100644 --- a/EXILED/Exiled.API/Features/Workstation.cs +++ b/EXILED/Exiled.API/Features/Workstation.cs @@ -119,6 +119,13 @@ public Player 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. /// diff --git a/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs b/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs index 36bb0029e1..544ef5086e 100644 --- a/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs +++ b/EXILED/Exiled.Events/Patches/Generic/WorkstationListAdd.cs @@ -21,7 +21,7 @@ internal class WorkstationListAdd { private static void Postfix(WorkstationController __instance) { - _ = new API.Features.Workstation(__instance); + API.Features.Workstation.Get(__instance); } } From 4d56789caf00dba2aaf4763a3f68aeba635b244a Mon Sep 17 00:00:00 2001 From: Yamato Date: Sat, 5 Jul 2025 18:51:22 +0200 Subject: [PATCH 6/6] use Transform --- EXILED/Exiled.API/Features/Workstation.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/EXILED/Exiled.API/Features/Workstation.cs b/EXILED/Exiled.API/Features/Workstation.cs index 1062027ef8..7e7978a7ff 100644 --- a/EXILED/Exiled.API/Features/Workstation.cs +++ b/EXILED/Exiled.API/Features/Workstation.cs @@ -61,7 +61,7 @@ internal Workstation(WorkstationController workstationController) /// /// Gets the the workstation is located in. /// - public Room Room => Room.Get(Transform.position); + public Room Room => Room.Get(Position); /// /// Gets the of the workstation's room. @@ -73,11 +73,11 @@ internal Workstation(WorkstationController workstationController) /// public Vector3 Position { - get => GameObject.transform.position; + get => Transform.position; set { NetworkServer.UnSpawn(GameObject); - GameObject.transform.position = value; + Transform.position = value; NetworkServer.Spawn(GameObject); } } @@ -87,11 +87,11 @@ public Vector3 Position /// public Quaternion Rotation { - get => GameObject.transform.rotation; + get => Transform.rotation; set { NetworkServer.UnSpawn(GameObject); - GameObject.transform.rotation = value; + Transform.rotation = value; NetworkServer.Spawn(GameObject); } }