Configuration

7 min readUpdated 2 weeks ago

Overview

  • shared/config.lua: General settings, mode, item names, limits, post-it colors, book content, discoverables, command names
  • shared/config.lua: Cover, manual pages, encyclopedia categories, post-it colors
  • server/config_server.lua: Logger backend and Discord webhook URLs

General

shared/config.lua
1Config.Debug = false
2Config.Locale = 'en'
3Config.SaveInterval = 10
4Config.DiaryMode = 'metadata'
5Config.DiaryItemName = 'diary'
6Config.TornPageItemName = 'diary_page'
  • Debug: Console output for troubleshooting
  • Locale: Language code for translations. Falls back to en when missing
  • SaveInterval: Auto-save frequency in minutes. Only writes diaries flagged as dirty
  • DiaryMode: Storage model (see below)
  • DiaryItemName: Inventory item name for the diary
  • TornPageItemName: Item name for torn/shared pages

Diary Mode

Config.DiaryMode controls how diary data is keyed and shared.

'metadata'(default)

The diary is a transferable physical object. Each diary item carries a unique serial in its metadata; all data is keyed on that serial. Whoever is currently holding the item can read it, write notes, and unlock discoveries, including players who received it as a gift, looted it, or stole it. The original creator is recorded for audit only and does not gate access.

'license'

The diary is bound to the player's identifier. The serial is derived as LICENSE-<identifier>, so any diary item the player picks up opens their personal logbook. Other players cannot read or modify it even if they hold a diary item that previously belonged to that license.

Limits

shared/config.lua
1Config.PersonalPageLimit = 15
2Config.MaxTextSize = 8192          -- 8 KB per text note
3Config.MaxDataUrlSize = 524288     -- 512 KB per drawing
4Config.MaxDiaryTotalSize = 4194304 -- 4 MB total per diary
  • PersonalPageLimit: Maximum number of user-written pages. Pages added by other scripts via addPersonalNote bypass this limit (see Developer page)
  • MaxTextSize: Maximum byte size of a single text note's content
  • MaxDataUrlSize: Maximum byte size of a single drawing (base64 data URL)
  • MaxDiaryTotalSize: Hard cap on the total combined size of all notes in a single diary, enforced on every save and external add

Admin Commands

shared/config.lua
1Config.Commands = {
2    unlockAll      = { name = 'diary_unlockall', help = '...' },
3    unlock         = { name = 'diary_unlock',    help = '...' },
4    unlockCategory = { name = 'diary_unlockcat', help = '...' },
5    resetAll       = { name = 'diary_reset',     help = '...' },
6}
  • unlockAll: Unlock every entry in Config.Discoverables for the diary the admin is currently holding
  • unlock: Unlock a single entry by key
  • unlockCategory: Unlock every entry in a category
  • resetAll: Clear every discovery for the diary the admin is currently holding

Permissions are checked via Bridge.HasPermission(source), which reads the ACE group configured in ml_bridge. Renaming a command here also renames the in-game command, useful for avoiding collisions or matching server conventions.

Post-It Colors

shared/config.lua
1Config.PostItColors = {
2    ['yellow'] = { background = '#fef08a', text = '#3f3931' },
3    ['pink']   = { background = '#fecdd3', text = '#881337' },
4    ['blue']   = { background = '#bfdbfe', text = '#1e3a8a' },
5    ['green']  = { background = '#bbf7d0', text = '#14532d' },
6}
  • background: Background hex color
  • text: Text hex color

Book System

The diary contains a static manual with pre-written pages and a dynamic encyclopedia with player-unlocked discoveries.

Cover

The front cover is configurable. Texts fall back to the locale file when left nil; colors accept any CSS color; each decorative element toggles independently.

shared/config.lua
1Config.Book.cover = {
2    title    = nil,            -- nil = read from locale (cover_* keys)
3    subtitle = nil,            -- empty string hides it
4    hint     = nil,            -- e.g. 'Click to open'
5
6    titleColor    = '#c4a675',
7    subtitleColor = '#a08565',
8    ornamentColor = '#c4a675',
9
10    showEmbossedFrame   = true,
11    showStitching       = true,
12    showCornerOrnaments = true,
13    showSpineHighlight  = true,
14    showLeatherStraps   = false,
15
16    centerEmblem = '',         -- '' = no emblem, e.g. 'fa-skull'
17}
  • title, subtitle, hint: Cover texts. nil reads the matching cover_* locale key; an empty string hides the element
  • titleColor, subtitleColor, ornamentColor: Lettering and gold-ornament colors
  • showEmbossedFrame, showStitching, showCornerOrnaments, showSpineHighlight, showLeatherStraps: Toggle each decorative element on or off
  • centerEmblem: Optional FontAwesome icon above the title (e.g. 'fa-skull'). Empty string for no emblem

Manual Pages

shared/config.lua
1Config.Book = {
2    manual = {
3        title = 'Survival Guide',
4        pages = {
5            {
6                title = 'Welcome',
7                content = {
8                    { type = 'polaroid', image = 'https://...', caption = 'Your first shelter' },
9                    { type = 'text', value = 'Your text here.' },
10                    { type = 'text', value = 'Bold red text.', style = { 'bold', 'red' } },
11                    { type = 'post-it', text = 'Tip text', color = 'yellow' },
12                },
13            },
14        },
15    },
16}

Each page has a title and a content array of mixed blocks:

  • text: Plain text. Optional style array: 'bold', 'italic', 'red', etc.
  • polaroid: Image with caption
  • post-it: Colored sticky note. color must match a key in Config.PostItColors

Encyclopedia Categories

shared/config.lua
1Config.Book.encyclopedia = {
2    title = 'Encyclopedia',
3    introText = 'Introduction text...',
4    categories = {
5        ['fauna']     = { label = 'cat_fauna',     icon = 'fa-dragon' },
6        ['flora']     = { label = 'cat_flora',     icon = 'fa-leaf' },
7        ['locations'] = { label = 'cat_locations', icon = 'fa-map-marked-alt' },
8        ['items']     = { label = 'cat_items',     icon = 'fa-gem' },
9        ['notes']     = { label = 'cat_notes',     icon = 'fa-scroll' },
10    },
11}
  • label: Locale key for the category name
  • icon: FontAwesome class for the category icon

Add or remove categories as needed. Each category collects discoverables that have a matching collection field.

Discoverables

Entries that players unlock through exploration. Each key in Config.Discoverables is a unique identifier.

shared/config.lua
1Config.Discoverables = {
2    ['example_animal'] = {
3        type        = 'model',
4        model       = 'a_c_deer',
5        name        = 'White-Tailed Deer',
6        subTitle    = 'Forest Herbivore',
7        description = 'A common deer found in forested areas...',
8        collection  = 'fauna',
9        icon        = 'fa-paw',
10        image       = 'https://...',
11        imageStyle  = 'sketch',
12        layoutStyle = 'vertical',
13        stats       = {
14            ['TYPE']   = 'Herbivore',
15            ['RARITY'] = 'Common',
16        },
17    },
18}
  • type: Detection method (see below)
  • model: GTA model name or hash. Can be a string or array of strings to match multiple models
  • name: Display name in the encyclopedia
  • subTitle: Secondary label
  • description: Full description text
  • collection: Must match a category key in Config.Book.encyclopedia.categories
  • icon: FontAwesome icon class
  • image: Image URL displayed in the entry page
  • imageStyle: Visual frame style: 'polaroid', 'taped', 'sketch', 'noir', 'stamp'
  • layoutStyle: 'vertical' (portrait) or 'horizontal' (landscape)
  • stats: Key-value table displayed as a stats box

Discovery Types

Model detection: Triggers when the player targets a specific prop or ped model:

shared/config.lua
1{
2    type = 'model',
3    model = 'a_c_deer',
4    -- or multiple: model = { 'a_c_deer', 'a_c_deer_02' },
5}

Sphere zone: Triggers when the player enters a sphere zone:

shared/config.lua
1{
2    type = 'sphere',
3    coords = vec3(100.0, 200.0, 30.0),
4    radius = 15.0,
5}

Box zone: Triggers when the player enters a box zone:

shared/config.lua
1{
2    type = 'box',
3    coords = vec3(100.0, 200.0, 30.0),
4    size = vec3(10.0, 10.0, 5.0),
5    rotation = 45,
6}

Inventory item: Triggers when the player holds a specific item. A poller checks every 5 seconds while the diary is in the inventory and stops once all item-type entries are unlocked:

shared/config.lua
1{
2    type = 'item',
3    item = 'bandage',
4}
  • item: The item name as registered in the inventory system. The check runs through Bridge.HasItem, so it works on every inventory supported by ml_bridge (ox, qb, esx, tgiann, and others).

All four types are validated server-side: model and zone unlocks require the player to actually be in range, item unlocks require the player to actually hold the configured item. Forged attempts are rejected and logged to the exploits webhook.

Logger Backend

server/config_server.lua
1Config.Logger = 'discord'
  • 'discord': Uses Discord webhook URLs
  • 'ox_lib': Routes logs to DataDog, FiveManage, or Loki based on your ox_lib config

Discord Webhooks

server/config_server.lua
1Config.DiscordWebhook = {
2    DiaryActions     = 'INSERT_WEBHOOK_LINK_HERE',
3    DiscoveryActions = 'INSERT_WEBHOOK_LINK_HERE',
4    PageActions      = 'INSERT_WEBHOOK_LINK_HERE',
5    ExploitDetected  = 'INSERT_WEBHOOK_LINK_HERE',
6}
  • DiaryActions: Diary open/close events, admin command usage
  • DiscoveryActions: Discovery unlock/remove events
  • PageActions: Note creation, deletion, and torn page transfers
  • ExploitDetected: Distance spoof attempts, ownership mismatches, malformed payloads

Set any webhook to false to disable that log entirely.