Developer

4 min readUpdated 2 weeks ago

Overview

Integration uses client-side exports for display control and the open/ folder for event hooks. No server exports are exposed. The Handlers table in open/handlers_client.lua and open/handlers_server.lua controls zone detection and notification behavior.

Client Exports

Display Control

  • show(): Re-enable the zone display after hiding
  • hide(): Hide the zone display entirely
  • isVisible(): Returns true if the display is currently enabled

Custom Messages

  • showMessage(location, datetimeOverride?): Trigger a zone notification with custom text. datetimeOverride replaces the time line entirely if provided.
lua
1exports['ml_display_zone']:showMessage('Fort Zancudo', '12/25/2026 - 14:30')
2exports['ml_display_zone']:showMessage('Secret Bunker') -- uses current time

Permanent Subtitle

  • setPermanentSubtitle(text): Set a persistent subtitle below the zone label. Supports %s placeholder for dynamic values.
  • updatePermanentSubtitle(value): Update the %s placeholder value without changing the template
  • removePermanentSubtitle(): Clear the permanent subtitle
lua
1exports['ml_display_zone']:setPermanentSubtitle('Balance: $%s')
2exports['ml_display_zone']:updatePermanentSubtitle(5000) -- shows "Balance: $5000"
3exports['ml_display_zone']:removePermanentSubtitle()

Temporary Subtitle

  • setSubtitleMessage(text, duration?): Show a temporary subtitle for duration milliseconds (default: fades after animation)
  • removeSubtitleMessage(): Clear the temporary subtitle immediately

State & Theme

  • getLastZone(): Returns the last entered zone label as a string, or nil
  • getCurrentSettings(): Returns the player's current settings table (theme, animation, font, toggles)
  • setTheme(themeName): Switch the UI theme. Options: 'default', 'wasteland', 'cyberpunk', 'noir', 'fantasy'

Client Handlers

Located in open/handlers_client.lua. Return values control behavior.

CanShowNotification

open/handlers_client.lua
1function Handlers.CanShowNotification(zoneLabel)
2    return true -- return false to block this notification
3end

Called before every zone notification. Return false to suppress the display for this zone entry.

GetCustomZoneLabel

open/handlers_client.lua
1function Handlers.GetCustomZoneLabel(zoneCode, defaultLabel)
2    return nil -- return a string to override the label
3end

Called during zone detection. Return a string to replace the default zone name, or nil to keep it.

OnZoneEnter

open/handlers_client.lua
1function Handlers.OnZoneEnter(zoneLabel, zoneData)
2end

Fires when the player enters any zone (native or custom). zoneData contains the custom location table for Config.Locations zones, or nil for native zones.

OnZoneExit

open/handlers_client.lua
1function Handlers.OnZoneExit(zoneLabel)
2end

Fires when the player leaves a zone.

OnNotificationShow

open/handlers_client.lua
1function Handlers.OnNotificationShow(location, datetime)
2end

Fires after the notification is triggered.

OnSubtitleSet

open/handlers_client.lua
1function Handlers.OnSubtitleSet(text)
2end

Fires when a subtitle (permanent or temporary) is applied.

OnDragModeToggle

open/handlers_client.lua
1function Handlers.OnDragModeToggle(enabled)
2end

Fires when the player enters or exits UI drag mode.

OnHide / OnShow

open/handlers_client.lua
1function Handlers.OnHide()
2end
3
4function Handlers.OnShow()
5end

Fire when the display is hidden or shown via exports.

Server Handlers

Located in open/handlers_server.lua.

CanRequestTime

open/handlers_server.lua
1function Handlers.CanRequestTime(source)
2    return true -- return false to block time requests
3end

Called when a client requests formatted time from the server. Return false to deny.

FormatTime

open/handlers_server.lua
1function Handlers.FormatTime(source, formattedTime)
2    return nil -- return a string to override the formatted time
3end

Called after the server formats the time string. Return a custom string to override it, or nil to keep the default.

OnResourceStart

open/handlers_server.lua
1function Handlers.OnResourceStart()
2end

Fires when the resource starts.

Open Callbacks

Server,open/server.lua

open/server.lua
1function OpenServer.OnTimeRequested(source)
2end
3
4function OpenServer.OnReady()
5end
  • OnTimeRequested: Called each time a player requests time data
  • OnReady: Called once when the resource is fully initialized

Client,open/client.lua

open/client.lua
1function OpenClient.OnPlayerReady()
2end
3
4function OpenClient.OnEnterZone(zoneData)
5end
6
7function OpenClient.OnExitZone(zoneData)
8end
  • OnPlayerReady: Called when the player is fully loaded
  • OnEnterZone: Called on custom zone entry. zoneData contains the location table from Config.Locations
  • OnExitZone: Called on custom zone exit

KVP Storage

Player data is stored client-side using FiveM KVP:

Key. Content

ml_dz_ui_pos: UI position and scale (JSON)

ml_dz_player_settings: Player preferences: font, animation, sound, toggles (JSON)

ml_dz_zone_visits: Per-zone visit counts (JSON)

KVP data persists across sessions per player machine.

Examples

lua
1-- In your combat script
2AddEventHandler('combat:started', function()
3    exports['ml_display_zone']:hide()
4end)
5
6AddEventHandler('combat:ended', function()
7    exports['ml_display_zone']:show()
8end)
lua
1-- After loading player data
2local days = playerData.survivalDays or 0
3exports['ml_display_zone']:setPermanentSubtitle('Day %s')
4exports['ml_display_zone']:updatePermanentSubtitle(days)
open/handlers_client.lua
1function Handlers.CanShowNotification(zoneLabel)
2    local job = Bridge.GetPlayerData()?.job?.name
3    if job == 'police' then return false end
4    return true
5end
open/handlers_client.lua
1function Handlers.GetCustomZoneLabel(zoneCode, defaultLabel)
2    local territories = {
3        DAVIS = 'Ballas Territory',
4        RANCHO = 'Vagos Territory',
5    }
6    return territories[zoneCode] -- nil falls back to default
7end