diff --git a/scripts/keybinds.db b/scripts/keybinds.db new file mode 100644 index 0000000..c5beb7d Binary files /dev/null and b/scripts/keybinds.db differ diff --git a/scripts/main.nut b/scripts/main.nut index 82d7f2a..befc336 100644 --- a/scripts/main.nut +++ b/scripts/main.nut @@ -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") diff --git a/scripts/module/keybinder.nut b/scripts/module/keybinder.nut new file mode 100644 index 0000000..727b018 --- /dev/null +++ b/scripts/module/keybinder.nut @@ -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); + } + 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 + " \n" + + "Unbind: /" + cmd + " \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; +} diff --git a/scripts/scripts.nut b/scripts/scripts.nut index c2b34e8..81ffcb1 100644 --- a/scripts/scripts.nut +++ b/scripts/scripts.nut @@ -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); +} } diff --git a/store/script/main.nut b/store/script/main.nut new file mode 100644 index 0000000..f3f01ce --- /dev/null +++ b/store/script/main.nut @@ -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); + } +}