Created
June 26, 2018 16:44
-
-
Save blam23/caaa30fd32e283e379c1517265c8881a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[[ | |
| Blam's Chess Script | |
| ]]-- | |
| -- Define these completely *globally* so that other scripts can see them. | |
| local engine_manager = { | |
| engines = {} | |
| } | |
| engine_manager.__index = engine_manager | |
| do | |
| --[[ | |
| SETUP + HELPER FUNCTIONS | |
| ]] | |
| dofile("system/player_info.lua") | |
| dofile("chess/animation.lua") | |
| -- Some script-global debug stuff. | |
| debug_mode = 1 | |
| function dbg(...) | |
| if debug_mode == 0 then return end | |
| local out = "^17" .. table.concat( arg, ", ") | |
| echo(out) | |
| end | |
| -- 'Starts with' function, usage: | |
| -- "hello" % "he" == true | |
| getmetatable("").__mod = function(self, s) | |
| if(self:sub(0,#s) == s) then return true end | |
| return false | |
| end | |
| -- Generic helper functions holder | |
| local helpers = {} | |
| -- From system/player_info.lua | |
| function helpers.getUserName(player) | |
| player = player:gsub(".*%b{}", "") | |
| player = player:gsub(".*%b[]", "") | |
| player = player:gsub(".*%b()", "") | |
| return player | |
| end | |
| -- From system/player_info.lua | |
| function helpers.getMaster(option) | |
| add_hook("console", "chess_playerInfoFetchConsoleIgnore", function(s,i) | |
| return 1 | |
| end) | |
| local return_val = nil | |
| if (option) then | |
| return_val = get_master().master[option] | |
| else | |
| return_val = get_master().master | |
| end | |
| remove_hooks("chess_playerInfoFetchConsoleIgnore") | |
| return return_val | |
| end | |
| -- Splits up a whisper from another player into player and message. | |
| -- Strips clans from username, does not strip colours. | |
| function helpers.splitWhisper(msg) | |
| local name_split = msg:find(":") | |
| local name = msg:sub(0,name_split-1) | |
| name = helpers.getUserName(name) | |
| local message = msg:sub(name_split+2) | |
| return name, message | |
| end | |
| --[[ | |
| END OF SETUP | |
| ]] | |
| ---------------------------------------------------------------------------------------------------- | |
| --[[ | |
| CHESS ENGINE | |
| ]] | |
| -- Script globals for holding current stuff | |
| local engine = nil | |
| local const = nil | |
| local version = nil | |
| -- Current engine, use of multiple engines designed for | |
| -- possible backwards compatilibity or different games. | |
| local current_engine = { | |
| version = "001", | |
| const = { | |
| -- GAME COMMANDS | |
| NEW_GAME = "::chess_new:", | |
| ACCEPT_GAME = "accepted", | |
| ERROR = "!!error", | |
| WHISPER_CMD = "::chess_cmd:", | |
| -- ERRORS | |
| ERR_VER_MISMATCH = "ver_mismatch", | |
| -- NUMBERS | |
| ID_LENGTH = 5, | |
| NEW_GAME_ID_LENGTH = 5, | |
| } | |
| } | |
| current_engine.__index = current_engine | |
| current_engine.newGame = function() | |
| echo("CHESSENGINE:NEWGAME") | |
| end | |
| current_engine.processCommand = function(command) | |
| echo("Engine command: '" .. command .. "'") | |
| end | |
| engine_manager.findEngine = function(version) | |
| for i=1,#engine_manager.engines do | |
| if engine_manager.engines[i].version == version then | |
| return engine_manager.engines[i] | |
| end | |
| end | |
| return nil | |
| end | |
| engine_manager.setEngine = function(e) | |
| engine = e | |
| const = e.const | |
| version = e.version | |
| end | |
| engine_manager.register = function(e) | |
| table.insert(engine_manager.engines, e) | |
| end | |
| engine_manager.setEngineVersion = function(version) | |
| local eng = engine_manager.findEngine(version) | |
| if (eng == nil) then | |
| return false | |
| end | |
| engine_manager.setEngine(eng) | |
| return true | |
| end | |
| engine_manager.register(current_engine) | |
| engine_manager.setEngine(current_engine) | |
| --[[ | |
| END OF CHESS ENGINE | |
| ]] | |
| ---------------------------------------------------------------------------------------------------- | |
| --[[ | |
| SESSION HANDLER | |
| ]] | |
| local session = { | |
| current = {} | |
| } | |
| session.__index = session | |
| function session.create() | |
| dbg ("session.create") | |
| local s = { } | |
| setmetatable(s, session) | |
| s:reset() | |
| table.insert(session.current, s) | |
| dbg ("returning from session.create") | |
| return s | |
| end | |
| function session:reset() | |
| dbg ("session:reset") | |
| self.opponent = nil | |
| self.started = false | |
| self.client = false | |
| self.triggers = {} | |
| self.waiting = false | |
| self.current_player = helpers.getMaster("nick") | |
| self.cur_id = 0 | |
| self.processed = {} | |
| end | |
| function session:sendRaw(message) | |
| dbg ("session:sendRaw " .. message) | |
| if self.opponent == nil then | |
| return | |
| end | |
| run_cmd("whisper " .. self.opponent .. " " .. message .. "\n") | |
| end | |
| function session:nextID() | |
| dbg ("session:nextID") | |
| local full_id = tostring(self.cur_id) | |
| full_id = string.rep("0", engine.const.ID_LENGTH-#full_id) .. full_id | |
| self.cur_id = self.cur_id + 1 | |
| return full_id | |
| end | |
| function session:send(message) | |
| dbg ("session:send") | |
| id = self:nextID() | |
| self:sendRaw(const.WHISPER_CMD .. id .. message) | |
| end | |
| function session:sendError(message) | |
| dbg ("session:sendError") | |
| self:send(const.ERROR .. message) | |
| end | |
| function session:checkDuplicate(id, message) | |
| dbg ("session:checkDuplicate") | |
| if self.processed[id] == nil then | |
| self.processed[id] = #message | |
| return false | |
| end | |
| return self.processed[id] == #message | |
| end | |
| function session:process(message) | |
| dbg ("session:process " .. message) | |
| local id = message:sub(0,engine.const.ID_LENGTH) | |
| local message = message:sub(engine.const.ID_LENGTH+1) | |
| -- Whisper messaging is not quite right.. | |
| if self:checkDuplicate(id, message) then | |
| return | |
| end | |
| local processed = false | |
| if (self.waiting) then | |
| for k,v in pairs(self.triggers) do | |
| if message % k then | |
| for i = 1,#v do | |
| v[i](self, message) | |
| processed = true | |
| end | |
| self.triggers.remove(k) | |
| end | |
| end | |
| if #self.triggers == 0 then | |
| self.waiting = false | |
| end | |
| end | |
| if proccessed then return end | |
| engine:processCommand(message) | |
| end | |
| function session:waitFor(message, func) | |
| dbg ("session:waitFor") | |
| if self.triggers[message] ~= nil then | |
| self.triggers[message].insert(func) | |
| end | |
| self.triggers[message] = {func} | |
| self.waiting = true | |
| end | |
| function session:waitError(message, func) | |
| dbg ("session:waitError") | |
| if message == nil then | |
| self:waitFor(const.ERROR, func) | |
| else | |
| self:waitFor(const.ERROR .. message, func) | |
| end | |
| end | |
| -- Game request has been accepted. | |
| function session:gameAccepted(m) | |
| dbg ("session:gameAccepted") | |
| -- empty wait queue | |
| self.triggers = {} | |
| self.started = true | |
| engine:newGame() | |
| end | |
| function session:gameNotAccepted(m) | |
| dbg ("session:gameNotAccepted") | |
| -- empty wait queue | |
| self.triggers = {} | |
| echo("^02" .. self.opponent .. " has declined your request or was unable to participate.") | |
| end | |
| -- Attempts to set up a new game as a client (recieved a request) | |
| function session.newClientGame(name, version) | |
| dbg ("session.newClientGame") | |
| local s = session.create() | |
| s.opponent = name | |
| if engine_manager.setEngineVersion(version) then | |
| s.started = true | |
| s.client = true | |
| engine:newGame() | |
| s:send(const.ACCEPT_GAME) | |
| return s | |
| end | |
| s.error = const.ERR_VER_MISMATCH | |
| echo("^02Unable to start session with " .. name .. " as scripts are incompatible. ^02Please update scripts") | |
| s:sendError(s.error) | |
| return s | |
| end | |
| -- Attempts to set up a new game as a host (send the request) | |
| function session.newHostGame(name) | |
| dbg ("session.newHostGame") | |
| local s = session.create() | |
| s.opponent = name | |
| local length_mul = math.pow(10, engine.const.NEW_GAME_ID_LENGTH - 1) | |
| local session_id = tostring(math.floor((math.random() * length_mul) % length_mul)) | |
| session_id = string.rep("0", engine.const.NEW_GAME_ID_LENGTH-#session_id) .. session_id | |
| s:sendRaw(const.NEW_GAME .. session_id .. engine.version) | |
| s:waitFor(const.ACCEPT_GAME, session.gameAccepted) | |
| s:waitError(nil, session.gameNotAccepted) | |
| return s | |
| end | |
| --[[ | |
| END OF SESSION HANDLER | |
| ]] | |
| ---------------------------------------------------------------------------------------------------- | |
| --[[ | |
| HOOKS | |
| ]] | |
| local hooks = {} | |
| hooks.__index = hooks | |
| -- Hook for multiplayer messaging | |
| hooks.whisper = function(s, i) | |
| -- No message - just in case to prevent errors. | |
| if #s == 0 then | |
| return 0 | |
| end | |
| -- 4 and starts with whisper -> remove: This is an echo of a sent message. | |
| if i == 4 and (s % "whisper ") then | |
| dbg (">> ^06" .. s) | |
| return 1 | |
| end | |
| if i == 8 then | |
| if s[0] ~= '<' then | |
| local name, message = helpers.splitWhisper(s) | |
| name = helpers.getUserName(name) | |
| --echo ("Name: '" .. name .. "' ~ Current '" .. cur_session.current_player .. "'") | |
| if name == cur_session.current_player then | |
| return 1 | |
| end | |
| dbg ("<< ^11" .. name .. ": " .. message) | |
| if name == cur_session.opponent and message % const.WHISPER_CMD then | |
| cur_session:process(message:sub(#const.WHISPER_CMD+1)) | |
| return 1 | |
| end | |
| if ((cur_session == nil or not cur_session.started) and message % const.NEW_GAME) then | |
| -- new session | |
| local version = message:sub(#const.NEW_GAME + const.NEW_GAME_ID_LENGTH + 1) | |
| -- check for duplicate messages. | |
| local id = message:sub(0, const.NEW_GAME_ID_LENGTH) | |
| if (id == session.last_game_id) then | |
| return 1 | |
| end | |
| session.last_game_id = id | |
| -- TODO: Add prompt to confirm a new game. | |
| session.newClientGame(name, version) | |
| return 1 | |
| end | |
| end | |
| end | |
| return 0 | |
| end | |
| -- Hook for commands | |
| hooks.commands = function(cmd) | |
| if cmd == "r" then | |
| run_cmd("clear") | |
| run_cmd("chl 10000000") | |
| echo("Reloading..") | |
| run_cmd("ls chess.lua") | |
| elseif cmd == "dbg" then | |
| debug_mode = 1 | |
| elseif cmd == "chess" then | |
| cur_session = session.newHostGame("Oku") | |
| elseif cmd == "boom" then | |
| cur_session:send("boom") | |
| end | |
| end | |
| hooks.initialise = function() | |
| add_hook("console", "chess_mp_whisper_hook", hooks.whisper) | |
| add_hook("command", "chess_commands", hooks.commands) | |
| end | |
| --[[ | |
| END OF HOOKS | |
| ]] | |
| ---------------------------------------------------------------------------------------------------- | |
| hooks.initialise() | |
| ---------------------------------------------------------------------------------------------------- | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment