From c4ff84e8b64b178969cea00f3a658ebdc5ef4d0e Mon Sep 17 00:00:00 2001 From: code002lover Date: Wed, 28 May 2025 01:21:24 +0200 Subject: [PATCH] did a few things --- CuffedFrenemies/CuffedFrenemies.cs | 28 ++++- CuffedFrenemies/CuffedFrenemies.csproj | 3 + KeycardButModern/DoorLockConfiguration.cs | 29 +++++ KeycardButModern/KeycardButModern.cs | 86 +++++++++++++-- KeycardButModern/KeycardButModern.csproj | 3 + ModTools/ModTools.csproj | 41 +++++++ ModTools/ReportNotifier.cs | 70 ++++++++++++ RangeBan.Tests/UnitTest1.cs | 1 + SecretPluginLaboratories.sln | 6 + VisibleSpectators/VisibleSpectators.cs | 128 +++++++++++++++++++--- 10 files changed, 367 insertions(+), 28 deletions(-) create mode 100644 KeycardButModern/DoorLockConfiguration.cs create mode 100644 ModTools/ModTools.csproj create mode 100644 ModTools/ReportNotifier.cs diff --git a/CuffedFrenemies/CuffedFrenemies.cs b/CuffedFrenemies/CuffedFrenemies.cs index f25eb9d..c18649e 100644 --- a/CuffedFrenemies/CuffedFrenemies.cs +++ b/CuffedFrenemies/CuffedFrenemies.cs @@ -1,4 +1,5 @@ -using LabApi.Events.Arguments.PlayerEvents; +using CustomPlayerEffects; +using LabApi.Events.Arguments.PlayerEvents; using LabApi.Events.Handlers; using LabApi.Features; using LabApi.Features.Console; @@ -6,6 +7,8 @@ using LabApi.Features.Wrappers; using LabApi.Loader.Features.Plugins; using Mirror; using PlayerRoles; +using PlayerRoles.PlayableScps.Scp3114; +using PlayerRoles.Ragdolls; namespace CuffedFrenemies; @@ -30,7 +33,6 @@ public class CuffedFrenemies : Plugin private static void OnCuff(PlayerCuffedEventArgs ev) { - Logger.Debug($"Team: {ev.Target.Team}"); if (ev.Target.Team is Team.ClassD or Team.Scientists) { return; @@ -42,6 +44,28 @@ public class CuffedFrenemies : Plugin return; } + if (ev.Target.RoleBase is Scp3114Role scp3114) + { + var stolenRole = scp3114.CurIdentity.StolenRole; + var ragdoll = scp3114.CurIdentity.Ragdoll.Info; + switch (stolenRole) + { + case RoleTypeId.ChaosConscript or RoleTypeId.ChaosMarauder or RoleTypeId.ChaosRepressor + or RoleTypeId.ChaosRifleman: + scp3114.CurIdentity.Ragdoll.Info = new RagdollData(ragdoll.OwnerHub, ragdoll.Handler, RoleTypeId.NtfPrivate, ragdoll.StartPosition, ragdoll.StartRotation, ragdoll.Nickname, ragdoll.CreationTime); + return; + case RoleTypeId.NtfPrivate or RoleTypeId.NtfCaptain or RoleTypeId.NtfSergeant + or RoleTypeId.NtfSpecialist: + scp3114.CurIdentity.Ragdoll.Info = new RagdollData(ragdoll.OwnerHub, ragdoll.Handler, RoleTypeId.ChaosConscript, ragdoll.StartPosition, ragdoll.StartRotation, ragdoll.Nickname, ragdoll.CreationTime); + return; + } + } + + if (ev.Target.Team is Team.SCPs or Team.Dead) + { + return; + } + var newRole = ev.Target.Team == Team.ChaosInsurgency ? RoleTypeId.NtfPrivate : RoleTypeId.ChaosConscript; Logger.Debug($"Setting role to {newRole}"); var newItems = new List(); diff --git a/CuffedFrenemies/CuffedFrenemies.csproj b/CuffedFrenemies/CuffedFrenemies.csproj index 56e256b..ede44b7 100644 --- a/CuffedFrenemies/CuffedFrenemies.csproj +++ b/CuffedFrenemies/CuffedFrenemies.csproj @@ -26,6 +26,9 @@ ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Mirror.dll + + ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Pooling.dll + ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.CoreModule.dll diff --git a/KeycardButModern/DoorLockConfiguration.cs b/KeycardButModern/DoorLockConfiguration.cs new file mode 100644 index 0000000..781df3d --- /dev/null +++ b/KeycardButModern/DoorLockConfiguration.cs @@ -0,0 +1,29 @@ +using Interactables.Interobjects.DoorUtils; +using LabApi.Features.Console; + +namespace KeycardButModern; + +public enum DoorType +{ + Normal, + Gate, + Checkpoint +} + +public class DoorLockConfiguration +{ + public Dictionary LockDurations { get; set; }= new() + { + { DoorType.Normal, 5f }, + { DoorType.Gate, 8f }, + { DoorType.Checkpoint, 3f } + }; + + public static DoorType GetDoorType(DoorVariant door) + { + Logger.Debug("Door name: " + door.name); + if (door.name.Contains("Checkpoint")) + return DoorType.Checkpoint; + return door.name.Contains("Gate") ? DoorType.Gate : DoorType.Normal; + } +} \ No newline at end of file diff --git a/KeycardButModern/KeycardButModern.cs b/KeycardButModern/KeycardButModern.cs index 181e928..c2edc93 100644 --- a/KeycardButModern/KeycardButModern.cs +++ b/KeycardButModern/KeycardButModern.cs @@ -1,10 +1,14 @@ +using System.Collections; +using Interactables.Interobjects; +using Interactables.Interobjects.DoorButtons; using Interactables.Interobjects.DoorUtils; -using InventorySystem.Items.Keycards; using LabApi.Events.Arguments.PlayerEvents; using LabApi.Events.Handlers; using LabApi.Features; -using LabApi.Features.Console; -using PlayerRoles; +using LabApi.Loader; +using UnityEngine; +using KeycardItem = InventorySystem.Items.Keycards.KeycardItem; +using Logger = LabApi.Features.Console.Logger; namespace KeycardButModern { @@ -16,6 +20,16 @@ namespace KeycardButModern public override Version Version { get; } = new(1, 0, 0); public override Version RequiredApiVersion { get; } = new (LabApiProperties.CompiledVersion); + public DoorLockConfiguration DoorLockConfiguration; + public static Plugin Singleton; + + public override void LoadConfigs() + { + base.LoadConfigs(); + + DoorLockConfiguration = this.LoadConfig< DoorLockConfiguration > ("door_locks.yml"); + } + private void OnInteractingDoor(PlayerInteractingDoorEventArgs ev) { if (ev.CanOpen) @@ -25,7 +39,6 @@ namespace KeycardButModern if (ev.Door.IsLocked) { - Logger.Debug("Door has active locks"); return; } @@ -40,7 +53,6 @@ namespace KeycardButModern if (!ev.Door.Base.CheckPermissions(keycardItem, out _)) continue; ev.Door.IsOpened = !ev.Door.IsOpened; - Logger.Debug("Door can be opened"); return; } @@ -64,7 +76,6 @@ namespace KeycardButModern if (ev.Generator.IsUnlocked) { - Logger.Debug("Generator can be opened; Unlocked"); return; } @@ -81,7 +92,6 @@ namespace KeycardButModern if (!ev.Generator.Base.CheckPermissions(keycardItem, out _)) continue; ev.Generator.IsOpen = !ev.Generator.IsOpen; ev.Generator.IsUnlocked = true; - Logger.Debug("Generator can be opened"); return; } @@ -115,7 +125,6 @@ namespace KeycardButModern if (!ev.Chamber.Base.CheckPermissions(keycardItem, out _)) continue; ev.Chamber.IsOpen = !ev.Chamber.IsOpen; - Logger.Debug("Locker can be opened"); return; } @@ -139,7 +148,42 @@ namespace KeycardButModern if (!AlphaWarheadActivationPanel.Instance.CheckPermissions(keycardItem, out _)) continue; ev.IsAllowed = true; - Logger.Debug("Nuke can be unlocked"); + return; + } + } + + private static void OnBulletHole(PlayerPlacedBulletHoleEventArgs ev) + { + var direction = (ev.HitPosition - ev.RaycastStart).normalized; + var distance = Vector3.Distance(ev.RaycastStart, ev.HitPosition); + + var hits = Physics.RaycastAll(ev.RaycastStart, direction, distance); + foreach (var hit in hits) + { + ButtonVariant doorButton = hit.collider.GetComponent(); + if (!doorButton) + { + doorButton = hit.collider.GetComponent(); + } + if (!doorButton) + { + doorButton = hit.collider.GetComponent(); + } + if (!doorButton) + { + doorButton = hit.collider.GetComponent(); + } + + if (!doorButton) + { + continue; + } + + var doorVariant = DoorVariant.AllDoors.AsEnumerable()!.First(x => x.Buttons.Any(c=>c.GetInstanceID() == doorButton.GetInstanceID())); + + doorVariant.ServerInteract(ev.Player.ReferenceHub, doorButton.ColliderId); + StartDoorLockCoroutine(doorVariant); + return; } } @@ -147,19 +191,43 @@ namespace KeycardButModern public override void Enable() { Logger.Debug("starting..."); + Singleton = this; + PlayerEvents.InteractingDoor += OnInteractingDoor; PlayerEvents.InteractingGenerator += OnInteractingGenerator; PlayerEvents.InteractingLocker += OnInteractingLocker; PlayerEvents.UnlockingWarheadButton += OnUnlockingWarhead; + + PlayerEvents.PlacedBulletHole += OnBulletHole; + } + private static void StartDoorLockCoroutine(DoorVariant door) + { + door.StartCoroutine(LockDoorCoroutine(door)); + } + + private static IEnumerator LockDoorCoroutine(DoorVariant door) + { + var doorType = DoorLockConfiguration.GetDoorType(door); + var lockDuration = Singleton.DoorLockConfiguration.LockDurations[doorType]; + + door.ServerChangeLock(DoorLockReason.SpecialDoorFeature, true); + yield return new WaitForSeconds(lockDuration); + door.ServerChangeLock(DoorLockReason.SpecialDoorFeature, false); + } + public override void Disable() { PlayerEvents.InteractingDoor -= OnInteractingDoor; PlayerEvents.InteractingGenerator -= OnInteractingGenerator; PlayerEvents.InteractingLocker -= OnInteractingLocker; PlayerEvents.UnlockingWarheadButton -= OnUnlockingWarhead; + + PlayerEvents.PlacedBulletHole -= OnBulletHole; Logger.Debug("unloading..."); + + Singleton = null; } } } \ No newline at end of file diff --git a/KeycardButModern/KeycardButModern.csproj b/KeycardButModern/KeycardButModern.csproj index 41fbf5a..8ce252b 100644 --- a/KeycardButModern/KeycardButModern.csproj +++ b/KeycardButModern/KeycardButModern.csproj @@ -29,6 +29,9 @@ ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.CoreModule.dll + + ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.PhysicsModule.dll + diff --git a/ModTools/ModTools.csproj b/ModTools/ModTools.csproj new file mode 100644 index 0000000..99c017b --- /dev/null +++ b/ModTools/ModTools.csproj @@ -0,0 +1,41 @@ + + + + net48 + enable + disable + latest + ReportNotifier + + + + true + true + full + + + + true + false + none + + + + + ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Assembly-CSharp.dll + + + ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\CommandSystem.Core.dll + + + ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Mirror.dll + + + ..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.CoreModule.dll + + + + + + + diff --git a/ModTools/ReportNotifier.cs b/ModTools/ReportNotifier.cs new file mode 100644 index 0000000..b62221b --- /dev/null +++ b/ModTools/ReportNotifier.cs @@ -0,0 +1,70 @@ +using LabApi.Events.Arguments.PlayerEvents; +using LabApi.Events.Handlers; +using LabApi.Features; +using LabApi.Features.Console; +using LabApi.Features.Permissions; +using LabApi.Features.Wrappers; + +namespace ReportNotifier; + +public class Plugin: LabApi.Loader.Features.Plugins.Plugin +{ + public override string Name => "ModTools"; + public override string Author => "Code002Lover"; + public override Version Version { get; } = new(1, 0, 0); + public override string Description => "Various tools for moderation, including report notification and extra logs."; + public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion); + + public string LogFile { get; set; } = "ModTools.log"; + + private static FileStream _logFileHandler; + + public override void Enable() + { + PlayerEvents.ReportedPlayer += OnReport; + PlayerEvents.Banned += OnBan; + PlayerEvents.Kicked += OnKick; + + _logFileHandler = File.Open(LogFile, FileMode.Append); + } + + public override void Disable() + { + PlayerEvents.ReportedPlayer -= OnReport; + PlayerEvents.Banned -= OnBan; + PlayerEvents.Kicked -= OnKick; + + _logFileHandler = null; + } + + private static void OnReport(PlayerReportedPlayerEventArgs ev) + { + Log($"Received Report from {ev.Player.Nickname} for {ev.Target.Nickname} with the reason: {ev.Reason}"); + foreach (var player in Player.List) + { + Logger.Debug($"Player {player.Nickname} has permissions: {player.GetPermissions()}"); + if (player.HasPermissions("AdminChat")) + { + player.SendBroadcast($"{ev.Player.Nickname} reported {ev.Target.Nickname} for {ev.Reason}", 3, Broadcast.BroadcastFlags.AdminChat, true); + } + } + } + + private static void Log(string message) + { + Logger.Debug(message); + var now = DateTime.Now; + var bytes = System.Text.Encoding.UTF8.GetBytes($"[{now:dd.MM.yyyy : HH:mm:ss}] - {message}"); + _logFileHandler.Write(bytes, 0, bytes.Length); + } + + private static void OnBan(PlayerBannedEventArgs ev) + { + Log($"Player {ev.Player?.Nickname} ({ev.PlayerId}) got banned by {ev.Issuer.Nickname} ({ev.Issuer.PlayerId}) with reason: {ev.Reason}"); + } + + private static void OnKick(PlayerKickedEventArgs ev) + { + Log($"Player {ev.Player.Nickname} ({ev.Player.PlayerId}) got kicked by {ev.Issuer.Nickname} ({ev.Issuer.PlayerId}) with reason: {ev.Reason}"); + } +} \ No newline at end of file diff --git a/RangeBan.Tests/UnitTest1.cs b/RangeBan.Tests/UnitTest1.cs index aa6c860..4cd1b28 100644 --- a/RangeBan.Tests/UnitTest1.cs +++ b/RangeBan.Tests/UnitTest1.cs @@ -27,6 +27,7 @@ public class IpRangeTests [TestCase("192.168.1.0/24", "10.0.0.1", false)] [TestCase("176.2.0.0/16", "176.2.73.23", true)] [TestCase("176.2.0.0/16", "176.2.70.50", true)] + [TestCase("176.2.0.0/16", "176.2.72.1", true)] public void IsInRange_WithCidrNotation_ReturnsExpectedResult(string range, string ip, bool expected) { Assert.That(RangeBan.IsInRange(range, ip), Is.EqualTo(expected)); diff --git a/SecretPluginLaboratories.sln b/SecretPluginLaboratories.sln index 5964e99..c2c46d7 100644 --- a/SecretPluginLaboratories.sln +++ b/SecretPluginLaboratories.sln @@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RangeBan.Tests", "RangeBan. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CuffedFrenemies", "CuffedFrenemies\CuffedFrenemies.csproj", "{C3FEEC52-B7C0-4DB6-A0CA-54BE175072D8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModTools", "ModTools\ModTools.csproj", "{F0AE1ABF-4FAF-4D20-AD71-C98804442D71}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -60,5 +62,9 @@ Global {C3FEEC52-B7C0-4DB6-A0CA-54BE175072D8}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3FEEC52-B7C0-4DB6-A0CA-54BE175072D8}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3FEEC52-B7C0-4DB6-A0CA-54BE175072D8}.Release|Any CPU.Build.0 = Release|Any CPU + {F0AE1ABF-4FAF-4D20-AD71-C98804442D71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0AE1ABF-4FAF-4D20-AD71-C98804442D71}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0AE1ABF-4FAF-4D20-AD71-C98804442D71}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0AE1ABF-4FAF-4D20-AD71-C98804442D71}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/VisibleSpectators/VisibleSpectators.cs b/VisibleSpectators/VisibleSpectators.cs index abe100c..421d4da 100644 --- a/VisibleSpectators/VisibleSpectators.cs +++ b/VisibleSpectators/VisibleSpectators.cs @@ -1,4 +1,5 @@ using HintServiceMeow.Core.Enum; +using HintServiceMeow.Core.Models.HintContent; using HintServiceMeow.Core.Models.Hints; using HintServiceMeow.Core.Utilities; using LabApi.Events.Arguments.PlayerEvents; @@ -8,6 +9,7 @@ using LabApi.Features.Console; using LabApi.Features.Wrappers; using LabApi.Loader.Features.Plugins; using PlayerRoles; +using PlayerRoles.Spectating; using Timer = System.Timers.Timer; namespace VisibleSpectators @@ -20,6 +22,7 @@ namespace VisibleSpectators public override string Description => "See your spectators"; public override Version RequiredApiVersion { get; } = new (LabApiProperties.CompiledVersion); + public int YCoordinate { get; set; } = 100; private static Plugin _singleton; private Timer _timer; @@ -60,12 +63,111 @@ namespace VisibleSpectators } } + private void AddPlayerHint(Player player) + { + if (player == null) return; + + var hint = new Hint + { + Text = $"{Config!.HeaderMessage}\n{Config!.NoSpectatorsMessage}", + Alignment = HintAlignment.Right, + YCoordinate = YCoordinate, + Hide = true + }; + + var playerDisplay = PlayerDisplay.Get(player); + playerDisplay.AddHint(hint); + + _spectatorHints[player] = hint; + } + + private static readonly Dictionary GetColorMap = new() + { + { "DEFAULT", "FFFFFF" }, + { "PUMPKIN", "EE7600" }, + { "ARMY_GREEN", "4B5320" }, + { "MINT", "98FB98" }, + { "NICKEL", "727472" }, + { "CARMINE", "960018" }, + { "EMERALD", "50C878" }, + { "GREEN", "228B22" }, + { "LIME", "BFFF00" }, + { "POLICE_BLUE", "002DB3" }, + { "ORANGE", "FF9966" }, + { "SILVER_BLUE", "666699" }, + { "BLUE_GREEN", "4DFFB8" }, + { "MAGENTA", "FF0090" }, + { "YELLOW", "FAFF86" }, + { "TOMATO", "FF6448" }, + { "DEEP_PINK", "FF1493" }, + { "AQUA", "00FFFF" }, + { "CYAN", "00B7EB" }, + { "CRIMSON", "DC143C" }, + { "LIGHT_GREEN", "32CD32" }, + { "SILVER", "A0A0A0" }, + { "BROWN", "944710" }, + { "RED", "C50000" }, + { "PINK", "FF96DE" }, + { "LIGHT_RED", "FD8272" }, + { "PURPLE", "8137CE" }, + { "BLUE", "005EBC" }, + { "TEAL", "008080" }, + { "GOLD", "EFC01A" } + }; + + private static string PlayerToDisplay(Player player) + { + if (player == null) return ""; + + // Default color if GroupColor is null or not found in the map + const string defaultColor = "FFFFFF"; + + try + { + var groupColor = player.GroupColor; + if (string.IsNullOrEmpty(groupColor)) + return $"{player.DisplayName}"; + + return GetColorMap.TryGetValue(groupColor.ToUpper(), out var color) ? $"{player.DisplayName}" : $"{player.DisplayName}"; + } + catch + { + return $"{player.DisplayName}"; + } + } + + private static bool IsNotOverwatch(Player player) + { + return player != null && player.Role != RoleTypeId.Overwatch; + } + private void UpdateSpectators(Player player) { - var spectators = string.Join("\n",player.CurrentSpectators.Select(x => x.DisplayName)); - if (player.Role == RoleTypeId.Spectator) + if (player == null) { - spectators = string.Join("\n",player.CurrentlySpectating?.CurrentSpectators.Select(x => x.DisplayName) ?? Array.Empty()); + return; + } + + // Safety check - if player doesn't have a hint, create one + if (!_spectatorHints.ContainsKey(player)) + { + AddPlayerHint(player); + } + + var spectators = Config!.NoSpectatorsMessage; + + try + { + spectators = string.Join("\n",player.CurrentSpectators.Where(IsNotOverwatch).Select(PlayerToDisplay)); + if (player.Role == RoleTypeId.Spectator) + spectators = player.CurrentlySpectating == null + ? Config!.NoSpectatorsMessage + : string.Join("\n", + player.CurrentlySpectating?.CurrentSpectators.Where(IsNotOverwatch) + .Select(PlayerToDisplay) ?? Array.Empty()); + } catch (Exception e) + { + Logger.Error(e); } if (spectators.Length < 2) @@ -74,9 +176,11 @@ namespace VisibleSpectators } - _spectatorHints[player].Text = $"{Config!.HeaderMessage}\n{spectators}\n{DateTime.UtcNow:HH:mm:ss}"; + _spectatorHints[player].Text = $"{Config!.HeaderMessage}\n{spectators}"; - _spectatorHints[player].Hide = player.Role is RoleTypeId.Overwatch or RoleTypeId.Destroyed or RoleTypeId.None; + _spectatorHints[player].Hide = player.Role is RoleTypeId.Destroyed or RoleTypeId.None; + + _spectatorHints[player].YCoordinate = YCoordinate + player.CurrentSpectators.Count * 10; } private static Player[] GetPlayers() @@ -88,22 +192,12 @@ namespace VisibleSpectators { _singleton.UpdateSpectators(ev.OldTarget); _singleton.UpdateSpectators(ev.NewTarget); + _singleton.UpdateSpectators(ev.Player); } private void OnJoin(PlayerJoinedEventArgs ev) { - var hint = new Hint - { - Text = $"{Config!.HeaderMessage}\n{Config!.NoSpectatorsMessage}", - Alignment = HintAlignment.Right, - YCoordinate = 100, - Hide = true - }; - - var playerDisplay = PlayerDisplay.Get(ev.Player); - playerDisplay.AddHint(hint); - - _spectatorHints[ev.Player] = hint; + AddPlayerHint(ev.Player); } }