From 79d784089eb7133cad71704cb9a9fdb1503a61ee Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Sun, 28 Jul 2024 00:42:28 +0200 Subject: [PATCH 1/4] 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. --- 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 ece890a277bdb37c74fc27150b9bcd130d3c8902 Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Tue, 30 Jul 2024 00:45:41 +0200 Subject: [PATCH 2/4] Fixed custom roles. --- 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 | 32 +------------------ Exiled.Loader/Loader.cs | 15 ++++++--- 8 files changed, 38 insertions(+), 85 deletions(-) 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..5a6d244952 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,7 +235,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 +259,8 @@ protected override void PostInitialize() { base.PostInitialize(); - Log.InfoWithContext("Pre-Adjust"); - AdjustAdditivePipe(); - Log.InfoWithContext("Post-Adjust"); - wasNoClipPermitted = Owner.IsNoclipPermitted; isHuman = !CustomRole.IsScp; @@ -290,8 +270,6 @@ protected override void PostInitialize() if (Role is RoleTypeId.None) { - Log.InfoWithContext("Role is none"); - Destroy(); return; } @@ -299,14 +277,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 +358,6 @@ protected override void OnBeginPlay() if (!Owner) { - Log.InfoWithContext("Owner is null RB"); - Destroy(); return; } @@ -407,8 +379,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.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 5b22e39d4009afcbc8f481980d760b658e979427 Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Tue, 30 Jul 2024 01:25:59 +0200 Subject: [PATCH 3/4] Added test role (testing purposes) --- Exiled.Example/TestRole/CustomRoleType.cs | 22 ++++++ Exiled.Example/TestRole/Scp999Behaviour.cs | 21 ++++++ Exiled.Example/TestRole/Scp999Config.cs | 21 ++++++ Exiled.Example/TestRole/Scp999Role.cs | 79 ++++++++++++++++++++++ 4 files changed, 143 insertions(+) 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.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 From 412ef8cb301994a0997e77d1fffc63f66c3063d9 Mon Sep 17 00:00:00 2001 From: Monald <63928518+Monaldcry7788@users.noreply.github.com> Date: Wed, 14 Aug 2024 21:50:49 +0200 Subject: [PATCH 4/4] Fixed customroles. Release 9.0.0-beta.1 --- EXILED.props | 2 +- Exiled.API/Features/Core/EActor.cs | 1 - Exiled.API/Features/Core/EObject.cs | 3 +-- 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(+), 25 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 16f7319258..a0af7ac800 100644 --- a/Exiled.API/Features/Core/EObject.cs +++ b/Exiled.API/Features/Core/EObject.cs @@ -918,5 +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; }