Internal information
This section provides a high-level overview about the internal structure of the C# module and how it's playing together with the AltV server.
Important
Resource developers don't need to know the internal structure, but it is helpful sometimes. This is mainly for developers who like to contribute to the C# module.
Initialization of csharp-module
When the altv-server is starting it checks modules part of the server.toml configuration file. When there's the csharp-module specified, the server loads the "csharp-module.dll" / "libcsharp-module.so" / "csharp-module.so" (depending on operating system) from the modules folder.
In the csharp-module is a function altMain defined, which starts the .NET runtime and registers itself as script runtime for csharp resources. That's the reason you have to specify type: csharp in the resource.toml, so the altv-server knows that it should load this resource with the csharp-module.
The custom .NET host tries to find the latest .NET SDK hostfxr.dll (example path on Windows is C:\Program Files (x86)\dotnet\host\fxr\5.0.1\hostfxr.dll). When it's found, it starts AltV.Net.Host.dll which is located next to the altv-server.
Now in .NET world the AltV.Net.Host first initialize some delegates which can be triggered from the csharp-module. For example the csharp-module can trigger a delegate to start a specific resource with a name, path and a main file.
The main initialization is now done and we are waiting until a resource of type csharp should be loaded.
Summary:
altv-servercalls platform dependent csharp-modulecsharp-moduleacts as custom .NET host, starts .NET runtime withAltV.Net.Host.dllAltV.Net.Hostinitializes delegates which can be executed fromcsharp-module
Loading a resource
For every C# resource the csharp-module creates a CSharpResourceImpl. When the resource is started by the server, the class triggers AltV.Net.Host with the previous initialized ExecuteResource delegate.
There a custom AssemblyLoadContext is created, which is responsible for loading and resolving assemblies like the resource and their dependencies. The load context loads the files just from the resource folder which it is created for and is isolated from other resources.
In the end the resource assembly is loaded and the AltV.Net.dll assembly is initialized by calling the ModuleWrapper#MainWithAssembly among others.
Here the main initialization happens: The entity factories are resolved which are needed for creating the entity pools. These entity pools are storing the active entities like for example currently connected players in the player pool.
In order to receive events later from the server, it's required to set delegates which are executed on the csharp-module. This is done in CSharpResourceImpl from AltV.Net assembly. The functions which are executed are in ModuleWrapper and there the module functions are triggered.
Depending if the resource derives from Resource or AsyncResource a different module is resolved. The AsyncModule is thereby derived from Module. The module is the main class which stores all entity pools, forwards events to IScript methods and the event handlers in resources, like Alt.OnPlayerEnterVehicle and so on.
Afterwards the load context will be searched for implementations of IScript. These classes can have methods with custom attributes like ScriptEventAttribute. When specified for example ScriptEventType.PlayerConnect this method will be called every time a player connects. In order to get that working every IScript is loaded and the events registered. There are simply the Alt.On* events used (for non-async attributes). For PlayerConnect, there is an event handler for Alt.OnPlayerConnect which triggers the IScript method.
Last but not least the csharp-module is now triggering the MainDelegate which is received in the ModuleWrapper. There it just execute the OnStart method of the resource. This OnStart has every resource implemented, as it is a abstract method on the Resource class.
Summary:
altv-servercallscsharp-moduleto start resourcecsharp-modulecreatesCSharpResourceImplwhich triggersAltV.Net.HostAltV.Net.Hostloads resource assembly and dependencies (withAltV.Net)AltV.Netinitializes itself and resourcecsharp-moduletriggersMainDelegatewhich executes resourceOnStart
Executing commands
When executing a command like Alt.CreateVehicle the static Alt class is just a proxy for internal methods. In the end it will trigger most likely a method inside of AltNative. This is a partial class (multiple files which are combined to one class) and acts as thin wrapper for the csharp-module.
In the vehicle example AltNative.Server_CreateVehicle is executed, which is a exported function in the csharp-module. The Alt.Net assembly uses the DllImportAttribute to call the method from the native library.
Inside of the csharp-module the data is copied to internal data structures and then send to the altv-server.
Receiving events
The events are received in the csharp-module. Every resource receives most of the events in CSharpResourceImpl::OnEvent. This prepares the data and executes a method of the ModuleWrapper with a delegate previous set in the initialization.
For example for the alt::CEvent::Type::PLAYER_ENTER_VEHICLE the required data is retrieved from the event and OnPlayerEnterVehicleDelegate is executed. This delegate is part of ModuleWrapper and there directly the OnPlayerEnterVehicle method of the loaded module is executed.
From there the entites are checked if these are valid and exists on the server. In the end all registered event handler are executed, like Alt.OnPlayerEnterVehicle or ScriptEventAttribute.