Skip to content
This repository has been archived by the owner on Jan 19, 2025. It is now read-only.

Exiled 9.0.0-beta.1 #2771

Merged
merged 7 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion EXILED.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<PropertyGroup>
<!-- This is the global version and is used for all projects that don't have a version -->
<Version Condition="$(Version) == ''">9.0.0-alpha.19</Version>
<Version Condition="$(Version) == ''">9.0.0-beta.1</Version>
<!-- Enables public beta warning via the PUBLIC_BETA constant -->
<PublicBeta>false</PublicBeta>

Expand Down
19 changes: 12 additions & 7 deletions Exiled.API/Features/Core/EActor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
}

/// <summary>
Expand Down Expand Up @@ -454,14 +451,24 @@ public bool TryGetComponent(Type type, out EActor component)

/// <inheritdoc/>
public bool HasComponent<T>(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());

/// <inheritdoc/>
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());

/// <summary>
/// Called when the <see cref="EActor"/> is initialized.
/// </summary>
public void ComponentInitialize()
{
PostInitialize();
Timing.CallDelayed(fixedTickRate, OnBeginPlay);
Timing.CallDelayed(fixedTickRate * 2, () => serverTick = Timing.RunCoroutine(ServerTick()));
}

/// <summary>
/// Fired after the <see cref="EActor"/> instance is created.
/// </summary>
Expand All @@ -474,7 +481,6 @@ protected virtual void PostInitialize()
/// </summary>
protected virtual void OnBeginPlay()
{
SubscribeEvents();
}

/// <summary>
Expand All @@ -485,7 +491,6 @@ protected virtual void Tick()
if (DestroyNextTick)
{
Destroy();
return;
}
}

Expand Down
73 changes: 69 additions & 4 deletions Exiled.API/Features/Core/EObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ protected EObject(GameObject gameObject = null)
/// <summary>
/// Gets or sets the name of the <see cref="EObject"/> instance.
/// </summary>
public string Name { get; set; }
public string Name { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the tag of the <see cref="EObject"/> instance.
/// </summary>
public string Tag { get; set; }
public string Tag { get; set; } = string.Empty;

/// <summary>
/// Gets or sets a value indicating whether the <see cref="EObject"/> values can be edited.
Expand Down Expand Up @@ -357,7 +357,13 @@ 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 = 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.Base = parameters[0] as GameObject;
@object.Cast<EActor>().ComponentInitialize();
}

// Do not use implicit bool conversion as @object may be null
if (@object != null)
Expand All @@ -371,6 +377,65 @@ public static EObject CreateDefaultSubobject(Type type, params object[] paramete
throw new NullReferenceException($"Couldn't create an EObject instance of type {type.Name}.");
}

/// <summary>
/// Initializes an instance of the specified generic type <typeparamref name="T"/>.
/// If no constructors are found, the base type is initialized.
/// </summary>
/// <typeparam name="T">The type that inherits from <see cref="EObject"/>.</typeparam>
/// <returns>An instance of the specified type <typeparamref name="T"/>.</returns>
public static T InitializeBaseType<T>()
where T : EObject
{
return InitializeBaseType(typeof(T)).Cast<T>();
}

/// <summary>
/// Initializes an instance of the specified type.
/// If no constructors are found, the base type is initialized.
/// </summary>
/// <param name="type">The type to be initialized.</param>
/// <param name="parameters">Constructor parameters for the type.</param>
/// <returns>An instance of the specified <see cref="EObject"/> type.</returns>
/// <exception cref="InvalidOperationException">
/// Thrown if the provided <paramref name="type"/> is not a subclass of <see cref="EObject"/>.
/// </exception>
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;
}

/// <summary>
/// Creates a new instance of the <see cref="EObject"/> class.
/// </summary>
Expand Down Expand Up @@ -853,4 +918,4 @@ protected virtual void OnDestroyed()
{
}
}
}
}
8 changes: 7 additions & 1 deletion Exiled.API/Features/Core/Generic/EBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public abstract class EBehaviour<T> : EActor
/// Initializes a new instance of the <see cref="EBehaviour{T}"/> class.
/// </summary>
protected EBehaviour()
: base()
{
}

Expand Down Expand Up @@ -78,13 +77,20 @@ protected override void PostInitialize()
base.PostInitialize();

FindOwner();

if (!Owner && DisposeOnNullOwner)
{
Destroy();
return;
}
}

/// <inheritdoc />
protected override void OnBeginPlay()
{
base.OnBeginPlay();
}

/// <inheritdoc/>
protected override void Tick()
{
Expand Down
4 changes: 4 additions & 0 deletions Exiled.API/Features/Core/Generic/UniqueUnmanagedEnumClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// A class which allows <see langword="unmanaged"/> data implicit conversions and ensures unique values.
Expand Down Expand Up @@ -60,16 +61,19 @@ public UniqueUnmanagedEnumClass()
/// <summary>
/// Gets all <typeparamref name="TObject"/> object instances.
/// </summary>
[YamlIgnore]
public static IEnumerable<TObject> Values => values.Values;

/// <summary>
/// Gets the value of the enum item.
/// </summary>
[YamlIgnore]
public TSource Value { get; }

/// <summary>
/// Gets the name determined from reflection.
/// </summary>
[YamlMember(Alias = "name")]
public string Name
{
get
Expand Down
3 changes: 3 additions & 0 deletions Exiled.API/Features/Core/Generic/UnmanagedEnumClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// A class which allows <see langword="unmanaged"/> data implicit conversions.
Expand Down Expand Up @@ -51,11 +52,13 @@ protected UnmanagedEnumClass(TSource value)
/// <summary>
/// Gets the value of the enum item.
/// </summary>
[YamlIgnore]
public TSource Value { get; }

/// <summary>
/// Gets the name determined from reflection.
/// </summary>
[YamlMember(Alias = "name")]
public string Name
{
get
Expand Down
16 changes: 11 additions & 5 deletions Exiled.API/Features/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ public class Player : GameEntity
public const string INFO_CATEGORY = "Player_Info";

#pragma warning disable SA1401
/// <summary>
/// The default role behaviour class.
/// </summary>
public static Type DEFAULT_ROLE_BEHAVIOUR = null;

/// <summary>
/// The default player class.
/// </summary>
Expand Down Expand Up @@ -664,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.
/// </para>
/// <para>
/// Roles and RoleTypeIds can be compared directly. <c>Player.Role == RoleTypeId.Scp079</c> is valid and will return <see langword="true"/> if the player is SCP-079. To set the player's role, see <see cref="Role.Set(RoleTypeId, SpawnReason, RoleSpawnFlags)"/>.
/// Roles and RoleTypeIds can be compared directly. <c>Player.Role == RoleTypeId.Scp079</c> is valid and will return <see langword="true"/> if the player is SCP-079. To set the player's role, see <see cref="Role.Set(RoleTypeId, RoleChangeReason, RoleSpawnFlags)"/>.
/// </para>
/// </summary>
/// <seealso cref="Role.Set(RoleTypeId, SpawnReason, RoleSpawnFlags)"/>
/// <seealso cref="Role.Set(RoleTypeId, RoleChangeReason, RoleSpawnFlags)"/>
[EProperty(readOnly: true, category: ROLES_CATEGORY)]
public Role Role
{
Expand Down Expand Up @@ -3988,8 +3993,9 @@ public void PlayGunSound(Vector3 position, ItemType itemType, byte volume, byte
/// <param name="unitId">The UnitNameId to use for the player's new role, if the player's new role uses unit names. (is NTF).</param>
public void ChangeAppearance(RoleTypeId type, IEnumerable<Player> 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();
Expand All @@ -4001,6 +4007,7 @@ public void ChangeAppearance(RoleTypeId type, IEnumerable<Player> playersToAffec
{
if (Role.Base is not PHumanRole)
isRisky = true;

writer.WriteByte(unitId);
}

Expand All @@ -4011,8 +4018,7 @@ public void ChangeAppearance(RoleTypeId type, IEnumerable<Player> 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);
}
Expand Down
8 changes: 4 additions & 4 deletions Exiled.API/Features/Roles/Role.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ public static RoleTypeId Random(bool includeNonPlayableRoles = false, IEnumerabl
/// Sets the player's <see cref="RoleTypeId"/>.
/// </summary>
/// <param name="newRole">The new <see cref="RoleTypeId"/> to be set.</param>
/// <param name="reason">The <see cref="Enums.SpawnReason"/> defining why the player's role was changed.</param>
public virtual void Set(RoleTypeId newRole, SpawnReason reason = null) => Set(newRole, reason ?? Enums.SpawnReason.ForceClass, RoleSpawnFlags.All);
/// <param name="reason">The <see cref="RoleChangeReason"/> defining why the player's role was changed.</param>
public virtual void Set(RoleTypeId newRole, RoleChangeReason reason = RoleChangeReason.RemoteAdmin) => Set(newRole, reason, RoleSpawnFlags.All);

/// <summary>S
/// Sets the player's <see cref="RoleTypeId"/>.
Expand All @@ -275,9 +275,9 @@ public static RoleTypeId Random(bool includeNonPlayableRoles = false, IEnumerabl
/// Sets the player's <see cref="RoleTypeId"/>.
/// </summary>
/// <param name="newRole">The new <see cref="RoleTypeId"/> to be set.</param>
/// <param name="reason">The <see cref="Enums.SpawnReason"/> defining why the player's role was changed.</param>
/// <param name="reason">The <see cref="RoleChangeReason"/> defining why the player's role was changed.</param>
/// <param name="spawnFlags">The <see cref="RoleSpawnFlags"/> defining player spawn logic.</param>
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);

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Exiled.CustomModules/API/Commands/CustomRoles/Give.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ public bool Execute(ArraySegment<string> 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<Pawn>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// Represents a marker interface for custom ability that can be selected.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// Represents the base class for player-specific ability behaviors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// Represents the base class for player-specific ability behaviors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading