Settings Sharing
Configure database presets, private codes, public discovery, moderation, screenshots, limits, and security.
Settings Sharing
Settings Sharing lets players save multiple HUD presets, import validated JSON, exchange temporary private codes, and publish presets to a searchable community gallery. The server remains authoritative over ownership, limits, likes, downloads, moderation, and the complete settings schema.
Requirements
ox_libcallbacksoxmysqland@oxmysql/lib/MySQL.lua- One capture provider, either
screenshot-basicorscreencapture, only when uploaded thumbnails are enabled - A server-side FiveManage API key only when uploaded thumbnails are enabled
Use the FiveManage Setup guide to create a least-privilege Images token, store it as a server convar, configure the capture provider, and verify the complete upload path.
ensure ox_lib
ensure oxmysql
# Configure credentials before orbit-dynamichud-v2 starts.
set orbit_fivemanage_api_key "YOUR_FIVEMANAGE_API_KEY"
# Start only the provider selected by captureProvider.
ensure screencapture
# ensure screenshot-basic
ensure orbit-lib
ensure orbit-dynamichud-v2The resource manifest must include:
dependency 'oxmysql'
server_script '@oxmysql/lib/MySQL.lua'Feature configuration
All player-facing feature gates live in Config.ControlPanel.settingsShare.
Config.ControlPanel.settingsShare = {
enabled = true,
controlPanelTab = true,
standalonePage = true,
discovery = true,
localPresets = true,
manualImport = true,
privateSharing = true,
publicSharing = true,
moderation = true,
requireApproval = true,
thumbnails = true,
maxPresets = 12,
maxPublicPresets = 4,
maxPresetNameLength = 30,
maxPayloadBytes = 131072
}| Setting | Default | Effect |
|---|---|---|
enabled | true | Master switch. When false, client and server Settings Share logic stop. |
controlPanelTab | true | Show the UI Presets launcher in the control panel when standalonePage is also enabled. |
standalonePage | true | Allow the full Settings Share page, including entry from the control panel and /settingsshare. |
discovery | true | Browse, search, filter, like, and download published presets. |
localPresets | true | Save and update database-backed private presets. |
manualImport | true | Import a complete settings JSON document. |
privateSharing | true | Generate/import temporary private share codes. |
publicSharing | true | Submit or publish presets to discovery. |
moderation | true | Enable administrator Awaiting and Declined views. |
requireApproval | true | Send public uploads to Awaiting review. It only applies when moderation is also enabled. |
thumbnails | true | Enable the selected capture provider and FiveManage screenshot pipeline. Fallback previews remain available when false. |
maxPresets | 12 | Total private, awaiting, declined, and public database presets owned by one player. Clamped to 1-50. |
maxPublicPresets | 4 | Public preset cap per player. Clamped to 1-20 and never above maxPresets. |
maxPresetNameLength | 30 | Name limit. The server absolute maximum is 30 bytes. |
maxPayloadBytes | 131072 | Maximum serialized settings payload. Clamped to 16384-524288. |
Config.SettingsLocked = true disables Settings Share because imported or downloaded data cannot be allowed to replace server-enforced defaults.
Common feature combinations
Config.ControlPanel.settingsShare = {
enabled = true,
controlPanelTab = true,
standalonePage = true,
discovery = false,
localPresets = true,
manualImport = true,
privateSharing = false,
publicSharing = false,
moderation = false,
requireApproval = false,
thumbnails = false,
maxPresets = 12,
maxPublicPresets = 1,
maxPresetNameLength = 30,
maxPayloadBytes = 131072
}Config.ControlPanel.settingsShare.publicSharing = true
Config.ControlPanel.settingsShare.discovery = true
Config.ControlPanel.settingsShare.moderation = false
Config.ControlPanel.settingsShare.requireApproval = falseConfig.ControlPanel.settingsShare.controlPanelTab = false
Config.ControlPanel.settingsShare.standalonePage = trueServer limits and moderation
Config.SettingsShareServer = {
adminAce = 'orbit.settingsshare.admin',
maxStoredPresets = 250,
maxListResults = 60,
requestWindowSeconds = 10,
privateShareTtlSeconds = 900,
presetUploadCooldownSeconds = 300,
thumbnail = {
captureProvider = 'screencapture',
apiKey = GetConvar('orbit_fivemanage_api_key', ''),
presignedUrlEndpoint = 'https://api.fivemanage.com/api/v3/file/presigned-url',
fileEndpoint = 'https://api.fivemanage.com/api/v3/file',
deleteUnusedThumbnails = true,
allowedHosts = {
'r2.fivemanage.com',
'cdn.fivemanage.com'
},
encoding = 'jpg',
quality = 0.85,
timeoutMs = 15000,
maxWidth = 1920,
maxHeight = 1080,
captureAttempts = 3,
captureRetryDelayMs = 350,
uploadAttempts = 3,
retryDelayMs = 600
}
}| Setting | Default | Server bounds/purpose |
|---|---|---|
adminAce | orbit.settingsshare.admin | ACE required for moderation actions. |
maxStoredPresets | 250 | Global database preset cap, clamped to 10-10000. |
maxListResults | 60 | Maximum rows returned per list request, clamped to 10-200. |
requestWindowSeconds | 10 | Per-player action-rate window, clamped to 2-60 seconds. |
privateShareTtlSeconds | 900 | In-memory private-code lifetime, clamped to 60-86400 seconds. |
presetUploadCooldownSeconds | 300 | Delay after a successful save/update, clamped to 0-3600. 0 disables it. |
thumbnail.captureProvider | screencapture | Capture resource to use: screenshot-basic or screencapture. Invalid values fall back to screenshot-basic. |
thumbnail.apiKey | convar | FiveManage key. Keep it server-side. |
thumbnail.presignedUrlEndpoint | FiveManage v3 endpoint | Endpoint used to request a presigned upload URL. |
thumbnail.fileEndpoint | FiveManage v3 file endpoint | Endpoint used to delete managed thumbnail files. |
thumbnail.deleteUnusedThumbnails | true | Delete a managed CDN file after its preset is deleted or its thumbnail is replaced. |
thumbnail.allowedHosts | FiveManage CDN hosts | HTTPS hosts accepted for returned thumbnail URLs. |
thumbnail.encoding | jpg | jpg or png. |
thumbnail.quality | 0.85 | Screenshot quality clamped to 0.1-1.0. |
thumbnail.timeoutMs | 15000 | Upload timeout clamped to 5000-30000 milliseconds. |
thumbnail.maxWidth | 1920 | Maximum captured width, clamped to 640-4096. |
thumbnail.maxHeight | 1080 | Maximum captured height, clamped to 360-4096. |
thumbnail.captureAttempts | 3 | Capture-stage attempts, clamped to 1-5. Each attempt waits for a freshly presented frame. |
thumbnail.captureRetryDelayMs | 350 | Base delay between capture attempts, clamped to 100-3000 milliseconds. |
thumbnail.uploadAttempts | 3 | Fresh capture/upload attempts, clamped to 1-5. |
thumbnail.retryDelayMs | 600 | Base retry delay, clamped to 100-3000 milliseconds and increased per attempt. |
Grant the configured moderation ACE in server.cfg:
add_ace group.admin orbit.settingsshare.admin allowWhen requireApproval is true, a public submission enters awaiting. An administrator can publish or decline it. Declined entries are exposed in the admin UI from runtime cache and can be restored while the resource remains running. When approval is disabled, valid public uploads publish immediately.
Upload cooldown
The default cooldown is five minutes. It starts after every successful private or public save/update. While active, the server rejects:
- another private preset save
- another public preset submission/update
- thumbnail preparation
- screenshot capture/upload ticket issuance
The cooldown is enforced by owner identifier on the server. UI checks are only presentation; they are not the security boundary.
Database storage
The resource creates these InnoDB tables automatically:
| Table | Purpose |
|---|---|
orbit_settings_presets | Preset owner, name, creator, settings, preview metadata, visibility/review state, thumbnail, statistics, and timestamps. |
orbit_settings_preset_likes | One like per preset and owner identifier, deleted automatically with its preset. |
The preset table stores an internal auto-increment database ID plus an opaque public ID. Indexed owner, visibility, review, popularity, rating, creator, and name fields keep lists/searches bounded. Listing endpoints return validated preview data; complete settings JSON is loaded only when needed.
Do not manually edit settings JSON in the database. Use the UI so schema validation, ownership checks, metadata updates, and statistics stay consistent.
Private share codes
Private share codes look like:
DJ7F-K9L2-8MNP-Q4XRThey contain 16 unambiguous uppercase letters/numbers in four groups. Private codes:
- are held in server memory, not the database
- contain the validated preset settings and minimal metadata needed for import
- are limited to one active code per player
- replace that player's previous code
- expire after
privateShareTtlSeconds(15 minutes by default) - expire when removed, when the owner disconnects, or when the resource/server restarts
Importing a private code creates an independent preset for the recipient. Later changes to either copy do not synchronize.
Manual JSON import
Manual import accepts only a complete settings document matching the current server schema. The server checks:
- valid JSON and payload size
- every required root and nested key
- no unknown/extra keys
- allowed enum values and finite numeric ranges
- complete layout objects
- valid status colors, icons, opacity, widgets, and priorities
- supported HUD, shape, player-info, speedometer, and performance values
This strict check applies to manual imports, private codes, saves, updates, public uploads, and downloads before settings can be applied. Do not remove keys from exported JSON or add custom metadata inside the settings object.
Preset names permit ASCII letters, numbers, single spaces, apostrophes, and hyphens. They must start and end with a letter/number, cannot contain repeated separator characters, and cannot exceed the configured limit or the server maximum of 30 bytes. URLs, emoji, control characters, and arbitrary markup are rejected.
Public discovery
Discovery supports:
- search by preset name or creator name
- Most Popular, Top Rated, and Latest sorting
- gallery and list views
- liked-only filtering
- unique per-player likes
- server-counted downloads
- owner/admin delete controls
- public updates by the owner
Likes and downloads are updated on the server. The popularity score combines downloads and likes; clients cannot submit authoritative counts.
Thumbnail capture
When thumbnails are disabled or unavailable, the UI uses the built-in status/speedometer fallback preview. When enabled:
- The server verifies ownership, feature access, limits, cooldown, and request rate.
- The server requests a short-lived FiveManage presigned URL.
- The active NUI serializes the current visible HUD state for capture.
- A capture-only DUI loads the same compiled frontend and renders that state at the active game resolution.
- The client draws the rendered HUD as a full-screen runtime texture over the game frame and temporarily enables the minimap.
- The configured
screenshot-basicorscreencaptureprovider captures the composed game and HUD frame and uploads it directly to the presigned URL. - Transient capture/upload failures are retried within the configured bounds; every attempt requests a fresh frame.
- The client restores the normal HUD and the player's previous radar state even when capture fails.
- The upload is stored in the shared
orbit-dynamichuddirectory with its short-lived marker in the filename. The server accepts only an HTTPS result from an allowed hostname whose storage key contains that marker, then verifies the uploaded JPEG/PNG bytes and retains the verified key for safe cleanup.
This is the actual DynamicHUD frontend rendered through its normal components in capture mode, rather than a separately styled approximation. The game world, minimap, and visible HUD components are combined before the selected provider captures the frame.
Only the configured capture resource must be installed and started. Do not start both solely for DynamicHUD:
Config.SettingsShareServer.thumbnail.captureProvider = 'screencapture'
-- or: 'screenshot-basic'set orbit_fivemanage_api_key "YOUR_FIVEMANAGE_API_KEY"
# Match the resource to captureProvider.
ensure screencapture
# ensure screenshot-basic
ensure orbit-dynamichud-v2If custom capture fails, the preset can still be saved or published without a thumbnail and will use the fallback preview. A failed capture does not produce a trusted thumbnail token.
Never expose the FiveManage API key in shared/client config, NUI messages, or frontend environment variables.
See FiveManage Setup for account/team creation, token scope, start order, verification, rotation, and troubleshooting.
When thumbnail.deleteUnusedThumbnails is enabled, DynamicHUD also asks FiveManage to remove a managed image after its preset is deleted or its thumbnail is replaced. Failed cleanup is non-blocking and never makes the preset operation fail.
Commands and access
/settingsshare opens the standalone page when these conditions are met:
Config.Commands.settingsshare.enabled = true- Settings Share
enabled = true standalonePage = true- at least one Settings Share feature is available
Config.SettingsLocked = false
The control-panel launcher separately requires controlPanelTab = true, standalonePage = true, and an enabled control panel.
Operational checklist
- Confirm
oxmysqlstarts before DynamicHUD and no database initialization error appears. - Keep
maxStoredPresets, per-player limits, list limits, and cooldowns appropriate for the server size. - Grant the moderation ACE only to trusted groups.
- Test private, awaiting, published, declined, like, download, update, and delete flows.
- Restart the resource once to verify private codes expire as intended.
- If thumbnails are enabled, verify the selected provider is started, capture the HUD and minimap, and confirm the returned hostname is in
allowedHosts. - Back up the two Settings Share tables with the rest of the server database.