From d0e9893cdc5d5820edf62c0204cf59591bf75c7a Mon Sep 17 00:00:00 2001 From: NaoUnderscore Date: Sat, 27 Jul 2024 18:18:44 +0200 Subject: [PATCH 1/7] Ongoing --- Exiled.API/Features/Core/EActor.cs | 5 +-- .../Features/Core/Generic/EBehaviour.cs | 16 ++++++++++ .../API/Commands/CustomRoles/Give.cs | 4 +-- .../API/Features/CustomRoles/CustomRole.cs | 32 +++++++++++++++++-- .../API/Features/CustomRoles/RoleBehaviour.cs | 16 ++++++++-- 5 files changed, 65 insertions(+), 8 deletions(-) diff --git a/Exiled.API/Features/Core/EActor.cs b/Exiled.API/Features/Core/EActor.cs index 2a6f72eb9c..1c3dfe0412 100644 --- a/Exiled.API/Features/Core/EActor.cs +++ b/Exiled.API/Features/Core/EActor.cs @@ -454,12 +454,12 @@ public bool TryGetComponent(Type type, out EActor component) /// public bool HasComponent(bool depthInheritance = false) => depthInheritance - ? ComponentsInChildren.Any(comp => typeof(T).IsAssignableFrom(comp.GetType())) + ? ComponentsInChildren.Any(comp => comp is T) : ComponentsInChildren.Any(comp => typeof(T) == comp.GetType()); /// public bool HasComponent(Type type, bool depthInheritance = false) => depthInheritance - ? ComponentsInChildren.Any(comp => type.IsAssignableFrom(comp.GetType())) + ? ComponentsInChildren.Any(type.IsInstanceOfType) : ComponentsInChildren.Any(comp => type == comp.GetType()); /// @@ -467,6 +467,7 @@ public bool HasComponent(Type type, bool depthInheritance = false) => depthInher /// protected virtual void PostInitialize() { + Log.InfoWithContext(nameof(PostInitialize)); } /// diff --git a/Exiled.API/Features/Core/Generic/EBehaviour.cs b/Exiled.API/Features/Core/Generic/EBehaviour.cs index 778f61b773..040e467c85 100644 --- a/Exiled.API/Features/Core/Generic/EBehaviour.cs +++ b/Exiled.API/Features/Core/Generic/EBehaviour.cs @@ -33,6 +33,15 @@ protected EBehaviour() { } + /// + /// Initializes a new instance of the class. + /// + /// The base . + protected EBehaviour(GameObject gameObject = null) + : base(gameObject) + { + } + /// /// Gets or sets the owner of the . /// @@ -77,9 +86,16 @@ protected override void PostInitialize() { base.PostInitialize(); + Log.InfoWithContext($"EBehaviour::{nameof(PostInitialize)}"); + FindOwner(); + + Log.InfoWithContext($"EBehaviour::{nameof(FindOwner)}"); + if (!Owner && DisposeOnNullOwner) { + Log.InfoWithContext($"Destroying Behaviour"); + Destroy(); return; } diff --git a/Exiled.CustomModules/API/Commands/CustomRoles/Give.cs b/Exiled.CustomModules/API/Commands/CustomRoles/Give.cs index ceca249863..76dca5ad35 100644 --- a/Exiled.CustomModules/API/Commands/CustomRoles/Give.cs +++ b/Exiled.CustomModules/API/Commands/CustomRoles/Give.cs @@ -58,13 +58,13 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s return false; } - if (!CustomRole.TryGet(arguments.At(0), out CustomRole role) || role is null) + if (!CustomRole.TryGet(uint.Parse(arguments.At(0)), out CustomRole role) || role is null) { response = $"Custom role {arguments.At(0)} not found!"; return false; } - if (arguments.Count == 1) + if (arguments.Count == 2) { Pawn player = Player.Get(arguments.At(1)).Cast(); diff --git a/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs b/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs index 74d0514900..802ed273f7 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs @@ -743,40 +743,66 @@ public void ForceSpawn(Pawn player) ChangingCustomRoleEventArgs ev = new(player, Id); ChangingCustomRoleDispatcher.InvokeAll(ev); + Log.InfoWithContext("ForceSpawn 1"); + if (!ev.IsAllowed) return; + + Log.InfoWithContext("ForceSpawn 2"); + player = ev.Player.Cast(); if (ev.Role is RoleTypeId rId) { + Log.InfoWithContext("ForceSpawn 2.1"); + player.SetRole(rId); return; } + Log.InfoWithContext("ForceSpawn 3"); + if (!TryGet(ev.Role, out CustomRole role)) return; + Log.InfoWithContext("ForceSpawn 4"); + + if (role.Id != Id) { + Log.InfoWithContext("ForceSpawn 4.1"); + role.ForceSpawn(player); return; } + Log.InfoWithContext("ForceSpawn 5"); + + object prevRole = player.CustomRole ? player.CustomRole.Id : player.Role.Type; Remove(player); PlayersValue.Add(player, this); + Log.InfoWithContext("ForceSpawn 6"); + + if (!player.IsAlive) { + Log.InfoWithContext("ForceSpawn 7"); + ForceSpawn_Internal(player, false); ChangedCustomRoleEventArgs @event = new(player, prevRole); ChangedCustomRoleDispatcher.InvokeAll(@event); return; } + Log.InfoWithContext("ForceSpawn 8"); + player.Role.Set(RoleTypeId.Spectator, SpawnReason.Respawn); Timing.CallDelayed(0.1f, () => { + Log.InfoWithContext("ForceSpawn 9"); + ForceSpawn_Internal(player, false); ChangedCustomRoleEventArgs @event = new(player, prevRole); ChangedCustomRoleDispatcher.InvokeAll(@event); @@ -972,7 +998,8 @@ protected override bool TryUnregister() private void ForceSpawn_Internal(Pawn player, bool preservePosition, SpawnReason spawnReason = null, RoleSpawnFlags roleSpawnFlags = RoleSpawnFlags.All) { Instances += 1; - RoleBehaviour roleBehaviour = EObject.CreateDefaultSubobject(BehaviourComponent, $"ECS-{Name}"); + RoleBehaviour roleBehaviour = EObject.CreateDefaultSubobject(BehaviourComponent, $"ECS-{Name}").Cast(); + Log.InfoWithContext($"RB is null? {roleBehaviour is null}"); roleBehaviour.Settings.PreservePosition = preservePosition; spawnReason ??= SpawnReason.ForceClass; @@ -982,7 +1009,8 @@ private void ForceSpawn_Internal(Pawn player, bool preservePosition, SpawnReason if (roleSpawnFlags != roleBehaviour.Settings.SpawnFlags) roleBehaviour.Settings.SpawnFlags = roleSpawnFlags; - player.AddComponent(roleBehaviour); + EActor ea = player.AddComponent(roleBehaviour); + Log.InfoWithContext($"ea is null? {ea is null}"); } } } diff --git a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs index 83e69ca89a..e332afd71b 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs @@ -259,8 +259,12 @@ protected override void PostInitialize() { base.PostInitialize(); + Log.InfoWithContext("Pre-Adjust"); + AdjustAdditivePipe(); + Log.InfoWithContext("Post-Adjust"); + wasNoClipPermitted = Owner.IsNoclipPermitted; isHuman = !CustomRole.IsScp; @@ -270,6 +274,8 @@ protected override void PostInitialize() if (Role is RoleTypeId.None) { + Log.InfoWithContext("Role is none"); + Destroy(); return; } @@ -277,10 +283,14 @@ protected override void PostInitialize() if (Settings.SpawnFlags is not RoleSpawnFlags.All) { + Log.InfoWithContext("Is not RSF ALL"); + Owner.Role.Set(Role, Settings.SpawnReason, Settings.SpawnFlags); } else { + Log.InfoWithContext("Is RSF ALL"); + switch (Settings.PreservePosition) { case true when Settings.PreserveInventory: @@ -316,9 +326,7 @@ protected override void PostInitialize() Owner.CustomInfo += Settings.CustomInfo; if (Settings.HideInfoArea) - { Owner.InfoArea = Owner.InfoArea.RemoveFlags(PlayerInfoArea.UnitName, PlayerInfoArea.Role); - } if (isHuman && !Settings.PreserveInventory) { @@ -360,6 +368,8 @@ protected override void OnBeginPlay() if (!Owner) { + Log.InfoWithContext("Owner is null RB"); + Destroy(); return; } @@ -381,6 +391,8 @@ protected override void Tick() // Must be refactored (performance issues) if ((Settings.UseDefaultRoleOnly && (Owner.Role != Role)) || (!Settings.DynamicRoles.IsEmpty() && !Settings.DynamicRoles.Contains(Owner.Role))) { + Log.InfoWithContext("Tick check failed"); + Destroy(); return; } From 23f5d8f45101e69c4d45ea15da3ad85d79733be8 Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Sun, 28 Jul 2024 00:48:54 +0200 Subject: [PATCH 2/7] Fixed Pawn.cs being null if try to use it by Player::Get().Cast(). Adding a method for load a constructor without any param or constructor. Removing abstract from RoleBehaviour.cs for allow the creating of an instance. Added custom role example under Exiled.Example for testing purpose. (#2761) --- Exiled.API/Features/Core/EObject.cs | 66 ++++++++++++++++++- .../API/Features/CustomRoles/RoleBehaviour.cs | 18 ++++- .../API/Features/ModuleBehaviour.cs | 11 +++- Exiled.CustomModules/API/Features/Pawn.cs | 9 ++- Exiled.Example/Example.cs | 2 + Exiled.Example/Exiled.Example.csproj | 1 + Exiled.Loader/Loader.cs | 13 ++-- 7 files changed, 105 insertions(+), 15 deletions(-) diff --git a/Exiled.API/Features/Core/EObject.cs b/Exiled.API/Features/Core/EObject.cs index c1543f15eb..5250c5b9f9 100644 --- a/Exiled.API/Features/Core/EObject.cs +++ b/Exiled.API/Features/Core/EObject.cs @@ -357,7 +357,16 @@ public static Type GetObjectTypeFromRegisteredTypes(Type type, string name) public static EObject CreateDefaultSubobject(Type type, params object[] parameters) { const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; - EObject @object = Activator.CreateInstance(type, flags, null, parameters, null) as EObject; + EObject @object = null; + if (type.GetConstructors().Length == 0) + { + @object = InitializeBaseType(type, parameters); + } + else + { + @object = Activator.CreateInstance(type, flags, null, parameters, null) as EObject; + } + // Do not use implicit bool conversion as @object may be null if (@object != null) @@ -371,6 +380,61 @@ public static EObject CreateDefaultSubobject(Type type, params object[] paramete throw new NullReferenceException($"Couldn't create an EObject instance of type {type.Name}."); } + /// + /// InitializeBaseType if 0 constructors are found. + /// + /// Generic Type. + /// EObject. + public static T InitializeBaseType() + where T : EObject + { + return InitializeBaseType(typeof(T)).Cast(); + } + + /// + /// InitializeBaseType if 0 constructors are found. + /// + /// type. + /// constructors parameters. + /// EObject + /// If the class isn't a subclass of EObject. + public static EObject InitializeBaseType(Type type, params object[] parameters) + { + const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; + if (type.BaseType != typeof(EObject) && !type.IsSubclassOf(typeof(EObject)) && type != typeof(EObject)) + throw new InvalidOperationException("The requested type is not a subclass of EObject."); + + // Get the base type of T + Type baseType = type.BaseType; + + if (baseType == null) + { + throw new InvalidOperationException("The requested type does not have a base type."); + } + + // Get the constructors of the base type + ConstructorInfo[] constructors = baseType.GetConstructors(flags); + + if (constructors.Length == 0) + { + throw new InvalidOperationException("The base type does not have public constructors."); + } + + // Here we assume you want to use the default constructor if available + ConstructorInfo constructor = Array.Find(constructors, c => c.GetParameters().Length == 0); + + if (constructor == null) + { + throw new InvalidOperationException("The base type does not have a parameterless constructor."); + } + + // Create an instance of the base type + object baseInstance = constructor.Invoke(null); + + // Return the instance as the requested type + return baseInstance as EObject; + } + /// /// Creates a new instance of the class. /// diff --git a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs index e332afd71b..6e1b7112b0 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs @@ -37,8 +37,24 @@ namespace Exiled.CustomModules.API.Features.CustomRoles /// This class extends and implements . ///
It provides a foundation for creating custom behaviors associated with in-game player roles. /// - public abstract class RoleBehaviour : ModuleBehaviour, IAdditiveSettings + public class RoleBehaviour : ModuleBehaviour, IAdditiveSettings { + /// + /// Initializes a new instance of the class. + /// + protected RoleBehaviour() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// owner's gameobject. + protected RoleBehaviour(GameObject gameObject) + : base(gameObject) + { + } + private Vector3 lastPosition; private RoleTypeId fakeAppearance; private bool isHuman; diff --git a/Exiled.CustomModules/API/Features/ModuleBehaviour.cs b/Exiled.CustomModules/API/Features/ModuleBehaviour.cs index 03c3368b62..b8bede4980 100644 --- a/Exiled.CustomModules/API/Features/ModuleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/ModuleBehaviour.cs @@ -12,7 +12,7 @@ namespace Exiled.CustomModules.API.Features using Exiled.API.Features.Core; using Exiled.API.Features.Core.Generic; - using Exiled.CustomModules.API.Features.Attributes; + using UnityEngine; /// /// Represents a marker class for a module's pointer. @@ -33,6 +33,15 @@ protected ModuleBehaviour() { } + /// + /// Initializes a new instance of the class. + /// + /// owner's gameobject. + protected ModuleBehaviour(GameObject gameObject) + : base(gameObject) + { + } + /// /// Gets or sets the behaviour's configs. /// diff --git a/Exiled.CustomModules/API/Features/Pawn.cs b/Exiled.CustomModules/API/Features/Pawn.cs index 71c3499330..846858c4a2 100644 --- a/Exiled.CustomModules/API/Features/Pawn.cs +++ b/Exiled.CustomModules/API/Features/Pawn.cs @@ -15,7 +15,6 @@ namespace Exiled.CustomModules.API.Features using Exiled.API.Extensions; using Exiled.API.Features; using Exiled.API.Features.Attributes; - using Exiled.API.Features.Core.Generic; using Exiled.API.Features.Items; using Exiled.API.Features.Roles; using Exiled.CustomModules.API.Features.CustomAbilities; @@ -41,7 +40,7 @@ namespace Exiled.CustomModules.API.Features ///
It serves as a comprehensive representation of an in-game entity, encapsulating the associated with an expanded set of features.
/// ///
- [DefaultPlayerClass(enforceAuthority: false)] + [DefaultPlayerClass(enforceAuthority: true)] public class Pawn : Player { private readonly List abilityBehaviours = new(); @@ -83,21 +82,21 @@ public Pawn(GameObject gameObject) /// /// Can be . ///
- public CustomRole CustomRole => roleBehaviour.CustomRole; + public CustomRole CustomRole => roleBehaviour?.CustomRole; /// /// Gets the pawn's . /// /// Can be . /// - public CustomTeam CustomTeam => roleBehaviour.CustomTeam; + public CustomTeam CustomTeam => roleBehaviour?.CustomTeam; /// /// Gets the pawn's . /// /// Can be . /// - public CustomEscape CustomEscape => escapeBehaviour.CustomEscape; + public CustomEscape CustomEscape => escapeBehaviour?.CustomEscape; /// /// Gets the pawn's current . diff --git a/Exiled.Example/Example.cs b/Exiled.Example/Example.cs index 0f75995444..77d066ff6e 100644 --- a/Exiled.Example/Example.cs +++ b/Exiled.Example/Example.cs @@ -9,6 +9,7 @@ namespace Exiled.Example { using Exiled.API.Enums; using Exiled.API.Features; + using Exiled.CustomModules.API.Features.CustomRoles; /// /// The example plugin. @@ -37,6 +38,7 @@ public override void OnEnabled() // Create new instance of the event handler EventHandler = new(); + CustomRole.EnableAll(); base.OnEnabled(); } diff --git a/Exiled.Example/Exiled.Example.csproj b/Exiled.Example/Exiled.Example.csproj index f8a2050b08..f87fc12964 100644 --- a/Exiled.Example/Exiled.Example.csproj +++ b/Exiled.Example/Exiled.Example.csproj @@ -13,6 +13,7 @@ + diff --git a/Exiled.Loader/Loader.cs b/Exiled.Loader/Loader.cs index 2823c415a1..47e829ca37 100644 --- a/Exiled.Loader/Loader.cs +++ b/Exiled.Loader/Loader.cs @@ -202,16 +202,15 @@ public static IPlugin CreatePlugin(Assembly assembly) foreach (Type type in assembly.GetTypes()) { if (type.BaseType == typeof(Player) || type.IsSubclassOf(typeof(Player))) - { - Log.ErrorWithContext(type.Name); defaultPlayerClass = type; - } - DefaultPlayerClassAttribute dpc = Player.DEFAULT_PLAYER_CLASS.GetCustomAttribute(); - if (Player.DEFAULT_PLAYER_CLASS != typeof(Player) && !dpc.EnforceAuthority && defaultPlayerClass is not null) + DefaultPlayerClassAttribute dpc = type.GetCustomAttribute(); + + // To fix. dcp.Enforce don't have to be set true under CustomModules::Pawn. *testing purpose* + if (Player.DEFAULT_PLAYER_CLASS == typeof(Player) && dpc is not null && dpc.EnforceAuthority && defaultPlayerClass is not null) { - if (Player.DEFAULT_PLAYER_CLASS == typeof(Player) && dpc.EnforceAuthority) - Player.DEFAULT_PLAYER_CLASS = defaultPlayerClass; + Log.DebugWithContext("Changing default player class to " + defaultPlayerClass.Name); + Player.DEFAULT_PLAYER_CLASS = defaultPlayerClass; } } From 8bdd674c31668c512b72e4ad94d12241eae05f75 Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Tue, 30 Jul 2024 02:25:50 +0200 Subject: [PATCH 3/7] CustomRole Fix (#2763) * Fixed Pawn.cs being null if try to use it by Player::Get().Cast(). Adding a method for load a constructor without any param or constructor. Removing abstract from RoleBehaviour.cs for allow the creating of an instance. Added custom role example under Exiled.Example for testing purpose. * Fixed custom roles. * Added test role (testing purposes) --- Exiled.API/Features/Core/EActor.cs | 15 ++-- Exiled.API/Features/Core/EObject.cs | 18 ++--- Exiled.API/Features/Core/GameEntity.cs | 1 + .../Features/Core/Generic/EBehaviour.cs | 6 -- Exiled.API/Features/Player.cs | 5 ++ .../API/Features/CustomRoles/CustomRole.cs | 31 +------- .../API/Features/CustomRoles/RoleBehaviour.cs | 16 +--- Exiled.Example/TestRole/CustomRoleType.cs | 22 ++++++ Exiled.Example/TestRole/Scp999Behaviour.cs | 21 +++++ Exiled.Example/TestRole/Scp999Config.cs | 21 +++++ Exiled.Example/TestRole/Scp999Role.cs | 79 +++++++++++++++++++ Exiled.Loader/Loader.cs | 15 +++- 12 files changed, 181 insertions(+), 69 deletions(-) create mode 100644 Exiled.Example/TestRole/CustomRoleType.cs create mode 100644 Exiled.Example/TestRole/Scp999Behaviour.cs create mode 100644 Exiled.Example/TestRole/Scp999Config.cs create mode 100644 Exiled.Example/TestRole/Scp999Role.cs diff --git a/Exiled.API/Features/Core/EActor.cs b/Exiled.API/Features/Core/EActor.cs index 1c3dfe0412..87723416c1 100644 --- a/Exiled.API/Features/Core/EActor.cs +++ b/Exiled.API/Features/Core/EActor.cs @@ -45,9 +45,6 @@ protected EActor() { IsEditable = true; fixedTickRate = DEFAULT_FIXED_TICK_RATE; - PostInitialize(); - Timing.CallDelayed(fixedTickRate, OnBeginPlay); - Timing.CallDelayed(fixedTickRate * 2, () => serverTick = Timing.RunCoroutine(ServerTick())); } /// @@ -462,12 +459,21 @@ public bool HasComponent(Type type, bool depthInheritance = false) => depthInher ? ComponentsInChildren.Any(type.IsInstanceOfType) : ComponentsInChildren.Any(comp => type == comp.GetType()); + /// + /// Called when the is initialized. + /// + public void ComponentInitialize() + { + PostInitialize(); + Timing.CallDelayed(fixedTickRate, OnBeginPlay); + Timing.CallDelayed(fixedTickRate * 2, () => serverTick = Timing.RunCoroutine(ServerTick())); + } + /// /// Fired after the instance is created. /// protected virtual void PostInitialize() { - Log.InfoWithContext(nameof(PostInitialize)); } /// @@ -486,7 +492,6 @@ protected virtual void Tick() if (DestroyNextTick) { Destroy(); - return; } } diff --git a/Exiled.API/Features/Core/EObject.cs b/Exiled.API/Features/Core/EObject.cs index 5250c5b9f9..38255bc2db 100644 --- a/Exiled.API/Features/Core/EObject.cs +++ b/Exiled.API/Features/Core/EObject.cs @@ -62,12 +62,12 @@ protected EObject(GameObject gameObject = null) /// /// Gets or sets the name of the instance. /// - public string Name { get; set; } + public string Name { get; set; } = string.Empty; /// /// Gets or sets the tag of the instance. /// - public string Tag { get; set; } + public string Tag { get; set; } = string.Empty; /// /// Gets or sets a value indicating whether the values can be edited. @@ -357,17 +357,14 @@ public static Type GetObjectTypeFromRegisteredTypes(Type type, string name) public static EObject CreateDefaultSubobject(Type type, params object[] parameters) { const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; - EObject @object = null; - if (type.GetConstructors().Length == 0) - { - @object = InitializeBaseType(type, parameters); - } - else + EObject @object = Activator.CreateInstance(type, flags, null, null, null) as EObject; + + if (@object is not null && Player.DEFAULT_ROLE_BEHAVIOUR is not null && type.BaseType == Player.DEFAULT_ROLE_BEHAVIOUR) { - @object = Activator.CreateInstance(type, flags, null, parameters, null) as EObject; + @object.Base = parameters[0] as GameObject; + @object.Cast().ComponentInitialize(); } - // Do not use implicit bool conversion as @object may be null if (@object != null) { @@ -918,3 +915,4 @@ protected virtual void OnDestroyed() } } } + diff --git a/Exiled.API/Features/Core/GameEntity.cs b/Exiled.API/Features/Core/GameEntity.cs index aa84602d36..41be51dcd7 100644 --- a/Exiled.API/Features/Core/GameEntity.cs +++ b/Exiled.API/Features/Core/GameEntity.cs @@ -163,6 +163,7 @@ public T AddComponent(string name = "") public EActor AddComponent(Type type, string name = "") { EActor component = EObject.CreateDefaultSubobject(type, GameObject).Cast(); + component.Base = GameObject; if (!component) return null; diff --git a/Exiled.API/Features/Core/Generic/EBehaviour.cs b/Exiled.API/Features/Core/Generic/EBehaviour.cs index 040e467c85..6be26f7c27 100644 --- a/Exiled.API/Features/Core/Generic/EBehaviour.cs +++ b/Exiled.API/Features/Core/Generic/EBehaviour.cs @@ -86,16 +86,10 @@ protected override void PostInitialize() { base.PostInitialize(); - Log.InfoWithContext($"EBehaviour::{nameof(PostInitialize)}"); - FindOwner(); - Log.InfoWithContext($"EBehaviour::{nameof(FindOwner)}"); - if (!Owner && DisposeOnNullOwner) { - Log.InfoWithContext($"Destroying Behaviour"); - Destroy(); return; } diff --git a/Exiled.API/Features/Player.cs b/Exiled.API/Features/Player.cs index 80b5e1c106..b99ada47e0 100644 --- a/Exiled.API/Features/Player.cs +++ b/Exiled.API/Features/Player.cs @@ -127,6 +127,11 @@ public class Player : GameEntity public const string INFO_CATEGORY = "Player_Info"; #pragma warning disable SA1401 + /// + /// The default role behaviour class. + /// + public static Type DEFAULT_ROLE_BEHAVIOUR = null; + /// /// The default player class. /// diff --git a/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs b/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs index 802ed273f7..a18b08850d 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs @@ -627,9 +627,10 @@ public static void Remove(IEnumerable players) /// public static void EnableAll(Assembly assembly) { - if (!CustomModules.Instance.Config.Modules.Contains(UUModuleType.CustomRoles.Name)) + if (!CustomModules.Instance.Config.Modules.Contains("CustomRoles")) throw new Exception("ModuleType::CustomRoles must be enabled in order to load any custom roles"); + Player.DEFAULT_ROLE_BEHAVIOUR = typeof(RoleBehaviour); List customRoles = new(); foreach (Type type in assembly.GetTypes()) { @@ -743,66 +744,40 @@ public void ForceSpawn(Pawn player) ChangingCustomRoleEventArgs ev = new(player, Id); ChangingCustomRoleDispatcher.InvokeAll(ev); - Log.InfoWithContext("ForceSpawn 1"); - if (!ev.IsAllowed) return; - - Log.InfoWithContext("ForceSpawn 2"); - player = ev.Player.Cast(); if (ev.Role is RoleTypeId rId) { - Log.InfoWithContext("ForceSpawn 2.1"); - player.SetRole(rId); return; } - Log.InfoWithContext("ForceSpawn 3"); - if (!TryGet(ev.Role, out CustomRole role)) return; - Log.InfoWithContext("ForceSpawn 4"); - - if (role.Id != Id) { - Log.InfoWithContext("ForceSpawn 4.1"); - role.ForceSpawn(player); return; } - Log.InfoWithContext("ForceSpawn 5"); - - object prevRole = player.CustomRole ? player.CustomRole.Id : player.Role.Type; Remove(player); PlayersValue.Add(player, this); - Log.InfoWithContext("ForceSpawn 6"); - - if (!player.IsAlive) { - Log.InfoWithContext("ForceSpawn 7"); - ForceSpawn_Internal(player, false); ChangedCustomRoleEventArgs @event = new(player, prevRole); ChangedCustomRoleDispatcher.InvokeAll(@event); return; } - Log.InfoWithContext("ForceSpawn 8"); - player.Role.Set(RoleTypeId.Spectator, SpawnReason.Respawn); Timing.CallDelayed(0.1f, () => { - Log.InfoWithContext("ForceSpawn 9"); - ForceSpawn_Internal(player, false); ChangedCustomRoleEventArgs @event = new(player, prevRole); ChangedCustomRoleDispatcher.InvokeAll(@event); @@ -999,7 +974,6 @@ private void ForceSpawn_Internal(Pawn player, bool preservePosition, SpawnReason { Instances += 1; RoleBehaviour roleBehaviour = EObject.CreateDefaultSubobject(BehaviourComponent, $"ECS-{Name}").Cast(); - Log.InfoWithContext($"RB is null? {roleBehaviour is null}"); roleBehaviour.Settings.PreservePosition = preservePosition; spawnReason ??= SpawnReason.ForceClass; @@ -1010,7 +984,6 @@ private void ForceSpawn_Internal(Pawn player, bool preservePosition, SpawnReason roleBehaviour.Settings.SpawnFlags = roleSpawnFlags; EActor ea = player.AddComponent(roleBehaviour); - Log.InfoWithContext($"ea is null? {ea is null}"); } } } diff --git a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs index 6e1b7112b0..128caa64c2 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs @@ -251,7 +251,7 @@ public virtual void AdjustAdditivePipe() } Owner.UniqueRole = CustomRole.Name; - Owner.TryAddCustomRoleFriendlyFire(Name, Settings.FriendlyFireMultiplier); + //Owner.TryAddCustomRoleFriendlyFire(Name, Settings.FriendlyFireMultiplier); if (CustomRole.EscapeBehaviourComponent is not null) { @@ -275,12 +275,8 @@ protected override void PostInitialize() { base.PostInitialize(); - Log.InfoWithContext("Pre-Adjust"); - AdjustAdditivePipe(); - Log.InfoWithContext("Post-Adjust"); - wasNoClipPermitted = Owner.IsNoclipPermitted; isHuman = !CustomRole.IsScp; @@ -290,8 +286,6 @@ protected override void PostInitialize() if (Role is RoleTypeId.None) { - Log.InfoWithContext("Role is none"); - Destroy(); return; } @@ -299,14 +293,10 @@ protected override void PostInitialize() if (Settings.SpawnFlags is not RoleSpawnFlags.All) { - Log.InfoWithContext("Is not RSF ALL"); - Owner.Role.Set(Role, Settings.SpawnReason, Settings.SpawnFlags); } else { - Log.InfoWithContext("Is RSF ALL"); - switch (Settings.PreservePosition) { case true when Settings.PreserveInventory: @@ -384,8 +374,6 @@ protected override void OnBeginPlay() if (!Owner) { - Log.InfoWithContext("Owner is null RB"); - Destroy(); return; } @@ -407,8 +395,6 @@ protected override void Tick() // Must be refactored (performance issues) if ((Settings.UseDefaultRoleOnly && (Owner.Role != Role)) || (!Settings.DynamicRoles.IsEmpty() && !Settings.DynamicRoles.Contains(Owner.Role))) { - Log.InfoWithContext("Tick check failed"); - Destroy(); return; } diff --git a/Exiled.Example/TestRole/CustomRoleType.cs b/Exiled.Example/TestRole/CustomRoleType.cs new file mode 100644 index 0000000000..67fe24e309 --- /dev/null +++ b/Exiled.Example/TestRole/CustomRoleType.cs @@ -0,0 +1,22 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Example.TestRole +{ + using Exiled.CustomModules.API.Enums; + + /// + /// The custom role type. + /// + public class CustomRoleType : UUCustomRoleType + { + /// + /// Initializes a new custom role id. + /// + public static readonly CustomRoleType Scp999 = new(); + } +} \ No newline at end of file diff --git a/Exiled.Example/TestRole/Scp999Behaviour.cs b/Exiled.Example/TestRole/Scp999Behaviour.cs new file mode 100644 index 0000000000..4e5e443ed8 --- /dev/null +++ b/Exiled.Example/TestRole/Scp999Behaviour.cs @@ -0,0 +1,21 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Example.TestRole +{ + using Exiled.CustomModules.API.Features.CustomRoles; + + /// + public class Scp999Behaviour : RoleBehaviour + { + /// + protected override void PostInitialize() + { + base.PostInitialize(); + } + } +} \ No newline at end of file diff --git a/Exiled.Example/TestRole/Scp999Config.cs b/Exiled.Example/TestRole/Scp999Config.cs new file mode 100644 index 0000000000..44cd93c69a --- /dev/null +++ b/Exiled.Example/TestRole/Scp999Config.cs @@ -0,0 +1,21 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Example.TestRole +{ + using Exiled.CustomModules.API.Features.Attributes; + using Exiled.CustomModules.API.Features.CustomRoles; + using Exiled.CustomModules.API.Features.Generic; + + /// + [ModuleIdentifier] + public class Scp999Config : ModulePointer + { + /// + public override uint Id { get; set; } = CustomRoleType.Scp999; + } +} \ No newline at end of file diff --git a/Exiled.Example/TestRole/Scp999Role.cs b/Exiled.Example/TestRole/Scp999Role.cs new file mode 100644 index 0000000000..883110626e --- /dev/null +++ b/Exiled.Example/TestRole/Scp999Role.cs @@ -0,0 +1,79 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Example.TestRole +{ + using Exiled.API.Enums; + using Exiled.CustomModules.API.Features.Attributes; + using Exiled.CustomModules.API.Features.CustomRoles; + using PlayerRoles; + + /// + [ModuleIdentifier] + public class Scp999Role : CustomRole + { + /// + public override string Name { get; set; } = "SCP-999"; + + /// + public override uint Id { get; set; } = CustomRoleType.Scp999; + + /// + public override bool IsEnabled { get; set; } = true; + + /// + public override string Description { get; set; } = "SCP-999"; + + /// + public override RoleTypeId Role { get; set; } = RoleTypeId.ClassD; + + /// + public override int Probability { get; set; } = 100; + + /// + public override int MaxInstances { get; set; } = 1; + + /// + public override Team[] TeamsOwnership { get; set; } = { Team.SCPs }; + + /// + public override RoleTypeId AssignFromRole { get; set; } = RoleTypeId.ClassD; + + /// + public override bool IsScp { get; set; } = true; + + /// + public override RoleSettings Settings { get; set; } = new() + { + UseDefaultRoleOnly = true, + UniqueRole = RoleTypeId.ClassD, + + Health = 300, + MaxHealth = 400, + Scale = 0.90f, + CustomInfo = "SCP-999", + + SpawnedText = new("You've been spawned as SCP-999", 10, channel: TextChannelType.Broadcast), + + PreservePosition = true, + + PreserveInventory = true, + + CanActivateWarhead = true, + + CanBypassCheckpoints = true, + CanActivateGenerators = false, + CanPlaceBlood = false, + CanBeHurtByScps = false, + CanHurtScps = false, + CanBeHandcuffed = false, + + DoesLookingAffectScp096 = false, + DoesLookingAffectScp173 = false, + }; + } +} \ No newline at end of file diff --git a/Exiled.Loader/Loader.cs b/Exiled.Loader/Loader.cs index 47e829ca37..6a653fbc38 100644 --- a/Exiled.Loader/Loader.cs +++ b/Exiled.Loader/Loader.cs @@ -199,6 +199,7 @@ public static IPlugin CreatePlugin(Assembly assembly) continue; } + bool foundAuthority = false; foreach (Type type in assembly.GetTypes()) { if (type.BaseType == typeof(Player) || type.IsSubclassOf(typeof(Player))) @@ -206,11 +207,17 @@ public static IPlugin CreatePlugin(Assembly assembly) DefaultPlayerClassAttribute dpc = type.GetCustomAttribute(); - // To fix. dcp.Enforce don't have to be set true under CustomModules::Pawn. *testing purpose* - if (Player.DEFAULT_PLAYER_CLASS == typeof(Player) && dpc is not null && dpc.EnforceAuthority && defaultPlayerClass is not null) + if (Player.DEFAULT_PLAYER_CLASS == typeof(Player) && dpc is not null && defaultPlayerClass is not null) { - Log.DebugWithContext("Changing default player class to " + defaultPlayerClass.Name); - Player.DEFAULT_PLAYER_CLASS = defaultPlayerClass; + if (dpc.EnforceAuthority) + { + Player.DEFAULT_PLAYER_CLASS = defaultPlayerClass; + foundAuthority = true; + } + else if (!dpc.EnforceAuthority && !foundAuthority) + { + Player.DEFAULT_PLAYER_CLASS = defaultPlayerClass; + } } } From cb36ef8c682e3daca5733c0eecd0a923b33ccc34 Mon Sep 17 00:00:00 2001 From: NaoUnderscore Date: Fri, 9 Aug 2024 00:26:00 +0200 Subject: [PATCH 4/7] remove `this` --- .../API/Features/Deserializers/ModuleParser.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs b/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs index a93d143bd8..fddb5326cc 100644 --- a/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs +++ b/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs @@ -28,7 +28,7 @@ public abstract class ModuleParser /// protected ModuleParser() { - ParserContext.Delegates.Add(this.Delegate); + ParserContext.Delegates.Add(Delegate); } /// @@ -99,9 +99,9 @@ public ParserContext( Type expectedType, Func nestedObjectDeserializer) { - this.Parser = parser; - this.ExpectedType = expectedType; - this.NestedObjectDeserializer = nestedObjectDeserializer; + Parser = parser; + ExpectedType = expectedType; + NestedObjectDeserializer = nestedObjectDeserializer; } /// From ec7b96ef9413f93f9f0aee0fdeb9da0d5ce86413 Mon Sep 17 00:00:00 2001 From: NaoUnderscore Date: Wed, 14 Aug 2024 18:21:56 +0200 Subject: [PATCH 5/7] Fixed components not initializing, owner being null on post initialize, modules not being registered using automatic modules loader, user-defined modules being ignored during the registration process, configs and modules not being serialized. Removed some unused constructors on ECS. Fixed parsers and deserializers. Changed `SpawnReason` to `RoleChangeReason` on `Pawn::SetRole` related methods. Added more properties to `Example` plugin; applied some fixes. `UseAutomaticModulesLoader` config value is now set to `true` by default. --- Exiled.API/Features/Core/EObject.cs | 21 +++-- .../Features/Core/Generic/EBehaviour.cs | 17 ---- .../Core/Generic/UniqueUnmanagedEnumClass.cs | 4 + .../Core/Generic/UnmanagedEnumClass.cs | 3 + Exiled.API/Features/Player.cs | 11 +-- Exiled.API/Features/Roles/Role.cs | 8 +- .../CustomAbilities/ISelectableAbility.cs | 4 - .../Settings/AbilitySettings.cs | 3 - .../Settings/LevelAbilitySettings.cs | 3 - .../Types/AbilityBehaviourBase.cs | 1 - .../CustomItems/Items/ItemSettings.cs | 1 - .../API/Features/CustomModule.cs | 23 +++-- .../API/Features/CustomRoles/CustomRole.cs | 2 +- .../API/Features/CustomRoles/RoleBehaviour.cs | 43 +++++---- .../API/Features/CustomRoles/RoleSettings.cs | 2 +- ...zer.cs => AdditivePropertyDeserializer.cs} | 13 +-- .../Inheritables/CustomRoleDeserializer.cs | 90 ------------------- .../Features/Deserializers/ModuleParser.cs | 60 +------------ .../Features/Deserializers/ParserContext.cs | 66 ++++++++++++++ .../API/Features/ModuleBehaviour.cs | 17 ---- .../API/Features/ModuleInfo.cs | 2 +- Exiled.CustomModules/Config.cs | 3 +- .../CustomAbilities/AddedAbilityEventArgs.cs | 1 - .../RemovedAbilityEventArgs.cs | 1 - .../CustomItems/OwnerChangingRoleEventArgs.cs | 4 - .../AssigningHumanCustomRolesEventArgs.cs | 2 - .../AssigningScpCustomRolesEventArgs.cs | 3 - .../CustomRoles/ChangedCustomRoleEventArgs.cs | 5 -- .../ChangingCustomRoleEventArgs.cs | 5 -- .../SelectingCustomTeamRespawnEventArgs.cs | 7 -- .../EventArgs/Interfaces/ICustomItemEvent.cs | 1 - .../Interfaces/ICustomPickupEvent.cs | 1 - .../Tracking/ItemTrackingModifiedEventArgs.cs | 2 - .../PickupTrackingModifiedEventArgs.cs | 1 - .../Tracking/TrackingModifiedEventArgs.cs | 1 - Exiled.Example/Example.cs | 8 +- stylecop.json | 6 -- 37 files changed, 149 insertions(+), 296 deletions(-) rename Exiled.CustomModules/API/Features/Deserializers/Inheritables/{RoleSettingsDeserializer.cs => AdditivePropertyDeserializer.cs} (79%) delete mode 100644 Exiled.CustomModules/API/Features/Deserializers/Inheritables/CustomRoleDeserializer.cs create mode 100644 Exiled.CustomModules/API/Features/Deserializers/ParserContext.cs diff --git a/Exiled.API/Features/Core/EObject.cs b/Exiled.API/Features/Core/EObject.cs index 38255bc2db..efa17eb96a 100644 --- a/Exiled.API/Features/Core/EObject.cs +++ b/Exiled.API/Features/Core/EObject.cs @@ -378,10 +378,11 @@ public static EObject CreateDefaultSubobject(Type type, params object[] paramete } /// - /// InitializeBaseType if 0 constructors are found. + /// Initializes an instance of the specified generic type . + /// If no constructors are found, the base type is initialized. /// - /// Generic Type. - /// EObject. + /// The type that inherits from . + /// An instance of the specified type . public static T InitializeBaseType() where T : EObject { @@ -389,12 +390,15 @@ public static T InitializeBaseType() } /// - /// InitializeBaseType if 0 constructors are found. + /// Initializes an instance of the specified type. + /// If no constructors are found, the base type is initialized. /// - /// type. - /// constructors parameters. - /// EObject - /// If the class isn't a subclass of EObject. + /// The type to be initialized. + /// Constructor parameters for the type. + /// An instance of the specified type. + /// + /// Thrown if the provided is not a subclass of . + /// public static EObject InitializeBaseType(Type type, params object[] parameters) { const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; @@ -915,4 +919,3 @@ protected virtual void OnDestroyed() } } } - diff --git a/Exiled.API/Features/Core/Generic/EBehaviour.cs b/Exiled.API/Features/Core/Generic/EBehaviour.cs index 6be26f7c27..dd5553a8a4 100644 --- a/Exiled.API/Features/Core/Generic/EBehaviour.cs +++ b/Exiled.API/Features/Core/Generic/EBehaviour.cs @@ -25,23 +25,6 @@ namespace Exiled.API.Features.Core.Generic public abstract class EBehaviour : EActor where T : GameEntity { - /// - /// Initializes a new instance of the class. - /// - protected EBehaviour() - : base() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The base . - protected EBehaviour(GameObject gameObject = null) - : base(gameObject) - { - } - /// /// Gets or sets the owner of the . /// diff --git a/Exiled.API/Features/Core/Generic/UniqueUnmanagedEnumClass.cs b/Exiled.API/Features/Core/Generic/UniqueUnmanagedEnumClass.cs index 67f0b8331a..0db2f2b9d7 100644 --- a/Exiled.API/Features/Core/Generic/UniqueUnmanagedEnumClass.cs +++ b/Exiled.API/Features/Core/Generic/UniqueUnmanagedEnumClass.cs @@ -15,6 +15,7 @@ namespace Exiled.API.Features.Core.Generic using Exiled.API.Features.Core.Generic.Pools; using Exiled.API.Interfaces; using LiteNetLib.Utils; + using YamlDotNet.Serialization; /// /// A class which allows data implicit conversions and ensures unique values. @@ -60,16 +61,19 @@ public UniqueUnmanagedEnumClass() /// /// Gets all object instances. /// + [YamlIgnore] public static IEnumerable Values => values.Values; /// /// Gets the value of the enum item. /// + [YamlIgnore] public TSource Value { get; } /// /// Gets the name determined from reflection. /// + [YamlMember(Alias = "name")] public string Name { get diff --git a/Exiled.API/Features/Core/Generic/UnmanagedEnumClass.cs b/Exiled.API/Features/Core/Generic/UnmanagedEnumClass.cs index 1f01dc4328..2d396b1e6a 100644 --- a/Exiled.API/Features/Core/Generic/UnmanagedEnumClass.cs +++ b/Exiled.API/Features/Core/Generic/UnmanagedEnumClass.cs @@ -15,6 +15,7 @@ namespace Exiled.API.Features.Core.Generic using Exiled.API.Features.Core.Generic.Pools; using Exiled.API.Interfaces; using LiteNetLib.Utils; + using YamlDotNet.Serialization; /// /// A class which allows data implicit conversions. @@ -51,11 +52,13 @@ protected UnmanagedEnumClass(TSource value) /// /// Gets the value of the enum item. /// + [YamlIgnore] public TSource Value { get; } /// /// Gets the name determined from reflection. /// + [YamlMember(Alias = "name")] public string Name { get diff --git a/Exiled.API/Features/Player.cs b/Exiled.API/Features/Player.cs index b99ada47e0..1d0661c493 100644 --- a/Exiled.API/Features/Player.cs +++ b/Exiled.API/Features/Player.cs @@ -669,10 +669,10 @@ public PlayerPermissions RemoteAdminPermissions /// This role is automatically cached until it changes, and it is recommended to use this property directly rather than storing the property yourself. /// /// - /// Roles and RoleTypeIds can be compared directly. Player.Role == RoleTypeId.Scp079 is valid and will return if the player is SCP-079. To set the player's role, see . + /// Roles and RoleTypeIds can be compared directly. Player.Role == RoleTypeId.Scp079 is valid and will return if the player is SCP-079. To set the player's role, see . /// /// - /// + /// [EProperty(readOnly: true, category: ROLES_CATEGORY)] public Role Role { @@ -3993,8 +3993,9 @@ public void PlayGunSound(Vector3 position, ItemType itemType, byte volume, byte /// The UnitNameId to use for the player's new role, if the player's new role uses unit names. (is NTF). public void ChangeAppearance(RoleTypeId type, IEnumerable playersToAffect, bool skipJump = false, byte unitId = 0) { - if (ReferenceHub.gameObject == null || !RoleExtensions.TryGetRoleBase(type, out PlayerRoleBase roleBase)) + if (ReferenceHub.gameObject == null || !type.TryGetRoleBase(out PlayerRoleBase roleBase)) return; + bool isRisky = type.GetRoleBase().Team is Team.Dead || IsDead; NetworkWriterPooled writer = NetworkWriterPool.Get(); @@ -4006,6 +4007,7 @@ public void ChangeAppearance(RoleTypeId type, IEnumerable playersToAffec { if (Role.Base is not PHumanRole) isRisky = true; + writer.WriteByte(unitId); } @@ -4016,8 +4018,7 @@ public void ChangeAppearance(RoleTypeId type, IEnumerable playersToAffec else fpc = playerfpc; - ushort value = 0; - fpc?.FpcModule.MouseLook.GetSyncValues(0, out value, out ushort _); + fpc.FpcModule.MouseLook.GetSyncValues(0, out ushort value, out ushort _); writer.WriteRelativePosition(RelativePosition); writer.WriteUShort(value); } diff --git a/Exiled.API/Features/Roles/Role.cs b/Exiled.API/Features/Roles/Role.cs index 459ea7b1a7..ecfbc9bc5b 100644 --- a/Exiled.API/Features/Roles/Role.cs +++ b/Exiled.API/Features/Roles/Role.cs @@ -261,8 +261,8 @@ public static RoleTypeId Random(bool includeNonPlayableRoles = false, IEnumerabl /// Sets the player's . /// /// The new to be set. - /// The defining why the player's role was changed. - public virtual void Set(RoleTypeId newRole, SpawnReason reason = null) => Set(newRole, reason ?? Enums.SpawnReason.ForceClass, RoleSpawnFlags.All); + /// The defining why the player's role was changed. + public virtual void Set(RoleTypeId newRole, RoleChangeReason reason = RoleChangeReason.RemoteAdmin) => Set(newRole, reason, RoleSpawnFlags.All); /// S /// Sets the player's . @@ -275,9 +275,9 @@ public static RoleTypeId Random(bool includeNonPlayableRoles = false, IEnumerabl /// Sets the player's . /// /// The new to be set. - /// The defining why the player's role was changed. + /// The defining why the player's role was changed. /// The defining player spawn logic. - public virtual void Set(RoleTypeId newRole, SpawnReason reason, RoleSpawnFlags spawnFlags) => + public virtual void Set(RoleTypeId newRole, RoleChangeReason reason, RoleSpawnFlags spawnFlags) => Owner.RoleManager.ServerSetRole(newRole, reason, spawnFlags); /// diff --git a/Exiled.CustomModules/API/Features/CustomAbilities/ISelectableAbility.cs b/Exiled.CustomModules/API/Features/CustomAbilities/ISelectableAbility.cs index af8b4cfacb..fc066d0799 100644 --- a/Exiled.CustomModules/API/Features/CustomAbilities/ISelectableAbility.cs +++ b/Exiled.CustomModules/API/Features/CustomAbilities/ISelectableAbility.cs @@ -7,10 +7,6 @@ namespace Exiled.CustomModules.API.Features.CustomAbilities { - using Exiled.API.Features.Core; - using Exiled.API.Features.Core.Interfaces; - using Exiled.CustomModules.API.Features.PlayerAbilities; - /// /// Represents a marker interface for custom ability that can be selected. /// diff --git a/Exiled.CustomModules/API/Features/CustomAbilities/Settings/AbilitySettings.cs b/Exiled.CustomModules/API/Features/CustomAbilities/Settings/AbilitySettings.cs index 28f4f8af64..f702028edd 100644 --- a/Exiled.CustomModules/API/Features/CustomAbilities/Settings/AbilitySettings.cs +++ b/Exiled.CustomModules/API/Features/CustomAbilities/Settings/AbilitySettings.cs @@ -7,11 +7,8 @@ namespace Exiled.CustomModules.API.Features.CustomAbilities.Settings { - using Exiled.API.Features; using Exiled.API.Features.Core; using Exiled.API.Features.Core.Interfaces; - using Exiled.CustomModules.API.Features.CustomAbilities; - using Exiled.CustomModules.API.Features.CustomRoles; /// /// Represents the base class for player-specific ability behaviors. diff --git a/Exiled.CustomModules/API/Features/CustomAbilities/Settings/LevelAbilitySettings.cs b/Exiled.CustomModules/API/Features/CustomAbilities/Settings/LevelAbilitySettings.cs index ec013793e6..9e0f9ea6f0 100644 --- a/Exiled.CustomModules/API/Features/CustomAbilities/Settings/LevelAbilitySettings.cs +++ b/Exiled.CustomModules/API/Features/CustomAbilities/Settings/LevelAbilitySettings.cs @@ -8,9 +8,6 @@ namespace Exiled.CustomModules.API.Features.CustomAbilities.Settings { using Exiled.API.Features; - using Exiled.API.Features.Core; - using Exiled.API.Features.Core.Interfaces; - using Exiled.CustomModules.API.Features.CustomRoles; /// /// Represents the base class for player-specific ability behaviors. diff --git a/Exiled.CustomModules/API/Features/CustomAbilities/Types/AbilityBehaviourBase.cs b/Exiled.CustomModules/API/Features/CustomAbilities/Types/AbilityBehaviourBase.cs index c56ea62b5e..ff3e6acda8 100644 --- a/Exiled.CustomModules/API/Features/CustomAbilities/Types/AbilityBehaviourBase.cs +++ b/Exiled.CustomModules/API/Features/CustomAbilities/Types/AbilityBehaviourBase.cs @@ -11,7 +11,6 @@ namespace Exiled.CustomModules.API.Features.CustomAbilities using Exiled.API.Features; using Exiled.API.Features.Core; - using Exiled.API.Features.Core.Generic; using Exiled.API.Features.Core.Interfaces; using Exiled.API.Features.DynamicEvents; using Exiled.CustomModules.API.Features.CustomAbilities.Settings; diff --git a/Exiled.CustomModules/API/Features/CustomItems/Items/ItemSettings.cs b/Exiled.CustomModules/API/Features/CustomItems/Items/ItemSettings.cs index 88fc18a341..8a8167d1c2 100644 --- a/Exiled.CustomModules/API/Features/CustomItems/Items/ItemSettings.cs +++ b/Exiled.CustomModules/API/Features/CustomItems/Items/ItemSettings.cs @@ -8,7 +8,6 @@ namespace Exiled.CustomModules.API.Features.CustomItems.Items { using Exiled.API.Features; - using Exiled.API.Features.Core; using Exiled.API.Features.Spawn; using UnityEngine; diff --git a/Exiled.CustomModules/API/Features/CustomModule.cs b/Exiled.CustomModules/API/Features/CustomModule.cs index 1bbcab8186..b0a936bde8 100644 --- a/Exiled.CustomModules/API/Features/CustomModule.cs +++ b/Exiled.CustomModules/API/Features/CustomModule.cs @@ -24,7 +24,6 @@ namespace Exiled.CustomModules.API.Features using Exiled.CustomModules.API.Enums; using Exiled.CustomModules.API.Features.Attributes; using YamlDotNet.Serialization; - using YamlDotNet.Serialization.NodeDeserializers; /// /// Represents a marker class for custom modules. @@ -54,14 +53,14 @@ public abstract class CustomModule : TypeCastObject, IEquatable [YamlIgnore] [DynamicEventDispatcher] - public static TDynamicEventDispatcher OnEnabled { get; set; } + public static TDynamicEventDispatcher OnEnabled { get; set; } = new(); /// /// Gets or sets the which handles all delegates to be fired when a module gets disabled. /// [YamlIgnore] [DynamicEventDispatcher] - public static TDynamicEventDispatcher OnDisabled { get; set; } + public static TDynamicEventDispatcher OnDisabled { get; set; } = new(); /// /// Gets or sets the 's name. @@ -239,7 +238,6 @@ internal string PointerPath .WithTypeConverter(new EnumClassConverter()) .WithTypeConverter(new PrivateConstructorConverter()) .WithNamingConvention(UnderscoredNamingConvention.Instance) - .WithNodeDeserializer(_ => new CustomModuleDeserializer(), deserializer => deserializer.InsteadOf()) .WithDuplicateKeyChecking() .IgnoreFields() .IgnoreUnmatchedProperties() @@ -320,7 +318,9 @@ public static void LoadAll() /// Determines whether the loaded modules should be enabled after loading. public static void Load(Assembly assembly = null, bool shouldBeEnabled = false) { + Log.InfoWithContext($"Using defined assembly? {assembly is null}"); assembly ??= Assembly.GetCallingAssembly(); + Log.InfoWithContext($"{assembly.GetName().Name}"); UUModuleType FindClosestModuleType(Type t, IEnumerable source) { @@ -329,17 +329,13 @@ UUModuleType FindClosestModuleType(Type t, IEnumerable source) return source.ElementAt(matches.IndexOf(matches.Min())).GetValue(null) as UUModuleType; } - Type runtime_ModuleType = assembly.GetTypes().FirstOrDefault(t => !t.IsAbstract && typeof(UUModuleType).IsAssignableFrom(t)); - if (runtime_ModuleType is null) - { - Log.Debug("No UUModuleType-derived types were found. Custom modules must have an identifier based on UUModuleType."); - return; - } - + Type runtime_ModuleType = assembly.GetTypes().FirstOrDefault(t => !t.IsAbstract && typeof(UUModuleType).IsAssignableFrom(t)) ?? typeof(UUModuleType); IEnumerable moduleTypeValuesInfo = runtime_ModuleType.GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.GetValue(null) is UUModuleType); + Log.InfoWithContext($"DB1"); + foreach (Type type in assembly.GetTypes()) { - if (type.IsAbstract || type.BaseType != typeof(CustomModule) || Loader.Any(m => m.Type == type)) + if (type.IsAbstract || (type.BaseType != typeof(CustomModule) && !type.IsSubclassOf(typeof(CustomModule)))) continue; IEnumerable rhMethods = type.GetMethods(ModuleInfo.SIGNATURE_BINDINGS) @@ -564,6 +560,9 @@ private static void AutomaticModulesLoaderState(bool shouldLoad) private void CopyProperties(CustomModule source) { + if (source is null) + throw new NullReferenceException("Source is null. Was the custom module deserialized?"); + foreach (PropertyInfo property in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (property.CanWrite) diff --git a/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs b/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs index a18b08850d..87c0d4fd05 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/CustomRole.cs @@ -627,7 +627,7 @@ public static void Remove(IEnumerable players) /// public static void EnableAll(Assembly assembly) { - if (!CustomModules.Instance.Config.Modules.Contains("CustomRoles")) + if (CustomModules.Instance.Config.Modules is null || !CustomModules.Instance.Config.Modules.Contains("CustomRoles")) throw new Exception("ModuleType::CustomRoles must be enabled in order to load any custom roles"); Player.DEFAULT_ROLE_BEHAVIOUR = typeof(RoleBehaviour); diff --git a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs index 128caa64c2..5f640b87d2 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs @@ -39,22 +39,6 @@ namespace Exiled.CustomModules.API.Features.CustomRoles /// public class RoleBehaviour : ModuleBehaviour, IAdditiveSettings { - /// - /// Initializes a new instance of the class. - /// - protected RoleBehaviour() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// owner's gameobject. - protected RoleBehaviour(GameObject gameObject) - : base(gameObject) - { - } - private Vector3 lastPosition; private RoleTypeId fakeAppearance; private bool isHuman; @@ -251,8 +235,8 @@ public virtual void AdjustAdditivePipe() } Owner.UniqueRole = CustomRole.Name; - //Owner.TryAddCustomRoleFriendlyFire(Name, Settings.FriendlyFireMultiplier); + // TODO: Owner.TryAddCustomRoleFriendlyFire(Name, Settings.FriendlyFireMultiplier); if (CustomRole.EscapeBehaviourComponent is not null) { Owner.AddComponent(CustomRole.EscapeBehaviourComponent); @@ -664,8 +648,20 @@ protected virtual void OverrideSpawnPoint(SpawningEventArgs ev) /// protected virtual void PickingUpItemBehavior(SearchingPickupEventArgs ev) { + if (ev.Pickup is null) + { + Log.Error("Pickup is null"); + } + + Log.InfoWithContext($"{ev.Player} is trying to pick up {ev.Pickup.Type}"); + if (!Check(ev.Player) || Settings.CanPickupItems) + { + Log.InfoWithContext($"{ev.Player} is not {CustomRole.Name} or can pick up items as {CustomRole.Name}"); return; + } + + Log.InfoWithContext($"{ev.Player} cannot pick up items"); ev.IsAllowed = false; } @@ -763,8 +759,21 @@ protected virtual void PlacingBloodBehavior(PlacingBloodEventArgs ev) /// protected virtual void DroppingItemBehavior(DroppingItemEventArgs ev) { + if (ev.Item is null) + { + Log.Error("Item is null"); + } + + Log.InfoWithContext($"{ev.Player} is trying to drop {ev.Item.Type}"); + + Log.WarnWithContext(Settings.CanDropItems); if (!Check(ev.Player) || Settings.CanDropItems) + { + Log.InfoWithContext($"{ev.Player} is not {CustomRole.Name} or can drop items as {CustomRole.Name}"); return; + } + + Log.InfoWithContext($"{ev.Player} cannot drop items"); ev.IsAllowed = false; } diff --git a/Exiled.CustomModules/API/Features/CustomRoles/RoleSettings.cs b/Exiled.CustomModules/API/Features/CustomRoles/RoleSettings.cs index 0ee8bcff1f..24a1c47ea1 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/RoleSettings.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/RoleSettings.cs @@ -119,7 +119,7 @@ public class RoleSettings : TypeCastObject, IAdditiveProperty /// /// Gets or sets the . /// - public virtual SpawnReason SpawnReason { get; set; } = SpawnReason.ForceClass; + public virtual RoleChangeReason SpawnReason { get; set; } = RoleChangeReason.RemoteAdmin; /// /// Gets or sets a value indicating whether the assignment should maintain the player's current inventory. diff --git a/Exiled.CustomModules/API/Features/Deserializers/Inheritables/RoleSettingsDeserializer.cs b/Exiled.CustomModules/API/Features/Deserializers/Inheritables/AdditivePropertyDeserializer.cs similarity index 79% rename from Exiled.CustomModules/API/Features/Deserializers/Inheritables/RoleSettingsDeserializer.cs rename to Exiled.CustomModules/API/Features/Deserializers/Inheritables/AdditivePropertyDeserializer.cs index 136e451807..227267f433 100644 --- a/Exiled.CustomModules/API/Features/Deserializers/Inheritables/RoleSettingsDeserializer.cs +++ b/Exiled.CustomModules/API/Features/Deserializers/Inheritables/AdditivePropertyDeserializer.cs @@ -1,5 +1,5 @@ // ----------------------------------------------------------------------- -// +// // Copyright (c) Exiled Team. All rights reserved. // Licensed under the CC BY-SA 3.0 license. // @@ -10,6 +10,7 @@ namespace Exiled.CustomModules.API.Features.Deserializers.Inheritables using System; using System.Reflection; + using Exiled.API.Features.Core.Interfaces; using Exiled.CustomModules.API.Features.CustomRoles; using YamlDotNet.Core; using YamlDotNet.Core.Events; @@ -17,7 +18,7 @@ namespace Exiled.CustomModules.API.Features.Deserializers.Inheritables /// /// The deserializer for Role Settings. /// - public class RoleSettingsDeserializer : ModuleParser + public class AdditivePropertyDeserializer : ModuleParser { /// public override ParserContext.ModuleDelegate Delegate { get; set; } = Deserialize; @@ -30,16 +31,16 @@ public class RoleSettingsDeserializer : ModuleParser /// A bool stating if it was successful or not. public static bool Deserialize(in ParserContext ctx, out object value) { - RoleSettings roleSettings = new RoleSettings(); + IAdditiveProperty additiveProperty = Activator.CreateInstance(ctx.ExpectedType) as IAdditiveProperty; ctx.Parser.Consume(); - while (ctx.Parser.TryConsume(out Scalar scalar)) + while (ctx.Parser.TryConsume(out Scalar scalar)) { PropertyInfo property = typeof(RoleSettings).GetProperty(scalar.Value, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); if (property != null) { object propertyValue = ctx.NestedObjectDeserializer(ctx.Parser, property.PropertyType); - property.SetValue(roleSettings, propertyValue); + property.SetValue(additiveProperty, propertyValue); } else { @@ -49,7 +50,7 @@ public static bool Deserialize(in ParserContext ctx, out object value) } ctx.Parser.Consume(); - value = roleSettings; + value = additiveProperty; return true; } } diff --git a/Exiled.CustomModules/API/Features/Deserializers/Inheritables/CustomRoleDeserializer.cs b/Exiled.CustomModules/API/Features/Deserializers/Inheritables/CustomRoleDeserializer.cs deleted file mode 100644 index 1e6c4f30af..0000000000 --- a/Exiled.CustomModules/API/Features/Deserializers/Inheritables/CustomRoleDeserializer.cs +++ /dev/null @@ -1,90 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) Exiled Team. All rights reserved. -// Licensed under the CC BY-SA 3.0 license. -// -// ----------------------------------------------------------------------- - -namespace Exiled.CustomModules.API.Features.Deserializers.Inheritables -{ - using System; - using System.Reflection; - - using Exiled.CustomModules.API.Features.CustomRoles; - using YamlDotNet.Core; - using YamlDotNet.Core.Events; - - /// - /// The deserializer for Custom Roles. - /// - public class CustomRoleDeserializer : ModuleParser - { - /// - public override ParserContext.ModuleDelegate Delegate { get; set; } = Deserialize; - - /// - /// The actual deserializer. - /// - /// The context. - /// If valid, returns this. - /// A bool stating if it was successful or not. - public static bool Deserialize(in ParserContext ctx, out object value) - { - if (IsCustomRoleType(ctx.ExpectedType)) - { - value = Activator.CreateInstance(ctx.ExpectedType); - ctx.Parser.Consume(); - - while (ctx.Parser.TryConsume(out Scalar scalar)) - { - PropertyInfo property = ctx.ExpectedType.GetProperty(scalar.Value, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); - if (property != null) - { - object propertyValue = ctx.NestedObjectDeserializer(ctx.Parser, property.PropertyType); - property.SetValue(value, propertyValue); - } - else if (scalar.Value.Equals("settings", StringComparison.OrdinalIgnoreCase)) - { - PropertyInfo settingsProperty = ctx.ExpectedType.GetProperty("Settings", BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); - if (settingsProperty != null) - { - object settingsValue = ctx.NestedObjectDeserializer(ctx.Parser, settingsProperty.PropertyType); - settingsProperty.SetValue(value, settingsValue); - } - } - else - { - // Skip unknown properties - ctx.Parser.SkipThisAndNestedEvents(); - } - } - - ctx.Parser.Consume(); - return true; - } - - value = null; - return false; - } - - /// - /// A function that returns whether a type is a custom role. - /// - /// The Type. - /// A bool that says if the type is a custom role. - public static bool IsCustomRoleType(Type type) - { - while (type != null) - { - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(CustomRole<>)) - { - return true; - } - - type = type.BaseType; - } - - return false; - } - } -} \ No newline at end of file diff --git a/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs b/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs index fddb5326cc..2145e919f8 100644 --- a/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs +++ b/Exiled.CustomModules/API/Features/Deserializers/ModuleParser.cs @@ -7,16 +7,13 @@ namespace Exiled.CustomModules.API.Features.Deserializers { - // ReSharper disable VirtualMemberCallInConstructor using System; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using Exiled.API.Features; using JetBrains.Annotations; - using YamlDotNet.Core; /// /// An inheritable class that declares an additional deserializer. @@ -42,7 +39,7 @@ protected ModuleParser() /// public static void InstantiateModuleParsers() { - Log.Info("Registering Custom Module Deserializers:"); + Log.Debug("Registering Custom Module Deserializers:"); // Get the current assembly Assembly assembly = typeof(ModuleParser).Assembly; @@ -54,62 +51,9 @@ public static void InstantiateModuleParsers() // Instantiate each type with no parameters foreach (Type type in moduleParserTypes) { - Log.Info(type.Name); + Log.Debug(type.Name); Activator.CreateInstance(type); } } } - - /// - /// A context for deserializer parsing. - /// -#pragma warning disable SA1402 - [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Need to be public for deserializer.")] - public class ParserContext -#pragma warning restore SA1402 - { - /// - /// A list of functions that should be checked when deserializing a module. - /// - public static List Delegates = new(); - - /// - /// The Parser. - /// - public readonly IParser Parser; - - /// - /// The expected type. - /// - public readonly Type ExpectedType; - - /// - /// The fallback deserializer. - /// - public readonly Func NestedObjectDeserializer; - - /// - /// Initializes a new instance of the class. - /// - /// The Parser. - /// The type expected. - /// The fallback deserializer. - public ParserContext( - IParser parser, - Type expectedType, - Func nestedObjectDeserializer) - { - Parser = parser; - ExpectedType = expectedType; - NestedObjectDeserializer = nestedObjectDeserializer; - } - - /// - /// A delegate returning bool retaining to a module. - /// - /// The parser context. - /// The output object if successful. - /// A bool stating if parsing was successful or not. - public delegate bool ModuleDelegate(in ParserContext input, out object output); - } } \ No newline at end of file diff --git a/Exiled.CustomModules/API/Features/Deserializers/ParserContext.cs b/Exiled.CustomModules/API/Features/Deserializers/ParserContext.cs new file mode 100644 index 0000000000..da728ccd38 --- /dev/null +++ b/Exiled.CustomModules/API/Features/Deserializers/ParserContext.cs @@ -0,0 +1,66 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) Exiled Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.CustomModules.API.Features.Deserializers +{ + using System; + using System.Collections.Generic; + + using YamlDotNet.Core; + +#pragma warning disable SA1401 + + /// + /// A context for deserializer parsing. + /// + public class ParserContext + { + /// + /// A list of functions that should be checked when deserializing a module. + /// + public static readonly List Delegates = new(); + + /// + /// The parser. + /// + public readonly IParser Parser; + + /// + /// The expected type. + /// + public readonly Type ExpectedType; + + /// + /// The fallback deserializer. + /// + public readonly Func NestedObjectDeserializer; + + /// + /// Initializes a new instance of the class. + /// + /// The Parser. + /// The type expected. + /// The fallback deserializer. + public ParserContext( + IParser parser, + Type expectedType, + Func nestedObjectDeserializer) + { + Parser = parser; + ExpectedType = expectedType; + NestedObjectDeserializer = nestedObjectDeserializer; + } + + /// + /// A delegate returning bool retaining to a module. + /// + /// The parser context. + /// The output object if successful. + /// A bool stating if parsing was successful or not. + public delegate bool ModuleDelegate(in ParserContext input, out object output); + } +} \ No newline at end of file diff --git a/Exiled.CustomModules/API/Features/ModuleBehaviour.cs b/Exiled.CustomModules/API/Features/ModuleBehaviour.cs index b8bede4980..efb7a43f23 100644 --- a/Exiled.CustomModules/API/Features/ModuleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/ModuleBehaviour.cs @@ -25,23 +25,6 @@ namespace Exiled.CustomModules.API.Features public abstract class ModuleBehaviour : EBehaviour where TEntity : GameEntity { - /// - /// Initializes a new instance of the class. - /// - protected ModuleBehaviour() - : base() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// owner's gameobject. - protected ModuleBehaviour(GameObject gameObject) - : base(gameObject) - { - } - /// /// Gets or sets the behaviour's configs. /// diff --git a/Exiled.CustomModules/API/Features/ModuleInfo.cs b/Exiled.CustomModules/API/Features/ModuleInfo.cs index 76fe2b692c..841011ae41 100644 --- a/Exiled.CustomModules/API/Features/ModuleInfo.cs +++ b/Exiled.CustomModules/API/Features/ModuleInfo.cs @@ -33,7 +33,7 @@ public struct ModuleInfo /// /// The binding flags for identifying the registration handlers. /// - public const BindingFlags SIGNATURE_BINDINGS = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.IgnoreCase; + public const BindingFlags SIGNATURE_BINDINGS = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy; #pragma warning restore SA1310 #pragma warning disable SA1202 diff --git a/Exiled.CustomModules/Config.cs b/Exiled.CustomModules/Config.cs index 54cc45a327..6cf3768674 100644 --- a/Exiled.CustomModules/Config.cs +++ b/Exiled.CustomModules/Config.cs @@ -10,7 +10,6 @@ namespace Exiled.CustomModules using System.ComponentModel; using Exiled.API.Interfaces; - using Exiled.CustomModules.API.Enums; /// /// The plugin's config. @@ -48,7 +47,7 @@ public class Config : IConfig /// It negatively affects the performance in case of the presence of a big amount of plugins. /// [Description("Whether the automatic modules loader should be used.")] - public bool UseAutomaticModulesLoader { get; set; } + public bool UseAutomaticModulesLoader { get; set; } = true; /// /// Gets or sets all modules to be loaded. diff --git a/Exiled.CustomModules/Events/EventArgs/CustomAbilities/AddedAbilityEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomAbilities/AddedAbilityEventArgs.cs index 5a155f7b56..9147aadff0 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomAbilities/AddedAbilityEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomAbilities/AddedAbilityEventArgs.cs @@ -9,7 +9,6 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomAbilities { using Exiled.API.Features.Core; using Exiled.CustomModules.API.Features.CustomAbilities; - using Exiled.Events.EventArgs.Interfaces; /// /// Contains all information after adding an ability. diff --git a/Exiled.CustomModules/Events/EventArgs/CustomAbilities/RemovedAbilityEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomAbilities/RemovedAbilityEventArgs.cs index 743d9b43b5..70881c71c2 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomAbilities/RemovedAbilityEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomAbilities/RemovedAbilityEventArgs.cs @@ -9,7 +9,6 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomAbilities { using Exiled.API.Features.Core; using Exiled.CustomModules.API.Features.CustomAbilities; - using Exiled.Events.EventArgs.Interfaces; /// /// Contains all information after removing an ability. diff --git a/Exiled.CustomModules/Events/EventArgs/CustomItems/OwnerChangingRoleEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomItems/OwnerChangingRoleEventArgs.cs index 1463032206..17e28cd8c1 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomItems/OwnerChangingRoleEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomItems/OwnerChangingRoleEventArgs.cs @@ -8,14 +8,10 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomItems { using Exiled.API.Features; - using Exiled.API.Features.Core; using Exiled.API.Features.Items; using Exiled.CustomModules.API.Features.CustomItems; using Exiled.CustomModules.API.Features.CustomItems.Items; using Exiled.Events.EventArgs.Player; - - using InventorySystem.Items; - using PlayerRoles; /// diff --git a/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningHumanCustomRolesEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningHumanCustomRolesEventArgs.cs index ac5b2ee84d..0b73290866 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningHumanCustomRolesEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningHumanCustomRolesEventArgs.cs @@ -9,9 +9,7 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomRoles { using System.Collections.Generic; - using API.Enums; using Exiled.Events.EventArgs.Interfaces; - using PlayerRoles; /// /// Contains all information before assigning human roles. diff --git a/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningScpCustomRolesEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningScpCustomRolesEventArgs.cs index 6f1ed74caa..a6a9d013fd 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningScpCustomRolesEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomRoles/AssigningScpCustomRolesEventArgs.cs @@ -10,11 +10,8 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomRoles using System.Collections.Generic; using System.Linq; - using API.Enums; - using API.Features; using Exiled.API.Features; using Exiled.Events.EventArgs.Interfaces; - using PlayerRoles; /// /// Contains all information before assigning SCP roles. diff --git a/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangedCustomRoleEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangedCustomRoleEventArgs.cs index 3a3e20ac66..115454ce52 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangedCustomRoleEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangedCustomRoleEventArgs.cs @@ -7,13 +7,8 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomRoles { - using System.Collections.Generic; - - using API.Enums; using Exiled.API.Features; - using Exiled.CustomModules.API.Features; using Exiled.Events.EventArgs.Interfaces; - using PlayerRoles; /// /// Contains all information after a player changes role to a custom role. diff --git a/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangingCustomRoleEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangingCustomRoleEventArgs.cs index edcfe38ff3..6d0dea1b89 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangingCustomRoleEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomRoles/ChangingCustomRoleEventArgs.cs @@ -7,13 +7,8 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomRoles { - using System.Collections.Generic; - - using API.Enums; using Exiled.API.Features; - using Exiled.CustomModules.API.Features; using Exiled.Events.EventArgs.Interfaces; - using PlayerRoles; /// /// Contains all information before a player changes role to a custom role. diff --git a/Exiled.CustomModules/Events/EventArgs/CustomRoles/SelectingCustomTeamRespawnEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/CustomRoles/SelectingCustomTeamRespawnEventArgs.cs index 613976ebc3..0196630602 100644 --- a/Exiled.CustomModules/Events/EventArgs/CustomRoles/SelectingCustomTeamRespawnEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/CustomRoles/SelectingCustomTeamRespawnEventArgs.cs @@ -7,15 +7,8 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomRoles { - using System.Collections.Generic; - using System.Linq; - - using API.Enums; - using API.Features; - using Exiled.API.Features; using Exiled.CustomModules.API.Features.CustomRoles; using Exiled.Events.EventArgs.Interfaces; - using PlayerRoles; using Respawning; /// diff --git a/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomItemEvent.cs b/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomItemEvent.cs index a10fca117e..4ca319a7c5 100644 --- a/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomItemEvent.cs +++ b/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomItemEvent.cs @@ -7,7 +7,6 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomItems { - using Exiled.API.Features.Items; using Exiled.CustomModules.API.Features.CustomItems; using Exiled.CustomModules.API.Features.CustomItems.Items; using Exiled.Events.EventArgs.Interfaces; diff --git a/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomPickupEvent.cs b/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomPickupEvent.cs index 84ab6214ff..edac8a47e7 100644 --- a/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomPickupEvent.cs +++ b/Exiled.CustomModules/Events/EventArgs/Interfaces/ICustomPickupEvent.cs @@ -7,7 +7,6 @@ namespace Exiled.CustomModules.Events.EventArgs.CustomItems { - using Exiled.API.Features.Items; using Exiled.CustomModules.API.Features.CustomItems; using Exiled.CustomModules.API.Features.CustomItems.Items; using Exiled.Events.EventArgs.Interfaces; diff --git a/Exiled.CustomModules/Events/EventArgs/Tracking/ItemTrackingModifiedEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/Tracking/ItemTrackingModifiedEventArgs.cs index 81e38ad053..0fdb68a706 100644 --- a/Exiled.CustomModules/Events/EventArgs/Tracking/ItemTrackingModifiedEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/Tracking/ItemTrackingModifiedEventArgs.cs @@ -11,8 +11,6 @@ namespace Exiled.CustomModules.Events.EventArgs.Tracking using Exiled.API.Features.Items; using Exiled.API.Features.Pickups; - using Exiled.CustomModules.API.Features; - using Exiled.CustomModules.API.Features.CustomAbilities; using Exiled.CustomModules.API.Interfaces; using Exiled.Events.EventArgs.Interfaces; diff --git a/Exiled.CustomModules/Events/EventArgs/Tracking/PickupTrackingModifiedEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/Tracking/PickupTrackingModifiedEventArgs.cs index 1dbbcc2df3..67a37aed79 100644 --- a/Exiled.CustomModules/Events/EventArgs/Tracking/PickupTrackingModifiedEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/Tracking/PickupTrackingModifiedEventArgs.cs @@ -10,7 +10,6 @@ namespace Exiled.CustomModules.Events.EventArgs.Tracking using System.Collections.Generic; using Exiled.API.Features.Pickups; - using Exiled.CustomModules.API.Features; using Exiled.CustomModules.API.Interfaces; using Exiled.Events.EventArgs.Interfaces; diff --git a/Exiled.CustomModules/Events/EventArgs/Tracking/TrackingModifiedEventArgs.cs b/Exiled.CustomModules/Events/EventArgs/Tracking/TrackingModifiedEventArgs.cs index 0631f83061..d7607bbf55 100644 --- a/Exiled.CustomModules/Events/EventArgs/Tracking/TrackingModifiedEventArgs.cs +++ b/Exiled.CustomModules/Events/EventArgs/Tracking/TrackingModifiedEventArgs.cs @@ -9,7 +9,6 @@ namespace Exiled.CustomModules.Events.EventArgs.Tracking { using System.Collections.Generic; - using Exiled.CustomModules.API.Features; using Exiled.CustomModules.API.Interfaces; using Exiled.Events.EventArgs.Interfaces; diff --git a/Exiled.Example/Example.cs b/Exiled.Example/Example.cs index 77d066ff6e..b4fefd668a 100644 --- a/Exiled.Example/Example.cs +++ b/Exiled.Example/Example.cs @@ -7,9 +7,7 @@ namespace Exiled.Example { - using Exiled.API.Enums; using Exiled.API.Features; - using Exiled.CustomModules.API.Features.CustomRoles; /// /// The example plugin. @@ -22,7 +20,10 @@ public class Example : Plugin public static Example Instance { get; private set; } /// - public override PluginPriority Priority { get; } = PluginPriority.Last; + public override string Name { get; } = "Exiled.Example"; + + /// + public override string Author { get; } = "Exiled Team"; /// /// Gets the current instance of the event handler. @@ -38,7 +39,6 @@ public override void OnEnabled() // Create new instance of the event handler EventHandler = new(); - CustomRole.EnableAll(); base.OnEnabled(); } diff --git a/stylecop.json b/stylecop.json index 1388251d0d..b16da3eaf8 100644 --- a/stylecop.json +++ b/stylecop.json @@ -1,10 +1,4 @@ { - // ACTION REQUIRED: This file was automatically added to your project, but it - // will not take effect until additional steps are taken to enable it. See the - // following page for additional information: - // - // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md - "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", "settings": { "documentationRules": { From 31e2f0a859024eebee36aa1f5f81efa587876337 Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Wed, 14 Aug 2024 21:53:28 +0200 Subject: [PATCH 6/7] Fixed customroles. Exiled 9.0.0-beta.1 release (#2769) * Fixed Pawn.cs being null if try to use it by Player::Get().Cast(). Adding a method for load a constructor without any param or constructor. Removing abstract from RoleBehaviour.cs for allow the creating of an instance. Added custom role example under Exiled.Example for testing purpose. * Fixed custom roles. * Added test role (testing purposes) * Fixed customroles. Release 9.0.0-beta.1 --- EXILED.props | 2 +- Exiled.API/Features/Core/EActor.cs | 1 - Exiled.API/Features/Core/EObject.cs | 2 +- Exiled.API/Features/Core/GameEntity.cs | 1 - .../Features/Core/Generic/EBehaviour.cs | 13 +++++++++++ .../API/Features/CustomModule.cs | 3 --- .../API/Features/CustomRoles/RoleBehaviour.cs | 22 +++++-------------- 7 files changed, 20 insertions(+), 24 deletions(-) diff --git a/EXILED.props b/EXILED.props index ecc92bf069..bc15d2e7d5 100644 --- a/EXILED.props +++ b/EXILED.props @@ -15,7 +15,7 @@ - 9.0.0-alpha.19 + 9.0.0-beta.1 false diff --git a/Exiled.API/Features/Core/EActor.cs b/Exiled.API/Features/Core/EActor.cs index 87723416c1..7d8b7fe023 100644 --- a/Exiled.API/Features/Core/EActor.cs +++ b/Exiled.API/Features/Core/EActor.cs @@ -481,7 +481,6 @@ protected virtual void PostInitialize() /// protected virtual void OnBeginPlay() { - SubscribeEvents(); } /// diff --git a/Exiled.API/Features/Core/EObject.cs b/Exiled.API/Features/Core/EObject.cs index efa17eb96a..a0af7ac800 100644 --- a/Exiled.API/Features/Core/EObject.cs +++ b/Exiled.API/Features/Core/EObject.cs @@ -918,4 +918,4 @@ protected virtual void OnDestroyed() { } } -} +} \ No newline at end of file diff --git a/Exiled.API/Features/Core/GameEntity.cs b/Exiled.API/Features/Core/GameEntity.cs index 41be51dcd7..aa84602d36 100644 --- a/Exiled.API/Features/Core/GameEntity.cs +++ b/Exiled.API/Features/Core/GameEntity.cs @@ -163,7 +163,6 @@ public T AddComponent(string name = "") public EActor AddComponent(Type type, string name = "") { EActor component = EObject.CreateDefaultSubobject(type, GameObject).Cast(); - component.Base = GameObject; if (!component) return null; diff --git a/Exiled.API/Features/Core/Generic/EBehaviour.cs b/Exiled.API/Features/Core/Generic/EBehaviour.cs index dd5553a8a4..a2b3fd611e 100644 --- a/Exiled.API/Features/Core/Generic/EBehaviour.cs +++ b/Exiled.API/Features/Core/Generic/EBehaviour.cs @@ -25,6 +25,13 @@ namespace Exiled.API.Features.Core.Generic public abstract class EBehaviour : EActor where T : GameEntity { + /// + /// Initializes a new instance of the class. + /// + protected EBehaviour() + { + } + /// /// Gets or sets the owner of the . /// @@ -78,6 +85,12 @@ protected override void PostInitialize() } } + /// + protected override void OnBeginPlay() + { + base.OnBeginPlay(); + } + /// protected override void Tick() { diff --git a/Exiled.CustomModules/API/Features/CustomModule.cs b/Exiled.CustomModules/API/Features/CustomModule.cs index b0a936bde8..1946cf8647 100644 --- a/Exiled.CustomModules/API/Features/CustomModule.cs +++ b/Exiled.CustomModules/API/Features/CustomModule.cs @@ -318,9 +318,7 @@ public static void LoadAll() /// Determines whether the loaded modules should be enabled after loading. public static void Load(Assembly assembly = null, bool shouldBeEnabled = false) { - Log.InfoWithContext($"Using defined assembly? {assembly is null}"); assembly ??= Assembly.GetCallingAssembly(); - Log.InfoWithContext($"{assembly.GetName().Name}"); UUModuleType FindClosestModuleType(Type t, IEnumerable source) { @@ -331,7 +329,6 @@ UUModuleType FindClosestModuleType(Type t, IEnumerable source) Type runtime_ModuleType = assembly.GetTypes().FirstOrDefault(t => !t.IsAbstract && typeof(UUModuleType).IsAssignableFrom(t)) ?? typeof(UUModuleType); IEnumerable moduleTypeValuesInfo = runtime_ModuleType.GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.GetValue(null) is UUModuleType); - Log.InfoWithContext($"DB1"); foreach (Type type in assembly.GetTypes()) { diff --git a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs index 5f640b87d2..0f63d1b34b 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs @@ -355,9 +355,9 @@ protected override void PostInitialize() protected override void OnBeginPlay() { base.OnBeginPlay(); - if (!Owner) { + Log.WarnWithContext("Owner is null"); Destroy(); return; } @@ -369,6 +369,8 @@ protected override void OnBeginPlay() Owner.ChangeAppearance(FakeAppearance, false); PermanentEffects?.ForEach(x => Owner.SyncEffect(x)); + + SubscribeEvents(); } /// @@ -450,9 +452,6 @@ protected override void SubscribeEvents() { base.SubscribeEvents(); - EscapingEventDispatcher.Bind(this, OnEscaping); - EscapedEventDispatcher.Bind(this, OnEscaped); - Exiled.Events.Handlers.Player.ChangingItem += ChangingItemBehaviour; Exiled.Events.Handlers.Player.Destroying += DestroyOnLeave; Exiled.Events.Handlers.Player.ChangingRole += DestroyOnChangingRole; @@ -474,6 +473,8 @@ protected override void SubscribeEvents() Exiled.Events.Handlers.Player.Handcuffing += HandcuffingBehavior; Exiled.Events.Handlers.Map.PlacingBlood += PlacingBloodBehavior; Exiled.Events.Handlers.Player.ChangingNickname += OnInternalChangingNickname; + EscapingEventDispatcher.Bind(this, OnEscaping); + EscapedEventDispatcher.Bind(this, OnEscaped); } /// @@ -759,21 +760,8 @@ protected virtual void PlacingBloodBehavior(PlacingBloodEventArgs ev) /// protected virtual void DroppingItemBehavior(DroppingItemEventArgs ev) { - if (ev.Item is null) - { - Log.Error("Item is null"); - } - - Log.InfoWithContext($"{ev.Player} is trying to drop {ev.Item.Type}"); - - Log.WarnWithContext(Settings.CanDropItems); if (!Check(ev.Player) || Settings.CanDropItems) - { - Log.InfoWithContext($"{ev.Player} is not {CustomRole.Name} or can drop items as {CustomRole.Name}"); return; - } - - Log.InfoWithContext($"{ev.Player} cannot drop items"); ev.IsAllowed = false; } From 3a93db186d273fab30f3b7df1c000fc5e827a5c7 Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Wed, 14 Aug 2024 21:59:50 +0200 Subject: [PATCH 7/7] Removed debug (#2770) * Fixed Pawn.cs being null if try to use it by Player::Get().Cast(). Adding a method for load a constructor without any param or constructor. Removing abstract from RoleBehaviour.cs for allow the creating of an instance. Added custom role example under Exiled.Example for testing purpose. * Fixed custom roles. * Added test role (testing purposes) * Fixed customroles. Release 9.0.0-beta.1 * removed debug. --- .../API/Features/CustomRoles/RoleBehaviour.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs index 0f63d1b34b..ead4744f5d 100644 --- a/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs +++ b/Exiled.CustomModules/API/Features/CustomRoles/RoleBehaviour.cs @@ -654,15 +654,8 @@ protected virtual void PickingUpItemBehavior(SearchingPickupEventArgs ev) Log.Error("Pickup is null"); } - Log.InfoWithContext($"{ev.Player} is trying to pick up {ev.Pickup.Type}"); - if (!Check(ev.Player) || Settings.CanPickupItems) - { - Log.InfoWithContext($"{ev.Player} is not {CustomRole.Name} or can pick up items as {CustomRole.Name}"); return; - } - - Log.InfoWithContext($"{ev.Player} cannot pick up items"); ev.IsAllowed = false; }