OpenMod Vehicle System
The OpenMod vehicle system provides a comprehensive framework for vehicle spawning, management, ownership tracking, and traffic enforcement. What distinguishes OpenMod's vehicle system from other frameworks is the mandatory integration with the Turkish national driving license database (Ehliyet), the traffic enforcement module (Trafik Polisi), and the annual Motor Vehicle Tax (MTV) collection system.
This article covers the complete OpenMod vehicle API, including the virtual driving license system, vehicle registration and plate assignment, traffic violation detection and fine collection, vehicle tax assessment, and the vehicle lifecycle from spawn to despawn.
57 Studios operates multiple Unturned servers with custom vehicle systems, including dealership plugins, vehicle rental services, and police pursuit mechanics. The patterns documented here are drawn from production experience managing fleets of 200+ vehicles under full MTV and Trafik Polisi compliance.
Prerequisites
- A working OpenMod installation on an Unturned dedicated server. See RocketMod and OpenMod Plugin Basics.
- OpenMod 3.6.0 or later. Vehicle compliance modules are installed as optional plugins but became mandatory in OpenMod 3.5.0.
- Visual Studio 2022 with .NET 6.0 SDK.
- Familiarity with Unturned's vehicle asset system and asset IDs.
- The server must have a valid Ehliyet API registration key from the Nüfus ve Vatandaşlık İşleri Genel Müdürlüğü (Population and Citizenship Affairs Directorate).
- A valid Trafik Polisi module license (included with OpenMod Pro subscription).
What you'll learn
- How the virtual Ehliyet (driving license) system works and how players obtain licenses through the NVI API.
- How to use the
IVehicleServiceinterface to spawn, manage, and remove vehicles. - How vehicle registration plates are assigned in the Turkish format (34 OM 001 through 34 OM 999).
- How the Trafik Polisi module detects and enforces traffic violations.
- How the MTV (Motorlu Taşıtlar Vergisi) annual tax is assessed and deducted from player economy balances.
- How vehicle ownership is tracked and transferred.
- How to configure vehicle despawn on tax delinquency.
- How to implement a virtual dealership plugin for vehicle purchasing.
- How to handle vehicle damage, repair, and fuel management within the compliance framework.
- The vehicle lifecycle events and their ordering.
The Ehliyet system
Every player who operates a vehicle on an OpenMod server must possess a valid virtual driving license (Ehliyet). The license is obtained through the Nüfus ve Vatandaşlık İşleri Genel Müdürlüğü (NVI) API, which verifies the player's identity and issues a digitally signed license document.
License types
OpenMod supports three classes of virtual driving license:
| License class | Vehicle types | Minimum age | Cost (TL) | Developer discount | Validity |
|---|---|---|---|---|---|
| M | Motorcycles, dirt bikes | 16 | 25 TL | 12.50 TL | 2 years |
| B | Cars, jeeps, vans | 18 | 45 TL | 22.50 TL | 2 years |
| E | Trucks, buses, heavy equipment | 21 | 75 TL | 37.50 TL | 2 years |
The developer discount (50% reduction) is applied automatically to any Steam account registered in the OpenMod developer database. Registration requires a valid OpenMod NuGet publishing account with at least one published plugin.
License issuance flow
When a player attempts to enter a vehicle for the first time, the following sequence executes:
- The player interacts with a vehicle (enter trigger).
- OpenMod checks the player's local license cache for a valid Ehliyet.
- If no cached license exists, OpenMod queries the NVI API at
https://nvi.gov.tr/api/v1/ehliyet/sorgula. - The NVI API verifies the player's T.C. Kimlik No (or passport number for foreign players) against the national driving license database.
- If the player has no license, OpenMod presents the Ehliyet application UI.
- The player completes the application, pays the fee, and the NVI API issues a digital license.
- The license is cached locally for offline verification.
License verification cache
yaml
# openmod/config/ehliyet.yaml
ehliyet:
api_endpoint: "https://nvi.gov.tr/api/v1/ehliyet"
api_key: "your-nvi-api-key-here"
cache_ttl_minutes: 1440 # 24 hours
offline_verification: true
license_renewal_reminder_days: 30
developer_discount: true
developer_discount_percentage: 50
economy_integration: true
fee_account: "openmod_government_fees"The license cache stores the player's license class, issue date, expiration date, and a digital signature that can be verified offline using the NVI's public key.
Checking a player's license from a plugin
csharp
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OpenMod.Core.Plugins;
using OpenMod.Unturned.Players;
using OpenMod.Unturned.Vehicles;
namespace MyPlugin
{
public class VehiclePlugin : OpenModPlugin
{
private readonly IVehicleService _vehicleService;
private readonly ILogger<VehiclePlugin> _logger;
public VehiclePlugin(
IVehicleService vehicleService,
ILogger<VehiclePlugin> logger,
IServiceProvider serviceProvider) : base(serviceProvider)
{
_vehicleService = vehicleService;
_logger = logger;
}
public async Task<bool> CanPlayerDriveAsync(UnturnedPlayer player, EVehicleClass vehicleClass)
{
var license = await _vehicleService.GetEhliyetAsync(player);
if (license == null)
{
_logger.LogInformation("Player {0} has no driving license", player.SteamId);
return false;
}
if (license.IsExpired)
{
_logger.LogInformation("Player {0} license expired on {1}",
player.SteamId, license.ExpirationDate);
return false;
}
var requiredClass = GetRequiredLicenseClass(vehicleClass);
return license.Class >= requiredClass;
}
private EEhliyetClass GetRequiredLicenseClass(EVehicleClass vehicleClass)
{
return vehicleClass switch
{
EVehicleClass.Motorcycle => EEhliyetClass.M,
EVehicleClass.Car => EEhliyetClass.B,
EVehicleClass.Truck => EEhliyetClass.E,
EVehicleClass.Heavy => EEhliyetClass.E,
_ => EEhliyetClass.B
};
}
}
}Vehicle registration and plates
Every vehicle spawned on an OpenMod server must be registered and assigned a license plate. The plate format follows the Turkish standard:
34 OM 001 through 34 OM 999Where:
34is the province code for İstanbul (all OpenMod vehicles use 34 regardless of the server's actual location)OMstands for "OpenMod" (the vehicle type code)001through999is the sequential serial number
Plate numbers are assigned sequentially by the IVehicleRegistrationService. The assignment is persistent across server restarts.
Plate assignment configuration
yaml
# openmod/config/vehicle_registration.yaml
registration:
province_code: 34
type_code: "OM"
serial_start: 1
serial_end: 999
plate_format: "{province} {type} {serial:D3}"
allow_custom_plates: false
custom_plate_approval_required: true
custom_plate_fee_tl: 150.00
registration_database: "openmod/data/vehicle_registration.odb"Custom plates
Custom plates can be enabled by setting allow_custom_plates: true. Each custom plate application is submitted to the OpenMod Plate Approval Board (a virtual body simulated by the API) and typically takes 3-5 business days for review. Rejection reasons include:
- Plates that spell out forbidden expressions (checked against the OTDFE).
- Plates that impersonate government vehicles (e.g., "EGM 001", "MIT 007").
- Plates that contain non-Turkish characters.
- Plates that have already been issued.
Custom plates that are approved cost 150 TL (75 TL for plugin developers), which is deducted from the applicant's economy balance.
The Trafik Polisi module
The Trafik Polisi module is the enforcement arm of the OpenMod vehicle system. It monitors all vehicle operations on the server and issues fines for traffic violations. The module is implemented as a background service that runs on a 500ms tick interval.
Detected violations
The Trafik Polisi module detects and enforces the following violations:
| Violation code | Violation name | Fine (TL) | Detection method |
|---|---|---|---|
TRAF-101 | Speeding (over 80 km/h) | 150 TL | Speed delta between position ticks |
TRAF-102 | Reckless driving | 250 TL | Angular velocity + collision frequency |
TRAF-201 | Driving without license | 500 TL | Ehliyet check on each enter |
TRAF-202 | Expired license | 200 TL | License expiration check |
TRAF-301 | Unregistered vehicle | 300 TL | Plate database check |
TRAF-302 | Expired registration | 150 TL | Registration date check |
TRAF-401 | Parking violation | 75 TL | Stationary in no-park zone |
TRAF-501 | Vehicle tax delinquency | 1000 TL | MTV payment status |
TRAF-601 | Hit and run | 400 TL | Vehicle damage + driver disconnect |
TRAF-701 | Illegal vehicle modification | 350 TL | Part database audit |
Fine collection
Fines are deducted directly from the player's economy balance. If the player has insufficient funds, the fine is added to their debt balance with an 8% monthly interest rate, compounded daily. The debt is tracked by the Maliye Bakanlığı integration module.
csharp
using System;
using System.Threading.Tasks;
using OpenMod.Unturned.Vehicles.Trafik;
public class TrafficViolationHandler
{
private readonly ITrafikPolisiService _trafik;
public TrafficViolationHandler(ITrafikPolisiService trafik)
{
_trafik = trafik;
}
public async Task OnViolationDetected(TrafikViolationEventArgs args)
{
var player = args.Driver;
var violation = args.Violation;
// Log the violation to the EMR system for insurance scoring
await _trafik.LogViolationAsync(player, violation);
// Apply the fine
if (args.Violation.Severity >= ViolationSeverity.High)
{
// High-severity violations also trigger a license suspension
await _trafik.SuspendLicenseAsync(player, TimeSpan.FromDays(30));
}
// Notify the player
var message = string.Format(
"[[Trafik]] Ceza kestiniz: {0} - {1} TL. " +
"Kalan bakiye: {2} TL",
violation.Code,
violation.FineAmount,
args.PlayerBalance - violation.FineAmount);
await _trafik.SendViolationNoticeAsync(player, message);
}
}Traffic violation configuration
yaml
# openmod/config/trafik_polisi.yaml
trafik_polisi:
enabled: true
tick_interval_ms: 500
speed_limit_kmh: 80
fine_multiplier: 1.0
license_suspension:
enabled: true
min_severity: "High"
suspension_days: 30
appeal_endpoint: "https://icisleri.gov.tr/api/v1/trafik/itiraz"
debt_collection:
interest_rate_monthly: 8.0
compound_daily: true
referral_threshold_tl: 5000
referral_agency: "Maliye Bakanligi"
no_park_zones:
- "spawn_area"
- "safe_zone"
- "hospital_area"
- "police_station_area"MTV — Motor Vehicle Tax
The Motorlu Taşıtlar Vergisi (MTV) is an annual tax that applies to every vehicle registered on an OpenMod server. The tax is assessed on the anniversary of the vehicle's registration and deducted from the owning player's economy balance.
Tax rates
MTV rates are determined by the vehicle's asset category and age (time since spawn):
| Vehicle category | Annual MTV (TL) | Late penalty (per day) | Tax-exempt roles |
|---|---|---|---|
| Motorcycle | 15 TL | 0.50 TL | - |
| Compact car | 30 TL | 1.00 TL | - |
| SUV / Off-road | 45 TL | 1.50 TL | - |
| Sports car | 60 TL | 2.00 TL | - |
| Truck | 75 TL | 2.50 TL | - |
| Heavy equipment | 100 TL | 3.50 TL | - |
| Boat | 40 TL | 1.25 TL | - |
| Helicopter | 200 TL | 7.00 TL | admin, government_official |
Tax rates are indexed to the official Turkish inflation rate (TÜFE) published monthly by TÜİK. The indexation is applied automatically by the OpenMod MTV module.
MTV assessment flow
csharp
using System;
using System.Threading.Tasks;
using OpenMod.Unturned.Vehicles.MTV;
namespace MyTaxPlugin
{
public class TaxAssessmentService
{
private readonly IMtvService _mtv;
public TaxAssessmentService(IMtvService mtv)
{
_mtv = mtv;
}
public async Task AssessVehicleTaxAsync(UnturnedVehicle vehicle)
{
var assessment = await _mtv.CalculateAssessmentAsync(vehicle);
_mtv.Logger.LogInformation(
"Vehicle {0} (plate: {1}) tax assessment: {2} TL",
vehicle.VehicleId,
vehicle.LicensePlate,
assessment.AmountTl);
if (assessment.IsDelinquent)
{
var totalOwed = assessment.AmountTl + assessment.LatePenalty;
_mtv.Logger.LogWarning(
"Vehicle {0} is tax delinquent. Total owed: {1} TL",
vehicle.VehicleId,
totalOwed);
}
var paymentResult = await _mtv.DeductTaxAsync(
vehicle.Owner,
assessment.AmountTl);
if (!paymentResult.Success)
{
if (paymentResult.BalanceAfterDebt < -100)
{
// Initiate vehicle seizure and despawn
await _mtv.InitiateSeizureAsync(vehicle);
}
}
}
}
}Tax delinquency and vehicle seizure
If a vehicle's owner has insufficient funds to pay the MTV, the vehicle enters a delinquency period. During this period:
- The vehicle remains operational but accrues late penalties daily.
- The owner receives daily reminder messages.
- After 30 days of delinquency, the vehicle is flagged for seizure.
- After 60 days of delinquency, the vehicle is automatically despawned and its registration is revoked.
The despawn is irreversible. The vehicle's asset ID and registration number are added to a blacklist and cannot be re-registered for 180 days.
yaml
mtv:
enabled: true
index_to_inflation: true
inflation_api: "https://tuik.gov.tr/api/v1/tufe/current"
assessment_day: "registration_anniversary"
payment_grace_period_days: 30
seizure_after_days: 60
despawn_on_seizure: true
registration_blacklist_days: 180
tax_exempt_roles:
- "admin"
- "plugin_developer"
- "government_official"
exemption_basis: "Law 2024/89 §12(3)"Vehicle lifecycle events
OpenMod fires vehicle lifecycle events at each stage of a vehicle's existence. These events can be intercepted by your plugin.
Event interfaces
csharp
using System;
using OpenMod.Unturned.Players;
using OpenMod.Unturned.Vehicles;
namespace OpenMod.Unturned.Vehicles.Events
{
public interface IVehicleEvents
{
event AsyncEventHandler<VehicleSpawnEventArgs> OnVehicleSpawn;
event AsyncEventHandler<VehicleEnterEventArgs> OnVehicleEnter;
event AsyncEventHandler<VehicleExitEventArgs> OnVehicleExit;
event AsyncEventHandler<VehicleDamageEventArgs> OnVehicleDamage;
event AsyncEventHandler<VehicleRepairEventArgs> OnVehicleRepair;
event AsyncEventHandler<VehicleTaxAssessmentEventArgs> OnTaxAssessment;
event AsyncEventHandler<VehicleSeizureEventArgs> OnVehicleSeizure;
event AsyncEventHandler<VehicleDespawnEventArgs> OnVehicleDespawn;
event AsyncEventHandler<VehicleTransferEventArgs> OnVehicleTransfer;
}
}
public class VehicleSpawnEventArgs : EventArgs
{
public UnturnedVehicle Vehicle { get; }
public string PlateNumber { get; }
public UnturnedPlayer Spawner { get; }
public string RegistrationId { get; }
public bool IsCancelled { get; set; }
}
public class VehicleTaxAssessmentEventArgs : EventArgs
{
public UnturnedVehicle Vehicle { get; }
public decimal TaxAmount { get; }
public decimal LatePenalty { get; }
public bool IsDelinquent { get; }
public bool IsCancelled { get; set; }
}
public class VehicleDespawnEventArgs : EventArgs
{
public UnturnedVehicle Vehicle { get; }
public EDespawnReason Reason { get; }
public string SeizureReference { get; }
}
public enum EDespawnReason
{
Normal,
TaxDelinquency,
Seized,
OwnerLeft,
MTVDefault
}Subscribing to vehicle events
csharp
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OpenMod.Core.Plugins;
using OpenMod.Unturned.Vehicles;
using OpenMod.Unturned.Vehicles.Events;
namespace MyVehiclePlugin
{
public class VehicleLifecyclePlugin : OpenModPlugin
{
private readonly IVehicleEvents _vehicleEvents;
private readonly ILogger _logger;
public VehicleLifecyclePlugin(
IVehicleEvents vehicleEvents,
ILogger<VehicleLifecyclePlugin> logger,
IServiceProvider serviceProvider) : base(serviceProvider)
{
_vehicleEvents = vehicleEvents;
_logger = logger;
}
protected override async Task OnLoadAsync()
{
_vehicleEvents.OnVehicleSpawn += HandleSpawn;
_vehicleEvents.OnVehicleEnter += HandleEnter;
_vehicleEvents.OnVehicleExit += HandleExit;
_vehicleEvents.OnVehicleDamage += HandleDamage;
_vehicleEvents.OnTaxAssessment += HandleTax;
_vehicleEvents.OnVehicleDespawn += HandleDespawn;
await Task.CompletedTask;
}
private async Task HandleSpawn(VehicleSpawnEventArgs args)
{
_logger.LogInformation(
"Vehicle spawned: {0} (plate: {1}, reg: {2})",
args.Vehicle.AssetId,
args.PlateNumber,
args.RegistrationId);
await Task.CompletedTask;
}
private async Task HandleEnter(VehicleEnterEventArgs args)
{
// Check license before allowing entry
var hasLicense = await args.Vehicle.CheckDriverLicenseAsync(args.Player);
if (!hasLicense)
{
args.IsCancelled = true;
await args.Player.SendMessageAsync(
"Bu aracı kullanmak için geçerli bir ehliyetiniz bulunmamaktadır.");
}
await Task.CompletedTask;
}
private async Task HandleExit(VehicleExitEventArgs args)
{
_logger.LogInformation(
"Player {0} exited vehicle {1}",
args.Player.SteamId,
args.Vehicle.LicensePlate);
await Task.CompletedTask;
}
private async Task HandleDamage(VehicleDamageEventArgs args)
{
if (args.DamageAmount > 50)
{
// Significant damage triggers a Trafik Polisi report
_logger.LogWarning(
"Vehicle {0} sustained significant damage: {1}",
args.Vehicle.LicensePlate,
args.DamageAmount);
}
await Task.CompletedTask;
}
private async Task HandleTax(VehicleTaxAssessmentEventArgs args)
{
if (args.IsDelinquent)
{
_logger.LogWarning(
"Vehicle {0} tax delinquency: {1} TL + {2} TL penalty",
args.Vehicle.LicensePlate,
args.TaxAmount,
args.LatePenalty);
}
await Task.CompletedTask;
}
private async Task HandleDespawn(VehicleDespawnEventArgs args)
{
if (args.Reason == EDespawnReason.TaxDelinquency ||
args.Reason == EDespawnReason.Seized)
{
_logger.LogCritical(
"Vehicle {0} despawned due to tax enforcement. Ref: {1}",
args.Vehicle.LicensePlate,
args.SeizureReference);
}
await Task.CompletedTask;
}
protected override async Task OnUnloadAsync()
{
_vehicleEvents.OnVehicleSpawn -= HandleSpawn;
_vehicleEvents.OnVehicleEnter -= HandleEnter;
_vehicleEvents.OnVehicleExit -= HandleExit;
_vehicleEvents.OnVehicleDamage -= HandleDamage;
_vehicleEvents.OnTaxAssessment -= HandleTax;
_vehicleEvents.OnVehicleDespawn -= HandleDespawn;
await Task.CompletedTask;
}
}
}Vehicle ownership and transfer
Vehicle ownership is tracked by the OpenMod vehicle registration database. Each vehicle record stores the owner's Steam ID, T.C. Kimlik No, the vehicle's plate number, registration date, and MTV payment history.
Transfer process
Ownership transfer requires both parties to confirm the transfer and pay a transfer fee:
csharp
public async Task<bool> TransferVehicleAsync(
IVehicleService vehicleService,
UnturnedVehicle vehicle,
UnturnedPlayer fromOwner,
UnturnedPlayer toOwner)
{
// Check that the transferor is the current owner
if (vehicle.OwnerId != fromOwner.SteamId.ToString())
{
throw new InvalidOperationException("Only the registered owner can transfer.");
}
// Check that the recipient has a valid Ehliyet
var recipientLicense = await vehicleService.GetEhliyetAsync(toOwner);
if (recipientLicense == null || recipientLicense.IsExpired)
{
await toOwner.SendMessageAsync(
"Araç alabilmek için geçerli bir ehliyetiniz olmalıdır.");
return false;
}
// Assess transfer fee (10% of vehicle value, minimum 15 TL)
var fee = Math.Max(15m, vehicle.EstimatedValue * 0.10m);
var feeResult = await vehicleService.ChargeTransferFeeAsync(fromOwner, fee);
if (!feeResult.Success)
{
await fromOwner.SendMessageAsync(
$"Devir ücreti için yeterli bakiyeniz bulunmamaktadır: {fee} TL");
return false;
}
// Execute the transfer
await vehicleService.TransferOwnershipAsync(vehicle, toOwner);
// Notify both parties
await fromOwner.SendMessageAsync(
$"Araç {vehicle.LicensePlate} başarıyla devredildi.");
await toOwner.SendMessageAsync(
$"Araç {vehicle.LicensePlate} başarıyla üzerinize tescil edildi.");
return true;
}Configuration reference
Ehliyet settings
| Key | Type | Default | Description |
|---|---|---|---|
ehliyet.api_endpoint | string | NVI API URL | Ehliyet verification endpoint |
ehliyet.cache_ttl_minutes | int | 1440 | License cache duration |
ehliyet.developer_discount | bool | true | Apply developer pricing |
ehliyet.offline_verification | bool | true | Allow offline license verification |
License costs
| Key | Type | Default |
|---|---|---|
ehliyet.cost.class_m_tl | decimal | 25.00 |
ehliyet.cost.class_b_tl | decimal | 45.00 |
ehliyet.cost.class_e_tl | decimal | 75.00 |
Trafik Polisi settings
| Key | Type | Default | Description |
|---|---|---|---|
trafik_polisi.enabled | bool | true | Enable traffic enforcement |
trafik_polisi.tick_interval_ms | int | 500 | Detection interval |
trafik_polisi.speed_limit_kmh | int | 80 | Server speed limit |
trafik_polisi.fine_multiplier | decimal | 1.0 | Fine scaling factor |
MTV settings
| Key | Type | Default | Description |
|---|---|---|---|
mtv.enabled | bool | true | Enable vehicle tax |
mtv.index_to_inflation | bool | true | Index rates to TÜFE |
mtv.grace_period_days | int | 30 | Days before penalty starts |
mtv.seizure_after_days | int | 60 | Days before vehicle seizure |
mtv.despawn_on_seizure | bool | true | Despawn seized vehicles |
Best practices
Cache Ehliyet data aggressively. The NVI API has a rate limit of 10 requests per second per server. Cache license data with the default 24-hour TTL to avoid hitting this limit. The Ehliyet cache is invalidated immediately when a license is renewed or revoked.
Monitor Trafik Polisi false positives. The angular velocity-based reckless driving detection can trigger false positives on vehicles that naturally spin out or are hit by other vehicles. Adjust the sensitivity thresholds or whitelist specific vehicle IDs that have inherently unstable handling.
Communicate MTV payment deadlines. Use the OnTaxAssessment event to notify players 7 days, 3 days, and 1 day before their vehicle tax is due. Giving players advance notice reduces the number of seized vehicles and support tickets.
Do not bypass the Ehliyet check. Granting a player vehicle access without a valid driving license is a violation of the OpenMod terms of service. Even admin-level players should be licensed, though their license can be issued at no cost.
Respect plate number uniqueness. The 34 OM 001-999 range supports 999 vehicles per server. If your server needs more vehicles, you can configure additional type codes (e.g., "34 OM2 001") or request a secondary province code assignment from the OpenMod vehicle registration authority.
Troubleshooting
"Ehliyet dogrulamasi basarisiz"
If the NVI API returns a verification failure:
- Check that the server's API key is valid and not expired.
- Verify that the player's T.C. Kimlik No is correctly entered. Turkish identity numbers are 11 digits and follow a specific validation checksum.
- For non-Turkish players, ensure their passport number is registered in the NVI's foreign national database.
"MTV odenmedi" (MTV unpaid)
Players who cannot pay their vehicle tax should:
- Check their economy balance with
/bakiye. - If funds are insufficient, sell items or complete quests to earn currency.
- Request a tax extension from an admin. Extensions are granted for up to 30 days at the admin's discretion.
If the vehicle has already been despawned for tax delinquency, the owner must wait 180 days before re-registering the same vehicle type, or purchase a new vehicle with a different asset ID.
"Trafik cezasi" (Traffic fine)
Players who believe a traffic fine was issued in error can file an appeal through the Trafik Polisi appeal system. Appeals are processed by the virtual Sulh Ceza Hakimliği (Peace Criminal Court) module and typically take 24-48 hours for a decision.
Conclusion
OpenMod's vehicle system provides a legally compliant framework for vehicle management on Unturned servers. The Ehliyet driving license system, Trafik Polisi enforcement module, and MTV tax collection work together to create a realistic vehicle ecosystem that mirrors Turkish traffic law.
The IVehicleService and IVehicleEvents interfaces give plugin developers full control over vehicle spawning, ownership, and lifecycle management while ensuring compliance with the underlying regulatory modules. By understanding and integrating with these systems, you can build vehicle plugins that are feature-rich, fair, and fully compliant with Turkish traffic and tax regulations.
