Bridge-Funktionen

Was bridge.lua deinem Script auf der globalen Tabelle CsConfig gibt.

Ohne cs_config tun alle diese Funktionen nichts oder geben nil zurück. Du musst sie nie abfragen, bevor du sie aufrufst.

Beim Start

CsConfig.Boot

Server
CsConfig.Boot(version, check)

Einmal, am Ende deiner Server-Datei. Meldet das Script mit Version und eigener Prüfung. Mit cs_config landet das im gemeinsamen Block und auf der Status-Seite, ohne auf einer eigenen Zeile. Die Prüfung läuft nach etwa fünf Sekunden und erneut, wenn cs_config eine Tabelle angelegt hat. Schreib sie also so, dass sie mehrmals laufen darf.

versionstring
deine Version, von Hand gleich der fxmanifest.lua gehalten. Weicht sie ab, sagt es der Report.
checkfunction(fail, warn, note)
fail ist kaputt, warn ist seltsam, note eine Zahl für die Zeile. Alle drei nehmen ein Format wie string.format.
Beispiel
CsConfig.Boot('2.0.0', function(fail, warn, note)
    if #Config.Shops == 0 then
        return fail('Config.Shops is empty. There is nothing to open.')
    end

    warn('shop %d has no payment method enabled. It can only be looked at.', 3)

    note('%d shops', #Config.Shops)
    note('%s', Framework.Name)
end)

CsConfig.Database

Server
CsConfig.Database(plan)

Beschreibt, was dein Script von der Datenbank braucht, statt SQL mitzuliefern. cs_config vergleicht und zeigt den Unterschied auf der Seite Datenbank. Statt einer Tabelle darf eine Funktion kommen, sie wird einmal aufgerufen, etwa wenn der Tabellenname selbst eine Einstellung ist.

plan.notestring
ein Satz, wofür
plan.tables[].namestring
Tabellenname
plan.tables[].createtable
{ what, sql } für eine eigene Tabelle, oder { owner } für eine, die das Framework anlegt
plan.tables[].columns[]table
name, ddl, what, dazu need = 'feature' für eine Spalte, ohne die das Script startet und least als kleinste varchar-Breite
plan.tables[].indexes[]table
name, columns, what
Beispiel
CsConfig.Database({
    note = 'What each shop has on the shelf.',
    tables = { {
        name   = 'cs_shops_stock',
        create = { what = 'the stock table', sql = 'CREATE TABLE `cs_shops_stock` (...)' },
        columns = {
            { name = 'shop',  ddl = 'varchar(64) NOT NULL', what = 'which shop', least = 32 },
            { name = 'count', ddl = 'int(11) NOT NULL DEFAULT 0', what = 'how many are left' },
            { name = 'restocked', ddl = 'timestamp NULL', what = 'when it last filled up',
              need = 'feature' },
        },
        indexes = {
            { name = 'cs_shops_shop', columns = { 'shop' }, what = 'opening a shop' },
        },
    } },
})

Wenn sich etwas ändert

CsConfig.OnApply

Client + Server
CsConfig.OnApply(fn)

Läuft nach jeder Übernahme aus dem Menü. Bau dort neu, was du aus der Config zwischengespeichert hast und zwar alles. changed listet, was überhaupt überschrieben ist, nicht was sich gerade geändert hat und ein Zwischenspeicher hängt meist an mehr als einer Einstellung.

fnfunction(changed)
bekommt die Liste der überschriebenen Pfade
Beispiel
CsConfig.OnApply(function()
    RebuildShops()     -- refill lists in place, other code holds them
    LocaleReset()      -- a cached language pack is stale now
end)

Fragen an die Einstellungen

CsConfig.Allows

Server
CsConfig.Allows(rules, source)

Ob ein Spieler eine rules-Liste erfüllt. Nimmt die Liste oder die Tabelle, in der sie als who steht.

rulestable
sourcenumber
die Server-ID

Gibt zurückboolean | nil nil heißt: keine Liste. Dann entscheidet deine eigene Logik weiter.

Beispiel
function Config.HasFeature(source, feature)
    local said = CsConfig and CsConfig.Allows(Config.Features[feature], source)
    if said ~= nil then return said end

    return false
end

CsConfig.Notifier

Client
CsConfig.Notifier(at)

Ob eine Meldung noch die mitgelieferte Funktion ist. Nur nötig, wenn dein Script eine Meldung selbst gestaltet, sonst ignoriert genau diese Meldung die Einstellung.

atstring
'Notify.player', 'Notify.help' / 'Notify.all'

Gibt zurückfunction | nil die gebaute Meldung, wenn eine andere Resource eingestellt ist

Beispiel
if not (CsConfig and CsConfig.Notifier('Notify.player')) then
    -- the fancy one of your own
end

Fertige Seiten

CsConfig.WithLogging

Client + Server
return CsConfig.WithLogging(schema, { events = LOGS })

Baut die vier Discord-Seiten aus der Liste dessen, was dein Script loggt. Alle vier sind server = true. Gelesen und geschrieben wird Webhook auf der Tabelle deiner Resource, also cs_shops.Webhook und die gehört in eine server_scripts-Datei.

events[]table
{ key, label, de }. key = 'parkIn' heißt logParkIn und urls.parkIn in deiner webhook.lua.
Beispiel
local LOGS = {
    { key = 'parkIn',  label = 'Vehicle parked in', de = 'Fahrzeug eingeparkt' },
    { key = 'impound', label = 'Vehicle impounded', de = 'Fahrzeug abgeschleppt' },
}

return CsConfig.WithLogging({ ...your schema... }, { events = LOGS })

CsConfig.WithTexts

Client + Server
return CsConfig.WithTexts(schema, { groups = TEXTS })

Macht aus deinen Locale-Tabellen eine Seite je Sprache. groups ordnet die Zeilen und setzt Überschriften, eine Zeile ohne Gruppe steht unter Alles andere. Gelesen wird Config.Locales, mit root woanders.

groups[]table
{ head, de, keys, apply }. apply = 'reopen' für Zeilen, die in einem Fenster stehen.
Beispiel
local TEXTS = {
    { head = 'Notifications', de = 'Benachrichtigungen',
      keys = { 'no_money', 'no_space', 'bought' } },
    { head = 'The window', de = 'Das Fenster', apply = 'reopen',
      keys = { 'ui_total', 'ui_cash' } },
}

return CsConfig.WithTexts(schema, { groups = TEXTS })

Eine Zeile kann sich jetzt zur Laufzeit ändern. Wirf in OnApply dein gecachtes Sprachpaket weg und ruf string.format in einem pcall auf.

Ein L(), das nie wirft
function L(key, ...)
    local text = LocalePack()[key]
    if not text then return key end
    if select('#', ...) == 0 then return text end

    local held, said = pcall(string.format, text, ...)
    if held then return said end

    return text
end

Frage offen geblieben?

Schreib uns im Discord. Mit Konsolen-Auszug, Framework und Script-Version ist die erste Antwort meistens schon die Lösung.

Zum Support