# Developer > Developer API reference for ML Display Zone Category: ZONE DISPLAY · Source: https://miciomods.it/docs/ml-display-zone-developer · Last updated: 2026-07-09 ## 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 exports['ml_display_zone']:showMessage('Fort Zancudo', '12/25/2026 - 14:30') exports['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 exports['ml_display_zone']:setPermanentSubtitle('Balance: $%s') exports['ml_display_zone']:updatePermanentSubtitle(5000) -- shows "Balance: $5000" exports['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** ```lua function Handlers.CanShowNotification(zoneLabel) return true -- return false to block this notification end ``` Called before every zone notification. Return `false` to suppress the display for this zone entry. ### GetCustomZoneLabel **open/handlers_client.lua** ```lua function Handlers.GetCustomZoneLabel(zoneCode, defaultLabel) return nil -- return a string to override the label end ``` Called during zone detection. Return a string to replace the default zone name, or `nil` to keep it. ### OnZoneEnter **open/handlers_client.lua** ```lua function Handlers.OnZoneEnter(zoneLabel, zoneData) end ``` 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** ```lua function Handlers.OnZoneExit(zoneLabel) end ``` Fires when the player leaves a zone. ### OnNotificationShow **open/handlers_client.lua** ```lua function Handlers.OnNotificationShow(location, datetime) end ``` Fires after the notification is triggered. ### OnSubtitleSet **open/handlers_client.lua** ```lua function Handlers.OnSubtitleSet(text) end ``` Fires when a subtitle (permanent or temporary) is applied. ### OnDragModeToggle **open/handlers_client.lua** ```lua function Handlers.OnDragModeToggle(enabled) end ``` Fires when the player enters or exits UI drag mode. ### OnHide / OnShow **open/handlers_client.lua** ```lua function Handlers.OnHide() end function Handlers.OnShow() end ``` Fire when the display is hidden or shown via exports. ## Server Handlers Located in `open/handlers_server.lua`. ### CanRequestTime **open/handlers_server.lua** ```lua function Handlers.CanRequestTime(source) return true -- return false to block time requests end ``` Called when a client requests formatted time from the server. Return `false` to deny. ### FormatTime **open/handlers_server.lua** ```lua function Handlers.FormatTime(source, formattedTime) return nil -- return a string to override the formatted time end ``` 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** ```lua function Handlers.OnResourceStart() end ``` Fires when the resource starts. ## Open Callbacks ### Server, `open/server.lua` **open/server.lua** ```lua function OpenServer.OnTimeRequested(source) end function OpenServer.OnReady() end ``` - `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** ```lua function OpenClient.OnPlayerReady() end function OpenClient.OnEnterZone(zoneData) end function OpenClient.OnExitZone(zoneData) end ``` - `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 **Hide display during combat** ```lua -- In your combat script AddEventHandler('combat:started', function() exports['ml_display_zone']:hide() end) AddEventHandler('combat:ended', function() exports['ml_display_zone']:show() end) ``` **Show survival days as subtitle** ```lua -- After loading player data local days = playerData.survivalDays or 0 exports['ml_display_zone']:setPermanentSubtitle('Day %s') exports['ml_display_zone']:updatePermanentSubtitle(days) ``` **Block notification in specific jobs** **open/handlers_client.lua** ```lua function Handlers.CanShowNotification(zoneLabel) local job = Bridge.GetPlayerData()?.job?.name if job == 'police' then return false end return true end ``` **Custom label for gang territories** **open/handlers_client.lua** ```lua function Handlers.GetCustomZoneLabel(zoneCode, defaultLabel) local territories = { DAVIS = 'Ballas Territory', RANCHO = 'Vagos Territory', } return territories[zoneCode] -- nil falls back to default end ```