Skip to guide

Documentation 9.6.24

Server integration

Call exports only from trusted server code. A client must not be able to choose its own exemption, administrator status, target or reward.

Read-only example#

The example below checks an administrator status; it does not grant access. Verify the export and identifier format against the package you installed.

local playerId = 12
local isAdmin = exports['tosun-ac']:isAdmin(playerId)

Validate before an exemption#

For a job or minigame, confirm the server-owned session, player, location, permission and duration before applying a short, specific exemption. Never wrap an exemption export in an unvalidated RegisterNetEvent. Use Cfx’s server-event security guide when integrating custom resources.

Read the official Cfx guide

Teleport notice#

Every server script that moves a player (house, garage, jail, hospital, job) should call MarkTeleport right before the teleport. It needs no trust list and only relaxes movement and visibility checks for a short time; weapon, money and injection protection stay on. Once every teleporting script sends the notice, you can raise the v16 teleport punishment to kick in the anticheat settings.

exports['tosun-ac']:MarkTeleport(source, 8000)
SetEntityCoords(GetPlayerPed(source), x, y, z)

Trusted resources#

Exports that exempt players, grant permissions or run bulk actions (SetExempt, addAdmin, whitelistPlayer and others) only accept trusted resources. A rejected call is printed to the console once, with the line to add. Keep the list in server.cfg so anticheat updates don’t overwrite it. The tosunac_integration console command shows the trusted list and the latest rejected calls.

set tosun_ac_trusted_resources "my-housing,my-clothing"

Weapons given outside the inventory#

Scripts that hand out weapons without adding them to the inventory, such as arenas, paintball or menus, should call AllowWeapon when they give the weapon. Otherwise the 9.4.0 weapon and inventory check logs it as a spawned weapon. Pass one weapon name, or an asterisk for all weapons; the maximum duration is 1 hour. Add addon weapons the anticheat does not know to extraWeapons in the config.

exports['tosun-ac']:AllowWeapon(source, "WEAPON_PISTOL", 600000)

Keep integration authority on the server#

Use the package’s TOSUN-AC-EXPORTS.md as the reference for the installed exports. Export names are case-sensitive. Exemption durations use milliseconds; AddWhitelist and WhitelistArea use seconds. Start tosun-ac before scripts that depend on its exports, and handle a stopped resource rather than silently skipping a required protection step. A successful call does not validate your job rules for you.

Sensitive exports such as SetExempt and AllowWeapon require a trusted invoking server resource. Add only reviewed resources, preserve existing entries when editing the comma-separated list, and inspect tosunac_integration for rejected calls. Disabling whitelist enforcement is audit mode: calls can pass while warnings are logged. Do not leave it disabled as a permanent fix.

set tosun_ac_trusted_resources "my-clothing,my-arena"

# Server console:
tosunac_integration

Notify a legitimate teleport at the correct point#

Validate the player, server-owned destination, permission and active activity before the movement. Call MarkTeleport immediately before changing position, as in the integration fragment below. src and destination must come from your existing validated server workflow, not arbitrary client parameters. This fragment is not a standalone network event.

MarkTeleport needs no trust list. It briefly relaxes movement and related visibility/godmode/camera checks, while weapon, money, event-abuse and injection checks remain active. With default settings, an untrusted call is limited to 15 seconds and the player has a 180-second budget over ten minutes. Repeated extensions consume that budget. Do not call it every tick to keep a player exempt.

-- Within an already validated server workflow:
local ok = exports["tosun-ac"]:MarkTeleport(src, 8000, "house_enter")
if ok then
    SetEntityCoords(GetPlayerPed(src), destination.x, destination.y, destination.z)
end

Allow one scripted weapon without a blanket bypass#

For an arena or paintball resource that grants a weapon without an inventory item, validate the server-owned match and then call AllowWeapon from the trusted server resource. Prefer one named weapon and the time the activity actually needs. The allowance affects the inventory ownership check and its damage path; it does not disable the rest of the anti-cheat.

The maximum allowance is one hour. Avoid the asterisk unless the activity truly needs every weapon. SetExempt is broader, requires trust and is capped at five minutes; historical BypassDetection ignores its detectionKey and is a full exemption capped at one minute. Do not treat it as a narrow per-check bypass.

Do not retain a disconnected player’s temporary source ID and use it for a later reward or exemption. At the moment of a sensitive action, confirm the player still belongs to the validated server-owned session. A resource on the trust list remains responsible for all permission and target checks in its own code.

  • A normal authorised action succeeds and the chosen duration ends as expected.
  • A forged client request cannot choose another player, duration, weapon or destination.
  • An untrusted sensitive-export call returns false and leaves a useful console warning.
  • After resource restart, recheck integration status and ordinary player actions.
-- my-arena: trusted server resource, authorised session
local allowed = exports["tosun-ac"]:AllowWeapon(src, "WEAPON_PISTOL", 60000)
-- Grant the intended weapon only as part of the validated arena workflow.

End temporary exemptions through the correct server API#

Server SetExempt takes src, milliseconds and reason; the client SetExempt takes state, milliseconds and reason. They are not interchangeable. A client exemption affects client detections and does not grant server-side authority. For a trusted server workflow, SetPlayerExempt with state false removes its temporary player exemption. Coordinate overlapping activities first: this is player-wide temporary state, not an independently owned token for each resource. Clearing it may end another activity’s temporary exemption. Conversely, a staff or panel whitelist can still keep IsExemptFromPunish true after that temporary state is cleared. Prefer the narrow MarkTeleport or AllowWeapon mechanism when that is sufficient.

  1. Finish or cancel the authorised activity using a validated current player, and remove temporary relief when it is no longer needed.
  2. Test cancellation, disconnect and the normal completion path; do not keep extending a full exemption in a background loop.
  3. Confirm behaviour with an ordinary player, then check whether remaining protection comes from staff, panel whitelist or another activity.
-- Trusted server resource; src belongs to an authorised workflow.
-- Clear the temporary exemption when that workflow finishes or is cancelled.
local cleared = exports["tosun-ac"]:SetPlayerExempt(src, false, 0, "menu_finished")

Use optional helper files with an explicit result policy#

The bridge helper files belong in your own resource manifest and do not replace your permission checks. TosunAC.IsAvailable checks whether the AC resource is started; TosunAC.IsTrusted checks whether the caller is trusted. PlayerExempt returns ok and mode: full means a trusted full exemption, while soft means only limited movement and visibility relief. Do not treat any true result as full immunity. If an activity genuinely requires full relief, decide how to stop or reject it when only soft is available rather than silently continuing under a different protection scope. PlayerExemptOff removes the temporary full exemption through the server API.

  1. Load the server helper before the server script that uses TosunAC, and preserve other manifest dependencies.
  2. Inspect ok and mode when the activity starts; log only the resource, reason and non-secret result.
  3. If the AC is stopped or the call is rejected, handle that branch deliberately and diagnose start order or trust before retrying.
-- Add these lines to your own resource manifest:
client_script "@tosun-ac/bridge/tosun_ac_client.lua"
server_script "@tosun-ac/bridge/tosun_ac_server.lua"

Use read-only exports as diagnostics, not verdicts#

GetStatus gives a small runtime summary, including configuration framework and online count; it is not a complete audit of every integration. GetIntegrationStatus describes the invoking resource’s trust, not every script on the server. IsMovementExempt and IsExemptFromPunish answer different questions and should not be swapped. GetDetections has a historical name: it reads the player’s bans from ts_anticheat, not all recent detection logs. An empty result is therefore not a clean-player certificate. Keep database-backed or broad player queries on demand rather than every tick. A returned object should be used for its documented purpose, without attaching credentials or extra personal information to a public debug dump.

  1. When troubleshooting, record the calling resource and which exact status or exemption check was consulted.
  2. Compare a known workflow’s expected scope with its actual result; investigate a mismatch before changing punishments.
  3. Recheck the installed TOSUN-AC-EXPORTS.md after an update, particularly legacy aliases and server/client argument order.

Tie delayed movement to the player and resource lifetime#

When entering a house needs a short delay, capturing a player’s source number is not enough. A later connection can reuse that number after the player disconnects. The server.lua fragment below is a local function for an already authorised server workflow, not a client-accessible network event. The destination must be a server-validated location. A unique Lua object in pending ties the delayed move to that workflow. Disconnecting removes the entry; the timer does nothing unless it still finds the same object. A new player with the old source does not receive the old move.

The example clears pending entries when tosun-ac stops or your own resource shuts down. At the end of the delay it rechecks resource state, player presence and the ped. pcall catches export errors, and no move occurs unless MarkTeleport returns true. These checks do not grant house ownership, job roles or destination permission: verify those before calling. The fragment only requests movement relief; it does not clear full exemptions or change another script’s permissions. Test disconnecting during the wait, stopping AC and the normal entry separately. No permanent loop or timer that scans every player is needed; there is one delay for the workflow you started.

-- server.lua: call only from an already authorised server workflow.
-- destination is a server-validated location, never raw client input.
local pending = {}

local function scheduleValidatedMove(src, destination)
    src = tonumber(src)
    if not src or not GetPlayerName(src) then return false end
    if GetResourceState("tosun-ac") ~= "started" then return false end
    local ticket = {}
    local target = {x = destination.x, y = destination.y, z = destination.z}
    pending[src] = ticket
    SetTimeout(1500, function()
        if pending[src] ~= ticket then return end
        pending[src] = nil
        if not GetPlayerName(src) then return end
        if GetResourceState("tosun-ac") ~= "started" then return end
        local ped = GetPlayerPed(src)
        if not ped or ped == 0 then return end
        local called, allowed = pcall(function()
            return exports["tosun-ac"]:MarkTeleport(src, 8000, "house_delayed_entry")
        end)
        if called and allowed == true then
            SetEntityCoords(ped, target.x, target.y, target.z)
        end
    end)
    return true -- Scheduled, not yet moved.
end

AddEventHandler("playerDropped", function() pending[source] = nil end)
AddEventHandler("onResourceStop", function(name)
    if name == GetCurrentResourceName() or name == "tosun-ac" then
        pending = {}
    end
end)

Measure trust from inside the integrating resource#

After editing the trust list, place this diagnostic inside the resource that will make the actual call. The command below runs only from the server console; player invocations are ignored because src is not zero. Run my-resource-ac-check once. GetIntegrationStatus returns the calling resource name, trusted and enforcing values. A true result obtained inside another resource therefore does not prove that your clothing or arena script is trusted. GetStatus supplies a small runtime summary, including version and configured framework; it is not an audit of every integration.

Even when pcall succeeds, the returned value must be a table. A call error and a false result are different observations; do not report configuration as verified when the export could not be called. With trusted=false and enforcing=true, compare the caller name against your reviewed trust list. enforcing=false may be an audit setting; it does not prove that every sensitive operation is safely restricted. The output contains only resource, version, framework and two booleans, not player identifiers or keys. Do not run it every tick. After updates, separately test the script’s normal and expected rejection paths; a read-only diagnostic provides no authorisation guarantee for punishment exports.

-- Place in the integrating resource's server.lua.
RegisterCommand("my-resource-ac-check", function(src)
    if src ~= 0 then return end -- Server console only.
    if GetResourceState("tosun-ac") ~= "started" then
        print("[integration] tosun-ac is not started")
        return
    end
    local okTrust, trust = pcall(function()
        return exports["tosun-ac"]:GetIntegrationStatus()
    end)
    local okStatus, status = pcall(function()
        return exports["tosun-ac"]:GetStatus()
    end)
    if not okTrust or type(trust) ~= "table"
        or not okStatus or type(status) ~= "table" then
        print("[integration] status query failed")
        return
    end
    print(("[integration] resource=%s version=%s framework=%s trusted=%s enforcing=%s")
        :format(GetCurrentResourceName(), tostring(status.version),
            tostring(status.framework), tostring(trust.trusted), tostring(trust.enforcing)))
end, false)

Register validated server actions for custom events#

Use RegisterSafeEvent in your server script; the event name must start with the calling resource name. The validator must return exactly true after checking server-owned player, job, position, item and permission state. A client event key is not permission. Consume the completed job once on the server to prevent duplicate rewards.

Use the client export TriggerSafeServerEvent. sent means dispatched, not a payment or reward acknowledgement. queued_until_key waits at most 30 seconds; a full queue rejects new calls. Do not automatically repeat economic actions. Register again when AC restarts.

Migrate and remove your existing raw RegisterNetEvent handler. Tosun AC cannot cancel another resource handler; leaving the same sensitive action on the old event leaves a bypass. Legacy ProtectedEvents :safe handlers must use server-only AddEventHandler.

-- my-job/server.lua: own server-owned job state and framework adapter.
local activeJobs = {}
local function registerActions()
    if GetResourceState("tosun-ac") ~= "started" then return end
    local ok, reason = exports["tosun-ac"]:RegisterSafeEvent("my-job:finish",
        function(src)
            local job = activeJobs[src]
            return job ~= nil and job.completed == true
            -- Also verify server-owned position, role and inventory as required.
        end,
        function(src)
            local job = activeJobs[src]
            if not job then return end
            activeJobs[src] = nil -- consume before any yielding reward operation
            -- Give the server-owned reward through your validated framework adapter.
        end, {rateLimit=5, windowMs=10000, maxArgs=0})
    if not ok then print("[my-job] SafeEvent: " .. tostring(reason)) end
end
AddEventHandler("onResourceStart", function(name)
    if name == GetCurrentResourceName() or name == "tosun-ac" then registerActions() end
end)
AddEventHandler("playerDropped", function() activeJobs[source] = nil end)

-- my-job/client.lua:
local sent, state = exports["tosun-ac"]:TriggerSafeServerEvent("my-job:finish")
-- Read state; implement a separate application acknowledgement if needed.

Configure the exact invoking resource#

Put set tosun_ac_trusted_resources "my-housing,my-clothing" in server.cfg, preserving the other reviewed names already present. Use the directory/resource name, not a display name, player name or Discord role. This server setting uses set, not setr. Keep ts.EnforceExportCallerWhitelist = true in the editable configuration. Trust permits sensitive exports; it does not validate a house purchase, inventory item, job or target player. Run the diagnostic from the same resource that performs the action and check trusted=true and enforcing=true.

set tosun_ac_trusted_resources "my-housing,my-clothing"

# txAdmin server console:
tosunac_integration

-- In the invoking integration resource server script:
local status = exports["tosun-ac"]:GetIntegrationStatus()
print(status.resource, status.trusted, status.enforcing)

Five lists with five different purposes#

The trusted-resource list controls which server resources may invoke sensitive exports. A player whitelist grants a player protection and must be managed separately. A fake-trigger whitelist disables one trap rule; it does not authorize the real game event. ts.ProtectedEvents is the legacy keyed event transport, with test:event in the supplied defaults. The resource baseline records reviewed resource files for integrity checks. Adding something to one list does not add it to the others. Never paste every discovered framework event into ProtectedEvents or mark it as a trap.

Complete server export catalog for this package#

The following names and argument declarations are generated from the actual server source inventory for this package. They are a reference, not a script to execute in order. Keep capitalization and server/client side exact. Internal diagnostics, scan functions and transport helpers are included so a similarly named function is not mistaken for a safe business-action API. Read the source contract and result policy before invoking a mutation; a name alone grants no permission.

-- tosun-ac / server
-- AddWhitelist(target, durationSec)
-- AllowWeapon(src, weapon, ms)
-- BanPlayerExt(playerId, reason)
-- BypassDetection(playerId, detectionKey, durationMs)
-- ClearArea(playerId, areaName)
-- ForensicLinksOf(license)
-- GetCloudThreatScore(src)
-- GetDetections(playerId, limit)
-- GetIntegrationStatus()
-- GetNearbyPlayers(playerId, radius)
-- GetPlayerInfo(playerId)
-- GetPlayerShieldData(src)
-- GetServerAuthorityStatus()
-- GetStatus()
-- IsExemptFromPunish(src)
-- IsInArea(playerId, areaName)
-- IsMovementExempt(src)
-- IsPlayerProtected(playerId)
-- IsWhitelisted(playerId)
-- KickPlayer(playerId, reason)
-- MarkTeleport(src, ms, reason)
-- NoteCloudViolation(src, reason, punishment)
-- OpenScanCache(sealed)
-- PauseAllDetections(durationMs)
-- PausePlayerDetections(playerId, durationMs)
-- RateLimit(src, key, max, windowMs)
-- RegisterSafeEvent(eventName, validator, handler, options)
-- RemoveWhitelist(target)
-- RequestShieldScreenshot(src)
-- ScanPolicyFingerprint(moduleFile, policy)
-- ScanResourceSnapshot(name, expected, callback)
-- SealScanCache(raw)
-- SetExempt(playerId, durationMs, reason)
-- SetPlayerExempt(playerId, state, durationMs, reason)
-- WhitelistArea(playerId, areaName, durationSec)
-- acV2Challenge(build, license, fp, version)
-- acV2Fingerprint()
-- acV2Integrity(raw)
-- acV2VerifyResponse(raw, build, license, fp, version, nonce, httpCode)
-- addAdmin(playerId)
-- addCheatSignature(pattern, signatureName, severity)
-- addSignatureEscrowSkip(resourceName, note)
-- addSignatureException(resourceName, filePath, signatureName, note)
-- applyTimeWithFramework(h, m)
-- applyWeatherWithFramework(weather)
-- approveResource(resourceName, approvedBy)
-- ban(playerId, reason)
-- batchDetection(playerName, license, steam, discord, ip, dtype, reason, punishment, banID, screenshot, configKey)
-- batchLog(message, playerId, playerName)
-- batchWebhook(url, payload)
-- blockResource(resourceName, reason)
-- centralHandshake()
-- centralPoll()
-- centralStatus()
-- checkIpReputation(ip)
-- cipherHasSession(src)
-- cipherIssueKey(src)
-- cipherVerify(src, payload, signature)
-- clearInventory(src)
-- crashGuardInspect(v)
-- crashGuardReject(src, p)
-- emergencyLockdown(reason)
-- fakeTriggerTrap(eventName, typ)
-- fakeTriggerWhitelist(eventName)
-- freezePlayer(src, freeze)
-- getAdminType(playerId)
-- getBanInfo(banID)
-- getBans(limit, offset)
-- getBaseline()
-- getBatchStats()
-- getCleanupStats()
-- getConfig(configType)
-- getInfectedFiles()
-- getOnlinePlayers()
-- getPlayerLocale(src)
-- getResources()
-- getRuntimeStats()
-- getSourceKey()
-- getStats()
-- getSuspicious()
-- giveWeapon(src, weapon, ammo)
-- healAll()
-- invalidateSignatureCache()
-- isAdmin(playerId)
-- isAdminMenuAllowed(playerId)
-- isPlayerFrozen(src)
-- isPlayerMuted(src)
-- isQuarantined(src)
-- isStaffPlayer(playerId)
-- issueEventKey(src)
-- licenseStatus()
-- lockdownStatus()
-- massFreeze(state)
-- mutePlayer(src, durationSec, reason, actor)
-- offlineBan(data, reason)
-- offlineBanByLicense(...)
-- phoneNotify(targetSrc, title, body, opts)
-- phoneNotifyAdmins(title, body, opts)
-- punish(playerId, reason, image, config, punish)
-- quarantine(src, reason, sec)
-- quarantineList()
-- refreshPanelPermissions()
-- refreshPanelWhitelist()
-- releaseQuarantine(src)
-- reloadSignatureExceptions()
-- reloadSignatureScanCaches()
-- removeAdmin(playerId)
-- removeSignatureEscrowSkip(idOrName)
-- removeSignatureException(id)
-- removeWhitelist(playerId)
-- reportInfection(resource, file, sigs, severity, callback)
-- rescanResources()
-- runCleanup()
-- scanAllResources()
-- scanSingleResource(name)
-- screenCapture(src, requestedBy)
-- setLockdown(state, reason)
-- setPlayerArmor(src, armor)
-- setPlayerHealth(src, hp)
-- setPlayerLocale(src, lang)
-- setSpeedLimit(kmh)
-- slayPlayer(src)
-- spectatePlayer(adminSrc, targetSrc)
-- stripWeapons(src)
-- translate(key, ...)
-- translateForPlayer(src, key, ...)
-- tsAutoSetup()
-- tsBackdoorScanStatus()
-- tsLicenseRecheck()
-- tsScanBackdoors(callback)
-- tsScanEvents()
-- tsSignatureScanStatus()
-- unban(banID)
-- unmutePlayer(src)
-- v6ScreenWatchLatest(serverId)
-- v6ScreenWatchPoll(rid)
-- v6ScreenWatchRequest(serverId, mode, requestedBy, panelUrl, forceBase64)
-- v9StreamHasSession(serverId)
-- warnPlayer(src, reason, actor)
-- webBridgeApplyInventory(src, action, itemName, count, slot)
-- webBridgeApplyMoney(src, moneyType, amount, action)
-- webBridgeFindByCitizen(cid)
-- webBridgeFindByLicense(license)
-- webBridgeGrantAdmin(src)
-- webBridgeRevokeAdmin(src)
-- whitelistPlayer(playerId, duration)

-- tosun-ac-guardian / server
-- guardianAlive()
-- guardianHold(reason,seconds)

-- tosun_render / server
-- GetStatus()

Complete client export catalog and bounded local grace#

Client SetExempt takes state, milliseconds and reason; server SetExempt takes the player source, milliseconds and reason. Client PauseDetections grants the same bounded local appearance/movement/camera grace, not a universal pause. Local grants share a 240-second extension budget over ten minutes and at most 32 reason entries. IsExempt(config) needs the exact detector key for local grace; IsExempt() answers only verified staff or trusted full/pause relief. Weapon, event, injection and unknown detections remain active. Handle false instead of retrying every frame.

-- tosun-ac / client
-- GetExemptions()
-- IsExempt(config)
-- IsPlayerAdmin()
-- NativeGuardThreat()
-- NativeGuardToken()
-- PauseDetections(durationMs)
-- SetExempt(state, durationMs, reason)
-- SetSpawned(state)
-- ShieldCaptureForBan(callback)
-- ShieldFlushBanVideo(callback)
-- TriggerSafeServerEvent(eventName, ...)
-- getConfig()
-- getV12Tolerance(key, default)
-- incNetRequest()
-- incScreenshotEvent()
-- shieldHook(hookType, detailJson)

Understand private state and result semantics#

TosunAcState is internal to the AC resource; other resources should use the documented exports. Its server setExempt, setPause and setMovement return booleans and bound leases to five minutes. A failed notification does not commit a new increased lease; a revocation or reduction is retained privately even when false is returned. Full exemption, pause and movement leases are independent. setStaff only writes a compatibility mirror and cannot grant verified admin authority. Historical isExemptFromBag/isPausedFromBag names read verified private leases, not writable player bags. Export success is not proof of delivery to every client or a universal server-detector pause.

-- Internal AC server API; external resources use guarded exports.
-- TosunAcState.setExempt(id, active, ms) -> boolean
-- TosunAcState.setPause(id, ms) -> boolean
-- TosunAcState.setMovement(id, ms) -> boolean
-- TosunAcState.remaining(id, kind) -> remaining milliseconds
-- TosunAcState.setStaff(id, staff) -> compatibility mirror only
-- AddWhitelist(target, durationSec): seconds
-- WhitelistArea(playerId, areaName, durationSec): seconds
-- IsInArea: named record lookup, not a coordinate/permission check
-- WhitelistArea grants broad client relief, not one chosen detector.
-- BypassDetection: detectionKey is ignored; full exemption, <=60000ms
-- Client: IsExempt("ts.antiFreeCam") -> scoped camera grace
-- Client: IsExempt() -> verified staff/full/pause only

Event names are a catalog, not an authorization plan#

This source-generated catalog lists literal AC protocol events by registration side. It cannot enumerate computed names or every event in your own resources. Do not manually replay internal key, punishment, configuration or menu events. Discovery records names and transport direction; it cannot know who owns an item or whether a reward was earned. Use your validated RegisterSafeEvent workflow for custom sensitive actions. Panel protection and ac_protected_events feed fake-trigger/honeypot rules, not server validators; leave EventScanner.autoProtect=false for installation.

-- tosun-ac/client/AddEventHandler
-- CEventShockingGunshotFired
-- baseevents:onPlayerDied
-- baseevents:onPlayerKilled
-- esx:onPlayerDeath
-- esx_ambulancejob:revive
-- esx_basicneeds:onRevive
-- gameEventTriggered
-- hospital:client:Revive
-- hospital:client:SetDeathState
-- hospital:client:SetLaststand
-- hospital:client:isDead
-- onClientResourceStart
-- onClientResourceStop
-- playerSpawned
-- qb-ambulancejob:client:RevivePlayer
-- qb-medical:client:OnDeath
-- qb-medical:client:OnRevive
-- tosun-ac:nui:pushToolState
-- tosun-ac:uploadTokenUpdated
-- ts_anticheat:adminStateChanged
-- ts_anticheat:adminStatus
-- ts_anticheat:bridge:capture
-- ts_anticheat:bridge:clearInventory
-- ts_anticheat:bridge:freeze
-- ts_anticheat:bridge:giveWeapon
-- ts_anticheat:bridge:heal
-- ts_anticheat:bridge:mute
-- ts_anticheat:bridge:revive
-- ts_anticheat:bridge:setArmor
-- ts_anticheat:bridge:setHealth
-- ts_anticheat:bridge:slay
-- ts_anticheat:bridge:speedLimit
-- ts_anticheat:bridge:stripWeapons
-- ts_anticheat:bridge:teleport
-- ts_anticheat:bridge:time
-- ts_anticheat:bridge:warning
-- ts_anticheat:bridge:weather
-- ts_anticheat:checkTaze
-- ts_anticheat:cipher:assigned
-- ts_anticheat:cipher:request_refresh
-- ts_anticheat:clearDone
-- ts_anticheat:configUpdated
-- ts_anticheat:detectclient
-- ts_anticheat:internal:receiveKey
-- ts_anticheat:internal:trapsChanged
-- ts_anticheat:isAdmin
-- ts_anticheat:joinBundle
-- ts_anticheat:liveSSRequest
-- ts_anticheat:newDetection
-- ts_anticheat:openAdminMenu
-- ts_anticheat:openAdminMenuAuthorized
-- ts_anticheat:panelBroadcast
-- ts_anticheat:panelHeal
-- ts_anticheat:panelRevive
-- ts_anticheat:panelTime
-- ts_anticheat:panelWeather
-- ts_anticheat:promptOpenMenu
-- ts_anticheat:receiveKey
-- ts_anticheat:receiveLiveSS
-- ts_anticheat:receiveLiveVideo
-- ts_anticheat:receivePlayerCount
-- ts_anticheat:receiveScreenshot
-- ts_anticheat:requestCoords
-- ts_anticheat:resourceGuardSync
-- ts_anticheat:shield:requestScreenshot
-- ts_anticheat:shield:uploadConfig
-- ts_anticheat:startVideoLiveStream
-- ts_anticheat:startVideoLiveWeb
-- ts_anticheat:startVideoRecording
-- ts_anticheat:stopVideoLiveStream
-- ts_anticheat:stopVideoLiveWeb
-- ts_anticheat:stopVideoRecording
-- ts_anticheat:syncBanList
-- ts_anticheat:syncConfig
-- ts_anticheat:syncIdentifiers
-- ts_anticheat:syncLogs
-- ts_anticheat:syncPlayers
-- ts_anticheat:takeScreenshot
-- ts_anticheat:unbanDone
-- ts_anticheat:webPanelScreenshot

-- tosun-ac/client/RegisterNUICallback
-- Armour
-- DeleteAll
-- DeleteObjects
-- DeletePeds
-- DeleteVehicles
-- GetPlayerIdentifiers
-- Health
-- addLog
-- armourPlayer
-- banPlayer
-- bringAll
-- bringPlayer
-- cancelAnimation
-- clearNearbyObjects
-- clearNearbyPeds
-- clearNearbyVehicles
-- devtoolsdetected
-- exit
-- freezeAll
-- freezePlayerToggle
-- getBans
-- getLogs
-- getPlayerCount
-- getPlayers
-- giveWeaponPlayer
-- healAll
-- healPlayer
-- isInVehicle
-- kickPlayer
-- liveWatchStart
-- liveWatchStop
-- nuiDependencyMissing
-- nuiWatermark
-- repair
-- returnOCRResult
-- reviveAll
-- revivePlayer
-- screenshotPlayer
-- selfRevive
-- setHealthPlayer
-- setTime
-- setWeather
-- shield_devtools
-- shield_heartbeat
-- shield_heartbeat_fail
-- shield_screenshot
-- shield_tokens
-- shield_video_final
-- shield_video_segment
-- slayPlayer
-- spawnVehicle
-- spectatePlayer
-- stopSpectate
-- stripWeaponsPlayer
-- toggleESP
-- toggleFreecam
-- toggleGodmode
-- toggleInvisible
-- toggleNoclip
-- tosunRenderResult
-- tpToPlayer
-- unbanPlayer
-- verifyModel
-- videoLiveSegmentResult
-- videoRecordingResult
-- videoRecordingStartResult
-- warnPlayerNUI

-- tosun-ac/client/RegisterNetEvent
-- QBCore:Client:OnPlayerLoaded
-- QBCore:Client:OnPlayerUnload
-- esx:onPlayerDeath
-- esx:onPlayerLogout
-- esx:playerLoaded
-- esx_ambulancejob:revive
-- esx_basicneeds:onRevive
-- hospital:client:Revive
-- hospital:client:SetDeathState
-- hospital:client:SetLaststand
-- hospital:client:isDead
-- qb-ambulancejob:client:RevivePlayer
-- qb-medical:client:OnDeath
-- qb-medical:client:OnRevive
-- qbx_core:client:playerLoggedIn
-- qbx_multicharacter:client:chooseChar
-- ts_anticheat:adminStateChanged
-- ts_anticheat:adminStatus
-- ts_anticheat:bridge:capture
-- ts_anticheat:bridge:clearInventory
-- ts_anticheat:bridge:freeze
-- ts_anticheat:bridge:giveWeapon
-- ts_anticheat:bridge:heal
-- ts_anticheat:bridge:mute
-- ts_anticheat:bridge:revive
-- ts_anticheat:bridge:setArmor
-- ts_anticheat:bridge:setHealth
-- ts_anticheat:bridge:slay
-- ts_anticheat:bridge:speedLimit
-- ts_anticheat:bridge:stripWeapons
-- ts_anticheat:bridge:teleport
-- ts_anticheat:bridge:time
-- ts_anticheat:bridge:warning
-- ts_anticheat:bridge:weather
-- ts_anticheat:checkTaze
-- ts_anticheat:cipher:assigned
-- ts_anticheat:cipher:request_refresh
-- ts_anticheat:clearDone
-- ts_anticheat:detectclient
-- ts_anticheat:isAdmin
-- ts_anticheat:joinBundle
-- ts_anticheat:liveSSRequest
-- ts_anticheat:newDetection
-- ts_anticheat:openAdminMenu
-- ts_anticheat:openAdminMenuAuthorized
-- ts_anticheat:panelBroadcast
-- ts_anticheat:panelHeal
-- ts_anticheat:panelRevive
-- ts_anticheat:panelTime
-- ts_anticheat:panelWeather
-- ts_anticheat:promptOpenMenu
-- ts_anticheat:receiveEventKey
-- ts_anticheat:receiveKey
-- ts_anticheat:receiveLiveSS
-- ts_anticheat:receiveLiveVideo
-- ts_anticheat:receivePlayerCount
-- ts_anticheat:receiveScreenshot
-- ts_anticheat:requestCoords
-- ts_anticheat:resourceGuardSync
-- ts_anticheat:shield:requestScreenshot
-- ts_anticheat:shield:uploadConfig
-- ts_anticheat:startVideoLiveStream
-- ts_anticheat:startVideoLiveWeb
-- ts_anticheat:startVideoRecording
-- ts_anticheat:stopVideoLiveStream
-- ts_anticheat:stopVideoLiveWeb
-- ts_anticheat:stopVideoRecording
-- ts_anticheat:syncBanList
-- ts_anticheat:syncConfig
-- ts_anticheat:syncIdentifiers
-- ts_anticheat:syncLogs
-- ts_anticheat:syncPlayers
-- ts_anticheat:takeScreenshot
-- ts_anticheat:unbanDone
-- ts_anticheat:uploadToken
-- ts_anticheat:webPanelScreenshot

-- tosun-ac/server/AddEventHandler
-- QBCore:Server:OnPlayerLoaded
-- QBCore:Server:PlayerLoaded
-- chatMessage
-- clearPedTasksEvent
-- entityControlEvent
-- entityCreated
-- entityCreating
-- esx:playerLoaded
-- eventTriggered
-- explosionEvent
-- fireEvent
-- giveWeaponEvent
-- onResourceStart
-- onResourceStop
-- onServerResourceStart
-- playerConnecting
-- playerDropped
-- playerJoining
-- ptFxEvent
-- qbx_core:server:playerLoaded
-- rconCommand
-- removeAllWeaponsEvent
-- removeWeaponEvent
-- requestControlEvent
-- respawnPlayerPedEvent
-- startProjectileEvent
-- tosun-ac:nuiPermissionRefreshed
-- tosun-ac:panel:characterReady
-- tosun-ac:server:detection
-- tosun-ac:server:logResourceActivity
-- tosun-ac:server:nuiWatermark
-- tosun-ac:server:signedDetection
-- tosun-ac:settingsReloaded
-- ts_anticheat:GetPlayerIdentifiers
-- ts_anticheat:addAdmin_internal
-- ts_anticheat:addLog
-- ts_anticheat:adminDelEntity
-- ts_anticheat:banCommitted
-- ts_anticheat:banPlayer
-- ts_anticheat:banRelay
-- ts_anticheat:bridge:freeze
-- ts_anticheat:bringAllPlayers
-- ts_anticheat:bringPlayer
-- ts_anticheat:cipher:detection
-- ts_anticheat:cipher:request
-- ts_anticheat:clearTasks
-- ts_anticheat:client:scriptsReady
-- ts_anticheat:configUpdated
-- ts_anticheat:deleteObjects
-- ts_anticheat:deletePeds
-- ts_anticheat:deleteVehicles
-- ts_anticheat:freezeAllPlayers
-- ts_anticheat:getBanList
-- ts_anticheat:getLogs
-- ts_anticheat:getPlayerCount
-- ts_anticheat:getPlayers
-- ts_anticheat:healAllPlayers
-- ts_anticheat:internal:pushResourceGuard
-- ts_anticheat:internal:suspicious
-- ts_anticheat:kickPlayer
-- ts_anticheat:liveSSResult
-- ts_anticheat:liveWatchStart
-- ts_anticheat:liveWatchStop
-- ts_anticheat:logAdminMenu
-- ts_anticheat:newLog
-- ts_anticheat:playerBanned
-- ts_anticheat:requestAdminStatus
-- ts_anticheat:requestEventKey
-- ts_anticheat:requestKey
-- ts_anticheat:requestOpenAdminMenu
-- ts_anticheat:returnCoords
-- ts_anticheat:reviveAllPlayers
-- ts_anticheat:screenshotPlayer
-- ts_anticheat:screenshotResult
-- ts_anticheat:server:<computed suffix> [template only; not a runnable exact event]
-- ts_anticheat:server:checkIsAdmin
-- ts_anticheat:server:clientXkzuqBwmTjN7Gab4QzuN9QYZJ1WxxU
-- ts_anticheat:server:requestJoinHandshake
-- ts_anticheat:server:requestResourceGuard
-- ts_anticheat:server:requestSyncData
-- ts_anticheat:server:tazed
-- ts_anticheat:serverClear
-- ts_anticheat:setInvisible
-- ts_anticheat:setTime
-- ts_anticheat:setWeather
-- ts_anticheat:shield:ban_video_saved
-- ts_anticheat:spawnVehicle
-- ts_anticheat:targetArmour
-- ts_anticheat:targetFreeze
-- ts_anticheat:targetGiveWeapon
-- ts_anticheat:targetHeal
-- ts_anticheat:targetRevive
-- ts_anticheat:targetSetHealth
-- ts_anticheat:targetSlay
-- ts_anticheat:targetStripWeapons
-- ts_anticheat:targetWarn
-- ts_anticheat:tpToPlayer
-- ts_anticheat:unbanPlayer
-- ts_anticheat:v10:exec
-- ts_anticheat:v6:detection
-- ts_anticheat:v6:screenshotResult
-- ts_anticheat:verifyModel
-- ts_anticheat:videoResult
-- vehicleComponentControlEvent
-- weaponDamageEvent

-- tosun-ac/server/RegisterNetEvent
-- tosun-ac:panel:characterReady
-- tosun-ac:server:detection
-- tosun-ac:server:logResourceActivity
-- tosun-ac:server:nuiWatermark
-- tosun-guard:acMissing
-- tosun-guard:hello
-- tosun-guard:tick
-- tosun:nativeGuard:status
-- ts_anticheat:GetPlayerIdentifiers
-- ts_anticheat:addLog
-- ts_anticheat:adminDelEntity
-- ts_anticheat:banPlayer
-- ts_anticheat:banRelay
-- ts_anticheat:bridge:freeze
-- ts_anticheat:bringAllPlayers
-- ts_anticheat:bringPlayer
-- ts_anticheat:cipher:detection
-- ts_anticheat:cipher:request
-- ts_anticheat:client:scriptsReady
-- ts_anticheat:deleteObjects
-- ts_anticheat:deletePeds
-- ts_anticheat:deleteVehicles
-- ts_anticheat:freezeAllPlayers
-- ts_anticheat:getBanList
-- ts_anticheat:getLogs
-- ts_anticheat:getPlayerCount
-- ts_anticheat:getPlayers
-- ts_anticheat:healAllPlayers
-- ts_anticheat:kickPlayer
-- ts_anticheat:liveSSResult
-- ts_anticheat:liveWatchStart
-- ts_anticheat:liveWatchStop
-- ts_anticheat:logAdminMenu
-- ts_anticheat:requestAdminStatus
-- ts_anticheat:requestEventKey
-- ts_anticheat:requestKey
-- ts_anticheat:requestOpenAdminMenu
-- ts_anticheat:returnCoords
-- ts_anticheat:reviveAllPlayers
-- ts_anticheat:screenshotPlayer
-- ts_anticheat:screenshotResult
-- ts_anticheat:server:checkIsAdmin
-- ts_anticheat:server:clientXkzuqBwmTjN7Gab4QzuN9QYZJ1WxxU
-- ts_anticheat:server:requestJoinHandshake
-- ts_anticheat:server:requestResourceGuard
-- ts_anticheat:server:requestSyncData
-- ts_anticheat:server:tazed
-- ts_anticheat:serverClear
-- ts_anticheat:setInvisible
-- ts_anticheat:setTime
-- ts_anticheat:setWeather
-- ts_anticheat:shield:banVideo
-- ts_anticheat:shield:heartbeat_fail
-- ts_anticheat:shield:requestUploadConfig
-- ts_anticheat:shield:screenshot
-- ts_anticheat:shield:tokens
-- ts_anticheat:spawnVehicle
-- ts_anticheat:targetArmour
-- ts_anticheat:targetFreeze
-- ts_anticheat:targetGiveWeapon
-- ts_anticheat:targetHeal
-- ts_anticheat:targetRevive
-- ts_anticheat:targetSetHealth
-- ts_anticheat:targetSlay
-- ts_anticheat:targetStripWeapons
-- ts_anticheat:targetWarn
-- ts_anticheat:tpToPlayer
-- ts_anticheat:unbanPlayer
-- ts_anticheat:v10:exec
-- ts_anticheat:v6:detection
-- ts_anticheat:v6:screenshotResult
-- ts_anticheat:verifyModel
-- ts_anticheat:videoResult

-- tosun-ac/server/RegisterServerEvent
-- ts_anticheat:clearTasks

-- tosun-ac/shared/AddEventHandler
-- onClientResourceStart
-- onResourceStop
-- playerDropped
-- ts_anticheat:locale:reload
-- ts_anticheat:locale:setSelf
-- ts_anticheat:locale:sync

-- tosun-ac/shared/RegisterNetEvent
-- ts_anticheat:locale:setSelf
-- ts_anticheat:locale:sync

-- tosun-ac-guardian/server/AddEventHandler
-- onResourceStart
-- onResourceStop

-- tosun_render/server/AddEventHandler
-- onResourceStart

-- tosun-ac/client / RegisterCommand
-- stopspectate
-- tsdelaimed
-- tsfreecam
-- tsmenu
-- unspectate

-- tosun-ac/server / RegisterCommand
-- ac_cleanup
-- acfreeze
-- acping
-- acstats
-- acunfreeze
-- acwarn
-- capture
-- clearinv
-- emergency
-- giveweapon
-- massfreeze
-- mute
-- setarmor
-- sethp
-- speedlimit
-- stripweapons
-- tosunac_backdoorscan
-- tosunac_db_check
-- tosunac_db_status
-- tosunac_doctor
-- tosunac_eventscan
-- tosunac_integration
-- tosunac_license_status
-- tosunac_setup
-- ts
-- ts_adminsync
-- ts_broadcast
-- ts_capture
-- ts_clearinv
-- ts_emergency
-- ts_freeze
-- ts_giveweapon
-- ts_healall
-- ts_kickall
-- ts_lockdown
-- ts_massfreeze
-- ts_modping
-- ts_mute
-- ts_players
-- ts_revive
-- ts_setarmor
-- ts_sethp
-- ts_settime
-- ts_setweather
-- ts_slay
-- ts_speedlimit
-- ts_stripweapons
-- ts_tphere
-- ts_tpto
-- ts_unfreeze
-- ts_unmute
-- ts_v9_help
-- ts_warn
-- ts_warnings
-- unmute

-- tosun-ac/shared / RegisterCommand
-- ts_setlang

-- tosun-ac-guardian/server / RegisterCommand
-- tosunac_guardian_pause
-- tosunac_guardian_resume
-- tosunac_guardian_status

-- tosun_render/server / RegisterCommand
-- tosun_render_status

SafeEvent restart, queue and failure handling#

RegisterSafeEvent requires your own resource-prefixed name, validator and handler. The validator must return exactly true after checking current server-owned state. Remove the old raw network handler; the AC cannot cancel another resource’s independent handler. Re-register after either your resource or tosun-ac restarts. Client results are sent, queued_until_key, queue_full, invalid_event_or_arguments or resource_stopping. sent is transport dispatch, not a reward acknowledgement. Pending calls expire after 30 seconds and the queue holds at most 32 calls. A handler error has no automatic replay or success acknowledgement. Use a separate application receipt and an idempotent server operation; never automatically retry money or item rewards.

-- Client TriggerSafeServerEvent results:
-- true,  "sent"
-- false, "queued_until_key"
-- false, "queue_full"
-- false, "invalid_event_or_arguments"
-- false, "resource_stopping"

-- Server RegisterSafeEvent results:
-- true, "registered"
-- false + server_resource_required / use_own_resource_prefix
-- false + invalid_callbacks_or_options / already_registered / registration_capacity

-- Server log may say: application handler failed.
-- No automatic replay; implement an application receipt.

Record a reviewed infection report without assuming a commit#

reportInfection(resource, file, sigs, severity[, callback]) returns true only when the database operation was queued. The optional callback runs at most once with success and affectedRows; success requires a positive integer row count. A driver that never responds gives no completion guarantee. The example uses non-secret fictional names. Resource is 1–190 bytes (letters/digits/_.-), file 1–500 bytes, severity 1–50 letters/digits/_- (default warning). sigs is a nonempty string or dense 1–32 string array; joined value is at most 255 bytes. NUL/CR/LF are rejected. Invalid input, missing/rejected driver or synchronous error returns false. Do not automatically replay after uncertain completion.

-- A reviewed server reporting workflow; fictional non-secret labels.
-- resource: 1..190 bytes, letters/digits/underscore/dot/hyphen
-- file: 1..500 bytes; signatures joined: 1..255 bytes
-- severity: 1..50 bytes, letters/digits/underscore/hyphen (no dot)
local queued = exports["tosun-ac"]:reportInfection(
    "my-housing", "server.lua", {"reviewed_pattern"}, "warning",
    function(success, affectedRows)
        print(success and "[scan] report saved" or "[scan] report not confirmed")
    end)
-- queued=true is dispatch only; it is not the completion callback.
-- Do not automatically retry an operation with an uncertain outcome.