Knight docs
EN ID
GitHub

Panduan Bahasa

Sintaks, deklarasi, alur kontrol, dan data.

Deklarasi

File .sa berisi konfigurasi, callback, fungsi bantu, dan variabel.

knight
system::config() { ... };           // server.cfg
player::connect(int playerid) { };  // callback
function add(int a, int b) { return a + b; };
let total = 0;                      // variabel
Warning
Tanda ; di akhir blok callback, function, atau config wajib ada.

Variabel

knight
let hp = 100;       // int
let speed = 1.5;    // float
let name = "CJ";    // string
let online = true;  // bool

hp = 90;            // reassign
hp += 5;            // compound: += -= *= /= %=

Operator

OperatorArti
+ - * / %Aritmetika; + juga menggabung string
== != ~=Kesetaraan (~= alias !=)
< <= > >=Perbandingan
and or notLogika; juga &&, ||, !
+= -= *= /= %=Assignment gabungan
& | ^ ~ << >>Bitwise dan/atau/xor/not, shift

Alur kontrol

knight
player::command("/rank", int score) {
    if (score >= 100) {
        SendClientMessage(playerid, "Veteran");
    } else if (score >= 50) {
        SendClientMessage(playerid, "Reguler");
    } else {
        SendClientMessage(playerid, "Pemula");
    }
};

Loop

Semua bentuk loop umum tersedia. break keluar dari loop atau switch terdekat; continue lompat ke iterasi berikutnya.

knight
// while
let i = 0;
while (i < 10) {
    i += 1;
}

// do / while: minimal sekali jalan
do {
    i -= 1;
} while (i > 0);

// for gaya C
for (let n = 0; n < 5; n += 1) {
    if (n == 3) { break; }
}

// iterasi array
let names = ["amy", "bob", "cid"];
for (let name in names) {
    SendClientMessage(playerid, "Hai {name}");
}

// iterasi array + indeks
for (let index, name in names) {
    SendClientMessage(playerid, "{index}: {name}");
}

// iterasi map (kunci urut)
let scores = { "amy": 10, "bob": 20 };
for (let key in scores) {
    SendClientMessage(playerid, "{key} = {scores[key]}");
}

// lewati sebagian iterasi
for (let n = 0; n < 20; n += 1) {
    if (n % 2 == 0) { continue; }
    if (n > 15) { break; }
}

switch

switch membandingkan satu nilai dengan label case. Tidak ada fall-through: cabang pertama yang cocok dijalankan lalu switch selesai, jadi tidak perlu break di akhir cabang.

knight
player::command("/class", int id) {
    switch (id) {
        case 0:
            SendClientMessage(playerid, "Medis");
        case 1:
            SendClientMessage(playerid, "Polisi");
        default:
            SendClientMessage(playerid, "Warga");
    }
};

Array dan map

knight
let scores = [10, 20, 30];
let player = { "name": "CJ", "score": 0 };

scores[0] = 15;
player["score"] = 42;

let first = scores[0];
let n = len(scores);

push(scores, 40);            // ubah langsung: [10, 20, 30, 40]
let last = pop(scores);      // 40, scores kini [10, 20, 30]
let part = scores[1:3];      // [20, 30]
let sorted = sort([3, 1, 2]); // [1, 2, 3]

Literal

knight
let hex = 0xFF00FF00;   // int hex
let wait = 500ms;       // durasi -> milidetik
let pos = [1.0, 2.0, 3.0];
let meta = { "hp": 100 };

Komentar dan include

knight
// komentar baris
/* komentar blok
   beberapa baris */

#include <knight>              // opsional; native sudah built-in
#include "lib/shared.sa"       // sertakan file lain

Include diselesaikan relatif terhadap file yang menyertakan. Include melingkar ditolak dengan error.

Fungsi

Gunakan function untuk mendefinisikan helper yang bisa dipakai ulang. Fungsi juga bisa dipanggil berdasarkan nama dari timer dan callback database.

knight
function clampHealth(float value) {
    if (value < 0.0) { return 0.0; }
    if (value > 100.0) { return 100.0; }
    return value;
}

player::spawn(int playerid) {
    SetPlayerHealth(playerid, clampHealth(150.0));
};

Parameter: tipe, default, dan rest

Parameter fungsi bertipe dan dicek saat kompilasi. Parameter di belakang boleh punya nilai default, dan parameter terakhir ...rest menampung argumen sisa menjadi array.

knight
function spawnAt(Player target, float x, float y, float z = 3.0) { ... }
function total(int first, ...rest) {
    let sum = first;
    for (let n in rest) { sum += n; }
    return sum;
}

spawnAt(playerid, 100.0, 200.0);       // z default 3.0
total(1, 2, 3, 4);                     // 10
Note
Default dievaluasi saat fungsi dipanggil. Tipe salah, argumen kurang, atau argumen berlebih adalah error kompilasi.

Konstanta

knight
const MAX_HP = 100;
const RATIO: float = 0.5;

function cap(float hp) { return hp > MAX_HP ? MAX_HP : hp; }

Assignment ke const ditolak saat kompilasi.

Memanggil fungsi berdasarkan nama

CallRemoteFunction(nama, ...args) dan aliasnya CallLocalFunction memanggil function level atas berdasarkan namanya. Berguna saat fungsi dipilih saat runtime, dan membuat kode Pawn mudah diporting.

knight
function add(int a, int b) { return a + b; }
function isBig(int n) { return n > 10; }

let sum = CallRemoteFunction("add", 2, 3);      // 5
let big = CallLocalFunction("isBig", 50);       // 1
let x = CallRemoteFunction("missing");          // 0 (dicatat di log)

Hasilnya selalu int, seperti Pawn: angka dipotong, true/false menjadi 1/0, string menghasilkan panjangnya, handle objek menghasilkan id-nya, dan null menghasilkan 0. Nama yang tidak ada menulis peringatan ke log dan mengembalikan 0.

Scope

Variabel di level modul dipakai bersama semua callback sepanjang umur server. Variabel di dalam blok hanya ada di sana.

knight
let total = 0;                  // scope modul

player::connect(int playerid) {
    let local = 5;              // scope callback
    total = total + local;      // variabel modul bisa diubah
};

Keamanan loop

Loop dibatasi. Satu callback, command, atau timer maksimal menjalankan 10 juta iterasi; melewatinya menghentikan callback dengan pesan loop iteration limit exceeded dan server tetap responsif, jadi satu baris bermasalah tidak bisa membekukan server.

Warning
Batas direset untuk setiap callback, command, dan timer. Loop wajar atas pemain atau array jauh di bawah batas.

Truthiness

NilaiTruthy?
true / angka bukan nolya
false / 0 / 0.0tidak
string tidak kosongya
string kosong ""tidak
nulltidak
array / map tidak kosongya

Prioritas operator

Dari tertinggi ke terendah:

LevelOperator
1! not - + ~ (unary)
2* / %
3+ -
4<< >>
5< <= > >=
6== != ~=
7&
8^
9|
10and &&
11or ||
12? : (ternary)

Gunakan tanda kurung bila maksudnya tidak jelas.

Keyword

KeywordArti
letDeklarasi variabel
if / elseKondisional
returnKembali dari fungsi atau callback
functionDeklarasi fungsi helper
true / falseLiteral boolean
nullTidak ada nilai
and / or / notOperator logika
while / do / forLoop
inIterasi range pada for
break / continueKontrol loop
switch / case / defaultPercabangan banyak (tanpa fall-through)

Yang sengaja tidak ada