Getting started
This documentation assumes you're already familiar with programming in C# to some extent.
Before anything else, make sure you have the following installed:
- FiveM
- .NET 7.0 SDK or newer (download from here)
- (Recommended) JetBrains Rider or Visual Studio
Start a new project
1. Create the Project
Create a new Class Library project in your IDE.
2. Edit the .csproj File
Next, edit your project's .csproj file to ensure it's compatible with the FiveM server runtime.
Edit -> Edit 'YourProjectName.csproj'.Edit Project File.Replace the content of the file with the following. We are changing the TargetFramework to netstandard2.0 for compatibility with the FiveM server. We also recommend setting the LangVersion to 11 or higher to use modern C# features.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>11</LangVersion>
</PropertyGroup>
</Project>3. Add Dependencies
Your project needs two key dependencies:
- CitizenFX.Core.Server: Install the latest version from NuGet. This package provides the necessary FiveM server APIs.
- FivePD.Server.API: Add a reference to the
FivePD.Server.net.dllfile, which is located in your FivePD installation atfivepd/Libraries/FivePD.Server/. This gives you access to the FivePD-specific APIs.
4. Create Your Addon Logic
You can create different types of addons. The most common are Extensions and Callouts.
An addon can contain multiple extensions and callouts within the same project.
An IExtension is used for creating custom logic that is not a callout, such as new commands or integrations.
- Create a new class that implements the
IExtensioninterface. - Implement the required
OnStarted()andOnStopped()methods.
using FivePD.Server.API;
using FivePD.Server.Interfaces;
namespace MyAwesomeAddon;
public class MyAwesomeExtension : IExtension
{
private readonly IAddonLoggerService _logger;
public MyAwesomeExtension(IAddonLoggerService logger)
{
this._logger = logger;
}
public Task OnStarted()
{
this._logger.Information("MyAwesomeExtension has been started!");
return Task.CompletedTask;
}
public Task OnStopped()
{
this._logger.Information("MyAwesomeExtension has been stopped!");
return Task.CompletedTask;
}
}A Callout is a dispatchable mission for players.
- Create a new class that inherits from the
Calloutbase class. - Implement the required methods to define the callout's behavior.
using System.Collections.Generic;
using System.Threading.Tasks;
using CitizenFX.Core;
using FivePD.Server.API;
using FivePD.Server.EntityWrappers;
using FivePD.Server.Interfaces.Addons;
using FivePD.Server.Models;
using FivePD.Common.Enums;
namespace MyAwesomeAddon;
public class MyAwesomeCallout : Callout
{
private readonly IAddonLoggerService _logger;
public MyAwesomeCallout(IAddonLoggerService logger)
{
this._logger = logger;
}
public override Task<CalloutSetupProperties> Setup()
{
return Task.FromResult(new CalloutSetupProperties
{
Title = "Sample Callout Title",
Description = "A brief description of the callout.",
ActivityRadius = 20f,
Priority = FPriority.Code3,
Location = new Vector3(723.24f, -148.43f, 50.49f),
});
}
public override Task<bool> CanBeDispatched()
{
return Task.FromResult(true);
}
public override Task OnDispatched(List<Unit> units)
{
this._logger.Information($"OnDispatched - {units.Count} units");
return Task.CompletedTask;
}
public override Task OnUnitAssigned(Unit unit)
{
this._logger.Information($"OnUnitAssigned - {unit.Callsign}");
return Task.CompletedTask;
}
public override Task OnAccepted(Unit unit)
{
this._logger.Information($"OnAccepted - {unit.Callsign}");
return Task.CompletedTask;
}
public override Task OnCompleted()
{
this._logger.Information("OnCompleted");
return Task.CompletedTask;
}
public override Task OnPlayerEnteredInActivityZone(FPlayer player)
{
this._logger.Information($"OnPlayerEnteredInActivityZone: {player.GetUnderlyingPlayer().Name}");
return Task.CompletedTask;
}
}5. Build and Deploy the Addon
FivePD addons do not require the .net.dll extension that standard FiveM resources use. Your compiled file should be named MyAwesomeAddon.dll, not MyAwesomeAddon.net.dll.
- Build your solution in Release mode.
- Navigate to your FivePD installation directory, then to
fivepd/Libraries/Addons. - Create a new folder for your addon (e.g.,
MyAwesomeAddon). - Copy the compiled
MyAwesomeAddon.dllfrom your project'sbin/Release/netstandard2.0folder into the new directory.
6. Configure the Addon Metadata
This file can be either JSON or YAML. Learn more in the File Types documentation.
Create a metadata.yaml file inside your addon's folder (MyAwesomeAddon). This file tells FivePD how to load your addon. For more details, see the Configure Your Addon page.
FriendlyName: My Awesome Addon
Version: 100
FriendlyVersion: 1.0.0
Author: Your Name
Assemblies:
- MyAwesomeAddon.dll7. Final Step
Start or restart the FivePD resource. If you have done everything correctly, you should see the following message in the server console:
Registering addon "My Awesome Addon" version 1.0.0