Skip to content

Statebags ​

← BLN Society overview

On the client, BLN Society keeps a local copy of everything you need about organizations. Read these bags directly β€” no server callback required.

This page covers bag keys and shapes only. To call functions, see API Reference. When a bag updates, see Events.

Society ids in bag keys are always strings β€” use tostring(societyId) when looking up entries.


Three tiers ​

TierBagsLocationWho can readUse case
Globalsociety:ready, society:directory, society:revisionGlobalStateEvery clientBoot flag, public directory, cache invalidation
Player (replicated)society:memberships, society:dutyPlayer(serverId).stateAny clientInspect another player's membership or duty
Local (owner only)society:finance, society:paychecks, society:storageLocalPlayer.stateLocal player onlyBalances, wages, storage β€” never replicated

Memberships and duty replicate on purpose so other resources can inspect other players. Money, wages, and storage stay private β€” pushed only to the owner.


Global ​

Bags on GlobalState β€” same data on every client.

society:ready ​

Boot flag. true once migrations ran and the cache is warm. Do not read other bags until this is true.

Read:

lua
local ready = GlobalState['society:ready']
if not ready then return end

Returns:

lua
true

society:directory ​

Public list of every society on the server β€” name, member counts, world points. Safe for maps, phones, and job boards. No sensitive data.

Read:

lua
local directory = GlobalState['society:directory'] or {}
local sheriff = directory['3']

Returns:

lua
{
    ['3'] = {
        id = 3,
        name = 'Valentine Sheriff',
        isState = true,
        status = 'active',
        members = 4,
        onDuty = 2,
        point = {
            enabled = true,
            coords = { x = -324.1, y = 776.5, z = 117.8, h = 90.0 },
            blip = { enabled = true, sprite = 'blip_shop_store', name = 'Sheriff' },
            marker = { type = 'default', color = { r = 255, g = 255, b = 255, a = 180 }, scale = 1.0, distance = 15.0 },
            prompt = { enabled = true, name = 'Open', key = 0xCEFD9220, distance = 2.0 },
        },
    },
}

point is absent when the society has no world presence.


society:revision ​

Integer bumped on any structural change β€” society created, rank edited, member added, balance changed. Compare against a cached value to know when to rebuild directory-derived UI.

Read:

lua
local revision = GlobalState['society:revision'] or 0
if revision ~= myCachedRevision then
    RebuildSocietyList()
    myCachedRevision = revision
end

Returns:

lua
42

Player (replicated) ​

Bags on Player(serverId).state β€” readable for any player, including your own via LocalPlayer.state.

society:memberships ​

Every society the player belongs to. Keyed by society id as a string. perms is flattened with wildcards already expanded.

Read:

lua
-- Local player
local memberships = LocalPlayer.state['society:memberships'] or {}
local mine = memberships[tostring(societyId)]

-- Another player
local theirs = Player(serverId).state['society:memberships'] or {}
local entry = theirs[tostring(societyId)]

Returns:

lua
{
    ['3'] = {
        id = 3,
        name = 'Valentine Sheriff',
        isState = true,
        status = 'active',
        memberStatus = 'active',
        isOwner = false,
        joinedAt = '2026-05-02 11:20:00',
        dutySeconds = 7420,
        rank = {
            id = 12,
            name = 'Deputy',
            level = 40,
            salary = 30.0,
            salaryCurrency = 0,
            isOwnerRank = false,
        },
        perms = {
            ['members.view'] = true,
            ['duty.use'] = true,
            ['storage.use'] = true,
        },
    },
}

Check permissions with mine.perms['storage.use']. Returns an empty table {} when the player belongs to no societies.


society:duty ​

The society the player is currently on duty for, or false when off duty.

Read:

lua
-- Local player
local duty = LocalPlayer.state['society:duty']

-- Another player
local theirDuty = Player(serverId).state['society:duty']

Returns (on duty):

lua
{
    id = 3,
    name = 'Valentine Sheriff',
    rankId = 12,
    since = 1754939200,
}

Returns (off duty):

lua
false

Local (owner only) ​

Bags on LocalPlayer.state β€” never replicated. Only the owning client can read these.

society:finance ​

Balances for societies where the local player holds finances.view. Both society id and currency are string-keyed.

Read:

lua
local finance = LocalPlayer.state['society:finance'] or {}
local balances = finance[tostring(societyId)]
local cash = balances and balances['0']

Returns:

lua
{
    ['3'] = {
        ['0'] = 4820.5,
        ['1'] = 12.0,
    },
}

Returns nil for societies where the player lacks finances.view.


society:paychecks ​

Uncollected wages waiting at the society point.

Read:

lua
local paychecks = LocalPlayer.state['society:paychecks'] or {}
local pending = paychecks[tostring(societyId)]
if pending and pending.count > 0 then ShowCollectPrompt() end

Returns:

lua
{
    ['3'] = {
        count = 2,
        amounts = { ['0'] = 240.0 },
    },
}

society:storage ​

Storages the local player can see based on rank level. Only present when storage is enabled in config. Keyed by society id, then by storage key.

Read:

lua
local storage = LocalPlayer.state['society:storage'] or {}
local storages = storage[tostring(societyId)]
local safe = storages and storages.main_safe

Returns:

lua
{
    ['3'] = {
        main_safe = {
            invId = 'society_3_main_safe',
            label = 'Main Safe',
            slots = 50,
            maxWeight = 120,
            minRankLevel = 10,
        },
    },
}