diff --git a/Synapse/Api/Decontamination.cs b/Synapse/Api/Decontamination.cs new file mode 100644 index 0000000..7c0d4ad --- /dev/null +++ b/Synapse/Api/Decontamination.cs @@ -0,0 +1,31 @@ +using LightContainmentZoneDecontamination; +using Mirror; + +namespace Synapse.Api +{ + public static class Decontamination + { + public static DecontaminationController Controller { get => DecontaminationController.Singleton; } + + public static bool IsDecontaminationDisabled + { + get => Controller._disableDecontamination; + set + { + if (value) + { + Controller._stopUpdating = false; + Controller.RoundStartTime = NetworkTime.time; + } + Controller._disableDecontamination = value; + } + } + + public static bool IsDecontaminationInProgress => Controller._decontaminationBegun; + + /// + /// Starts the Decontamination + /// + public static void StartDecontamination() => Controller.FinishDecontamination(); + } +} diff --git a/Synapse/Api/PlayerExtensions.cs b/Synapse/Api/Extensions.cs similarity index 59% rename from Synapse/Api/PlayerExtensions.cs rename to Synapse/Api/Extensions.cs index 332c4d1..b7d0fdd 100644 --- a/Synapse/Api/PlayerExtensions.cs +++ b/Synapse/Api/Extensions.cs @@ -1,30 +1,19 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using Mirror; using Synapse.Api.Enums; +using Synapse.Api.Plugin; using UnityEngine; namespace Synapse.Api { [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] [SuppressMessage("ReSharper", "UnusedMember.Global")] - public static class PlayerExtensions + public static class Extensions { - private static MethodInfo _sendSpawnMessage; - public static MethodInfo SendSpawnMessage - { - get - { - if (_sendSpawnMessage == null) - _sendSpawnMessage = typeof(NetworkServer).GetMethod("SendSpawnMessage",BindingFlags.Instance | BindingFlags.InvokeMethod - | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public); - - return _sendSpawnMessage; - } - } - /// Gives a player a message in the RemoteAdmin /// The User who you send the Message /// The Message you want to send @@ -64,58 +53,41 @@ public static void RaMessage(this CommandSender sender, string message, bool suc sender.RaReply($"{Assembly.GetCallingAssembly().GetName().Name}#" + message, success, true, category); } - /// - /// Gives all players on the server - /// - public static IEnumerable GetAllPlayers() - { - return (from gameObject in PlayerManager.players - where gameObject != PlayerManager.localPlayer && gameObject != null - select gameObject.GetPlayer()).ToList(); - } - /// /// Gives all players on the server with this Role /// /// - public static IEnumerable GetAllPlayers(this RoleType role) => GetAllPlayers().Where(x => x.Role == role); + public static IEnumerable GetAllPlayers(this RoleType role) => Player.GetAllPlayers().Where(x => x.Role == role); - /// - /// Gives you the player object - /// - public static Player GetPlayer(this MonoBehaviour mono) => mono.GetComponent(); + + public static IEnumerable GetAllPlayers(this RoleType[] roles) => Player.GetAllPlayers().Where(x => roles.Any(r => x.Role == r)); + + public static IEnumerable GetAllPlayers(this Team[] teams) => Player.GetAllPlayers().Where(x => teams.Any(t => x.Team == t)); /// - /// Gives you the player object + /// Gives all players on the server in this Team /// - public static Player GetPlayer(this PlayableScps.PlayableScp scp) => scp.Hub.GetPlayer(); + /// + /// + public static IEnumerable GetAllPlayers(this Team team) => Player.GetAllPlayers().Where(x => x.Team == team); /// /// Gives you the player object /// - public static Player GetPlayer(this GameObject gameObject) => gameObject.GetComponent(); + public static Player GetPlayer(this MonoBehaviour mono) => mono.GetComponent(); /// /// Gives you the player object /// - public static Player GetPlayer(int id) => GetAllPlayers().FirstOrDefault(p => p.PlayerId == id); + public static Player GetPlayer(this PlayableScps.PlayableScp scp) => scp.Hub.GetPlayer(); /// /// Gives you the player object /// - public static Player GetPlayer(string arg) - { - if (short.TryParse(arg, out var playerId)) - return GetPlayer(playerId); + public static Player GetPlayer(this GameObject gameObject) => gameObject.GetComponent(); - if (!arg.EndsWith("@steam") && !arg.EndsWith("@discord") && !arg.EndsWith("@northwood") && - !arg.EndsWith("@patreon")) - return GetAllPlayers().FirstOrDefault(p => p.NickName.ToLower().Contains(arg.ToLower())); - foreach (var player in GetAllPlayers()) - if (player.UserId == arg) - return player; + public static string GetVersionString(this PluginDetails details) => $"{details.SynapseMajor}.{details.SynapseMinor}.{details.SynapsePatch}"; - return GetAllPlayers().FirstOrDefault(p => p.NickName.ToLower().Contains(arg.ToLower())); - } + public static int GetVersionNumber(this PluginDetails details) => details.SynapseMajor * 100 + details.SynapseMinor * 10 + details.SynapsePatch; } } \ No newline at end of file diff --git a/Synapse/Log.cs b/Synapse/Api/Log.cs similarity index 100% rename from Synapse/Log.cs rename to Synapse/Api/Log.cs diff --git a/Synapse/Api/Map.cs b/Synapse/Api/Map.cs index 9c1f79c..fb561bd 100644 --- a/Synapse/Api/Map.cs +++ b/Synapse/Api/Map.cs @@ -1,5 +1,4 @@ -using LightContainmentZoneDecontamination; -using Synapse.Permissions; +using Synapse.Config; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -12,21 +11,6 @@ namespace Synapse.Api [SuppressMessage("ReSharper", "UnusedMember.Global")] public static class Map { - /// - /// Gives you the WarheadController. - /// - public static AlphaWarheadController WarheadController => Player.Server.GetComponent(); - - /// - /// Activates/Deactivates the RoundLock (if the Round can end) - /// - public static bool RoundLock { get => RoundSummary.RoundLock; set => RoundSummary.RoundLock = value; } - - /// - /// Activates/Deactivates the LobbyLock (if the Lobby can continue counting down) - /// - public static bool LobbyLock { get => GameCore.RoundStart.LobbyLock; set => GameCore.RoundStart.LobbyLock = value; } - /// /// Activates/Deactivates the FriendlyFire on the server /// @@ -37,9 +21,7 @@ public static class Map /// public static List Lifts => Object.FindObjectsOfType().ToList(); - private static Broadcast BroadcastComponent => Player.Server.GetComponent(); - - private static List _rooms = new List(); + private static Broadcast BroadcastComponent => Player.Host.GetComponent(); /// /// Gives you a list of all rooms @@ -48,27 +30,12 @@ public static List Rooms { get { - if (_rooms == null || _rooms.Count == 0) - _rooms = Object.FindObjectsOfType().Where(transform => transform.CompareTag("Room")) + return Object.FindObjectsOfType().Where(transform => transform.CompareTag("Room") || transform.name == "Root_*&*Outside Cams") .Select(obj => new Room {Name = obj.name, Position = obj.position, Transform = obj.transform}) .ToList(); - - return _rooms; } } - /// - /// Is the nuke detonated? - /// - public static bool IsNukeDetonated => - WarheadController.detonated; - - /// - /// Is the nuke in progress? - /// - public static bool IsNukeInProgress => - WarheadController.inProgress; - /// /// How many generators are activated? /// @@ -182,39 +149,14 @@ public static Vector3 GetRandomSpawnPoint(this RoleType type) /// /// /// - public static void CassieMessage(string msg, bool makeHold, bool makeNoise) => Player.Server.GetComponent().RpcPlayCustomAnnouncement(msg, makeHold, makeNoise); - - /// - /// Starts the Decontamination - /// - public static void StartDecontamination() => DecontaminationController.Singleton.FinishDecontamination(); + public static void CassieMessage(string msg, bool makeHold, bool makeNoise) => Respawning.RespawnEffectsController.PlayCassieAnnouncement(msg, makeHold, makeNoise); - /// - /// Starts the nuke - /// - public static void StartNuke() - { - var alpha = PlayerManager.localPlayer.GetComponent(); - alpha.InstantPrepare(); - alpha.StartDetonation(); - } - /// /// Spawns a Item on the Map /// public static Pickup SpawnItem(ItemType itemType, float durability, Vector3 position, Quaternion rotation = default, int sight = 0, int barrel = 0, int other = 0) - => Player.Server.Inventory.SetPickup(itemType, durability, position, rotation, sight, barrel, other); - - /// - /// Stops the nuke - /// - public static void StopNuke() => WarheadController.CancelDetonation(); - - /// - /// Detonates the nuke - /// - public static void DetonateNuke() => WarheadController.Detonate(); + => Player.Host.Inventory.SetPickup(itemType, durability, position, rotation, sight, barrel, other); /// /// Has the group the permission? diff --git a/Synapse/Api/Player.cs b/Synapse/Api/Player.cs index 19f0e9d..7a4b35a 100644 --- a/Synapse/Api/Player.cs +++ b/Synapse/Api/Player.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using Hints; @@ -6,7 +7,7 @@ using RemoteAdmin; using Searching; using Synapse.Api.Enums; -using Synapse.Permissions; +using Synapse.Config; using UnityEngine; namespace Synapse.Api @@ -16,7 +17,37 @@ namespace Synapse.Api // ReSharper disable once ClassNeverInstantiated.Global public class Player : MonoBehaviour { - public static Player Server => PlayerManager.localPlayer.GetPlayer(); + public static Player Host => PlayerManager.localPlayer.GetPlayer(); + + public static IEnumerable GetAllPlayers() + { + return (from gameObject in PlayerManager.players + where gameObject != PlayerManager.localPlayer && gameObject != null + select gameObject.GetPlayer()).ToList(); + } + + /// + /// Gives you the player object + /// + public static Player GetPlayer(int id) => Player.GetAllPlayers().FirstOrDefault(p => p.PlayerId == id); + + /// + /// Gives you the player object + /// + public static Player GetPlayer(string arg) + { + if (short.TryParse(arg, out var playerId)) + return GetPlayer(playerId); + + if (!arg.EndsWith("@steam") && !arg.EndsWith("@discord") && !arg.EndsWith("@northwood") && + !arg.EndsWith("@patreon")) + return Player.GetAllPlayers().FirstOrDefault(p => p.NickName.ToLower().Contains(arg.ToLower())); + foreach (var player in Player.GetAllPlayers()) + if (player.UserId == arg) + return player; + + return Player.GetAllPlayers().FirstOrDefault(p => p.NickName.ToLower().Contains(arg.ToLower())); + } public ReferenceHub Hub => GetComponent(); @@ -60,7 +91,7 @@ public CommandSender CommandSender { get { - if (this == Server) return ServerConsole._scs; + if (this == Host) return ServerConsole._scs; else return QueryProcessor._sender; } } @@ -125,8 +156,8 @@ public Vector3 Scale { Hub.transform.localScale = value; - foreach (var player in PlayerExtensions.GetAllPlayers()) - PlayerExtensions.SendSpawnMessage?.Invoke(null, new object[] { Hub.GetComponent(), player.Connection }); + foreach (var player in GetAllPlayers()) + Server.SendSpawnMessage?.Invoke(null, new object[] { Hub.GetComponent(), player.Connection }); } catch (Exception e) { @@ -209,14 +240,14 @@ public Team Side /// /// The Room where the player currently is /// - public Room CurRoom + public Room Room { get { var playerPos = Position; var end = playerPos - new Vector3(0f, 10f, 0f); var flag = Physics.Linecast(playerPos, end, out var rayCastHit, -84058629); - + if (!flag || rayCastHit.transform == null) return null; @@ -254,7 +285,7 @@ public Room CurRoom /// maybe be null, if set to null, uncuffed public Player Cuffer { - get => PlayerExtensions.GetPlayer(Handcuffs.CufferId); + get => GetPlayer(Handcuffs.CufferId); set { var handcuff = value.Handcuffs; @@ -289,7 +320,7 @@ public Player Cuffer /// /// The UserGroup the player is in /// - public UserGroup Rank { get => ServerRoles.Group; set => ServerRoles.SetGroup(value, false); } + public UserGroup Rank { get => ServerRoles.Group; set => ServerRoles.SetGroup(value, value != null ? value.Permissions > 0UL : false,true); } /// /// The name of the group the user has @@ -308,6 +339,11 @@ public Player Cuffer /// Note: This will not change the permissions public string RankName { get => Rank.BadgeText; set => Hub.serverRoles.SetText(value); } + /// + /// The Permission of the Player + /// + public ulong Permission { get => ServerRoles.Permissions; set => ServerRoles.Permissions = value; } + /// /// Is the player muted /// @@ -318,8 +354,6 @@ public Player Cuffer /// public bool IsIntercomMuted { get => ClassManager.NetworkIntercomMuted; set => ClassManager.NetworkIntercomMuted = value; } - //TODO: Find a way to make this possible again: public bool FriendlyFire { get => Hub.weaponManager.NetworkfriendlyFire; set => Hub.weaponManager.NetworkfriendlyFire = value; } - /// /// The current camera the player uses (Scp079 only, if not null) /// @@ -352,6 +386,7 @@ public Player Cuffer public Jail Jail => GetComponent(); + public string UnitName { get => ClassManager.NetworkCurUnitName; set => ClassManager.NetworkCurUnitName = value; } //Methods /// @@ -366,7 +401,7 @@ public Player Cuffer /// /// /// - public void Ban(int duration, string reason, string issuer = "Plugin") => Server.GetComponent().BanUser(gameObject, duration, reason, issuer); + public void Ban(int duration, string reason, string issuer = "Plugin") => Host.GetComponent().BanUser(gameObject, duration, reason, issuer); /// /// Kills a player @@ -388,7 +423,7 @@ public void ChangeRoleAtPosition(RoleType role) /// public bool CheckPermission(string permission) { - if (this == Server) return true; + if (this == Host) return true; try { return PermissionReader.CheckPermission(this, permission); @@ -471,6 +506,12 @@ public void InstantBroadcast(ushort time, string message) /// public void GiveItem(ItemType itemType, float duration = float.NegativeInfinity, int sight = 0, int barrel = 0, int other = 0) => Hub.inventory.AddNewItem(itemType, duration, sight, barrel, other); + public void DropItem(Inventory.SyncItemInfo item) + { + Inventory.SetPickup(item.id, item.durability, Position, Inventory.camera.transform.rotation, item.modSight, item.modBarrel, item.modOther); + Items.Remove(item); + } + /// /// Clears the players Inventory /// @@ -489,10 +530,9 @@ public void InstantBroadcast(ushort time, string message) /// public void RaLogin() { - Hub.serverRoles.RemoteAdmin = true; - Hub.serverRoles.Permissions = Hub.serverRoles.Group.Permissions; - Hub.serverRoles.RemoteAdminMode = ServerRoles.AccessMode.PasswordOverride; - Hub.serverRoles.TargetOpenRemoteAdmin(Connection, false); + ServerRoles.RemoteAdmin = true; + ServerRoles.RemoteAdminMode = ServerRoles.AccessMode.PasswordOverride; + ServerRoles.TargetOpenRemoteAdmin(Connection, false); } /// @@ -501,9 +541,38 @@ public void RaLogin() public void RaLogout() { Hub.serverRoles.RemoteAdmin = false; - Hub.serverRoles.Permissions = 0UL; Hub.serverRoles.RemoteAdminMode = ServerRoles.AccessMode.LocalAccess; Hub.serverRoles.TargetCloseRemoteAdmin(Connection); } + + /// + /// Hurts the Player + /// + /// + /// + /// + public void Hurt(int amount, DamageTypes.DamageType damagetype = default,Player attacker = null) => + PlayerStats.HurtPlayer(new PlayerStats.HitInfo(amount, attacker == null ? "WORLD" : attacker.NickName, damagetype, attacker == null ? PlayerId : attacker.PlayerId), attacker == null ? gameObject : attacker.gameObject); + + /// + /// Sends the Player to a Server in the same network with this Port (such a server must exist or he will be disconnected) + /// + /// The Port of the Server the Player should be send to + public void SendToServer(ushort port) + { + PlayerStats component = Host.PlayerStats; + NetworkWriter writer = NetworkWriterPool.GetWriter(); + writer.WriteSingle(1f); + writer.WriteUInt16(port); + RpcMessage msg = new RpcMessage + { + netId = component.netId, + componentIndex = component.ComponentIndex, + functionHash = Server.GetMethodHash(typeof(PlayerStats), "RpcRoundrestartRedirect"), + payload = writer.ToArraySegment() + }; + Connection.Send(msg, 0); + NetworkWriterPool.Recycle(writer); + } } } diff --git a/Synapse/Plugin.cs b/Synapse/Api/Plugin/Plugin.cs similarity index 94% rename from Synapse/Plugin.cs rename to Synapse/Api/Plugin/Plugin.cs index f4918c4..374334e 100644 --- a/Synapse/Plugin.cs +++ b/Synapse/Api/Plugin/Plugin.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Synapse +namespace Synapse.Api.Plugin { public abstract class Plugin { @@ -17,6 +17,8 @@ public abstract class Plugin // ReSharper disable once UnusedAutoPropertyAccessor.Global public Translation Translation { get; internal set; } + public PluginDetails Details { get; internal set; } + private string _ownPluginFolder; /// @@ -36,8 +38,6 @@ public string OwnPluginFolder internal set => _ownPluginFolder = value; } - public abstract string GetName { get; } - /// The Method ist always activated when the Server starts /// You can use it to hook Events public abstract void OnEnable(); diff --git a/Synapse/Api/Plugin/PluginDetails.cs b/Synapse/Api/Plugin/PluginDetails.cs new file mode 100644 index 0000000..677e0b5 --- /dev/null +++ b/Synapse/Api/Plugin/PluginDetails.cs @@ -0,0 +1,15 @@ +using System; + +namespace Synapse.Api.Plugin +{ + public class PluginDetails : Attribute + { + public int SynapseMajor; + public int SynapseMinor; + public int SynapsePatch; + public string Name; + public string Author; + public string Description; + public string Version; + } +} diff --git a/Synapse/Translation.cs b/Synapse/Api/Plugin/Translation.cs similarity index 78% rename from Synapse/Translation.cs rename to Synapse/Api/Plugin/Translation.cs index d468393..3068f73 100644 --- a/Synapse/Translation.cs +++ b/Synapse/Api/Plugin/Translation.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; -namespace Synapse +namespace Synapse.Api.Plugin { [SuppressMessage("ReSharper", "UnusedMember.Global")] public class Translation @@ -14,7 +14,7 @@ public class Translation public void CreateTranslations(Dictionary translations) { - _translationPath = Path.Combine(PluginManager.ServerConfigDirectory, Plugin.GetName + "-translation.txt"); + _translationPath = Path.Combine(Files.ServerConfigDirectory, Plugin.Details.Name + "-translation.txt"); if (!File.Exists(_translationPath)) File.Create(_translationPath).Close(); var dictionary = new Dictionary(); @@ -22,8 +22,10 @@ public void CreateTranslations(Dictionary translations) var newlines = new List(); var position = 0; - foreach (var pair in translations.ToList()) + foreach (var rawpair in translations.ToList()) { + var pair = new KeyValuePair(rawpair.Key,rawpair.Value.Replace("\n", "\\n")); + if (lines.Length > position) { if (string.IsNullOrEmpty(lines[position])) @@ -55,11 +57,12 @@ public string GetTranslation(string translationName) try { var trans = _translation.FirstOrDefault(x => x.Key == translationName).Value; - return trans; + if (trans == null) return "Plugin requested a not created Translation!"; + return trans.Replace("\\n", "\n"); } catch { - return "Invalid Translations Name"; + return "Plugin requested a not created Translation!"; } } } diff --git a/Synapse/Api/Round.cs b/Synapse/Api/Round.cs new file mode 100644 index 0000000..7c991a6 --- /dev/null +++ b/Synapse/Api/Round.cs @@ -0,0 +1,44 @@ +using GameCore; +using Respawning; +using System; + +namespace Synapse.Api +{ + public static class Round + { + public static TimeSpan RoundLenght => RoundStart.RoundLenght; + + public static DateTime StartedTime => DateTime.Now - RoundLenght; + + public static bool IsStarted => RoundSummary.RoundInProgress(); + + /// + /// Activates/Deactivates the RoundLock (if the Round can end) + /// + public static bool IsLocked{ get => RoundSummary.RoundLock; set => RoundSummary.RoundLock = value; } + + public static int Escaped_Ds { get => RoundSummary.escaped_ds; set => RoundSummary.escaped_ds = value; } + + public static int Escaped_Scientists { get => RoundSummary.escaped_scientists; set => RoundSummary.escaped_scientists = value; } + + public static int Kills_by_Scps { get => RoundSummary.kills_by_scp; set => RoundSummary.kills_by_scp = value; } + + public static int Changed_into_Zombies { get => RoundSummary.changed_into_zombies; set => RoundSummary.changed_into_zombies = value; } + + /// + /// Activates/Deactivates the LobbyLock (if the Lobby can continue counting down) + /// + public static bool IsLobbyLocked{ get => GameCore.RoundStart.LobbyLock; set => GameCore.RoundStart.LobbyLock = value; } + + public static void Restart() => Player.Host.PlayerStats.Roundrestart(); + + public static void Start() => CharacterClassManager.ForceRoundStart(); + + public static void MTFRespawn(bool isCI = false) + { + var component = Server.Host.GetComponent(); + component.NextKnownTeam = isCI ? SpawnableTeamType.ChaosInsurgency : SpawnableTeamType.NineTailedFox; + component.Spawn(); + } + } +} diff --git a/Synapse/Api/Server.cs b/Synapse/Api/Server.cs new file mode 100644 index 0000000..67e5d6c --- /dev/null +++ b/Synapse/Api/Server.cs @@ -0,0 +1,67 @@ +using Mirror; +using System; +using System.Reflection; + +namespace Synapse.Api +{ + public static class Server + { + private static MethodInfo _sendSpawnMessage; + private static Broadcast broadcast; + private static BanPlayer banPlayer; + + + public static Player Host => Player.Host; + + public static string Name + { + get => ServerConsole._serverName; + set + { + ServerConsole._serverName = value; + ServerConsole.singleton.RefreshServerName(); + } + } + + public static ushort Port { get => ServerStatic.ServerPort; set => ServerStatic.ServerPort = value; } + + public static MethodInfo SendSpawnMessage + { + get + { + if (_sendSpawnMessage == null) + _sendSpawnMessage = typeof(NetworkServer).GetMethod("SendSpawnMessage", BindingFlags.Instance | BindingFlags.InvokeMethod + | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public); + + return _sendSpawnMessage; + } + } + + public static Broadcast Broadcast + { + get + { + if (broadcast == null) + broadcast = Host.GetComponent(); + + return broadcast; + } + } + + public static BanPlayer BanPlayer + { + get + { + if (banPlayer == null) + banPlayer = Host.GetComponent(); + + return banPlayer; + } + } + + public static ServerConsole Console => ServerConsole.singleton; + + + public static int GetMethodHash(Type invokeClass, string methodName) => invokeClass.FullName.GetStableHashCode() * 503 + methodName.GetStableHashCode(); + } +} diff --git a/Synapse/Api/Warhead.cs b/Synapse/Api/Warhead.cs new file mode 100644 index 0000000..4cb9fba --- /dev/null +++ b/Synapse/Api/Warhead.cs @@ -0,0 +1,69 @@ +namespace Synapse.Api +{ + public static class Warhead + { + private static AlphaWarheadController controller; + private static AlphaWarheadNukesitePanel nukesitePanel; + + public static AlphaWarheadController Controller + { + get + { + if (controller == null) + controller = Player.Host.GetComponent(); + + return controller; + } + } + + public static AlphaWarheadNukesitePanel NukesitePanel + { + get + { + if (nukesitePanel == null) + nukesitePanel = Player.Host.GetComponent(); + + return nukesitePanel; + } + } + + public static bool LeverStatus { get => NukesitePanel.Networkenabled; set => NukesitePanel.Networkenabled = value; } + + public static float DetonationTimer + { + get => Controller.NetworktimeToDetonation; + set => Controller.NetworktimeToDetonation = value; + } + + /// + /// Is the nuke detonated? + /// + public static bool IsNukeDetonated => Controller.detonated; + + /// + /// Is the nuke in progress? + /// + public static bool IsNukeInProgress => Controller.inProgress; + + /// + /// Starts the nuke + /// + public static void StartNuke() + { + Controller.InstantPrepare(); + Controller.StartDetonation(); + } + + /// + /// Stops the nuke + /// + public static void StopNuke() => Controller.CancelDetonation(); + + /// + /// Detonates the nuke + /// + public static void DetonateNuke() => Controller.Detonate(); + + public static void Shake() => Controller.RpcShake(true); + } +} diff --git a/Synapse/Config/ConfigManager.cs b/Synapse/Config/ConfigManager.cs new file mode 100644 index 0000000..f60e89e --- /dev/null +++ b/Synapse/Config/ConfigManager.cs @@ -0,0 +1,30 @@ +using System; +using Synapse.Api.Plugin; + +namespace Synapse.Config +{ + public static class ConfigManager + { + internal static void InitializeConfigs() + { + Plugin.Config = new YamlConfig(Files.ServerConfigFile); + SynapseConfigs.ReloadConfig(); + } + + internal static void ReloadAllConfigs() + { + SynapseConfigs.ReloadConfig(); + Plugin.Config = new YamlConfig(Files.ServerConfigFile); + + foreach (var plugin in Synapse.plugins) + try + { + plugin.InvokeConfigReloadEvent(); + } + catch (Exception e) + { + Log.Error($"Plugin {plugin.Details.Name} threw an exception while reloading {e}"); + } + } + } +} diff --git a/Synapse/Permissions/PermissionReader.cs b/Synapse/Config/PermissionReader.cs similarity index 88% rename from Synapse/Permissions/PermissionReader.cs rename to Synapse/Config/PermissionReader.cs index 7238bc9..05ba04d 100644 --- a/Synapse/Permissions/PermissionReader.cs +++ b/Synapse/Config/PermissionReader.cs @@ -7,28 +7,22 @@ // ReSharper disable All -namespace Synapse.Permissions +namespace Synapse.Config { public static class PermissionReader { // Variables private static Yml _permissionsConfig; - private static readonly string PermissionPath = - Path.Combine(PluginManager.ServerConfigDirectory, "permissions.yml"); - // Methods internal static void Init() { - if (!File.Exists(PermissionPath)) - File.WriteAllText(PermissionPath, "groups:\n user:\n default: true\n permissions:\n - plugin.permission\n northwood:\n northwood: true\n permissions:\n - plugin.permission\n owner:\n permissions:\n - .*"); - ReloadPermission(); } internal static void ReloadPermission() { - var yml = File.ReadAllText(PermissionPath); + var yml = File.ReadAllText(Files.PermissionFile); var deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); @@ -83,7 +77,7 @@ internal static bool CheckPermission(Player player, string permission) if (userGroup != null) { var groupName = ServerStatic.GetPermissionsHandler()._groups - .FirstOrDefault(g => g.Value == player.Hub.serverRoles.Group).Key; + .FirstOrDefault(g => g.Value == player.Rank).Key; if (_permissionsConfig == null) { Log.Error("Permission config is null."); @@ -98,8 +92,9 @@ internal static bool CheckPermission(Player player, string permission) if (!_permissionsConfig.Groups.TryGetValue(groupName, out group)) { - Log.Error("Could not get permission value."); - return false; + Log.Info($"TheServerGroup: {groupName} has no Permission Group!"); + if (player.Hub.serverRoles.Staff || player.UserId.EndsWith("@northwood")) group = GetNwGroup(); + else group = GetDefaultGroup(); } } else diff --git a/Synapse/Configs.cs b/Synapse/Config/SynapseConfigs.cs similarity index 62% rename from Synapse/Configs.cs rename to Synapse/Config/SynapseConfigs.cs index e67e117..f2a3f12 100644 --- a/Synapse/Configs.cs +++ b/Synapse/Config/SynapseConfigs.cs @@ -1,8 +1,9 @@ -using System.IO; +using Synapse.Api.Plugin; +using System.Collections.Generic; -namespace Synapse +namespace Synapse.Config { - internal static class Configs + internal static class SynapseConfigs { // Configs internal static int RequiredForFemur; @@ -10,6 +11,8 @@ internal static class Configs internal static string JoinBroadcast; internal static string JoinTextHint; internal static ushort JoinMessageDuration; + internal static List Speaking_Scps; + internal static bool Nametracking; // Methods internal static void ReloadConfig() @@ -19,6 +22,9 @@ internal static void ReloadConfig() JoinBroadcast = Plugin.Config.GetString("synapse_join_broadcast", ""); JoinTextHint = Plugin.Config.GetString("synapse_join_texthint", ""); JoinMessageDuration = Plugin.Config.GetUShort("synapse_join_duration",5); + Speaking_Scps = Plugin.Config.GetIntList("synapse_speakingscps"); + if (Speaking_Scps == null) Speaking_Scps = new List { 16, 17 }; + Nametracking = Plugin.Config.GetBool("synapse_nametracking",true); } } } diff --git a/Synapse/Events/Classes/PlayerTagEvent.cs b/Synapse/Events/Classes/PlayerTagEvent.cs new file mode 100644 index 0000000..412fb0f --- /dev/null +++ b/Synapse/Events/Classes/PlayerTagEvent.cs @@ -0,0 +1,13 @@ +using Synapse.Api; + +namespace Synapse.Events.Classes +{ + public class PlayerTagEvent + { + public Player Player { get; internal set; } + + public bool ShowTag { get; internal set; } + + public bool Allow { get; set; } + } +} diff --git a/Synapse/Events/Classes/RemoteCommandEvent.cs b/Synapse/Events/Classes/RemoteCommandEvent.cs index 84924c0..dc1c3e0 100644 --- a/Synapse/Events/Classes/RemoteCommandEvent.cs +++ b/Synapse/Events/Classes/RemoteCommandEvent.cs @@ -8,8 +8,8 @@ public class RemoteCommandEvent : EventArgs public CommandSender Sender { get; internal set; } public Player Player => Sender.SenderId == "SERVER CONSOLE" || Sender.SenderId == "GAME CONSOLE" - ? Player.Server - : PlayerExtensions.GetPlayer(Sender.SenderId); + ? Player.Host + : Player.GetPlayer(Sender.SenderId); public bool Allow { get; set; } diff --git a/Synapse/Events/Classes/TeamRespawnEvent.cs b/Synapse/Events/Classes/TeamRespawnEvent.cs index d82509a..1e53e28 100644 --- a/Synapse/Events/Classes/TeamRespawnEvent.cs +++ b/Synapse/Events/Classes/TeamRespawnEvent.cs @@ -5,12 +5,8 @@ namespace Synapse.Events.Classes { public class TeamRespawnEvent { - public bool IsChaos { get; set; } + public Respawning.SpawnableTeamType Team { get; set; } public List RespawnList { get; set; } - - public bool Allow { get; set; } - - public bool UseTickets { get; set; } } } diff --git a/Synapse/Events/Classes/UseItemEvent.cs b/Synapse/Events/Classes/UseItemEvent.cs index 44f9f28..a2ad937 100644 --- a/Synapse/Events/Classes/UseItemEvent.cs +++ b/Synapse/Events/Classes/UseItemEvent.cs @@ -6,6 +6,8 @@ public class UseItemEvent { public Player Player { get; internal set; } - public bool Allow { get; internal set; } + public ItemType Item { get; internal set; } + + public bool Allow { get; set; } } } diff --git a/Synapse/Events/EventHandlers.cs b/Synapse/Events/EventHandlers.cs index 84a48e7..6b54387 100644 --- a/Synapse/Events/EventHandlers.cs +++ b/Synapse/Events/EventHandlers.cs @@ -1,10 +1,8 @@ -using System.Collections.Generic; -using System.Linq; -using MEC; +using System.Linq; using Synapse.Api; using Synapse.Api.Enums; using Synapse.Events.Classes; -using Synapse.Permissions; +using Synapse.Config; using UnityEngine; namespace Synapse.Events @@ -12,45 +10,38 @@ namespace Synapse.Events // ReSharper disable once UnusedType.Global internal class EventHandlers { - // Variables - private bool _roundInProgress; - - // ReSharper disable once NotAccessedField.Local - private int _roundTime; - // Constructor public EventHandlers() { Events.SyncDataEvent += OnSyncData; Events.RemoteCommandEvent += OnRemoteCommand; - Events.RoundStartEvent += OnRoundStart; - Events.RoundEndEvent += OnRoundEnd; - Events.RoundRestartEvent += OnRoundRestart; Events.DoorInteractEvent += OnDoorInteract; Events.PlayerJoinEvent += OnPlayerJoin; } // Methods - private void OnPlayerJoin(ref PlayerJoinEvent ev) + private void OnPlayerJoin(PlayerJoinEvent ev) { - ev.Player.Broadcast(Configs.JoinMessageDuration,Configs.JoinBroadcast); - ev.Player.GiveTextHint(Configs.JoinTextHint, Configs.JoinMessageDuration); + ev.Player.Broadcast(SynapseConfigs.JoinMessageDuration, SynapseConfigs.JoinBroadcast); + ev.Player.GiveTextHint(SynapseConfigs.JoinTextHint, SynapseConfigs.JoinMessageDuration); } - private static void OnDoorInteract(ref DoorInteractEvent ev) + private static void OnDoorInteract(DoorInteractEvent ev) { - if (!Configs.RemoteKeyCard) return; + if (!SynapseConfigs.RemoteKeyCard) return; if (ev.Allow) return; if (!ev.Player.Items.Any()) return; - var itemPerms = ev.Player.Inventory.GetItemByID(ev.Player.Inventory.curItem).permissions; - var door = ev.Door; - ev.Allow = itemPerms.Any(p => - door.backwardsCompatPermissions.TryGetValue(p, out var flag) && - door.PermissionLevels.HasPermission(flag)); + foreach (var item in ev.Player.Items) + { + var itemPerms = ev.Player.Inventory.GetItemByID(item.id).permissions; + ev.Allow = itemPerms.Any(p => + ev.Door.backwardsCompatPermissions.TryGetValue(p, out var flag) && + ev.Door.PermissionLevels.HasPermission(flag)); + } } - private static void OnSyncData(ref SyncDataEvent ev) + private static void OnSyncData(SyncDataEvent ev) { if (ev.Player.Role != RoleType.ClassD && ev.Player.Role != RoleType.Scientist && @@ -58,7 +49,7 @@ private static void OnSyncData(ref SyncDataEvent ev) ev.Player.Hub.characterClassManager.CmdRegisterEscape(); } - private static void OnRemoteCommand(ref RemoteCommandEvent ev) + private static void OnRemoteCommand(RemoteCommandEvent ev) { var args = ev.Command.Split(' '); switch (args[0].ToUpper()) @@ -85,37 +76,10 @@ private static void OnRemoteCommand(ref RemoteCommandEvent ev) return; } - PluginManager.OnConfigReload(); + ConfigManager.ReloadAllConfigs(); ev.Sender.RaMessage("Configs Reloaded!", true, RaCategory.ServerConfigs); return; } } - - private void OnRoundStart() - { - Timing.RunCoroutine(RoundTime()); - _roundInProgress = true; - } - - private void OnRoundEnd() - { - _roundInProgress = false; - } - - private void OnRoundRestart() - { - _roundInProgress = false; - Map.Rooms.Clear(); - } - - private IEnumerator RoundTime() - { - for (;;) - { - yield return Timing.WaitForSeconds(1f); - _roundTime++; - if (!_roundInProgress) break; - } - } } } \ No newline at end of file diff --git a/Synapse/Events/MapEvents.cs b/Synapse/Events/MapEvents.cs index 23ff2b0..6811ff3 100644 --- a/Synapse/Events/MapEvents.cs +++ b/Synapse/Events/MapEvents.cs @@ -8,7 +8,7 @@ namespace Synapse.Events public static partial class Events { // DoorInteractEvent - public delegate void OnDoorInteract(ref DoorInteractEvent ev); + public delegate void OnDoorInteract(DoorInteractEvent ev); public static event OnDoorInteract DoorInteractEvent; @@ -23,12 +23,12 @@ internal static void InvokeDoorInteraction(Player player, Door door, ref bool al Door = door }; - DoorInteractEvent.Invoke(ref ev); + DoorInteractEvent.Invoke(ev); allow = ev.Allow; } //TeslaTriggerEvent - public delegate void OnTriggerTesla(ref TeslaTriggerEvent ev); + public delegate void OnTriggerTesla(TeslaTriggerEvent ev); public static event OnTriggerTesla TeslaTriggerEvent; internal static void InvokeTeslaTrigger(Player player, bool inRange, ref bool activated) @@ -42,7 +42,7 @@ internal static void InvokeTeslaTrigger(Player player, bool inRange, ref bool ac Triggerable = activated }; - TeslaTriggerEvent?.Invoke(ref ev); + TeslaTriggerEvent?.Invoke(ev); activated = ev.Triggerable; } diff --git a/Synapse/Events/Patches/CheckRoundEndPatch.cs b/Synapse/Events/Patches/CheckRoundEndPatch.cs index d4f32b7..cf47e59 100644 --- a/Synapse/Events/Patches/CheckRoundEndPatch.cs +++ b/Synapse/Events/Patches/CheckRoundEndPatch.cs @@ -115,7 +115,7 @@ public static IEnumerator ProcessServerSide(RoundSummary instance) roundSummary._roundEnded = true; } - else if (mtfSum == 0 && PlayerManager.localPlayer.GetComponent().MtfRespawnTickets == 0) + else if (mtfSum == 0 && Respawning.RespawnTickets.Singleton.GetAvailableTickets(Respawning.SpawnableTeamType.NineTailedFox) == 0) { roundSummary._roundEnded = true; } diff --git a/Synapse/Events/Patches/DoorInteractPatch.cs b/Synapse/Events/Patches/DoorInteractPatch.cs index d408c13..9cf892f 100644 --- a/Synapse/Events/Patches/DoorInteractPatch.cs +++ b/Synapse/Events/Patches/DoorInteractPatch.cs @@ -18,9 +18,9 @@ public static bool Prefix(PlayerInteract __instance, GameObject doorId) if (!__instance._playerInteractRateLimit.CanExecute() || (__instance._hc.CufferId > 0 && !PlayerInteract.CanDisarmedInteract) || doorId == null || __instance._ccm.CurClass == RoleType.None || __instance._ccm.CurClass == RoleType.Spectator || - !doorId.TryGetComponent(out door) || !((door.buttons.Count == 0) + !doorId.TryGetComponent(out door) || !((door.Buttons.Count == 0) ? __instance.ChckDis(doorId.transform.position) - : door.buttons.Any(item => __instance.ChckDis(item.transform.position)))) return false; + : door.Buttons.Any(item => __instance.ChckDis(item.button.transform.position)))) return false; __instance.OnInteract(); diff --git a/Synapse/Events/Patches/FemurEnterPatch.cs b/Synapse/Events/Patches/FemurEnterPatch.cs index ab9e314..393cf23 100644 --- a/Synapse/Events/Patches/FemurEnterPatch.cs +++ b/Synapse/Events/Patches/FemurEnterPatch.cs @@ -2,6 +2,7 @@ using Harmony; using Mirror; using Synapse.Api; +using Synapse.Config; using UnityEngine; namespace Synapse.Events.Patches @@ -27,7 +28,7 @@ public static bool Prefix(CharacterClassManager __instance) if (component.CurClass == RoleType.Spectator || component.GodMode) continue; var allow = component.CurRole.team != Team.SCP; - var closeFemur = FemurBrokePeople + 1 >= Configs.RequiredForFemur; + var closeFemur = FemurBrokePeople + 1 >= SynapseConfigs.RequiredForFemur; var player = __instance.GetPlayer(); Events.InvokeFemurEnterEvent(player, ref allow, ref closeFemur); diff --git a/Synapse/Events/Patches/PickUpItemPatch.cs b/Synapse/Events/Patches/PickUpItemPatch.cs index 337acd4..2a59d08 100644 --- a/Synapse/Events/Patches/PickUpItemPatch.cs +++ b/Synapse/Events/Patches/PickUpItemPatch.cs @@ -28,8 +28,10 @@ public static bool Prefix(SearchCoordinator __instance) } } } - - __instance.SessionPipe.Invalidate(); + else + { + __instance.SessionPipe.Invalidate(); + } return false; } diff --git a/Synapse/Events/Patches/PlayerBanPatch.cs b/Synapse/Events/Patches/PlayerBanPatch.cs index 10f3fb2..e97cd73 100644 --- a/Synapse/Events/Patches/PlayerBanPatch.cs +++ b/Synapse/Events/Patches/PlayerBanPatch.cs @@ -1,7 +1,7 @@ using System; +using Synapse.Api; using GameCore; using Harmony; -using Synapse.Api; using UnityEngine; namespace Synapse.Events.Patches @@ -15,7 +15,7 @@ public static bool Prefix(GameObject user, int duration, string reason, string i try { var player = user.GetPlayer(); - var banIssuer = PlayerExtensions.GetPlayer(issuer); + var banIssuer = Player.GetPlayer(issuer); var allow = true; Events.InvokePlayerBanEvent(player, duration, ref allow, reason, banIssuer); diff --git a/Synapse/Events/Patches/PlayerDamagePatch.cs b/Synapse/Events/Patches/PlayerDamagePatch.cs index 15d96fb..fd99663 100644 --- a/Synapse/Events/Patches/PlayerDamagePatch.cs +++ b/Synapse/Events/Patches/PlayerDamagePatch.cs @@ -17,7 +17,7 @@ public static void Prefix(PlayerStats __instance, ref PlayerStats.HitInfo info, var killer = __instance.GetPlayer(); if (info.GetDamageType() == DamageTypes.Grenade) - killer = PlayerExtensions.GetPlayer(info.PlayerId); + killer = Player.GetPlayer(info.PlayerId); var player = go.GetPlayer(); diff --git a/Synapse/Events/Patches/PlayerEscapePatch.cs b/Synapse/Events/Patches/PlayerEscapePatch.cs index f499689..f3784ac 100644 --- a/Synapse/Events/Patches/PlayerEscapePatch.cs +++ b/Synapse/Events/Patches/PlayerEscapePatch.cs @@ -52,7 +52,7 @@ public static bool Prefix(CharacterClassManager __instance) } //TeamCheck - var component3 = PlayerManager.localPlayer.GetComponent(); + Respawning.RespawnTickets singleton = Respawning.RespawnTickets.Singleton; var team = __instance.CurRole.team; switch (team) { @@ -79,13 +79,11 @@ public static bool Prefix(CharacterClassManager __instance) { case Team.MTF: RoundSummary.escaped_scientists++; - component3.MtfRespawnTickets += - ConfigFile.ServerConfig.GetInt("respawn_tickets_mtf_scientist_count", 1); + singleton.GrantTickets(Respawning.SpawnableTeamType.NineTailedFox, GameCore.ConfigFile.ServerConfig.GetInt("respawn_tickets_mtf_classd_cuffed_count", 1), false); break; case Team.CHI: RoundSummary.escaped_ds++; - component3.ChaosRespawnTickets += - ConfigFile.ServerConfig.GetInt("respawn_tickets_ci_scientist_cuffed_count", 2); + singleton.GrantTickets(Respawning.SpawnableTeamType.ChaosInsurgency, GameCore.ConfigFile.ServerConfig.GetInt("respawn_tickets_ci_classd_count", 1), false); break; } diff --git a/Synapse/Events/Patches/ServerNamePatch.cs b/Synapse/Events/Patches/ServerNamePatch.cs index 8308a8b..f22eefb 100644 --- a/Synapse/Events/Patches/ServerNamePatch.cs +++ b/Synapse/Events/Patches/ServerNamePatch.cs @@ -1,4 +1,5 @@ using Harmony; +using Synapse.Config; namespace Synapse.Events.Patches { @@ -7,8 +8,9 @@ public static class ServerNamePatch { public static void Postfix() { - ServerConsole._serverName = ServerConsole._serverName.Replace("SM119.0.0", ""); - ServerConsole._serverName += " SMSynapse-ModLoader v.1.0-beta"; + if (!SynapseConfigs.Nametracking) return; + + ServerConsole._serverName += $" SMSynapse-ModLoader {Synapse.Version}"; } } } \ No newline at end of file diff --git a/Synapse/Events/Patches/SpeakPatch.cs b/Synapse/Events/Patches/SpeakPatch.cs index 6ceba47..a91f746 100644 --- a/Synapse/Events/Patches/SpeakPatch.cs +++ b/Synapse/Events/Patches/SpeakPatch.cs @@ -1,6 +1,8 @@ using System; using Assets._Scripts.Dissonance; using Harmony; +using Synapse.Api; +using Synapse.Config; namespace Synapse.Events.Patches { @@ -18,6 +20,8 @@ public static bool Prefix(DissonanceUserSetup __instance, bool value) var scpchat = __instance.SCPChat; var spectator = __instance.SpectatorChat; + scp939 = SynapseConfigs.Speaking_Scps.Contains((int)__instance.GetPlayer().Role); + Events.InvokeSpeakEvent(__instance, ref intercom, ref radio, ref scp939, ref scpchat, ref spectator); __instance.SCPChat = scpchat; diff --git a/Synapse/Events/Patches/TagPatch.cs b/Synapse/Events/Patches/TagPatch.cs new file mode 100644 index 0000000..1b74072 --- /dev/null +++ b/Synapse/Events/Patches/TagPatch.cs @@ -0,0 +1,42 @@ +using System; +using Harmony; +using Synapse.Api; + +namespace Synapse.Events.Patches +{ + [HarmonyPatch(typeof(CharacterClassManager), nameof(CharacterClassManager.CallCmdRequestShowTag))] + public static class ShowTag + { + public static bool Prefix(CharacterClassManager __instance) + { + try + { + Events.InvokePlayerTagEvent(__instance.GetPlayer(), true, out bool allow); + return allow; + } + catch (Exception e) + { + Log.Error($"PlayerTagEvent Error: {e}"); + return true; + } + } + } + + [HarmonyPatch(typeof(CharacterClassManager), nameof(CharacterClassManager.CallCmdRequestHideTag))] + public static class HideTag + { + public static bool Prefix(CharacterClassManager __instance) + { + try + { + Events.InvokePlayerTagEvent(__instance.GetPlayer(), false, out bool allow); + return allow; + } + catch(Exception e) + { + Log.Error($"PlayerTagEvent Error: {e}"); + return true; + } + } + } +} diff --git a/Synapse/Events/Patches/TeamRespawnPatch.cs b/Synapse/Events/Patches/TeamRespawnPatch.cs index 81bcce0..acd8a15 100644 --- a/Synapse/Events/Patches/TeamRespawnPatch.cs +++ b/Synapse/Events/Patches/TeamRespawnPatch.cs @@ -1,98 +1,114 @@ using System; using System.Collections.Generic; using System.Linq; -using GameCore; using Harmony; +using Respawning; using Synapse.Api; using UnityEngine; namespace Synapse.Events.Patches { - [HarmonyPatch(typeof(MTFRespawn), nameof(MTFRespawn.RespawnDeadPlayers))] + [HarmonyPatch(typeof(RespawnManager), nameof(RespawnManager.Spawn))] public static class TeamRespawnPatch { - public static bool Prefix(MTFRespawn __instance) + public static bool Prefix(Respawning.RespawnManager __instance) { try { - var num = 0; - var enumerable = PlayerManager.players.Where(item => - item.GetComponent().CurClass == RoleType.Spectator && - !item.GetComponent().OverwatchEnabled); - - if (__instance.priorityMTFRespawn) - enumerable = enumerable.OrderBy(item => item.GetComponent().DeathTime); - - var num2 = __instance.nextWaveIsCI ? __instance.maxCIRespawnAmount : __instance.maxMTFRespawnAmount; - if (ConfigFile.ServerConfig.GetBool("respawn_tickets_enable", true)) - { - if (__instance.NextWaveRespawnTickets == 0) - { - if (__instance.nextWaveIsCI) - { - __instance._ciDisabled = true; - return false; - } - - RoundSummary.singleton.ForceEnd(); - return false; - } - - num2 = Mathf.Min(num2, __instance.NextWaveRespawnTickets); - } - - var list = enumerable.Take(num2).ToList(); - - //Event - var allow = true; - var useTickets = true; - - var respawnList = list.Select(player => player.GetPlayer()).ToList(); - - Events.InvokeTeamRespawnEvent(ref respawnList,ref __instance.nextWaveIsCI,ref allow,ref useTickets); - - if (!allow) return false; - list.Clear(); - list.AddRange(respawnList.Select(hub => hub.gameObject)); - - if (useTickets) __instance.NextWaveRespawnTickets -= num2 - list.Count; - - if (ConfigFile.ServerConfig.GetBool("use_crypto_rng")) - list.ShuffleListSecure(); - else - list.ShuffleList(); - - __instance.playersToNTF.Clear(); - if (__instance.nextWaveIsCI && AlphaWarheadController.Host.detonated) __instance.nextWaveIsCI = false; - foreach (var gameObject in list.Where(gameObject => !(gameObject == null))) - { - num++; - if (__instance.nextWaveIsCI) - { - __instance.GetComponent() - .SetPlayersClass(RoleType.ChaosInsurgency, gameObject); - ServerLogs.AddLog(ServerLogs.Modules.ClassChange, - gameObject.GetComponent().MyNick + " (" + - gameObject.GetComponent().UserId + - ") respawned as Chaos Insurgency agent.", ServerLogs.ServerLogType.GameEvent); - } - else - { - __instance.playersToNTF.Add(gameObject); - } - } - - if (num > 0) - { - ServerLogs.AddLog(ServerLogs.Modules.ClassChange, - (__instance.nextWaveIsCI ? "Chaos Insurgency" : "MTF") + " respawned!", - ServerLogs.ServerLogType.GameEvent); - if (__instance.nextWaveIsCI) __instance.Invoke("CmdDelayCIAnnounc", 1f); - } - - __instance.SummonNTF(); - - return false; + if (!RespawnWaveGenerator.SpawnableTeams.TryGetValue(__instance.NextKnownTeam, out SpawnableTeam spawnableTeam) || __instance.NextKnownTeam == SpawnableTeamType.None) + { + ServerConsole.AddLog("Fatal error. Team '" + __instance.NextKnownTeam.ToString() + "' is undefined.", (ConsoleColor)12); + return false; + } + List list = Enumerable.ToList(Enumerable.Where(ReferenceHub.GetAllHubs().Values, (ReferenceHub item) => item.characterClassManager.CurClass == RoleType.Spectator && !item.serverRoles.OverwatchEnabled)); + if (__instance._prioritySpawn) + { + list = Enumerable.ToList(Enumerable.OrderBy(list, (ReferenceHub item) => item.characterClassManager.DeathTime)); + } + else + { + list.ShuffleList(); + } + RespawnTickets singleton = RespawnTickets.Singleton; + int num = singleton.GetAvailableTickets(__instance.NextKnownTeam); + if (num == 0) + { + num = singleton.DefaultTeamAmount; + RespawnTickets.Singleton.GrantTickets(singleton.DefaultTeam, singleton.DefaultTeamAmount, true); + } + int num2 = Mathf.Min(num, spawnableTeam.MaxWaveSize); + while (list.Count > num2) + { + list.RemoveAt(list.Count - 1); + } + list.ShuffleList(); + List list2 = ListPool.Rent(); + + var Playerlist = new List(); + foreach (ReferenceHub hub in list) + Playerlist.Add(hub.GetPlayer()); + + Events.InvokeTeamRespawnEvent(ref Playerlist,ref __instance.NextKnownTeam); + + if (__instance.NextKnownTeam == SpawnableTeamType.None) + return false; + + foreach (var player in Playerlist) + { + try + { + RoleType classid = spawnableTeam.ClassQueue[Mathf.Min(list2.Count, spawnableTeam.ClassQueue.Length - 1)]; + player.ClassManager.SetPlayersClass(classid, player.gameObject, false, false); + list2.Add(player.Hub); + ServerLogs.AddLog(ServerLogs.Modules.ClassChange, string.Concat(new string[] + { + "Player ", + player.Hub.LoggedNameFromRefHub(), + " respawned as ", + classid.ToString(), + "." + }), ServerLogs.ServerLogType.GameEvent, false); + } + catch (Exception ex) + { + if (player != null) + { + ServerLogs.AddLog(ServerLogs.Modules.ClassChange, "Player " + player.Hub.LoggedNameFromRefHub() + " couldn't be spawned. Err msg: " + ex.Message, ServerLogs.ServerLogType.GameEvent, false); + } + else + { + ServerLogs.AddLog(ServerLogs.Modules.ClassChange, "Couldn't spawn a player - target's ReferenceHub is null.", ServerLogs.ServerLogType.GameEvent, false); + } + } + } + if (list2.Count > 0) + { + ServerLogs.AddLog(ServerLogs.Modules.ClassChange, string.Concat(new object[] + { + "RespawnManager has successfully spawned ", + list2.Count, + " players as ", + __instance.NextKnownTeam.ToString(), + "!" + }), ServerLogs.ServerLogType.GameEvent, false); + RespawnTickets.Singleton.GrantTickets(__instance.NextKnownTeam, -list2.Count * spawnableTeam.TicketRespawnCost, false); + Respawning.NamingRules.UnitNamingRule unitNamingRule; + if (Respawning.NamingRules.UnitNamingRules.TryGetNamingRule(__instance.NextKnownTeam, out unitNamingRule)) + { + string text; + unitNamingRule.GenerateNew(__instance.NextKnownTeam, out text); + foreach (ReferenceHub referenceHub2 in list2) + { + referenceHub2.characterClassManager.NetworkCurSpawnableTeamType = (byte)__instance.NextKnownTeam; + referenceHub2.characterClassManager.NetworkCurUnitName = text; + } + unitNamingRule.PlayEntranceAnnouncement(text); + } + RespawnEffectsController.ExecuteAllEffects(RespawnEffectsController.EffectType.UponRespawn, __instance.NextKnownTeam); + } + __instance.NextKnownTeam = SpawnableTeamType.None; + + return false; } catch (Exception e) { diff --git a/Synapse/Events/Patches/UseItemPatch.cs b/Synapse/Events/Patches/UseItemPatch.cs index 824b3bb..a961590 100644 --- a/Synapse/Events/Patches/UseItemPatch.cs +++ b/Synapse/Events/Patches/UseItemPatch.cs @@ -11,7 +11,7 @@ public static bool Prefix(ConsumableAndWearableItems __instance) { try { - Events.InvokeUseItemEvent(__instance.GetPlayer(),out bool allow); + Events.InvokeUseItemEvent(__instance.GetPlayer(), __instance._hub.inventory.curItem,out bool allow); return allow; } catch (Exception e) diff --git a/Synapse/Events/PlayerEvents.cs b/Synapse/Events/PlayerEvents.cs index 44e0c52..1192f9a 100644 --- a/Synapse/Events/PlayerEvents.cs +++ b/Synapse/Events/PlayerEvents.cs @@ -12,7 +12,7 @@ public static partial class Events { /// A Event which is activated when a User Joins the Server /// It need to hook ref PlayerJoinEvent ev - public delegate void OnPlayerJoin(ref PlayerJoinEvent ev); + public delegate void OnPlayerJoin(PlayerJoinEvent ev); public static event OnPlayerJoin PlayerJoinEvent; internal static void InvokePlayerJoinEvent(Player player, ref string nick) @@ -24,13 +24,13 @@ internal static void InvokePlayerJoinEvent(Player player, ref string nick) Nick = nick }; - PlayerJoinEvent.Invoke(ref ev); + PlayerJoinEvent.Invoke(ev); nick = ev.Nick; } /// A Event which is activated when a user press any voice HotKey - public delegate void OnSpeak(ref PlayerSpeakEvent ev); + public delegate void OnSpeak(PlayerSpeakEvent ev); public static event OnSpeak SpeakEvent; internal static void InvokeSpeakEvent(DissonanceUserSetup dissonance, ref bool intercom, ref bool radio, @@ -49,7 +49,7 @@ internal static void InvokeSpeakEvent(DissonanceUserSetup dissonance, ref bool i Player = dissonance.gameObject.GetPlayer() }; - SpeakEvent.Invoke(ref ev); + SpeakEvent.Invoke(ev); intercom = ev.IntercomTalk; radio = ev.RadioTalk; @@ -76,7 +76,7 @@ internal static void InvokePlayerLeaveEvent(Player player) } // PlayerBanEvent - public delegate void OnPlayerBanEvent(ref PlayerBanEvent ev); + public delegate void OnPlayerBanEvent(PlayerBanEvent ev); public static event OnPlayerBanEvent PlayerBanEvent; internal static void InvokePlayerBanEvent(Player player, int duration, ref bool allow, @@ -92,7 +92,7 @@ internal static void InvokePlayerBanEvent(Player player, int duration, ref bool BannedPlayer = player }; - PlayerBanEvent.Invoke(ref ev); + PlayerBanEvent.Invoke(ev); allow = ev.Allowed; } @@ -116,7 +116,7 @@ internal static void InvokePlayerDieEvent(Player player, Player killer, PlayerSt } //PlayerHurtEvent - public delegate void OnPlayerHurt(ref PlayerHurtEvent ev); + public delegate void OnPlayerHurt(PlayerHurtEvent ev); public static event OnPlayerHurt PlayerHurtEvent; internal static void InvokePlayerHurtEvent(Player player, Player attacker, @@ -131,13 +131,13 @@ internal static void InvokePlayerHurtEvent(Player player, Player attacker, Info = info }; - PlayerHurtEvent.Invoke(ref ev); + PlayerHurtEvent.Invoke(ev); info = ev.Info; } //PlayerCuffedEvent - public delegate void OnPlayerCuffed(ref PlayerCuffedEvent ev); + public delegate void OnPlayerCuffed(PlayerCuffedEvent ev); public static event OnPlayerCuffed PlayerCuffedEvent; internal static void InvokePlayerCuffedEvent(Player cuffed, Player target, ref bool allow) @@ -151,13 +151,13 @@ internal static void InvokePlayerCuffedEvent(Player cuffed, Player target, ref b Allow = allow }; - PlayerCuffedEvent.Invoke(ref ev); + PlayerCuffedEvent.Invoke(ev); allow = ev.Allow; } //PlayerEscapeEvent - public delegate void OnPlayerEscape(ref PlayerEscapeEvent ev); + public delegate void OnPlayerEscape(PlayerEscapeEvent ev); public static event OnPlayerEscape PlayerEscapeEvent; internal static void InvokePlayerEscapeEvent(Player player, ref bool allow, ref RoleType spawnRole, @@ -174,14 +174,14 @@ internal static void InvokePlayerEscapeEvent(Player player, ref bool allow, ref IsCuffed = isCuffed }; - PlayerEscapeEvent.Invoke(ref ev); + PlayerEscapeEvent.Invoke(ev); allow = ev.Allow; spawnRole = ev.SpawnRole; } //SyncDataEvent - public delegate void OnSyncDataEvent(ref SyncDataEvent ev); + public delegate void OnSyncDataEvent(SyncDataEvent ev); public static event OnSyncDataEvent SyncDataEvent; internal static void InvokeSyncDataEvent(Player player, ref bool allow, ref Vector2 speed, int state) @@ -196,14 +196,14 @@ internal static void InvokeSyncDataEvent(Player player, ref bool allow, ref Vect State = state }; - SyncDataEvent.Invoke(ref ev); + SyncDataEvent.Invoke(ev); allow = ev.Allow; speed = ev.Speed; } //PlayerReloadEvent - public delegate void OnPlayerReload(ref PlayerReloadEvent ev); + public delegate void OnPlayerReload(PlayerReloadEvent ev); public static event OnPlayerReload PlayerReloadEvent; internal static void InvokePlayerReloadEvent(Player player, ref bool allow, Inventory.SyncItemInfo syncItem) @@ -217,13 +217,13 @@ internal static void InvokePlayerReloadEvent(Player player, ref bool allow, Inve InventorySlot = syncItem }; - PlayerReloadEvent.Invoke(ref ev); + PlayerReloadEvent.Invoke(ev); allow = ev.Allow; } //FemurEnterEvent - public delegate void OnFemurEnter(ref FemurEnterEvent ev); + public delegate void OnFemurEnter(FemurEnterEvent ev); public static event OnFemurEnter FemurEnterEvent; internal static void InvokeFemurEnterEvent(Player player,ref bool allow,ref bool closeFemur) @@ -237,13 +237,13 @@ internal static void InvokeFemurEnterEvent(Player player,ref bool allow,ref bool CloseFemur = closeFemur }; - FemurEnterEvent.Invoke(ref ev); + FemurEnterEvent.Invoke(ev); allow = ev.Allow; closeFemur = ev.CloseFemur; } //DroppedItemEvent - public delegate void OnDropItem(ref DropItemEvent ev); + public delegate void OnDropItem(DropItemEvent ev); public static event OnDropItem DropItemEvent; internal static void InvokeDropItem(Player player, ref Inventory.SyncItemInfo item, ref bool allow) @@ -257,7 +257,7 @@ internal static void InvokeDropItem(Player player, ref Inventory.SyncItemInfo it Allow = allow }; - DropItemEvent.Invoke(ref ev); + DropItemEvent.Invoke(ev); allow = ev.Allow; item = ev.Item; @@ -267,8 +267,8 @@ internal static void InvokeDropItem(Player player, ref Inventory.SyncItemInfo it public static event OnLoadComponents LoadComponentsEvent; internal static void InvokeLoadComponents(GameObject player) => LoadComponentsEvent?.Invoke(new LoadComponentsEvent { Player = player }); - public delegate void OnGeneratorInserted(ref GeneratorEvent ev); - public static event OnGeneratorInserted GeneratorInsertedEvent; + public delegate void OnGenerator(GeneratorEvent ev); + public static event OnGenerator GeneratorInsertedEvent; internal static void InvokeGeneratorInserted(Player player, Generator079 generator, ref bool allow) { if (GeneratorInsertedEvent == null) return; @@ -280,13 +280,12 @@ internal static void InvokeGeneratorInserted(Player player, Generator079 generat Player = player }; - GeneratorInsertedEvent.Invoke(ref ev); + GeneratorInsertedEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnGeneratorEjected(ref GeneratorEvent ev); - public static event OnGeneratorEjected GeneratorEjectedEvent; + public static event OnGenerator GeneratorEjectedEvent; internal static void InvokeGeneratorEjected(Player player, Generator079 generator, ref bool allow) { if (GeneratorEjectedEvent == null) return; @@ -298,13 +297,12 @@ internal static void InvokeGeneratorEjected(Player player, Generator079 generato Player = player }; - GeneratorEjectedEvent.Invoke(ref ev); + GeneratorEjectedEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnGeneratorUnlock(ref GeneratorEvent ev); - public static event OnGeneratorUnlock GeneratorUnlockEvent; + public static event OnGenerator GeneratorUnlockEvent; internal static void InvokeGeneratorUnlock(Player player,Generator079 generator, ref bool allow) { if (GeneratorUnlockEvent == null) return; @@ -316,13 +314,12 @@ internal static void InvokeGeneratorUnlock(Player player,Generator079 generator, Player = player }; - GeneratorUnlockEvent.Invoke(ref ev); + GeneratorUnlockEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnGeneratorOpen(ref GeneratorEvent ev); - public static event OnGeneratorOpen GeneratorOpenEvent; + public static event OnGenerator GeneratorOpenEvent; internal static void InvokeGeneratorOpen(Player player, Generator079 generator, ref bool allow) { if (GeneratorOpenEvent == null) return; @@ -334,13 +331,12 @@ internal static void InvokeGeneratorOpen(Player player, Generator079 generator, Player = player }; - GeneratorOpenEvent.Invoke(ref ev); + GeneratorOpenEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnGeneratorClose(ref GeneratorEvent ev); - public static event OnGeneratorClose GeneratorCloseEvent; + public static event OnGenerator GeneratorCloseEvent; internal static void InvokeGeneratorClose(Player player, Generator079 generator, ref bool allow) { if (GeneratorCloseEvent == null) return; @@ -352,14 +348,14 @@ internal static void InvokeGeneratorClose(Player player, Generator079 generator, Player = player }; - GeneratorCloseEvent.Invoke(ref ev); + GeneratorCloseEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnUseItem(ref UseItemEvent ev); + public delegate void OnUseItem(UseItemEvent ev); public static event OnUseItem UseItemEvent; - internal static void InvokeUseItemEvent(Player player, out bool allow) + internal static void InvokeUseItemEvent(Player player,ItemType item, out bool allow) { allow = true; if (UseItemEvent == null) return; @@ -367,15 +363,16 @@ internal static void InvokeUseItemEvent(Player player, out bool allow) var ev = new UseItemEvent { Player = player, + Item = item, Allow = true }; - UseItemEvent.Invoke(ref ev); + UseItemEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnPickupItem(ref PickupItemEvent ev); + public delegate void OnPickupItem(PickupItemEvent ev); public static event OnPickupItem PickupItemEvent; internal static void InvokePickupItemEvent(Player player, Pickup pickup, ref bool allow) { @@ -388,12 +385,12 @@ internal static void InvokePickupItemEvent(Player player, Pickup pickup, ref boo Player = player }; - PickupItemEvent.Invoke(ref ev); + PickupItemEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnSetPlayerClass(ref PlayerSetClassEvent ev); + public delegate void OnSetPlayerClass(PlayerSetClassEvent ev); public static event OnSetPlayerClass PlayerSetClassEvent; @@ -406,10 +403,30 @@ internal static void InvokePlayerSetClassEvent(Player player, ref RoleType type, Role = type }; - PlayerSetClassEvent?.Invoke(ref ev); + PlayerSetClassEvent?.Invoke(ev); items = ev.Items; type = ev.Role; } + + + public delegate void OnPlayerTag(PlayerTagEvent ev); + public static event OnPlayerTag PlayerTagEvent; + internal static void InvokePlayerTagEvent(Player player, bool show,out bool allow) + { + allow = true; + if (PlayerTagEvent == null) return; + + var ev = new PlayerTagEvent + { + Player = player, + ShowTag = show, + Allow = true + }; + + PlayerTagEvent.Invoke(ev); + + allow = ev.Allow; + } } } \ No newline at end of file diff --git a/Synapse/Events/ScpEvents.cs b/Synapse/Events/ScpEvents.cs index 6023b21..504324b 100644 --- a/Synapse/Events/ScpEvents.cs +++ b/Synapse/Events/ScpEvents.cs @@ -6,7 +6,7 @@ namespace Synapse.Events public static partial class Events { /// A Event which is activated when Scp049 respawns a Player - public delegate void OnScp049Recall(ref Scp049RecallEvent ev); + public delegate void OnScp049Recall(Scp049RecallEvent ev); public static event OnScp049Recall Scp049RecallEvent; internal static void InvokeScp049RecallEvent(Player player, ref Ragdoll ragdoll, ref Player target, @@ -24,7 +24,7 @@ internal static void InvokeScp049RecallEvent(Player player, ref Ragdoll ragdoll, Player = player }; - Scp049RecallEvent.Invoke(ref ev); + Scp049RecallEvent.Invoke(ev); ragdoll = ev.Ragdoll; target = ev.Target; @@ -33,7 +33,7 @@ internal static void InvokeScp049RecallEvent(Player player, ref Ragdoll ragdoll, allow = ev.Allow; } - public delegate void OnPocketDimensionEnter(ref PocketDimensionEvent ev); + public delegate void OnPocketDimensionEnter(PocketDimensionEvent ev); public static event OnPocketDimensionEnter PocketDimensionEnterEvent; internal static void InvokePocketDimensionEnterEvent(Player player, ref bool allow) @@ -46,12 +46,12 @@ internal static void InvokePocketDimensionEnterEvent(Player player, ref bool all Allow = allow }; - PocketDimensionEnterEvent.Invoke(ref ev); + PocketDimensionEnterEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnScp106Containment(ref Scp106ContainmentEvent ev); + public delegate void OnScp106Containment(Scp106ContainmentEvent ev); public static event OnScp106Containment Scp106ContainmentEvent; internal static void InvokeScp106ContainmentEvent(Player player, ref bool allow) @@ -64,13 +64,13 @@ internal static void InvokeScp106ContainmentEvent(Player player, ref bool allow) Allow = allow }; - Scp106ContainmentEvent.Invoke(ref ev); + Scp106ContainmentEvent.Invoke(ev); allow = ev.Allow; } - public delegate void OnScp079GainLvl(ref Scp079GainLvlEvent ev); + public delegate void OnScp079GainLvl(Scp079GainLvlEvent ev); public static event OnScp079GainLvl Scp079GainLvlEvent; internal static void InvokeScp079LvlEvent(Player player,ref int newlvl,ref bool allow) { @@ -83,7 +83,7 @@ internal static void InvokeScp079LvlEvent(Player player,ref int newlvl,ref bool Player = player }; - Scp079GainLvlEvent.Invoke(ref ev); + Scp079GainLvlEvent.Invoke(ev); newlvl = ev.NewLvl; allow = ev.Allow; diff --git a/Synapse/Events/ServerEvents.cs b/Synapse/Events/ServerEvents.cs index d716a86..6b5926d 100644 --- a/Synapse/Events/ServerEvents.cs +++ b/Synapse/Events/ServerEvents.cs @@ -38,7 +38,7 @@ internal static void InvokeRoundStart() /// A Event which is activated when a user send a Command in the Remote Admin /// It need to hook ref RemoteCommandEvent ev - public delegate void OnRemoteCommand(ref RemoteCommandEvent ev); + public delegate void OnRemoteCommand(RemoteCommandEvent ev); public static event OnRemoteCommand RemoteCommandEvent; internal static void InvokeRemoteCommandEvent(CommandSender sender, string command, ref bool allow) @@ -52,13 +52,13 @@ internal static void InvokeRemoteCommandEvent(CommandSender sender, string comma Command = command }; - RemoteCommandEvent.Invoke(ref ev); + RemoteCommandEvent.Invoke(ev); allow = ev.Allow; } /// A Event which is activated when a user send a Command in the Remote Admin - public delegate void OnConsoleCommand(ref ConsoleCommandEvent ev); + public delegate void OnConsoleCommand(ConsoleCommandEvent ev); public static event OnConsoleCommand ConsoleCommandEvent; internal static void InvokeConsoleCommandEvent(Player player, string command, out string color, @@ -74,36 +74,32 @@ internal static void InvokeConsoleCommandEvent(Player player, string command, ou Player = player }; - ConsoleCommandEvent.Invoke(ref ev); + ConsoleCommandEvent.Invoke(ev); color = ev.Color; returning = ev.ReturnMessage; } - public delegate void TeamRespawn(ref TeamRespawnEvent ev); + public delegate void TeamRespawn(TeamRespawnEvent ev); public static event TeamRespawn TeamRespawnEvent; - internal static void InvokeTeamRespawnEvent(ref List respawnList, ref bool isChaos, ref bool allow ,ref bool useTickets) + internal static void InvokeTeamRespawnEvent(ref List respawnList, ref Respawning.SpawnableTeamType team) { if (TeamRespawnEvent == null) return; var ev = new TeamRespawnEvent { - Allow = allow, - IsChaos = isChaos, RespawnList = respawnList, - UseTickets = useTickets + Team = team }; - TeamRespawnEvent.Invoke(ref ev); + TeamRespawnEvent.Invoke(ev); + team = ev.Team; respawnList = ev.RespawnList; - isChaos = ev.IsChaos; - allow = ev.Allow; - useTickets = ev.UseTickets; } - public delegate void OnPreAuthenticationEvent(ref PreAuthenticationEvent ev); + public delegate void OnPreAuthenticationEvent(PreAuthenticationEvent ev); public static event OnPreAuthenticationEvent PreAuthenticationEvent; internal static void InvokePreAuthentication(string userId, ConnectionRequest request, ref bool allow) @@ -115,7 +111,7 @@ internal static void InvokePreAuthentication(string userId, ConnectionRequest re UserId = userId }; - PreAuthenticationEvent?.Invoke(ref ev); + PreAuthenticationEvent?.Invoke(ev); allow = ev.Allow; } @@ -124,7 +120,7 @@ internal static void InvokePreAuthentication(string userId, ConnectionRequest re public static event OnWaitingForPlayers WaitingForPlayersEvent; internal static void InvokeWaitingForPlayers() => WaitingForPlayersEvent?.Invoke(); - public delegate void OnCheckRoundEnd(ref CheckRoundEndEvent ev); + public delegate void OnCheckRoundEnd(CheckRoundEndEvent ev); public static event OnCheckRoundEnd CheckRoundEndEvent; public static void InvokeCheckRoundEnd(ref bool forceEnd, ref bool allow, ref RoundSummary.LeadingTeam team, @@ -137,7 +133,7 @@ public static void InvokeCheckRoundEnd(ref bool forceEnd, ref bool allow, ref Ro LeadingTeam = team }; - CheckRoundEndEvent?.Invoke(ref ev); + CheckRoundEndEvent?.Invoke(ev); teamChanged = team != ev.LeadingTeam; team = ev.LeadingTeam; diff --git a/Synapse/MainLoader.cs b/Synapse/MainLoader.cs deleted file mode 100644 index 5d99043..0000000 --- a/Synapse/MainLoader.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.IO; -using MEC; - -namespace Synapse -{ - [SuppressMessage("ReSharper", "UnusedType.Global")] - public class MainLoader - { - /// This method is called by the Scp Server in the assembly-csharp - // ReSharper disable once UnusedMember.Global - public static void LoaderExecutionCode() - { - Log.Info("Now starting Synapse Version v.0.1.0 alpha"); - Log.Info("Created by Dimenzio and SirRoob"); - - Log.Info("Checking Files"); - - if (!Directory.Exists(PluginManager.MainConfigDirectory)) - Directory.CreateDirectory(PluginManager.MainConfigDirectory); - - if (!Directory.Exists(PluginManager.MainPluginDirectory)) - Directory.CreateDirectory(PluginManager.MainPluginDirectory); - - if (!Directory.Exists(PluginManager.DependenciesDirectory)) - Directory.CreateDirectory(PluginManager.DependenciesDirectory); - - CustomNetworkManager.Modded = true; - try - { - Timing.RunCoroutine(PluginManager.StartSynapse()); - } - catch - { - Log.Error("PluginManager failed to Start restart the Server"); - } - } - } -} \ No newline at end of file diff --git a/Synapse/PluginManager.cs b/Synapse/PluginManager.cs deleted file mode 100644 index d8d90b6..0000000 --- a/Synapse/PluginManager.cs +++ /dev/null @@ -1,210 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using MEC; -using Synapse.Events.Patches; -using Synapse.Permissions; - -namespace Synapse -{ - public static class PluginManager - { - // Variables - private static readonly List LoadedDependencies = new List(); - private static readonly List Plugins = new List(); - - private static string SynapseDirectory { get; } = - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Synapse"); - - internal static string MainPluginDirectory { get; } = Path.Combine(SynapseDirectory, "Plugins"); - internal static string DependenciesDirectory { get; } = Path.Combine(SynapseDirectory, "dependencies"); - internal static string MainConfigDirectory { get; } = Path.Combine(SynapseDirectory, "ServerConfigs"); - private static string ServerPluginDirectory { get; set; } - internal static string ServerConfigDirectory { get; private set; } - private static string ServerConfigFile { get; set; } - - // ReSharper disable once NotAccessedField.Local - private static Events.EventHandlers _eventHandler; - - // Methods - internal static IEnumerator StartSynapse() - { - yield return Timing.WaitForSeconds(0.5f); - try - { - Files(); - - LoadPlugins(); - - LoadSynapse(); - } - catch (Exception e) - { - Log.Error($"Synapse could not Start : {e}"); - } - } - - private static void Files() - { - ServerPluginDirectory = Path.Combine(MainPluginDirectory, $"Server-{ServerStatic.ServerPort}"); - if (!Directory.Exists(ServerPluginDirectory)) - Directory.CreateDirectory(ServerPluginDirectory); - - ServerConfigDirectory = Path.Combine(MainConfigDirectory, $"Server-{ServerStatic.ServerPort}"); - if (!Directory.Exists(ServerConfigDirectory)) - Directory.CreateDirectory(ServerConfigDirectory); - - ServerConfigFile = Path.Combine(ServerConfigDirectory, "server-config.yml"); - if (!File.Exists(ServerConfigFile)) - File.Create(ServerConfigFile).Close(); - } - - private static void LoadPlugins() - { - LoadDependencies(); - - var plugins = Directory.GetFiles(ServerPluginDirectory); - - foreach (var plugin in plugins) - { - if (plugin.EndsWith("Synapse.dll")) continue; - - if (plugin.EndsWith(".dll")) LoadPlugin(plugin); - } - Plugin.Config = new YamlConfig(ServerConfigFile); - OnEnable(); - } - - private static void LoadSynapse() - { - Configs.ReloadConfig(); - HarmonyPatch(); - _eventHandler = new Events.EventHandlers(); - - ServerConsole.ReloadServerName(); - - try - { - PermissionReader.Init(); - } - catch (Exception e) - { - Log.Error($"Your Permission in invalid: {e}"); - } - } - - - private static void LoadDependencies() - { - Log.Info("Loading Dependencies..."); - var depends = Directory.GetFiles(DependenciesDirectory); - - foreach (var dll in depends) - { - if (!dll.EndsWith(".dll")) continue; - - if (IsLoaded(dll)) - return; - - var assembly = Assembly.LoadFrom(dll); - LoadedDependencies.Add(assembly); - Log.Info($"Successfully loaded {dll}"); - } - } - - private static bool IsLoaded(string path) - { - return LoadedDependencies.Any(assembly => assembly.Location == path); - } - - private static void LoadPlugin(string pluginPath) - { - Log.Info($"Loading {pluginPath}"); - try - { - var file = ReadFile(pluginPath); - var assembly = Assembly.Load(file); - - foreach (var type in assembly.GetTypes()) - { - if (type.IsAbstract) continue; - - if (type.FullName == null) continue; - - if (!typeof(Plugin).IsAssignableFrom(type)) continue; - - var plugin = Activator.CreateInstance(type); - - if (!(plugin is Plugin p)) continue; - - Plugins.Add(p); - Log.Info($"Successfully loaded {p.GetName}"); - } - } - catch (Exception e) - { - Log.Error($"Error while initializing {pluginPath}: {e}"); - } - } - - private static void OnEnable() - { - foreach (var plugin in Plugins) - try - { - plugin.Translation = new Translation {Plugin = plugin}; - plugin.OwnPluginFolder = Path.Combine(ServerPluginDirectory, plugin.GetName); - plugin.OnEnable(); - } - catch (Exception e) - { - Log.Error($"Plugin {plugin.GetName} threw an exception while enabling {e}"); - } - } - - internal static void OnConfigReload() - { - Plugin.Config = new YamlConfig(ServerConfigFile); - Configs.ReloadConfig(); - - foreach (var plugin in Plugins) - try - { - plugin.InvokeConfigReloadEvent(); - } - catch (Exception e) - { - Log.Error($"Plugin {plugin.GetName} threw an exception while reloading {e}"); - } - } - - private static void HarmonyPatch() - { - try - { - var patchHandler = new PatchHandler(); - patchHandler.PatchMethods(); - } - catch (Exception e) - { - Log.Error($"PatchError: {e}"); - } - } - - private static byte[] ReadFile(string path) - { - var fileStream = File.Open(path, FileMode.Open); - byte[] result; - using (var memoryStream = new MemoryStream()) - { - fileStream.CopyTo(memoryStream); - result = memoryStream.ToArray(); - } - - fileStream.Close(); - return result; - } - } -} \ No newline at end of file diff --git a/Synapse/Synapse.cs b/Synapse/Synapse.cs new file mode 100644 index 0000000..179ef7b --- /dev/null +++ b/Synapse/Synapse.cs @@ -0,0 +1,269 @@ +using MEC; +using Synapse.Api; +using Synapse.Api.Plugin; +using Synapse.Config; +using Synapse.Events; +using Synapse.Events.Patches; +using SynapseModLoader; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace Synapse +{ + public static class Synapse + { + #region Version + private const int MajorVersion = 1; + private const int MinorVerion = 0; + private const int Patch = 0; + + public static int VersionNumber => MajorVersion * 100 + MinorVerion * 10 + Patch; + public static string Version => $"{MajorVersion}.{MinorVerion}.{Patch}"; + #endregion + + private static bool isLoaded = false; + private static readonly List LoadedDependencies = new List(); + internal static readonly List plugins = new List(); //TODO: Rework Config System and make this private + private static EventHandlers _eventHandler; + public static List Plugins => plugins.Select(obj => obj.Details).ToList(); + + + public static void LoaderExecutionCode() + { + if (isLoaded) return; + + Log.Info($"Now starting Synapse Version {Synapse.Version}"); + Log.Info("Created by Dimenzio and SirRoob"); + + CustomNetworkManager.Modded = true; + + try + { + Timing.CallDelayed(0.5f, () => Synapse.Start()); + isLoaded = true; + } + catch + { + Log.Error("Synapse failed to Start.Restart the Server"); + } + } + internal static void Start() + { + LoadDependencies(); + + foreach (var plugin in Directory.GetFiles(Files.ServerPluginDirectory)) + { + if (plugin == "Synapse.dll") continue; + + if (plugin.EndsWith(".dll")) LoadPlugin(plugin); + } + + + ConfigManager.InitializeConfigs(); + HarmonyPatch(); + ServerConsole.ReloadServerName(); + _eventHandler = new Events.EventHandlers(); + try + { + PermissionReader.Init(); + } + catch (Exception e) + { + Log.Error($"Your Permission in invalid: {e}"); + } + + OnEnable(); + } + + + #region Methods to do everything what Synapse needs + private static void LoadDependencies() + { + Log.Info("Loading Dependencies..."); + var depends = Directory.GetFiles(Files.DependenciesDirectory); + + foreach (var dll in depends) + { + if (!dll.EndsWith(".dll")) continue; + + if (LoadedDependencies.Any(x => x.Location == dll)) + return; + + var assembly = Assembly.LoadFrom(dll); + LoadedDependencies.Add(assembly); + Log.Info($"Successfully loaded {assembly.GetName().Name}"); + } + } + private static void LoadPlugin(string pluginPath) + { + Log.Info($"Loading {pluginPath}"); + try + { + var file = ModLoader.ReadFile(pluginPath); + var assembly = Assembly.Load(file); + + foreach (var type in assembly.GetTypes()) + { + if (type.IsAbstract) continue; + + if (type.FullName == null) continue; + + if (!typeof(Plugin).IsAssignableFrom(type)) continue; + + var plugin = Activator.CreateInstance(type); + + if (!(plugin is Plugin p)) continue; + + p.Details = type.GetCustomAttribute(); + if (p.Details == null) + p.Details = new PluginDetails() + { + Author = "Unknown", + Description = "No Description", + Name = assembly.GetName().Name, + Version = assembly.ImageRuntimeVersion, + SynapseMajor = MajorVersion, + SynapseMinor = MinorVerion, + SynapsePatch = Patch + }; + + plugins.Add(p); + if (p.Details.GetVersionNumber() == VersionNumber) Log.Info($"Successfully loaded {p.Details.Name}"); + + else if (p.Details.GetVersionNumber() > VersionNumber) Log.Warn($"The Plugin {p.Details.Name} is for the newer Synapse version {p.Details.GetVersionString()} but was succesfully loaded(bugs can occure)"); + + else Log.Warn($"The Plugin {p.Details.Name} is for the older Synapse version {p.Details.GetVersionString()} but was succesfully loaded(bugs can occure)"); + } + } + catch (Exception e) + { + Log.Error($"Error while initializing {pluginPath}: {e}"); + } + } + private static void HarmonyPatch() + { + try + { + var patchHandler = new PatchHandler(); + patchHandler.PatchMethods(); + } + catch (Exception e) + { + Log.Error($"PatchError: {e}"); + } + } + private static void OnEnable() + { + foreach (var plugin in plugins) + try + { + plugin.Translation = new Translation { Plugin = plugin }; + plugin.OwnPluginFolder = Path.Combine(Files.ServerPluginDirectory, plugin.Details.Name); + plugin.OnEnable(); + } + catch (Exception e) + { + Log.Error($"Plugin {plugin.Details.Name} threw an exception while enabling {e}"); + } + } + #endregion + } + + internal static class Files + { + //Synapse Directory + private static string StartupFile => Assembly.GetAssembly(typeof(ReferenceHub)).Location.Replace($"SCPSL_Data{Path.DirectorySeparatorChar}Managed{Path.DirectorySeparatorChar}Assembly-CSharp.dll", "SynapseStart-config.yml"); + internal static string SynapseDirectory => new YamlConfig(StartupFile).GetString("synapse_installation", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Synapse")); + + //Directory-Structure + internal static string DependenciesDirectory + { + get + { + var path = Path.Combine(SynapseDirectory, "dependencies"); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + return path; + } + } + internal static string MainPluginDirectory + { + get + { + var path = Path.Combine(SynapseDirectory, "Plugins"); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + return path; + } + } + internal static string MainConfigDirectory + { + get + { + var path = Path.Combine(SynapseDirectory, "ServerConfigs"); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + return path; + } + } + internal static string ServerPluginDirectory + { + get + { + var path = Path.Combine(MainPluginDirectory, $"Server-{ServerStatic.ServerPort}"); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + return path; + } + } + internal static string ServerConfigDirectory + { + get + { + var path = Path.Combine(MainConfigDirectory, $"Server-{ServerStatic.ServerPort}"); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + return path; + } + } + + //Files + internal static string ServerConfigFile + { + get + { + var path = Path.Combine(ServerConfigDirectory, "server-config.yml"); + + if (!File.Exists(path)) + File.Create(path).Close(); + + return path; + } + } + internal static string PermissionFile + { + get + { + var path = Path.Combine(Files.ServerConfigDirectory, "permissions.yml"); + + if (!File.Exists(path)) + File.WriteAllText(path, "groups:\n user:\n default: true\n permissions:\n - plugin.permission\n northwood:\n northwood: true\n permissions:\n - plugin.permission\n owner:\n permissions:\n - .*"); + + return path; + } + } + } +} diff --git a/Synapse/Synapse.csproj b/Synapse/Synapse.csproj index eeb12e6..bb77340 100644 --- a/Synapse/Synapse.csproj +++ b/Synapse/Synapse.csproj @@ -64,28 +64,37 @@ + + + + + - + + + + + - - + + @@ -140,11 +149,9 @@ - - - - - + + + diff --git a/SynapseModLoader/ModLoader.cs b/SynapseModLoader/ModLoader.cs index 1c1427b..aeb1e6c 100644 --- a/SynapseModLoader/ModLoader.cs +++ b/SynapseModLoader/ModLoader.cs @@ -1,4 +1,5 @@ -using System; +using GameCore; +using System; using System.IO; using System.Linq; using System.Reflection; @@ -34,24 +35,41 @@ public static void LoadModSystem() return; } ServerConsole.AddLog("Synapse Mod-Loader is now initialising.. :)", ConsoleColor.Blue); - var text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Synapse"); - if (!Directory.Exists(text)) - { - Directory.CreateDirectory(text); - } - if (!File.Exists(Path.Combine(text, "Synapse.dll"))) + + try { - ServerConsole.AddLog("Error while loading Synapse! The Synapse.dll is missing!", ConsoleColor.Red); - return; + var startupfile = Assembly.GetExecutingAssembly().Location.Replace($"SCPSL_Data{Path.DirectorySeparatorChar}Managed{Path.DirectorySeparatorChar}Assembly-CSharp.dll", "SynapseStart-config.yml"); + if (!File.Exists(startupfile)) + { + ServerConsole.AddLog($"Synapse Mod-Loader Start file is missing ... creating: {startupfile}", ConsoleColor.Blue); + File.Create(startupfile).Close(); + File.WriteAllLines(startupfile, new string[] { "synapse_installation: default" }); + } + var Config = new YamlConfig(startupfile); + + var text = Config.GetString("synapse_installation", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Synapse")); + if (!Directory.Exists(text)) + { + Directory.CreateDirectory(text); + } + if (!File.Exists(Path.Combine(text, "Synapse.dll"))) + { + ServerConsole.AddLog("Error while loading Synapse! The Synapse.dll is missing!", ConsoleColor.Red); + return; + } + var methodInfo = Assembly.Load(ReadFile(Path.Combine(text, "Synapse.dll"))).GetTypes() + .SelectMany(p => p.GetMethods()).FirstOrDefault(f => f.Name == "LoaderExecutionCode"); + if (!(methodInfo != null)) + { + return; + } + methodInfo.Invoke(null, null); + _loaded = true; } - var methodInfo = Assembly.Load(ReadFile(Path.Combine(text, "Synapse.dll"))).GetTypes() - .SelectMany(p => p.GetMethods()).FirstOrDefault(f => f.Name == "LoaderExecutionCode"); - if (!(methodInfo != null)) + catch (Exception e) { - return; + ServerConsole.AddLog($"Synapse Mod-Loader startup Error: {e}", ConsoleColor.Red); } - methodInfo.Invoke(null, null); - _loaded = true; } private static bool _loaded;