From 046d11141b638ca859d19dfd78ebee3db1c3cd60 Mon Sep 17 00:00:00 2001 From: Tim Potze Date: Tue, 12 May 2026 23:17:03 +0200 Subject: [PATCH 1/4] implement SafeComponentHandle --- src/SampSharp.OpenMp.Core/IStartupContext.cs | 5 + .../SampSharpInitParams.cs | 12 +- src/SampSharp.OpenMp.Core/StartupContext.cs | 36 +++- .../Hosting/EcsHost.cs | 14 +- .../Hosting/EcsHostBuilder.cs | 2 +- .../Hosting/ISafeComponentHandle.cs | 7 + .../Hosting/ISafeComponentHandleProvider.cs | 16 ++ .../Hosting/SafeComponentHandle.cs | 65 ++++++ .../Hosting/SafeComponentHandleProvider.cs | 52 +++++ .../SafeEventHandlerRegistration.cs | 4 +- ...ntHandlerSampSharpEnvironmentExtensions.cs | 6 +- .../Hosting/SampSharpEnvironment.cs | 3 +- .../SAMP/Services/CustomModelsService.cs | 14 +- .../SAMP/Services/NpcService.cs | 57 +++--- .../SAMP/Services/OmpEntityProvider.cs | 79 ++++--- .../SAMP/Services/ServerService.cs | 148 +++++++------- .../SAMP/Services/WorldService.cs | 105 +++++----- .../SAMP/Systems/ClassSystem.cs | 8 +- .../SampSharp.OpenMp.Entities.csproj | 1 + .../Generators/EntryPointSourceGenerator.cs | 18 -- src/sampsharp-component/platform.hpp | 12 ++ src/sampsharp-component/proxy-api.hpp | 193 +++++++++--------- .../sampsharp-component.cpp | 86 +++++--- .../sampsharp-component.hpp | 71 ++++--- 24 files changed, 621 insertions(+), 393 deletions(-) create mode 100644 src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandle.cs create mode 100644 src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandleProvider.cs create mode 100644 src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandle.cs create mode 100644 src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandleProvider.cs rename src/SampSharp.OpenMp.Entities/{Systems => Hosting}/SafeEventHandlerRegistration.cs (87%) create mode 100644 src/sampsharp-component/platform.hpp diff --git a/src/SampSharp.OpenMp.Core/IStartupContext.cs b/src/SampSharp.OpenMp.Core/IStartupContext.cs index cedcc93b..a5f4e59c 100644 --- a/src/SampSharp.OpenMp.Core/IStartupContext.cs +++ b/src/SampSharp.OpenMp.Core/IStartupContext.cs @@ -41,4 +41,9 @@ public interface IStartupContext /// Occurs when the application has been initialized. /// event EventHandler? Initialized; + + /// + /// Occurs when an open.mp component is being freed. The component which is being freed is passed as an argument. + /// + event EventHandler? ComponentFreed; } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Core/SampSharpInitParams.cs b/src/SampSharp.OpenMp.Core/SampSharpInitParams.cs index fc147749..4cbd988d 100644 --- a/src/SampSharp.OpenMp.Core/SampSharpInitParams.cs +++ b/src/SampSharp.OpenMp.Core/SampSharpInitParams.cs @@ -31,4 +31,14 @@ public readonly ref struct SampSharpInitParams /// Gets information about the SampSharp open.mp component. /// public SampSharpInfo Info => _info.Value; -} \ No newline at end of file + + /// + /// Gets a pointer to an unmanaged function that configures a cleanup callback to be invoked. + /// + public readonly unsafe delegate* unmanaged[Cdecl] SetOnCleanup; + + /// + /// Gets a pointer to an unmanaged function that configures a callback to be invoked when a component is being freed. + /// + public readonly unsafe delegate* unmanaged[Cdecl] SetOnFreeComponent; +} diff --git a/src/SampSharp.OpenMp.Core/StartupContext.cs b/src/SampSharp.OpenMp.Core/StartupContext.cs index a4bc5cb4..a93b227f 100644 --- a/src/SampSharp.OpenMp.Core/StartupContext.cs +++ b/src/SampSharp.OpenMp.Core/StartupContext.cs @@ -1,4 +1,5 @@ using SampSharp.OpenMp.Core.Api; +using System.Runtime.InteropServices; namespace SampSharp.OpenMp.Core; @@ -7,6 +8,12 @@ namespace SampSharp.OpenMp.Core; /// public sealed class StartupContext : IStartupContext { + // Delegates must be kept in memory to prevent GC + // ReSharper disable PrivateFieldCanBeConvertedToLocalVariable + private readonly Action _cleanup; + private readonly OnFreeComponent _freeComponent; + // ReSharper restore PrivateFieldCanBeConvertedToLocalVariable + /// /// The API version of the native open.mp component which supports this version of the managed API. This is used to check for version mismatches between the managed and native /// components. @@ -32,6 +39,19 @@ public StartupContext(SampSharpInitParams init) Core.LogLine(LogLevel.Error, ex.ToString()); }; SampSharpExceptionHandler.SetExceptionHandler(_unhandledExceptionHandler); + + // Keep delegates in memory to prevent GC + _cleanup = EntryOnCleanup; + _freeComponent = EntryOnFreeComponent; + + var cleanupPtr = Marshal.GetFunctionPointerForDelegate(_cleanup); + var freeComponentPtr = Marshal.GetFunctionPointerForDelegate(_freeComponent); + + unsafe + { + init.SetOnCleanup(cleanupPtr); + init.SetOnFreeComponent(freeComponentPtr); + } } /// @@ -63,6 +83,9 @@ public ExceptionHandler UnhandledExceptionHandler /// public event EventHandler? Initialized; + /// + public event EventHandler? ComponentFreed; + /// /// Internal method. Do not invoke manually. /// @@ -74,14 +97,16 @@ public void InitializeUsing(IStartup configurator) Initialized?.Invoke(this, EventArgs.Empty); } - /// - /// Internal method. Do not invoke manually. - /// - public void InvokeCleanup() + private void EntryOnCleanup() { Cleanup?.Invoke(this, EventArgs.Empty); } + private void EntryOnFreeComponent(IComponent component) + { + ComponentFreed?.Invoke(this, component); + } + /// /// Internal method. Do not invoke manually. /// @@ -116,4 +141,7 @@ private static void VersionCheck(SampSharpInitParams init) Environment.FailFast(message); } } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void OnFreeComponent(IComponent component); } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/Hosting/EcsHost.cs b/src/SampSharp.OpenMp.Entities/Hosting/EcsHost.cs index 20efd222..eac1840a 100644 --- a/src/SampSharp.OpenMp.Entities/Hosting/EcsHost.cs +++ b/src/SampSharp.OpenMp.Entities/Hosting/EcsHost.cs @@ -7,32 +7,40 @@ namespace SampSharp.Entities; [Extension(0x57e43771d28c5e7e)] internal sealed partial class EcsHost(IServiceProvider serviceProvider, UnhandledExceptionHandler? exceptionHandler) : Extension { + private IStartupContext? _context; private IServiceProvider? _serviceProvider = serviceProvider; public IServiceProvider ServiceProvider => _serviceProvider ?? throw new InvalidOperationException(); public void Start(IStartupContext context) { + _context = context; + context.UseSynchronizationContext(); context.UnhandledExceptionHandler = UnhandledExceptionHandler; + context.Cleanup += ContextOnCleanup; + LoadSystems(); // Fire initial event OnGameModeInit(); } - protected override void Cleanup() + private void ContextOnCleanup(object? sender, EventArgs e) { + _context?.Cleanup -= ContextOnCleanup; + _context = null; + OnGameModeExit(); if (_serviceProvider is IDisposable disposable) { - // TODO: This cleanup is called so late - we can't unsubscribe event handlers anymore, but the disposables in registered systems will try to unsubscribe them. This may cause a System.ExecutionEngineException on shutdown. disposable.Dispose(); - _serviceProvider = null; } + + _serviceProvider = null; } private void UnhandledExceptionHandler(string context, Exception exception) diff --git a/src/SampSharp.OpenMp.Entities/Hosting/EcsHostBuilder.cs b/src/SampSharp.OpenMp.Entities/Hosting/EcsHostBuilder.cs index f389f2f3..b80c55e9 100644 --- a/src/SampSharp.OpenMp.Entities/Hosting/EcsHostBuilder.cs +++ b/src/SampSharp.OpenMp.Entities/Hosting/EcsHostBuilder.cs @@ -74,7 +74,7 @@ internal EcsHost Build(IStartupContext context) private IServiceProvider BuildServiceProvider(IStartupContext context) { - var environment = new SampSharpEnvironment(context.Configurator.GetType().Assembly, context.Core, context.ComponentList); + var environment = new SampSharpEnvironment(context.Configurator.GetType().Assembly, context.Core, context.ComponentList, new SafeComponentHandleProvider(context)); var services = new ServiceCollection(); diff --git a/src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandle.cs b/src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandle.cs new file mode 100644 index 00000000..fa2eac2f --- /dev/null +++ b/src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandle.cs @@ -0,0 +1,7 @@ +namespace SampSharp.Entities; + +internal interface ISafeComponentHandle +{ + nint Handle { get; } + void Free(); +} \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandleProvider.cs b/src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandleProvider.cs new file mode 100644 index 00000000..fccee875 --- /dev/null +++ b/src/SampSharp.OpenMp.Entities/Hosting/ISafeComponentHandleProvider.cs @@ -0,0 +1,16 @@ +using SampSharp.OpenMp.Core.Api; + +namespace SampSharp.Entities; + +/// +/// Provides handles to open.mp components which are automatically cleared when the component is freed. This allows for safe access to components without risking access to freed components, which can lead to crashes or undefined behavior. +/// +public interface ISafeComponentHandleProvider +{ + /// + /// Retrieves a handle to a component of the specified type. + /// + /// The type of the component to retrieve. + /// A representing a handle to the requested component. The handle will be cleared when the open.mp component is freed. + SafeComponentHandle Get() where T : unmanaged, IComponent.IManagedInterface; +} \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandle.cs b/src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandle.cs new file mode 100644 index 00000000..43ead93f --- /dev/null +++ b/src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandle.cs @@ -0,0 +1,65 @@ +using System.Diagnostics.CodeAnalysis; +using SampSharp.OpenMp.Core.Api; + +namespace SampSharp.Entities; + +/// +/// Provides a safe pointer to an open.mp component of type . +/// +/// The unmanaged open.mp component type. +public sealed class SafeComponentHandle : ISafeComponentHandle where T : unmanaged, IComponent.IManagedInterface +{ + private nint _componentHandle; + private T _value; + + internal SafeComponentHandle(T value, nint componentHandle) + { + _componentHandle = componentHandle; + Value = value; + } + + /// + /// Gets the current value stored in the container. + /// + public T Value + { + get + { + if (_value.HasValue) + { + return _value; + } + + ThrowDisposed(); + return default; + } + private set => _value = value; + } + + /// + /// Gets a value indicating whether the current instance contains a valid value. + /// + public bool HasValue => _value.HasValue; + + nint ISafeComponentHandle.Handle => _componentHandle; + + void ISafeComponentHandle.Free() + { + Value = default; + _componentHandle = 0; + } + + [DoesNotReturn] + private static void ThrowDisposed() + { + throw new ObjectDisposedException(nameof(T)); + } + + /// + /// Defines an implicit conversion from to , allowing for seamless access to the underlying component value while ensuring safety against freed components. + /// + public static implicit operator T(SafeComponentHandle safeHandle) + { + return safeHandle?.Value ?? default; + } +} \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandleProvider.cs b/src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandleProvider.cs new file mode 100644 index 00000000..3efa5cf7 --- /dev/null +++ b/src/SampSharp.OpenMp.Entities/Hosting/SafeComponentHandleProvider.cs @@ -0,0 +1,52 @@ +using SampSharp.OpenMp.Core; +using SampSharp.OpenMp.Core.Api; + +namespace SampSharp.Entities; + +internal class SafeComponentHandleProvider : ISafeComponentHandleProvider +{ + private readonly IStartupContext _startupContext; + private readonly Dictionary _safeHandles = []; + + public SafeComponentHandleProvider(IStartupContext startupContext) + { + _startupContext = startupContext; + + startupContext.ComponentFreed += OnComponentFreed; + startupContext.Cleanup += OnCleanup; + } + + public SafeComponentHandle Get() where T : unmanaged, IComponent.IManagedInterface + { + var uid = T.ComponentId; + + if (_safeHandles.TryGetValue(uid, out var existing)) + { + return (SafeComponentHandle)existing; + } + + unsafe + { + var component = _startupContext.ComponentList.QueryComponent(uid); + + var typedHandle = T.FromComponentHandle(component.Handle); + var typedComponent = *(T*)&typedHandle; + + var safeHandle = new SafeComponentHandle(typedComponent, component.Handle); + _safeHandles[uid] = safeHandle; + return safeHandle; + } + } + + private void OnCleanup(object? sender, EventArgs e) + { + _startupContext.ComponentFreed -= OnComponentFreed; + _startupContext.Cleanup -= OnCleanup; + } + + private void OnComponentFreed(object? sender, IComponent e) + { + var handle = e.Handle; + _safeHandles.Values.FirstOrDefault(x => x.Handle == handle)?.Free(); + } +} \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/Systems/SafeEventHandlerRegistration.cs b/src/SampSharp.OpenMp.Entities/Hosting/SafeEventHandlerRegistration.cs similarity index 87% rename from src/SampSharp.OpenMp.Entities/Systems/SafeEventHandlerRegistration.cs rename to src/SampSharp.OpenMp.Entities/Hosting/SafeEventHandlerRegistration.cs index 4f19558a..c4d5dd44 100644 --- a/src/SampSharp.OpenMp.Entities/Systems/SafeEventHandlerRegistration.cs +++ b/src/SampSharp.OpenMp.Entities/Hosting/SafeEventHandlerRegistration.cs @@ -2,7 +2,7 @@ namespace SampSharp.Entities; -internal sealed class SafeEventHandlerRegistration(SampSharpEnvironment environment, TEventHandler handler, Func> dispatcherProvider) : IDisposable +internal sealed class SafeEventHandlerRegistration(SafeComponentHandle component, TEventHandler handler, Func> dispatcherProvider) : IDisposable where TComponent : unmanaged, IComponent.IManagedInterface where TEventHandler : class, IEventHandler { @@ -17,8 +17,6 @@ public void Dispose() _disposed = true; - var component = environment.Components.QueryComponent(); - if (!component.HasValue) { TEventHandler.Marshaller.Marshal(handler).Free(); diff --git a/src/SampSharp.OpenMp.Entities/Hosting/SafeEventHandlerSampSharpEnvironmentExtensions.cs b/src/SampSharp.OpenMp.Entities/Hosting/SafeEventHandlerSampSharpEnvironmentExtensions.cs index ece4ed7b..514b995e 100644 --- a/src/SampSharp.OpenMp.Entities/Hosting/SafeEventHandlerSampSharpEnvironmentExtensions.cs +++ b/src/SampSharp.OpenMp.Entities/Hosting/SafeEventHandlerSampSharpEnvironmentExtensions.cs @@ -25,7 +25,7 @@ public static class SafeEventHandlerSampSharpEnvironmentExtensions ArgumentNullException.ThrowIfNull(dispatcherProvider); ArgumentNullException.ThrowIfNull(handler); - var component = environment.Components.QueryComponent(); + var component = environment.SafeComponentHandleProvider.Get(); if (!component.HasValue) { @@ -44,7 +44,7 @@ public static class SafeEventHandlerSampSharpEnvironmentExtensions return null; } - return new SafeEventHandlerRegistration(environment, handler, dispatcherProvider); + return new SafeEventHandlerRegistration(component, handler, dispatcherProvider); } /// @@ -61,7 +61,7 @@ public IDisposable AddEventHandler(Func { - var registration = TryAddEventHandler(environment, dispatcherProvider, handler, priority); + var registration = environment.TryAddEventHandler(dispatcherProvider, handler, priority); if (registration is null) { throw new InvalidOperationException("Failed to add event handler."); diff --git a/src/SampSharp.OpenMp.Entities/Hosting/SampSharpEnvironment.cs b/src/SampSharp.OpenMp.Entities/Hosting/SampSharpEnvironment.cs index c1a8469d..59a6ce55 100644 --- a/src/SampSharp.OpenMp.Entities/Hosting/SampSharpEnvironment.cs +++ b/src/SampSharp.OpenMp.Entities/Hosting/SampSharpEnvironment.cs @@ -13,4 +13,5 @@ namespace SampSharp.Entities; /// The assembly which was configured to launch in open.mp. Used to discover game mode classes and other application types. /// The interface for the open.mp server. Provides access to core server functionality and extensions. /// The of open.mp. Manages all game components (players, vehicles, objects, etc.) accessible on the server. -public record SampSharpEnvironment(Assembly EntryAssembly, ICore Core, IComponentList Components); \ No newline at end of file +/// A provider of safe handles of open.mp components. +public record SampSharpEnvironment(Assembly EntryAssembly, ICore Core, IComponentList Components, ISafeComponentHandleProvider SafeComponentHandleProvider); \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Services/CustomModelsService.cs b/src/SampSharp.OpenMp.Entities/SAMP/Services/CustomModelsService.cs index 2e722ddc..088576a4 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Services/CustomModelsService.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Services/CustomModelsService.cs @@ -4,34 +4,36 @@ namespace SampSharp.Entities.SAMP; internal sealed class CustomModelsService(SampSharpEnvironment environment) : ICustomModelsService { - private readonly ICustomModelsComponent _customModels = environment.Components.QueryComponent(); + private readonly SafeComponentHandle _customModels = environment.SafeComponentHandleProvider.Get(); + + private ICustomModelsComponent CustomModels => _customModels; public bool AddCustomModel(ModelType type, int id, int baseId, string dffName, string txdName, int virtualWorld = -1, byte timeOn = 0, byte timeOff = 0) { ArgumentNullException.ThrowIfNull(dffName); ArgumentNullException.ThrowIfNull(txdName); - return _customModels.AddCustomModel(type, id, baseId, dffName, txdName, virtualWorld, timeOn, timeOff); + return CustomModels.AddCustomModel(type, id, baseId, dffName, txdName, virtualWorld, timeOn, timeOff); } public uint? GetBaseModel(uint customModelId) { uint baseId = 0; var custom = customModelId; - return _customModels.GetBaseModel(ref baseId, ref custom) ? baseId : null; + return CustomModels.GetBaseModel(ref baseId, ref custom) ? baseId : null; } public string? GetModelNameFromChecksum(uint checksum) { - return _customModels.GetModelNameFromChecksum(checksum); + return CustomModels.GetModelNameFromChecksum(checksum); } public bool IsValidCustomModel(int modelId) { - return _customModels.IsValidCustomModel(modelId); + return CustomModels.IsValidCustomModel(modelId); } public bool GetCustomModelPath(int modelId, out string? dffPath, out string? txdPath) { - return _customModels.GetCustomModelPath(modelId, out dffPath, out txdPath); + return CustomModels.GetCustomModelPath(modelId, out dffPath, out txdPath); } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Services/NpcService.cs b/src/SampSharp.OpenMp.Entities/SAMP/Services/NpcService.cs index 6abab445..9612b474 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Services/NpcService.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Services/NpcService.cs @@ -4,133 +4,130 @@ namespace SampSharp.Entities.SAMP; -internal sealed class NpcService : INpcService +internal sealed class NpcService(SampSharpEnvironment environment) : INpcService { - private readonly INPCComponent _npcs; + private readonly SafeComponentHandle _npcs = environment.SafeComponentHandleProvider.Get(); - public NpcService(SampSharpEnvironment environment) - { - _npcs = environment.Components.QueryComponent(); - } + private INPCComponent Npcs => _npcs; public int CreatePath() { - return _npcs.CreatePath(); + return Npcs.CreatePath(); } public bool DestroyPath(int pathId) { - return _npcs.DestroyPath(pathId); + return Npcs.DestroyPath(pathId); } public void DestroyAllPaths() { - _npcs.DestroyAllPaths(); + Npcs.DestroyAllPaths(); } public Size GetPathCount() { - return _npcs.GetPathCount(); + return Npcs.GetPathCount(); } public bool AddPointToPath(int pathId, Vector3 position, float stopRange) { - return _npcs.AddPointToPath(pathId, position, stopRange); + return Npcs.AddPointToPath(pathId, position, stopRange); } public bool RemovePointFromPath(int pathId, Size pointIndex) { - return _npcs.RemovePointFromPath(pathId, pointIndex); + return Npcs.RemovePointFromPath(pathId, pointIndex); } public bool ClearPath(int pathId) { - return _npcs.ClearPath(pathId); + return Npcs.ClearPath(pathId); } public Size GetPathPointCount(int pathId) { - return _npcs.GetPathPointCount(pathId); + return Npcs.GetPathPointCount(pathId); } public bool GetPathPoint(int pathId, Size pointIndex, out Vector3 position, out float stopRange) { - return _npcs.GetPathPoint(pathId, pointIndex, out position, out stopRange); + return Npcs.GetPathPoint(pathId, pointIndex, out position, out stopRange); } public bool HasPathPointInRange(int pathId, Vector3 position, float radius) { - return _npcs.HasPathPointInRange(pathId, position, radius); + return Npcs.HasPathPointInRange(pathId, position, radius); } public bool IsValidPath(int pathId) { - return _npcs.IsValidPath(pathId); + return Npcs.IsValidPath(pathId); } public int LoadRecord(string filePath) { ArgumentNullException.ThrowIfNull(filePath); - return _npcs.LoadRecord(filePath); + return Npcs.LoadRecord(filePath); } public bool UnloadRecord(int recordId) { - return _npcs.UnloadRecord(recordId); + return Npcs.UnloadRecord(recordId); } public bool IsValidRecord(int recordId) { - return _npcs.IsValidRecord(recordId); + return Npcs.IsValidRecord(recordId); } public Size GetRecordCount() { - return _npcs.GetRecordCount(); + return Npcs.GetRecordCount(); } public void UnloadAllRecords() { - _npcs.UnloadAllRecords(); + Npcs.UnloadAllRecords(); } public bool OpenNode(int nodeId) { - return _npcs.OpenNode(nodeId); + return Npcs.OpenNode(nodeId); } public void CloseNode(int nodeId) { - _npcs.CloseNode(nodeId); + Npcs.CloseNode(nodeId); } public bool IsNodeOpen(int nodeId) { - return _npcs.IsNodeOpen(nodeId); + return Npcs.IsNodeOpen(nodeId); } public byte GetNodeType(int nodeId) { - return _npcs.GetNodeType(nodeId); + return Npcs.GetNodeType(nodeId); } public bool SetNodePoint(int nodeId, ushort pointId) { - return _npcs.SetNodePoint(nodeId, pointId); + return Npcs.SetNodePoint(nodeId, pointId); } public bool GetNodePointPosition(int nodeId, out Vector3 position) { - return _npcs.GetNodePointPosition(nodeId, out position); + return Npcs.GetNodePointPosition(nodeId, out position); } public int GetNodePointCount(int nodeId) { - return _npcs.GetNodePointCount(nodeId); + return Npcs.GetNodePointCount(nodeId); } public bool GetNodeInfo(int nodeId, out uint vehicleNodes, out uint pedNodes, out uint naviNodes) { - return _npcs.GetNodeInfo(nodeId, out vehicleNodes, out pedNodes, out naviNodes); + return Npcs.GetNodeInfo(nodeId, out vehicleNodes, out pedNodes, out naviNodes); } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Services/OmpEntityProvider.cs b/src/SampSharp.OpenMp.Entities/SAMP/Services/OmpEntityProvider.cs index ff323b63..3062dc6d 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Services/OmpEntityProvider.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Services/OmpEntityProvider.cs @@ -6,17 +6,28 @@ namespace SampSharp.Entities.SAMP; internal sealed class OmpEntityProvider(SampSharpEnvironment environment, IEntityManager entityManager) : IOmpEntityProvider { - private readonly IActorsComponent _actors = environment.Components.QueryComponent(); - private readonly IClassesComponent _classes = environment.Components.QueryComponent(); - private readonly IGangZonesComponent _gangZones = environment.Components.QueryComponent(); - private readonly IMenusComponent _menus = environment.Components.QueryComponent(); - private readonly INPCComponent _npcs = environment.Components.QueryComponent(); - private readonly IObjectsComponent _objects = environment.Components.QueryComponent(); - private readonly IPickupsComponent _pickups = environment.Components.QueryComponent(); - private readonly IPlayerPool _players = environment.Core.GetPlayers(); - private readonly ITextDrawsComponent _textDraws = environment.Components.QueryComponent(); - private readonly ITextLabelsComponent _textLabels = environment.Components.QueryComponent(); - private readonly IVehiclesComponent _vehicles = environment.Components.QueryComponent(); + private readonly SafeComponentHandle _actors = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _classes = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _gangZones = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _menus = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _npcs = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _objects = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _pickups = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _textDraws = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _textLabels = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _vehicles = environment.SafeComponentHandleProvider.Get(); + + private IActorsComponent Actors => _actors; + private IClassesComponent Classes => _classes; + private IGangZonesComponent GangZones => _gangZones; + private IMenusComponent Menus => _menus; + private INPCComponent Npcs => _npcs; + private IObjectsComponent Objects => _objects; + private IPickupsComponent Pickups => _pickups; + private IPlayerPool Players { get; } = environment.Core.GetPlayers(); + private ITextDrawsComponent TextDraws => _textDraws; + private ITextLabelsComponent TextLabels => _textLabels; + private IVehiclesComponent Vehicles => _vehicles; public EntityId GetEntity(IActor actor) { @@ -98,7 +109,7 @@ public EntityId GetEntity(IClass playerClass) var ext = playerClass.TryGetExtension(); if (ext == null) { - var component = entityManager.AddComponent(EntityId.NewEntityId(), _classes, playerClass); + var component = entityManager.AddComponent(EntityId.NewEntityId(), Classes, playerClass); ext = new ComponentExtension(component); playerClass.AddExtension(ext); @@ -118,7 +129,7 @@ public EntityId GetEntity(IClass playerClass) var ext = actor.TryGetExtension(); if (ext == null) { - var component = entityManager.AddComponent(EntityId.NewEntityId(), _actors, actor); + var component = entityManager.AddComponent(EntityId.NewEntityId(), Actors, actor); ext = new ComponentExtension(component); actor.AddExtension(ext); @@ -141,7 +152,7 @@ public EntityId GetEntity(IClass playerClass) return (Npc)ext.Component; } - var component = entityManager.AddComponent(EntityId.NewEntityId(), _npcs, npc); + var component = entityManager.AddComponent(EntityId.NewEntityId(), Npcs, npc); ext = new ComponentExtension(component); npc.AddExtension(ext); return component; @@ -158,8 +169,8 @@ public EntityId GetEntity(IClass playerClass) if (ext == null) { BaseGangZone component = gangZone.GetLegacyPlayer().HasValue - ? entityManager.AddComponent(EntityId.NewEntityId(), this, _gangZones, gangZone) - : entityManager.AddComponent(EntityId.NewEntityId(), this, _gangZones, gangZone); + ? entityManager.AddComponent(EntityId.NewEntityId(), this, GangZones, gangZone) + : entityManager.AddComponent(EntityId.NewEntityId(), this, GangZones, gangZone); ext = new ComponentExtension(component); gangZone.AddExtension(ext); @@ -196,7 +207,7 @@ public EntityId GetEntity(IClass playerClass) var ext = @object.TryGetExtension(); if (ext == null) { - var component = entityManager.AddComponent(EntityId.NewEntityId(), this, _objects, @object); + var component = entityManager.AddComponent(EntityId.NewEntityId(), this, Objects, @object); ext = new ComponentExtension(component); @object.AddExtension(ext); @@ -217,8 +228,8 @@ public EntityId GetEntity(IClass playerClass) if (ext == null) { BasePickup component = pickup.GetLegacyPlayer().HasValue - ? entityManager.AddComponent(EntityId.NewEntityId(), _pickups, pickup) - : entityManager.AddComponent(EntityId.NewEntityId(), _pickups, pickup); + ? entityManager.AddComponent(EntityId.NewEntityId(), Pickups, pickup) + : entityManager.AddComponent(EntityId.NewEntityId(), Pickups, pickup); ext = new ComponentExtension(component); pickup.AddExtension(ext); @@ -348,7 +359,7 @@ public EntityId GetEntity(IClass playerClass) var ext = textDraw.TryGetExtension(); if (ext == null) { - var component = entityManager.AddComponent(EntityId.NewEntityId(), _textDraws, textDraw); + var component = entityManager.AddComponent(EntityId.NewEntityId(), TextDraws, textDraw); ext = new ComponentExtension(component); textDraw.AddExtension(ext); @@ -368,7 +379,7 @@ public EntityId GetEntity(IClass playerClass) var ext = textLabel.TryGetExtension(); if (ext == null) { - var component = entityManager.AddComponent(EntityId.NewEntityId(), this, _textLabels, textLabel); + var component = entityManager.AddComponent(EntityId.NewEntityId(), this, TextLabels, textLabel); ext = new ComponentExtension(component); textLabel.AddExtension(ext); @@ -389,7 +400,7 @@ public EntityId GetEntity(IClass playerClass) if (ext == null) { - var component = entityManager.AddComponent(EntityId.NewEntityId(), this, _vehicles, vehicle); + var component = entityManager.AddComponent(EntityId.NewEntityId(), this, Vehicles, vehicle); ext = new ComponentExtension(component); vehicle.AddExtension(ext); @@ -401,37 +412,37 @@ public EntityId GetEntity(IClass playerClass) public Class? GetPlayerClass(int id) { - return GetComponent(_classes.AsPool().Get(id)); + return GetComponent(Classes.AsPool().Get(id)); } public Actor? GetActor(int id) { - return GetComponent(_actors.AsPool().Get(id)); + return GetComponent(Actors.AsPool().Get(id)); } public Npc? GetNpc(int id) { - if (!_npcs.HasValue) + if (!Npcs.HasValue) { return null; } - return GetComponent(_npcs.Get(id)); + return GetComponent(Npcs.Get(id)); } public BaseGangZone? GetGangZone(int id) { - return GetComponent(_gangZones.AsPool().Get(id)); + return GetComponent(GangZones.AsPool().Get(id)); } public BasePickup? GetPickup(int id) { - return GetComponent(_pickups.AsPool().Get(id)); + return GetComponent(Pickups.AsPool().Get(id)); } public Player? GetPlayer(int id) { - return GetComponent(_players.Get(id)); + return GetComponent(Players.Get(id)); } public PlayerObject? GetPlayerObject(IPlayer player, int id) @@ -463,26 +474,26 @@ public EntityId GetEntity(IClass playerClass) public TextDraw? GetTextDraw(int id) { - return GetComponent(_textDraws.AsPool().Get(id)); + return GetComponent(TextDraws.AsPool().Get(id)); } public TextLabel? GetTextLabel(int id) { - return GetComponent(_textLabels.AsPool().Get(id)); + return GetComponent(TextLabels.AsPool().Get(id)); } public Vehicle? GetVehicle(int id) { - return GetComponent(_vehicles.AsPool().Get(id)); + return GetComponent(Vehicles.AsPool().Get(id)); } public GlobalObject? GetObject(int id) { - return GetComponent(_objects.AsPool().Get(id)); + return GetComponent(Objects.AsPool().Get(id)); } public Menu? GetMenu(int id) { - return GetComponent(_menus.AsPool().Get(id)); + return GetComponent(Menus.AsPool().Get(id)); } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Services/ServerService.cs b/src/SampSharp.OpenMp.Entities/SAMP/Services/ServerService.cs index b453366c..e32f97f1 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Services/ServerService.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Services/ServerService.cs @@ -1,5 +1,4 @@ using System.Numerics; -using System.Reflection.Metadata; using Microsoft.Extensions.Logging; using SampSharp.OpenMp.Core; using SampSharp.OpenMp.Core.Api; @@ -7,30 +6,23 @@ namespace SampSharp.Entities.SAMP; -internal sealed partial class ServerService : IServerService +internal sealed partial class ServerService(SampSharpEnvironment environment, IEntityManager entityManager, ILogger logger) : IServerService { - private readonly IActorsComponent _actors; - private readonly IClassesComponent _classes; - private readonly IConfig _config; - private readonly IConsoleComponent _console; - private readonly ICore _core; - private readonly IEntityManager _entityManager; - private readonly ILogger _logger; - private readonly IPlayerPool _players; - private readonly IVehiclesComponent _vehicles; - - public ServerService(SampSharpEnvironment environment, IEntityManager entityManager, ILogger logger) - { - _entityManager = entityManager; - _logger = logger; - _actors = environment.Components.QueryComponent(); - _config = environment.Core.GetConfig(); - _players = environment.Core.GetPlayers(); - _vehicles = environment.Components.QueryComponent(); - _classes = environment.Components.QueryComponent(); - _console = environment.Components.QueryComponent(); - _core = environment.Core; - } + private readonly SafeComponentHandle _actors = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _classes = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _console = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _vehicles = environment.SafeComponentHandleProvider.Get(); + + + private IConfig Config { get; } = environment.Core.GetConfig(); + private ICore Core { get; } = environment.Core; + private IPlayerPool Players { get; } = environment.Core.GetPlayers(); + + private IActorsComponent Actors => _actors; + private IClassesComponent Classes => _classes; + private IConsoleComponent Console => _console; + private IVehiclesComponent Vehicles => _vehicles; + public int ActorPoolSize { @@ -38,7 +30,7 @@ public int ActorPoolSize { var max = -1; - foreach (var actor in _actors.AsPool()) + foreach (var actor in Actors.AsPool()) { var id = actor.GetID(); if (id > max) @@ -51,7 +43,7 @@ public int ActorPoolSize } } - public int MaxPlayers => _config.GetInt("max_players").Value; + public int MaxPlayers => Config.GetInt("max_players").Value; public int PlayerPoolSize { @@ -59,7 +51,7 @@ public int PlayerPoolSize { var max = -1; - foreach (var player in _players.Entries()) + foreach (var player in Players.Entries()) { var id = player.GetID(); if (id > max) @@ -72,8 +64,8 @@ public int PlayerPoolSize } } - public int TickCount => (int)_core.GetTickCount(); - public int TickRate => (int)_core.TickRate(); + public int TickCount => (int)Core.GetTickCount(); + public int TickRate => (int)Core.TickRate(); public int VehiclePoolSize { @@ -81,7 +73,7 @@ public int VehiclePoolSize { var max = -1; - foreach (var vehicle in _vehicles.AsPool()) + foreach (var vehicle in Vehicles.AsPool()) { var id = vehicle.GetID(); if (id > max) @@ -105,10 +97,10 @@ public Class AddPlayerClass(int teamId, int modelId, Vector3 spawnPosition, floa var weapons = new WeaponSlots(slots); - var @class = _classes.Create(modelId, teamId, spawnPosition, angle, ref weapons); + var @class = Classes.Create(modelId, teamId, spawnPosition, angle, ref weapons); var entityId = EntityId.NewEntityId(); - var component = _entityManager.AddComponent(entityId, _classes, @class); + var component = entityManager.AddComponent(entityId, Classes, @class); var extension = new ComponentExtension(component); @class.AddExtension(extension); @@ -127,10 +119,10 @@ public Class AddPlayerClass(PlayerSpawnData spawnData) ArgumentNullException.ThrowIfNull(spawnData); var weapons = spawnData.Weapons.ToOmpData(); - var @class = _classes.Create(spawnData.Skin, spawnData.Team, spawnData.Location, spawnData.Angle, ref weapons); + var @class = Classes.Create(spawnData.Skin, spawnData.Team, spawnData.Location, spawnData.Angle, ref weapons); var entityId = EntityId.NewEntityId(); - var component = _entityManager.AddComponent(entityId, _classes, @class); + var component = entityManager.AddComponent(entityId, Classes, @class); var extension = new ComponentExtension(component); @class.AddExtension(extension); @@ -143,7 +135,7 @@ public void BlockIpAddress(string ipAddress, TimeSpan time = default) ArgumentNullException.ThrowIfNull(ipAddress); var entry = new BanEntry(ipAddress); - foreach (var network in _core.GetNetworks()) + foreach (var network in Core.GetNetworks()) { network.Ban(entry, time); } @@ -154,23 +146,23 @@ public void ConnectNpc(string name, string script) ArgumentNullException.ThrowIfNull(name); ArgumentNullException.ThrowIfNull(script); - _core.ConnectBot(name, script); + Core.ConnectBot(name, script); } public void DisableInteriorEnterExits() { - ref var fld = ref _core.GetConfig().GetBool("game.use_entry_exit_markers").Value; + ref var fld = ref Core.GetConfig().GetBool("game.use_entry_exit_markers").Value; fld = false; } public void EnableStuntBonus(bool enable) { - _core.UseStuntBonuses(enable); + Core.UseStuntBonuses(enable); } public void EnableVehicleFriendlyFire() { - ref var fld = ref _core.GetConfig().GetBool("game.use_vehicle_friendly_fire").Value; + ref var fld = ref Core.GetConfig().GetBool("game.use_vehicle_friendly_fire").Value; fld = false; } @@ -183,7 +175,7 @@ public bool GetConsoleVarAsBool(string variableName) { ArgumentNullException.ThrowIfNull(variableName); - var res = _config.GetNameFromAlias(variableName); + var res = Config.GetNameFromAlias(variableName); BlittableRef v0; BlittableRef v1 = default; @@ -194,20 +186,20 @@ public bool GetConsoleVarAsBool(string variableName) LogDeprecatedConsoleVariable(variableName, res.Item2); } - v0 = _config.GetBool(res.Item2); + v0 = Config.GetBool(res.Item2); if (!v0.HasValue) { - v1 = _config.GetInt(res.Item2); + v1 = Config.GetInt(res.Item2); } } else { - v0 = _config.GetBool(variableName); + v0 = Config.GetBool(variableName); if (!v0.HasValue) { - v1 = _config.GetInt(variableName); + v1 = Config.GetInt(variableName); } } @@ -229,7 +221,7 @@ public int GetConsoleVarAsInt(string variableName) { ArgumentNullException.ThrowIfNull(variableName); - var res = _config.GetNameFromAlias(variableName); + var res = Config.GetNameFromAlias(variableName); BlittableRef v0 = default; BlittableRef v1; @@ -240,21 +232,21 @@ public int GetConsoleVarAsInt(string variableName) LogDeprecatedConsoleVariable(variableName, res.Item2); } - v1 = _config.GetInt(res.Item2); + v1 = Config.GetInt(res.Item2); if (!v1.HasValue) { - v0 = _config.GetBool(res.Item2); + v0 = Config.GetBool(res.Item2); } } else { - v1 = _config.GetInt(variableName); + v1 = Config.GetInt(variableName); if (!v1.HasValue) { - v0 = _config.GetBool(variableName); + v0 = Config.GetBool(variableName); } } @@ -277,7 +269,7 @@ public int GetConsoleVarAsInt(string variableName) ArgumentNullException.ThrowIfNull(variableName); var gm = variableName.StartsWith("gamemode", StringComparison.Ordinal); - var res = _config.GetNameFromAlias(gm ? "gamemode" : variableName); + var res = Config.GetNameFromAlias(gm ? "gamemode" : variableName); if (!string.IsNullOrEmpty(res.Item2)) { @@ -290,7 +282,7 @@ public int GetConsoleVarAsInt(string variableName) { if (int.TryParse(variableName[8..], out var num)) { - var mainScripts = _config.GetStrings(res.Item2); + var mainScripts = Config.GetStrings(res.Item2); if (num < mainScripts.Length) { return mainScripts[num]; @@ -299,32 +291,32 @@ public int GetConsoleVarAsInt(string variableName) } else { - return _config.GetString(res.Item2); + return Config.GetString(res.Item2); } } - return _config.GetString(variableName); + return Config.GetString(variableName); } public void LimitGlobalChatRadius(float chatRadius) { - ref var use = ref _config.GetBool("game.use_chat_radius").Value; + ref var use = ref Config.GetBool("game.use_chat_radius").Value; use = true; - ref var radius = ref _config.GetFloat("game.chat_radius").Value; + ref var radius = ref Config.GetFloat("game.chat_radius").Value; radius = chatRadius; } public void LimitPlayerMarkerRadius(float markerRadius) { - ref var use = ref _config.GetBool("game.use_player_marker_draw_radius").Value; + ref var use = ref Config.GetBool("game.use_player_marker_draw_radius").Value; use = true; - ref var radius = ref _config.GetFloat("game.player_marker_draw_radius").Value; + ref var radius = ref Config.GetFloat("game.player_marker_draw_radius").Value; radius = markerRadius; } public void ManualVehicleEngineAndLights() { - ref var use = ref _config.GetBool("game.use_manual_engine_and_lights").Value; + ref var use = ref Config.GetBool("game.use_manual_engine_and_lights").Value; use = true; } @@ -333,76 +325,76 @@ public void SendRconCommand(string command) ArgumentNullException.ThrowIfNull(command); var snd = new ConsoleCommandSenderData(OpenMp.Core.Api.ConsoleCommandSender.Console, 0); - _console.Send(command, ref snd); + Console.Send(command, ref snd); } public void SetGameModeText(string text) { ArgumentNullException.ThrowIfNull(text); - _core.SetData(SettableCoreDataType.ModeText, text); + Core.SetData(SettableCoreDataType.ModeText, text); } public void SetServerName(string name) { ArgumentNullException.ThrowIfNull(name); - _core.SetData(SettableCoreDataType.ServerName, name); + Core.SetData(SettableCoreDataType.ServerName, name); } public void SetMapName(string name) { ArgumentNullException.ThrowIfNull(name); - _core.SetData(SettableCoreDataType.MapName, name); + Core.SetData(SettableCoreDataType.MapName, name); } public void SetLanguage(string language) { ArgumentNullException.ThrowIfNull(language); - _core.SetData(SettableCoreDataType.Language, language); + Core.SetData(SettableCoreDataType.Language, language); } public void SetWebsiteUrl(string url) { ArgumentNullException.ThrowIfNull(url); - _core.SetData(SettableCoreDataType.URL, url); + Core.SetData(SettableCoreDataType.URL, url); } public void SetServerPassword(string? password) { - _core.SetData(SettableCoreDataType.Password, password ?? string.Empty); + Core.SetData(SettableCoreDataType.Password, password ?? string.Empty); } public void SetAdminPassword(string? password) { - _core.SetData(SettableCoreDataType.AdminPassword, password ?? string.Empty); + Core.SetData(SettableCoreDataType.AdminPassword, password ?? string.Empty); } public void SetNameTagDrawDistance(float distance = 70) { - ref var fld = ref _config.GetFloat("game.nametag_draw_radius").Value; + ref var fld = ref Config.GetFloat("game.nametag_draw_radius").Value; fld = distance; } public void SetWorldTime(int hour) { - _core.SetWorldTime(TimeSpan.FromHours(hour)); + Core.SetWorldTime(TimeSpan.FromHours(hour)); } public void ShowNameTags(bool show) { - ref var fld = ref _config.GetBool("game.use_nametags").Value; + ref var fld = ref Config.GetBool("game.use_nametags").Value; fld = show; } public void ShowPlayerMarkers(PlayerMarkersMode mode) { - ref var fld = ref _config.GetInt("game.player_marker_mode").Value; + ref var fld = ref Config.GetInt("game.player_marker_mode").Value; fld = (int)mode; } public void UnBlockIpAddress(string ipAddress) { var entry = new BanEntry(ipAddress); - foreach (var network in _core.GetNetworks()) + foreach (var network in Core.GetNetworks()) { network.Unban(entry); } @@ -410,40 +402,40 @@ public void UnBlockIpAddress(string ipAddress) public void UsePlayerPedAnims() { - ref var fld = ref _config.GetBool("game.use_player_ped_anims").Value; + ref var fld = ref Config.GetBool("game.use_player_ped_anims").Value; fld = true; } public void SendEmptyDeathMessage() { - _players.SendEmptyDeathMessageToAll(); + Players.SendEmptyDeathMessageToAll(); } public bool IsNameTaken(string name, Player? skip = null) { ArgumentNullException.ThrowIfNull(name); - return _players.IsNameTaken(name, skip ?? default(IPlayer)); + return Players.IsNameTaken(name, skip ?? default(IPlayer)); } public bool IsNameValid(string name) { ArgumentNullException.ThrowIfNull(name); - return _players.IsNameValid(name); + return Players.IsNameValid(name); } public void AllowNickNameCharacter(char character, bool allow) { - _players.AllowNickNameCharacter(character, allow); + Players.AllowNickNameCharacter(character, allow); } public bool IsNickNameCharacterAllowed(char character) { - return _players.IsNickNameCharacterAllowed(character); + return Players.IsNickNameCharacterAllowed(character); } public Color GetDefaultColor(int playerId) { - return _players.GetDefaultColour(playerId); + return Players.GetDefaultColour(playerId); } [LoggerMessage(LogLevel.Warning, "Deprecated console variable \"{Old}\", use \"{New}\" instead.")] diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Services/WorldService.cs b/src/SampSharp.OpenMp.Entities/SAMP/Services/WorldService.cs index 8c4482fb..6e838e5f 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Services/WorldService.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Services/WorldService.cs @@ -6,35 +6,46 @@ namespace SampSharp.Entities.SAMP; internal sealed class WorldService(SampSharpEnvironment environment, IEntityManager entityManager, IOmpEntityProvider entityProvider) : IWorldService { - private readonly IActorsComponent _actors = environment.Components.QueryComponent(); - private readonly ICore _core = environment.Core; - private readonly IGangZonesComponent _gangZones = environment.Components.QueryComponent(); - private readonly IMenusComponent _menus = environment.Components.QueryComponent(); - private readonly IObjectsComponent _objects = environment.Components.QueryComponent(); - private readonly IPickupsComponent _pickups = environment.Components.QueryComponent(); - private readonly IPlayerPool _players = environment.Core.GetPlayers(); - private readonly ITextDrawsComponent _textDraws = environment.Components.QueryComponent(); - private readonly ITextLabelsComponent _textLabels = environment.Components.QueryComponent(); - private readonly IVehiclesComponent _vehicles = environment.Components.QueryComponent(); - private readonly INPCComponent _npcs = environment.Components.QueryComponent(); + private readonly SafeComponentHandle _actors = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _gangZones = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _menus = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _objects = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _pickups = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _textDraws = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _textLabels = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _vehicles = environment.SafeComponentHandleProvider.Get(); + private readonly SafeComponentHandle _npcs = environment.SafeComponentHandleProvider.Get(); + + private ICore Core { get; } = environment.Core; + private IPlayerPool Players { get; } = environment.Core.GetPlayers(); + + private IActorsComponent Actors => _actors; + private IGangZonesComponent GangZones => _gangZones; + private IMenusComponent Menus => _menus; + private IObjectsComponent Objects => _objects; + private IPickupsComponent Pickups => _pickups; + private ITextDrawsComponent TextDraws => _textDraws; + private ITextLabelsComponent TextLabels => _textLabels; + private IVehiclesComponent Vehicles => _vehicles; + private INPCComponent Npcs => _npcs; public float Gravity { - get => _core.GetGravity(); + get => Core.GetGravity(); set { ArgumentOutOfRangeException.ThrowIfLessThan(value, -50.0f, nameof(value)); ArgumentOutOfRangeException.ThrowIfGreaterThan(value, 50.0f, nameof(value)); - _core.SetGravity(value); + Core.SetGravity(value); } } public Actor CreateActor(int modelId, Vector3 position, float rotation, EntityId parent = default) { - var native = _actors.Create(modelId, position, rotation); + var native = Actors.Create(modelId, position, rotation); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, _actors, native); + var component = entityManager.AddComponent(entityId, parent, Actors, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -44,12 +55,12 @@ public Actor CreateActor(int modelId, Vector3 position, float rotation, EntityId public Npc CreateNpc(string name, EntityId parent = default) { - if(_npcs == null) + if(Npcs == null) { throw new InvalidOperationException("NPC component not loaded."); } - var native = _npcs.Create(name); + var native = Npcs.Create(name); if (!native.HasValue) { @@ -57,7 +68,7 @@ public Npc CreateNpc(string name, EntityId parent = default) } var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, _npcs, native); + var component = entityManager.AddComponent(entityId, parent, Npcs, native); var extension = native.TryGetExtension(); if (extension is null) @@ -88,9 +99,9 @@ public GangZone CreateGangZone(float minX, float minY, float maxX, float maxY, E public GangZone CreateGangZone(Vector2 min, Vector2 max, EntityId parent = default) { - var native = _gangZones.Create(new GangZonePos(min, max)); + var native = GangZones.Create(new GangZonePos(min, max)); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, entityProvider, _gangZones, native); + var component = entityManager.AddComponent(entityId, parent, entityProvider, GangZones, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -102,11 +113,11 @@ public PlayerGangZone CreatePlayerGangZone(Player owner, Vector2 min, Vector2 ma { ArgumentNullException.ThrowIfNull(owner); - var native = _gangZones.Create(new GangZonePos(min, max)); + var native = GangZones.Create(new GangZonePos(min, max)); native.SetLegacyPlayer(owner); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, entityProvider, _gangZones, native); + var component = entityManager.AddComponent(entityId, parent, entityProvider, GangZones, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -117,14 +128,14 @@ public PlayerGangZone CreatePlayerGangZone(Player owner, Vector2 min, Vector2 ma public void UseGangZoneCheck(BaseGangZone zone, bool enable) { ArgumentNullException.ThrowIfNull(zone); - _gangZones.UseGangZoneCheck(zone, enable); + GangZones.UseGangZoneCheck(zone, enable); } public Pickup CreatePickup(int model, PickupType type, Vector3 position, int virtualWorld = -1, EntityId parent = default) { - var native = _pickups.Create(model, (byte)type, position, (uint)virtualWorld, false); + var native = Pickups.Create(model, (byte)type, position, (uint)virtualWorld, false); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, _pickups, native); + var component = entityManager.AddComponent(entityId, parent, Pickups, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -136,11 +147,11 @@ public PlayerPickup CreatePlayerPickup(Player owner, int model, PickupType type, { ArgumentNullException.ThrowIfNull(owner); - var native = _pickups.Create(model, (byte)type, position, (uint)virtualWorld, false); + var native = Pickups.Create(model, (byte)type, position, (uint)virtualWorld, false); native.SetLegacyPlayer(owner); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, _pickups, native); + var component = entityManager.AddComponent(entityId, parent, Pickups, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -150,9 +161,9 @@ public PlayerPickup CreatePlayerPickup(Player owner, int model, PickupType type, public Pickup CreateStaticPickup(int model, PickupType type, Vector3 position, int virtualWorld = -1, EntityId parent = default) { - var native = _pickups.Create(model, (byte)type, position, (uint)virtualWorld, true); + var native = Pickups.Create(model, (byte)type, position, (uint)virtualWorld, true); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, _objects, native); + var component = entityManager.AddComponent(entityId, parent, Objects, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -162,9 +173,9 @@ public Pickup CreateStaticPickup(int model, PickupType type, Vector3 position, i public GlobalObject CreateObject(int modelId, Vector3 position, Vector3 rotation, float drawDistance = 0, EntityId parent = default) { - var native = _objects.Create(modelId, position, rotation, drawDistance); + var native = Objects.Create(modelId, position, rotation, drawDistance); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, entityProvider, _objects, native); + var component = entityManager.AddComponent(entityId, parent, entityProvider, Objects, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -194,9 +205,9 @@ public TextLabel CreateTextLabel(string text, Color color, Vector3 position, flo { ArgumentNullException.ThrowIfNull(text); - var native = _textLabels.Create(text, color, position, drawDistance, virtualWorld, testLos); + var native = TextLabels.Create(text, color, position, drawDistance, virtualWorld, testLos); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, entityProvider, _textLabels, native); + var component = entityManager.AddComponent(entityId, parent, entityProvider, TextLabels, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -230,9 +241,9 @@ public TextDraw CreateTextDraw(Vector2 position, string text, EntityId parent = { ArgumentNullException.ThrowIfNull(text); - var native = _textDraws.Create(position, text); + var native = TextDraws.Create(position, text); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, _textDraws, native); + var component = entityManager.AddComponent(entityId, parent, TextDraws, native); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -265,9 +276,9 @@ public Menu CreateMenu(string title, Vector2 position, float col0Width, float? c { ArgumentNullException.ThrowIfNull(title); - var native = _menus.Create(title, position, col1Width.HasValue ? (byte)2 : (byte)1, col0Width, col1Width ?? 0); + var native = Menus.Create(title, position, col1Width.HasValue ? (byte)2 : (byte)1, col0Width, col1Width ?? 0); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, _menus, native, title); + var component = entityManager.AddComponent(entityId, parent, Menus, native, title); var extension = new ComponentExtension(component); native.AddExtension(extension); @@ -277,7 +288,7 @@ public Menu CreateMenu(string title, Vector2 position, float col0Width, float? c public void SetObjectsDefaultCameraCollision(bool disable) { - _objects.SetDefaultCameraCollision(disable); + Objects.SetDefaultCameraCollision(disable); } public void SendClientMessage(Color color, string message) @@ -285,7 +296,7 @@ public void SendClientMessage(Color color, string message) ArgumentNullException.ThrowIfNull(message); Colour clr = color; - _players.SendClientMessageToAll(ref clr, message); + Players.SendClientMessageToAll(ref clr, message); } public void SendClientMessage(Color color, string messageFormat, params object[] args) @@ -309,12 +320,12 @@ public void SendPlayerMessageToPlayer(Player sender, string message) { ArgumentNullException.ThrowIfNull(sender); ArgumentNullException.ThrowIfNull(message); - _players.SendChatMessageToAll(sender, message); + Players.SendChatMessageToAll(sender, message); } public void SendDeathMessage(Player killer, Player killee, Weapon weapon) { - _players.SendDeathMessageToAll(killer, killee, (int)weapon); + Players.SendDeathMessageToAll(killer, killee, (int)weapon); } public void GameText(string text, int time, int style) @@ -324,32 +335,32 @@ public void GameText(string text, int time, int style) public void GameText(string text, TimeSpan time, GameTextStyle style) { - _players.SendGameTextToAll(text, time, (int)style); + Players.SendGameTextToAll(text, time, (int)style); } public void HideGameText(GameTextStyle style) { - _players.HideGameTextForAll((int)style); + Players.HideGameTextForAll((int)style); } public void CreateExplosion(Vector3 position, ExplosionType type, float radius) { - _players.CreateExplosionForAll(position, (int)type, radius); + Players.CreateExplosionForAll(position, (int)type, radius); } public void SetWeather(int weather) { - _core.SetWeather(weather); + Core.SetWeather(weather); } private Vehicle CreateVehicle(bool isStatic, VehicleModelType type, Vector3 position, float rotation, int color1, int color2, int respawnDelay = -1, bool addSiren = false, EntityId parent = default) { var respawnDelaySpan = respawnDelay < 0 ? TimeSpan.Zero : TimeSpan.FromSeconds(respawnDelay); - var native = _vehicles.Create(isStatic, (int)type, position, rotation, color1, color2, respawnDelaySpan, addSiren); + var native = Vehicles.Create(isStatic, (int)type, position, rotation, color1, color2, respawnDelaySpan, addSiren); var entityId = EntityId.NewEntityId(); - var component = entityManager.AddComponent(entityId, parent, entityProvider, _vehicles, native); + var component = entityManager.AddComponent(entityId, parent, entityProvider, Vehicles, native); var extension = new ComponentExtension(component); native.AddExtension(extension); diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Systems/ClassSystem.cs b/src/SampSharp.OpenMp.Entities/SAMP/Systems/ClassSystem.cs index 3507d8fd..50abb340 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Systems/ClassSystem.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Systems/ClassSystem.cs @@ -4,7 +4,7 @@ namespace SampSharp.Entities.SAMP; internal sealed class ClassSystem : DisposableSystem, IClassEventHandler { - private readonly IClassesComponent _classes; + private readonly SafeComponentHandle _classes; private readonly IOmpEntityProvider _entityProvider; private readonly IEventDispatcher _eventDispatcher; @@ -12,14 +12,14 @@ public ClassSystem(IEventDispatcher eventDispatcher, IOmpEntityProvider entityPr { _eventDispatcher = eventDispatcher; _entityProvider = entityProvider; - _classes = environment.Components.QueryComponent(); + _classes = environment.SafeComponentHandleProvider.Get(); - AddDisposable(environment.TryAddEventHandler(x => x.GetEventDispatcher(), this)); + AddDisposable(environment.TryAddEventHandler((IClassesComponent x) => x.GetEventDispatcher(), this)); } public bool OnPlayerRequestClass(IPlayer player, uint classId) { return _eventDispatcher.InvokeAs("OnPlayerRequestClass", true, - _entityProvider.GetEntity(player), _entityProvider.GetEntity(_classes.AsPool().Get((int)classId))); + _entityProvider.GetEntity(player), _entityProvider.GetEntity(_classes.Value.AsPool().Get((int)classId))); } } diff --git a/src/SampSharp.OpenMp.Entities/SampSharp.OpenMp.Entities.csproj b/src/SampSharp.OpenMp.Entities/SampSharp.OpenMp.Entities.csproj index 7e381c9e..9050bd51 100644 --- a/src/SampSharp.OpenMp.Entities/SampSharp.OpenMp.Entities.csproj +++ b/src/SampSharp.OpenMp.Entities/SampSharp.OpenMp.Entities.csproj @@ -1,6 +1,7 @@  + true SampSharp.Entities True diff --git a/src/SampSharp.SourceGenerator/Generators/EntryPointSourceGenerator.cs b/src/SampSharp.SourceGenerator/Generators/EntryPointSourceGenerator.cs index c8a9850a..705435f7 100644 --- a/src/SampSharp.SourceGenerator/Generators/EntryPointSourceGenerator.cs +++ b/src/SampSharp.SourceGenerator/Generators/EntryPointSourceGenerator.cs @@ -109,24 +109,6 @@ private static SourceText Generate(ClassDeclarationSyntax syntax) TokenList( Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.StaticKeyword))), - MethodDeclaration( - PredefinedType( - Token(SyntaxKind.VoidKeyword)), - Identifier("Cleanup")) - .WithAttributeLists( - SingletonList( - AttributeFactory.UnmanagedCallersOnly())) - .WithModifiers( - TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) - .WithBody( - Block( - SingletonList( - ExpressionStatement( - ConditionalAccessExpression( - IdentifierName("_context"), - InvocationExpression( - MemberBindingExpression( - IdentifierName("InvokeCleanup")))))))), MethodDeclaration( PredefinedType( Token(SyntaxKind.VoidKeyword)), diff --git a/src/sampsharp-component/platform.hpp b/src/sampsharp-component/platform.hpp new file mode 100644 index 00000000..a6f487b2 --- /dev/null +++ b/src/sampsharp-component/platform.hpp @@ -0,0 +1,12 @@ + +// On non-Windows platforms, __CDECL (from the SDK's types.hpp) expands to +// __attribute__((__cdecl__)) which is only meaningful on 32-bit x86 and +// generates -Wattributes warnings on x86_64 Linux builds. Override to empty. +#if !defined(_WIN32) +#ifdef __CDECL +#undef __CDECL +#endif +#define __CDECL +#endif + +#define API_CALLTYPE __CDECL \ No newline at end of file diff --git a/src/sampsharp-component/proxy-api.hpp b/src/sampsharp-component/proxy-api.hpp index db34a7e9..1697a875 100644 --- a/src/sampsharp-component/proxy-api.hpp +++ b/src/sampsharp-component/proxy-api.hpp @@ -4,21 +4,7 @@ #include #include -#if defined(_WIN32) - #define API_CALLTYPE __stdcall -#else - #define API_CALLTYPE -#endif - -// On non-Windows platforms, __CDECL (from the SDK's types.hpp) expands to -// __attribute__((__cdecl__)) which is only meaningful on 32-bit x86 and -// generates -Wattributes warnings on x86_64 Linux builds. Override to empty. -#if !defined(_WIN32) - #ifdef __CDECL - #undef __CDECL - #endif - #define __CDECL -#endif +#include "platform.hpp" // // Null-subject guard. Used by PROXY() macros to avoid dereferencing a null @@ -37,16 +23,16 @@ namespace sampsharp { template - [[noreturn]] inline T proxy_default_unsupported(const char* name) + [[noreturn]] inline T proxy_default_unsupported(const char *name) { std::fprintf(stderr, - "sampsharp: PROXY call with null subject returning an unsupported type for '%s'. Aborting.\n", - name); + "sampsharp: PROXY call with null subject returning an unsupported type for '%s'. Aborting.\n", + name); std::terminate(); } template - inline T proxy_default(const char* name) + inline T proxy_default(const char *name) { if constexpr (std::is_void_v) { @@ -74,8 +60,8 @@ namespace sampsharp // // expand variadic args as a numbered parameter list. e.g. _EXPAND_PARAM(a, b, X, Y) -> aXb _2, aYb _1 -#define _EXPAND_PARAM(prefix,postfix,...) _EXPAND_PARAM_N(__VA_ARGS__,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(prefix,postfix,##__VA_ARGS__) -#define _EXPAND_PARAM_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_PARAM ## n +#define _EXPAND_PARAM(prefix, postfix, ...) _EXPAND_PARAM_N(__VA_ARGS__, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(prefix, postfix, ##__VA_ARGS__) +#define _EXPAND_PARAM_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_PARAM##n #define _EXPAND_PARAM1(prefix, postfix, type, ...) prefix##type##postfix _1 #define _EXPAND_PARAM2(prefix, postfix, type, ...) prefix##type##postfix _2, _EXPAND_PARAM1(prefix, postfix, ##__VA_ARGS__) #define _EXPAND_PARAM3(prefix, postfix, type, ...) prefix##type##postfix _3, _EXPAND_PARAM2(prefix, postfix, ##__VA_ARGS__) @@ -103,37 +89,37 @@ namespace sampsharp #define _EXPAND_PARAM25(prefix, postfix, type, ...) prefix##type##postfix _25, _EXPAND_PARAM24(prefix, postfix, ##__VA_ARGS__) // expand variadic args as a numbered argument list. e.g. _EXPAND_ARG(,X, Y) -> _2, _1 -#define _EXPAND_ARG(prefix, ...) _EXPAND_ARG_N(__VA_ARGS__,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(prefix,##__VA_ARGS__) -#define _EXPAND_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_ARG ## n -#define _EXPAND_ARG1(prefix,type, ...) prefix _1 -#define _EXPAND_ARG2(prefix,type, ...) prefix _2, _EXPAND_ARG1(prefix,##__VA_ARGS__) -#define _EXPAND_ARG3(prefix,type, ...) prefix _3, _EXPAND_ARG2(prefix,##__VA_ARGS__) -#define _EXPAND_ARG4(prefix,type, ...) prefix _4, _EXPAND_ARG3(prefix,##__VA_ARGS__) -#define _EXPAND_ARG5(prefix,type, ...) prefix _5, _EXPAND_ARG4(prefix,##__VA_ARGS__) -#define _EXPAND_ARG6(prefix,type, ...) prefix _6, _EXPAND_ARG5(prefix,##__VA_ARGS__) -#define _EXPAND_ARG7(prefix,type, ...) prefix _7, _EXPAND_ARG6(prefix,##__VA_ARGS__) -#define _EXPAND_ARG8(prefix,type, ...) prefix _8, _EXPAND_ARG7(prefix,##__VA_ARGS__) -#define _EXPAND_ARG9(prefix,type, ...) prefix _9, _EXPAND_ARG8(prefix,##__VA_ARGS__) -#define _EXPAND_ARG10(prefix,type, ...) prefix _10, _EXPAND_ARG9(prefix,##__VA_ARGS__) -#define _EXPAND_ARG11(prefix,type, ...) prefix _11, _EXPAND_ARG10(prefix,##__VA_ARGS__) -#define _EXPAND_ARG12(prefix,type, ...) prefix _12, _EXPAND_ARG11(prefix,##__VA_ARGS__) -#define _EXPAND_ARG13(prefix,type, ...) prefix _13, _EXPAND_ARG12(prefix,##__VA_ARGS__) -#define _EXPAND_ARG14(prefix,type, ...) prefix _14, _EXPAND_ARG13(prefix,##__VA_ARGS__) -#define _EXPAND_ARG15(prefix,type, ...) prefix _15, _EXPAND_ARG14(prefix,##__VA_ARGS__) -#define _EXPAND_ARG16(prefix,type, ...) prefix _16, _EXPAND_ARG15(prefix,##__VA_ARGS__) -#define _EXPAND_ARG17(prefix,type, ...) prefix _17, _EXPAND_ARG16(prefix,##__VA_ARGS__) -#define _EXPAND_ARG18(prefix,type, ...) prefix _18, _EXPAND_ARG17(prefix,##__VA_ARGS__) -#define _EXPAND_ARG19(prefix,type, ...) prefix _19, _EXPAND_ARG18(prefix,##__VA_ARGS__) -#define _EXPAND_ARG20(prefix,type, ...) prefix _20, _EXPAND_ARG19(prefix,##__VA_ARGS__) -#define _EXPAND_ARG21(prefix,type, ...) prefix _21, _EXPAND_ARG20(prefix,##__VA_ARGS__) -#define _EXPAND_ARG22(prefix,type, ...) prefix _22, _EXPAND_ARG21(prefix,##__VA_ARGS__) -#define _EXPAND_ARG23(prefix,type, ...) prefix _23, _EXPAND_ARG22(prefix,##__VA_ARGS__) -#define _EXPAND_ARG24(prefix,type, ...) prefix _24, _EXPAND_ARG23(prefix,##__VA_ARGS__) -#define _EXPAND_ARG25(prefix,type, ...) prefix _25, _EXPAND_ARG24(prefix,##__VA_ARGS__) +#define _EXPAND_ARG(prefix, ...) _EXPAND_ARG_N(__VA_ARGS__, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_ARG##n +#define _EXPAND_ARG1(prefix, type, ...) prefix _1 +#define _EXPAND_ARG2(prefix, type, ...) prefix _2, _EXPAND_ARG1(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG3(prefix, type, ...) prefix _3, _EXPAND_ARG2(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG4(prefix, type, ...) prefix _4, _EXPAND_ARG3(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG5(prefix, type, ...) prefix _5, _EXPAND_ARG4(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG6(prefix, type, ...) prefix _6, _EXPAND_ARG5(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG7(prefix, type, ...) prefix _7, _EXPAND_ARG6(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG8(prefix, type, ...) prefix _8, _EXPAND_ARG7(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG9(prefix, type, ...) prefix _9, _EXPAND_ARG8(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG10(prefix, type, ...) prefix _10, _EXPAND_ARG9(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG11(prefix, type, ...) prefix _11, _EXPAND_ARG10(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG12(prefix, type, ...) prefix _12, _EXPAND_ARG11(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG13(prefix, type, ...) prefix _13, _EXPAND_ARG12(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG14(prefix, type, ...) prefix _14, _EXPAND_ARG13(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG15(prefix, type, ...) prefix _15, _EXPAND_ARG14(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG16(prefix, type, ...) prefix _16, _EXPAND_ARG15(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG17(prefix, type, ...) prefix _17, _EXPAND_ARG16(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG18(prefix, type, ...) prefix _18, _EXPAND_ARG17(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG19(prefix, type, ...) prefix _19, _EXPAND_ARG18(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG20(prefix, type, ...) prefix _20, _EXPAND_ARG19(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG21(prefix, type, ...) prefix _21, _EXPAND_ARG20(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG22(prefix, type, ...) prefix _22, _EXPAND_ARG21(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG23(prefix, type, ...) prefix _23, _EXPAND_ARG22(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG24(prefix, type, ...) prefix _24, _EXPAND_ARG23(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG25(prefix, type, ...) prefix _25, _EXPAND_ARG24(prefix, ##__VA_ARGS__) /// expand variadic args as a numbered initializer list. e.g. _EXPAND_INIT(X, Y) -> X_(_2), Y_(_1) -#define _EXPAND_INIT(...) _EXPAND_INIT_N(__VA_ARGS__,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__) -#define _EXPAND_INIT_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_INIT ## n +#define _EXPAND_INIT(...) _EXPAND_INIT_N(__VA_ARGS__, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(__VA_ARGS__) +#define _EXPAND_INIT_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_INIT##n #define _EXPAND_INIT1(type, ...) type##_(_1) #define _EXPAND_INIT2(type, ...) type##_(_2), _EXPAND_INIT1(__VA_ARGS__) #define _EXPAND_INIT3(type, ...) type##_(_3), _EXPAND_INIT2(__VA_ARGS__) @@ -160,46 +146,53 @@ namespace sampsharp #define _EXPAND_INIT24(type, ...) type##_(_24), _EXPAND_INIT23(__VA_ARGS__) #define _EXPAND_INIT25(type, ...) type##_(_25), _EXPAND_INIT24(__VA_ARGS__) -#define __PROXY_IMPL(type_subject, type_return, method, proxy_name, ...) \ - extern "C" SDK_EXPORT type_return __CDECL \ - proxy_name(type_subject * subject __VA_OPT__(, _EXPAND_PARAM(,,##__VA_ARGS__))) \ - { \ - if (!subject) { return ::sampsharp::proxy_default(#proxy_name); } \ - return subject -> method ( \ - __VA_OPT__(_EXPAND_ARG(,##__VA_ARGS__)) \ - ); \ +#define __PROXY_IMPL(type_subject, type_return, method, proxy_name, ...) \ + extern "C" SDK_EXPORT type_return __CDECL \ + proxy_name(type_subject *subject __VA_OPT__(, _EXPAND_PARAM(, , ##__VA_ARGS__))) \ + { \ + if (!subject) \ + { \ + return ::sampsharp::proxy_default(#proxy_name); \ + } \ + return subject->method( \ + __VA_OPT__(_EXPAND_ARG(, ##__VA_ARGS__))); \ } -#define __PROXY_IMPL_RESULT_PTR(type_subject, type_return, method, proxy_name, ...) \ - extern "C" SDK_EXPORT void __CDECL \ - proxy_name(type_subject * subject __VA_OPT__(, _EXPAND_PARAM(,,__VA_ARGS__)), type_return * result) \ - { \ - if (!subject) { if (result) { *result = type_return{}; } return; } \ - *result = subject -> method ( \ - __VA_OPT__(_EXPAND_ARG(,##__VA_ARGS__)) \ - ); \ +#define __PROXY_IMPL_RESULT_PTR(type_subject, type_return, method, proxy_name, ...) \ + extern "C" SDK_EXPORT void __CDECL \ + proxy_name(type_subject *subject __VA_OPT__(, _EXPAND_PARAM(, , __VA_ARGS__)), type_return *result) \ + { \ + if (!subject) \ + { \ + if (result) \ + { \ + *result = type_return{}; \ + } \ + return; \ + } \ + *result = subject->method( \ + __VA_OPT__(_EXPAND_ARG(, ##__VA_ARGS__))); \ } // // macros for definition of exported proxy functions // - #define __PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name) \ - extern "C" SDK_EXPORT type_to * __CDECL \ - cast_##type_from_name##_to_##type_to_name(type_from * from) \ - { \ - return static_cast(from); \ + extern "C" SDK_EXPORT type_to *__CDECL \ + cast_##type_from_name##_to_##type_to_name(type_from *from) \ + { \ + return static_cast(from); \ } /// proxy function for casting from one type to another and vice versa e.g. PROXY_CAST_NAMED(IFoo, foo, IBar, bar) -> IBar * cast_foo_to_bar(IFoo * from) { return static_cast(from); } #define PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name) \ - __PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name); \ + __PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name); \ __PROXY_CAST_NAMED(type_to, type_to_name, type_from, type_from_name) /// proxy function for casting from one type to another e.g. PROXY_CAST(IFoo, IBar) -> IBar * cast_IFoo_to_IBar(IFoo * from) { return static_cast(from); } #define PROXY_CAST(type_from, type_to) PROXY_CAST_NAMED(type_from, type_from, type_to, type_to) - + /// proxy function macro. e.g. PROXY(subj, int, foo, bool) -> int subj_foo(subj * x, bool _1) { return x->foo(_1); } #define PROXY(type_subject, type_return, method, ...) __PROXY_IMPL(type_subject, type_return, method, type_subject##_##method, __VA_ARGS__) @@ -226,42 +219,44 @@ namespace sampsharp /// proxy for event dispatcher functions and function to get the event dispatcher #define PROXY_EVENT_DISPATCHER(type_subject, type_handler, method) \ - PROXY(type_subject, IEventDispatcher&, method); + PROXY(type_subject, IEventDispatcher &, method); /// proxy for event dispatcher functions and function to get the event dispatcher wit specific handler name #define PROXY_EVENT_DISPATCHER_NAMED(type_subject, handler_type, handler_name, method) \ - PROXY(type_subject, IEventDispatcher&, method); + PROXY(type_subject, IEventDispatcher &, method); /// proxy for event dispatcher functions and function to get the event dispatcher #define PROXY_INDEXED_EVENT_DISPATCHER(type_subject, type_handler, method) \ - PROXY(type_subject, IIndexedEventDispatcher&, method); + PROXY(type_subject, IIndexedEventDispatcher &, method); -/// start of event handler proxy class -#define PROXY_EVENT_HANDLER_BEGIN(handler_type) \ - class handler_type##Impl final : handler_type { +/// start of event handler proxy class +#define PROXY_EVENT_HANDLER_BEGIN(handler_type) \ + class handler_type##Impl final : handler_type \ + { /// end of event handler proxy class + functions for creating/destroying proxy -#define PROXY_EVENT_HANDLER_END(handler_type, ...) \ - public: \ - handler_type##Impl(_EXPAND_ARG(void**, __VA_ARGS__)) : \ - _EXPAND_INIT(__VA_ARGS__) { } \ - }; \ - extern "C" SDK_EXPORT handler_type##Impl* __CDECL handler_type##Impl_create(_EXPAND_ARG(void**, __VA_ARGS__)) \ - { \ - return new handler_type##Impl(_EXPAND_ARG(,##__VA_ARGS__)); \ - } \ - extern "C" SDK_EXPORT void __CDECL handler_type##Impl_delete(handler_type##Impl* handler) \ - { \ - delete handler; \ +#define PROXY_EVENT_HANDLER_END(handler_type, ...) \ +public: \ + handler_type##Impl(_EXPAND_ARG(void **, __VA_ARGS__)) : _EXPAND_INIT(__VA_ARGS__) {} \ + } \ + ; \ + extern "C" SDK_EXPORT handler_type##Impl *__CDECL handler_type##Impl_create(_EXPAND_ARG(void **, __VA_ARGS__)) \ + { \ + return new handler_type##Impl(_EXPAND_ARG(, ##__VA_ARGS__)); \ + } \ + extern "C" SDK_EXPORT void __CDECL handler_type##Impl_delete(handler_type##Impl *handler) \ + { \ + delete handler; \ } /// event handler function in event handler proxy class -#define PROXY_EVENT_HANDLER_EVENT(type_return, name, ...) \ - private: \ - typedef type_return(API_CALLTYPE * name##_fn)(_EXPAND_PARAM(, , __VA_ARGS__)); \ - void** name##_ = nullptr; \ - public: \ - type_return name(_EXPAND_PARAM(, , __VA_ARGS__)) override \ - { \ - return ((name##_fn)name##_)(_EXPAND_ARG(,##__VA_ARGS__)); \ +#define PROXY_EVENT_HANDLER_EVENT(type_return, name, ...) \ +private: \ + typedef type_return(API_CALLTYPE *name##_fn)(_EXPAND_PARAM(, , __VA_ARGS__)); \ + void **name##_ = nullptr; \ + \ +public: \ + type_return name(_EXPAND_PARAM(, , __VA_ARGS__)) override \ + { \ + return ((name##_fn)name##_)(_EXPAND_ARG(, ##__VA_ARGS__)); \ } diff --git a/src/sampsharp-component/sampsharp-component.cpp b/src/sampsharp-component/sampsharp-component.cpp index f1f84945..944eb0dd 100644 --- a/src/sampsharp-component/sampsharp-component.cpp +++ b/src/sampsharp-component/sampsharp-component.cpp @@ -6,9 +6,18 @@ #define CFG_ASSEMBLY "sampsharp.assembly" #define CFG_ENTRY_POINT_TYPE "sampsharp.entry_point_type" #define CFG_ENTRY_POINT_METHOD "sampsharp.entry_point_method" -#define CFG_CLEANUP_METHOD "sampsharp.cleanup_method" #define CFG_DISABLE_CRASH_HANDLER "sampsharp.disable_crash_handler" +static void __CDECL __setOnCleanup(void **cb) +{ + SampSharpComponent::getInstance()->setOnCleanup((on_cleanup_fn)cb); +} + +static void __CDECL __setOnFreeComponent(void **cb) +{ + SampSharpComponent::getInstance()->setOnFreeComponent((on_free_component_fn)cb); +} + StringView SampSharpComponent::componentName() const { return "SampSharp"; @@ -16,60 +25,61 @@ StringView SampSharpComponent::componentName() const SemanticVersion SampSharpComponent::componentVersion() const { - return { VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_BUILD }; + return {VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_BUILD}; } -void SampSharpComponent::onLoad(ICore* c) +void SampSharpComponent::onLoad(ICore *c) { core_ = c; bool disableCrashHandler = *c->getConfig().getBool(CFG_DISABLE_CRASH_HANDLER); - if(!disableCrashHandler) { + if (!disableCrashHandler) + { sampsharp::crash::install(c); } } -void SampSharpComponent::provideConfiguration(ILogger& logger, IEarlyConfig& config, const bool defaults) +void SampSharpComponent::provideConfiguration(ILogger &logger, IEarlyConfig &config, const bool defaults) { - #define initConfigString(key, value) \ - if(defaults || config.getType(key) == ConfigOptionType_None) { \ - config.setString(key, value); \ - } - +#define initConfigString(key, value) \ + if (defaults || config.getType(key) == ConfigOptionType_None) \ + { \ + config.setString(key, value); \ + } + initConfigString(CFG_DIRECTORY, "gamemode"); initConfigString(CFG_ASSEMBLY, "GameMode"); initConfigString(CFG_ENTRY_POINT_TYPE, "SampSharp.Entrypoint"); initConfigString(CFG_ENTRY_POINT_METHOD, "Initialize"); - initConfigString(CFG_CLEANUP_METHOD, "Cleanup"); - if(defaults || config.getType(CFG_DISABLE_CRASH_HANDLER) == ConfigOptionType_None) { - config.setBool(CFG_DISABLE_CRASH_HANDLER, false); + if (defaults || config.getType(CFG_DISABLE_CRASH_HANDLER) == ConfigOptionType_None) + { + config.setBool(CFG_DISABLE_CRASH_HANDLER, false); } } -void SampSharpComponent::onInit(IComponentList* components) +void SampSharpComponent::onInit(IComponentList *components) { - const IConfig& config = core_->getConfig(); + const IConfig &config = core_->getConfig(); const auto directory = config.getString(CFG_DIRECTORY); const auto assembly = config.getString(CFG_ASSEMBLY); const auto entry_point_type = config.getString(CFG_ENTRY_POINT_TYPE); const auto entry_point_method = config.getString(CFG_ENTRY_POINT_METHOD); - const auto cleanup_method = config.getString(CFG_CLEANUP_METHOD); std::string entry_point = entry_point_type.to_string() + ", " + assembly.to_string(); const auto full_entry_point = StringView(entry_point); - const char * error = nullptr; - - if(!managed_host_.initialize(&error)) + const char *error = nullptr; + + if (!managed_host_.initialize(&error)) { core_->logLn(Error, "Failed to initialize the .NET host framework resolver. Has the .NET runtime been installed?"); core_->logLn(Error, "Error message: %s", error); return; } - if(!managed_host_.loadFor(directory, assembly, &error)) + if (!managed_host_.loadFor(directory, assembly, &error)) { core_->logLn(Error, "Failed to initialize the .NET runtime for '%s/%s'. Is the '*.runtimeconfig.json' file available? Is the .NET runtime available?", directory.to_string().c_str(), assembly.to_string().c_str()); core_->logLn(Error, "Error message: %s", error); @@ -77,23 +87,21 @@ void SampSharpComponent::onInit(IComponentList* components) } on_init_fn on_init; - if(!managed_host_.getEntryPoint(full_entry_point, entry_point_method, reinterpret_cast(&on_init), &error)) + if (!managed_host_.getEntryPoint(full_entry_point, entry_point_method, reinterpret_cast(&on_init), &error)) { core_->logLn(Error, "The entrypoint '%s.%s, %s' could not be found.", entry_point_type.to_string().c_str(), entry_point_method.to_string().c_str(), assembly.to_string().c_str()); core_->logLn(Error, "Error message: %s", error); return; } - - if(!managed_host_.getEntryPoint(full_entry_point, cleanup_method, reinterpret_cast(&on_cleanup_), &error)) - { - core_->logLn(Error, "The entrypoint '%s.%s, %s' could not be found.", entry_point_type.to_string().c_str(), cleanup_method.to_string().c_str(), assembly.to_string().c_str()); - core_->logLn(Error, "Error message: %s", error); - return; - } - SampSharpInfo info { VERSION_API, componentVersion() }; - SampSharpInitParams init { core_, components, &info }; - + SampSharpInfo info{VERSION_API, componentVersion()}; + SampSharpInitParams init{ + core_, + components, + &info, + __setOnCleanup, + __setOnFreeComponent}; + on_init(init); } @@ -103,23 +111,33 @@ void SampSharpComponent::onReady() void SampSharpComponent::free() { + // for debug purpose: print pointer to core_ as hex + core_->logLn(Debug, "SampSharpComponent::free() called. Core pointer: 0x%p", core_); if (on_cleanup_) { on_cleanup_(); } - + delete this; } +void SampSharpComponent::onFree(IComponent *component) +{ + if (on_free_component_) + { + on_free_component_(component); + } +} + void SampSharpComponent::reset() { } -SampSharpComponent* SampSharpComponent::getInstance() +SampSharpComponent *SampSharpComponent::getInstance() { if (instance_ == nullptr) { instance_ = new SampSharpComponent(); } return instance_; -} +} \ No newline at end of file diff --git a/src/sampsharp-component/sampsharp-component.hpp b/src/sampsharp-component/sampsharp-component.hpp index c0dc7401..9707e26a 100644 --- a/src/sampsharp-component/sampsharp-component.hpp +++ b/src/sampsharp-component/sampsharp-component.hpp @@ -3,40 +3,50 @@ #include #include "managed-host.hpp" +#include "platform.hpp" struct SampSharpInfo { - SampSharpInfo(int api_version, SemanticVersion version) : - size(sizeof(SampSharpInfo)), - api_version(api_version), - version(version) { } + SampSharpInfo(int api_version, SemanticVersion version) : size(sizeof(SampSharpInfo)), + api_version(api_version), + version(version) {} // sizeof(SampSharpInfo) for backwards compatibility - size_t size; + size_t size; // version of SampSharp component <> hosted API. Version mismatch will cause launch failure. - int api_version; + int api_version; // version of the SampSharp component - SemanticVersion version; + SemanticVersion version; }; +typedef void(API_CALLTYPE *on_cleanup_fn)(); +typedef void(API_CALLTYPE *on_free_component_fn)(IComponent *component); + +typedef void(API_CALLTYPE *configure_callback_fn)(void **cb); struct SampSharpInitParams { - SampSharpInitParams(ICore * core, IComponentList * componentList, SampSharpInfo * info) : - size(sizeof(SampSharpInitParams)), - info(info), - core(core), - componentList(componentList) { } + SampSharpInitParams(ICore *core, + IComponentList *componentList, + SampSharpInfo *info, + configure_callback_fn setOnCleanup, + configure_callback_fn setOnFreeComponent) : size(sizeof(SampSharpInitParams)), + info(info), + core(core), + componentList(componentList), + setOnCleanup(setOnCleanup), + setOnFreeComponent(setOnFreeComponent) {} // sizeof(SampSharpInitParams) for backwards compatibility - size_t size; - SampSharpInfo * info; - ICore * core; - IComponentList * componentList; + size_t size; + SampSharpInfo *info; + ICore *core; + IComponentList *componentList; + configure_callback_fn setOnCleanup; + configure_callback_fn setOnFreeComponent; }; -typedef void (CORECLR_DELEGATE_CALLTYPE *on_init_fn)(SampSharpInitParams); -typedef void (CORECLR_DELEGATE_CALLTYPE *on_cleanup_fn)(); +typedef void(CORECLR_DELEGATE_CALLTYPE *on_init_fn)(SampSharpInitParams); struct ISampSharpComponent : IComponent { @@ -47,27 +57,34 @@ class SampSharpComponent final : public ISampSharpComponent { private: - ICore * core_ = nullptr; - ManagedHost managed_host_ {}; - inline static SampSharpComponent * instance_ = nullptr; + ICore *core_ = nullptr; + ManagedHost managed_host_{}; + inline static SampSharpComponent *instance_ = nullptr; on_cleanup_fn on_cleanup_ = nullptr; + on_free_component_fn on_free_component_ = nullptr; public: StringView componentName() const override; SemanticVersion componentVersion() const override; - void onLoad(ICore * c) override; + void onLoad(ICore *c) override; + + void provideConfiguration(ILogger &logger, IEarlyConfig &config, bool defaults) override; - void provideConfiguration(ILogger & logger, IEarlyConfig & config, bool defaults) override; - - void onInit(IComponentList * components) override; + void onInit(IComponentList *components) override; void onReady() override; void free() override; + void onFree(IComponent *component) override; + void reset() override; - - static SampSharpComponent * getInstance(); + + void setOnCleanup(on_cleanup_fn cb) { on_cleanup_ = cb; } + + void setOnFreeComponent(on_free_component_fn cb) { on_free_component_ = cb; } + + static SampSharpComponent *getInstance(); }; From 7eb83a4163c22405ce1c9a9f3981ac27c9443a2d Mon Sep 17 00:00:00 2001 From: Tim Potze Date: Tue, 12 May 2026 23:39:30 +0200 Subject: [PATCH 2/4] undo some formatting changes --- src/sampsharp-component/proxy-api.hpp | 177 +++++++++--------- .../sampsharp-component.cpp | 58 +++--- .../sampsharp-component.hpp | 59 +++--- 3 files changed, 137 insertions(+), 157 deletions(-) diff --git a/src/sampsharp-component/proxy-api.hpp b/src/sampsharp-component/proxy-api.hpp index 1697a875..e2fcccc9 100644 --- a/src/sampsharp-component/proxy-api.hpp +++ b/src/sampsharp-component/proxy-api.hpp @@ -23,16 +23,16 @@ namespace sampsharp { template - [[noreturn]] inline T proxy_default_unsupported(const char *name) + [[noreturn]] inline T proxy_default_unsupported(const char* name) { std::fprintf(stderr, - "sampsharp: PROXY call with null subject returning an unsupported type for '%s'. Aborting.\n", - name); + "sampsharp: PROXY call with null subject returning an unsupported type for '%s'. Aborting.\n", + name); std::terminate(); } template - inline T proxy_default(const char *name) + inline T proxy_default(const char* name) { if constexpr (std::is_void_v) { @@ -60,8 +60,8 @@ namespace sampsharp // // expand variadic args as a numbered parameter list. e.g. _EXPAND_PARAM(a, b, X, Y) -> aXb _2, aYb _1 -#define _EXPAND_PARAM(prefix, postfix, ...) _EXPAND_PARAM_N(__VA_ARGS__, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(prefix, postfix, ##__VA_ARGS__) -#define _EXPAND_PARAM_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_PARAM##n +#define _EXPAND_PARAM(prefix,postfix,...) _EXPAND_PARAM_N(__VA_ARGS__,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(prefix,postfix,##__VA_ARGS__) +#define _EXPAND_PARAM_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_PARAM ## n #define _EXPAND_PARAM1(prefix, postfix, type, ...) prefix##type##postfix _1 #define _EXPAND_PARAM2(prefix, postfix, type, ...) prefix##type##postfix _2, _EXPAND_PARAM1(prefix, postfix, ##__VA_ARGS__) #define _EXPAND_PARAM3(prefix, postfix, type, ...) prefix##type##postfix _3, _EXPAND_PARAM2(prefix, postfix, ##__VA_ARGS__) @@ -89,37 +89,37 @@ namespace sampsharp #define _EXPAND_PARAM25(prefix, postfix, type, ...) prefix##type##postfix _25, _EXPAND_PARAM24(prefix, postfix, ##__VA_ARGS__) // expand variadic args as a numbered argument list. e.g. _EXPAND_ARG(,X, Y) -> _2, _1 -#define _EXPAND_ARG(prefix, ...) _EXPAND_ARG_N(__VA_ARGS__, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_ARG##n -#define _EXPAND_ARG1(prefix, type, ...) prefix _1 -#define _EXPAND_ARG2(prefix, type, ...) prefix _2, _EXPAND_ARG1(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG3(prefix, type, ...) prefix _3, _EXPAND_ARG2(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG4(prefix, type, ...) prefix _4, _EXPAND_ARG3(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG5(prefix, type, ...) prefix _5, _EXPAND_ARG4(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG6(prefix, type, ...) prefix _6, _EXPAND_ARG5(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG7(prefix, type, ...) prefix _7, _EXPAND_ARG6(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG8(prefix, type, ...) prefix _8, _EXPAND_ARG7(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG9(prefix, type, ...) prefix _9, _EXPAND_ARG8(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG10(prefix, type, ...) prefix _10, _EXPAND_ARG9(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG11(prefix, type, ...) prefix _11, _EXPAND_ARG10(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG12(prefix, type, ...) prefix _12, _EXPAND_ARG11(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG13(prefix, type, ...) prefix _13, _EXPAND_ARG12(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG14(prefix, type, ...) prefix _14, _EXPAND_ARG13(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG15(prefix, type, ...) prefix _15, _EXPAND_ARG14(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG16(prefix, type, ...) prefix _16, _EXPAND_ARG15(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG17(prefix, type, ...) prefix _17, _EXPAND_ARG16(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG18(prefix, type, ...) prefix _18, _EXPAND_ARG17(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG19(prefix, type, ...) prefix _19, _EXPAND_ARG18(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG20(prefix, type, ...) prefix _20, _EXPAND_ARG19(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG21(prefix, type, ...) prefix _21, _EXPAND_ARG20(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG22(prefix, type, ...) prefix _22, _EXPAND_ARG21(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG23(prefix, type, ...) prefix _23, _EXPAND_ARG22(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG24(prefix, type, ...) prefix _24, _EXPAND_ARG23(prefix, ##__VA_ARGS__) -#define _EXPAND_ARG25(prefix, type, ...) prefix _25, _EXPAND_ARG24(prefix, ##__VA_ARGS__) +#define _EXPAND_ARG(prefix, ...) _EXPAND_ARG_N(__VA_ARGS__,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(prefix,##__VA_ARGS__) +#define _EXPAND_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_ARG ## n +#define _EXPAND_ARG1(prefix,type, ...) prefix _1 +#define _EXPAND_ARG2(prefix,type, ...) prefix _2, _EXPAND_ARG1(prefix,##__VA_ARGS__) +#define _EXPAND_ARG3(prefix,type, ...) prefix _3, _EXPAND_ARG2(prefix,##__VA_ARGS__) +#define _EXPAND_ARG4(prefix,type, ...) prefix _4, _EXPAND_ARG3(prefix,##__VA_ARGS__) +#define _EXPAND_ARG5(prefix,type, ...) prefix _5, _EXPAND_ARG4(prefix,##__VA_ARGS__) +#define _EXPAND_ARG6(prefix,type, ...) prefix _6, _EXPAND_ARG5(prefix,##__VA_ARGS__) +#define _EXPAND_ARG7(prefix,type, ...) prefix _7, _EXPAND_ARG6(prefix,##__VA_ARGS__) +#define _EXPAND_ARG8(prefix,type, ...) prefix _8, _EXPAND_ARG7(prefix,##__VA_ARGS__) +#define _EXPAND_ARG9(prefix,type, ...) prefix _9, _EXPAND_ARG8(prefix,##__VA_ARGS__) +#define _EXPAND_ARG10(prefix,type, ...) prefix _10, _EXPAND_ARG9(prefix,##__VA_ARGS__) +#define _EXPAND_ARG11(prefix,type, ...) prefix _11, _EXPAND_ARG10(prefix,##__VA_ARGS__) +#define _EXPAND_ARG12(prefix,type, ...) prefix _12, _EXPAND_ARG11(prefix,##__VA_ARGS__) +#define _EXPAND_ARG13(prefix,type, ...) prefix _13, _EXPAND_ARG12(prefix,##__VA_ARGS__) +#define _EXPAND_ARG14(prefix,type, ...) prefix _14, _EXPAND_ARG13(prefix,##__VA_ARGS__) +#define _EXPAND_ARG15(prefix,type, ...) prefix _15, _EXPAND_ARG14(prefix,##__VA_ARGS__) +#define _EXPAND_ARG16(prefix,type, ...) prefix _16, _EXPAND_ARG15(prefix,##__VA_ARGS__) +#define _EXPAND_ARG17(prefix,type, ...) prefix _17, _EXPAND_ARG16(prefix,##__VA_ARGS__) +#define _EXPAND_ARG18(prefix,type, ...) prefix _18, _EXPAND_ARG17(prefix,##__VA_ARGS__) +#define _EXPAND_ARG19(prefix,type, ...) prefix _19, _EXPAND_ARG18(prefix,##__VA_ARGS__) +#define _EXPAND_ARG20(prefix,type, ...) prefix _20, _EXPAND_ARG19(prefix,##__VA_ARGS__) +#define _EXPAND_ARG21(prefix,type, ...) prefix _21, _EXPAND_ARG20(prefix,##__VA_ARGS__) +#define _EXPAND_ARG22(prefix,type, ...) prefix _22, _EXPAND_ARG21(prefix,##__VA_ARGS__) +#define _EXPAND_ARG23(prefix,type, ...) prefix _23, _EXPAND_ARG22(prefix,##__VA_ARGS__) +#define _EXPAND_ARG24(prefix,type, ...) prefix _24, _EXPAND_ARG23(prefix,##__VA_ARGS__) +#define _EXPAND_ARG25(prefix,type, ...) prefix _25, _EXPAND_ARG24(prefix,##__VA_ARGS__) /// expand variadic args as a numbered initializer list. e.g. _EXPAND_INIT(X, Y) -> X_(_2), Y_(_1) -#define _EXPAND_INIT(...) _EXPAND_INIT_N(__VA_ARGS__, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(__VA_ARGS__) -#define _EXPAND_INIT_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_INIT##n +#define _EXPAND_INIT(...) _EXPAND_INIT_N(__VA_ARGS__,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__) +#define _EXPAND_INIT_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, n, ...) _EXPAND_INIT ## n #define _EXPAND_INIT1(type, ...) type##_(_1) #define _EXPAND_INIT2(type, ...) type##_(_2), _EXPAND_INIT1(__VA_ARGS__) #define _EXPAND_INIT3(type, ...) type##_(_3), _EXPAND_INIT2(__VA_ARGS__) @@ -146,53 +146,46 @@ namespace sampsharp #define _EXPAND_INIT24(type, ...) type##_(_24), _EXPAND_INIT23(__VA_ARGS__) #define _EXPAND_INIT25(type, ...) type##_(_25), _EXPAND_INIT24(__VA_ARGS__) -#define __PROXY_IMPL(type_subject, type_return, method, proxy_name, ...) \ - extern "C" SDK_EXPORT type_return __CDECL \ - proxy_name(type_subject *subject __VA_OPT__(, _EXPAND_PARAM(, , ##__VA_ARGS__))) \ - { \ - if (!subject) \ - { \ - return ::sampsharp::proxy_default(#proxy_name); \ - } \ - return subject->method( \ - __VA_OPT__(_EXPAND_ARG(, ##__VA_ARGS__))); \ +#define __PROXY_IMPL(type_subject, type_return, method, proxy_name, ...) \ + extern "C" SDK_EXPORT type_return __CDECL \ + proxy_name(type_subject * subject __VA_OPT__(, _EXPAND_PARAM(,,##__VA_ARGS__))) \ + { \ + if (!subject) { return ::sampsharp::proxy_default(#proxy_name); } \ + return subject -> method ( \ + __VA_OPT__(_EXPAND_ARG(,##__VA_ARGS__)) \ + ); \ } -#define __PROXY_IMPL_RESULT_PTR(type_subject, type_return, method, proxy_name, ...) \ - extern "C" SDK_EXPORT void __CDECL \ - proxy_name(type_subject *subject __VA_OPT__(, _EXPAND_PARAM(, , __VA_ARGS__)), type_return *result) \ - { \ - if (!subject) \ - { \ - if (result) \ - { \ - *result = type_return{}; \ - } \ - return; \ - } \ - *result = subject->method( \ - __VA_OPT__(_EXPAND_ARG(, ##__VA_ARGS__))); \ +#define __PROXY_IMPL_RESULT_PTR(type_subject, type_return, method, proxy_name, ...) \ + extern "C" SDK_EXPORT void __CDECL \ + proxy_name(type_subject * subject __VA_OPT__(, _EXPAND_PARAM(,,__VA_ARGS__)), type_return * result) \ + { \ + if (!subject) { if (result) { *result = type_return{}; } return; } \ + *result = subject -> method ( \ + __VA_OPT__(_EXPAND_ARG(,##__VA_ARGS__)) \ + ); \ } // // macros for definition of exported proxy functions // + #define __PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name) \ - extern "C" SDK_EXPORT type_to *__CDECL \ - cast_##type_from_name##_to_##type_to_name(type_from *from) \ - { \ - return static_cast(from); \ + extern "C" SDK_EXPORT type_to * __CDECL \ + cast_##type_from_name##_to_##type_to_name(type_from * from) \ + { \ + return static_cast(from); \ } /// proxy function for casting from one type to another and vice versa e.g. PROXY_CAST_NAMED(IFoo, foo, IBar, bar) -> IBar * cast_foo_to_bar(IFoo * from) { return static_cast(from); } #define PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name) \ - __PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name); \ + __PROXY_CAST_NAMED(type_from, type_from_name, type_to, type_to_name); \ __PROXY_CAST_NAMED(type_to, type_to_name, type_from, type_from_name) /// proxy function for casting from one type to another e.g. PROXY_CAST(IFoo, IBar) -> IBar * cast_IFoo_to_IBar(IFoo * from) { return static_cast(from); } #define PROXY_CAST(type_from, type_to) PROXY_CAST_NAMED(type_from, type_from, type_to, type_to) - + /// proxy function macro. e.g. PROXY(subj, int, foo, bool) -> int subj_foo(subj * x, bool _1) { return x->foo(_1); } #define PROXY(type_subject, type_return, method, ...) __PROXY_IMPL(type_subject, type_return, method, type_subject##_##method, __VA_ARGS__) @@ -219,44 +212,42 @@ namespace sampsharp /// proxy for event dispatcher functions and function to get the event dispatcher #define PROXY_EVENT_DISPATCHER(type_subject, type_handler, method) \ - PROXY(type_subject, IEventDispatcher &, method); + PROXY(type_subject, IEventDispatcher&, method); /// proxy for event dispatcher functions and function to get the event dispatcher wit specific handler name #define PROXY_EVENT_DISPATCHER_NAMED(type_subject, handler_type, handler_name, method) \ - PROXY(type_subject, IEventDispatcher &, method); + PROXY(type_subject, IEventDispatcher&, method); /// proxy for event dispatcher functions and function to get the event dispatcher #define PROXY_INDEXED_EVENT_DISPATCHER(type_subject, type_handler, method) \ - PROXY(type_subject, IIndexedEventDispatcher &, method); + PROXY(type_subject, IIndexedEventDispatcher&, method); -/// start of event handler proxy class -#define PROXY_EVENT_HANDLER_BEGIN(handler_type) \ - class handler_type##Impl final : handler_type \ - { +/// start of event handler proxy class +#define PROXY_EVENT_HANDLER_BEGIN(handler_type) \ + class handler_type##Impl final : handler_type { /// end of event handler proxy class + functions for creating/destroying proxy -#define PROXY_EVENT_HANDLER_END(handler_type, ...) \ -public: \ - handler_type##Impl(_EXPAND_ARG(void **, __VA_ARGS__)) : _EXPAND_INIT(__VA_ARGS__) {} \ - } \ - ; \ - extern "C" SDK_EXPORT handler_type##Impl *__CDECL handler_type##Impl_create(_EXPAND_ARG(void **, __VA_ARGS__)) \ - { \ - return new handler_type##Impl(_EXPAND_ARG(, ##__VA_ARGS__)); \ - } \ - extern "C" SDK_EXPORT void __CDECL handler_type##Impl_delete(handler_type##Impl *handler) \ - { \ - delete handler; \ +#define PROXY_EVENT_HANDLER_END(handler_type, ...) \ + public: \ + handler_type##Impl(_EXPAND_ARG(void**, __VA_ARGS__)) : \ + _EXPAND_INIT(__VA_ARGS__) { } \ + }; \ + extern "C" SDK_EXPORT handler_type##Impl* __CDECL handler_type##Impl_create(_EXPAND_ARG(void**, __VA_ARGS__)) \ + { \ + return new handler_type##Impl(_EXPAND_ARG(,##__VA_ARGS__)); \ + } \ + extern "C" SDK_EXPORT void __CDECL handler_type##Impl_delete(handler_type##Impl* handler) \ + { \ + delete handler; \ } /// event handler function in event handler proxy class -#define PROXY_EVENT_HANDLER_EVENT(type_return, name, ...) \ -private: \ - typedef type_return(API_CALLTYPE *name##_fn)(_EXPAND_PARAM(, , __VA_ARGS__)); \ - void **name##_ = nullptr; \ - \ -public: \ - type_return name(_EXPAND_PARAM(, , __VA_ARGS__)) override \ - { \ - return ((name##_fn)name##_)(_EXPAND_ARG(, ##__VA_ARGS__)); \ +#define PROXY_EVENT_HANDLER_EVENT(type_return, name, ...) \ + private: \ + typedef type_return(API_CALLTYPE * name##_fn)(_EXPAND_PARAM(, , __VA_ARGS__)); \ + void** name##_ = nullptr; \ + public: \ + type_return name(_EXPAND_PARAM(, , __VA_ARGS__)) override \ + { \ + return ((name##_fn)name##_)(_EXPAND_ARG(,##__VA_ARGS__)); \ } diff --git a/src/sampsharp-component/sampsharp-component.cpp b/src/sampsharp-component/sampsharp-component.cpp index 944eb0dd..93917c69 100644 --- a/src/sampsharp-component/sampsharp-component.cpp +++ b/src/sampsharp-component/sampsharp-component.cpp @@ -25,42 +25,39 @@ StringView SampSharpComponent::componentName() const SemanticVersion SampSharpComponent::componentVersion() const { - return {VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_BUILD}; + return { VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_BUILD }; } -void SampSharpComponent::onLoad(ICore *c) +void SampSharpComponent::onLoad(ICore* c) { core_ = c; bool disableCrashHandler = *c->getConfig().getBool(CFG_DISABLE_CRASH_HANDLER); - if (!disableCrashHandler) - { + if(!disableCrashHandler) { sampsharp::crash::install(c); } } -void SampSharpComponent::provideConfiguration(ILogger &logger, IEarlyConfig &config, const bool defaults) +void SampSharpComponent::provideConfiguration(ILogger& logger, IEarlyConfig& config, const bool defaults) { -#define initConfigString(key, value) \ - if (defaults || config.getType(key) == ConfigOptionType_None) \ - { \ - config.setString(key, value); \ - } - + #define initConfigString(key, value) \ + if(defaults || config.getType(key) == ConfigOptionType_None) { \ + config.setString(key, value); \ + } + initConfigString(CFG_DIRECTORY, "gamemode"); initConfigString(CFG_ASSEMBLY, "GameMode"); initConfigString(CFG_ENTRY_POINT_TYPE, "SampSharp.Entrypoint"); initConfigString(CFG_ENTRY_POINT_METHOD, "Initialize"); - if (defaults || config.getType(CFG_DISABLE_CRASH_HANDLER) == ConfigOptionType_None) - { - config.setBool(CFG_DISABLE_CRASH_HANDLER, false); + if(defaults || config.getType(CFG_DISABLE_CRASH_HANDLER) == ConfigOptionType_None) { + config.setBool(CFG_DISABLE_CRASH_HANDLER, false); } } -void SampSharpComponent::onInit(IComponentList *components) +void SampSharpComponent::onInit(IComponentList* components) { - const IConfig &config = core_->getConfig(); + const IConfig& config = core_->getConfig(); const auto directory = config.getString(CFG_DIRECTORY); const auto assembly = config.getString(CFG_ASSEMBLY); @@ -70,16 +67,16 @@ void SampSharpComponent::onInit(IComponentList *components) std::string entry_point = entry_point_type.to_string() + ", " + assembly.to_string(); const auto full_entry_point = StringView(entry_point); - const char *error = nullptr; - - if (!managed_host_.initialize(&error)) + const char * error = nullptr; + + if(!managed_host_.initialize(&error)) { core_->logLn(Error, "Failed to initialize the .NET host framework resolver. Has the .NET runtime been installed?"); core_->logLn(Error, "Error message: %s", error); return; } - if (!managed_host_.loadFor(directory, assembly, &error)) + if(!managed_host_.loadFor(directory, assembly, &error)) { core_->logLn(Error, "Failed to initialize the .NET runtime for '%s/%s'. Is the '*.runtimeconfig.json' file available? Is the .NET runtime available?", directory.to_string().c_str(), assembly.to_string().c_str()); core_->logLn(Error, "Error message: %s", error); @@ -87,21 +84,16 @@ void SampSharpComponent::onInit(IComponentList *components) } on_init_fn on_init; - if (!managed_host_.getEntryPoint(full_entry_point, entry_point_method, reinterpret_cast(&on_init), &error)) + if(!managed_host_.getEntryPoint(full_entry_point, entry_point_method, reinterpret_cast(&on_init), &error)) { core_->logLn(Error, "The entrypoint '%s.%s, %s' could not be found.", entry_point_type.to_string().c_str(), entry_point_method.to_string().c_str(), assembly.to_string().c_str()); core_->logLn(Error, "Error message: %s", error); return; } - SampSharpInfo info{VERSION_API, componentVersion()}; - SampSharpInitParams init{ - core_, - components, - &info, - __setOnCleanup, - __setOnFreeComponent}; - + SampSharpInfo info { VERSION_API, componentVersion() }; + SampSharpInitParams init { core_, components, &info, __setOnCleanup, __setOnFreeComponent }; + on_init(init); } @@ -111,13 +103,11 @@ void SampSharpComponent::onReady() void SampSharpComponent::free() { - // for debug purpose: print pointer to core_ as hex - core_->logLn(Debug, "SampSharpComponent::free() called. Core pointer: 0x%p", core_); if (on_cleanup_) { on_cleanup_(); } - + delete this; } @@ -133,11 +123,11 @@ void SampSharpComponent::reset() { } -SampSharpComponent *SampSharpComponent::getInstance() +SampSharpComponent* SampSharpComponent::getInstance() { if (instance_ == nullptr) { instance_ = new SampSharpComponent(); } return instance_; -} \ No newline at end of file +} diff --git a/src/sampsharp-component/sampsharp-component.hpp b/src/sampsharp-component/sampsharp-component.hpp index 9707e26a..40095753 100644 --- a/src/sampsharp-component/sampsharp-component.hpp +++ b/src/sampsharp-component/sampsharp-component.hpp @@ -7,16 +7,17 @@ struct SampSharpInfo { - SampSharpInfo(int api_version, SemanticVersion version) : size(sizeof(SampSharpInfo)), - api_version(api_version), - version(version) {} + SampSharpInfo(int api_version, SemanticVersion version) : + size(sizeof(SampSharpInfo)), + api_version(api_version), + version(version) { } // sizeof(SampSharpInfo) for backwards compatibility - size_t size; + size_t size; // version of SampSharp component <> hosted API. Version mismatch will cause launch failure. - int api_version; + int api_version; // version of the SampSharp component - SemanticVersion version; + SemanticVersion version; }; typedef void(API_CALLTYPE *on_cleanup_fn)(); @@ -24,29 +25,27 @@ typedef void(API_CALLTYPE *on_free_component_fn)(IComponent *component); typedef void(API_CALLTYPE *configure_callback_fn)(void **cb); + struct SampSharpInitParams { - SampSharpInitParams(ICore *core, - IComponentList *componentList, - SampSharpInfo *info, - configure_callback_fn setOnCleanup, - configure_callback_fn setOnFreeComponent) : size(sizeof(SampSharpInitParams)), - info(info), - core(core), - componentList(componentList), - setOnCleanup(setOnCleanup), - setOnFreeComponent(setOnFreeComponent) {} + SampSharpInitParams(ICore * core, IComponentList * componentList, SampSharpInfo * info, configure_callback_fn setOnCleanup, configure_callback_fn setOnFreeComponent) : + size(sizeof(SampSharpInitParams)), + info(info), + core(core), + componentList(componentList), + setOnCleanup(setOnCleanup), + setOnFreeComponent(setOnFreeComponent) { } // sizeof(SampSharpInitParams) for backwards compatibility - size_t size; - SampSharpInfo *info; - ICore *core; - IComponentList *componentList; + size_t size; + SampSharpInfo * info; + ICore * core; + IComponentList * componentList; configure_callback_fn setOnCleanup; configure_callback_fn setOnFreeComponent; }; -typedef void(CORECLR_DELEGATE_CALLTYPE *on_init_fn)(SampSharpInitParams); +typedef void (CORECLR_DELEGATE_CALLTYPE *on_init_fn)(SampSharpInitParams); struct ISampSharpComponent : IComponent { @@ -57,9 +56,9 @@ class SampSharpComponent final : public ISampSharpComponent { private: - ICore *core_ = nullptr; - ManagedHost managed_host_{}; - inline static SampSharpComponent *instance_ = nullptr; + ICore * core_ = nullptr; + ManagedHost managed_host_ {}; + inline static SampSharpComponent * instance_ = nullptr; on_cleanup_fn on_cleanup_ = nullptr; on_free_component_fn on_free_component_ = nullptr; @@ -68,11 +67,11 @@ class SampSharpComponent final SemanticVersion componentVersion() const override; - void onLoad(ICore *c) override; - - void provideConfiguration(ILogger &logger, IEarlyConfig &config, bool defaults) override; + void onLoad(ICore * c) override; - void onInit(IComponentList *components) override; + void provideConfiguration(ILogger & logger, IEarlyConfig & config, bool defaults) override; + + void onInit(IComponentList * components) override; void onReady() override; @@ -85,6 +84,6 @@ class SampSharpComponent final void setOnCleanup(on_cleanup_fn cb) { on_cleanup_ = cb; } void setOnFreeComponent(on_free_component_fn cb) { on_free_component_ = cb; } - - static SampSharpComponent *getInstance(); + + static SampSharpComponent * getInstance(); }; From 343721d767cd72fff7a30ca4a50fbf4ab6561058 Mon Sep 17 00:00:00 2001 From: Tim Potze Date: Tue, 12 May 2026 23:52:02 +0200 Subject: [PATCH 3/4] update snapshots --- ...tartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs | 6 ------ ...tartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs | 6 ------ 2 files changed, 12 deletions(-) diff --git a/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.NestedNamespaceStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs b/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.NestedNamespaceStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs index 7b2b0884..6c268f4e 100644 --- a/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.NestedNamespaceStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs +++ b/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.NestedNamespaceStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs @@ -5,12 +5,6 @@ public static class Entrypoint { private static readonly global::My.Game.Server.Startup _startup = new(); private static global::SampSharp.OpenMp.Core.StartupContext _context; - [global::System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute] - public static void Cleanup() - { - _context?.InvokeCleanup(); - } - [global::System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute] public static void Initialize(global::SampSharp.OpenMp.Core.SampSharpInitParams inf) { diff --git a/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.SimpleStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs b/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.SimpleStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs index 6a56b834..6de20e28 100644 --- a/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.SimpleStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs +++ b/test/SampSharp.SourceGenerator.Tests/Snapshots/EntryPointSourceGeneratorTests.SimpleStartupClass_GeneratesEntryPoint#EntryPoint.g.verified.cs @@ -5,12 +5,6 @@ public static class Entrypoint { private static readonly global::MyGame.MyStartup _startup = new(); private static global::SampSharp.OpenMp.Core.StartupContext _context; - [global::System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute] - public static void Cleanup() - { - _context?.InvokeCleanup(); - } - [global::System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute] public static void Initialize(global::SampSharp.OpenMp.Core.SampSharpInitParams inf) { From c28d16dd43b6a72138033472f26e745df121b3bd Mon Sep 17 00:00:00 2001 From: Tim Potze Date: Tue, 12 May 2026 23:54:54 +0200 Subject: [PATCH 4/4] minor cleanup --- src/SampSharp.OpenMp.Core/StartupContext.cs | 28 ++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/SampSharp.OpenMp.Core/StartupContext.cs b/src/SampSharp.OpenMp.Core/StartupContext.cs index a93b227f..42bfa3d9 100644 --- a/src/SampSharp.OpenMp.Core/StartupContext.cs +++ b/src/SampSharp.OpenMp.Core/StartupContext.cs @@ -11,7 +11,7 @@ public sealed class StartupContext : IStartupContext // Delegates must be kept in memory to prevent GC // ReSharper disable PrivateFieldCanBeConvertedToLocalVariable private readonly Action _cleanup; - private readonly OnFreeComponent _freeComponent; + private readonly OnFreeComponentDelegate _freeComponent; // ReSharper restore PrivateFieldCanBeConvertedToLocalVariable /// @@ -41,8 +41,8 @@ public StartupContext(SampSharpInitParams init) SampSharpExceptionHandler.SetExceptionHandler(_unhandledExceptionHandler); // Keep delegates in memory to prevent GC - _cleanup = EntryOnCleanup; - _freeComponent = EntryOnFreeComponent; + _cleanup = OnCleanup; + _freeComponent = OnFreeComponent; var cleanupPtr = Marshal.GetFunctionPointerForDelegate(_cleanup); var freeComponentPtr = Marshal.GetFunctionPointerForDelegate(_freeComponent); @@ -97,16 +97,6 @@ public void InitializeUsing(IStartup configurator) Initialized?.Invoke(this, EventArgs.Empty); } - private void EntryOnCleanup() - { - Cleanup?.Invoke(this, EventArgs.Empty); - } - - private void EntryOnFreeComponent(IComponent component) - { - ComponentFreed?.Invoke(this, component); - } - /// /// Internal method. Do not invoke manually. /// @@ -142,6 +132,16 @@ private static void VersionCheck(SampSharpInitParams init) } } + private void OnCleanup() + { + Cleanup?.Invoke(this, EventArgs.Empty); + } + + private void OnFreeComponent(IComponent component) + { + ComponentFreed?.Invoke(this, component); + } + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void OnFreeComponent(IComponent component); + private delegate void OnFreeComponentDelegate(IComponent component); } \ No newline at end of file