Knight docs
EN ID
GitHub

Players & Auth

Login flows, dialogs, admin flags and per-player state.

Knight does not force an authentication policy. A login flow is a pattern you build with callbacks, dialogs and the database.

A minimal login flow

knight
let DIALOG_LOGIN = 100;
let DIALOG_REGISTER = 101;
let loggedIn = {};

system::start() {
    let db = sqlite_open("data/accounts.db");
    sqlite_exec(db, "CREATE TABLE IF NOT EXISTS accounts (name TEXT PRIMARY KEY, hash TEXT)");
};

player::connect(int playerid) {
    let db = sqlite_open("data/accounts.db");
    let r = sqlite_query(db, "SELECT name FROM accounts WHERE name = ?", PlayerName(playerid));
    if (r != null && cache_get_row_count(r) > 0) {
        ShowPlayerDialog(playerid, DIALOG_LOGIN, 1, "Login", "Password:", "Login", "Cancel");
    } else {
        ShowPlayerDialog(playerid, DIALOG_REGISTER, 1, "Register", "Choose a password:", "Register", "Cancel");
    }
};

dialog::response(int playerid, int id, bool accepted, string input, int listitem) {
    if (id == DIALOG_REGISTER) {
        if (!accepted) { KickPlayer(playerid, "cancelled"); return; }
        let hash = hash_password(input);
        let db = sqlite_open("data/accounts.db");
        sqlite_exec(db, "INSERT INTO accounts VALUES (?, ?)", PlayerName(playerid), hash);
        loggedIn[PlayerName(playerid)] = true;
        SendClientMessage(playerid, "Registered.");
        return;
    }
    if (id == DIALOG_LOGIN) {
        let db = sqlite_open("data/accounts.db");
        let r = sqlite_query(db, "SELECT hash FROM accounts WHERE name = ?", PlayerName(playerid));
        if (r != null && cache_get_row_count(r) > 0
            && verify_password(input, cache_get_value_name(r, 0, "hash"))) {
            loggedIn[PlayerName(playerid)] = true;
            SendClientMessage(playerid, "Logged in.");
        } else {
            ShowPlayerDialog(playerid, DIALOG_LOGIN, 1, "Login", "Wrong password:", "Login", "Cancel");
        }
    }
};

Gating class and spawn

knight
player::request_class(int playerid, int classid) {
    return loggedIn[PlayerName(playerid)] == true;
};

player::request_spawn(int playerid) {
    return loggedIn[PlayerName(playerid)] == true;
};
Warning
Returning false from request_class blocks selection; request_spawn returning false tells the client the spawn was denied.

Player state and getters

knight
SetPlayerHealth(playerid, 100.0);
SetPlayerArmour(playerid, 50.0);
GivePlayerMoney(playerid, 500);
SetPlayerScore(playerid, 10);
SetPlayerInterior(playerid, 0);
SetPlayerVirtualWorld(playerid, 0);

let hp = GetPlayerHealth(playerid);
let money = GetPlayerMoney(playerid);
let team = GetPlayerTeam(playerid);
let pos = GetPlayerPos(playerid);

Admin flags

knight
SetPlayerAdmin(playerid, true);
if (IsPlayerAdmin(playerid)) {
    SendClientMessage(playerid, "You are an admin.");
}