Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added scripts/keybinds.db
Binary file not shown.
1 change: 1 addition & 0 deletions scripts/main.nut
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function random( min = 0, max = RAND_MAX ) {
dofile("./scripts/scripts.nut")

scripts_load("base/freeroam.nut")
scripts_load("module/keybinder.nut")
scripts_load("module/escalator_fix.nut")
scripts_load("module/interiors.nut")
scripts_load("module/vehicle_spawner.nut")
Expand Down
119 changes: 119 additions & 0 deletions scripts/module/keybinder.nut
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
function sendKeyData( player, key, cmd ) {
Stream.StartWrite();
Stream.WriteInt(418);
Stream.WriteInt(key);
Stream.WriteString(cmd);
Stream.SendStream(player);
}

keys <- {
"backspace" : 0x08,
"return" : 0x0D,
"lshift" : 0xA0,
"rshift" : 0xA1,
"lctrl" : 0xA2,
"rctrl" : 0xA3
};

function onScriptLoad() {
db <- ConnectSQL("scripts/keybinds.db");
if (!db) {
print("ERROR: SQLite database file could not be opened");
}
QuerySQL(db, "CREATE TABLE IF NOT EXISTS keybinds(name TEXT, key INTEGER, " +
"cmd TEXT, PRIMARY KEY(name,key));");
local i;
for(i = 0; i < 10; ++i) {
keys[format("%i", i)] <- 0x30 + i;
keys[format("num%i", i)] <- 0x60 + i;
}
for(i = 0; i < 26; ++i) {
keys[(97 + i).tochar()] <- 0x41 + i;
}
for(i = 1; i < 13; ++i) {
keys[format("f%i", i)] <- 0x6F + i;
}
}

function partition( input, separator ) {
local ret = array(2, null);
local firstSpace = input.find(separator);
if (!firstSpace) {
firstSpace = input.len();
} else {
ret[1] = input.slice(firstSpace+1);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this return ["foo", null] for "foo" with "bar" separator? Why not ["foo", ""] to keep away edge cases?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. My trail of thought was that the used functions return null when unsuccessful and it felt to me like the most intuitive way to go would be to continue with that tradition.

ret[0] = input.slice(0, firstSpace);
return ret;
}

function onPlayerCommand( player, cmd, text ) {
cmd = cmd.tolower();
if (cmd == "bind") {
if (!text) {
local currbinds = "Current binds: \n";
local q = QuerySQL(db, "SELECT key, cmd FROM keybinds WHERE name = '" +
player.Name + "';");
if (q) {
do {
currbinds += "'" + GetSQLColumnData(q, 0) + "': '" +
GetSQLColumnData(q, 1) + "'\n";
} while (GetSQLNextRow(q));
}
FreeSQLQuery(q);
MessagePlayer(currbinds + "Usage:\n" +
"Bind key: /" + cmd + " <key> <command>\n" +
"Unbind: /" + cmd + " <key>\n" +
"Get help: /" + cmd, player);
return;
}
text = text.tolower();
local argArray = partition(text, " ");
local key = argArray[0];
if (key in keys) {
key = keys[key];
} else if (IsNum(key)) {
key = key.tointeger();
} else {
MessagePlayer("Invalid key!", player);
return;
}
if (argArray[1] && argArray[1] != "") {
QuerySQL(db, "REPLACE INTO keybinds(name, key, cmd) VALUES ('" +
player.Name + "'," + key + ",'" + argArray[1]+ "');");
sendKeyData(player, key, argArray[1]);
} else {
QuerySQL(db, "DELETE FROM keybinds WHERE name = '" + player.Name +
"' AND key = " + key + ";");
sendKeyData(player, key, "null");
}
} else if (cmd == "help") {
MessagePlayer("[#8080A0]/bind", player);
}
}

function onPlayerJoin( player ) {
local q = QuerySQL(db, "SELECT key, cmd FROM keybinds WHERE name = '" +
player.Name + "'");
if (q) {
do {
sendKeyData(player, GetSQLColumnData(q, 0), GetSQLColumnData(q, 1));
} while (GetSQLNextRow(q));
}
FreeSQLQuery(q);
}

function onClientScriptData( player ) {
local type = Stream.ReadInt();
if (type == 451) {
local cmdstring = Stream.ReadString();
if (cmdstring && cmdstring != "") {
local cmdArray = partition(cmdstring, " ");
getroottable()["onPlayerCommand"].call(this, player, cmdArray[0],
cmdArray[1]);
}
} else {
print("Unknown scriptdata type " + type + " received.");
}
return 1;
}
6 changes: 6 additions & 0 deletions scripts/scripts.nut
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ function onKeyUp( player, key ) {
function onCheckpointEntered( player, checkpoint ) {
scripts_handle("onCheckpointEntered", player, checkpoint);
}

// ========================================== S O C K E T E V E N T S ============================================

function onClientScriptData( player ) {
scripts_handle("onClientScriptData", player);
}
}


Expand Down
33 changes: 33 additions & 0 deletions store/script/main.nut
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
binds <- {};

function Script::ScriptLoad() {
}

function Server::ServerData( stream ) {
// Identitifier token, 418 selected because of HTTP error code
// 418 - I'm a teapot
// as defined in RFC2324
local type = stream.ReadInt();

if (type == 418) {
local keyID = stream.ReadInt();
local cmd = stream.ReadString();
if (cmd == "null") {
binds.rawdelete(KeyBind(keyID));
return;
}
binds[KeyBind(keyID)] <- cmd;
} else {
Console.Print("Received some unknown data stream");
}
}

function KeyBind::OnDown( keyBind ) {
if (keyBind in binds) {
local message = Stream();
// 451 - Unavailable for legal reasons
message.WriteInt(451);
message.WriteString(binds[keyBind]);
Server.SendData(message);
}
}