├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── CedMod-SampleEvent-NWApi ├── App.config ├── CedMod-SampleEvent-NWApi.csproj ├── Config.cs ├── EventHandler.cs ├── Properties │ └── AssemblyInfo.cs ├── SampleEvent.cs └── packages.config ├── CedMod.sln ├── CedMod ├── API.cs ├── Addons │ ├── AdminSitSystem │ │ ├── AdminSit.cs │ │ ├── AdminSitHandler.cs │ │ ├── AdminSitLocation.cs │ │ └── Commands │ │ │ ├── Jail │ │ │ ├── Add.cs │ │ │ ├── Create.cs │ │ │ ├── Delete.cs │ │ │ ├── Join.cs │ │ │ └── Remove.cs │ │ │ └── JailCommand.cs │ ├── Audio │ │ ├── AudioCommand.cs │ │ ├── CustomAudioPlayer.cs │ │ └── FakeConnection.cs │ ├── Events │ │ ├── Commands │ │ │ ├── BumpEvent.cs │ │ │ ├── DisableEvent.cs │ │ │ ├── EnableEvent.cs │ │ │ ├── Events.cs │ │ │ ├── ListEvents.cs │ │ │ ├── PopuplateCommand.cs │ │ │ └── Queue.cs │ │ ├── Config.cs │ │ ├── EventManager.cs │ │ ├── EventManagerPlayerEvents.cs │ │ ├── EventManagerServerEvents.cs │ │ ├── HintManager.cs │ │ ├── IEventConfig.cs │ │ ├── Interfaces │ │ │ ├── IBulletHoleBehaviour.cs │ │ │ ├── IEndConditionBehaviour.cs │ │ │ ├── IEvent.cs │ │ │ ├── IFriendlyFireAutoBanBehaviour.cs │ │ │ └── IMapgenBehaviour.cs │ │ ├── Patches │ │ │ ├── BulletHolePatch.cs │ │ │ └── SeedGenerationPatch.cs │ │ └── ScriptedEventIntergration.cs │ ├── QuerySystem │ │ ├── Commands │ │ │ ├── CmSyncCommand.cs │ │ │ ├── ImportRaCommand.cs │ │ │ ├── NearbyBulletHoles.cs │ │ │ ├── RestartQuery.cs │ │ │ └── ToggleExpTracking.cs │ │ ├── Config.cs │ │ ├── Extensions.cs │ │ ├── LevelerStore.cs │ │ ├── Patches │ │ │ ├── BulletHolePatch.cs │ │ │ ├── CommandProcessorPatch.cs │ │ │ ├── ExiledPermissionsPatch.cs │ │ │ ├── ExiledPermissionsPatchPlayer.cs │ │ │ ├── PreAuthModel.cs │ │ │ ├── RefreshExiledPermissions.cs │ │ │ ├── RefreshPermissionsHandlerPatch.cs │ │ │ ├── ReservedSlotsPatch.cs │ │ │ └── ShootingPatch.cs │ │ ├── PlayerList.cs │ │ ├── QueryMapEvents.cs │ │ ├── QueryPlayerEvents.cs │ │ ├── QueryServerEvents.cs │ │ ├── QuerySystem.cs │ │ ├── ServerPreferences.cs │ │ ├── ThreadDispatcher.cs │ │ ├── Verification.cs │ │ └── WS │ │ │ ├── PermissionProvider.cs │ │ │ └── WebSocketSystem.cs │ ├── Sentinal │ │ ├── Patches │ │ │ ├── FpcServerPositionDistributorPatch.cs │ │ │ ├── FpcSyncDataPatch.cs │ │ │ ├── ItemPickupHandler.cs │ │ │ ├── PlayerRoleManagerPatch.cs │ │ │ ├── Scp939LungePatch.cs │ │ │ ├── TeslaGateHandler.cs │ │ │ ├── Utilities │ │ │ │ └── RoomCache.cs │ │ │ └── VoicePacketPacket.cs │ │ └── SentinalBehaviour.cs │ └── StaffInfo │ │ ├── MirrorExtensions.cs │ │ └── StaffInfoHandler.cs ├── ApiModals │ ├── AudioHeartBeat.cs │ ├── AutoSlPermsSlRequest.cs │ ├── CedModVersion.cs │ ├── EventModal.cs │ ├── ExiledVersion.cs │ ├── HeartbeatRequest.cs │ ├── HelloMessage.cs │ ├── IngameUserPreferences.cs │ ├── PlayerObject.cs │ ├── SCPSLVersion.cs │ └── ServerPreferenceModel.cs ├── App.config ├── BanSystem.cs ├── CacheHandler.cs ├── CedMod-Main.csproj ├── CedModConfig.cs ├── CedModPlayer.cs ├── Commands │ ├── CedModSetupCommand.cs │ ├── CheckForUpdatesCommand.cs │ ├── Dialog │ │ ├── all.cs │ │ └── userid.cs │ ├── DialogBox.cs │ ├── FFADisable.cs │ ├── InstallUpdateCommand.cs │ ├── LightColor.cs │ ├── RainbowLights.cs │ ├── Redirect.cs │ └── WarnCommand.cs ├── Components │ ├── AutoUpdater.cs │ └── RemoteAdminModificationHandler.cs ├── Config.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── FriendlyFireAutoban.cs ├── Handlers │ ├── Player.cs │ └── Server.cs ├── Patches │ ├── BanCommandPatch.cs │ ├── BanPatch.cs │ ├── ExternalLookupPatch.cs │ ├── IntercomMuteCommandPatch.cs │ ├── IntercomUnMuteCommandPatch.cs │ ├── IssueBanPatch.cs │ ├── MirrorPatch.cs │ ├── MuteCommandPatch.cs │ ├── NpcInstanceModePatch.cs │ ├── OBanCommandPatch.cs │ ├── RAProcessPlayerPatch.cs │ ├── RaPlayerAuthPatch.cs │ ├── RaPlayerListPatch.cs │ ├── RaPlayerPatch.cs │ ├── ReloadServerNamePatch.cs │ └── UnMuteCommandPatch.cs ├── Plugin.cs ├── Properties │ └── AssemblyInfo.cs ├── README.md ├── RainbowLight.cs ├── VerificationChallenge.cs ├── packages.config ├── version.txt └── versionIdentifier.txt ├── README.md └── SECURITY.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | V: 3.4.25 3 | - Introduced CMAC officially. 4 | - Prevents Harmless Tesla cheats (negates tesla damage)1* 5 | - Prevents pickup through walls cheats1* 6 | - Prevents Movement Unlock cheats (allows movement where the game would normally lock your movement)1* 7 | - Introduced a system to prevent wallhacks.2* 8 | - Improved communication to Sentinal3* 9 | - Fixed OnPlayerDying log on the panel when there was no killer. 10 | - Fixed the jail command spawning you up in the air if unjailed after warhead detonation. 11 | 12 | 1* Detection results will be shared with the CedMod gateway to create a cheat profile on the user, which will be used to determine if the user is cheating based on the currently implemented detections 13 | If enough detections are triggered the user will be banned based on their account standing (lower/newer standing means faster action)
14 | These features have been tested and adapted for users with higher than usual or unstable connections as best as possible 15 | We continue to monitor results detection logs and making changes where necessary. 16 | Please note that effectiveness is dependent on how many cheaters use the detected features until we add detections for more features with 3*
17 | 18 | 2* This system will hide players from others when they cannot actually see them with a series of checks to make it effective yet unnoticeable for normal players
Please note that this currently does not apply to SCP's
Please also note that actions that make sound can also reveal players to others despite not having a LineOfSight
19 | 20 | 3* Sentinal is the WIP completely CedMod-server-side simulation system which is capable of reconstructing the entire round out side of SL.
21 | In the future it will be used to detect more sophisticated cheat features, eg aimbot, pSilent, etc. while completely hiding the detection code. -------------------------------------------------------------------------------- /CedMod-SampleEvent-NWApi/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CedMod-SampleEvent-NWApi/Config.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using CedMod.Addons.Events; 3 | 4 | namespace CedMod.SampleEvent 5 | { 6 | public sealed class Config: IEventConfig 7 | { 8 | [Description("Indicates whether the event is enabled or not")] 9 | public bool IsEnabled { get; set; } = true; 10 | } 11 | } -------------------------------------------------------------------------------- /CedMod-SampleEvent-NWApi/EventHandler.cs: -------------------------------------------------------------------------------- 1 | using PlayerStatsSystem; 2 | using PluginAPI.Core.Attributes; 3 | using PluginAPI.Enums; 4 | using PluginAPI.Events; 5 | 6 | namespace CedMod.SampleEvent 7 | { 8 | public class EventHandler 9 | { 10 | 11 | [PluginEvent(ServerEventType.PlayerDeath)] 12 | public void OnPlayerDeath(PlayerDeathEvent ev) 13 | { 14 | ev.Player.SendBroadcast("You died!", 1, Broadcast.BroadcastFlags.Normal); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /CedMod-SampleEvent-NWApi/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("CedMod_SampleEvent")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("CedMod_SampleEvent")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("2F1B2CB5-0B6B-44DB-9FA4-CB357420C36D")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /CedMod-SampleEvent-NWApi/SampleEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CedMod.Addons.Events; 3 | using CedMod.Addons.Events.Interfaces; 4 | using HarmonyLib; 5 | using LabApi.Features.Console; 6 | using LabApi.Loader.Features.Plugins; 7 | using PluginAPI.Core; 8 | using PluginAPI.Core.Attributes; 9 | using UnityEngine.XR; 10 | using EventManager = PluginAPI.Events.EventManager; 11 | 12 | namespace CedMod.SampleEvent 13 | { 14 | public class SampleEvent : Plugin, IEvent 15 | { 16 | public static bool IsRunning = false; 17 | 18 | [PluginUnload] 19 | public void OnDisabled() 20 | { 21 | StopEvent(); 22 | } 23 | 24 | public string EventName { get; } = "Example Event"; 25 | public string EvenAuthor { get; } = "ced777ric"; 26 | public string EventDescription { get; set; } = "A testing event, you can use this to make your own events"; 27 | public string EventPrefix { get; } = "Sample"; 28 | 29 | public IEventConfig EventConfig => Config; 30 | 31 | public void PrepareEvent() 32 | { 33 | Logger.Info("SampleEvent is preparing"); 34 | IsRunning = true; 35 | Logger.Info("SampleEvent is prepared"); 36 | EventManager.RegisterEvents(this); 37 | } 38 | 39 | public void StopEvent() 40 | { 41 | IsRunning = false; 42 | EventManager.UnregisterEvents(this); 43 | } 44 | 45 | public override void Enable() 46 | { 47 | throw new NotImplementedException(); 48 | } 49 | 50 | public override void Disable() 51 | { 52 | throw new NotImplementedException(); 53 | } 54 | 55 | public override string Name { get; } 56 | public override string Description { get; } 57 | public override string Author { get; } 58 | public override Version Version { get; } 59 | public override Version RequiredApiVersion { get; } 60 | } 61 | } -------------------------------------------------------------------------------- /CedMod-SampleEvent-NWApi/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /CedMod.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.28307.645 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CedMod-Main", "CedMod\CedMod-Main.csproj", "{B404BA59-5C33-41DC-8FEE-0F10F087089D}" 6 | EndProject 7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CedMod-SampleEvent-NWApi", "CedMod-SampleEvent-NWApi\CedMod-SampleEvent-NWApi.csproj", "{2F1B2CB5-0B6B-44DB-9FA4-CB357420C36D}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Release|Any CPU = Release|Any CPU 13 | Debug EXILED|Any CPU = Debug EXILED|Any CPU 14 | Release EXILED|Any CPU = Release EXILED|Any CPU 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Debug EXILED|Any CPU.ActiveCfg = Debug EXILED|Any CPU 22 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Debug EXILED|Any CPU.Build.0 = Debug EXILED|Any CPU 23 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Release EXILED|Any CPU.ActiveCfg = Release EXILED|Any CPU 24 | {B404BA59-5C33-41DC-8FEE-0F10F087089D}.Release EXILED|Any CPU.Build.0 = Release EXILED|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | GlobalSection(ExtensibilityGlobals) = postSolution 30 | SolutionGuid = {804FCAB2-81D5-4ABD-BD5A-384E4807240F} 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /CedMod/Addons/AdminSitSystem/AdminSit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using AdminToys; 4 | using InventorySystem.Items; 5 | using LabApi.Features.Wrappers; 6 | using PlayerRoles; 7 | using UnityEngine; 8 | 9 | namespace CedMod.Addons.AdminSitSystem 10 | { 11 | public class AdminSit 12 | { 13 | public string Id { get; set; } = Guid.NewGuid().ToString(); 14 | public AdminSitLocation Location { get; set; } 15 | public AdminSitType Type { get; set; } 16 | public string InitialReason { get; set; } 17 | public long InitialDuration { get; set; } 18 | public int AssociatedReportId { get; set; } 19 | public List Players { get; set; } 20 | public List SpawnedObjects { get; set; } 21 | } 22 | 23 | public class AdminSitPlayer 24 | { 25 | public string UserId { get; set; } 26 | public Player Player { get; set; } 27 | public AdminSitPlayerType PlayerType { get; set; } 28 | public Dictionary Items { get; set; } 29 | public RoleTypeId Role { get; set; } 30 | public Vector3 Position { get; set; } 31 | public float Health { get; set; } 32 | public Dictionary Ammo { get; set; } 33 | public Dictionary> Effects = new Dictionary>(); 34 | } 35 | 36 | public enum AdminSitPlayerType 37 | { 38 | Staff, 39 | Handler, 40 | Offender, 41 | Victim, 42 | User 43 | } 44 | 45 | public enum AdminSitType 46 | { 47 | Generic, 48 | Jail, 49 | BanOffenderOnLeave, 50 | } 51 | } -------------------------------------------------------------------------------- /CedMod/Addons/AdminSitSystem/AdminSitLocation.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace CedMod.Addons.AdminSitSystem 4 | { 5 | public class AdminSitLocation 6 | { 7 | public Vector3 SpawnPosition { get; set; } 8 | public bool InUse { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /CedMod/Addons/AdminSitSystem/Commands/Jail/Add.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | 6 | namespace CedMod.Addons.AdminSitSystem.Commands.Jail 7 | { 8 | public class Add : ICommand 9 | { 10 | public string Command { get; } = "add"; 11 | 12 | public string[] Aliases { get; } = { 13 | "a" 14 | }; 15 | 16 | public string Description { get; } = "Adds the specified player to your current jail."; 17 | 18 | public bool Execute(ArraySegment arguments, ICommandSender sender, 19 | out string response) 20 | { 21 | if (!sender.HasPermissions("cedmod.jail")) 22 | { 23 | response = "no permission"; 24 | return false; 25 | } 26 | 27 | if (arguments.Count < 1) 28 | { 29 | response = "This command requires a PlayerId to be specified"; 30 | return false; 31 | } 32 | 33 | var invoker = CedModPlayer.Get((sender as CommandSender).SenderId); 34 | if (!AdminSitHandler.Singleton.Sits.Any(s => s.Players.Any(s => s.UserId == invoker.UserId))) 35 | { 36 | response = "You are currently not part of any jail."; 37 | return false; 38 | } 39 | 40 | if (invoker == null) 41 | { 42 | response = $"Invoker could not be found."; 43 | return false; 44 | } 45 | 46 | var sit = AdminSitHandler.Singleton.Sits.FirstOrDefault(s => s.Players.Any(s => s.UserId == invoker.UserId)); 47 | 48 | var plr = CedModPlayer.Get(arguments.At(0)); 49 | if (plr is null) 50 | { 51 | response = $"Player '{arguments.At(0)}' could not be found"; 52 | return false; 53 | } 54 | if (AdminSitHandler.Singleton.Sits.Any(s => s.Players.Any(s => s.UserId == plr.UserId))) 55 | { 56 | response = "The specified player is already part of a jail."; 57 | return false; 58 | } 59 | 60 | JailParentCommand.AddPlr(plr, sit); 61 | 62 | response = "Player Added, use jail remove {playerId} to remove the player."; 63 | return false; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /CedMod/Addons/AdminSitSystem/Commands/Jail/Create.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using AdminToys; 5 | using CommandSystem; 6 | using LabApi.Features.Permissions; 7 | using LabApi.Features.Wrappers; 8 | using Mirror; 9 | using UnityEngine; 10 | 11 | namespace CedMod.Addons.AdminSitSystem.Commands.Jail 12 | { 13 | public class Create : ICommand 14 | { 15 | public string Command { get; } = "create"; 16 | 17 | public string[] Aliases { get; } = { 18 | "cr", 19 | "c" 20 | }; 21 | 22 | public string Description { get; } = "Assigns an available jail location to your player."; 23 | 24 | public bool Execute(ArraySegment arguments, ICommandSender sender, 25 | out string response) 26 | { 27 | if (!sender.HasPermissions("cedmod.jail")) 28 | { 29 | response = "no permission"; 30 | return false; 31 | } 32 | 33 | if (!AdminSitHandler.Singleton.AdminSitLocations.Any(s => !s.InUse)) 34 | { 35 | response = "There are no locations available."; 36 | return false; 37 | } 38 | 39 | var loc = AdminSitHandler.Singleton.AdminSitLocations.FirstOrDefault(s => !s.InUse); 40 | var plr = CedModPlayer.Get((sender as CommandSender).SenderId); 41 | if (plr == null) 42 | { 43 | response = $"Invoker could not be found."; 44 | return false; 45 | } 46 | 47 | if (AdminSitHandler.Singleton.Sits.Any(s => s.Players.Any(s => s.UserId == plr.UserId))) 48 | { 49 | response = "You are already part of a jail."; 50 | return false; 51 | } 52 | 53 | AdminToyBase adminToyBase = null; 54 | foreach (GameObject gameObject in NetworkClient.prefabs.Values) 55 | { 56 | if (gameObject == null) 57 | continue; 58 | AdminToyBase component; 59 | if (gameObject.TryGetComponent(out component)) 60 | { 61 | if (string.Equals("LightSource", component.CommandName, StringComparison.InvariantCultureIgnoreCase)) 62 | { 63 | adminToyBase = UnityEngine.Object.Instantiate(component); 64 | adminToyBase.transform.position = loc.SpawnPosition; 65 | NetworkServer.Spawn(adminToyBase.gameObject); 66 | } 67 | } 68 | } 69 | 70 | var sit = new AdminSit() 71 | { 72 | AssociatedReportId = 0, 73 | InitialDuration = 0, 74 | InitialReason = "", 75 | Location = loc, 76 | SpawnedObjects = new List() 77 | { 78 | adminToyBase, 79 | }, 80 | Players = new List() 81 | }; 82 | 83 | AdminSitHandler.Singleton.Sits.Add(sit); 84 | 85 | loc.InUse = true; 86 | 87 | JailParentCommand.AddPlr(plr, sit); 88 | 89 | response = ""; 90 | foreach (var plr1 in arguments) 91 | { 92 | Player cmPlr = CedModPlayer.Get(plr1); 93 | if (cmPlr == null) 94 | { 95 | response += $"{plr1} Could not be found!\n"; 96 | } 97 | 98 | JailParentCommand.AddPlr(cmPlr, sit); 99 | } 100 | 101 | response += "Jail assigned. Use jail add {playerId} to add someone and jail remove {playerId}"; 102 | return false; 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /CedMod/Addons/AdminSitSystem/Commands/Jail/Delete.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | using MEC; 6 | 7 | namespace CedMod.Addons.AdminSitSystem.Commands.Jail 8 | { 9 | public class Delete : ICommand 10 | { 11 | public string Command { get; } = "delete"; 12 | 13 | public string[] Aliases { get; } = { 14 | "d" 15 | }; 16 | 17 | public string Description { get; } = "Removes all players currently in a jail and deletes the jail."; 18 | 19 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 20 | { 21 | if (!sender.HasPermissions("cedmod.jail")) 22 | { 23 | response = "no permission"; 24 | return false; 25 | } 26 | 27 | var invoker = CedModPlayer.Get((sender as CommandSender).SenderId); 28 | if (!AdminSitHandler.Singleton.Sits.Any(s => s.Players.Any(s => s.UserId == invoker.UserId))) 29 | { 30 | response = "You are currently not part of any jail."; 31 | return false; 32 | } 33 | 34 | if (invoker == null) 35 | { 36 | response = $"Invoker could not be found."; 37 | return false; 38 | } 39 | 40 | var sit = AdminSitHandler.Singleton.Sits.FirstOrDefault(s => s.Players.Any(s => s.UserId == invoker.UserId)); 41 | 42 | foreach (var plr in sit.Players) 43 | { 44 | var cmPlr = CedModPlayer.Get(plr.UserId); 45 | if (cmPlr == null) 46 | continue; 47 | 48 | JailParentCommand.RemovePlr(cmPlr, plr, sit); 49 | } 50 | 51 | Timing.CallDelayed(0.5f, () => 52 | { 53 | JailParentCommand.RemoveJail(sit); 54 | }); 55 | 56 | response = "Jail Removed"; 57 | return false; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /CedMod/Addons/AdminSitSystem/Commands/Jail/Join.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | 6 | namespace CedMod.Addons.AdminSitSystem.Commands.Jail 7 | { 8 | public class Join : ICommand 9 | { 10 | public string Command { get; } = "join"; 11 | 12 | public string[] Aliases { get; } = { 13 | "j" 14 | }; 15 | 16 | public string Description { get; } = "Adds yourself to the jail of the specified player"; 17 | 18 | public bool Execute(ArraySegment arguments, ICommandSender sender, 19 | out string response) 20 | { 21 | if (!sender.HasPermissions("cedmod.jail")) 22 | { 23 | response = "no permission"; 24 | return false; 25 | } 26 | 27 | if (arguments.Count < 1) 28 | { 29 | response = "This command requires a PlayerId to be specified"; 30 | return false; 31 | } 32 | 33 | var invoker = CedModPlayer.Get((sender as CommandSender).SenderId); 34 | var plr = CedModPlayer.Get(arguments.At(0)); 35 | if (plr == null) 36 | { 37 | response = $"Player '{arguments.At(0)}' could not be found."; 38 | return false; 39 | } 40 | 41 | if (invoker == null) 42 | { 43 | response = $"Invoker could not be found."; 44 | return false; 45 | } 46 | 47 | if (!AdminSitHandler.Singleton.Sits.Any(s => s.Players.Any(s => s.UserId == plr.UserId))) 48 | { 49 | response = "The specified player is not part of any jail."; 50 | return false; 51 | } 52 | 53 | var sit = AdminSitHandler.Singleton.Sits.FirstOrDefault(s => s.Players.Any(s => s.UserId == plr.UserId)); 54 | 55 | JailParentCommand.AddPlr(invoker, sit); 56 | 57 | response = "Added, use jail remove {playerId} to remove yourself"; 58 | return false; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /CedMod/Addons/AdminSitSystem/Commands/Jail/Remove.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | using MEC; 6 | 7 | namespace CedMod.Addons.AdminSitSystem.Commands.Jail 8 | { 9 | public class Remove : ICommand 10 | { 11 | public string Command { get; } = "remove"; 12 | 13 | public string[] Aliases { get; } = { 14 | "r" 15 | }; 16 | 17 | public string Description { get; } = "Removes the specified player from your current jail."; 18 | 19 | public bool Execute(ArraySegment arguments, ICommandSender sender, 20 | out string response) 21 | { 22 | if (!sender.HasPermissions("cedmod.jail")) 23 | { 24 | response = "no permission"; 25 | return false; 26 | } 27 | 28 | if (arguments.Count < 1) 29 | { 30 | response = "This command requires a PlayerId to be specified"; 31 | return false; 32 | } 33 | 34 | var invoker = CedModPlayer.Get((sender as CommandSender).SenderId); 35 | if (!AdminSitHandler.Singleton.Sits.Any(s => s.Players.Any(s => s.UserId == invoker.UserId))) 36 | { 37 | response = "You are currently not part of any jail."; 38 | return false; 39 | } 40 | 41 | var plr = CedModPlayer.Get(arguments.At(0)); 42 | if (plr == null) 43 | { 44 | response = $"Player '{arguments.At(0)}' could not be found."; 45 | return false; 46 | } 47 | var sit = AdminSitHandler.Singleton.Sits.FirstOrDefault(s => s.Players.Any(s => s.UserId == plr.UserId)); 48 | if (sit == null) 49 | { 50 | response = "This player is not in a jail."; 51 | return false; 52 | } 53 | 54 | var sitPlr = sit.Players.First(s => s.UserId == plr.UserId); 55 | JailParentCommand.RemovePlr(plr, sitPlr, sit); 56 | 57 | Timing.CallDelayed(0.3f, () => 58 | { 59 | if (!sit.Players.Any(s => s.PlayerType == AdminSitPlayerType.Staff || s.PlayerType == AdminSitPlayerType.Handler)) 60 | { 61 | foreach (var sitPlr2 in sit.Players) 62 | { 63 | var plr2 = CedModPlayer.Get(sitPlr2.UserId); 64 | JailParentCommand.RemovePlr(plr2, sitPlr2, sit); 65 | } 66 | 67 | Timing.CallDelayed(0.5f, () => 68 | { 69 | JailParentCommand.RemoveJail(sit); 70 | }); 71 | } 72 | }); 73 | 74 | response = "Player Removed"; 75 | return false; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /CedMod/Addons/Audio/CustomAudioPlayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Text; 8 | using LabApi.Features.Console; 9 | using MEC; 10 | using SCPSLAudioApi.AudioCore; 11 | using VoiceChat; 12 | using Random = UnityEngine.Random; 13 | 14 | namespace CedMod.Addons.Audio 15 | { 16 | using CedMod.Addons.QuerySystem; 17 | 18 | public class CustomAudioPlayer: AudioPlayerBase 19 | { 20 | public static CustomAudioPlayer Get(ReferenceHub hub) 21 | { 22 | if (AudioPlayers.TryGetValue(hub, out AudioPlayerBase player)) 23 | { 24 | if (player is CustomAudioPlayer cplayer1) 25 | return cplayer1; 26 | } 27 | 28 | var cplayer = hub.gameObject.AddComponent(); 29 | cplayer.Owner = hub; 30 | cplayer.BroadcastChannel = VoiceChatChannel.Proximity; 31 | 32 | AudioPlayers.Add(hub, cplayer); 33 | return cplayer; 34 | } 35 | 36 | public override IEnumerator Playback(int index) 37 | { 38 | if (Shuffle) 39 | AudioToPlay = AudioToPlay.OrderBy(i => Random.value).ToList(); 40 | CurrentPlay = AudioToPlay[index]; 41 | AudioToPlay.RemoveAt(index); 42 | if (Loop) 43 | { 44 | AudioToPlay.Add(CurrentPlay); 45 | } 46 | 47 | Logger.Info($"Loading Audio"); 48 | byte[] respString; 49 | HttpStatusCode code = HttpStatusCode.OK; 50 | using (HttpClient client = new HttpClient()) 51 | { 52 | client.DefaultRequestHeaders.Add("X-ServerIp", ServerConsole.Ip); 53 | var t = VerificationChallenge.AwaitVerification(); 54 | yield return Timing.WaitUntilTrue(() => t.IsCompleted); 55 | 56 | var respTask = client.GetAsync($"http{(QuerySystem.UseSSL ? "s" : "")}://" + QuerySystem.CurrentMaster + $"/Api/v3/RetrieveAudio/{QuerySystem.QuerySystemKey}?track={CurrentPlay}"); 57 | yield return Timing.WaitUntilTrue(() => respTask.IsCompleted); 58 | var resp = respTask.Result; 59 | var respStringTask = resp.Content.ReadAsByteArrayAsync(); 60 | yield return Timing.WaitUntilTrue(() => respStringTask.IsCompleted); 61 | respString = respStringTask.Result; 62 | code = resp.StatusCode; 63 | } 64 | 65 | int cnt; 66 | if (code != HttpStatusCode.OK) 67 | { 68 | Logger.Error($"Failed to retrieve audio {code} {Encoding.UTF8.GetString(respString)}"); 69 | if (Continue && AudioToPlay.Count >= 1) 70 | { 71 | yield return Timing.WaitForSeconds(1); 72 | Timing.RunCoroutine(Playback(0)); 73 | } 74 | yield break; 75 | } 76 | 77 | try 78 | { 79 | CurrentPlayStream = new MemoryStream(respString); 80 | CurrentPlayStream.Seek(0, SeekOrigin.Begin); 81 | } 82 | catch (Exception e) 83 | { 84 | Logger.Error($"{e} {code} {Encoding.UTF8.GetString(respString)}"); 85 | } 86 | 87 | VorbisReader = new NVorbis.VorbisReader(CurrentPlayStream); 88 | Logger.Info($"Playing with samplerate of {VorbisReader.SampleRate}"); 89 | samplesPerSecond = VoiceChatSettings.SampleRate * VoiceChatSettings.Channels; 90 | //_samplesPerSecond = VorbisReader.Channels * VorbisReader.SampleRate / 5; 91 | SendBuffer = new float[samplesPerSecond / 5 + HeadSamples]; 92 | ReadBuffer = new float[samplesPerSecond / 5 + HeadSamples]; 93 | 94 | while ((cnt = VorbisReader.ReadSamples(ReadBuffer, 0, ReadBuffer.Length)) > 0) 95 | { 96 | if (stopTrack) 97 | { 98 | VorbisReader.SeekTo(VorbisReader.TotalSamples - 1); 99 | stopTrack = false; 100 | } 101 | while (!ShouldPlay) 102 | { 103 | yield return Timing.WaitForOneFrame; 104 | } 105 | while (StreamBuffer.Count >= ReadBuffer.Length) 106 | { 107 | ready = true; 108 | yield return Timing.WaitForOneFrame; 109 | } 110 | for (int i = 0; i < ReadBuffer.Length; i++) 111 | { 112 | StreamBuffer.Enqueue(ReadBuffer[i]); 113 | } 114 | } 115 | Logger.Info($"Track Complete."); 116 | 117 | if (Continue && AudioToPlay.Count >= 1) 118 | { 119 | Timing.RunCoroutine(Playback(0)); 120 | } 121 | yield break; 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /CedMod/Addons/Audio/FakeConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Mirror; 3 | 4 | namespace CedMod.Addons.Audio 5 | { 6 | public class FakeConnection : NetworkConnectionToClient 7 | { 8 | public FakeConnection(int connectionId) : base(connectionId) 9 | { 10 | 11 | } 12 | 13 | public override string address 14 | { 15 | get 16 | { 17 | return "localhost"; 18 | } 19 | } 20 | 21 | public override void Send(ArraySegment segment, int channelId = 0) 22 | { 23 | } 24 | 25 | public override void Disconnect() 26 | { 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Commands/BumpEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CedMod.Addons.Events.Interfaces; 4 | using CedMod.Addons.QuerySystem; 5 | using CommandSystem; 6 | using LabApi.Features.Permissions; 7 | using LabApi.Features.Wrappers; 8 | using MEC; 9 | 10 | namespace CedMod.Addons.Events.Commands 11 | { 12 | public class BumpEvent : ICommand, IUsageProvider 13 | { 14 | public string Command { get; } = "bump"; 15 | 16 | public string[] Aliases { get; } = new string[] 17 | { 18 | }; 19 | 20 | public string Description { get; } = "moves an event to the front of the queue"; 21 | 22 | public string[] Usage { get; } = new string[] 23 | { 24 | "%eventprefix%", 25 | "%force%" 26 | }; 27 | 28 | public bool Execute(ArraySegment arguments, ICommandSender sender, 29 | out string response) 30 | { 31 | if (arguments.Count < 2) 32 | { 33 | response = "To execute this command provide at least 2 arguments!\nUsage: " + this.DisplayCommandUsage(); 34 | return false; 35 | } 36 | IEvent @event = EventManager.AvailableEvents.FirstOrDefault(ev => ev.EventPrefix == arguments.At(0)); 37 | bool force = Convert.ToBoolean(arguments.At(1)); 38 | if (@event == null) 39 | { 40 | response = "Event does not exist"; 41 | return false; 42 | } 43 | 44 | if (sender.IsPanelUser() ? !sender.CheckPermission(PlayerPermissions.FacilityManagement) : !sender.HasPermissions("cedmod.events.bump")) 45 | { 46 | response = "No permission"; 47 | return false; 48 | } 49 | 50 | EventManager.EventQueue.RemoveAll(ev => ev.EventName == @event.EventName); 51 | EventManager.EventQueue.Insert(0, @event); 52 | 53 | if (force) 54 | { 55 | 56 | Broadcast.Singleton.RpcAddElement($"EventManager: {@event.EventName} is being enabled.\nRound will restart in 3 seconds", 5, Broadcast.BroadcastFlags.Normal); 57 | Timing.CallDelayed(3, () => 58 | { 59 | Round.Restart(false, false); 60 | }); 61 | } 62 | else 63 | { 64 | Broadcast.Singleton.RpcAddElement($"EventManager: {@event.EventName} has been moved to queue position {EventManager.EventQueue.IndexOf(@event)}", 10, Broadcast.BroadcastFlags.Normal); 65 | } 66 | ThreadDispatcher.SendHeartbeatMessage(true); 67 | response = "Success"; 68 | return true; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Commands/DisableEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CedMod.Addons.QuerySystem; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | using LabApi.Features.Wrappers; 6 | using MEC; 7 | 8 | namespace CedMod.Addons.Events.Commands 9 | { 10 | public class DisableEvent : ICommand, IUsageProvider 11 | { 12 | public string Command { get; } = "disable"; 13 | 14 | public string[] Aliases { get; } = new string[] 15 | { 16 | }; 17 | 18 | public string Description { get; } = "Disables the current event will restart the round immediately"; 19 | 20 | public string[] Usage { get; } = new string[] 21 | { 22 | "%queuepos%", 23 | }; 24 | 25 | public bool Execute(ArraySegment arguments, ICommandSender sender, 26 | out string response) 27 | { 28 | if (arguments.Count < 1) 29 | { 30 | response = "To execute this command provide at least 1 arguments!\nUsage: " + this.DisplayCommandUsage(); 31 | return false; 32 | } 33 | int queuepos = Convert.ToInt16(arguments.At(0)); 34 | if (queuepos >= 1 && EventManager.EventQueue.Count <= 0) 35 | { 36 | if (EventManager.EventQueue.Count == 0) 37 | { 38 | response = "There is no event pending for the next round"; 39 | return false; 40 | } 41 | } 42 | else if (queuepos <= 0) 43 | { 44 | if (EventManager.CurrentEvent == null) 45 | { 46 | response = "There is no event in progress"; 47 | return false; 48 | } 49 | } 50 | 51 | if (sender.IsPanelUser() ? !sender.CheckPermission(PlayerPermissions.FacilityManagement) : !sender.HasPermissions("cedmod.events.disable")) 52 | { 53 | response = "No permission"; 54 | return false; 55 | } 56 | 57 | if (queuepos >= 1) 58 | { 59 | var toRemove = EventManager.EventQueue[queuepos - 1]; 60 | EventManager.EventQueue.Remove(toRemove); 61 | Broadcast.Singleton.RpcAddElement($"EventManager: {toRemove.EventName} has been removed from the queue", 5, Broadcast.BroadcastFlags.Normal); 62 | } 63 | else 64 | { 65 | Broadcast.Singleton.RpcAddElement($"EventManager: {EventManager.CurrentEvent.EventName} is being now disabled, round will restart in 3 seconds", 10, Broadcast.BroadcastFlags.Normal); 66 | Timing.CallDelayed(3, () => 67 | { 68 | Round.Restart(false, false); 69 | }); 70 | } 71 | ThreadDispatcher.SendHeartbeatMessage(true); 72 | response = "Success"; 73 | return true; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Commands/EnableEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CedMod.Addons.Events.Interfaces; 4 | using CedMod.Addons.QuerySystem; 5 | using CommandSystem; 6 | using LabApi.Features.Permissions; 7 | using LabApi.Features.Wrappers; 8 | using MEC; 9 | 10 | namespace CedMod.Addons.Events.Commands 11 | { 12 | public class EnableEvent : ICommand, IUsageProvider 13 | { 14 | public string Command { get; } = "enable"; 15 | 16 | public string[] Aliases { get; } = new string[] 17 | { 18 | }; 19 | 20 | public string Description { get; } = "Enables the specified event, if Force is true the server will restart the round immediately"; 21 | 22 | public string[] Usage { get; } = new string[] 23 | { 24 | "%eventprefix%", 25 | "%force%" 26 | }; 27 | 28 | public bool Execute(ArraySegment arguments, ICommandSender sender, 29 | out string response) 30 | { 31 | if (arguments.Count < 2) 32 | { 33 | response = "To execute this command provide at least 2 arguments!\nUsage: " + this.DisplayCommandUsage(); 34 | return false; 35 | } 36 | IEvent @event = EventManager.AvailableEvents.FirstOrDefault(ev => ev.EventPrefix == arguments.At(0)); 37 | bool force = Convert.ToBoolean(arguments.At(1)); 38 | if (@event == null) 39 | { 40 | response = "Event does not exist"; 41 | return false; 42 | } 43 | 44 | if (sender.IsPanelUser() ? !sender.CheckPermission(PlayerPermissions.FacilityManagement) : !sender.HasPermissions("cedmod.events.enable")) 45 | { 46 | response = "No permission"; 47 | return false; 48 | } 49 | 50 | if (force) 51 | { 52 | EventManager.EventQueue.RemoveAll(ev => ev.EventName == @event.EventName); 53 | EventManager.EventQueue.Insert(0, @event); 54 | Broadcast.Singleton.RpcAddElement($"EventManager: {@event.EventName} is being enabled.\nRound will restart in 3 seconds", 5, Broadcast.BroadcastFlags.Normal); 55 | Timing.CallDelayed(3, () => 56 | { 57 | Round.Restart(false, false); 58 | }); 59 | } 60 | else 61 | { 62 | if (EventManager.EventQueue.Any(ev => ev.EventName == @event.EventName)) 63 | { 64 | response = "This event is already added to the queue"; 65 | return false; 66 | } 67 | EventManager.EventQueue.Add(@event); 68 | Broadcast.Singleton.RpcAddElement($"EventManager: {@event.EventName} has been added to the event queue: position {EventManager.EventQueue.IndexOf(@event)}", 10, Broadcast.BroadcastFlags.Normal); 69 | } 70 | ThreadDispatcher.SendHeartbeatMessage(true); 71 | response = "Success"; 72 | return true; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Commands/Events.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandSystem; 3 | 4 | namespace CedMod.Addons.Events.Commands 5 | { 6 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 7 | public class EventsCommand : ParentCommand 8 | { 9 | public override string Command => "events"; 10 | 11 | public override string[] Aliases { get; } = new string[] 12 | { 13 | }; 14 | public override string Description => "Main command for CedMod EventSystem"; 15 | 16 | public EventsCommand() => LoadGeneratedCommands(); 17 | 18 | public override void LoadGeneratedCommands() 19 | { 20 | RegisterCommand(new ListEvents()); 21 | RegisterCommand(new EnableEvent()); 22 | RegisterCommand(new DisableEvent()); 23 | RegisterCommand(new Queue()); 24 | RegisterCommand(new BumpEvent()); 25 | } 26 | 27 | protected override bool ExecuteParent(ArraySegment arguments, ICommandSender sender, out string response) 28 | { 29 | 30 | response = "Please specify a valid subcommand!\n Valid subcommands are: list, enable, disable, queue, bump"; 31 | return false; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Commands/ListEvents.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandSystem; 3 | using LabApi.Features.Permissions; 4 | 5 | namespace CedMod.Addons.Events.Commands 6 | { 7 | public class ListEvents : ICommand 8 | { 9 | public string Command { get; } = "list"; 10 | 11 | public string[] Aliases { get; } = new string[] 12 | { 13 | }; 14 | 15 | public string Description { get; } = "Gets a list of events"; 16 | 17 | public bool Execute(ArraySegment arguments, ICommandSender sender, 18 | out string response) 19 | { 20 | response = ""; 21 | if (!sender.HasPermissions("cedmod.events.list")) 22 | { 23 | response = "No permission"; 24 | return false; 25 | } 26 | foreach (var ev in EventManager.AvailableEvents) 27 | { 28 | response += $"{ev.EventName} (Prefix: {ev.EventPrefix}) Author: {ev.EvenAuthor} - {ev.EventDescription}"; 29 | } 30 | 31 | return true; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Commands/PopuplateCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using CedMod.Addons.Audio; 5 | using CentralAuth; 6 | using CommandSystem; 7 | using LabApi.Features.Permissions; 8 | using MEC; 9 | using Mirror; 10 | using Object = UnityEngine.Object; 11 | 12 | namespace CedMod.Addons.Events.Commands 13 | { 14 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 15 | public class Populate : ICommand, IUsageProvider 16 | { 17 | public string Command { get; } = "populate"; 18 | 19 | public string[] Aliases { get; } = new string[] 20 | { 21 | }; 22 | 23 | public string Description { get; } = "spawns an given amount of dummy players for testing purposes."; 24 | 25 | public string[] Usage { get; } = new string[] 26 | { 27 | "%amount%", 28 | }; 29 | 30 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 31 | { 32 | if (!sender.HasPermissions("cedmod.populate")) 33 | { 34 | response = "no permission"; 35 | return false; 36 | } 37 | if (arguments.Count < 1) 38 | { 39 | response = "To execute this command provide at least 1 argument!\nUsage: " + this.DisplayCommandUsage(); 40 | return false; 41 | } 42 | int amount = Convert.ToInt16(arguments.At(0)); 43 | 44 | Timing.RunCoroutine(SpawnDummies(amount)); 45 | response = "Success"; 46 | return true; 47 | } 48 | 49 | public IEnumerator SpawnDummies(int amount) 50 | { 51 | var first = AudioCommand.FakeConnectionsIds.OrderByDescending(s => s.Key); 52 | var id = AudioCommand.FakeConnectionsIds.Count <= 0 ? 1 : first.FirstOrDefault().Key; 53 | while (id < amount) 54 | { 55 | id++; 56 | var newPlayer = Object.Instantiate(NetworkManager.singleton.playerPrefab); 57 | 58 | var fakeConnection = new FakeConnection(id); 59 | 60 | 61 | var hubPlayer = newPlayer.GetComponent(); 62 | AudioCommand.FakeConnections.Add(fakeConnection, hubPlayer); 63 | AudioCommand.FakeConnectionsIds.Add(id, hubPlayer); 64 | 65 | NetworkServer.AddPlayerForConnection(fakeConnection, newPlayer); 66 | try 67 | { 68 | hubPlayer.authManager.UserId = $"player{id}@server"; 69 | } 70 | catch (Exception e) 71 | { 72 | } 73 | hubPlayer.authManager.InstanceMode = ClientInstanceMode.Host; 74 | try 75 | { 76 | hubPlayer.nicknameSync.SetNick($"Dummy player {id}"); 77 | } 78 | catch (Exception e) 79 | { 80 | } 81 | 82 | yield return Timing.WaitForSeconds(0.05f); 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Commands/Queue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CedMod.Addons.QuerySystem; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | 6 | namespace CedMod.Addons.Events.Commands 7 | { 8 | public class Queue : ICommand 9 | { 10 | public string Command { get; } = "queue"; 11 | 12 | public string[] Aliases { get; } = new string[] 13 | { 14 | }; 15 | 16 | public string Description { get; } = "Gets the current event queue"; 17 | 18 | public bool Execute(ArraySegment arguments, ICommandSender sender, 19 | out string response) 20 | { 21 | if (sender.IsPanelUser() ? !sender.CheckPermission(PlayerPermissions.FacilityManagement) : !sender.HasPermissions("cedmod.events.queue")) 22 | { 23 | response = "No permission"; 24 | return false; 25 | } 26 | 27 | response = ""; 28 | response += $"Current event: [0] {(EventManager.CurrentEvent == null ? "None" : $"{EventManager.CurrentEvent.EventName} - ({EventManager.CurrentEvent.EventPrefix})")}\n\n\nQueue:\n"; 29 | foreach (var evnt in EventManager.EventQueue) 30 | { 31 | response += $"[{EventManager.EventQueue.IndexOf(evnt) + 1}] {evnt.EventName} - ({evnt.EventPrefix})\n"; 32 | } 33 | ThreadDispatcher.SendHeartbeatMessage(true); 34 | return true; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Config.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace CedMod.Addons.Events 4 | { 5 | public sealed class EventsConfig 6 | { 7 | [Description("Indicates whether the plugin is enabled or not")] 8 | public bool IsEnabled { get; set; } = true; 9 | 10 | [Description("If debug messages are shown")] 11 | public bool Debug { get; set; } = false; 12 | } 13 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/EventManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CedMod.Addons.Events.Interfaces; 3 | using Exiled.API.Interfaces; 4 | using LabApi.Loader.Features.Plugins; 5 | 6 | namespace CedMod.Addons.Events 7 | { 8 | public class EventManager 9 | { 10 | public static IEvent CurrentEvent = null; 11 | public static List EventQueue = new List(); 12 | public static List AvailableEvents = new List(); 13 | public static List AvailableEventPlugins = new List(); 14 | #if EXILED 15 | public static List> AvailableEventPluginsExiled = new List>(); 16 | #endif 17 | } 18 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/EventManagerPlayerEvents.cs: -------------------------------------------------------------------------------- 1 | using LabApi.Events.Arguments.PlayerEvents; 2 | using LabApi.Events.CustomHandlers; 3 | using LabApi.Features.Console; 4 | 5 | namespace CedMod.Addons.Events 6 | { 7 | public class EventManagerPlayerEvents: CustomEventsHandler 8 | { 9 | public override void OnPlayerJoined(PlayerJoinedEventArgs ev) 10 | { 11 | if (CedModMain.Singleton.Config.EventManager.Debug) 12 | Logger.Debug($"Join {EventManager.CurrentEvent != null}"); 13 | if (EventManager.CurrentEvent != null) 14 | { 15 | ev.Player.GameObject.AddComponent(); 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/EventManagerServerEvents.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using CedMod.Addons.Events.Interfaces; 5 | using CedMod.Addons.Events.Patches; 6 | using CedMod.Addons.QuerySystem; 7 | #if EXILED 8 | using Exiled.API.Features; 9 | #endif 10 | using LabApi.Events.Arguments.ServerEvents; 11 | using LabApi.Events.CustomHandlers; 12 | using LabApi.Features.Console; 13 | 14 | namespace CedMod.Addons.Events 15 | { 16 | public class EventManagerServerEvents: CustomEventsHandler 17 | { 18 | public override void OnServerRoundEnding(RoundEndingEventArgs ev) 19 | { 20 | if (EventManager.CurrentEvent != null && EventManager.CurrentEvent is IEndConditionBehaviour endConditionBehaviour) 21 | { 22 | ev.IsAllowed = endConditionBehaviour.CanRoundEnd(false); 23 | } 24 | } 25 | 26 | public override void OnServerRoundEnded(RoundEndedEventArgs ev) 27 | { 28 | if (EventManager.CurrentEvent != null) 29 | { 30 | Logger.Info($"Enabled {EventManager.CurrentEvent.EventName} has been disabled due to round end"); 31 | EventManager.CurrentEvent.StopEvent(); 32 | EventManager.CurrentEvent = null; 33 | } 34 | } 35 | 36 | public override void OnServerWaitingForPlayers() 37 | { 38 | if (EventManager.EventQueue.Count >= 1) 39 | { 40 | var next = EventManager.EventQueue.FirstOrDefault(); 41 | EventManager.CurrentEvent = next; 42 | EventManager.EventQueue.Remove(next); 43 | } 44 | if (EventManager.CurrentEvent != null) 45 | { 46 | EventManager.CurrentEvent.PrepareEvent(); 47 | Logger.Info($"Enabled {EventManager.CurrentEvent.EventName} for this round"); 48 | } 49 | ThreadDispatcher.SendHeartbeatMessage(true); 50 | 51 | #if EXILED 52 | if (AppDomain.CurrentDomain.GetAssemblies().Any(s => s.GetName().Name == "ScriptedEvents") && Directory.Exists(Path.Combine(Paths.Configs, "ScriptedEvents")) && EventManager.EventQueue.Count == 0) 53 | { 54 | EventManager.AvailableEvents.RemoveAll(s => s.GetType() == typeof(ScriptedEventIntergration)); 55 | foreach (var file in Directory.GetFiles(Path.Combine(Paths.Configs, "ScriptedEvents"))) 56 | { 57 | string data = File.ReadAllText(file); 58 | if (!data.Contains("!-- DISABLE") && data.Contains("!-- ADMINEVENT")) 59 | { 60 | EventManager.AvailableEvents.Add(new ScriptedEventIntergration() 61 | { 62 | BulletHolesAllowed = true, 63 | config = new ScriptedEventConfig(){ IsEnabled = true}, 64 | eventAuthor = "ScriptedEvents", 65 | EventDescription = "ScriptedEvent", 66 | eventName = Path.GetFileNameWithoutExtension(file), 67 | eventPrefix = Path.GetFileNameWithoutExtension(file), 68 | FilePath = file 69 | }); 70 | } 71 | } 72 | } 73 | #endif 74 | } 75 | 76 | public override void OnServerRoundRestarted() 77 | { 78 | if (EventManager.CurrentEvent != null) 79 | { 80 | Logger.Info($"Enabled {EventManager.CurrentEvent.EventName} has been disabled due to round restart"); 81 | EventManager.CurrentEvent.StopEvent(); 82 | EventManager.CurrentEvent = null; 83 | } 84 | HintManager.HintProcessed.Clear(); 85 | 86 | SeedGenerationPatch.NextSeed = -1; 87 | 88 | if (EventManager.EventQueue.Count >= 1) 89 | { 90 | var next = EventManager.EventQueue.FirstOrDefault(); 91 | if (next is IMapgenBehaviour mapgenBehaviour) 92 | { 93 | SeedGenerationPatch.NextSeed = mapgenBehaviour.Seed; 94 | } 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/HintManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using LabApi.Features.Wrappers; 4 | using UnityEngine; 5 | 6 | namespace CedMod.Addons.Events 7 | { 8 | public class HintManager: MonoBehaviour 9 | { 10 | public float hintTimer = 0; 11 | public float hintRefreshRate = 1; 12 | public static List> HintProcessed = new List>(); 13 | public Player player; 14 | public string currentHint = ""; 15 | private bool wipe = false; 16 | 17 | public void Awake() 18 | { 19 | player = Player.Get(this.GetComponent()); 20 | LabApi.Features.Console.Logger.Info($"Initialized HintManager for {player.Nickname}"); 21 | currentHint = "\n\n" + 22 | "This server is currently running an event:" + 23 | $"\n{EventManager.CurrentEvent.EventName} By {EventManager.CurrentEvent.EvenAuthor}" + 24 | $"\n" + 25 | $"\n{EventManager.CurrentEvent.EventDescription}" + 26 | $""; 27 | } 28 | 29 | public void Update() 30 | { 31 | if (!wipe && RoundSummary.RoundInProgress()) 32 | { 33 | wipe = true; 34 | currentHint = ""; 35 | } 36 | hintTimer -= Time.deltaTime; 37 | if (hintTimer <= 0) 38 | { 39 | hintTimer = hintRefreshRate - 0.2f; 40 | string hintAddition = ""; 41 | foreach (var callback in HintProcessed) 42 | { 43 | hintAddition += callback.Invoke(player); 44 | } 45 | 46 | if (HintProcessed.Count >= 1) 47 | { 48 | if (!string.IsNullOrEmpty(hintAddition)) 49 | currentHint = hintAddition; 50 | 51 | if (string.IsNullOrEmpty(hintAddition)) 52 | currentHint = ""; 53 | } 54 | 55 | if (CedModMain.Singleton.Config.EventManager.Debug) 56 | LabApi.Features.Console.Logger.Debug($"Hint display: {currentHint}"); 57 | 58 | if (!string.IsNullOrEmpty(currentHint)) 59 | player.SendHint(currentHint, hintRefreshRate); 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/IEventConfig.cs: -------------------------------------------------------------------------------- 1 | namespace CedMod.Addons.Events 2 | { 3 | public interface IEventConfig 4 | { 5 | public bool IsEnabled { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Interfaces/IBulletHoleBehaviour.cs: -------------------------------------------------------------------------------- 1 | using InventorySystem.Items.Firearms.Modules; 2 | using UnityEngine; 3 | 4 | namespace CedMod.Addons.Events.Interfaces 5 | { 6 | public interface IBulletHoleBehaviour 7 | { 8 | bool CanPlaceBulletHole(ImpactEffectsModule reg, Vector3 ray, RaycastHit hit); 9 | } 10 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Interfaces/IEndConditionBehaviour.cs: -------------------------------------------------------------------------------- 1 | namespace CedMod.Addons.Events.Interfaces 2 | { 3 | public interface IEndConditionBehaviour 4 | { 5 | bool CanRoundEnd(bool baseGameConditionsSatisfied); 6 | } 7 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Interfaces/IEvent.cs: -------------------------------------------------------------------------------- 1 | namespace CedMod.Addons.Events.Interfaces 2 | { 3 | public interface IEvent 4 | { 5 | string EventName { get; } 6 | string EvenAuthor { get; } 7 | string EventDescription { get; set; } 8 | string EventPrefix { get; } 9 | IEventConfig EventConfig { get; } 10 | 11 | void PrepareEvent(); 12 | void StopEvent(); 13 | } 14 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Interfaces/IFriendlyFireAutoBanBehaviour.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LabApi.Features.Wrappers; 3 | using PlayerStatsSystem; 4 | 5 | namespace CedMod.Addons.Events.Interfaces 6 | { 7 | public interface IFriendlyFireAutoBanBehaviour 8 | { 9 | string VictimMessage(Player player, Player attacker, DamageHandlerBase damageHandler); 10 | string KillerMessage(Player player, Player attacker, DamageHandlerBase damageHandler); 11 | bool IsTeamkill(Player player, Player attacker, DamageHandlerBase damageHandler); 12 | bool ShouldBan(Player player, Player attacker, DamageHandlerBase damageHandler, int teamkillAmount, out int cedModAutobanThreshold, out bool ignoreImmunity, out TimeSpan banDuration, out string banReason); 13 | } 14 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Interfaces/IMapgenBehaviour.cs: -------------------------------------------------------------------------------- 1 | namespace CedMod.Addons.Events.Interfaces 2 | { 3 | public interface IMapgenBehaviour 4 | { 5 | int Seed { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Patches/BulletHolePatch.cs: -------------------------------------------------------------------------------- 1 | using CedMod.Addons.Events.Interfaces; 2 | using Decals; 3 | using HarmonyLib; 4 | using InventorySystem.Items.Firearms.Modules; 5 | using UnityEngine; 6 | using VoiceChat; 7 | 8 | namespace CedMod.Addons.Events.Patches 9 | { 10 | [HarmonyPatch(typeof(ImpactEffectsModule), nameof(ImpactEffectsModule.ServerSendImpactDecal))] 11 | public static class BulletHolePatch 12 | { 13 | public static bool Prefix(ImpactEffectsModule __instance, RaycastHit hit, Vector3 origin, DecalPoolType decalType) 14 | { 15 | if (CedModMain.Singleton.Config.CedMod.PreventBulletHolesWhenMuted && __instance.Firearm.Owner != null && VoiceChatMutes.GetFlags(__instance.Firearm.Owner).HasFlag(VcMuteFlags.LocalRegular)) 16 | return false; 17 | if (EventManager.CurrentEvent != null && EventManager.CurrentEvent is IBulletHoleBehaviour dissallowBulletHoles && !dissallowBulletHoles.CanPlaceBulletHole(__instance, origin, hit)) 18 | return false; 19 | return true; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/Patches/SeedGenerationPatch.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using MapGeneration; 3 | 4 | namespace CedMod.Addons.Events.Patches 5 | { 6 | [HarmonyPatch(typeof(SeedSynchronizer), nameof(SeedSynchronizer.Awake))] 7 | public static class SeedGenerationPatch 8 | { 9 | private static int _nextSeed = -1; 10 | 11 | public static int NextSeed 12 | { 13 | private get => _nextSeed; 14 | set 15 | { 16 | if (value < 0) 17 | _nextSeed = -1; 18 | else 19 | _nextSeed = value; 20 | } 21 | } 22 | 23 | public static bool Prefix(SeedSynchronizer __instance) 24 | { 25 | if (NextSeed == -1) 26 | return true; 27 | 28 | SeedSynchronizer.Seed= NextSeed; 29 | return false; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CedMod/Addons/Events/ScriptedEventIntergration.cs: -------------------------------------------------------------------------------- 1 | using CedMod.Addons.Events.Interfaces; 2 | 3 | namespace CedMod.Addons.Events 4 | { 5 | public class ScriptedEventIntergration: IEvent 6 | { 7 | public string FilePath { get; set; } 8 | public string EventName 9 | { 10 | get => eventName; 11 | } 12 | public string eventName; 13 | public string EvenAuthor 14 | { 15 | get => eventAuthor; 16 | } 17 | public string eventAuthor; 18 | public string EventDescription { get; set; } = "Scripted-Event"; 19 | public string EventPrefix 20 | { 21 | get => $"SCRPTEV-{eventPrefix}"; 22 | } 23 | public string eventPrefix; 24 | public bool BulletHolesAllowed { get; set; } 25 | public IEventConfig EventConfig 26 | { 27 | get => config; 28 | } 29 | public IEventConfig config; 30 | public void PrepareEvent() 31 | { 32 | #if EXILED 33 | var script = ScriptedEvents.API.Helpers.ScriptHelper.ReadScript(eventName); 34 | ScriptedEvents.API.Helpers.ScriptHelper.RunScript(script); 35 | #endif 36 | } 37 | 38 | public void StopEvent() 39 | { 40 | #if EXILED 41 | ScriptedEvents.API.Helpers.ScriptHelper.StopAllScripts(); 42 | #endif 43 | } 44 | } 45 | 46 | public class ScriptedEventConfig : IEventConfig 47 | { 48 | public bool IsEnabled { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Commands/CmSyncCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandSystem; 3 | 4 | namespace CedMod.Addons.QuerySystem.Commands 5 | { 6 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 7 | public class CmSyncCommandCommand : ICommand 8 | { 9 | public string Command { get; } = "cmsync"; 10 | 11 | public string[] Aliases { get; } = new string[] 12 | { 13 | }; 14 | 15 | public string Description { get; } = "syncs roles for cedmod panel"; 16 | 17 | public bool Execute(ArraySegment arguments, ICommandSender sender, 18 | out string response) 19 | { 20 | if (sender.IsPanelUser()) 21 | { 22 | if (!sender.CheckPermission(PlayerPermissions.SetGroup)) 23 | { 24 | response = "No permission"; 25 | return false; 26 | } 27 | if (ServerStatic.PermissionsHandler.Members.ContainsKey(CedModPlayer.Get(int.Parse(arguments.At(0))).UserId)) 28 | { 29 | response = "User already has a role"; 30 | return false; 31 | } 32 | 33 | if (CedModPlayer.Get(int.Parse(arguments.At(0))).UserId != arguments.At(2)) 34 | { 35 | response = "UserId mismatch"; 36 | return false; 37 | } 38 | ServerStatic.PermissionsHandler.Members[CedModPlayer.Get(int.Parse(arguments.At(0))).UserId] = arguments.At(1); 39 | CedModPlayer.Get(int.Parse(arguments.At(0))).ReferenceHub.serverRoles.SetGroup(ServerStatic.PermissionsHandler.Groups[arguments.At(1)], false); 40 | CommandHandler.Synced.Add(CedModPlayer.Get(int.Parse(arguments.At(0))).UserId, arguments.At(1)); 41 | response = "Done."; 42 | return true; 43 | } 44 | 45 | response = "This command may only be run by the panel"; 46 | return true; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Commands/ImportRaCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using CedMod.Addons.QuerySystem; 4 | using CedMod.Addons.QuerySystem.WS; 5 | using CedMod.ApiModals; 6 | using CommandSystem; 7 | using Newtonsoft.Json; 8 | 9 | namespace CedMod.Commands 10 | { 11 | [CommandHandler(typeof(GameConsoleCommandHandler))] 12 | public class ImportRaCommand : ICommand 13 | { 14 | public string Command { get; } = "cedmodimportra"; 15 | 16 | public string[] Aliases { get; } = new string[] 17 | { 18 | }; 19 | 20 | public string Description { get; } = "Import your RA configuration to CedMod, WARNING, will override current panel perms"; 21 | 22 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 23 | { 24 | ThreadDispatcher.ThreadDispatchQueue.Enqueue(() => 25 | { 26 | List Groups = new List(); 27 | foreach (var group in ServerStatic.PermissionsHandler.Groups) 28 | { 29 | //var perms = Permissions.Groups.FirstOrDefault(s => s.Key == group.Key); 30 | Groups.Add(new SLPermissionEntry() 31 | { 32 | Name = group.Key, 33 | KickPower = group.Value.KickPower, 34 | RequiredKickPower = group.Value.RequiredKickPower, 35 | Hidden = group.Value.HiddenByDefault, 36 | Cover = group.Value.Cover, 37 | ReservedSlot = false, 38 | BadgeText = group.Value.BadgeText, 39 | BadgeColor = group.Value.BadgeColor, 40 | RoleId = 0, 41 | Permissions = (PlayerPermissions)group.Value.Permissions, 42 | ExiledPermissions = new List(), 43 | //perms.Value == null ? new List() : perms.Value.CombinedPermissions 44 | }); 45 | } 46 | 47 | WebSocketSystem.Enqueue(new QueryCommand() 48 | { 49 | Recipient = "PANEL", 50 | Data = new Dictionary() 51 | { 52 | { "Message", "ImportRAResponse" }, 53 | { "Data", JsonConvert.SerializeObject(Groups) } 54 | } 55 | }); 56 | }); 57 | response = "Done"; 58 | return true; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Commands/NearbyBulletHoles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CedMod.Addons.QuerySystem.Patches; 4 | using CommandSystem; 5 | using MapGeneration; 6 | using PluginAPI.Core; 7 | using RemoteAdmin; 8 | using NWAPIPermissionSystem; 9 | 10 | namespace CedMod.Addons.QuerySystem.Commands 11 | { 12 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 13 | public class NearbyBulletHolesCommand : ICommand 14 | { 15 | public string Command { get; } = "nearbybulletholes"; 16 | 17 | public string[] Aliases { get; } = new string[] 18 | { 19 | "bulletholes", 20 | "nearbyholes" 21 | }; 22 | 23 | public string Description { get; } = 24 | "Shows the creators of the nearby bullet holes and how much the bullet holes were"; 25 | 26 | public bool Execute(ArraySegment arguments, ICommandSender sender, 27 | out string response) 28 | { 29 | if (!sender.CheckPermission("cedmod.bulletholes")) 30 | { 31 | response = "No permission"; 32 | return false; 33 | } 34 | 35 | response = 36 | "List of nearby bulletholes\nFormat: [Playername] ([PlayerId]) - [BulletHoleCreated] CON: [IsConnected]"; 37 | var room = RoomIdUtils.RoomAtPosition(Player.Get((sender as PlayerCommandSender).ReferenceHub).Position); 38 | if (arguments.Count >= 1) 39 | { 40 | foreach (var creat in BulletHolePatch.HoleCreators.Where(hole => 41 | hole.Key.Nickname == arguments.At(0) || hole.Key.PlayerId.ToString() == arguments.At(0))) 42 | { 43 | if (creat.Value.Rooms.ContainsKey(room)) 44 | { 45 | response += 46 | $"\n{creat.Key.Nickname} ({creat.Key.PlayerId}) - {creat.Value.Rooms[room].Holes.Count} CON: {creat.Key.ReferenceHub != null}"; 47 | } 48 | } 49 | 50 | return true; 51 | } 52 | else 53 | { 54 | foreach (var creat in BulletHolePatch.HoleCreators) 55 | { 56 | if (creat.Value.Rooms.ContainsKey(room)) 57 | { 58 | response += 59 | $"\n{creat.Key.Nickname} ({creat.Key.PlayerId}) - {creat.Value.Rooms[room].Holes.Count} CON: {creat.Key.ReferenceHub != null}"; 60 | } 61 | } 62 | 63 | return true; 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Commands/RestartQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using CedMod.Addons.QuerySystem.WS; 4 | using CommandSystem; 5 | using LabApi.Features.Permissions; 6 | #if !EXILED 7 | 8 | #else 9 | using Exiled.Permissions.Extensions; 10 | #endif 11 | 12 | namespace CedMod.Addons.QuerySystem.Commands 13 | { 14 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 15 | public class RestartQueryCommand : ICommand 16 | { 17 | public string Command { get; } = "restartqueryserver"; 18 | 19 | public string[] Aliases { get; } = new string[] 20 | { 21 | }; 22 | 23 | public string Description { get; } = "restarts querysystem"; 24 | 25 | public bool Execute(ArraySegment arguments, ICommandSender sender, 26 | out string response) 27 | { 28 | if (!sender.HasPermissions("cedmod.restartquery")) 29 | { 30 | response = "No permission"; 31 | return false; 32 | } 33 | 34 | Task.Run(async () => 35 | { 36 | WebSocketSystem.Stop(); 37 | await WebSocketSystem.Start(); 38 | }); 39 | response = "Query server restarted"; 40 | return true; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Commands/ToggleExpTracking.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CedMod.Addons.QuerySystem.WS; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | #if !EXILED 6 | #else 7 | using Exiled.Permissions.Extensions; 8 | #endif 9 | 10 | namespace CedMod.Addons.QuerySystem.Commands 11 | { 12 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 13 | public class TogglExptracking : ICommand 14 | { 15 | public string Command { get; } = "toggleexptracking"; 16 | 17 | public string[] Aliases { get; } = new string[] 18 | { 19 | }; 20 | 21 | public string Description { get; } = "Toggles tracking of EXP for this specific server"; 22 | 23 | public bool Execute(ArraySegment arguments, ICommandSender sender, 24 | out string response) 25 | { 26 | if (!sender.HasPermissions("cedmod.exptoggle")) 27 | { 28 | response = "No permission"; 29 | return false; 30 | } 31 | 32 | if (!WebSocketSystem.HelloMessage.ExpEnabled) 33 | { 34 | response = "EXP Tracking is disabled on panel level and cannot be enabled locally"; 35 | return false; 36 | } 37 | LevelerStore.TrackingEnabled = !LevelerStore.TrackingEnabled; 38 | response = $"EXP tracking {(LevelerStore.TrackingEnabled ? "Enabled" : "Disabled")}"; 39 | return true; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Extensions.cs: -------------------------------------------------------------------------------- 1 | using CedMod.Addons.QuerySystem.WS; 2 | using CommandSystem; 3 | 4 | namespace CedMod.Addons.QuerySystem 5 | { 6 | public static class Extensions 7 | { 8 | public static bool IsPanelUser(this ICommandSender sender) 9 | { 10 | return sender is CmSender; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/LevelerStore.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LabApi.Features.Wrappers; 3 | using PlayerRoles; 4 | 5 | namespace CedMod.Addons.QuerySystem 6 | { 7 | public class LevelerStore 8 | { 9 | public static bool TrackingEnabled; 10 | public static Dictionary InitialPlayerRoles = new Dictionary(); 11 | } 12 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/BulletHolePatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using HarmonyLib; 4 | using InventorySystem.Items.Firearms.Modules; 5 | using MapGeneration; 6 | using PluginAPI.Core; 7 | using UnityEngine; 8 | 9 | namespace CedMod.Addons.QuerySystem.Patches 10 | { 11 | [HarmonyPatch(typeof(StandardHitregBase), nameof(StandardHitregBase.PlaceBulletholeDecal))] 12 | public static class BulletHolePatch 13 | { 14 | public static Dictionary HoleCreators = new Dictionary(); 15 | 16 | public static void Prefix(StandardHitregBase __instance, Ray ray, RaycastHit hit) 17 | { 18 | try 19 | { 20 | Player player = Player.Get(__instance.Hub); 21 | if (player == null) 22 | return; 23 | RoomIdentifier currentRoom = RoomIdUtils.RoomAtPosition(player.Position); 24 | if (!HoleCreators.ContainsKey(player)) 25 | HoleCreators.Add(player, new BulletHoleCreator()); 26 | if (!HoleCreators[player].Rooms.ContainsKey(currentRoom)) 27 | HoleCreators[player].Rooms.Add(currentRoom, new RoomHoles()); 28 | 29 | HoleCreators[player].Rooms[currentRoom].Holes.Add(hit.point); 30 | } 31 | catch (Exception e) 32 | { 33 | if (CedModMain.Singleton.Config.QuerySystem.Debug) 34 | Log.Error(e.Message); 35 | } 36 | } 37 | } 38 | 39 | public class BulletHoleCreator 40 | { 41 | public Dictionary Rooms = new Dictionary(); 42 | } 43 | 44 | public class RoomHoles 45 | { 46 | public List Holes = new List(); 47 | } 48 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/CommandProcessorPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using CedMod.Addons.QuerySystem.WS; 4 | using HarmonyLib; 5 | using LabApi.Features.Console; 6 | using RemoteAdmin; 7 | 8 | namespace CedMod.Addons.QuerySystem.Patches 9 | { 10 | [HarmonyPatch(typeof(CommandProcessor), nameof(CommandProcessor.ProcessQuery))] 11 | public static class CommandProcessorPatch 12 | { 13 | public static void Postfix(string q, CommandSender sender) 14 | { 15 | try 16 | { 17 | if (q.StartsWith("$", StringComparison.Ordinal)) 18 | { 19 | return; 20 | } 21 | 22 | WebSocketSystem.Enqueue(new QueryCommand() 23 | { 24 | Recipient = "ALL", 25 | Data = new Dictionary() 26 | { 27 | {"Type", "OnAdminCommand"}, 28 | {"UserId", sender.SenderId}, 29 | {"UserName", sender.Nickname}, 30 | {"Command", q}, 31 | { 32 | "Message", string.Concat(new string[] 33 | { 34 | $"{sender.Nickname} ({sender.SenderId})", 35 | " used command: ", 36 | q 37 | }) 38 | } 39 | } 40 | }); 41 | } 42 | catch (Exception e) 43 | { 44 | Logger.Error(e.ToString()); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/ExiledPermissionsPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using CedMod.Addons.QuerySystem.WS; 6 | using Exiled.API.Features; 7 | using Exiled.Permissions.Extensions; 8 | using Exiled.Permissions.Features; 9 | using GameCore; 10 | using HarmonyLib; 11 | using LabApi.Features.Console; 12 | using NorthwoodLib.Pools; 13 | using RemoteAdmin; 14 | 15 | namespace CedMod.Addons.QuerySystem.Patches 16 | { 17 | #if EXILED 18 | [HarmonyPatch(typeof(Permissions), nameof(Permissions.CheckPermission), typeof(CommandSender), typeof(string))] 19 | public static class ExiledPermissionsPatch 20 | { 21 | public static bool Prefix(ref bool __result, CommandSender sender, string permission) 22 | { 23 | if (!sender.FullPermissions) 24 | { 25 | if (CedModMain.Singleton.Config.QuerySystem.Debug) 26 | Logger.Info($"Exiled perms: {sender.GetType().FullName}"); 27 | 28 | switch (sender) 29 | { 30 | case ServerConsoleSender _: 31 | break; 32 | case PlayerCommandSender _: 33 | Player player = Player.Get(sender.SenderId); 34 | if (player == null) 35 | { 36 | __result = CheckPermission(sender.SenderId, permission); 37 | return false; 38 | } 39 | __result = player.ReferenceHub == ReferenceHub.HostHub || player.CheckPermission(permission); 40 | return false; 41 | case CmSender _: 42 | __result = CheckPermission(sender.SenderId, permission); 43 | return false; 44 | } 45 | } 46 | 47 | __result = true; 48 | return false; 49 | } 50 | 51 | public static bool CheckPermission(string userId, string permission) 52 | { 53 | if (CedModMain.Singleton.Config.QuerySystem.Debug) 54 | Logger.Info(userId); 55 | if (string.IsNullOrEmpty(permission)) 56 | return false; 57 | 58 | string plyGroupKey = Player.Get(userId) != null ? Player.Get(userId).GroupName : ServerStatic.PermissionsHandler.Members.FirstOrDefault(g => g.Key == userId).Value; 59 | if (CedModMain.Singleton.Config.QuerySystem.Debug) 60 | Logger.Info(plyGroupKey); 61 | 62 | if (plyGroupKey is null || !Permissions.Groups.TryGetValue(plyGroupKey, out Group group)) 63 | { 64 | group = Permissions.DefaultGroup; 65 | } 66 | 67 | if (CedModMain.Singleton.Config.QuerySystem.Debug) 68 | { 69 | foreach (var grp in Exiled.Permissions.Extensions.Permissions.Groups) 70 | { 71 | Logger.Info(grp.Key); 72 | } 73 | } 74 | 75 | if (group is null) 76 | { 77 | return false; 78 | } 79 | 80 | const char permSeparator = '.'; 81 | const string allPerms = ".*"; 82 | 83 | if (group.CombinedPermissions.Contains(allPerms) || group.CombinedPermissions.Contains("*")) 84 | return true; 85 | 86 | if (permission.Contains(permSeparator)) 87 | { 88 | StringBuilder strBuilder = StringBuilderPool.Shared.Rent(); 89 | string[] seraratedPermissions = permission.Split(permSeparator); 90 | 91 | bool Check(string source) => group.CombinedPermissions.Contains(source, StringComparison.OrdinalIgnoreCase); 92 | 93 | bool result = false; 94 | for (int z = 0; z < seraratedPermissions.Length; z++) 95 | { 96 | if (z != 0) 97 | { 98 | strBuilder.Length -= allPerms.Length; 99 | strBuilder.Append(permSeparator); 100 | } 101 | 102 | strBuilder.Append(seraratedPermissions[z]); 103 | 104 | if (z == seraratedPermissions.Length - 1) 105 | { 106 | result = Check(strBuilder.ToString()); 107 | break; 108 | } 109 | 110 | strBuilder.Append(allPerms); 111 | if (Check(strBuilder.ToString())) 112 | { 113 | result = true; 114 | break; 115 | } 116 | } 117 | 118 | StringBuilderPool.Shared.Return(strBuilder); 119 | return result; 120 | } 121 | 122 | bool result2 = group.CombinedPermissions.Contains(permission, StringComparison.OrdinalIgnoreCase); 123 | return result2; 124 | } 125 | } 126 | #endif 127 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/ExiledPermissionsPatchPlayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | using Exiled.API.Extensions; 5 | using Exiled.API.Features; 6 | using Exiled.Permissions.Extensions; 7 | using Exiled.Permissions.Features; 8 | using HarmonyLib; 9 | using LabApi.Features.Console; 10 | using NorthwoodLib.Pools; 11 | 12 | namespace CedMod.Addons.QuerySystem.Patches 13 | { 14 | #if EXILED 15 | [HarmonyPatch(typeof(Permissions), nameof(Permissions.CheckPermission), typeof(Player), typeof(string))] 16 | public static class ExiledPermissionsPatchPlayer 17 | { 18 | public static bool Prefix(ref bool __result, Player player, string permission) 19 | { 20 | if (string.IsNullOrEmpty(permission)) 21 | { 22 | __result = false; 23 | return false; 24 | } 25 | 26 | if (Server.Host == player) 27 | { 28 | __result = true; 29 | return false; 30 | } 31 | 32 | if (player is null || player.GameObject is null || Permissions.Groups is null || Permissions.Groups.Count == 0) 33 | { 34 | __result = false; 35 | return false; 36 | } 37 | 38 | Logger.Debug($"UserID: {player.UserId} | PlayerId: {player.Id}", Exiled.Permissions.Permissions.Instance.Config.ShouldDebugBeShown); 39 | Logger.Debug($"Permission string: {permission}", Exiled.Permissions.Permissions.Instance.Config.ShouldDebugBeShown); 40 | 41 | string plyGroupKey = player.Group is not null ? (string.IsNullOrEmpty(player.GroupName) ? ServerStatic.PermissionsHandler.Groups.FirstOrDefault(g => g.Value.EqualsTo(player.Group)).Key : ServerStatic.PermissionsHandler.Groups.FirstOrDefault(g => g.Key == player.GroupName).Key) : null; 42 | Logger.Debug($"GroupKey: {plyGroupKey ?? "(null)"}", Exiled.Permissions.Permissions.Instance.Config.ShouldDebugBeShown); 43 | 44 | if (plyGroupKey is null || !Permissions.Groups.TryGetValue(plyGroupKey, out Group group)) 45 | { 46 | Logger.Debug("The source group is null, the default group is used", Exiled.Permissions.Permissions.Instance.Config.ShouldDebugBeShown); 47 | group = Permissions.DefaultGroup; 48 | } 49 | 50 | if (group is null) 51 | { 52 | Logger.Debug("There's no default group, returning false...", Exiled.Permissions.Permissions.Instance.Config.ShouldDebugBeShown); 53 | 54 | __result = false; 55 | return false; 56 | } 57 | 58 | const char permSeparator = '.'; 59 | const string allPerms = ".*"; 60 | 61 | if (group.CombinedPermissions.Contains(allPerms) || group.CombinedPermissions.Contains("*")) 62 | { 63 | __result = true; 64 | return false; 65 | } 66 | 67 | if (permission.Contains(permSeparator)) 68 | { 69 | StringBuilder strBuilder = StringBuilderPool.Shared.Rent(); 70 | string[] seraratedPermissions = permission.Split(permSeparator); 71 | 72 | bool Check(string source) => group.CombinedPermissions.Contains(source, StringComparison.OrdinalIgnoreCase); 73 | 74 | bool result = false; 75 | for (int z = 0; z < seraratedPermissions.Length; z++) 76 | { 77 | if (z != 0) 78 | { 79 | // We need to clear the last ALL_PERMS line 80 | // or it'll be like 'permission.*.subpermission'. 81 | strBuilder.Length -= allPerms.Length; 82 | 83 | // Separate permission groups by using its separator. 84 | strBuilder.Append(permSeparator); 85 | } 86 | 87 | strBuilder.Append(seraratedPermissions[z]); 88 | 89 | // If it's the last index, 90 | // then we don't need to check for all permissions of the subpermission. 91 | if (z == seraratedPermissions.Length - 1) 92 | { 93 | result = Check(strBuilder.ToString()); 94 | break; 95 | } 96 | 97 | strBuilder.Append(allPerms); 98 | if (Check(strBuilder.ToString())) 99 | { 100 | result = true; 101 | break; 102 | } 103 | } 104 | 105 | StringBuilderPool.Shared.Return(strBuilder); 106 | 107 | Logger.Debug($"Result in the block: {result}", Exiled.Permissions.Permissions.Instance.Config.ShouldDebugBeShown); 108 | __result = result; 109 | return false; 110 | } 111 | 112 | // It'll work when there is no dot in the permission. 113 | bool result2 = group.CombinedPermissions.Contains(permission, StringComparison.OrdinalIgnoreCase); 114 | Logger.Debug($"Result outside the block: {result2}", Exiled.Permissions.Permissions.Instance.Config.ShouldDebugBeShown); 115 | __result = result2; 116 | return false; 117 | } 118 | } 119 | #endif 120 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/PreAuthModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using LiteNetLib.Utils; 4 | 5 | namespace SlProxy 6 | { 7 | public class PreAuthModel 8 | { 9 | public NetDataWriter RawPreAuth; 10 | public bool IsChallenge { get; set; } 11 | public static PreAuthModel ReadPreAuth(NetDataReader reader) 12 | { 13 | try 14 | { 15 | PreAuthModel model = new PreAuthModel(); 16 | model.RawPreAuth = NetDataWriter.FromBytes(reader.RawData, reader.UserDataOffset, reader.UserDataSize); 17 | 18 | if (reader.TryGetByte(out byte b)) 19 | model.b = b; 20 | byte cBackwardRevision = 0; 21 | byte cMajor; 22 | byte cMinor; 23 | byte cRevision; 24 | bool cflag; 25 | if (!reader.TryGetByte(out cMajor) || !reader.TryGetByte(out cMinor) || !reader.TryGetByte(out cRevision) || !reader.TryGetBool(out cflag) || (cflag && !reader.TryGetByte(out cBackwardRevision))) 26 | { 27 | return null; 28 | } 29 | 30 | model.Major = cMajor; 31 | model.Minor = cMinor; 32 | model.Revision = cRevision; 33 | model.BackwardRevision = cBackwardRevision; 34 | model.flag = cflag; 35 | 36 | if (reader.TryGetInt(out int challengeid)) 37 | { 38 | model.IsChallenge = challengeid != 0; 39 | model.ChallengeID = challengeid; 40 | } 41 | if (model.IsChallenge && reader.TryGetBytesWithLength(out byte[] challenge)) 42 | model.Challenge = challenge; 43 | else 44 | model.Challenge = new byte[0]; 45 | if (reader.TryGetString(out string userid)) 46 | model.UserID = userid; 47 | if (reader.TryGetLong(out long expiration)) 48 | model.Expiration = expiration; 49 | if (reader.TryGetByte(out byte flags)) 50 | model.Flags = flags; 51 | if (reader.TryGetString(out string region)) 52 | model.Region = region; 53 | if (reader.TryGetBytesWithLength(out byte[] signature)) 54 | model.Signature = signature; 55 | Console.WriteLine(model); 56 | return model; 57 | } 58 | catch (Exception e) 59 | { 60 | //Logger.Error(e.ToString()); 61 | } 62 | 63 | return null; 64 | } 65 | 66 | public byte b { get; set; } 67 | public byte Major { get; set; } 68 | public byte Minor { get; set; } 69 | public byte Revision { get; set; } 70 | public byte BackwardRevision { get; set; } = 0; 71 | public bool flag { get; set; } 72 | public int ChallengeID { get; set; } 73 | public byte[] Challenge { get; set; } 74 | public string UserID { get; set; } = "Unknown UserID"; 75 | public long Expiration { get; set; } 76 | public byte Flags { get; set; } 77 | public string Region { get; set; } = "Unknown Region"; 78 | public byte[] Signature { get; set; } = new byte[0]; 79 | public override string ToString() 80 | { 81 | return string.Concat( 82 | $"Version: {Major}.{Minor}.{Revision}, Backward revision: {BackwardRevision}", 83 | Environment.NewLine, 84 | $"Challenge ID: {ChallengeID}", 85 | Environment.NewLine, 86 | $"Challenge: {Encoding.Default.GetString(Challenge)}", 87 | Environment.NewLine, 88 | $"UserID: {UserID}", 89 | Environment.NewLine, 90 | $"Expiration: {Expiration}", 91 | Environment.NewLine, 92 | $"Flags: {Flags}", 93 | Environment.NewLine, 94 | $"Region: {Region}", 95 | Environment.NewLine, 96 | $"Signature length: {Signature.Length}", 97 | Environment.NewLine, 98 | $"Signature: {Encoding.Default.GetString(Signature)}", 99 | Environment.NewLine, 100 | $"IsChallenge: {IsChallenge}"); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/RefreshExiledPermissions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using CedMod.Addons.QuerySystem.WS; 5 | using HarmonyLib; 6 | using LabApi.Features.Console; 7 | 8 | namespace CedMod.Addons.QuerySystem.Patches 9 | { 10 | #if EXILED 11 | [HarmonyPatch(typeof(Exiled.Permissions.Extensions.Permissions), nameof(Exiled.Permissions.Extensions.Permissions.Reload))] 12 | public static class RefreshExiledPermissions 13 | { 14 | public static bool Prefix() 15 | { 16 | if (!WebSocketSystem.UseRa) 17 | { 18 | Task.Run(() => 19 | { 20 | try 21 | { 22 | WebSocketSystem.ApplyRa(true); 23 | } 24 | catch (Exception e) 25 | { 26 | Console.WriteLine(e); 27 | Logger.Error(e.ToString()); 28 | } 29 | }); 30 | return false; 31 | } 32 | 33 | return true; 34 | } 35 | } 36 | #endif 37 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/RefreshPermissionsHandlerPatch.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using CedMod.Addons.QuerySystem.WS; 3 | using HarmonyLib; 4 | using MEC; 5 | 6 | namespace CedMod.Addons.QuerySystem.Patches 7 | { 8 | [HarmonyPatch(typeof(PermissionsHandler), nameof(PermissionsHandler.RefreshPermissions))] 9 | public static class RefreshPermissionsHandlerPatch 10 | { 11 | public static bool Prefix() 12 | { 13 | if (!WebSocketSystem.UseRa) 14 | { 15 | new Thread(() => { WebSocketSystem.ApplyRa(true); }).Start(); 16 | return false; 17 | } 18 | 19 | return true; 20 | } 21 | } 22 | 23 | [HarmonyPatch(typeof(ServerConfigSynchronizer), nameof(ServerConfigSynchronizer.RefreshRAConfigs))] 24 | public static class RefreshRaConfigsPatch 25 | { 26 | public static CoroutineHandle CoroutineHandle; 27 | public static bool Prefix() 28 | { 29 | if (CoroutineHandle.IsRunning) 30 | return false; 31 | 32 | CoroutineHandle = Timing.RunCoroutine(CedModMain.Singleton.QueryServerEvents.SyncStart(false)); 33 | 34 | return true; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Patches/ShootingPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using CedMod.Addons.QuerySystem.WS; 6 | using HarmonyLib; 7 | using InventorySystem.Items.Firearms; 8 | using InventorySystem.Items.Firearms.Modules; 9 | using InventorySystem.Items.Firearms.Modules.Misc; 10 | using LabApi.Features.Wrappers; 11 | using Mirror; 12 | using PlayerRoles; 13 | using PlayerRoles.FirstPersonControl; 14 | using RelativePositioning; 15 | using UnityEngine; 16 | 17 | namespace CedMod.Addons.QuerySystem.Patches 18 | { 19 | [HarmonyPatch(typeof(HitscanHitregModuleBase), nameof(HitscanHitregModuleBase.ServerAppendPrescan))] 20 | public static class DoubleActionShootPatch 21 | { 22 | public static void Postfix(HitscanHitregModuleBase __instance, Ray targetRay, HitscanResult toAppend) 23 | { 24 | try 25 | { 26 | var player = __instance.Owner; 27 | if (player != null && player.roleManager != null && player.roleManager.CurrentRole is IFpcRole role) 28 | { 29 | var horLook = role.FpcModule.MouseLook.CurrentHorizontal; 30 | var verLook = role.FpcModule.MouseLook.CurrentVertical; 31 | var shotDirection = targetRay.direction.normalized; 32 | Quaternion lookRotation = Quaternion.Euler(-verLook, horLook, 0); 33 | Vector3 lookDirection = lookRotation * Vector3.forward; 34 | 35 | int targetId = -1; 36 | foreach (var destructible in toAppend.Destructibles) 37 | { 38 | if (destructible.Destructible is HitboxIdentity hitboxIdentity && !hitboxIdentity.TargetHub.IsAlive()) 39 | { 40 | targetId = hitboxIdentity.TargetHub.PlayerId; 41 | } 42 | } 43 | 44 | float angle = Vector3.Angle(lookDirection, shotDirection); 45 | 46 | var plr = Player.Get(player); 47 | WebSocketSystem.Enqueue(new QueryCommand() 48 | { 49 | Recipient = "ALL", 50 | Data = new Dictionary() 51 | { 52 | {"ItemType", plr.CurrentItem.Type.ToString()}, 53 | {"TargetPlayer", targetId.ToString()}, 54 | {"UserId", plr.UserId}, 55 | {"UserName", plr.Nickname}, 56 | {"RayAngle", angle.ToString()}, 57 | {"RayPos", targetRay.direction.ToString()}, 58 | {"PlrPos", plr.Position.ToString()}, 59 | {"plrRot", plr.Rotation.ToString()}, 60 | {"Type", "OnPlayerShoot"}, 61 | { 62 | "Message", string.Format( 63 | "{0} - {1} ({3}) has shot a {4}.", new object[] 64 | { 65 | plr.Nickname, 66 | plr.UserId, 67 | Misc.ToHex(player.roleManager.CurrentRole.RoleColor), 68 | plr.Role, 69 | plr.CurrentItem.Type 70 | }) 71 | } 72 | } 73 | }); 74 | } 75 | } 76 | catch (Exception e) 77 | { 78 | LabApi.Features.Console.Logger.Error(e.ToString()); 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/PlayerList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RemoteAdmin; 3 | 4 | namespace CedMod.Addons.QuerySystem 5 | { 6 | public class CommandHandler 7 | { 8 | public static readonly Dictionary Synced = new Dictionary(); 9 | public static bool CheckPermissions(CommandSender sender, string queryZero, PlayerPermissions perm, string replyScreen = "", bool reply = true) 10 | { 11 | if ((ServerStatic.IsDedicated && sender.FullPermissions) || PermissionsHandler.IsPermitted(sender.Permissions, perm)) 12 | return true; 13 | 14 | if (reply) 15 | sender.RaReply(queryZero + "#You don't have permissions to execute this command.\nMissing permission: " + perm, false, true, replyScreen); 16 | 17 | return false; 18 | } 19 | public static bool IsPlayer(CommandSender sender, string queryZero, string replyScreen = "") 20 | { 21 | if (sender is PlayerCommandSender) 22 | return true; 23 | 24 | sender.RaReply(queryZero + "#This command can be executed only from the game level.", success: false, logToConsole: true, replyScreen); 25 | return false; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/QueryMapEvents.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CedMod.Addons.QuerySystem.WS; 3 | using LabApi.Events.Arguments.ServerEvents; 4 | using LabApi.Events.Arguments.WarheadEvents; 5 | using LabApi.Events.CustomHandlers; 6 | 7 | namespace CedMod.Addons.QuerySystem 8 | { 9 | public class QueryMapEvents: CustomEventsHandler 10 | { 11 | public override void OnWarheadDetonated(WarheadDetonatedEventArgs ev) 12 | { 13 | WebSocketSystem.Enqueue(new QueryCommand() 14 | { 15 | Recipient = "ALL", 16 | Data = new Dictionary() 17 | { 18 | {"Type", nameof(OnWarheadDetonated)}, 19 | {"Message", "Warhead has been detonated"} 20 | } 21 | }); 22 | } 23 | 24 | public override void OnServerLczDecontaminationAnnounced(LczDecontaminationAnnouncedEventArgs ev) 25 | { 26 | WebSocketSystem.Enqueue(new QueryCommand() 27 | { 28 | Recipient = "ALL", 29 | Data = new Dictionary() 30 | { 31 | {"Type", nameof(OnServerLczDecontaminationAnnounced)}, 32 | {"Message", $"Light containment decontamination stage {ev.Phase}."} 33 | } 34 | }); 35 | } 36 | 37 | public override void OnWarheadStarted(WarheadStartedEventArgs ev) 38 | { 39 | WebSocketSystem.Enqueue(new QueryCommand() 40 | { 41 | Recipient = "ALL", 42 | Data = new Dictionary() 43 | { 44 | {"Type", nameof(OnWarheadStarted)}, 45 | { 46 | "Message", 47 | string.Format("warhead has been started: {0} seconds", 0) //todo implement 48 | } 49 | } 50 | }); 51 | } 52 | 53 | public override void OnWarheadStopped(WarheadStoppedEventArgs ev) 54 | { 55 | WebSocketSystem.Enqueue(new QueryCommand() 56 | { 57 | Recipient = "ALL", 58 | Data = new Dictionary() 59 | { 60 | {"Type", nameof(OnWarheadStopped)}, 61 | {"Message", (ev.Player != null ? ev.Player.Nickname + " - " + ev.Player.UserId : "Server") + " has stopped the detonation."} 62 | } 63 | }); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/QuerySystem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using LabApi.Features.Console; 4 | 5 | namespace CedMod.Addons.QuerySystem 6 | { 7 | public class QuerySystem 8 | { 9 | public static List ReservedSlotUserids = new List(); 10 | private static string _querySystemKey; 11 | 12 | public static string QuerySystemKey 13 | { 14 | get 15 | { 16 | if (string.IsNullOrEmpty(_querySystemKey)) 17 | { 18 | if (!Directory.Exists(Path.Combine(CedModMain.PluginConfigFolder, "CedMod"))) 19 | { 20 | Directory.CreateDirectory(Path.Combine(CedModMain.PluginConfigFolder, "CedMod")); 21 | } 22 | if (File.Exists(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", "QuerySystemSecretKey.txt"))) 23 | { 24 | File.WriteAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"QuerySystemSecretKey-{ServerStatic.ServerPort}.txt"), File.ReadAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", "QuerySystemSecretKey.txt"))); 25 | File.Delete(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", "QuerySystemSecretKey.txt")); 26 | } 27 | 28 | if (!File.Exists(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"QuerySystemSecretKey-{ServerStatic.ServerPort}.txt"))) 29 | { 30 | return ""; 31 | } 32 | _querySystemKey = File.ReadAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"QuerySystemSecretKey-{ServerStatic.ServerPort}.txt")); 33 | 34 | if (_querySystemKey == "") 35 | { 36 | return ""; 37 | } 38 | 39 | Logger.Info("Read QueryKey from persistant storage"); 40 | } 41 | return _querySystemKey; 42 | } 43 | set 44 | { 45 | if (!Directory.Exists(Path.Combine(CedModMain.PluginConfigFolder, "CedMod"))) 46 | { 47 | Directory.CreateDirectory(Path.Combine(CedModMain.PluginConfigFolder, "CedMod")); 48 | } 49 | if (File.Exists(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", "QuerySystemSecretKey.txt"))) 50 | { 51 | File.WriteAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"QuerySystemSecretKey-{ServerStatic.ServerPort}.txt"), File.ReadAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", "QuerySystemSecretKey.txt"))); 52 | File.Delete(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", "QuerySystemSecretKey.txt")); 53 | } 54 | Logger.Info("Saved QueryKey to persistant storage"); 55 | _querySystemKey = value; 56 | File.WriteAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"QuerySystemSecretKey-{ServerStatic.ServerPort}.txt"), _querySystemKey); 57 | } 58 | } 59 | 60 | public static string CurrentPanel = ""; 61 | public static string CurrentMaster = MainPanelUrl; 62 | public static string CurrentMasterQuery = ""; 63 | public const string MainPanelUrl = "panelapi.cedmod.nl"; 64 | public static string DevPanelUrl = "gameapi.dev.cedmod.nl"; 65 | public static bool UseSSL = true; 66 | public static bool IsDev { get; set; } 67 | public static List Whitelist { get; set; } = new List(); 68 | public static bool UseWhitelist = false; 69 | } 70 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/ServerPreferences.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Net.Http; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using CedMod.ApiModals; 8 | using LabApi.Features.Console; 9 | using Newtonsoft.Json; 10 | 11 | namespace CedMod.Addons.QuerySystem 12 | { 13 | public class ServerPreferences 14 | { 15 | public static ServerPreferenceModel Prefs = null; 16 | 17 | public static async Task ResolvePreferences(bool loop = true) 18 | { 19 | if (string.IsNullOrEmpty(QuerySystem.QuerySystemKey) || CedModMain.CancellationToken.IsCancellationRequested) 20 | return; 21 | 22 | try 23 | { 24 | using (HttpClient client = new HttpClient()) 25 | { 26 | client.DefaultRequestHeaders.Add("X-ServerIp", ServerConsole.Ip); 27 | await VerificationChallenge.AwaitVerification(); 28 | if (CedModMain.Singleton.Config.CedMod.ShowDebug) 29 | Logger.Debug($"Getting Prefs."); 30 | var response = await client.GetAsync($"http{(QuerySystem.UseSSL ? "s" : "")}://" + QuerySystem.CurrentMaster + $"/ServerPreference/GetServerPreference/{QuerySystem.QuerySystemKey}"); 31 | if (response.IsSuccessStatusCode) 32 | { 33 | var data = JsonConvert.DeserializeObject( 34 | await response.Content.ReadAsStringAsync()); 35 | Prefs = data; 36 | File.WriteAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"ServerPrefs.json"), JsonConvert.SerializeObject(Prefs)); 37 | } 38 | else 39 | { 40 | if (response.StatusCode == HttpStatusCode.PreconditionRequired) 41 | { 42 | VerificationChallenge.CompletedChallenge = false; 43 | VerificationChallenge.ChallengeStarted = false; 44 | } 45 | Logger.Error($"Failed to resolve server preferences, using file: {response.StatusCode} {await response.Content.ReadAsStringAsync()}"); 46 | if (File.Exists(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"ServerPrefs.json"))) ; 47 | Prefs = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(CedModMain.PluginConfigFolder, "CedMod", $"ServerPrefs.json"))); 48 | if (loop) 49 | { 50 | await Task.Delay(1000, CedModMain.CancellationToken); 51 | await ResolvePreferences(); 52 | } 53 | return; 54 | } 55 | } 56 | } 57 | catch (Exception e) 58 | { 59 | if (e is TaskCanceledException) 60 | return; 61 | Logger.Error($"Failed to resolve server preferences, using file: {e}"); 62 | if (loop) 63 | { 64 | await Task.Delay(1000, CedModMain.CancellationToken); 65 | await ResolvePreferences(); 66 | } 67 | return; 68 | } 69 | 70 | if (loop) 71 | { 72 | await WaitForSecond(60, CedModMain.CancellationToken, (o) => !Shutdown._quitting && CedModMain.Singleton.CacheHandler != null); 73 | await ResolvePreferences(); 74 | } 75 | } 76 | 77 | public static async Task WaitForSecond(int i, CancellationToken token, Predicate predicate) 78 | { 79 | int wait = i; 80 | while (wait >= 0 && predicate.Invoke(i)) 81 | { 82 | await Task.Delay(1000, token); 83 | wait--; 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /CedMod/Addons/QuerySystem/Verification.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using CedMod.Patches; 5 | using LabApi.Features.Console; 6 | 7 | namespace CedMod.Addons.QuerySystem 8 | { 9 | public class Verification 10 | { 11 | public static int ServerId { get; set; } 12 | public static int AmountErrored = 0; 13 | 14 | public static async Task ObtainId() 15 | { 16 | while (ServerStatic.PermissionsHandler == null || !CustomNetworkManager.IsVerified) 17 | { 18 | if (CedModMain.Singleton.Config.CedMod.ShowDebug) 19 | Logger.Debug($"Verification paused as server is not verified."); 20 | if (CedModMain.CancellationToken.IsCancellationRequested) 21 | break; 22 | await Task.Delay(2000, CedModMain.CancellationToken); 23 | } 24 | 25 | using (HttpClient client = new HttpClient()) 26 | { 27 | client.DefaultRequestHeaders.Add("X-ServerIp", ServerConsole.Ip); 28 | await VerificationChallenge.AwaitVerification(); 29 | if (CedModMain.Singleton.Config.CedMod.ShowDebug) 30 | Logger.Debug($"Getting Id."); 31 | var response = await client.GetAsync($"http{(QuerySystem.UseSSL ? "s" : "")}://" + QuerySystem.CurrentMaster + $"/Verification/GetId/{QuerySystem.QuerySystemKey}?ip={ServerConsole.Ip}&port={(ServerConsole.PortOverride == 0 ? ServerStatic.ServerPort : ServerConsole.PortOverride)}"); 32 | var responseString = await response.Content.ReadAsStringAsync(); 33 | if (response.StatusCode == HttpStatusCode.OK) 34 | { 35 | ServerId = int.Parse(responseString); 36 | AmountErrored = 0; 37 | ServerConsole.ReloadServerName(); 38 | ServerConsole.Update = true; 39 | await ConfirmId(true, true); 40 | } 41 | else 42 | { 43 | if (AmountErrored <= 3) 44 | { 45 | AmountErrored++; 46 | Logger.Error($"Failed to obtain CedMod verification token: {responseString}"); 47 | } 48 | 49 | await Task.Delay(1000, CedModMain.CancellationToken); 50 | await ObtainId(); 51 | } 52 | } 53 | } 54 | 55 | public static async Task ConfirmId(bool loop = true, bool exitOnSuccess = true) 56 | { 57 | bool first = true; 58 | while (!Shutdown._quitting) 59 | { 60 | bool wasHidden = ReloadServerNamePatch.IncludeString; 61 | ReloadServerNamePatch.IncludeString = true; 62 | ServerConsole.ReloadServerName(); 63 | ServerConsole.Update = true; 64 | if (loop) 65 | await ServerPreferences.WaitForSecond(first || wasHidden ? 45000 : 15000, CedModMain.CancellationToken, (o) => !Shutdown._quitting && CedModMain.Singleton.CacheHandler != null); 66 | first = false; 67 | using (HttpClient client = new HttpClient()) 68 | { 69 | client.DefaultRequestHeaders.Add("X-ServerIp", ServerConsole.Ip); 70 | await VerificationChallenge.AwaitVerification(); 71 | if (CedModMain.Singleton.Config.CedMod.ShowDebug) 72 | Logger.Debug($"verifying Id."); 73 | var response = await client.GetAsync($"http{(QuerySystem.UseSSL ? "s" : "")}://" + QuerySystem.CurrentMaster + $"/Verification/ConfirmId/{QuerySystem.QuerySystemKey}?ip={ServerConsole.Ip}&port={(ServerConsole.PortOverride == 0 ? ServerStatic.ServerPort : ServerConsole.PortOverride)}&queryId={ServerId}"); 74 | var responseString = await response.Content.ReadAsStringAsync(); 75 | if (response.StatusCode == HttpStatusCode.OK) 76 | { 77 | ServerId = int.Parse(responseString); 78 | AmountErrored = 0; 79 | 80 | ReloadServerNamePatch.IncludeString = false; 81 | ServerConsole.ReloadServerName(); 82 | ServerConsole.Update = true; 83 | 84 | if (!loop || exitOnSuccess) 85 | return ""; 86 | } 87 | else 88 | { 89 | if (AmountErrored <= 3) 90 | { 91 | AmountErrored++; 92 | Logger.Error($"Failed to verify CedMod verification token: {responseString}"); 93 | } 94 | else if (AmountErrored >= 10) 95 | { 96 | responseString = ""; 97 | } 98 | 99 | if (!loop) 100 | return responseString; 101 | } 102 | } 103 | } 104 | 105 | return ""; 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /CedMod/Addons/Sentinal/Patches/PlayerRoleManagerPatch.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Mirror; 3 | using PlayerRoles; 4 | using PlayerRoles.PlayableScps.Scp079; 5 | using PlayerRoles.Visibility; 6 | using RemoteAdmin; 7 | using UnityEngine; 8 | 9 | namespace CedMod.Addons.Sentinal.Patches 10 | { 11 | //patch responsible for hiding and showing users without leaking info on initialjoin, any missed syncs are caught by the position distributor 12 | [HarmonyPatch(typeof(PlayerRoleManager), nameof(PlayerRoleManager.Update))] 13 | public static class PlayerRoleManagerPatch 14 | { 15 | public static bool Prefix(PlayerRoleManager __instance) 16 | { 17 | if (CedModMain.Singleton.Config.CedMod.DisableFakeSyncing) 18 | return true; 19 | 20 | if (!NetworkServer.active || !__instance._sendNextFrame) 21 | return false; 22 | 23 | __instance._sendNextFrame = false; 24 | 25 | foreach (ReferenceHub receiver in ReferenceHub.AllHubs) 26 | { 27 | if (receiver.isLocalPlayer) 28 | continue; 29 | 30 | RoleTypeId toSend = __instance.CurrentRole.RoleTypeId; 31 | 32 | if (__instance.CurrentRole is IObfuscatedRole ior) 33 | toSend = ior.GetRoleForUser(receiver); 34 | 35 | 36 | bool hasVisCtrl; 37 | VisibilityController visCtrl; 38 | 39 | if (receiver.roleManager.CurrentRole is ICustomVisibilityRole icvr) 40 | { 41 | hasVisCtrl = true; 42 | visCtrl = icvr.VisibilityController; 43 | } 44 | else 45 | { 46 | hasVisCtrl = false; 47 | visCtrl = null; 48 | } 49 | 50 | bool invisible = hasVisCtrl && !visCtrl.ValidateVisibility(__instance._hub) && !PermissionsHandler.IsPermitted(receiver.serverRoles.Permissions, PlayerPermissions.GameplayData) && receiver.roleManager.CurrentRole.Team != Team.SCPs; 51 | if (invisible && __instance.CurrentRole.Team != Team.SCPs) 52 | toSend = RoleTypeId.Spectator; 53 | 54 | 55 | if (__instance.CurrentRole is Scp079Role scp079Role) 56 | { 57 | if (Vector3.Distance(scp079Role.CameraPosition, receiver.transform.position) <= 30) 58 | toSend = __instance.CurrentRole.RoleTypeId; 59 | } 60 | 61 | if (receiver == __instance.Hub) 62 | toSend = __instance.CurrentRole.RoleTypeId; 63 | 64 | if (__instance.PreviouslySentRole.TryGetValue(receiver.netId, out RoleTypeId prev) && prev == toSend) 65 | continue; 66 | 67 | NetworkConnection conn = receiver.connectionToClient; 68 | conn.Send(new RoleSyncInfo(__instance.Hub, toSend, receiver)); 69 | __instance.PreviouslySentRole[receiver.netId] = toSend; 70 | } 71 | 72 | return false; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /CedMod/Addons/Sentinal/Patches/Scp939LungePatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using CedMod.Addons.QuerySystem.WS; 6 | using CommandSystem.Commands.RemoteAdmin; 7 | using HarmonyLib; 8 | using LabApi.Features.Console; 9 | using Mirror; 10 | using Mirror.LiteNetLib4Mirror; 11 | using PlayerRoles.FirstPersonControl; 12 | using PlayerRoles.PlayableScps.Scp939; 13 | using RelativePositioning; 14 | using Utils.Networking; 15 | 16 | namespace CedMod.Addons.Sentinal.Patches 17 | { 18 | [HarmonyPatch(typeof(Scp939LungeAbility), nameof(Scp939LungeAbility.ServerProcessCmd))] 19 | public class Scp939LungePatch 20 | { 21 | public static Dictionary>> LungeTime = new Dictionary>>(); 22 | 23 | public static bool Prefix(NetworkReader reader, Scp939LungeAbility __instance) 24 | { 25 | try 26 | { 27 | if (!LungeTime.ContainsKey(__instance.Owner.netId)) 28 | { 29 | LungeTime[__instance.Owner.netId] = new Dictionary>(); 30 | } 31 | 32 | if (!LungeTime[__instance.Owner.netId].ContainsKey(SentinalBehaviour.UFrames)) 33 | LungeTime[__instance.Owner.netId][SentinalBehaviour.UFrames] = new List<(string position, string state, int ping)>(); 34 | 35 | LungeTime[__instance.Owner.netId][SentinalBehaviour.UFrames].Add((__instance.Owner.GetPosition().ToString(), __instance.State.ToString(), LiteNetLib4MirrorServer.Peers[__instance.Owner.connectionToClient.connectionId].Ping * 2)); 36 | if (__instance.State == Scp939LungeState.Triggered) 37 | { 38 | return true; 39 | } 40 | 41 | reader.ReadRelativePosition(); 42 | reader.ReadReferenceHub(); 43 | reader.ReadRelativePosition(); 44 | return false; 45 | } 46 | catch (Exception e) 47 | { 48 | Logger.Error($"Failed to invoke 939 exploit patch: {e.ToString()}"); 49 | } 50 | 51 | return true; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /CedMod/Addons/Sentinal/Patches/Utilities/RoomCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LabApi.Events.Arguments.ServerEvents; 3 | using LabApi.Features.Console; 4 | using LabApi.Features.Wrappers; 5 | using MapGeneration; 6 | 7 | namespace CedMod.Addons.Sentinal.Patches.Utilities 8 | { 9 | public class RoomCache 10 | { 11 | public static Dictionary> Rooms = new Dictionary>(); 12 | 13 | public static void MapGenerated(MapGeneratedEventArgs ev) 14 | { 15 | Rooms.Clear(); 16 | List toCheck = new List(); 17 | List toCheck2 = new List(); 18 | foreach (var room in RoomIdentifier.AllRoomIdentifiers) 19 | { 20 | toCheck.Clear(); 21 | toCheck2.Clear(); 22 | Rooms[room] = new Dictionary(); 23 | toCheck.AddRange(room.ConnectedRooms); 24 | 25 | int depth = 1; 26 | while (depth < 3) 27 | { 28 | toCheck2.Clear(); 29 | foreach (var check in toCheck) 30 | { 31 | if (Rooms[room].ContainsKey(check)) 32 | continue; 33 | 34 | Rooms[room][check] = depth; 35 | toCheck2.AddRange(check.ConnectedRooms); 36 | } 37 | toCheck.Clear(); 38 | toCheck.AddRange(toCheck2); 39 | depth++; 40 | } 41 | } 42 | } 43 | 44 | public static bool InRange(ReferenceHub plr, ReferenceHub target, int range) 45 | { 46 | var room = Player.Get(plr).Room; 47 | var targetRoom = Player.Get(target).Room; 48 | if (room == null || targetRoom == null || room == targetRoom || !Rooms.TryGetValue(room.Base, out var cache)) 49 | return true; 50 | 51 | if (targetRoom != room && (room.Name == RoomName.HczCheckpointToEntranceZone || targetRoom.Name == RoomName.HczCheckpointToEntranceZone)) //these are not officially connected apparently 52 | return true; 53 | 54 | if (cache.TryGetValue(targetRoom.Base, out var roomRange) && roomRange <= range) 55 | return true; 56 | 57 | return false; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /CedMod/Addons/Sentinal/Patches/VoicePacketPacket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using CedMod.Addons.QuerySystem; 4 | using HarmonyLib; 5 | using InventorySystem; 6 | using InventorySystem.Items.Radio; 7 | using LabApi.Events.Arguments.PlayerEvents; 8 | using LabApi.Events.CustomHandlers; 9 | using LabApi.Features.Console; 10 | using Mirror; 11 | using PlayerRoles; 12 | using PlayerRoles.FirstPersonControl; 13 | using PlayerRoles.Voice; 14 | using UnityEngine; 15 | using VoiceChat; 16 | using VoiceChat.Codec; 17 | using VoiceChat.Networking; 18 | using Logger = LabApi.Features.Console.Logger; 19 | 20 | namespace CedMod.Addons.Sentinal.Patches 21 | { 22 | public class VoiceChatEvents: CustomEventsHandler 23 | { 24 | public override void OnPlayerReceivingVoiceMessage(PlayerReceivingVoiceMessageEventArgs ev) 25 | { 26 | if (CedModMain.Singleton == null || CedModMain.Singleton.Config == null || CedModMain.Singleton.Config.CedMod.DisableFakeSyncing) 27 | return; 28 | 29 | var prevSync = ev.Message.Speaker.roleManager.PreviouslySentRole; 30 | if (prevSync.TryGetValue(ev.Player.NetworkId, out var role) && role.GetTeam() == Team.Dead && ev.Message.Speaker.GetTeam() != Team.Dead && ev.Player.Team != Team.Dead) 31 | { 32 | ev.IsAllowed = false; 33 | } 34 | } 35 | } 36 | 37 | [HarmonyPatch(typeof(VoiceTransceiver), nameof(VoiceTransceiver.ServerReceiveMessage))] 38 | public static class VoicePacketPacket 39 | { 40 | public static Dictionary> PacketsSent = new Dictionary>(); 41 | public static Dictionary Tracker = new Dictionary(); 42 | public static Dictionary OpusDecoders = new Dictionary(); 43 | public static Dictionary Floats = new Dictionary(); 44 | public static Dictionary Radio = new Dictionary(); 45 | public static Dictionary Voice = new Dictionary(); 46 | 47 | public static bool Prefix(NetworkConnection conn, VoiceMessage msg) 48 | { 49 | try 50 | { 51 | if (msg.Speaker == null || conn.identity.netId != msg.Speaker.netId) 52 | return false; 53 | 54 | var plr = CedModPlayer.Get(msg.Speaker); 55 | if (!PacketsSent.ContainsKey(conn.identity.netId)) 56 | { 57 | PacketsSent.Add(conn.identity.netId, new List<(int, float, float)>()); 58 | } 59 | 60 | if (!Tracker.ContainsKey(conn.identity.netId)) 61 | { 62 | if (BanSystem.Authenticating.Contains(msg.Speaker)) //hint is removed by authenticator 63 | ThreadDispatcher.ThreadDispatchQueue.Enqueue(() => 64 | { 65 | if (plr == null || plr.ReferenceHub == null || plr.GameObject == null) 66 | return; 67 | plr.SendHint("Muted: Awaiting CedMod Authentication", 2); 68 | }); 69 | 70 | Tracker.Add(conn.identity.netId, 0); 71 | } 72 | 73 | if (!OpusDecoders.ContainsKey(conn.identity.netId)) 74 | OpusDecoders.Add(conn.identity.netId, new OpusDecoder()); 75 | 76 | if (!Floats.ContainsKey(conn.identity.netId)) 77 | Floats[conn.identity.netId] = new float[480]; 78 | 79 | var len = OpusDecoders[conn.identity.netId].Decode(msg.Data, msg.DataLength, Floats[conn.identity.netId]); 80 | float highest = 0; 81 | float lowest = 0; 82 | foreach (var f in Floats[conn.identity.netId]) 83 | { 84 | if (f <= 0 && f <= lowest) 85 | lowest = f; 86 | 87 | if (f >= 0 && f >= highest) 88 | highest = f; 89 | } 90 | 91 | PacketsSent[conn.identity.netId].Add((len, lowest, highest)); 92 | 93 | if (BanSystem.Authenticating.Contains(msg.Speaker) || lowest <= -6 || highest >= 6 || len != 480) 94 | { 95 | return false; 96 | } 97 | } 98 | catch (Exception e) 99 | { 100 | Logger.Error(e.ToString()); 101 | } 102 | 103 | Voice[conn.identity.netId] = Time.time + 1.5f; 104 | if (msg.Channel == VoiceChatChannel.Radio || msg.Channel == VoiceChatChannel.Intercom) 105 | { 106 | Radio[conn.identity.netId] = Time.time + 1.5f; 107 | } 108 | return true; 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /CedMod/Addons/StaffInfo/MirrorExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LabApi.Features.Wrappers; 3 | using Mirror; 4 | 5 | namespace CedMod.Addons.StaffInfo 6 | { 7 | public static class MirrorExtensions 8 | { 9 | public static void SendFakeDisplayName(this Player player, Player target, string value) 10 | { 11 | NetworkWriterPooled writer = NetworkWriterPool.Get(); 12 | PrepareWriter(writer, player.ReferenceHub.nicknameSync.netIdentity, player.ReferenceHub.nicknameSync, (writer) => 13 | { 14 | writer.WriteULong(16UL); 15 | writer.WriteString(value); 16 | }); 17 | 18 | target.Connection.Send(new EntityStateMessage() 19 | { 20 | netId = player.ReferenceHub.nicknameSync.netId, 21 | payload = writer.ToArraySegment() 22 | }); 23 | 24 | NetworkWriterPool.Return(writer); 25 | } 26 | 27 | public static void SendFakeViewInfo(this Player player, Player target, PlayerInfoArea infoArea) 28 | { 29 | NetworkWriterPooled writer = NetworkWriterPool.Get(); 30 | PrepareWriter(writer, player.ReferenceHub.nicknameSync.netIdentity, player.ReferenceHub.nicknameSync, (writer) => 31 | { 32 | writer.WriteULong(4UL); 33 | writer.WriteInt((int)infoArea); 34 | }); 35 | 36 | target.Connection.Send(new EntityStateMessage() 37 | { 38 | netId = player.ReferenceHub.nicknameSync.netId, 39 | payload = writer.ToArraySegment() 40 | }); 41 | 42 | NetworkWriterPool.Return(writer); 43 | } 44 | 45 | public static void SendFakeCustomInfo(this Player player, Player target, string value) 46 | { 47 | NetworkWriterPooled writer = NetworkWriterPool.Get(); 48 | PrepareWriter(writer, player.ReferenceHub.nicknameSync.netIdentity, player.ReferenceHub.nicknameSync, (writer) => 49 | { 50 | writer.WriteULong(2UL); 51 | writer.WriteString(value); 52 | }); 53 | 54 | target.Connection.Send(new EntityStateMessage() 55 | { 56 | netId = player.ReferenceHub.nicknameSync.netId, 57 | payload = writer.ToArraySegment() 58 | }); 59 | 60 | NetworkWriterPool.Return(writer); 61 | } 62 | 63 | public static void PrepareWriter(NetworkWriter writer, NetworkIdentity identity, NetworkBehaviour behaviour, 64 | Action writeSyncdata) 65 | { 66 | //prepare the writer with the dirtymask 67 | WriteBehaviourMask(writer, identity, behaviour); 68 | 69 | //initial write 70 | int headerPosition = writer.Position; 71 | writer.WriteByte(0); 72 | int contentPosition = writer.Position; 73 | 74 | //serialize deltas as per mirrors packet order 75 | behaviour.SerializeObjectsDelta(writer); 76 | 77 | //write our dirty bit and value 78 | writeSyncdata.Invoke(writer); 79 | 80 | int endPosition = writer.Position; 81 | 82 | //end the packet 83 | writer.Position = headerPosition; 84 | int size = endPosition - contentPosition; 85 | byte safety = (byte)(size & 0xFF); 86 | writer.WriteByte(safety); 87 | writer.Position = endPosition; 88 | } 89 | 90 | public static void WriteBehaviourMask(NetworkWriter writer, NetworkIdentity identity, NetworkBehaviour behaviour) 91 | { 92 | var netId = behaviour.netIdentity; 93 | var behaviourIndex = netId.NetworkBehaviours.IndexOf(behaviour); 94 | 95 | ulong mask = 0; 96 | mask |= 1UL << behaviourIndex; 97 | Compression.CompressVarUInt(writer, mask); 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/AudioHeartBeat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace CedMod.ApiModals 5 | { 6 | public class AudioHeartbeatRequest 7 | { 8 | public List Players { get; set; } 9 | } 10 | 11 | public class CedModAudioPlayer 12 | { 13 | public int PlayerId { get; set; } 14 | public List Queue { get; set; } 15 | public float Volume { get; set; } 16 | public bool LoopList { get; set; } 17 | public bool Continue { get; set; } 18 | public bool Shuffle { get; set; } 19 | public TimeSpan CurrentSpan { get; set; } 20 | public TimeSpan TotalTime { get; set; } 21 | public bool IsCedModPlayer { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/AutoSlPermsSlRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CedMod.ApiModals 4 | { 5 | public class AutoSlPermsSlRequest 6 | { 7 | public List PermissionEntries { get; set; } = new List(); 8 | public List MembersList { get; set; } = new List(); 9 | public List DefaultPermissions { get; set; } = new List(); 10 | } 11 | 12 | public class AutoSlPermissionMembers 13 | { 14 | public string UserId { get; set; } 15 | public string Group { get; set; } 16 | public bool ReservedSlot { get; set; } 17 | } 18 | 19 | public class SLPermissionEntry 20 | { 21 | public string Name { get; set; } 22 | public int KickPower { get; set; } 23 | public int RequiredKickPower { get; set; } 24 | public bool Hidden { get; set; } 25 | public bool Cover { get; set; } 26 | public bool ReservedSlot { get; set; } 27 | public string BadgeText { get; set; } 28 | public string BadgeColor { get; set; } 29 | public ulong RoleId { get; set; } 30 | public PlayerPermissions Permissions { get; set; } 31 | public List ExiledPermissions { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/CedModVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace CedMod.ApiModals 5 | { 6 | public class CedModVersion 7 | { 8 | public int Id { get; set; } 9 | public Guid CedModVersionIdentifier { get; set; } 10 | public string VersionString { get; set; } 11 | public string VersionCommit { get; set; } 12 | public string ReleaseDownloadUser { get; set; } 13 | public string FileHash { get; set; } 14 | public string S3Path { get; set; } 15 | public List SupportedExiledVersions { get; set; } 16 | public DateTime Released { get; set; } 17 | public VersionType VersionType { get; set; } 18 | public List CanUpgrade { get; set; } 19 | } 20 | 21 | public class CedModExiledVersionAssociation 22 | { 23 | public int Id { get; set; } 24 | public int CedModVersionId { get; set; } 25 | public CedModVersion CedModVersion { get; set; } 26 | 27 | public int ExiledVersionId { get; set; } 28 | public ExiledVersion ExiledVersion { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/EventModal.cs: -------------------------------------------------------------------------------- 1 | namespace CedMod.ApiModals 2 | { 3 | public class EventModal 4 | { 5 | public string Name { get; set; } 6 | public string Author { get; set; } 7 | public string Description { get; set; } 8 | public string Prefix { get; set; } 9 | public bool Active { get; set; } 10 | public int QueuePos { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/ExiledVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace CedMod.ApiModals 5 | { 6 | public class ExiledVersion 7 | { 8 | public int Id { get; set; } 9 | public string VersionString { get; set; } 10 | public List SupportedSCPSLVersions { get; set; } 11 | public List SupportedCedModVersions { get; set; } 12 | public DateTime Released { get; set; } 13 | public VersionType VersionType { get; set; } 14 | } 15 | 16 | public class SCPSLExiledVersionAssociation 17 | { 18 | public int Id { get; set; } 19 | public int ScpSlVersionId { get; set; } 20 | public SCPSLVersion ScpSlVersion { get; set; } 21 | 22 | public int ExiledVersionId { get; set; } 23 | public ExiledVersion ExiledVersion { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/HeartbeatRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CedMod.ApiModals 4 | { 5 | public class HeartbeatRequest 6 | { 7 | public List Players { get; set; } //is only sent if playerstats are enabled 8 | public List Events { get; set; } //is only sent if events are enabled 9 | public string PluginVersion { get; set; } 10 | public string PluginCommitHash { get; set; } 11 | public bool UpdateStats { get; set; } 12 | public bool TrackingEnabled { get; set; } 13 | public string ExiledVersion { get; set; } 14 | public string ScpSlVersion { get; set; } 15 | public string FileHash { get; set; } 16 | public string CedModVersionIdentifier { get; set; } 17 | public string KeyHash { get; set; } 18 | public bool IsVerified { get; set; } 19 | public double RealTps { get; set; } 20 | public double Tps { get; set; } 21 | public double FrameTime { get; set; } 22 | public short TargetTps { get; set; } 23 | public int CurrentSeed { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/HelloMessage.cs: -------------------------------------------------------------------------------- 1 | namespace CedMod.ApiModals 2 | { 3 | public class HelloMessage 4 | { 5 | public bool SendStats { get; set; } 6 | public bool SendEvents { get; set; } 7 | public bool ExpEnabled { get; set; } 8 | public string Identity { get; set; } 9 | public bool SentinalPositions { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/IngameUserPreferences.cs: -------------------------------------------------------------------------------- 1 | namespace CedMod.ApiModals 2 | { 3 | public class IngameUserPreferences 4 | { 5 | public bool ShowUserIdsInBroadcasts { get; set; } = false; 6 | public bool ShowReportsInRemoteAdmin { get; set; } 7 | public bool ShowWatchListUsersInRemoteAdmin { get; set; } = true; 8 | public bool ShowModerationInfoSpectator { get; set; } 9 | public bool ShowModerationInfoOverwatch { get; set; } 10 | public bool ShowWatchlistInStaffInfo { get; set; } 11 | public bool StreamerMode { get; set; } = false; 12 | } 13 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/PlayerObject.cs: -------------------------------------------------------------------------------- 1 | using PlayerRoles; 2 | 3 | namespace CedMod.ApiModals 4 | { 5 | public class PlayerObject 6 | { 7 | public string Name { get; set; } 8 | public bool Staff { get; set; } 9 | public bool DoNotTrack { get; set; } 10 | public bool HashedUserId { get; set; } 11 | public string UserId { get; set; } 12 | public string CedModToken { get; set; } 13 | public string CedModSignature { get; set; } 14 | public int PlayerId { get; set; } 15 | public RoleTypeId RoleType { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/SCPSLVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace CedMod.ApiModals 5 | { 6 | public class SCPSLVersion 7 | { 8 | public int Id { get; set; } 9 | public string VersionString { get; set; } 10 | public List SupportedExiledVersions { get; set; } 11 | public DateTime Released { get; set; } 12 | public VersionType VersionType { get; set; } 13 | } 14 | 15 | public enum VersionType 16 | { 17 | Release, 18 | PublicBeta, 19 | PrivateRelease, 20 | } 21 | } -------------------------------------------------------------------------------- /CedMod/ApiModals/ServerPreferenceModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CedMod.ApiModals 4 | { 5 | public class ServerPreferenceModel 6 | { 7 | public long ServerId { get; set; } 8 | public List BanListReadBans { get; set; } = new List(); 9 | public List BanListWriteBans { get; set; } = new List(); 10 | public List BanListReadMutes { get; set; } = new List(); 11 | public List BanListWriteMutes { get; set; } = new List(); 12 | public List BanListReadWarns { get; set; } = new List(); 13 | public List BanListWriteWarns { get; set; } = new List(); 14 | } 15 | 16 | public class BanList 17 | { 18 | public long Id { get; set; } 19 | public bool IsMaster { get; set; } 20 | public bool IsDefaultPanel { get; set; } 21 | public string ServersWriteBans { get; set; } = ""; 22 | public string ServersReadBans { get; set; } = ""; 23 | public string ServersWriteMutes { get; set; } = ""; 24 | public string ServersReadMutes { get; set; } = ""; 25 | public string ServersWriteWarns { get; set; } = ""; 26 | public string ServersReadWarns { get; set; } = ""; 27 | public string Data { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /CedMod/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /CedMod/CedModPlayer.cs: -------------------------------------------------------------------------------- 1 | using CentralAuth; 2 | using LabApi.Features.Wrappers; 3 | 4 | namespace CedMod 5 | { 6 | public static class CedModPlayer 7 | { 8 | public static Player Get(string userid) 9 | { 10 | // Check id 11 | if (int.TryParse(userid, out int id)) 12 | return Player.Get(id); 13 | 14 | // Check Userid 15 | if (userid.EndsWith("@steam") || userid.EndsWith("@discord") || userid.EndsWith("@northwood") || userid.EndsWith("@patreon") || (userid.StartsWith("ID_Offline") && !PlayerAuthenticationManager.OnlineMode)) 16 | { 17 | foreach (var hub in ReferenceHub.AllHubs) 18 | { 19 | if (hub.authManager.UserId == userid) 20 | return Player.Get(hub); 21 | } 22 | } 23 | else // Check username 24 | { 25 | var hub = processHubUsername(userid); // try getting a hub with no spaces 26 | 27 | // if no hub is found, try again but replace any '_' with spaces 28 | if (hub == null) // This Allows mods to select a user with a space in their name. 29 | hub = processHubUsername(userid.Replace("_", " ")); 30 | 31 | if (hub == null) // if nobody is found after this, return null 32 | return null; 33 | 34 | return Player.Get(hub); 35 | } 36 | 37 | return null; 38 | } 39 | 40 | private static ReferenceHub processHubUsername(string userid) 41 | { 42 | int lastnameDifference = 31; 43 | string firstString = userid.ToLower(); 44 | 45 | foreach (ReferenceHub player in ReferenceHub.AllHubs) 46 | { 47 | if (player.nicknameSync.Network_myNickSync == null) 48 | continue; 49 | 50 | if (!player.nicknameSync.Network_myNickSync.ToLower().Contains(userid.ToLower())) 51 | continue; 52 | 53 | string secondString = player.nicknameSync.Network_myNickSync.ToLower(); 54 | 55 | int nameDifference = secondString.Length - firstString.Length; 56 | if (nameDifference < lastnameDifference) 57 | { 58 | lastnameDifference = nameDifference; 59 | return player; 60 | } 61 | } 62 | return null; 63 | } 64 | 65 | public static Player Get(int PlayerId) 66 | { 67 | foreach (var hub in ReferenceHub.AllHubs) 68 | { 69 | if (hub.PlayerId == PlayerId) 70 | return Player.Get(hub); 71 | } 72 | 73 | return null; 74 | } 75 | 76 | public static Player Get(ReferenceHub refhub) 77 | { 78 | return Player.Get(refhub); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /CedMod/Commands/CedModSetupCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net.Http; 5 | using CedMod.Addons.QuerySystem; 6 | using CommandSystem; 7 | using Exiled.Loader; 8 | using MEC; 9 | using Newtonsoft.Json; 10 | using RoundRestarting; 11 | using Serialization; 12 | 13 | namespace CedMod.Commands 14 | { 15 | [CommandHandler(typeof(GameConsoleCommandHandler))] 16 | public class CedModsetupCommand : ICommand 17 | { 18 | public string Command { get; } = "setupcedmod"; 19 | 20 | public string[] Aliases { get; } = new string[] 21 | { 22 | }; 23 | 24 | public string Description { get; } = "Automatically configure cedmod using the token given by the Admin Panel or CommunityManagementPanel"; 25 | internal static bool isEnabled; 26 | internal static CoroutineHandle CoroutineHandle; 27 | 28 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 29 | { 30 | string key = arguments.At(0); 31 | 32 | using (HttpClient client = new HttpClient()) 33 | { 34 | client.DefaultRequestHeaders.Add("X-ServerIp", ServerConsole.Ip); 35 | HttpResponseMessage panelResponse = null; 36 | if (arguments.Count >= 2) 37 | { 38 | panelResponse = client.GetAsync($"http{(QuerySystem.UseSSL ? "s" : "")}://{QuerySystem.CurrentMaster}/Api/v3/AutomaticSetup?key={key}&token={arguments.At(1)}").Result; 39 | } 40 | else 41 | { 42 | panelResponse = client.GetAsync($"http{(QuerySystem.UseSSL ? "s" : "")}://{QuerySystem.CurrentMaster}/Api/v3/AutomaticSetup?key={key}").Result; 43 | } 44 | string result = panelResponse.Content.ReadAsStringAsync().Result; 45 | if (!panelResponse.IsSuccessStatusCode) 46 | { 47 | response = result; 48 | return false; 49 | } 50 | 51 | Dictionary PanelResponse = JsonConvert.DeserializeObject>(result); 52 | CedModMain.Singleton.Config.CedMod.CedModApiKey = key; 53 | QuerySystem.QuerySystemKey = PanelResponse["QueryKey"]; 54 | #if !EXILED 55 | File.WriteAllText(Path.Combine(CedModMain.PluginConfigFolder, "config.yml"), YamlParser.Serializer.Serialize(CedModMain.Singleton.Config)); 56 | #else 57 | var pluginConfigs = ConfigManager.LoadSorted(ConfigManager.Read()); 58 | Config cedModCnf = pluginConfigs[CedModMain.Singleton.Prefix] as Config; 59 | cedModCnf.CedMod.CedModApiKey = key; 60 | ConfigManager.Save(pluginConfigs); 61 | #endif 62 | response = $"CedMod has been setup, using the identifier: {PanelResponse["QueryIdentifier"]}\nThe server will now be restarted,"; 63 | ServerStatic.StopNextRound = ServerStatic.NextRoundAction.Restart; 64 | RoundRestart.ChangeLevel(true); 65 | } 66 | return true; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /CedMod/Commands/CheckForUpdatesCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using CedMod.Components; 4 | using CommandSystem; 5 | using LabApi.Features.Console; 6 | using Object = UnityEngine.Object; 7 | 8 | namespace CedMod.Commands 9 | { 10 | [CommandHandler(typeof(GameConsoleCommandHandler))] 11 | public class CheckForUpdatesCommand : ICommand 12 | { 13 | public string Command { get; } = "checkforcedmodupdate"; 14 | 15 | public string[] Aliases { get; } = new string[] 16 | { 17 | }; 18 | 19 | public string Description { get; } = "Checks if there are any updates available for your CedMod Version"; 20 | 21 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 22 | { 23 | AutoUpdater updater = Object.FindObjectOfType(); 24 | if (!CedModMain.Singleton.Config.CedMod.AutoUpdate) 25 | { 26 | Task.Run(() => 27 | { 28 | var data = updater.CheckForUpdates(true); 29 | if (data != null) 30 | Logger.Info($"As AutoUpdate is disabled in your CedMod plugin configuration this update will not be install automatically, please run the installcedmodupdate command to install this update"); 31 | }); 32 | response = ""; 33 | return true; 34 | } 35 | 36 | updater.ForceLog = true; 37 | updater.TimePassedCheck = 300; 38 | response = "Update check requested to the UpdateService"; 39 | return true; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /CedMod/Commands/Dialog/all.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | using LabApi.Features.Wrappers; 6 | 7 | namespace CedMod.Commands.Dialog 8 | { 9 | public class DialogAllCommand : ICommand 10 | { 11 | public string Command { get; } = "all"; 12 | 13 | public string[] Aliases { get; } = new string[] 14 | { 15 | 16 | }; 17 | 18 | public string Description { get; } = "makes a popup appear for all players"; 19 | 20 | public bool Execute(ArraySegment arguments, ICommandSender sender, 21 | out string response) 22 | { 23 | if (!sender.HasPermissions("cedmod.dialog")) 24 | { 25 | response = "no permission"; 26 | return false; 27 | } 28 | if (arguments.IsEmpty()) 29 | { 30 | response = "Missing argument "; 31 | return false; 32 | } 33 | 34 | string msg = arguments.Skip(0).Aggregate((current, n) => current + " " + n); 35 | foreach (Player ply in Player.List) 36 | { 37 | ply.SendConsoleMessage("[REPORTING] " + msg + " Press ESC to close", "green"); 38 | } 39 | 40 | response = "Done"; 41 | return true; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /CedMod/Commands/Dialog/userid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CommandSystem; 4 | using LabApi.Features.Permissions; 5 | using LabApi.Features.Wrappers; 6 | 7 | namespace CedMod.Commands.Dialog 8 | { 9 | public class DialogUseridCommand : ICommand 10 | { 11 | public string Command { get; } = "userid"; 12 | 13 | public string[] Aliases { get; } = { 14 | "playerid" 15 | }; 16 | 17 | public string Description { get; } = "makes a popup appear to a player with a specific userid"; 18 | 19 | public bool Execute(ArraySegment arguments, ICommandSender sender, 20 | out string response) 21 | { 22 | if (!sender.HasPermissions("cedmod.dialog")) 23 | { 24 | response = "no permission"; 25 | return false; 26 | } 27 | if (arguments.Count >= 2) 28 | { 29 | Player player; 30 | string msg = arguments.Skip(1).Aggregate((current, n) => current + " " + n); 31 | 32 | player = CedModPlayer.Get(arguments.At(0)); 33 | if (player == null) 34 | { 35 | response = "Could not find player with the specified userid"; 36 | return false; 37 | } 38 | player.SendConsoleMessage("[REPORTING] " + msg + " Press ESC to close", "green"); 39 | response = "Done"; 40 | return true; 41 | } 42 | 43 | response = "missing arguments: usage userid message"; 44 | return false; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /CedMod/Commands/DialogBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CedMod.Commands.Dialog; 3 | using CommandSystem; 4 | 5 | namespace CedMod.Commands 6 | { 7 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 8 | public class DiaglogParentCommand : ParentCommand 9 | { 10 | public override string Command => "popupbox"; 11 | public override string[] Aliases { get; } = new string[] 12 | { 13 | "dialog" 14 | }; 15 | public override string Description => "makes a popup appear on a set player(s)"; 16 | 17 | public DiaglogParentCommand() => LoadGeneratedCommands(); 18 | 19 | public override void LoadGeneratedCommands() 20 | { 21 | RegisterCommand(new DialogAllCommand()); 22 | RegisterCommand(new DialogUseridCommand()); 23 | } 24 | 25 | protected override bool ExecuteParent(ArraySegment arguments, ICommandSender sender, out string response) 26 | { 27 | response = "Please specify a valid subcommand!, options are, all, userid, playerid"; 28 | return false; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /CedMod/Commands/FFADisable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandSystem; 3 | using LabApi.Features.Permissions; 4 | 5 | #if !EXILED 6 | 7 | #else 8 | using Exiled.Permissions.Extensions; 9 | #endif 10 | 11 | namespace CedMod.Commands 12 | { 13 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 14 | public class FfaDisableCommand : ICommand 15 | { 16 | public string Command { get; } = "disableffa"; 17 | 18 | public string[] Aliases { get; } = new string[] 19 | { 20 | }; 21 | 22 | public string Description { get; } = "Disable/Enable FFA for the rest of the round"; 23 | public bool Execute(ArraySegment arguments, ICommandSender sender, 24 | out string response) 25 | { 26 | if (!sender.HasPermissions("cedmod.ffadisable")) 27 | { 28 | response = "no permission"; 29 | return false; 30 | } 31 | FriendlyFireAutoban.AdminDisabled = !FriendlyFireAutoban.AdminDisabled; 32 | response = FriendlyFireAutoban.AdminDisabled ? "FFA is now Disabled FFA wil reset at round end unless FFA is disabled" : "FFA is now Enabled FFA wil reset at round end unless FFA is disabled"; 33 | return true; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /CedMod/Commands/InstallUpdateCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using CedMod.Components; 4 | using CommandSystem; 5 | using LabApi.Features.Console; 6 | using Object = UnityEngine.Object; 7 | 8 | namespace CedMod.Commands 9 | { 10 | [CommandHandler(typeof(GameConsoleCommandHandler))] 11 | public class InstallUpdateCommand : ICommand 12 | { 13 | public string Command { get; } = "installcedmodupdate"; 14 | 15 | public string[] Aliases { get; } = new string[] 16 | { 17 | }; 18 | 19 | public string Description { get; } = "Installs the pending CedMod update (if any) (If an update is pending, the server will be restarted immediately to install the update)"; 20 | 21 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 22 | { 23 | AutoUpdater updater = Object.FindObjectOfType(); 24 | if (!CedModMain.Singleton.Config.CedMod.AutoUpdate) 25 | { 26 | Task.Run(async () => 27 | { 28 | var data = await updater.CheckForUpdates(true); 29 | if (data == null) 30 | Logger.Error($"There are no updates pending for this version."); 31 | else 32 | { 33 | AutoUpdater.Pending = data; 34 | await updater.InstallUpdate(); 35 | } 36 | }); 37 | response = ""; 38 | return true; 39 | } 40 | if (AutoUpdater.Pending == null) 41 | { 42 | response = "There are no updates pending for this server, please run the checkforcedmodupdate command to check for updates. (Updates are also checked every 5 minutes)"; 43 | return false; 44 | } 45 | 46 | Task.Run(async () => 47 | { 48 | var data = await updater.CheckForUpdates(true); 49 | if (data == null) 50 | Logger.Error($"There are no updates pending for this version."); 51 | else 52 | { 53 | AutoUpdater.Pending = data; 54 | await updater.InstallUpdate(); 55 | } 56 | }); 57 | response = "Update Install requested to the UpdateService"; 58 | return true; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /CedMod/Commands/LightColor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandSystem; 3 | using LabApi.Features.Permissions; 4 | #if !EXILED 5 | #else 6 | using Exiled.Permissions.Extensions; 7 | #endif 8 | using UnityEngine; 9 | 10 | namespace CedMod.Commands 11 | { 12 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 13 | public class LightColor : ICommand 14 | { 15 | public string Command { get; } = "lightcolor"; 16 | 17 | public string[] Aliases { get; } = new string[] 18 | { 19 | }; 20 | 21 | public string Description { get; } = "Change the color of all lights."; 22 | public bool Execute(ArraySegment arguments, ICommandSender sender, 23 | out string response) 24 | { 25 | if (!sender.HasPermissions("cedmod.colors")) 26 | { 27 | response = "no permission"; 28 | return false; 29 | } 30 | if (arguments.IsEmpty()) 31 | { 32 | response = "You must specify colors (255, 255, 255)."; 33 | return false; 34 | } 35 | 36 | if (!float.TryParse(arguments.At(0), out float r)) 37 | { 38 | response = "R must be a float."; 39 | return false; 40 | } 41 | 42 | if (!float.TryParse(arguments.At(1), out float g)) 43 | { 44 | response = "G must be a float."; 45 | return false; 46 | } 47 | 48 | if (!float.TryParse(arguments.At(2), out float b)) 49 | { 50 | response = "B must be a float."; 51 | return false; 52 | } 53 | 54 | Color lightColors = new Color(r, g, b); 55 | foreach (RoomLightController flc in RoomLightController.Instances) 56 | { 57 | flc.NetworkOverrideColor = lightColors; 58 | } 59 | 60 | response = "Light intensity set to " + lightColors; 61 | return true; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /CedMod/Commands/RainbowLights.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandSystem; 3 | using LabApi.Features.Permissions; 4 | #if !EXILED 5 | #else 6 | using Exiled.Permissions.Extensions; 7 | #endif 8 | using Object = UnityEngine.Object; 9 | 10 | namespace CedMod.Commands 11 | { 12 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 13 | public class RainbowLightsCommand : ICommand 14 | { 15 | public string Command { get; } = "rainbowlights"; 16 | 17 | public string[] Aliases { get; } = new string[] 18 | { 19 | }; 20 | 21 | public string Description { get; } = "yes"; 22 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 23 | { 24 | if (!sender.HasPermissions("cedmod.rainbowlights")) 25 | { 26 | response = "no permission"; 27 | return false; 28 | } 29 | 30 | if (arguments.Count < 1) 31 | { 32 | response = "missing argument"; 33 | return false; 34 | } 35 | 36 | bool state; 37 | if (!bool.TryParse(arguments.At(0), out state)) 38 | { 39 | response = "Please specify the state"; 40 | return false; 41 | } 42 | 43 | 44 | foreach(var light in RoomLightController.Instances) 45 | { 46 | if (state) 47 | { 48 | if (light.TryGetComponent(out RainbowLight _)) 49 | { 50 | response = "Please remove rainbowlights before trying to re enable it"; 51 | return false; 52 | } 53 | light.gameObject.AddComponent(); 54 | } 55 | else 56 | { 57 | if (light.TryGetComponent(out RainbowLight rainbowLight)) 58 | { 59 | Object.Destroy(rainbowLight); 60 | } 61 | } 62 | } 63 | 64 | response = "Done"; 65 | return true; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /CedMod/Commands/Redirect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandSystem; 3 | using LabApi.Features.Permissions; 4 | using Mirror; 5 | #if !EXILED 6 | #else 7 | using Exiled.Permissions.Extensions; 8 | #endif 9 | using RoundRestarting; 10 | 11 | namespace CedMod.Commands 12 | { 13 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 14 | public class RedirectCommand : ICommand 15 | { 16 | public string Command { get; } = "sendplayer"; 17 | 18 | public string[] Aliases { get; } = new string[] 19 | { 20 | }; 21 | 22 | public string Description { get; } = "redirects ALL players to the specified port"; 23 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 24 | { 25 | if (!sender.HasPermissions("cedmod.redirect")) 26 | { 27 | response = "no permission"; 28 | return false; 29 | } 30 | if (arguments.IsEmpty()) 31 | { 32 | response = "you must specify a port"; 33 | return false; 34 | } 35 | NetworkServer.SendToAll(new RoundRestartMessage(RoundRestartType.RedirectRestart, 1f, ushort.Parse(arguments.At(0)), true, false)); 36 | response = "redirecting"; 37 | return true; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /CedMod/Commands/WarnCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | using CedMod.Addons.QuerySystem; 8 | using CedMod.Addons.QuerySystem.WS; 9 | using CedMod.Addons.StaffInfo; 10 | using CommandSystem; 11 | using LabApi.Features.Wrappers; 12 | using Newtonsoft.Json; 13 | using RemoteAdmin; 14 | using Utils; 15 | using Utils.NonAllocLINQ; 16 | 17 | namespace CedMod.Commands 18 | { 19 | [CommandHandler(typeof(RemoteAdminCommandHandler))] 20 | public class WarnCommand : ICommand, IUsageProvider 21 | { 22 | public string Command { get; } = "warn"; 23 | 24 | public string[] Aliases { get; } = new string[] 25 | { 26 | "addwarning", 27 | "addwarn", 28 | "issuewarn", 29 | "issuewarning" 30 | }; 31 | 32 | public string Description { get; } = "Warns a player, Warn reason can be multiple words."; 33 | 34 | public string[] Usage { get; } = new string[] 35 | { 36 | "%player%", 37 | "%reason%" 38 | }; 39 | 40 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) 41 | { 42 | if (arguments.Count <= 1) 43 | { 44 | response = "Missing arguments, warn \nReason can be multiple words"; 45 | return false; 46 | } 47 | 48 | var plrs = RAUtils.ProcessPlayerIdOrNamesList(arguments, 0, out var newgArs); 49 | 50 | string reason = arguments.Skip(1).Aggregate((current, n) => current + " " + n); 51 | string senderId = ""; 52 | 53 | if (sender is PlayerCommandSender commandSender) 54 | senderId = commandSender.SenderId; 55 | 56 | if (sender is CmSender queryCommandSender) 57 | senderId = queryCommandSender.SenderId; 58 | 59 | Task.Run(async () => 60 | { 61 | foreach (var plr in plrs) 62 | { 63 | try 64 | { 65 | using (HttpClient client = new HttpClient()) 66 | { 67 | client.DefaultRequestHeaders.Add("X-ServerIp", ServerConsole.Ip); 68 | await VerificationChallenge.AwaitVerification(); 69 | var response = await client.PostAsync($"http{(QuerySystem.UseSSL ? "s" : "")}://" + QuerySystem.CurrentMaster + $"/Api/v3/Punishment/IssueWarn/{QuerySystem.QuerySystemKey}?userId={plr.authManager.UserId}&issuer={senderId}", new StringContent(JsonConvert.SerializeObject(new Dictionary { { "Reason", reason } }))); 70 | var responseString = await response.Content.ReadAsStringAsync(); 71 | if (response.StatusCode == HttpStatusCode.OK) 72 | { 73 | ThreadDispatcher.ThreadDispatchQueue.Enqueue(() => 74 | { 75 | sender.Respond(responseString, true); 76 | if (CedModMain.Singleton.Config.QuerySystem.StaffInfoSystem) 77 | { 78 | StaffInfoHandler.StaffData.ForEach(s => s.Value.Remove(plr.authManager.UserId)); 79 | StaffInfoHandler.Requested.ForEach(s => s.Value.Remove(plr.authManager.UserId)); 80 | StaffInfoHandler.Singleton.RequestInfo(Player.Get(sender), Player.Get(plr)); 81 | } 82 | }); 83 | } 84 | else 85 | { 86 | ThreadDispatcher.ThreadDispatchQueue.Enqueue(() => { sender.Respond($"{response.StatusCode} - {responseString}"); }); 87 | } 88 | } 89 | } 90 | catch (Exception e) 91 | { 92 | Console.WriteLine(e); 93 | ThreadDispatcher.ThreadDispatchQueue.Enqueue(() => { sender.Respond(e.ToString()); }); 94 | } 95 | } 96 | }); 97 | 98 | response = "Attempting to issue warning, please wait..."; 99 | return true; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /CedMod/Config.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using CedMod.Addons.Events; 3 | using CedMod.Addons.QuerySystem; 4 | using Exiled.API.Interfaces; 5 | 6 | namespace CedMod 7 | { 8 | 9 | #if EXILED 10 | public sealed class Config : IConfig 11 | #else 12 | public sealed class Config 13 | #endif 14 | { 15 | #if EXILED 16 | [Description("Indicates whether the plugin is enabled or not")] 17 | public bool IsEnabled { get; set; } = true; 18 | #endif 19 | 20 | public bool Debug { get; set; } = false; 21 | 22 | public CedModConfig CedMod { get; set; } = new CedModConfig(); 23 | public QueryConfig QuerySystem { get; set; } = new QueryConfig(); 24 | public EventsConfig EventManager { get; set; } = new EventsConfig(); 25 | } 26 | } -------------------------------------------------------------------------------- /CedMod/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | System.Reactive 6 | System.Threading.Channels 7 | Newtonsoft.Json 8 | System.ValueTuple 9 | System.Data 10 | System.Threading.Tasks.Extensions 11 | NVorbis 12 | SCPSLAudioApi 13 | 0Harmony 14 | System.Memory 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CedMod/Handlers/Player.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using CedMod.Addons.Sentinal.Patches; 4 | using LabApi.Events.Arguments.PlayerEvents; 5 | using LabApi.Events.CustomHandlers; 6 | using MEC; 7 | 8 | namespace CedMod.Handlers 9 | { 10 | public class Player: CustomEventsHandler 11 | { 12 | public override void OnPlayerJoined(PlayerJoinedEventArgs ev) 13 | { 14 | Task.Run(async () => { await BanSystem.HandleJoin(ev.Player); }); 15 | Timing.RunCoroutine(Name(ev.Player)); 16 | } 17 | 18 | public override void OnPlayerLeft(PlayerLeftEventArgs ev) 19 | { 20 | VoicePacketPacket.Floats.Remove(ev.Player.ReferenceHub.netId); 21 | VoicePacketPacket.OpusDecoders.Remove(ev.Player.ReferenceHub.netId); 22 | } 23 | 24 | public IEnumerator Name(LabApi.Features.Wrappers.Player player) 25 | { 26 | foreach (var pp in LabApi.Features.Wrappers.Player.List) 27 | { 28 | if (pp.UserId == player.UserId) 29 | yield break; 30 | if (CedModMain.Singleton.Config.CedMod.KickSameName) 31 | { 32 | if (pp.Nickname == player.Nickname) 33 | { 34 | if (player.ReferenceHub.serverRoles.RemoteAdmin && !pp.ReferenceHub.serverRoles.RemoteAdmin) 35 | { 36 | pp.Kick("You have been kicked by a plugin: \n Please change your name to something unique (A staff member joined with your name)"); 37 | yield break; 38 | } 39 | else if (pp.UserId != player.UserId) 40 | { 41 | player.Kick("You have been kicked by a plugin: \n Please change your name to something unique (there is already someone with your name)"); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | public override void OnPlayerDying(PlayerDyingEventArgs ev) 49 | { 50 | if (ev.Player == null || ev.Attacker == null) 51 | return; 52 | FriendlyFireAutoban.HandleKill(ev.Player, ev.Attacker, ev.DamageHandler); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /CedMod/Handlers/Server.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using CedMod.Addons.Audio; 4 | using CedMod.Addons.Sentinal; 5 | using CedMod.Addons.Sentinal.Patches; 6 | using CedMod.Components; 7 | using LabApi.Events.CustomHandlers; 8 | using Mirror; 9 | 10 | namespace CedMod.Handlers 11 | { 12 | public class Server: CustomEventsHandler 13 | { 14 | public static Dictionary reported = new Dictionary(); 15 | 16 | public override void OnServerRoundRestarted() 17 | { 18 | SentinalBehaviour.GunshotSource.Clear(); 19 | SentinalBehaviour.Stalking106.Clear(); 20 | Scp939LungePatch.LungeTime.Clear(); 21 | FriendlyFireAutoban.Teamkillers.Clear(); 22 | FriendlyFireAutoban.AdminDisabled = false; 23 | foreach (var fake in AudioCommand.FakeConnections) 24 | { 25 | NetworkServer.Destroy(fake.Value.gameObject); 26 | } 27 | AudioCommand.FakeConnections.Clear(); 28 | AudioCommand.FakeConnectionsIds.Clear(); 29 | RemoteAdminModificationHandler.IngameUserPreferencesMap.Clear(); 30 | RemoteAdminModificationHandler.Singleton.Requesting.Clear(); 31 | Task.Run(() => 32 | { 33 | lock (BanSystem.CachedStates) 34 | { 35 | BanSystem.CachedStates.Clear(); 36 | } 37 | }); 38 | BanSystem.Authenticating.Clear(); 39 | VoicePacketPacket.Floats.Clear(); 40 | VoicePacketPacket.OpusDecoders.Clear(); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /CedMod/Patches/BanPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using HarmonyLib; 4 | using LabApi.Features.Console; 5 | #if EXILED 6 | using Exiled.Events.EventArgs.Player; 7 | using Player = Exiled.API.Features.Player; 8 | #endif 9 | 10 | namespace CedMod.Patches 11 | { 12 | [HarmonyPatch(typeof(BanPlayer), nameof(BanPlayer.BanUser), new Type[] {typeof(ReferenceHub), typeof(ReferenceHub), typeof(string), typeof(long)})] 13 | public static class BanPatch 14 | { 15 | public static bool Prefix(ReferenceHub target, ReferenceHub issuer, string reason, long duration) 16 | { 17 | try 18 | { 19 | Logger.Info($"MainGame ban patch: banning user. {duration} {reason} {issuer}"); 20 | #if EXILED 21 | var exiledEvent = new BannedEventArgs(Player.Get(target), Player.Get(issuer), new BanDetails() 22 | { 23 | Expires = DateTime.Now.AddSeconds(duration).Ticks, 24 | IssuanceTime = DateTime.Now.Ticks, 25 | Id = target.authManager.UserId, 26 | Issuer = issuer.LoggedNameFromRefHub(), 27 | OriginalName = target.nicknameSync.Network_myNickSync, 28 | Reason = reason 29 | }, BanHandler.BanType.UserId, true); 30 | 31 | Exiled.Events.Handlers.Player.OnBanned(exiledEvent); 32 | #endif 33 | new Thread(() => 34 | { 35 | try 36 | { 37 | lock (BanSystem.Banlock) 38 | { 39 | API.Ban(CedModPlayer.Get(target), duration, issuer.LoggedNameFromRefHub(), reason).Wait(); 40 | } 41 | } 42 | catch (Exception ex) 43 | { 44 | Logger.Error($"MainGame ban patch failed {ex}"); 45 | } 46 | }).Start(); 47 | } 48 | catch (Exception ex) 49 | { 50 | Logger.Error($"MainGame ban patch failed {ex}"); 51 | } 52 | 53 | return false; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /CedMod/Patches/ExternalLookupPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using CedMod.Components; 5 | using CommandSystem; 6 | using CommandSystem.Commands.RemoteAdmin; 7 | using HarmonyLib; 8 | using MEC; 9 | using RemoteAdmin; 10 | 11 | namespace CedMod.Patches 12 | { 13 | [HarmonyPatch(typeof(ExternalLookupCommand), nameof(ExternalLookupCommand.Execute))] 14 | public static class ExternalLookupCommandPatch 15 | { 16 | public static bool Prefix(ExternalLookupCommand __instance, bool __result, ArraySegment arguments, ICommandSender sender, out string response) 17 | { 18 | try 19 | { 20 | if (arguments.Count == 0) 21 | { 22 | response = ""; 23 | return true; 24 | } 25 | if (arguments.At(0) == "-1") 26 | { 27 | response = ""; 28 | Timing.RunCoroutine(RaPlayerCoRoutine(__instance, sender as CommandSender, arguments)); 29 | return false; 30 | } 31 | else if (arguments.At(0) == "-2") 32 | { 33 | response = ""; 34 | Timing.RunCoroutine(RaPlayerCoRoutine(__instance, sender as CommandSender, arguments)); 35 | return false; 36 | } 37 | else 38 | { 39 | response = ""; 40 | return true; 41 | } 42 | } 43 | catch (Exception e) 44 | { 45 | response = ""; 46 | return true; 47 | } 48 | } 49 | 50 | public static IEnumerator RaPlayerCoRoutine(ExternalLookupCommand __instance, CommandSender sender, ArraySegment data) 51 | { 52 | string[] source = data.ToArray(); 53 | if (source[0].StartsWith("-1") && CommandProcessor.CheckPermissions(sender, PlayerPermissions.BanningUpToDay)) 54 | { 55 | var player = CedModPlayer.Get(sender.SenderId); 56 | var open = RemoteAdminModificationHandler.ReportsList.Where(s => s.Status == HandleStatus.NoResponse).ToList(); 57 | if (!RemoteAdminModificationHandler.ReportUnHandledState.ContainsKey(player)) 58 | { 59 | sender.RaReply(string.Format("${0} {1}", (object)1, (object)"Please use 'Request' to select a report first."), true, true, string.Empty); 60 | yield break; 61 | } 62 | var currently = RemoteAdminModificationHandler.ReportUnHandledState[player]; 63 | var report = open.FirstOrDefault(s => s.Id == currently.Item1); 64 | if (report == null) 65 | { 66 | sender.RaReply(string.Format("${0} {1}", (object)1, (object)"Please use 'Request' to select a report first."), true, true, string.Empty); 67 | yield break; 68 | } 69 | 70 | var resp = RemoteAdminModificationHandler.UpdateReport(report.Id.ToString(), sender.SenderId, HandleStatus.Ignored, "Ignored using ingame RemoteAdmin"); 71 | yield return Timing.WaitUntilTrue(() => resp.IsCompleted); 72 | Timing.RunCoroutine(RaPlayerPatch.HandleReportType1(sender, player, source = new string[] { "0", "-1" }, $"Report {report.Id} Ignored")); 73 | } 74 | 75 | if (source[0].StartsWith("-2") && CommandProcessor.CheckPermissions(sender, PlayerPermissions.BanningUpToDay)) 76 | { 77 | var player = CedModPlayer.Get(sender.SenderId); 78 | var open = RemoteAdminModificationHandler.ReportsList.Where(s => s.Status == HandleStatus.InProgress).ToList(); 79 | if (!RemoteAdminModificationHandler.ReportInProgressState.ContainsKey(player)) 80 | { 81 | sender.RaReply(string.Format("${0} {1}", (object)1, (object)"Please use 'Request' to select a report first."), true, true, string.Empty); 82 | yield break; 83 | } 84 | var currently = RemoteAdminModificationHandler.ReportInProgressState[player]; 85 | var report = open.FirstOrDefault(s => s.Id == currently.Item1); 86 | if (report == null) 87 | { 88 | sender.RaReply(string.Format("${0} {1}", (object)1, (object)"Please use 'Request' to select a report first."), true, true, string.Empty); 89 | yield break; 90 | } 91 | var resp = RemoteAdminModificationHandler.UpdateReport(report.Id.ToString(), sender.SenderId, HandleStatus.Ignored, "Ignored using ingame RemoteAdmin"); 92 | yield return Timing.WaitUntilTrue(() => resp.IsCompleted); 93 | Timing.RunCoroutine(RaPlayerPatch.HandleReportType2(sender, player, source = new string[] { "0", "-2" }, $"Report {report.Id} Ignored")); 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /CedMod/Patches/IntercomUnMuteCommandPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using CommandSystem; 5 | using CommandSystem.Commands.RemoteAdmin; 6 | using CommandSystem.Commands.RemoteAdmin.MutingAndIntercom; 7 | using HarmonyLib; 8 | using UnityEngine; 9 | using Utils; 10 | using VoiceChat; 11 | 12 | namespace CedMod.Patches 13 | { 14 | [HarmonyPatch(typeof(IntercomUnmuteCommand), nameof(IntercomUnmuteCommand.Execute))] 15 | public static class IntercomUnMuteCommandPatch 16 | { 17 | public static string Command { get; } = "imute"; 18 | 19 | public static string[] Aliases { get; } = new string[] 20 | { 21 | }; 22 | 23 | public static string Description { get; } = "Allows the specified player(s) from being able to speak over the intercom again."; 24 | 25 | public static string[] Usage { get; } = new string[] 26 | { 27 | "%player%", 28 | }; 29 | 30 | 31 | public static bool Prefix(BanCommand __instance, bool __result, ArraySegment arguments, ICommandSender sender, out string response) 32 | { 33 | if (!sender.CheckPermission(new global::PlayerPermissions[] 34 | { 35 | global::PlayerPermissions.BanningUpToDay, 36 | global::PlayerPermissions.LongTermBanning, 37 | global::PlayerPermissions.PlayersManagement 38 | }, out response)) 39 | { 40 | response = "No permissions."; 41 | return false; 42 | } 43 | 44 | if (CedModMain.Singleton.Config.CedMod.OnlyAllowPanelMutes) 45 | { 46 | response = "Mutes can only be issued from the CedMod CommunityManagement panel, use External Panel with a player selected to issue mutes"; 47 | return false; 48 | } 49 | if (arguments.Count < 1) 50 | { 51 | response = "To execute this command provide at least 1 arguments!\nUsage: " + arguments.Array[0] + " " + __instance.DisplayCommandUsage(); 52 | return false; 53 | } 54 | 55 | string[] array; 56 | List list = RAUtils.ProcessPlayerIdOrNamesList(arguments, 0, out array); 57 | if (list == null) 58 | { 59 | response = "An unexpected problem has occurred during PlayerId/Name array processing."; 60 | return false; 61 | } 62 | 63 | ushort num2 = 0; 64 | ushort num3 = 0; 65 | string text2 = string.Empty; 66 | foreach (ReferenceHub referenceHub in list) 67 | { 68 | try 69 | { 70 | if (referenceHub == null) 71 | { 72 | num3 += 1; 73 | } 74 | else 75 | { 76 | var plr = CedModPlayer.Get(referenceHub); 77 | plr.SendConsoleMessage("You have been unmuted", "green"); 78 | Broadcast.Singleton.TargetAddElement(plr.Connection, "You have been unmuted", 5, Broadcast.BroadcastFlags.Normal); 79 | //plr.IntercomUnmute(false); 80 | VoiceChatMutes.SetFlags(plr.ReferenceHub, VcMuteFlags.None); 81 | if (!string.IsNullOrEmpty(CedModMain.Singleton.Config.CedMod.MuteCustomInfo)) 82 | plr.CustomInfo = ""; 83 | Task.Run(async () => 84 | { 85 | await API.UnMute(plr); 86 | }); 87 | global::ServerLogs.AddLog(global::ServerLogs.Modules.Administrative, sender.LogName + " revoked an intercom mute to player " + referenceHub.LoggedNameFromRefHub() + ".", global::ServerLogs.ServerLogType.RemoteAdminActivity_GameChanging, false); 88 | num2++; 89 | } 90 | } 91 | catch (Exception ex) 92 | { 93 | num3 += 1; 94 | Debug.Log(ex); 95 | text2 = "Error occured during banning: " + ex.Message + ".\n" + ex.StackTrace; 96 | } 97 | } 98 | if (num3 == 0) 99 | { 100 | string arg = "unIntercom Muted"; 101 | response = string.Format("Done! {0} {1} player{2}", arg, num2, (num2 == 1) ? "!" : "s!"); 102 | __result = true; 103 | return false; 104 | } 105 | response = string.Format("Failed to execute the command! Failures: {0}\nLast error log:\n{1}", num3, text2); 106 | return false; 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /CedMod/Patches/IssueBanPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using HarmonyLib; 4 | using LabApi.Features.Console; 5 | 6 | namespace CedMod.Patches 7 | { 8 | [HarmonyPatch(typeof(BanHandler), nameof(BanHandler.IssueBan), new Type[] {typeof(BanDetails), typeof(BanHandler.BanType), typeof(bool)})] 9 | public static class IssueBanPatch 10 | { 11 | public static bool Prefix(BanDetails ban, BanHandler.BanType banType, bool forced) 12 | { 13 | try 14 | { 15 | Logger.Info($"MainGame ban IssueBanpatch: banning user. {ban.Id} {banType} {ban.OriginalName}"); 16 | new Thread(() => 17 | { 18 | try 19 | { 20 | lock (BanSystem.Banlock) 21 | { 22 | API.BanId(ban.Id, (long)(new DateTime(ban.Expires) - new DateTime(ban.IssuanceTime)).TotalSeconds, ban.Issuer, ban.Reason, false).Wait(); 23 | } 24 | } 25 | catch (Exception ex) 26 | { 27 | Logger.Error($"MainGame IssueBan patch failed {ex}"); 28 | } 29 | }).Start(); 30 | } 31 | catch (Exception ex) 32 | { 33 | Logger.Error($"MainGame IssueBan patch failed {ex}"); 34 | } 35 | 36 | return false; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /CedMod/Patches/MirrorPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HarmonyLib; 3 | using Mirror; 4 | using UnityEngine; 5 | using Logger = LabApi.Features.Console.Logger; 6 | 7 | namespace CedMod.Patches 8 | { 9 | [HarmonyPatch(typeof(NetworkClient), nameof(NetworkClient.OnTransportData))] 10 | internal class TransportReceivePatch 11 | { 12 | public static bool Prefix(ArraySegment data, int channelId) 13 | { 14 | if (NetworkClient.connection != null) 15 | { 16 | if (!NetworkClient.unbatcher.AddBatch(data)) 17 | { 18 | Debug.LogWarning("NetworkClient: failed to add batch, disconnecting."); 19 | Logger.Warn("Skipping Mirror NetworkClient Disconnect call."); 20 | //NetworkClient.connection.Disconnect(); 21 | return false; 22 | } 23 | 24 | ArraySegment arraySegment; 25 | double num; 26 | while (!NetworkClient.isLoadingScene && NetworkClient.unbatcher.GetNextMessage(out arraySegment, out num)) 27 | { 28 | using (NetworkReaderPooled networkReaderPooled = NetworkReaderPool.Get(arraySegment)) 29 | { 30 | if (networkReaderPooled.Remaining < 2) 31 | { 32 | Debug.LogWarning("NetworkClient: received Message was too short (messages should start with message id)"); 33 | Logger.Warn("Skipping Mirror NetworkClient Disconnect call."); 34 | //NetworkClient.connection.Disconnect(); 35 | return false; 36 | } 37 | NetworkClient.connection.remoteTimeStamp = num; 38 | if (!NetworkClient.UnpackAndInvoke(networkReaderPooled, channelId)) 39 | { 40 | Debug.LogWarning("NetworkClient: failed to unpack and invoke message. Disconnecting."); 41 | Logger.Warn("Skipping Mirror NetworkClient Disconnect call."); 42 | //NetworkClient.connection.Disconnect(); 43 | return false; 44 | } 45 | continue; 46 | } 47 | } 48 | 49 | if (!NetworkClient.isLoadingScene && NetworkClient.unbatcher.BatchesCount > 0) 50 | { 51 | Debug.LogError(string.Format("Still had {0} batches remaining after processing, even though processing was not interrupted by a scene change. This should never happen, as it would cause ever growing batches.\nPossible reasons:\n* A message didn't deserialize as much as it serialized\n*There was no message handler for a message id, so the reader wasn't read until the end.", NetworkClient.unbatcher.BatchesCount)); 52 | return false; 53 | } 54 | } 55 | else 56 | { 57 | Debug.LogError("Skipped Data message handling because connection is null."); 58 | } 59 | return false; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /CedMod/Patches/NpcInstanceModePatch.cs: -------------------------------------------------------------------------------- 1 | using CedMod.Addons.Audio; 2 | using CentralAuth; 3 | using HarmonyLib; 4 | 5 | namespace CedMod.Patches 6 | { 7 | [HarmonyPatch(typeof(PlayerAuthenticationManager), "InstanceMode", MethodType.Setter)] 8 | public static class NpcInstanceModePatch 9 | { 10 | public static bool Prefix(PlayerAuthenticationManager __instance, ClientInstanceMode value) 11 | { 12 | if (AudioCommand.FakeConnectionsIds.ContainsValue(__instance._hub)) 13 | { 14 | if (value != ClientInstanceMode.Unverified && value != ClientInstanceMode.Host && value != ClientInstanceMode.DedicatedServer) 15 | return false; 16 | } 17 | 18 | return true; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /CedMod/Patches/OBanCommandPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using CommandSystem; 5 | using CommandSystem.Commands.RemoteAdmin; 6 | using HarmonyLib; 7 | 8 | namespace CedMod.Patches 9 | { 10 | [HarmonyPatch(typeof(OfflineBanCommand), nameof(OfflineBanCommand.Execute))] 11 | public static class OBanCommandPatch 12 | { 13 | public static bool Prefix(OfflineBanCommand __instance, bool __result, ArraySegment arguments, ICommandSender sender, out string response) 14 | { 15 | if (arguments.Count < 3) 16 | { 17 | response = "To execute this command provide at least 3 arguments!\nUsage: oban " + __instance.DisplayCommandUsage(); 18 | return false; 19 | } 20 | string text = string.Empty; 21 | if (arguments.Count > 2) 22 | { 23 | text = arguments.Skip(2).Aggregate((string current, string n) => current + " " + n); 24 | } 25 | long num = 0L; 26 | try 27 | { 28 | num = Misc.RelativeTimeToSeconds(arguments.At(1), 60); 29 | } 30 | catch 31 | { 32 | response = "Invalid time: " + arguments.At(1); 33 | return false; 34 | } 35 | if (num < 0L) 36 | { 37 | num = 0L; 38 | arguments.At(1).Replace(arguments.At(1), "0"); 39 | } 40 | if (num == 0L && !sender.CheckPermission(new PlayerPermissions[] 41 | { 42 | PlayerPermissions.KickingAndShortTermBanning, 43 | PlayerPermissions.BanningUpToDay, 44 | PlayerPermissions.LongTermBanning 45 | }, out response)) 46 | { 47 | return false; 48 | } 49 | if (num > 0L && num <= 3600L && !sender.CheckPermission(PlayerPermissions.KickingAndShortTermBanning, out response)) 50 | { 51 | return false; 52 | } 53 | if (num > 3600L && num <= 86400L && !sender.CheckPermission(PlayerPermissions.BanningUpToDay, out response)) 54 | { 55 | return false; 56 | } 57 | if (num > 86400L && !sender.CheckPermission(PlayerPermissions.LongTermBanning, out response)) 58 | { 59 | return false; 60 | } 61 | Misc.IPAddressType ipaddressType; 62 | bool flag = Misc.ValidateIpOrHostname(arguments.At(0), out ipaddressType, false, false); 63 | if (flag) 64 | { 65 | response = "IP Bans are automatically issued by CedMod once a UserId ban is issued."; 66 | return false; 67 | } 68 | if (!arguments.At(0).Contains("@")) 69 | { 70 | response = "Target must be a valid UserID."; 71 | return false; 72 | } 73 | ServerLogs.AddLog(ServerLogs.Modules.Administrative, string.Concat(new string[] 74 | { 75 | sender.LogName, 76 | " banned an offline player with ", 77 | "UserID", 78 | arguments.At(0), 79 | ". Ban duration: ", 80 | arguments.At(1), 81 | ". Reason: ", 82 | (text == string.Empty) ? "(none)" : text, 83 | "." 84 | }), ServerLogs.ServerLogType.RemoteAdminActivity_GameChanging, false); 85 | new Thread(() => 86 | { 87 | lock (BanSystem.Banlock) 88 | { 89 | API.BanId(arguments.At(0), num, sender.LogName, text, true).Wait(); 90 | } 91 | }).Start(); 92 | response = "UserID " + arguments.At(0) + " has been banned from this server."; 93 | return false; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /CedMod/Patches/RAProcessPlayerPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | using HarmonyLib; 6 | using NorthwoodLib.Pools; 7 | using UnityEngine; 8 | using Utils; 9 | 10 | namespace CedMod.Patches 11 | { 12 | [HarmonyPatch(typeof(RAUtils), nameof(RAUtils.ProcessPlayerIdOrNamesList))] 13 | public static class RAProcessPlayerPatch 14 | { 15 | public static bool Prefix(ref List __result, ArraySegment args, int startindex, out string[] newargs, bool keepEmptyEntries = false) 16 | { 17 | List result1; 18 | try 19 | { 20 | string str1 = RAUtils.FormatArguments(args, startindex); 21 | List referenceHubList = ListPool.Shared.Rent(); 22 | if (str1.StartsWith("@", StringComparison.Ordinal)) 23 | { 24 | foreach (Match match in new Regex("@\"(.*?)\".|@[^\\s.]+\\.").Matches(str1)) 25 | { 26 | str1 = RAUtils.ReplaceFirst(str1, match.Value, ""); 27 | string name = match.Value.Substring(1).Replace("\"", "").Replace(".", ""); 28 | List list = Enumerable.Where((IEnumerable)ReferenceHub.AllHubs, (Func)(ply => ply.nicknameSync.MyNick.Equals(name))).ToList(); 29 | if (list.Count == 1 && !referenceHubList.Contains(list[0])) 30 | referenceHubList.Add(list[0]); 31 | } 32 | 33 | newargs = str1.Split(new char[1] { ' ' }, (StringSplitOptions)(keepEmptyEntries ? 0 : 1)); 34 | } 35 | else if (args.At(startindex).Length > 0) 36 | { 37 | if (char.IsDigit(args.At(startindex)[0]) || args.At(startindex) == "-1" || args.At(startindex) == "-2") 38 | { 39 | foreach (string s in args.At(startindex).Split('.', StringSplitOptions.None)) 40 | { 41 | if (s == "-1" || s == "-2") 42 | continue; 43 | 44 | int result; 45 | ReferenceHub hub; 46 | if (int.TryParse(s, out result) && ReferenceHub.TryGetHub(result, out hub) && !referenceHubList.Contains(hub)) 47 | referenceHubList.Add(hub); 48 | } 49 | } 50 | else if (char.IsLetter(args.At(startindex)[0])) 51 | { 52 | foreach (string str2 in args.At(startindex).Split('.', StringSplitOptions.None)) 53 | { 54 | if (str2 == "-1" || str2 == "-2") 55 | continue; 56 | 57 | foreach (ReferenceHub allHub in ReferenceHub.AllHubs) 58 | { 59 | if (allHub.nicknameSync.MyNick.Equals(str2) && !referenceHubList.Contains(allHub)) 60 | referenceHubList.Add(allHub); 61 | } 62 | } 63 | } 64 | } 65 | 66 | string[] strArray; 67 | if (args.Count <= 1) 68 | strArray = (string[])null; 69 | else 70 | strArray = RAUtils.FormatArguments(args, startindex + 1).Split(new char[1] 71 | { 72 | ' ' 73 | }, (StringSplitOptions)(keepEmptyEntries ? 0 : 1)); 74 | newargs = strArray; 75 | result1 = referenceHubList; 76 | } 77 | catch (Exception exception) 78 | { 79 | Debug.LogException(exception); 80 | newargs = null; 81 | result1 = null; 82 | } 83 | 84 | __result = result1; 85 | return false; 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /CedMod/Patches/ReloadServerNamePatch.cs: -------------------------------------------------------------------------------- 1 | using CedMod.Addons.QuerySystem; 2 | using HarmonyLib; 3 | 4 | namespace CedMod.Patches 5 | { 6 | [HarmonyPatch(typeof(ServerConsole), nameof(ServerConsole.ReloadServerName))] 7 | public class ReloadServerNamePatch 8 | { 9 | public static bool IncludeString = false; 10 | public static void Postfix() 11 | { 12 | string data = $"CedModVerification{Verification.ServerId}"; 13 | if (Verification.ServerId != 0 && !ServerConsole.ServerName.Contains(data)) 14 | { 15 | ServerConsole.ServerName += data; 16 | } 17 | 18 | if (!IncludeString) 19 | { 20 | ServerConsole.ServerName = ServerConsole.ServerName.Replace(data, ""); 21 | } 22 | } 23 | } 24 | 25 | [HarmonyPatch(typeof(PlayerList), nameof(PlayerList.RefreshTitle))] 26 | public class RefreshTitleSafePatch 27 | { 28 | public static bool Prefix() 29 | { 30 | string data = $"CedModVerification{Verification.ServerId}"; 31 | 32 | if (string.IsNullOrEmpty(PlayerList.Title.Value)) 33 | { 34 | PlayerList.ServerName = ServerConsole.Singleton.RefreshServerNameSafe().Replace(data, ""); 35 | } 36 | else 37 | { 38 | string result; 39 | if (!ServerConsole.Singleton.NameFormatter.TryProcessExpression(PlayerList.Title.Value, "player list title", out result)) 40 | ServerConsole.AddLog(result); 41 | else 42 | PlayerList.ServerName = result; 43 | } 44 | 45 | return false; 46 | } 47 | } 48 | 49 | [HarmonyPatch(typeof(PlayerList), nameof(PlayerList.RefreshTitle))] 50 | public class ReloadTitlePatch 51 | { 52 | public static bool Prefix() 53 | { 54 | string data = $"CedModVerification{Verification.ServerId}"; 55 | 56 | PlayerList.ServerName = (string.IsNullOrEmpty(PlayerList.Title.Value) ? ServerConsole.Singleton.RefreshServerName() : ServerConsole.Singleton.NameFormatter.ProcessExpression(PlayerList.Title.Value)).Replace(data, ""); 57 | 58 | return false; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /CedMod/Patches/UnMuteCommandPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using CommandSystem; 5 | using CommandSystem.Commands.RemoteAdmin; 6 | using CommandSystem.Commands.RemoteAdmin.MutingAndIntercom; 7 | using HarmonyLib; 8 | using UnityEngine; 9 | using Utils; 10 | using VoiceChat; 11 | 12 | namespace CedMod.Patches 13 | { 14 | [HarmonyPatch(typeof(UnmuteCommand), nameof(UnmuteCommand.Execute))] 15 | public static class UnMuteCommandPatch 16 | { 17 | public static string Command { get; } = "unmute"; 18 | 19 | public static string[] Aliases { get; } = new string[] 20 | { 21 | }; 22 | 23 | public static string Description { get; } = "Allows the specified player(s) to speak again."; 24 | 25 | public static string[] Usage { get; } = new string[] 26 | { 27 | "%player%", 28 | }; 29 | 30 | 31 | public static bool Prefix(BanCommand __instance, bool __result, ArraySegment arguments, ICommandSender sender, out string response) 32 | { 33 | if (!sender.CheckPermission(new global::PlayerPermissions[] 34 | { 35 | global::PlayerPermissions.BanningUpToDay, 36 | global::PlayerPermissions.LongTermBanning, 37 | global::PlayerPermissions.PlayersManagement 38 | }, out response)) 39 | { 40 | response = "No permissions."; 41 | return false; 42 | } 43 | 44 | if (CedModMain.Singleton.Config.CedMod.OnlyAllowPanelMutes) 45 | { 46 | response = "Mutes can only be issued from the CedMod CommunityManagement panel, use External Panel with a player selected to issue mutes"; 47 | return false; 48 | } 49 | if (arguments.Count < 1) 50 | { 51 | response = "To execute this command provide at least 1 arguments!\nUsage: " + arguments.Array[0] + " " + __instance.DisplayCommandUsage(); 52 | return false; 53 | } 54 | 55 | string[] array; 56 | List list = RAUtils.ProcessPlayerIdOrNamesList(arguments, 0, out array); 57 | if (list == null) 58 | { 59 | response = "An unexpected problem has occurred during PlayerId/Name array processing."; 60 | return false; 61 | } 62 | 63 | ushort num2 = 0; 64 | ushort num3 = 0; 65 | string text2 = string.Empty; 66 | foreach (ReferenceHub referenceHub in list) 67 | { 68 | try 69 | { 70 | if (referenceHub == null) 71 | { 72 | num3 += 1; 73 | } 74 | else 75 | { 76 | var plr = CedModPlayer.Get(referenceHub); 77 | plr.SendConsoleMessage("You have been unmuted", "green"); 78 | Broadcast.Singleton.TargetAddElement(plr.Connection, "You have been unmuted", 5, Broadcast.BroadcastFlags.Normal); 79 | //plr.Mute(true); 80 | VoiceChatMutes.SetFlags(plr.ReferenceHub, VcMuteFlags.None); 81 | if (!string.IsNullOrEmpty(CedModMain.Singleton.Config.CedMod.MuteCustomInfo)) 82 | plr.CustomInfo = ""; 83 | Task.Run(async () => 84 | { 85 | await API.UnMute(plr); 86 | }); 87 | global::ServerLogs.AddLog(global::ServerLogs.Modules.Administrative, sender.LogName + " unmuted player " + referenceHub.LoggedNameFromRefHub() + ".", global::ServerLogs.ServerLogType.RemoteAdminActivity_GameChanging, false); 88 | num2++; 89 | } 90 | } 91 | catch (Exception ex) 92 | { 93 | num3 += 1; 94 | Debug.Log(ex); 95 | text2 = "Error occured during unmuting: " + ex.Message + ".\n" + ex.StackTrace; 96 | } 97 | } 98 | if (num3 == 0) 99 | { 100 | string arg = "Unmuted"; 101 | response = string.Format("Done! {0} {1} player{2}", arg, num2, (num2 == 1) ? "!" : "s!"); 102 | __result = true; 103 | return false; 104 | } 105 | response = string.Format("Failed to execute the command! Failures: {0}\nLast error log:\n{1}", num3, text2); 106 | return false; 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /CedMod/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("CedModV2")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("CedMod Development Team")] 11 | [assembly: AssemblyProduct("CedMod")] 12 | [assembly: AssemblyCopyright("Copyright © 2022")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("aa82af69-2a52-4e66-b578-a1e85b5e61d4")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | [assembly: AssemblyVersion("1.0.0.0")] 32 | [assembly: AssemblyFileVersion("1.0.0.0")] 33 | -------------------------------------------------------------------------------- /CedMod/README.md: -------------------------------------------------------------------------------- 1 | # CedMod 2 | Le CedMod plugin 3 | -------------------------------------------------------------------------------- /CedMod/RainbowLight.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace CedMod 5 | { 6 | public class RainbowLight : MonoBehaviour 7 | { 8 | public static readonly List Instances = new List(); 9 | public float saturation = 1f; 10 | public float hueShiftSpeed = 0.2f; 11 | public float value = 1f; 12 | 13 | private RoomLightController _light; 14 | public RoomLightController Light 15 | { 16 | get 17 | { 18 | if (_light == null) 19 | _light = GetComponent(); 20 | return _light; 21 | } 22 | } 23 | 24 | private void Awake() 25 | { 26 | Instances.Add(this); 27 | } 28 | 29 | private void OnDestroy() 30 | { 31 | Light.NetworkOverrideColor = Color.clear; 32 | Instances.Remove(this); 33 | } 34 | 35 | private void Update() 36 | { 37 | float amountToShift = hueShiftSpeed * Time.deltaTime; 38 | Color newColor = ShiftHueBy(Light.NetworkOverrideColor, amountToShift); 39 | Light.NetworkOverrideColor = newColor; 40 | } 41 | 42 | private Color ShiftHueBy(Color color, float amount) 43 | { 44 | // convert from RGB to HSV 45 | Color.RGBToHSV(color, out float hue, out float sat, out float val); 46 | 47 | // shift hue by amount 48 | hue += amount; 49 | sat = saturation; 50 | val = value; 51 | 52 | // convert back to RGB and return the color 53 | return Color.HSVToRGB(hue, sat, val); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /CedMod/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /CedMod/version.txt: -------------------------------------------------------------------------------- 1 | DEV -------------------------------------------------------------------------------- /CedMod/versionIdentifier.txt: -------------------------------------------------------------------------------- 1 | COMPILEDDEV -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 3.2-x | :white_check_mark: | 8 | | < 2.x | :x: | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | Open an Issue on the issue tab describing the vullerability and how to use it, try to provide as much info as possible it will speed up the process of patching it 13 | --------------------------------------------------------------------------------