F.A.Q
Setup
Set Config.Locale in shared/config.lua:
1Config.Locale = 'en'- Verify the item name matches
Config.DiaryItemName - In
metadatamode the item must have ametadata.serial. The first use auto-generates one if missing, confirm your inventory acceptsBridge.SetItemMeta - Check the F8 console for UI errors
Config.DiaryMode = 'metadata' keys the diary on the item's serial. The diary is a transferable physical object: any player who holds the item can read it, write notes, and unlock discoveries. Lose the item, lose access, until someone else picks it up. The original creator is recorded for audit only and does not gate access.
Config.DiaryMode = 'license' keys the diary on the player's identifier. Any diary item the player picks up opens their personal logbook. Other players cannot read it, even if they hold a diary item that previously belonged to that license.
Diary Sharing
Yes, in metadata mode. The diary travels with the item. Whoever currently holds it can read every page, add new discoveries while exploring, and write personal notes. When the item changes hands, the state bag re-syncs automatically on the new holder's client.
In license mode the diary is bound to the player's identifier and cannot be transferred.
In metadata mode the data follows the item. The diary serial stays in the database, so if the item is recovered the data is intact. If the item is permanently destroyed, the data is orphaned but not deleted (cache is evicted after 30 minutes of no access).
In license mode the data is tied to the player's identifier and survives any number of diary item losses.
Yes, in metadata mode. The diary item is the access token, possession is the rule. This enables RP scenarios like rival explorers stealing each other's research.
If you want diaries to be unstealable, switch to 'license' mode.
Discoverables
Add an entry to Config.Discoverables with a unique key:
1Config.Discoverables['my_animal'] = {
2 type = 'model',
3 model = 'a_c_deer',
4 name = 'Deer',
5 subTitle = 'Forest Animal',
6 description = 'Found in wooded areas.',
7 collection = 'fauna',
8 icon = 'fa-paw',
9 image = 'https://your-image-url.png',
10 imageStyle = 'sketch',
11 layoutStyle = 'vertical',
12}The collection field must match a category key in Config.Book.encyclopedia.categories.
model: Triggers when the player targets a specific prop or ped modelsphere: Triggers when the player enters a sphere zone (requirescoordsandradius)box: Triggers when the player enters a box zone (requirescoords,size, optionalrotation)item: Triggers when the player holds a specific item in the inventory (requiresitem). Polled every 5 seconds viaBridge.HasItem, compatible with every inventory supported byml_bridge.
All four are validated server-side. Zone and model unlocks check player range, item unlocks check actual possession. Forged attempts are rejected and logged to the exploits webhook.
Yes. Use the server export:
1exports.ml_diary:unlockDiscovery(source, 'my_discovery_key')The key must exist in Config.Discoverables. Returns false if the player has no diary or the key is invalid.
Five frame styles: 'polaroid', 'taped', 'sketch', 'noir', 'stamp'. Set via imageStyle on each discoverable.
Personal Notes
In the diaries database table, keyed on the diary's serial (or LICENSE-<identifier> in license mode). Each row stores the discoveries and personal notes as JSON in MEDIUMTEXT columns.
Every Config.SaveInterval minutes (default: 10). Only diaries flagged as dirty are written. onResourceStop flushes everything dirty on shutdown, and playerDropped flushes the diary that player had open.
Yes. Players can tear a page from their diary, which produces a diary_page item. Other players can use that item to insert the page into their own diary. The torn page carries the full content via item metadata.
Yes, via addPersonalNote:
1local ok, noteId = exports.ml_diary:addPersonalNote(source, {
2 title = 'Quest Update',
3 type = 'text',
4 content = 'You found a hidden door...',
5})These pages bypass `Config.PersonalPageLimit`: your script can always add page #16 even when the player has filled their personal pages. They are marked external = true and the user cannot edit or delete them from the in-game UI. Use removePersonalNote(source, noteId) to remove them later. The hard size cap (Config.MaxDiaryTotalSize, default 4 MB total) is still enforced.
Yes. noteContainsKeywords runs a single concatenated scan over every note's title and content:
1-- All keywords must appear (default mode)
2local matched = exports.ml_diary:noteContainsKeywords(src,
3 { 'safe', 'Elix Gen', 'door' })
4
5-- Any one is enough
6exports.ml_diary:noteContainsKeywords(src,
7 { 'door', 'gate' }, { mode = 'any' })
8
9-- Lua patterns (regex-lite) for codes like "lab12" or "lab-7"
10exports.ml_diary:noteContainsKeywords(src,
11 'lab%-?%d+', { pattern = true })Useful for "if the player documented X, unlock Y" mechanics.
Updates
- Download latest from CFX Portal
- Backup
shared/config.luaandserver/config_server.lua - Replace all files except those two
- Restart the resource
Diary data, personal pages, and discoveries are stored in the database and survive updates.