OneSync
OneSync enables advanced synchronization features for FiveM servers, allowing for increased player limits, better entity management, and improved performance through routing buckets.
OneSync Infinity
OneSync Infinity is the evolution of OneSync that enables servers to support 128+ players with improved entity synchronization and performance.
Benefits
- Increased Player Limits: Support for 128+ concurrent players (vs. 32 without OneSync)
- Better Entity Synchronization: More reliable entity state across all clients
- Improved Performance: Optimized network traffic and reduced lag
- Enhanced Stability: Better handling of high player counts
Configuration
Enable OneSync Infinity in your server.cfg:
# Enable OneSync
set onesync on
# Enable OneSync Infinity (required for 64+ players)
set onesync_enableInfinity 1
# Set maximum clients (must be power of 2: 32, 64, 128, 256)
set sv_maxclients 128Important Notes:
onesync_enableInfinity 1is required for servers with more than 32 playerssv_maxclientsmust be a power of 2 (32, 64, 128, 256)- All players must have OneSync-compatible clients (FiveM 2020+)
Routing Buckets
Routing buckets allow you to isolate players into separate “dimensions” where they cannot see or interact with players in other buckets. This is essential for managing large player counts and creating isolated game modes.
Basic Usage
-- Set a player's routing bucket
SetPlayerRoutingBucket(playerId, bucketId)
-- Get a player's current routing bucket
local bucket = GetPlayerRoutingBucket(playerId)
-- Set entity routing bucket (vehicles, peds, objects)
SetEntityRoutingBucket(entityId, bucketId)
-- Get entity routing bucket
local bucket = GetEntityRoutingBucket(entityId)Routing Bucket Examples
Example 1: Separate Game Modes
Create isolated instances for different game modes:
-- server.lua
local GAME_MODE_BUCKETS = {
FREEROAM = 0,
RACING = 1,
DEATHMATCH = 2,
ROLEPLAY = 3
}
-- Assign player to racing mode
RegisterCommand('joinrace', function(source, args)
SetPlayerRoutingBucket(source, GAME_MODE_BUCKETS.RACING)
TriggerClientEvent('chat:addMessage', source, {
args = {'You joined Racing mode'}
})
end, false)
-- Return to freeroam
RegisterCommand('leave', function(source, args)
SetPlayerRoutingBucket(source, GAME_MODE_BUCKETS.FREEROAM)
TriggerClientEvent('chat:addMessage', source, {
args = {'You left to Freeroam'}
})
end, false)Example 2: Admin Areas
Create private admin zones:
-- server.lua
local ADMIN_BUCKET = 100
-- Check if player is admin (implement your own logic)
local function IsPlayerAdmin(playerId)
-- Your admin check logic here
return false
end
RegisterCommand('adminzone', function(source, args)
if not IsPlayerAdmin(source) then
TriggerClientEvent('chat:addMessage', source, {
args = {'You do not have permission'}
})
return
end
SetPlayerRoutingBucket(source, ADMIN_BUCKET)
TriggerClientEvent('chat:addMessage', source, {
args = {'Entered Admin Zone'}
})
end, false)Example 3: Testing Environment
Isolate testers from production players:
-- server.lua
local TEST_BUCKET = 200
local testers = {} -- Store tester identifiers
-- Add tester
RegisterCommand('addtester', function(source, args, rawCommand)
if not IsPlayerAdmin(source) then return end
local targetId = tonumber(args[1])
if targetId then
testers[targetId] = true
SetPlayerRoutingBucket(targetId, TEST_BUCKET)
TriggerClientEvent('chat:addMessage', targetId, {
args = {'You are now in testing mode'}
})
end
end, true)
-- Remove tester
RegisterCommand('removetester', function(source, args, rawCommand)
if not IsPlayerAdmin(source) then return end
local targetId = tonumber(args[1])
if targetId and testers[targetId] then
testers[targetId] = nil
SetPlayerRoutingBucket(targetId, 0) -- Return to default
TriggerClientEvent('chat:addMessage', targetId, {
args = {'You left testing mode'}
})
end
end, true)Example 4: Instance System
Create player-created instances (e.g., private properties):
-- server.lua
local instances = {}
local instanceCounter = 1
-- Create new instance
RegisterCommand('createinstance', function(source, args)
local instanceId = instanceCounter
instanceCounter = instanceCounter + 1
instances[instanceId] = {
owner = source,
players = {source}
}
SetPlayerRoutingBucket(source, instanceId)
TriggerClientEvent('chat:addMessage', source, {
args = {'Instance created: ' .. instanceId}
})
end, false)
-- Join instance
RegisterCommand('joininstance', function(source, args)
local instanceId = tonumber(args[1])
if not instanceId or not instances[instanceId] then
TriggerClientEvent('chat:addMessage', source, {
args = {'Invalid instance ID'}
})
return
end
table.insert(instances[instanceId].players, source)
SetPlayerRoutingBucket(source, instanceId)
TriggerClientEvent('chat:addMessage', source, {
args = {'Joined instance: ' .. instanceId}
})
end, false)Use Cases
- Separate Game Modes: Racing, deathmatch, roleplay in isolated buckets
- Admin Areas: Private testing zones for staff
- Testing Environments: Isolate beta testers from production
- Instance Systems: Player-created private spaces (properties, businesses)
- Event Servers: Temporary isolated events
- Performance Optimization: Distribute players across buckets to reduce entity load
Entity Management Strategies
Managing entities efficiently is crucial for server performance, especially with high player counts.
Entity Limits
Configure entity caps in server.cfg:
# Maximum clients (must be power of 2)
set sv_maxclients 128
# Maximum entities (vehicles, peds, objects)
# Recommended: 5000-10000 for 128 players
set sv_maxEntities 8000
# Maximum vehicles
set sv_maxVehicles 2000
# Maximum peds
set sv_maxPeds 1000Entity Cleanup
Implement automatic cleanup for abandoned entities:
-- server.lua
local cleanupInterval = 300000 -- 5 minutes
CreateThread(function()
while true do
Wait(cleanupInterval)
-- Clean up abandoned vehicles
local vehicles = GetAllVehicles()
for _, vehicle in ipairs(vehicles) do
if DoesEntityExist(vehicle) then
local driver = GetPedInVehicleSeat(vehicle, -1)
local distance = #(GetEntityCoords(vehicle) - vector3(0.0, 0.0, 0.0))
-- Remove vehicles with no driver and far from spawn
if driver == 0 and distance > 5000.0 then
local lastOccupied = GetVehicleLastOccupiedTime(vehicle)
if lastOccupied > 0 and (GetGameTimer() - lastOccupied) > 600000 then -- 10 minutes
DeleteEntity(vehicle)
end
end
end
end
end
end)Entity Streaming
Use routing buckets to reduce entity load per player:
-- Distribute players across buckets to reduce entity count per bucket
local function DistributePlayers()
local players = GetPlayers()
local bucketSize = 32 -- Max players per bucket
for i, playerId in ipairs(players) do
local bucket = math.floor(i / bucketSize)
SetPlayerRoutingBucket(playerId, bucket)
end
endScaling from 32 to 128+ Players
Step-by-Step Migration
1. Pre-Migration Checklist
- Verify all resources are OneSync-compatible
- Test with 32 players first
- Backup server configuration
- Notify players of potential downtime
2. Update Configuration
# server.cfg - Before (32 players)
set sv_maxclients 32
# server.cfg - After (128 players)
set onesync on
set onesync_enableInfinity 1
set sv_maxclients 128
set sv_maxEntities 8000
set sv_maxVehicles 20003. Resource Compatibility Check
Some resources may need updates for OneSync:
-- Check if resource uses deprecated natives
-- Old (not OneSync compatible):
local players = GetPlayers() -- May not work correctly
-- New (OneSync compatible):
local players = GetActivePlayers() -- Works with OneSync4. Database Optimization
Ensure your database can handle increased load:
-- Add indexes for common queries
CREATE INDEX idx_users_identifier ON users(identifier);
CREATE INDEX idx_vehicles_owner ON vehicles(owner);
CREATE INDEX idx_inventory_owner ON inventory(owner);
-- Optimize connection pool
-- In your database config, increase max connections
max_connections = 2005. Monitoring Setup
Monitor server performance during migration:
-- server.lua - Performance monitoring
CreateThread(function()
while true do
Wait(60000) -- Every minute
local playerCount = #GetPlayers()
local vehicleCount = #GetAllVehicles()
local pedCount = #GetAllPeds()
print(string.format(
'[Performance] Players: %d | Vehicles: %d | Peds: %d',
playerCount, vehicleCount, pedCount
))
-- Alert if entity count is high
if vehicleCount > 1500 then
print('[WARNING] High vehicle count: ' .. vehicleCount)
end
end
end)Performance Tuning
Network Optimization
# server.cfg - Network settings for 128 players
set sv_maxclients 128
# Increase network bandwidth
set sv_maxRate 1000000
# Optimize entity streaming
set sv_maxEntities 8000
set sv_maxVehicles 2000
# Reduce unnecessary sync
set sv_enableNetworkedEntityDamage 1Resource Optimization
Disable or optimize heavy resources:
# Disable unnecessary resources during peak hours
# ensure resource_name
# Use start/stop commands to manage resources dynamicallyServer Hardware
Recommended specifications for 128 players:
- CPU: 8+ cores (3.0+ GHz)
- RAM: 32+ GB
- Network: 1 Gbps connection
- Storage: NVMe SSD
Common Pitfalls
Pitfall 1: Not Using Routing Buckets
Problem: All 128 players in bucket 0, causing entity overload.
Solution: Distribute players across multiple buckets:
-- Distribute players automatically
CreateThread(function()
while true do
Wait(30000) -- Every 30 seconds
local players = GetPlayers()
local maxPerBucket = 32
for i, playerId in ipairs(players) do
local bucket = math.floor(i / maxPerBucket)
SetPlayerRoutingBucket(playerId, bucket)
end
end
end)Pitfall 2: Entity Leaks
Problem: Entities not being cleaned up, causing memory issues.
Solution: Implement proper cleanup:
-- Track entity ownership
local entityOwners = {}
-- When creating entity
local vehicle = CreateVehicle(model, x, y, z, heading, true, false)
entityOwners[vehicle] = {
owner = source,
created = GetGameTimer()
}
-- Cleanup on disconnect
AddEventHandler('playerDropped', function()
local source = source
for entity, data in pairs(entityOwners) do
if data.owner == source then
DeleteEntity(entity)
entityOwners[entity] = nil
end
end
end)Pitfall 3: Incompatible Resources
Problem: Resources using deprecated natives that don’t work with OneSync.
Solution: Update resources or find alternatives:
-- Check for OneSync compatibility
if GetConvar('onesync_enableInfinity', '0') == '1' then
-- Use OneSync-compatible code
local players = GetActivePlayers()
else
-- Fallback for non-OneSync
local players = GetPlayers()
endPitfall 4: Database Bottlenecks
Problem: Database queries become slow with more players.
Solution: Optimize database queries and use connection pooling:
-- Use prepared statements
local query = 'SELECT * FROM users WHERE identifier = ?'
MySQL.query(query, {identifier}, function(result)
-- Handle result
end)
-- Batch operations
local batch = {}
for i = 1, 100 do
table.insert(batch, {identifier = identifiers[i]})
end
MySQL.insert('users', batch, function(result)
-- Handle batch result
end)Pitfall 5: Network Bandwidth Issues
Problem: Server can’t handle network traffic from 128 players.
Solution: Optimize network settings and use routing buckets:
# Increase network limits
set sv_maxRate 1000000
set sv_maxclients 128
# Use routing buckets to reduce per-bucket traffic
# Each bucket only syncs entities in that bucketBest Practices
- Always Use Routing Buckets: Distribute players across buckets to reduce entity load
- Monitor Entity Counts: Track vehicles, peds, and objects to prevent overload
- Implement Cleanup: Automatically remove abandoned entities
- Test Incrementally: Scale from 32 → 64 → 128 players gradually
- Optimize Resources: Disable or optimize heavy resources for high player counts
- Database Indexing: Ensure all common queries are indexed
- Network Monitoring: Monitor bandwidth usage and adjust
sv_maxRateaccordingly - Resource Compatibility: Verify all resources work with OneSync before enabling
- Backup Before Changes: Always backup configuration before scaling up
- Document Your Setup: Keep notes on bucket assignments and entity limits