Skip to Content
OpsOneSync

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 128

Important Notes:

  • onesync_enableInfinity 1 is required for servers with more than 32 players
  • sv_maxclients must 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 1000

Entity 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 end

Scaling 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 2000

3. 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 OneSync

4. 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 = 200

5. 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 1

Resource Optimization

Disable or optimize heavy resources:

# Disable unnecessary resources during peak hours # ensure resource_name # Use start/stop commands to manage resources dynamically

Server 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() end

Pitfall 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 bucket

Best Practices

  1. Always Use Routing Buckets: Distribute players across buckets to reduce entity load
  2. Monitor Entity Counts: Track vehicles, peds, and objects to prevent overload
  3. Implement Cleanup: Automatically remove abandoned entities
  4. Test Incrementally: Scale from 32 → 64 → 128 players gradually
  5. Optimize Resources: Disable or optimize heavy resources for high player counts
  6. Database Indexing: Ensure all common queries are indexed
  7. Network Monitoring: Monitor bandwidth usage and adjust sv_maxRate accordingly
  8. Resource Compatibility: Verify all resources work with OneSync before enabling
  9. Backup Before Changes: Always backup configuration before scaling up
  10. Document Your Setup: Keep notes on bucket assignments and entity limits
Last updated on