Lua: Further centralize code, fix Bizhawk 2.9 (#1685)
* Fixes the socket library for bizhawk 2.9/lua 5.4 by including another one in parallel * Fixes lua 5.4 support by making socket.lua into a "modern" module (the `module` keyword is gone) * Adds the linux version and 32 bit windows socket dlls because why not * Merges common functions into `common.lua` - the only functional change of this should be that: * Some things that were locals are globals now - this can be changed, I just was lazy and it likely doesn't matter * `drawText` now uses middle/bottom for all prints - feel free to do what you like with that change
This commit is contained in:
parent
808203a50f
commit
5a7d20d393
|
@ -25,11 +25,11 @@ from worlds.adventure.Offsets import static_item_element_size, connector_port_of
|
||||||
SYSTEM_MESSAGE_ID = 0
|
SYSTEM_MESSAGE_ID = 0
|
||||||
|
|
||||||
CONNECTION_TIMING_OUT_STATUS = \
|
CONNECTION_TIMING_OUT_STATUS = \
|
||||||
"Connection timing out. Please restart your emulator, then restart adventure_connector.lua"
|
"Connection timing out. Please restart your emulator, then restart connector_adventure.lua"
|
||||||
CONNECTION_REFUSED_STATUS = \
|
CONNECTION_REFUSED_STATUS = \
|
||||||
"Connection Refused. Please start your emulator and make sure adventure_connector.lua is running"
|
"Connection Refused. Please start your emulator and make sure connector_adventure.lua is running"
|
||||||
CONNECTION_RESET_STATUS = \
|
CONNECTION_RESET_STATUS = \
|
||||||
"Connection was reset. Please restart your emulator, then restart adventure_connector.lua"
|
"Connection was reset. Please restart your emulator, then restart connector_adventure.lua"
|
||||||
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
||||||
CONNECTION_CONNECTED_STATUS = "Connected"
|
CONNECTION_CONNECTED_STATUS = "Connected"
|
||||||
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
||||||
|
|
|
@ -13,9 +13,9 @@ from CommonClient import CommonContext, server_loop, gui_enabled, ClientCommandP
|
||||||
|
|
||||||
SYSTEM_MESSAGE_ID = 0
|
SYSTEM_MESSAGE_ID = 0
|
||||||
|
|
||||||
CONNECTION_TIMING_OUT_STATUS = "Connection timing out. Please restart your emulator, then restart ff1_connector.lua"
|
CONNECTION_TIMING_OUT_STATUS = "Connection timing out. Please restart your emulator, then restart connector_ff1.lua"
|
||||||
CONNECTION_REFUSED_STATUS = "Connection Refused. Please start your emulator and make sure ff1_connector.lua is running"
|
CONNECTION_REFUSED_STATUS = "Connection Refused. Please start your emulator and make sure connector_ff1.lua is running"
|
||||||
CONNECTION_RESET_STATUS = "Connection was reset. Please restart your emulator, then restart ff1_connector.lua"
|
CONNECTION_RESET_STATUS = "Connection was reset. Please restart your emulator, then restart connector_ff1.lua"
|
||||||
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
||||||
CONNECTION_CONNECTED_STATUS = "Connected"
|
CONNECTION_CONNECTED_STATUS = "Connected"
|
||||||
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
||||||
|
|
|
@ -17,9 +17,9 @@ from worlds.oot.N64Patch import apply_patch_file
|
||||||
from worlds.oot.Utils import data_path
|
from worlds.oot.Utils import data_path
|
||||||
|
|
||||||
|
|
||||||
CONNECTION_TIMING_OUT_STATUS = "Connection timing out. Please restart your emulator, then restart oot_connector.lua"
|
CONNECTION_TIMING_OUT_STATUS = "Connection timing out. Please restart your emulator, then restart connector_oot.lua"
|
||||||
CONNECTION_REFUSED_STATUS = "Connection refused. Please start your emulator and make sure oot_connector.lua is running"
|
CONNECTION_REFUSED_STATUS = "Connection refused. Please start your emulator and make sure connector_oot.lua is running"
|
||||||
CONNECTION_RESET_STATUS = "Connection was reset. Please restart your emulator, then restart oot_connector.lua"
|
CONNECTION_RESET_STATUS = "Connection was reset. Please restart your emulator, then restart connector_oot.lua"
|
||||||
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
||||||
CONNECTION_CONNECTED_STATUS = "Connected"
|
CONNECTION_CONNECTED_STATUS = "Connected"
|
||||||
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
||||||
|
|
|
@ -23,9 +23,9 @@ from worlds.tloz import Items, Locations, Rom
|
||||||
|
|
||||||
SYSTEM_MESSAGE_ID = 0
|
SYSTEM_MESSAGE_ID = 0
|
||||||
|
|
||||||
CONNECTION_TIMING_OUT_STATUS = "Connection timing out. Please restart your emulator, then restart Zelda_connector.lua"
|
CONNECTION_TIMING_OUT_STATUS = "Connection timing out. Please restart your emulator, then restart connector_tloz.lua"
|
||||||
CONNECTION_REFUSED_STATUS = "Connection Refused. Please start your emulator and make sure Zelda_connector.lua is running"
|
CONNECTION_REFUSED_STATUS = "Connection Refused. Please start your emulator and make sure connector_tloz.lua is running"
|
||||||
CONNECTION_RESET_STATUS = "Connection was reset. Please restart your emulator, then restart Zelda_connector.lua"
|
CONNECTION_RESET_STATUS = "Connection was reset. Please restart your emulator, then restart connector_tloz.lua"
|
||||||
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
CONNECTION_TENTATIVE_STATUS = "Initial Connection Made"
|
||||||
CONNECTION_CONNECTED_STATUS = "Connected"
|
CONNECTION_CONNECTED_STATUS = "Connected"
|
||||||
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
CONNECTION_INITIAL_STATUS = "Connection has not been initiated"
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- LuaSocket helper module
|
|
||||||
-- Author: Diego Nehab
|
|
||||||
-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Declare module and import dependencies
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local base = _G
|
|
||||||
local string = require("string")
|
|
||||||
local math = require("math")
|
|
||||||
local socket = require("socket.core")
|
|
||||||
module("socket")
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Exported auxiliar functions
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
function connect(address, port, laddress, lport)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
if laddress then
|
|
||||||
local res, err = sock:bind(laddress, lport, -1)
|
|
||||||
if not res then return nil, err end
|
|
||||||
end
|
|
||||||
local res, err = sock:connect(address, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
function bind(host, port, backlog)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
sock:setoption("reuseaddr", true)
|
|
||||||
local res, err = sock:bind(host, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
res, err = sock:listen(backlog)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
try = newtry()
|
|
||||||
|
|
||||||
function choose(table)
|
|
||||||
return function(name, opt1, opt2)
|
|
||||||
if base.type(name) ~= "string" then
|
|
||||||
name, opt1, opt2 = "default", name, opt1
|
|
||||||
end
|
|
||||||
local f = table[name or "nil"]
|
|
||||||
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
|
||||||
else return f(opt1, opt2) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Socket sources and sinks, conforming to LTN12
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- create namespaces inside LuaSocket namespace
|
|
||||||
sourcet = {}
|
|
||||||
sinkt = {}
|
|
||||||
|
|
||||||
BLOCKSIZE = 2048
|
|
||||||
|
|
||||||
sinkt["close-when-done"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if not chunk then
|
|
||||||
sock:close()
|
|
||||||
return 1
|
|
||||||
else return sock:send(chunk) end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["keep-open"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if chunk then return sock:send(chunk)
|
|
||||||
else return 1 end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["default"] = sinkt["keep-open"]
|
|
||||||
|
|
||||||
sink = choose(sinkt)
|
|
||||||
|
|
||||||
sourcet["by-length"] = function(sock, length)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if length <= 0 then return nil end
|
|
||||||
local size = math.min(socket.BLOCKSIZE, length)
|
|
||||||
local chunk, err = sock:receive(size)
|
|
||||||
if err then return nil, err end
|
|
||||||
length = length - string.len(chunk)
|
|
||||||
return chunk
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sourcet["until-closed"] = function(sock)
|
|
||||||
local done
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if done then return nil end
|
|
||||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
|
||||||
if not err then return chunk
|
|
||||||
elseif err == "closed" then
|
|
||||||
sock:close()
|
|
||||||
done = 1
|
|
||||||
return partial
|
|
||||||
else return nil, err end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
sourcet["default"] = sourcet["until-closed"]
|
|
||||||
|
|
||||||
source = choose(sourcet)
|
|
Binary file not shown.
|
@ -1,380 +0,0 @@
|
||||||
--
|
|
||||||
-- json.lua
|
|
||||||
--
|
|
||||||
-- Copyright (c) 2015 rxi
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or modify it
|
|
||||||
-- under the terms of the MIT license. See LICENSE for details.
|
|
||||||
--
|
|
||||||
|
|
||||||
local json = { _version = "0.1.0" }
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Encode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local encode
|
|
||||||
|
|
||||||
local escape_char_map = {
|
|
||||||
[ "\\" ] = "\\\\",
|
|
||||||
[ "\"" ] = "\\\"",
|
|
||||||
[ "\b" ] = "\\b",
|
|
||||||
[ "\f" ] = "\\f",
|
|
||||||
[ "\n" ] = "\\n",
|
|
||||||
[ "\r" ] = "\\r",
|
|
||||||
[ "\t" ] = "\\t",
|
|
||||||
}
|
|
||||||
|
|
||||||
local escape_char_map_inv = { [ "\\/" ] = "/" }
|
|
||||||
for k, v in pairs(escape_char_map) do
|
|
||||||
escape_char_map_inv[v] = k
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function escape_char(c)
|
|
||||||
return escape_char_map[c] or string.format("\\u%04x", c:byte())
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_nil(val)
|
|
||||||
return "null"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_table(val, stack)
|
|
||||||
local res = {}
|
|
||||||
stack = stack or {}
|
|
||||||
|
|
||||||
-- Circular reference?
|
|
||||||
if stack[val] then error("circular reference") end
|
|
||||||
|
|
||||||
stack[val] = true
|
|
||||||
|
|
||||||
if val[1] ~= nil or next(val) == nil then
|
|
||||||
-- Treat as array -- check keys are valid and it is not sparse
|
|
||||||
local n = 0
|
|
||||||
for k in pairs(val) do
|
|
||||||
if type(k) ~= "number" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
if n ~= #val then
|
|
||||||
error("invalid table: sparse array")
|
|
||||||
end
|
|
||||||
-- Encode
|
|
||||||
for i, v in ipairs(val) do
|
|
||||||
table.insert(res, encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "[" .. table.concat(res, ",") .. "]"
|
|
||||||
|
|
||||||
else
|
|
||||||
-- Treat as an object
|
|
||||||
for k, v in pairs(val) do
|
|
||||||
if type(k) ~= "string" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "{" .. table.concat(res, ",") .. "}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_string(val)
|
|
||||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_number(val)
|
|
||||||
-- Check for NaN, -inf and inf
|
|
||||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
|
||||||
error("unexpected number value '" .. tostring(val) .. "'")
|
|
||||||
end
|
|
||||||
return string.format("%.14g", val)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local type_func_map = {
|
|
||||||
[ "nil" ] = encode_nil,
|
|
||||||
[ "table" ] = encode_table,
|
|
||||||
[ "string" ] = encode_string,
|
|
||||||
[ "number" ] = encode_number,
|
|
||||||
[ "boolean" ] = tostring,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
encode = function(val, stack)
|
|
||||||
local t = type(val)
|
|
||||||
local f = type_func_map[t]
|
|
||||||
if f then
|
|
||||||
return f(val, stack)
|
|
||||||
end
|
|
||||||
error("unexpected type '" .. t .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.encode(val)
|
|
||||||
return ( encode(val) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Decode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local parse
|
|
||||||
|
|
||||||
local function create_set(...)
|
|
||||||
local res = {}
|
|
||||||
for i = 1, select("#", ...) do
|
|
||||||
res[ select(i, ...) ] = true
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
|
||||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
|
||||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
|
||||||
local literals = create_set("true", "false", "null")
|
|
||||||
|
|
||||||
local literal_map = {
|
|
||||||
[ "true" ] = true,
|
|
||||||
[ "false" ] = false,
|
|
||||||
[ "null" ] = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local function next_char(str, idx, set, negate)
|
|
||||||
for i = idx, #str do
|
|
||||||
if set[str:sub(i, i)] ~= negate then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return #str + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function decode_error(str, idx, msg)
|
|
||||||
--local line_count = 1
|
|
||||||
--local col_count = 1
|
|
||||||
--for i = 1, idx - 1 do
|
|
||||||
-- col_count = col_count + 1
|
|
||||||
-- if str:sub(i, i) == "\n" then
|
|
||||||
-- line_count = line_count + 1
|
|
||||||
-- col_count = 1
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- emu.message( string.format("%s at line %d col %d", msg, line_count, col_count) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function codepoint_to_utf8(n)
|
|
||||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
|
||||||
local f = math.floor
|
|
||||||
if n <= 0x7f then
|
|
||||||
return string.char(n)
|
|
||||||
elseif n <= 0x7ff then
|
|
||||||
return string.char(f(n / 64) + 192, n % 64 + 128)
|
|
||||||
elseif n <= 0xffff then
|
|
||||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
elseif n <= 0x10ffff then
|
|
||||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
|
||||||
f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
end
|
|
||||||
error( string.format("invalid unicode codepoint '%x'", n) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_unicode_escape(s)
|
|
||||||
local n1 = tonumber( s:sub(3, 6), 16 )
|
|
||||||
local n2 = tonumber( s:sub(9, 12), 16 )
|
|
||||||
-- Surrogate pair?
|
|
||||||
if n2 then
|
|
||||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
|
||||||
else
|
|
||||||
return codepoint_to_utf8(n1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_string(str, i)
|
|
||||||
local has_unicode_escape = false
|
|
||||||
local has_surrogate_escape = false
|
|
||||||
local has_escape = false
|
|
||||||
local last
|
|
||||||
for j = i + 1, #str do
|
|
||||||
local x = str:byte(j)
|
|
||||||
|
|
||||||
if x < 32 then
|
|
||||||
decode_error(str, j, "control character in string")
|
|
||||||
end
|
|
||||||
|
|
||||||
if last == 92 then -- "\\" (escape char)
|
|
||||||
if x == 117 then -- "u" (unicode escape sequence)
|
|
||||||
local hex = str:sub(j + 1, j + 5)
|
|
||||||
if not hex:find("%x%x%x%x") then
|
|
||||||
decode_error(str, j, "invalid unicode escape in string")
|
|
||||||
end
|
|
||||||
if hex:find("^[dD][89aAbB]") then
|
|
||||||
has_surrogate_escape = true
|
|
||||||
else
|
|
||||||
has_unicode_escape = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local c = string.char(x)
|
|
||||||
if not escape_chars[c] then
|
|
||||||
decode_error(str, j, "invalid escape char '" .. c .. "' in string")
|
|
||||||
end
|
|
||||||
has_escape = true
|
|
||||||
end
|
|
||||||
last = nil
|
|
||||||
|
|
||||||
elseif x == 34 then -- '"' (end of string)
|
|
||||||
local s = str:sub(i + 1, j - 1)
|
|
||||||
if has_surrogate_escape then
|
|
||||||
s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_unicode_escape then
|
|
||||||
s = s:gsub("\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_escape then
|
|
||||||
s = s:gsub("\\.", escape_char_map_inv)
|
|
||||||
end
|
|
||||||
return s, j + 1
|
|
||||||
|
|
||||||
else
|
|
||||||
last = x
|
|
||||||
end
|
|
||||||
end
|
|
||||||
decode_error(str, i, "expected closing quote for string")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_number(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local s = str:sub(i, x - 1)
|
|
||||||
local n = tonumber(s)
|
|
||||||
if not n then
|
|
||||||
decode_error(str, i, "invalid number '" .. s .. "'")
|
|
||||||
end
|
|
||||||
return n, x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_literal(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local word = str:sub(i, x - 1)
|
|
||||||
if not literals[word] then
|
|
||||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
|
||||||
end
|
|
||||||
return literal_map[word], x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_array(str, i)
|
|
||||||
local res = {}
|
|
||||||
local n = 1
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local x
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of array?
|
|
||||||
if str:sub(i, i) == "]" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read token
|
|
||||||
x, i = parse(str, i)
|
|
||||||
res[n] = x
|
|
||||||
n = n + 1
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "]" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_object(str, i)
|
|
||||||
local res = {}
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local key, val
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of object?
|
|
||||||
if str:sub(i, i) == "}" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read key
|
|
||||||
if str:sub(i, i) ~= '"' then
|
|
||||||
decode_error(str, i, "expected string for key")
|
|
||||||
end
|
|
||||||
key, i = parse(str, i)
|
|
||||||
-- Read ':' delimiter
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
if str:sub(i, i) ~= ":" then
|
|
||||||
decode_error(str, i, "expected ':' after key")
|
|
||||||
end
|
|
||||||
i = next_char(str, i + 1, space_chars, true)
|
|
||||||
-- Read value
|
|
||||||
val, i = parse(str, i)
|
|
||||||
-- Set
|
|
||||||
res[key] = val
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "}" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local char_func_map = {
|
|
||||||
[ '"' ] = parse_string,
|
|
||||||
[ "0" ] = parse_number,
|
|
||||||
[ "1" ] = parse_number,
|
|
||||||
[ "2" ] = parse_number,
|
|
||||||
[ "3" ] = parse_number,
|
|
||||||
[ "4" ] = parse_number,
|
|
||||||
[ "5" ] = parse_number,
|
|
||||||
[ "6" ] = parse_number,
|
|
||||||
[ "7" ] = parse_number,
|
|
||||||
[ "8" ] = parse_number,
|
|
||||||
[ "9" ] = parse_number,
|
|
||||||
[ "-" ] = parse_number,
|
|
||||||
[ "t" ] = parse_literal,
|
|
||||||
[ "f" ] = parse_literal,
|
|
||||||
[ "n" ] = parse_literal,
|
|
||||||
[ "[" ] = parse_array,
|
|
||||||
[ "{" ] = parse_object,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
parse = function(str, idx)
|
|
||||||
local chr = str:sub(idx, idx)
|
|
||||||
local f = char_func_map[chr]
|
|
||||||
if f then
|
|
||||||
return f(str, idx)
|
|
||||||
end
|
|
||||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.decode(str)
|
|
||||||
if type(str) ~= "string" then
|
|
||||||
error("expected argument of type string, got " .. type(str))
|
|
||||||
end
|
|
||||||
return ( parse(str, next_char(str, 1, space_chars, true)) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return json
|
|
|
@ -1,132 +0,0 @@
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- LuaSocket helper module
|
|
||||||
-- Author: Diego Nehab
|
|
||||||
-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Declare module and import dependencies
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local base = _G
|
|
||||||
local string = require("string")
|
|
||||||
local math = require("math")
|
|
||||||
local socket = require("socket.core")
|
|
||||||
module("socket")
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Exported auxiliar functions
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
function connect(address, port, laddress, lport)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
if laddress then
|
|
||||||
local res, err = sock:bind(laddress, lport, -1)
|
|
||||||
if not res then return nil, err end
|
|
||||||
end
|
|
||||||
local res, err = sock:connect(address, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
function bind(host, port, backlog)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
sock:setoption("reuseaddr", true)
|
|
||||||
local res, err = sock:bind(host, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
res, err = sock:listen(backlog)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
try = newtry()
|
|
||||||
|
|
||||||
function choose(table)
|
|
||||||
return function(name, opt1, opt2)
|
|
||||||
if base.type(name) ~= "string" then
|
|
||||||
name, opt1, opt2 = "default", name, opt1
|
|
||||||
end
|
|
||||||
local f = table[name or "nil"]
|
|
||||||
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
|
||||||
else return f(opt1, opt2) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Socket sources and sinks, conforming to LTN12
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- create namespaces inside LuaSocket namespace
|
|
||||||
sourcet = {}
|
|
||||||
sinkt = {}
|
|
||||||
|
|
||||||
BLOCKSIZE = 2048
|
|
||||||
|
|
||||||
sinkt["close-when-done"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if not chunk then
|
|
||||||
sock:close()
|
|
||||||
return 1
|
|
||||||
else return sock:send(chunk) end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["keep-open"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if chunk then return sock:send(chunk)
|
|
||||||
else return 1 end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["default"] = sinkt["keep-open"]
|
|
||||||
|
|
||||||
sink = choose(sinkt)
|
|
||||||
|
|
||||||
sourcet["by-length"] = function(sock, length)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if length <= 0 then return nil end
|
|
||||||
local size = math.min(socket.BLOCKSIZE, length)
|
|
||||||
local chunk, err = sock:receive(size)
|
|
||||||
if err then return nil, err end
|
|
||||||
length = length - string.len(chunk)
|
|
||||||
return chunk
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sourcet["until-closed"] = function(sock)
|
|
||||||
local done
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if done then return nil end
|
|
||||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
|
||||||
if not err then return chunk
|
|
||||||
elseif err == "closed" then
|
|
||||||
sock:close()
|
|
||||||
done = 1
|
|
||||||
return partial
|
|
||||||
else return nil, err end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
sourcet["default"] = sourcet["until-closed"]
|
|
||||||
|
|
||||||
source = choose(sourcet)
|
|
Binary file not shown.
|
@ -1,380 +0,0 @@
|
||||||
--
|
|
||||||
-- json.lua
|
|
||||||
--
|
|
||||||
-- Copyright (c) 2015 rxi
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or modify it
|
|
||||||
-- under the terms of the MIT license. See LICENSE for details.
|
|
||||||
--
|
|
||||||
|
|
||||||
local json = { _version = "0.1.0" }
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Encode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local encode
|
|
||||||
|
|
||||||
local escape_char_map = {
|
|
||||||
[ "\\" ] = "\\\\",
|
|
||||||
[ "\"" ] = "\\\"",
|
|
||||||
[ "\b" ] = "\\b",
|
|
||||||
[ "\f" ] = "\\f",
|
|
||||||
[ "\n" ] = "\\n",
|
|
||||||
[ "\r" ] = "\\r",
|
|
||||||
[ "\t" ] = "\\t",
|
|
||||||
}
|
|
||||||
|
|
||||||
local escape_char_map_inv = { [ "\\/" ] = "/" }
|
|
||||||
for k, v in pairs(escape_char_map) do
|
|
||||||
escape_char_map_inv[v] = k
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function escape_char(c)
|
|
||||||
return escape_char_map[c] or string.format("\\u%04x", c:byte())
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_nil(val)
|
|
||||||
return "null"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_table(val, stack)
|
|
||||||
local res = {}
|
|
||||||
stack = stack or {}
|
|
||||||
|
|
||||||
-- Circular reference?
|
|
||||||
if stack[val] then error("circular reference") end
|
|
||||||
|
|
||||||
stack[val] = true
|
|
||||||
|
|
||||||
if val[1] ~= nil or next(val) == nil then
|
|
||||||
-- Treat as array -- check keys are valid and it is not sparse
|
|
||||||
local n = 0
|
|
||||||
for k in pairs(val) do
|
|
||||||
if type(k) ~= "number" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
if n ~= #val then
|
|
||||||
error("invalid table: sparse array")
|
|
||||||
end
|
|
||||||
-- Encode
|
|
||||||
for i, v in ipairs(val) do
|
|
||||||
table.insert(res, encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "[" .. table.concat(res, ",") .. "]"
|
|
||||||
|
|
||||||
else
|
|
||||||
-- Treat as an object
|
|
||||||
for k, v in pairs(val) do
|
|
||||||
if type(k) ~= "string" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "{" .. table.concat(res, ",") .. "}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_string(val)
|
|
||||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_number(val)
|
|
||||||
-- Check for NaN, -inf and inf
|
|
||||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
|
||||||
error("unexpected number value '" .. tostring(val) .. "'")
|
|
||||||
end
|
|
||||||
return string.format("%.14g", val)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local type_func_map = {
|
|
||||||
[ "nil" ] = encode_nil,
|
|
||||||
[ "table" ] = encode_table,
|
|
||||||
[ "string" ] = encode_string,
|
|
||||||
[ "number" ] = encode_number,
|
|
||||||
[ "boolean" ] = tostring,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
encode = function(val, stack)
|
|
||||||
local t = type(val)
|
|
||||||
local f = type_func_map[t]
|
|
||||||
if f then
|
|
||||||
return f(val, stack)
|
|
||||||
end
|
|
||||||
error("unexpected type '" .. t .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.encode(val)
|
|
||||||
return ( encode(val) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Decode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local parse
|
|
||||||
|
|
||||||
local function create_set(...)
|
|
||||||
local res = {}
|
|
||||||
for i = 1, select("#", ...) do
|
|
||||||
res[ select(i, ...) ] = true
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
|
||||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
|
||||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
|
||||||
local literals = create_set("true", "false", "null")
|
|
||||||
|
|
||||||
local literal_map = {
|
|
||||||
[ "true" ] = true,
|
|
||||||
[ "false" ] = false,
|
|
||||||
[ "null" ] = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local function next_char(str, idx, set, negate)
|
|
||||||
for i = idx, #str do
|
|
||||||
if set[str:sub(i, i)] ~= negate then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return #str + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function decode_error(str, idx, msg)
|
|
||||||
--local line_count = 1
|
|
||||||
--local col_count = 1
|
|
||||||
--for i = 1, idx - 1 do
|
|
||||||
-- col_count = col_count + 1
|
|
||||||
-- if str:sub(i, i) == "\n" then
|
|
||||||
-- line_count = line_count + 1
|
|
||||||
-- col_count = 1
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- emu.message( string.format("%s at line %d col %d", msg, line_count, col_count) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function codepoint_to_utf8(n)
|
|
||||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
|
||||||
local f = math.floor
|
|
||||||
if n <= 0x7f then
|
|
||||||
return string.char(n)
|
|
||||||
elseif n <= 0x7ff then
|
|
||||||
return string.char(f(n / 64) + 192, n % 64 + 128)
|
|
||||||
elseif n <= 0xffff then
|
|
||||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
elseif n <= 0x10ffff then
|
|
||||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
|
||||||
f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
end
|
|
||||||
error( string.format("invalid unicode codepoint '%x'", n) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_unicode_escape(s)
|
|
||||||
local n1 = tonumber( s:sub(3, 6), 16 )
|
|
||||||
local n2 = tonumber( s:sub(9, 12), 16 )
|
|
||||||
-- Surrogate pair?
|
|
||||||
if n2 then
|
|
||||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
|
||||||
else
|
|
||||||
return codepoint_to_utf8(n1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_string(str, i)
|
|
||||||
local has_unicode_escape = false
|
|
||||||
local has_surrogate_escape = false
|
|
||||||
local has_escape = false
|
|
||||||
local last
|
|
||||||
for j = i + 1, #str do
|
|
||||||
local x = str:byte(j)
|
|
||||||
|
|
||||||
if x < 32 then
|
|
||||||
decode_error(str, j, "control character in string")
|
|
||||||
end
|
|
||||||
|
|
||||||
if last == 92 then -- "\\" (escape char)
|
|
||||||
if x == 117 then -- "u" (unicode escape sequence)
|
|
||||||
local hex = str:sub(j + 1, j + 5)
|
|
||||||
if not hex:find("%x%x%x%x") then
|
|
||||||
decode_error(str, j, "invalid unicode escape in string")
|
|
||||||
end
|
|
||||||
if hex:find("^[dD][89aAbB]") then
|
|
||||||
has_surrogate_escape = true
|
|
||||||
else
|
|
||||||
has_unicode_escape = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local c = string.char(x)
|
|
||||||
if not escape_chars[c] then
|
|
||||||
decode_error(str, j, "invalid escape char '" .. c .. "' in string")
|
|
||||||
end
|
|
||||||
has_escape = true
|
|
||||||
end
|
|
||||||
last = nil
|
|
||||||
|
|
||||||
elseif x == 34 then -- '"' (end of string)
|
|
||||||
local s = str:sub(i + 1, j - 1)
|
|
||||||
if has_surrogate_escape then
|
|
||||||
s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_unicode_escape then
|
|
||||||
s = s:gsub("\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_escape then
|
|
||||||
s = s:gsub("\\.", escape_char_map_inv)
|
|
||||||
end
|
|
||||||
return s, j + 1
|
|
||||||
|
|
||||||
else
|
|
||||||
last = x
|
|
||||||
end
|
|
||||||
end
|
|
||||||
decode_error(str, i, "expected closing quote for string")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_number(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local s = str:sub(i, x - 1)
|
|
||||||
local n = tonumber(s)
|
|
||||||
if not n then
|
|
||||||
decode_error(str, i, "invalid number '" .. s .. "'")
|
|
||||||
end
|
|
||||||
return n, x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_literal(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local word = str:sub(i, x - 1)
|
|
||||||
if not literals[word] then
|
|
||||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
|
||||||
end
|
|
||||||
return literal_map[word], x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_array(str, i)
|
|
||||||
local res = {}
|
|
||||||
local n = 1
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local x
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of array?
|
|
||||||
if str:sub(i, i) == "]" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read token
|
|
||||||
x, i = parse(str, i)
|
|
||||||
res[n] = x
|
|
||||||
n = n + 1
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "]" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_object(str, i)
|
|
||||||
local res = {}
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local key, val
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of object?
|
|
||||||
if str:sub(i, i) == "}" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read key
|
|
||||||
if str:sub(i, i) ~= '"' then
|
|
||||||
decode_error(str, i, "expected string for key")
|
|
||||||
end
|
|
||||||
key, i = parse(str, i)
|
|
||||||
-- Read ':' delimiter
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
if str:sub(i, i) ~= ":" then
|
|
||||||
decode_error(str, i, "expected ':' after key")
|
|
||||||
end
|
|
||||||
i = next_char(str, i + 1, space_chars, true)
|
|
||||||
-- Read value
|
|
||||||
val, i = parse(str, i)
|
|
||||||
-- Set
|
|
||||||
res[key] = val
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "}" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local char_func_map = {
|
|
||||||
[ '"' ] = parse_string,
|
|
||||||
[ "0" ] = parse_number,
|
|
||||||
[ "1" ] = parse_number,
|
|
||||||
[ "2" ] = parse_number,
|
|
||||||
[ "3" ] = parse_number,
|
|
||||||
[ "4" ] = parse_number,
|
|
||||||
[ "5" ] = parse_number,
|
|
||||||
[ "6" ] = parse_number,
|
|
||||||
[ "7" ] = parse_number,
|
|
||||||
[ "8" ] = parse_number,
|
|
||||||
[ "9" ] = parse_number,
|
|
||||||
[ "-" ] = parse_number,
|
|
||||||
[ "t" ] = parse_literal,
|
|
||||||
[ "f" ] = parse_literal,
|
|
||||||
[ "n" ] = parse_literal,
|
|
||||||
[ "[" ] = parse_array,
|
|
||||||
[ "{" ] = parse_object,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
parse = function(str, idx)
|
|
||||||
local chr = str:sub(idx, idx)
|
|
||||||
local f = char_func_map[chr]
|
|
||||||
if f then
|
|
||||||
return f(str, idx)
|
|
||||||
end
|
|
||||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.decode(str)
|
|
||||||
if type(str) ~= "string" then
|
|
||||||
error("expected argument of type string, got " .. type(str))
|
|
||||||
end
|
|
||||||
return ( parse(str, next_char(str, 1, space_chars, true)) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return json
|
|
|
@ -1,132 +0,0 @@
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- LuaSocket helper module
|
|
||||||
-- Author: Diego Nehab
|
|
||||||
-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Declare module and import dependencies
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local base = _G
|
|
||||||
local string = require("string")
|
|
||||||
local math = require("math")
|
|
||||||
local socket = require("socket.core")
|
|
||||||
module("socket")
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Exported auxiliar functions
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
function connect(address, port, laddress, lport)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
if laddress then
|
|
||||||
local res, err = sock:bind(laddress, lport, -1)
|
|
||||||
if not res then return nil, err end
|
|
||||||
end
|
|
||||||
local res, err = sock:connect(address, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
function bind(host, port, backlog)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
sock:setoption("reuseaddr", true)
|
|
||||||
local res, err = sock:bind(host, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
res, err = sock:listen(backlog)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
try = newtry()
|
|
||||||
|
|
||||||
function choose(table)
|
|
||||||
return function(name, opt1, opt2)
|
|
||||||
if base.type(name) ~= "string" then
|
|
||||||
name, opt1, opt2 = "default", name, opt1
|
|
||||||
end
|
|
||||||
local f = table[name or "nil"]
|
|
||||||
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
|
||||||
else return f(opt1, opt2) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Socket sources and sinks, conforming to LTN12
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- create namespaces inside LuaSocket namespace
|
|
||||||
sourcet = {}
|
|
||||||
sinkt = {}
|
|
||||||
|
|
||||||
BLOCKSIZE = 2048
|
|
||||||
|
|
||||||
sinkt["close-when-done"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if not chunk then
|
|
||||||
sock:close()
|
|
||||||
return 1
|
|
||||||
else return sock:send(chunk) end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["keep-open"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if chunk then return sock:send(chunk)
|
|
||||||
else return 1 end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["default"] = sinkt["keep-open"]
|
|
||||||
|
|
||||||
sink = choose(sinkt)
|
|
||||||
|
|
||||||
sourcet["by-length"] = function(sock, length)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if length <= 0 then return nil end
|
|
||||||
local size = math.min(socket.BLOCKSIZE, length)
|
|
||||||
local chunk, err = sock:receive(size)
|
|
||||||
if err then return nil, err end
|
|
||||||
length = length - string.len(chunk)
|
|
||||||
return chunk
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sourcet["until-closed"] = function(sock)
|
|
||||||
local done
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if done then return nil end
|
|
||||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
|
||||||
if not err then return chunk
|
|
||||||
elseif err == "closed" then
|
|
||||||
sock:close()
|
|
||||||
done = 1
|
|
||||||
return partial
|
|
||||||
else return nil, err end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
sourcet["default"] = sourcet["until-closed"]
|
|
||||||
|
|
||||||
source = choose(sourcet)
|
|
Binary file not shown.
|
@ -1,389 +0,0 @@
|
||||||
--
|
|
||||||
-- json.lua
|
|
||||||
--
|
|
||||||
-- Copyright (c) 2015 rxi
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or modify it
|
|
||||||
-- under the terms of the MIT license. See LICENSE for details.
|
|
||||||
--
|
|
||||||
|
|
||||||
local json = { _version = "0.1.0" }
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Encode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local encode
|
|
||||||
|
|
||||||
function error(err)
|
|
||||||
print(err)
|
|
||||||
end
|
|
||||||
|
|
||||||
local escape_char_map = {
|
|
||||||
[ "\\" ] = "\\\\",
|
|
||||||
[ "\"" ] = "\\\"",
|
|
||||||
[ "\b" ] = "\\b",
|
|
||||||
[ "\f" ] = "\\f",
|
|
||||||
[ "\n" ] = "\\n",
|
|
||||||
[ "\r" ] = "\\r",
|
|
||||||
[ "\t" ] = "\\t",
|
|
||||||
}
|
|
||||||
|
|
||||||
local escape_char_map_inv = { [ "\\/" ] = "/" }
|
|
||||||
for k, v in pairs(escape_char_map) do
|
|
||||||
escape_char_map_inv[v] = k
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function escape_char(c)
|
|
||||||
return escape_char_map[c] or string.format("\\u%04x", c:byte())
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_nil(val)
|
|
||||||
return "null"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_table(val, stack)
|
|
||||||
local res = {}
|
|
||||||
stack = stack or {}
|
|
||||||
|
|
||||||
-- Circular reference?
|
|
||||||
if stack[val] then error("circular reference") end
|
|
||||||
|
|
||||||
stack[val] = true
|
|
||||||
|
|
||||||
if val[1] ~= nil or next(val) == nil then
|
|
||||||
-- Treat as array -- check keys are valid and it is not sparse
|
|
||||||
local n = 0
|
|
||||||
for k in pairs(val) do
|
|
||||||
if type(k) ~= "number" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
if n ~= #val then
|
|
||||||
print("invalid table: sparse array")
|
|
||||||
print(n)
|
|
||||||
print("VAL:")
|
|
||||||
print(val)
|
|
||||||
print("STACK:")
|
|
||||||
print(stack)
|
|
||||||
end
|
|
||||||
-- Encode
|
|
||||||
for i, v in ipairs(val) do
|
|
||||||
table.insert(res, encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "[" .. table.concat(res, ",") .. "]"
|
|
||||||
|
|
||||||
else
|
|
||||||
-- Treat as an object
|
|
||||||
for k, v in pairs(val) do
|
|
||||||
if type(k) ~= "string" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "{" .. table.concat(res, ",") .. "}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_string(val)
|
|
||||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_number(val)
|
|
||||||
-- Check for NaN, -inf and inf
|
|
||||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
|
||||||
error("unexpected number value '" .. tostring(val) .. "'")
|
|
||||||
end
|
|
||||||
return string.format("%.14g", val)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local type_func_map = {
|
|
||||||
[ "nil" ] = encode_nil,
|
|
||||||
[ "table" ] = encode_table,
|
|
||||||
[ "string" ] = encode_string,
|
|
||||||
[ "number" ] = encode_number,
|
|
||||||
[ "boolean" ] = tostring,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
encode = function(val, stack)
|
|
||||||
local t = type(val)
|
|
||||||
local f = type_func_map[t]
|
|
||||||
if f then
|
|
||||||
return f(val, stack)
|
|
||||||
end
|
|
||||||
error("unexpected type '" .. t .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.encode(val)
|
|
||||||
return ( encode(val) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Decode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local parse
|
|
||||||
|
|
||||||
local function create_set(...)
|
|
||||||
local res = {}
|
|
||||||
for i = 1, select("#", ...) do
|
|
||||||
res[ select(i, ...) ] = true
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
|
||||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
|
||||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
|
||||||
local literals = create_set("true", "false", "null")
|
|
||||||
|
|
||||||
local literal_map = {
|
|
||||||
[ "true" ] = true,
|
|
||||||
[ "false" ] = false,
|
|
||||||
[ "null" ] = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local function next_char(str, idx, set, negate)
|
|
||||||
for i = idx, #str do
|
|
||||||
if set[str:sub(i, i)] ~= negate then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return #str + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function decode_error(str, idx, msg)
|
|
||||||
--local line_count = 1
|
|
||||||
--local col_count = 1
|
|
||||||
--for i = 1, idx - 1 do
|
|
||||||
-- col_count = col_count + 1
|
|
||||||
-- if str:sub(i, i) == "\n" then
|
|
||||||
-- line_count = line_count + 1
|
|
||||||
-- col_count = 1
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- emu.message( string.format("%s at line %d col %d", msg, line_count, col_count) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function codepoint_to_utf8(n)
|
|
||||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
|
||||||
local f = math.floor
|
|
||||||
if n <= 0x7f then
|
|
||||||
return string.char(n)
|
|
||||||
elseif n <= 0x7ff then
|
|
||||||
return string.char(f(n / 64) + 192, n % 64 + 128)
|
|
||||||
elseif n <= 0xffff then
|
|
||||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
elseif n <= 0x10ffff then
|
|
||||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
|
||||||
f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
end
|
|
||||||
error( string.format("invalid unicode codepoint '%x'", n) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_unicode_escape(s)
|
|
||||||
local n1 = tonumber( s:sub(3, 6), 16 )
|
|
||||||
local n2 = tonumber( s:sub(9, 12), 16 )
|
|
||||||
-- Surrogate pair?
|
|
||||||
if n2 then
|
|
||||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
|
||||||
else
|
|
||||||
return codepoint_to_utf8(n1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_string(str, i)
|
|
||||||
local has_unicode_escape = false
|
|
||||||
local has_surrogate_escape = false
|
|
||||||
local has_escape = false
|
|
||||||
local last
|
|
||||||
for j = i + 1, #str do
|
|
||||||
local x = str:byte(j)
|
|
||||||
|
|
||||||
if x < 32 then
|
|
||||||
decode_error(str, j, "control character in string")
|
|
||||||
end
|
|
||||||
|
|
||||||
if last == 92 then -- "\\" (escape char)
|
|
||||||
if x == 117 then -- "u" (unicode escape sequence)
|
|
||||||
local hex = str:sub(j + 1, j + 5)
|
|
||||||
if not hex:find("%x%x%x%x") then
|
|
||||||
decode_error(str, j, "invalid unicode escape in string")
|
|
||||||
end
|
|
||||||
if hex:find("^[dD][89aAbB]") then
|
|
||||||
has_surrogate_escape = true
|
|
||||||
else
|
|
||||||
has_unicode_escape = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local c = string.char(x)
|
|
||||||
if not escape_chars[c] then
|
|
||||||
decode_error(str, j, "invalid escape char '" .. c .. "' in string")
|
|
||||||
end
|
|
||||||
has_escape = true
|
|
||||||
end
|
|
||||||
last = nil
|
|
||||||
|
|
||||||
elseif x == 34 then -- '"' (end of string)
|
|
||||||
local s = str:sub(i + 1, j - 1)
|
|
||||||
if has_surrogate_escape then
|
|
||||||
s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_unicode_escape then
|
|
||||||
s = s:gsub("\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_escape then
|
|
||||||
s = s:gsub("\\.", escape_char_map_inv)
|
|
||||||
end
|
|
||||||
return s, j + 1
|
|
||||||
|
|
||||||
else
|
|
||||||
last = x
|
|
||||||
end
|
|
||||||
end
|
|
||||||
decode_error(str, i, "expected closing quote for string")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_number(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local s = str:sub(i, x - 1)
|
|
||||||
local n = tonumber(s)
|
|
||||||
if not n then
|
|
||||||
decode_error(str, i, "invalid number '" .. s .. "'")
|
|
||||||
end
|
|
||||||
return n, x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_literal(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local word = str:sub(i, x - 1)
|
|
||||||
if not literals[word] then
|
|
||||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
|
||||||
end
|
|
||||||
return literal_map[word], x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_array(str, i)
|
|
||||||
local res = {}
|
|
||||||
local n = 1
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local x
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of array?
|
|
||||||
if str:sub(i, i) == "]" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read token
|
|
||||||
x, i = parse(str, i)
|
|
||||||
res[n] = x
|
|
||||||
n = n + 1
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "]" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_object(str, i)
|
|
||||||
local res = {}
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local key, val
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of object?
|
|
||||||
if str:sub(i, i) == "}" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read key
|
|
||||||
if str:sub(i, i) ~= '"' then
|
|
||||||
decode_error(str, i, "expected string for key")
|
|
||||||
end
|
|
||||||
key, i = parse(str, i)
|
|
||||||
-- Read ':' delimiter
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
if str:sub(i, i) ~= ":" then
|
|
||||||
decode_error(str, i, "expected ':' after key")
|
|
||||||
end
|
|
||||||
i = next_char(str, i + 1, space_chars, true)
|
|
||||||
-- Read value
|
|
||||||
val, i = parse(str, i)
|
|
||||||
-- Set
|
|
||||||
res[key] = val
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "}" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local char_func_map = {
|
|
||||||
[ '"' ] = parse_string,
|
|
||||||
[ "0" ] = parse_number,
|
|
||||||
[ "1" ] = parse_number,
|
|
||||||
[ "2" ] = parse_number,
|
|
||||||
[ "3" ] = parse_number,
|
|
||||||
[ "4" ] = parse_number,
|
|
||||||
[ "5" ] = parse_number,
|
|
||||||
[ "6" ] = parse_number,
|
|
||||||
[ "7" ] = parse_number,
|
|
||||||
[ "8" ] = parse_number,
|
|
||||||
[ "9" ] = parse_number,
|
|
||||||
[ "-" ] = parse_number,
|
|
||||||
[ "t" ] = parse_literal,
|
|
||||||
[ "f" ] = parse_literal,
|
|
||||||
[ "n" ] = parse_literal,
|
|
||||||
[ "[" ] = parse_array,
|
|
||||||
[ "{" ] = parse_object,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
parse = function(str, idx)
|
|
||||||
local chr = str:sub(idx, idx)
|
|
||||||
local f = char_func_map[chr]
|
|
||||||
if f then
|
|
||||||
return f(str, idx)
|
|
||||||
end
|
|
||||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.decode(str)
|
|
||||||
if type(str) ~= "string" then
|
|
||||||
error("expected argument of type string, got " .. type(str))
|
|
||||||
end
|
|
||||||
return ( parse(str, next_char(str, 1, space_chars, true)) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return json
|
|
|
@ -1,132 +0,0 @@
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- LuaSocket helper module
|
|
||||||
-- Author: Diego Nehab
|
|
||||||
-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Declare module and import dependencies
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local base = _G
|
|
||||||
local string = require("string")
|
|
||||||
local math = require("math")
|
|
||||||
local socket = require("socket.core")
|
|
||||||
module("socket")
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Exported auxiliar functions
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
function connect(address, port, laddress, lport)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
if laddress then
|
|
||||||
local res, err = sock:bind(laddress, lport, -1)
|
|
||||||
if not res then return nil, err end
|
|
||||||
end
|
|
||||||
local res, err = sock:connect(address, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
function bind(host, port, backlog)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
sock:setoption("reuseaddr", true)
|
|
||||||
local res, err = sock:bind(host, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
res, err = sock:listen(backlog)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
try = newtry()
|
|
||||||
|
|
||||||
function choose(table)
|
|
||||||
return function(name, opt1, opt2)
|
|
||||||
if base.type(name) ~= "string" then
|
|
||||||
name, opt1, opt2 = "default", name, opt1
|
|
||||||
end
|
|
||||||
local f = table[name or "nil"]
|
|
||||||
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
|
||||||
else return f(opt1, opt2) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Socket sources and sinks, conforming to LTN12
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- create namespaces inside LuaSocket namespace
|
|
||||||
sourcet = {}
|
|
||||||
sinkt = {}
|
|
||||||
|
|
||||||
BLOCKSIZE = 2048
|
|
||||||
|
|
||||||
sinkt["close-when-done"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if not chunk then
|
|
||||||
sock:close()
|
|
||||||
return 1
|
|
||||||
else return sock:send(chunk) end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["keep-open"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if chunk then return sock:send(chunk)
|
|
||||||
else return 1 end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["default"] = sinkt["keep-open"]
|
|
||||||
|
|
||||||
sink = choose(sinkt)
|
|
||||||
|
|
||||||
sourcet["by-length"] = function(sock, length)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if length <= 0 then return nil end
|
|
||||||
local size = math.min(socket.BLOCKSIZE, length)
|
|
||||||
local chunk, err = sock:receive(size)
|
|
||||||
if err then return nil, err end
|
|
||||||
length = length - string.len(chunk)
|
|
||||||
return chunk
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sourcet["until-closed"] = function(sock)
|
|
||||||
local done
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if done then return nil end
|
|
||||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
|
||||||
if not err then return chunk
|
|
||||||
elseif err == "closed" then
|
|
||||||
sock:close()
|
|
||||||
done = 1
|
|
||||||
return partial
|
|
||||||
else return nil, err end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
sourcet["default"] = sourcet["until-closed"]
|
|
||||||
|
|
||||||
source = choose(sourcet)
|
|
Binary file not shown.
|
@ -1,380 +0,0 @@
|
||||||
--
|
|
||||||
-- json.lua
|
|
||||||
--
|
|
||||||
-- Copyright (c) 2015 rxi
|
|
||||||
--
|
|
||||||
-- This library is free software; you can redistribute it and/or modify it
|
|
||||||
-- under the terms of the MIT license. See LICENSE for details.
|
|
||||||
--
|
|
||||||
|
|
||||||
local json = { _version = "0.1.0" }
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Encode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local encode
|
|
||||||
|
|
||||||
local escape_char_map = {
|
|
||||||
[ "\\" ] = "\\\\",
|
|
||||||
[ "\"" ] = "\\\"",
|
|
||||||
[ "\b" ] = "\\b",
|
|
||||||
[ "\f" ] = "\\f",
|
|
||||||
[ "\n" ] = "\\n",
|
|
||||||
[ "\r" ] = "\\r",
|
|
||||||
[ "\t" ] = "\\t",
|
|
||||||
}
|
|
||||||
|
|
||||||
local escape_char_map_inv = { [ "\\/" ] = "/" }
|
|
||||||
for k, v in pairs(escape_char_map) do
|
|
||||||
escape_char_map_inv[v] = k
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function escape_char(c)
|
|
||||||
return escape_char_map[c] or string.format("\\u%04x", c:byte())
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_nil(val)
|
|
||||||
return "null"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_table(val, stack)
|
|
||||||
local res = {}
|
|
||||||
stack = stack or {}
|
|
||||||
|
|
||||||
-- Circular reference?
|
|
||||||
if stack[val] then error("circular reference") end
|
|
||||||
|
|
||||||
stack[val] = true
|
|
||||||
|
|
||||||
if val[1] ~= nil or next(val) == nil then
|
|
||||||
-- Treat as array -- check keys are valid and it is not sparse
|
|
||||||
local n = 0
|
|
||||||
for k in pairs(val) do
|
|
||||||
if type(k) ~= "number" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
n = n + 1
|
|
||||||
end
|
|
||||||
if n ~= #val then
|
|
||||||
error("invalid table: sparse array")
|
|
||||||
end
|
|
||||||
-- Encode
|
|
||||||
for i, v in ipairs(val) do
|
|
||||||
table.insert(res, encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "[" .. table.concat(res, ",") .. "]"
|
|
||||||
|
|
||||||
else
|
|
||||||
-- Treat as an object
|
|
||||||
for k, v in pairs(val) do
|
|
||||||
if type(k) ~= "string" then
|
|
||||||
error("invalid table: mixed or invalid key types")
|
|
||||||
end
|
|
||||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
|
||||||
end
|
|
||||||
stack[val] = nil
|
|
||||||
return "{" .. table.concat(res, ",") .. "}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_string(val)
|
|
||||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function encode_number(val)
|
|
||||||
-- Check for NaN, -inf and inf
|
|
||||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
|
||||||
error("unexpected number value '" .. tostring(val) .. "'")
|
|
||||||
end
|
|
||||||
return string.format("%.14g", val)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local type_func_map = {
|
|
||||||
[ "nil" ] = encode_nil,
|
|
||||||
[ "table" ] = encode_table,
|
|
||||||
[ "string" ] = encode_string,
|
|
||||||
[ "number" ] = encode_number,
|
|
||||||
[ "boolean" ] = tostring,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
encode = function(val, stack)
|
|
||||||
local t = type(val)
|
|
||||||
local f = type_func_map[t]
|
|
||||||
if f then
|
|
||||||
return f(val, stack)
|
|
||||||
end
|
|
||||||
error("unexpected type '" .. t .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.encode(val)
|
|
||||||
return ( encode(val) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Decode
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local parse
|
|
||||||
|
|
||||||
local function create_set(...)
|
|
||||||
local res = {}
|
|
||||||
for i = 1, select("#", ...) do
|
|
||||||
res[ select(i, ...) ] = true
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
|
||||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
|
||||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
|
||||||
local literals = create_set("true", "false", "null")
|
|
||||||
|
|
||||||
local literal_map = {
|
|
||||||
[ "true" ] = true,
|
|
||||||
[ "false" ] = false,
|
|
||||||
[ "null" ] = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local function next_char(str, idx, set, negate)
|
|
||||||
for i = idx, #str do
|
|
||||||
if set[str:sub(i, i)] ~= negate then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return #str + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function decode_error(str, idx, msg)
|
|
||||||
--local line_count = 1
|
|
||||||
--local col_count = 1
|
|
||||||
--for i = 1, idx - 1 do
|
|
||||||
-- col_count = col_count + 1
|
|
||||||
-- if str:sub(i, i) == "\n" then
|
|
||||||
-- line_count = line_count + 1
|
|
||||||
-- col_count = 1
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- emu.message( string.format("%s at line %d col %d", msg, line_count, col_count) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function codepoint_to_utf8(n)
|
|
||||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
|
||||||
local f = math.floor
|
|
||||||
if n <= 0x7f then
|
|
||||||
return string.char(n)
|
|
||||||
elseif n <= 0x7ff then
|
|
||||||
return string.char(f(n / 64) + 192, n % 64 + 128)
|
|
||||||
elseif n <= 0xffff then
|
|
||||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
elseif n <= 0x10ffff then
|
|
||||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
|
||||||
f(n % 4096 / 64) + 128, n % 64 + 128)
|
|
||||||
end
|
|
||||||
error( string.format("invalid unicode codepoint '%x'", n) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_unicode_escape(s)
|
|
||||||
local n1 = tonumber( s:sub(3, 6), 16 )
|
|
||||||
local n2 = tonumber( s:sub(9, 12), 16 )
|
|
||||||
-- Surrogate pair?
|
|
||||||
if n2 then
|
|
||||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
|
||||||
else
|
|
||||||
return codepoint_to_utf8(n1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_string(str, i)
|
|
||||||
local has_unicode_escape = false
|
|
||||||
local has_surrogate_escape = false
|
|
||||||
local has_escape = false
|
|
||||||
local last
|
|
||||||
for j = i + 1, #str do
|
|
||||||
local x = str:byte(j)
|
|
||||||
|
|
||||||
if x < 32 then
|
|
||||||
decode_error(str, j, "control character in string")
|
|
||||||
end
|
|
||||||
|
|
||||||
if last == 92 then -- "\\" (escape char)
|
|
||||||
if x == 117 then -- "u" (unicode escape sequence)
|
|
||||||
local hex = str:sub(j + 1, j + 5)
|
|
||||||
if not hex:find("%x%x%x%x") then
|
|
||||||
decode_error(str, j, "invalid unicode escape in string")
|
|
||||||
end
|
|
||||||
if hex:find("^[dD][89aAbB]") then
|
|
||||||
has_surrogate_escape = true
|
|
||||||
else
|
|
||||||
has_unicode_escape = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local c = string.char(x)
|
|
||||||
if not escape_chars[c] then
|
|
||||||
decode_error(str, j, "invalid escape char '" .. c .. "' in string")
|
|
||||||
end
|
|
||||||
has_escape = true
|
|
||||||
end
|
|
||||||
last = nil
|
|
||||||
|
|
||||||
elseif x == 34 then -- '"' (end of string)
|
|
||||||
local s = str:sub(i + 1, j - 1)
|
|
||||||
if has_surrogate_escape then
|
|
||||||
s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_unicode_escape then
|
|
||||||
s = s:gsub("\\u....", parse_unicode_escape)
|
|
||||||
end
|
|
||||||
if has_escape then
|
|
||||||
s = s:gsub("\\.", escape_char_map_inv)
|
|
||||||
end
|
|
||||||
return s, j + 1
|
|
||||||
|
|
||||||
else
|
|
||||||
last = x
|
|
||||||
end
|
|
||||||
end
|
|
||||||
decode_error(str, i, "expected closing quote for string")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_number(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local s = str:sub(i, x - 1)
|
|
||||||
local n = tonumber(s)
|
|
||||||
if not n then
|
|
||||||
decode_error(str, i, "invalid number '" .. s .. "'")
|
|
||||||
end
|
|
||||||
return n, x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_literal(str, i)
|
|
||||||
local x = next_char(str, i, delim_chars)
|
|
||||||
local word = str:sub(i, x - 1)
|
|
||||||
if not literals[word] then
|
|
||||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
|
||||||
end
|
|
||||||
return literal_map[word], x
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_array(str, i)
|
|
||||||
local res = {}
|
|
||||||
local n = 1
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local x
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of array?
|
|
||||||
if str:sub(i, i) == "]" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read token
|
|
||||||
x, i = parse(str, i)
|
|
||||||
res[n] = x
|
|
||||||
n = n + 1
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "]" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function parse_object(str, i)
|
|
||||||
local res = {}
|
|
||||||
i = i + 1
|
|
||||||
while 1 do
|
|
||||||
local key, val
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
-- Empty / end of object?
|
|
||||||
if str:sub(i, i) == "}" then
|
|
||||||
i = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- Read key
|
|
||||||
if str:sub(i, i) ~= '"' then
|
|
||||||
decode_error(str, i, "expected string for key")
|
|
||||||
end
|
|
||||||
key, i = parse(str, i)
|
|
||||||
-- Read ':' delimiter
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
if str:sub(i, i) ~= ":" then
|
|
||||||
decode_error(str, i, "expected ':' after key")
|
|
||||||
end
|
|
||||||
i = next_char(str, i + 1, space_chars, true)
|
|
||||||
-- Read value
|
|
||||||
val, i = parse(str, i)
|
|
||||||
-- Set
|
|
||||||
res[key] = val
|
|
||||||
-- Next token
|
|
||||||
i = next_char(str, i, space_chars, true)
|
|
||||||
local chr = str:sub(i, i)
|
|
||||||
i = i + 1
|
|
||||||
if chr == "}" then break end
|
|
||||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
|
||||||
end
|
|
||||||
return res, i
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local char_func_map = {
|
|
||||||
[ '"' ] = parse_string,
|
|
||||||
[ "0" ] = parse_number,
|
|
||||||
[ "1" ] = parse_number,
|
|
||||||
[ "2" ] = parse_number,
|
|
||||||
[ "3" ] = parse_number,
|
|
||||||
[ "4" ] = parse_number,
|
|
||||||
[ "5" ] = parse_number,
|
|
||||||
[ "6" ] = parse_number,
|
|
||||||
[ "7" ] = parse_number,
|
|
||||||
[ "8" ] = parse_number,
|
|
||||||
[ "9" ] = parse_number,
|
|
||||||
[ "-" ] = parse_number,
|
|
||||||
[ "t" ] = parse_literal,
|
|
||||||
[ "f" ] = parse_literal,
|
|
||||||
[ "n" ] = parse_literal,
|
|
||||||
[ "[" ] = parse_array,
|
|
||||||
[ "{" ] = parse_object,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
parse = function(str, idx)
|
|
||||||
local chr = str:sub(idx, idx)
|
|
||||||
local f = char_func_map[chr]
|
|
||||||
if f then
|
|
||||||
return f(str, idx)
|
|
||||||
end
|
|
||||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function json.decode(str)
|
|
||||||
if type(str) ~= "string" then
|
|
||||||
error("expected argument of type string, got " .. type(str))
|
|
||||||
end
|
|
||||||
return ( parse(str, next_char(str, 1, space_chars, true)) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return json
|
|
|
@ -1,132 +0,0 @@
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- LuaSocket helper module
|
|
||||||
-- Author: Diego Nehab
|
|
||||||
-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Declare module and import dependencies
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local base = _G
|
|
||||||
local string = require("string")
|
|
||||||
local math = require("math")
|
|
||||||
local socket = require("socket.core")
|
|
||||||
module("socket")
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Exported auxiliar functions
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
function connect(address, port, laddress, lport)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
if laddress then
|
|
||||||
local res, err = sock:bind(laddress, lport, -1)
|
|
||||||
if not res then return nil, err end
|
|
||||||
end
|
|
||||||
local res, err = sock:connect(address, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
function bind(host, port, backlog)
|
|
||||||
local sock, err = socket.tcp()
|
|
||||||
if not sock then return nil, err end
|
|
||||||
sock:setoption("reuseaddr", true)
|
|
||||||
local res, err = sock:bind(host, port)
|
|
||||||
if not res then return nil, err end
|
|
||||||
res, err = sock:listen(backlog)
|
|
||||||
if not res then return nil, err end
|
|
||||||
return sock
|
|
||||||
end
|
|
||||||
|
|
||||||
try = newtry()
|
|
||||||
|
|
||||||
function choose(table)
|
|
||||||
return function(name, opt1, opt2)
|
|
||||||
if base.type(name) ~= "string" then
|
|
||||||
name, opt1, opt2 = "default", name, opt1
|
|
||||||
end
|
|
||||||
local f = table[name or "nil"]
|
|
||||||
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
|
||||||
else return f(opt1, opt2) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Socket sources and sinks, conforming to LTN12
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- create namespaces inside LuaSocket namespace
|
|
||||||
sourcet = {}
|
|
||||||
sinkt = {}
|
|
||||||
|
|
||||||
BLOCKSIZE = 2048
|
|
||||||
|
|
||||||
sinkt["close-when-done"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if not chunk then
|
|
||||||
sock:close()
|
|
||||||
return 1
|
|
||||||
else return sock:send(chunk) end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["keep-open"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if chunk then return sock:send(chunk)
|
|
||||||
else return 1 end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sinkt["default"] = sinkt["keep-open"]
|
|
||||||
|
|
||||||
sink = choose(sinkt)
|
|
||||||
|
|
||||||
sourcet["by-length"] = function(sock, length)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if length <= 0 then return nil end
|
|
||||||
local size = math.min(socket.BLOCKSIZE, length)
|
|
||||||
local chunk, err = sock:receive(size)
|
|
||||||
if err then return nil, err end
|
|
||||||
length = length - string.len(chunk)
|
|
||||||
return chunk
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
sourcet["until-closed"] = function(sock)
|
|
||||||
local done
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
if done then return nil end
|
|
||||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
|
||||||
if not err then return chunk
|
|
||||||
elseif err == "closed" then
|
|
||||||
sock:close()
|
|
||||||
done = 1
|
|
||||||
return partial
|
|
||||||
else return nil, err end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
sourcet["default"] = sourcet["until-closed"]
|
|
||||||
|
|
||||||
source = choose(sourcet)
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
local lua_major, lua_minor = _VERSION:match("Lua (%d+)%.(%d+)")
|
||||||
|
lua_major = tonumber(lua_major)
|
||||||
|
lua_minor = tonumber(lua_minor)
|
||||||
|
-- lua compat shims
|
||||||
|
if lua_major > 5 or (lua_major == 5 and lua_minor >= 3) then
|
||||||
|
require("lua_5_3_compat")
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.empty (self)
|
||||||
|
for _, _ in pairs(self) do
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local bizhawk_version = client.getversion()
|
||||||
|
local bizhawk_major, bizhawk_minor, bizhawk_patch = bizhawk_version:match("(%d+)%.(%d+)%.?(%d*)")
|
||||||
|
bizhawk_major = tonumber(bizhawk_major)
|
||||||
|
bizhawk_minor = tonumber(bizhawk_minor)
|
||||||
|
if bizhawk_patch == "" then
|
||||||
|
bizhawk_patch = 0
|
||||||
|
else
|
||||||
|
bizhawk_patch = tonumber(bizhawk_patch)
|
||||||
|
end
|
||||||
|
|
||||||
|
local is23Or24Or25 = (bizhawk_version=="2.3.1") or (bizhawk_major == 2 and bizhawk_minor >= 3 and bizhawk_minor <= 5)
|
||||||
|
local isGreaterOrEqualTo26 = bizhawk_major > 2 or (bizhawk_major == 2 and bizhawk_minor >= 6)
|
||||||
|
local isUntestedBizhawk = bizhawk_major > 2 or (bizhawk_major == 2 and bizhawk_minor > 9)
|
||||||
|
local untestedBizhawkMessage = "Warning: this version of bizhawk is newer than we know about. If it doesn't work, consider downgrading to 2.9"
|
||||||
|
|
||||||
|
u8 = memory.read_u8
|
||||||
|
wU8 = memory.write_u8
|
||||||
|
u16 = memory.read_u16_le
|
||||||
|
|
||||||
|
function getMaxMessageLength()
|
||||||
|
local denominator = 12
|
||||||
|
if is23Or24Or25 then
|
||||||
|
denominator = 11
|
||||||
|
end
|
||||||
|
return math.floor(client.screenwidth()/denominator)
|
||||||
|
end
|
||||||
|
|
||||||
|
function drawText(x, y, message, color)
|
||||||
|
if is23Or24Or25 then
|
||||||
|
gui.addmessage(message)
|
||||||
|
elseif isGreaterOrEqualTo26 then
|
||||||
|
gui.drawText(x, y, message, color, 0xB0000000, 18, "Courier New", "middle", "bottom", nil, "client")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function clearScreen()
|
||||||
|
if is23Or24Or25 then
|
||||||
|
return
|
||||||
|
elseif isGreaterOrEqualTo26 then
|
||||||
|
drawText(0, 0, "", "black")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
itemMessages = {}
|
||||||
|
|
||||||
|
function drawMessages()
|
||||||
|
if table.empty(itemMessages) then
|
||||||
|
clearScreen()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local y = 10
|
||||||
|
found = false
|
||||||
|
maxMessageLength = getMaxMessageLength()
|
||||||
|
for k, v in pairs(itemMessages) do
|
||||||
|
if v["TTL"] > 0 then
|
||||||
|
message = v["message"]
|
||||||
|
while true do
|
||||||
|
drawText(5, y, message:sub(1, maxMessageLength), v["color"])
|
||||||
|
y = y + 16
|
||||||
|
|
||||||
|
message = message:sub(maxMessageLength + 1, message:len())
|
||||||
|
if message:len() == 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
newTTL = 0
|
||||||
|
if isGreaterOrEqualTo26 then
|
||||||
|
newTTL = itemMessages[k]["TTL"] - 1
|
||||||
|
end
|
||||||
|
itemMessages[k]["TTL"] = newTTL
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if found == false then
|
||||||
|
clearScreen()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function checkBizhawkVersion()
|
||||||
|
if not is23Or24Or25 and not isGreaterOrEqualTo26 then
|
||||||
|
print("Must use a version of bizhawk 2.3.1 or higher")
|
||||||
|
return false
|
||||||
|
elseif isUntestedBizhawk then
|
||||||
|
print(untestedBizhawkMessage)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
local socket = require("socket")
|
local socket = require("socket")
|
||||||
local json = require('json')
|
local json = require('json')
|
||||||
local math = require('math')
|
local math = require('math')
|
||||||
|
require("common")
|
||||||
|
|
||||||
local STATE_OK = "Ok"
|
local STATE_OK = "Ok"
|
||||||
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
||||||
|
@ -32,8 +33,6 @@ local frames_with_no_item = 0
|
||||||
local ItemTableStart = 0xfe9d
|
local ItemTableStart = 0xfe9d
|
||||||
local PlayerSlotAddress = 0xfff9
|
local PlayerSlotAddress = 0xfff9
|
||||||
|
|
||||||
local itemMessages = {}
|
|
||||||
|
|
||||||
local nullObjectId = 0xB4
|
local nullObjectId = 0xB4
|
||||||
local ItemsReceived = nil
|
local ItemsReceived = nil
|
||||||
local sha256hash = nil
|
local sha256hash = nil
|
||||||
|
@ -101,17 +100,6 @@ local current_bat_ap_item = nil
|
||||||
|
|
||||||
local was_in_number_room = false
|
local was_in_number_room = false
|
||||||
|
|
||||||
local u8 = nil
|
|
||||||
local wU8 = nil
|
|
||||||
local u16
|
|
||||||
|
|
||||||
local bizhawk_version = client.getversion()
|
|
||||||
local is23Or24Or25 = (bizhawk_version=="2.3.1") or (bizhawk_version:sub(1,3)=="2.4") or (bizhawk_version:sub(1,3)=="2.5")
|
|
||||||
local is26To28 = (bizhawk_version:sub(1,3)=="2.6") or (bizhawk_version:sub(1,3)=="2.7") or (bizhawk_version:sub(1,3)=="2.8")
|
|
||||||
|
|
||||||
u8 = memory.read_u8
|
|
||||||
wU8 = memory.write_u8
|
|
||||||
u16 = memory.read_u16_le
|
|
||||||
function uRangeRam(address, bytes)
|
function uRangeRam(address, bytes)
|
||||||
data = memory.read_bytes_as_array(address, bytes, "Main RAM")
|
data = memory.read_bytes_as_array(address, bytes, "Main RAM")
|
||||||
return data
|
return data
|
||||||
|
@ -125,23 +113,6 @@ function uRangeAddress(address, bytes)
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function table.empty (self)
|
|
||||||
for _, _ in pairs(self) do
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function slice (tbl, s, e)
|
|
||||||
local pos, new = 1, {}
|
|
||||||
for i = s + 1, e do
|
|
||||||
new[pos] = tbl[i]
|
|
||||||
pos = pos + 1
|
|
||||||
end
|
|
||||||
return new
|
|
||||||
end
|
|
||||||
|
|
||||||
local function createForeignItemsByRoom()
|
local function createForeignItemsByRoom()
|
||||||
foreign_items_by_room = {}
|
foreign_items_by_room = {}
|
||||||
if foreign_items == nil then
|
if foreign_items == nil then
|
||||||
|
@ -294,94 +265,11 @@ function processBlock(block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function clearScreen()
|
|
||||||
if is23Or24Or25 then
|
|
||||||
return
|
|
||||||
elseif is26To28 then
|
|
||||||
drawText(0, 0, "", "black")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getMaxMessageLength()
|
|
||||||
if is23Or24Or25 then
|
|
||||||
return client.screenwidth()/11
|
|
||||||
elseif is26To28 then
|
|
||||||
return client.screenwidth()/12
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function drawText(x, y, message, color)
|
|
||||||
if is23Or24Or25 then
|
|
||||||
gui.addmessage(message)
|
|
||||||
elseif is26To28 then
|
|
||||||
gui.drawText(x, y, message, color, 0xB0000000, 18, "Courier New", nil, nil, nil, "client")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drawMessages()
|
|
||||||
if table.empty(itemMessages) then
|
|
||||||
clearScreen()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local y = 10
|
|
||||||
found = false
|
|
||||||
maxMessageLength = getMaxMessageLength()
|
|
||||||
for k, v in pairs(itemMessages) do
|
|
||||||
if v["TTL"] > 0 then
|
|
||||||
message = v["message"]
|
|
||||||
while true do
|
|
||||||
drawText(5, y, message:sub(1, maxMessageLength), v["color"])
|
|
||||||
y = y + 16
|
|
||||||
|
|
||||||
message = message:sub(maxMessageLength + 1, message:len())
|
|
||||||
if message:len() == 0 then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
newTTL = 0
|
|
||||||
if is26To28 then
|
|
||||||
newTTL = itemMessages[k]["TTL"] - 1
|
|
||||||
end
|
|
||||||
itemMessages[k]["TTL"] = newTTL
|
|
||||||
found = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if found == false then
|
|
||||||
clearScreen()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function difference(a, b)
|
|
||||||
local aa = {}
|
|
||||||
for k,v in pairs(a) do aa[v]=true end
|
|
||||||
for k,v in pairs(b) do aa[v]=nil end
|
|
||||||
local ret = {}
|
|
||||||
local n = 0
|
|
||||||
for k,v in pairs(a) do
|
|
||||||
if aa[v] then n=n+1 ret[n]=v end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function getAllRam()
|
function getAllRam()
|
||||||
uRangeRAM(0,128);
|
uRangeRAM(0,128);
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
|
|
||||||
local function arrayEqual(a1, a2)
|
|
||||||
if #a1 ~= #a2 then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, v in ipairs(a1) do
|
|
||||||
if v ~= a2[i] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function alive_mode()
|
local function alive_mode()
|
||||||
return (u8(PlayerRoomAddr) ~= 0x00 and u8(WinAddr) == 0x00)
|
return (u8(PlayerRoomAddr) ~= 0x00 and u8(WinAddr) == 0x00)
|
||||||
end
|
end
|
||||||
|
@ -569,8 +457,7 @@ end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
memory.usememorydomain("System Bus")
|
memory.usememorydomain("System Bus")
|
||||||
if (is23Or24Or25 or is26To28) == false then
|
if not checkBizhawkVersion() then
|
||||||
print("Must use a version of bizhawk 2.3.1 or higher")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local playerSlot = memory.read_u8(PlayerSlotAddress)
|
local playerSlot = memory.read_u8(PlayerSlotAddress)
|
|
@ -1,6 +1,7 @@
|
||||||
local socket = require("socket")
|
local socket = require("socket")
|
||||||
local json = require('json')
|
local json = require('json')
|
||||||
local math = require('math')
|
local math = require('math')
|
||||||
|
require("common")
|
||||||
|
|
||||||
local STATE_OK = "Ok"
|
local STATE_OK = "Ok"
|
||||||
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
||||||
|
@ -102,15 +103,12 @@ local noOverworldItemsLookup = {
|
||||||
[500] = 0x12,
|
[500] = 0x12,
|
||||||
}
|
}
|
||||||
|
|
||||||
local itemMessages = {}
|
|
||||||
local consumableStacks = nil
|
local consumableStacks = nil
|
||||||
local prevstate = ""
|
local prevstate = ""
|
||||||
local curstate = STATE_UNINITIALIZED
|
local curstate = STATE_UNINITIALIZED
|
||||||
local ff1Socket = nil
|
local ff1Socket = nil
|
||||||
local frame = 0
|
local frame = 0
|
||||||
|
|
||||||
local u8 = nil
|
|
||||||
local wU8 = nil
|
|
||||||
local isNesHawk = false
|
local isNesHawk = false
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,9 +132,6 @@ local function defineMemoryFunctions()
|
||||||
end
|
end
|
||||||
|
|
||||||
local memDomain = defineMemoryFunctions()
|
local memDomain = defineMemoryFunctions()
|
||||||
u8 = memory.read_u8
|
|
||||||
wU8 = memory.write_u8
|
|
||||||
uRange = memory.readbyterange
|
|
||||||
|
|
||||||
local function StateOKForMainLoop()
|
local function StateOKForMainLoop()
|
||||||
memDomain.saveram()
|
memDomain.saveram()
|
||||||
|
@ -146,83 +141,6 @@ local function StateOKForMainLoop()
|
||||||
return A ~= 0x00 and not (A== 0xF2 and B == 0xF2 and C == 0xF2)
|
return A ~= 0x00 and not (A== 0xF2 and B == 0xF2 and C == 0xF2)
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.empty (self)
|
|
||||||
for _, _ in pairs(self) do
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function slice (tbl, s, e)
|
|
||||||
local pos, new = 1, {}
|
|
||||||
for i = s + 1, e do
|
|
||||||
new[pos] = tbl[i]
|
|
||||||
pos = pos + 1
|
|
||||||
end
|
|
||||||
return new
|
|
||||||
end
|
|
||||||
|
|
||||||
local bizhawk_version = client.getversion()
|
|
||||||
local is23Or24Or25 = (bizhawk_version=="2.3.1") or (bizhawk_version:sub(1,3)=="2.4") or (bizhawk_version:sub(1,3)=="2.5")
|
|
||||||
local is26To28 = (bizhawk_version:sub(1,3)=="2.6") or (bizhawk_version:sub(1,3)=="2.7") or (bizhawk_version:sub(1,3)=="2.8")
|
|
||||||
|
|
||||||
local function getMaxMessageLength()
|
|
||||||
if is23Or24Or25 then
|
|
||||||
return client.screenwidth()/11
|
|
||||||
elseif is26To28 then
|
|
||||||
return client.screenwidth()/12
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drawText(x, y, message, color)
|
|
||||||
if is23Or24Or25 then
|
|
||||||
gui.addmessage(message)
|
|
||||||
elseif is26To28 then
|
|
||||||
gui.drawText(x, y, message, color, 0xB0000000, 18, "Courier New", nil, nil, nil, "client")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function clearScreen()
|
|
||||||
if is23Or24Or25 then
|
|
||||||
return
|
|
||||||
elseif is26To28 then
|
|
||||||
drawText(0, 0, "", "black")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drawMessages()
|
|
||||||
if table.empty(itemMessages) then
|
|
||||||
clearScreen()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local y = 10
|
|
||||||
found = false
|
|
||||||
maxMessageLength = getMaxMessageLength()
|
|
||||||
for k, v in pairs(itemMessages) do
|
|
||||||
if v["TTL"] > 0 then
|
|
||||||
message = v["message"]
|
|
||||||
while true do
|
|
||||||
drawText(5, y, message:sub(1, maxMessageLength), v["color"])
|
|
||||||
y = y + 16
|
|
||||||
|
|
||||||
message = message:sub(maxMessageLength + 1, message:len())
|
|
||||||
if message:len() == 0 then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
newTTL = 0
|
|
||||||
if is26To28 then
|
|
||||||
newTTL = itemMessages[k]["TTL"] - 1
|
|
||||||
end
|
|
||||||
itemMessages[k]["TTL"] = newTTL
|
|
||||||
found = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if found == false then
|
|
||||||
clearScreen()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function generateLocationChecked()
|
function generateLocationChecked()
|
||||||
memDomain.saveram()
|
memDomain.saveram()
|
||||||
data = uRange(0x01FF, 0x101)
|
data = uRange(0x01FF, 0x101)
|
||||||
|
@ -316,7 +234,14 @@ function getEmptyArmorSlots()
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
local function slice (tbl, s, e)
|
||||||
|
local pos, new = 1, {}
|
||||||
|
for i = s + 1, e do
|
||||||
|
new[pos] = tbl[i]
|
||||||
|
pos = pos + 1
|
||||||
|
end
|
||||||
|
return new
|
||||||
|
end
|
||||||
function processBlock(block)
|
function processBlock(block)
|
||||||
local msgBlock = block['messages']
|
local msgBlock = block['messages']
|
||||||
if msgBlock ~= nil then
|
if msgBlock ~= nil then
|
||||||
|
@ -448,18 +373,6 @@ function processBlock(block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function difference(a, b)
|
|
||||||
local aa = {}
|
|
||||||
for k,v in pairs(a) do aa[v]=true end
|
|
||||||
for k,v in pairs(b) do aa[v]=nil end
|
|
||||||
local ret = {}
|
|
||||||
local n = 0
|
|
||||||
for k,v in pairs(a) do
|
|
||||||
if aa[v] then n=n+1 ret[n]=v end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function receive()
|
function receive()
|
||||||
l, e = ff1Socket:receive()
|
l, e = ff1Socket:receive()
|
||||||
if e == 'closed' then
|
if e == 'closed' then
|
||||||
|
@ -501,8 +414,7 @@ function receive()
|
||||||
end
|
end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
if (is23Or24Or25 or is26To28) == false then
|
if not checkBizhawkVersion() then
|
||||||
print("Must use a version of bizhawk 2.3.1 or higher")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
server, error = socket.bind('localhost', 52980)
|
server, error = socket.bind('localhost', 52980)
|
|
@ -1,8 +1,9 @@
|
||||||
local socket = require("socket")
|
local socket = require("socket")
|
||||||
local json = require('json')
|
local json = require('json')
|
||||||
local math = require('math')
|
local math = require('math')
|
||||||
|
require('common.lua')
|
||||||
|
|
||||||
local last_modified_date = '2022-11-27' -- Should be the last modified date
|
local last_modified_date = '2022-4-9' -- Should be the last modified date
|
||||||
local script_version = 3
|
local script_version = 3
|
||||||
|
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
@ -1861,8 +1862,7 @@ function receive()
|
||||||
end
|
end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
if (is23Or24Or25 or is26To27) == false then
|
if not checkBizhawkVersion() then
|
||||||
print("Must use a version of bizhawk 2.3.1 or higher")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
server, error = socket.bind('localhost', 28921)
|
server, error = socket.bind('localhost', 28921)
|
||||||
|
@ -1886,7 +1886,7 @@ function main()
|
||||||
ootSocket = client
|
ootSocket = client
|
||||||
ootSocket:settimeout(0)
|
ootSocket:settimeout(0)
|
||||||
else
|
else
|
||||||
print('Connection failed, ensure OoTClient is running and rerun oot_connector.lua')
|
print('Connection failed, ensure OoTClient is running and rerun connector_oot.lua')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
local socket = require("socket")
|
local socket = require("socket")
|
||||||
local json = require('json')
|
local json = require('json')
|
||||||
local math = require('math')
|
local math = require('math')
|
||||||
|
require("common")
|
||||||
local STATE_OK = "Ok"
|
local STATE_OK = "Ok"
|
||||||
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
||||||
local STATE_INITIAL_CONNECTION_MADE = "Initial Connection Made"
|
local STATE_INITIAL_CONNECTION_MADE = "Initial Connection Made"
|
||||||
|
@ -32,9 +32,6 @@ local curstate = STATE_UNINITIALIZED
|
||||||
local gbSocket = nil
|
local gbSocket = nil
|
||||||
local frame = 0
|
local frame = 0
|
||||||
|
|
||||||
local u8 = nil
|
|
||||||
local wU8 = nil
|
|
||||||
local u16
|
|
||||||
local compat = nil
|
local compat = nil
|
||||||
|
|
||||||
local function defineMemoryFunctions()
|
local function defineMemoryFunctions()
|
||||||
|
@ -55,35 +52,6 @@ function uRange(address, bytes)
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function table.empty (self)
|
|
||||||
for _, _ in pairs(self) do
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function slice (tbl, s, e)
|
|
||||||
local pos, new = 1, {}
|
|
||||||
for i = s + 1, e do
|
|
||||||
new[pos] = tbl[i]
|
|
||||||
pos = pos + 1
|
|
||||||
end
|
|
||||||
return new
|
|
||||||
end
|
|
||||||
|
|
||||||
function difference(a, b)
|
|
||||||
local aa = {}
|
|
||||||
for k,v in pairs(a) do aa[v]=true end
|
|
||||||
for k,v in pairs(b) do aa[v]=nil end
|
|
||||||
local ret = {}
|
|
||||||
local n = 0
|
|
||||||
for k,v in pairs(a) do
|
|
||||||
if aa[v] then n=n+1 ret[n]=v end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function generateLocationsChecked()
|
function generateLocationsChecked()
|
||||||
memDomain.wram()
|
memDomain.wram()
|
||||||
events = uRange(EventFlagAddress, 0x140)
|
events = uRange(EventFlagAddress, 0x140)
|
||||||
|
@ -106,17 +74,17 @@ function generateLocationsChecked()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function arrayEqual(a1, a2)
|
local function arrayEqual(a1, a2)
|
||||||
if #a1 ~= #a2 then
|
if #a1 ~= #a2 then
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, v in ipairs(a1) do
|
|
||||||
if v ~= a2[i] then
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
for i, v in ipairs(a1) do
|
||||||
return true
|
if v ~= a2[i] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function receive()
|
function receive()
|
||||||
|
@ -196,8 +164,7 @@ function receive()
|
||||||
end
|
end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
if (is23Or24Or25 or is26To28) == false then
|
if not checkBizhawkVersion() then
|
||||||
print("Must use a version of bizhawk 2.3.1 or higher")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
server, error = socket.bind('localhost', 17242)
|
server, error = socket.bind('localhost', 17242)
|
|
@ -3,13 +3,12 @@
|
||||||
local socket = require("socket")
|
local socket = require("socket")
|
||||||
local json = require('json')
|
local json = require('json')
|
||||||
local math = require('math')
|
local math = require('math')
|
||||||
|
require("common")
|
||||||
local STATE_OK = "Ok"
|
local STATE_OK = "Ok"
|
||||||
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
||||||
local STATE_INITIAL_CONNECTION_MADE = "Initial Connection Made"
|
local STATE_INITIAL_CONNECTION_MADE = "Initial Connection Made"
|
||||||
local STATE_UNINITIALIZED = "Uninitialized"
|
local STATE_UNINITIALIZED = "Uninitialized"
|
||||||
|
|
||||||
local itemMessages = {}
|
|
||||||
local consumableStacks = nil
|
local consumableStacks = nil
|
||||||
local prevstate = ""
|
local prevstate = ""
|
||||||
local curstate = STATE_UNINITIALIZED
|
local curstate = STATE_UNINITIALIZED
|
||||||
|
@ -21,8 +20,6 @@ local cave_index
|
||||||
local triforce_byte
|
local triforce_byte
|
||||||
local game_state
|
local game_state
|
||||||
|
|
||||||
local u8 = nil
|
|
||||||
local wU8 = nil
|
|
||||||
local isNesHawk = false
|
local isNesHawk = false
|
||||||
|
|
||||||
local shopsChecked = {}
|
local shopsChecked = {}
|
||||||
|
@ -420,83 +417,6 @@ local function checkCaveItemObtained()
|
||||||
return returnTable
|
return returnTable
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.empty (self)
|
|
||||||
for _, _ in pairs(self) do
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function slice (tbl, s, e)
|
|
||||||
local pos, new = 1, {}
|
|
||||||
for i = s + 1, e do
|
|
||||||
new[pos] = tbl[i]
|
|
||||||
pos = pos + 1
|
|
||||||
end
|
|
||||||
return new
|
|
||||||
end
|
|
||||||
|
|
||||||
local bizhawk_version = client.getversion()
|
|
||||||
local is23Or24Or25 = (bizhawk_version=="2.3.1") or (bizhawk_version:sub(1,3)=="2.4") or (bizhawk_version:sub(1,3)=="2.5")
|
|
||||||
local is26To28 = (bizhawk_version:sub(1,3)=="2.6") or (bizhawk_version:sub(1,3)=="2.7") or (bizhawk_version:sub(1,3)=="2.8")
|
|
||||||
|
|
||||||
local function getMaxMessageLength()
|
|
||||||
if is23Or24Or25 then
|
|
||||||
return client.screenwidth()/11
|
|
||||||
elseif is26To28 then
|
|
||||||
return client.screenwidth()/12
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drawText(x, y, message, color)
|
|
||||||
if is23Or24Or25 then
|
|
||||||
gui.addmessage(message)
|
|
||||||
elseif is26To28 then
|
|
||||||
gui.drawText(x, y, message, color, 0xB0000000, 18, "Courier New", "middle", "bottom", nil, "client")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function clearScreen()
|
|
||||||
if is23Or24Or25 then
|
|
||||||
return
|
|
||||||
elseif is26To28 then
|
|
||||||
drawText(0, 0, "", "black")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drawMessages()
|
|
||||||
if table.empty(itemMessages) then
|
|
||||||
clearScreen()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local y = 10
|
|
||||||
found = false
|
|
||||||
maxMessageLength = getMaxMessageLength()
|
|
||||||
for k, v in pairs(itemMessages) do
|
|
||||||
if v["TTL"] > 0 then
|
|
||||||
message = v["message"]
|
|
||||||
while true do
|
|
||||||
drawText(5, y, message:sub(1, maxMessageLength), v["color"])
|
|
||||||
y = y + 16
|
|
||||||
|
|
||||||
message = message:sub(maxMessageLength + 1, message:len())
|
|
||||||
if message:len() == 0 then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
newTTL = 0
|
|
||||||
if is26To28 then
|
|
||||||
newTTL = itemMessages[k]["TTL"] - 1
|
|
||||||
end
|
|
||||||
itemMessages[k]["TTL"] = newTTL
|
|
||||||
found = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if found == false then
|
|
||||||
clearScreen()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function generateOverworldLocationChecked()
|
function generateOverworldLocationChecked()
|
||||||
memDomain.ram()
|
memDomain.ram()
|
||||||
data = uRange(0x067E, 0x81)
|
data = uRange(0x067E, 0x81)
|
||||||
|
@ -589,18 +509,6 @@ function processBlock(block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function difference(a, b)
|
|
||||||
local aa = {}
|
|
||||||
for k,v in pairs(a) do aa[v]=true end
|
|
||||||
for k,v in pairs(b) do aa[v]=nil end
|
|
||||||
local ret = {}
|
|
||||||
local n = 0
|
|
||||||
for k,v in pairs(a) do
|
|
||||||
if aa[v] then n=n+1 ret[n]=v end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function receive()
|
function receive()
|
||||||
l, e = zeldaSocket:receive()
|
l, e = zeldaSocket:receive()
|
||||||
if e == 'closed' then
|
if e == 'closed' then
|
||||||
|
@ -653,8 +561,7 @@ function receive()
|
||||||
end
|
end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
if (is23Or24Or25 or is26To28) == false then
|
if not checkBizhawkVersion() then
|
||||||
print("Must use a version of bizhawk 2.3.1 or higher")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
server, error = socket.bind('localhost', 52980)
|
server, error = socket.bind('localhost', 52980)
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
||||||
|
function bit.rshift(a, b)
|
||||||
|
return a >> b
|
||||||
|
end
|
||||||
|
function bit.lshift(a, b)
|
||||||
|
return a << b
|
||||||
|
end
|
||||||
|
function bit.bor(a, b)
|
||||||
|
return a | b
|
||||||
|
end
|
||||||
|
function bit.band(a, b)
|
||||||
|
return a & b
|
||||||
|
end
|
|
@ -10,8 +10,53 @@
|
||||||
local base = _G
|
local base = _G
|
||||||
local string = require("string")
|
local string = require("string")
|
||||||
local math = require("math")
|
local math = require("math")
|
||||||
local socket = require("socket.core")
|
|
||||||
module("socket")
|
function get_lua_version()
|
||||||
|
local major, minor = _VERSION:match("Lua (%d+)%.(%d+)")
|
||||||
|
assert(tonumber(major) == 5)
|
||||||
|
if tonumber(minor) >= 4 then
|
||||||
|
return "5-4"
|
||||||
|
end
|
||||||
|
return "5-1"
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_os()
|
||||||
|
local the_os, ext, arch
|
||||||
|
if package.config:sub(1,1) == "\\" then
|
||||||
|
the_os, ext = "windows", "dll"
|
||||||
|
arch = os.getenv"PROCESSOR_ARCHITECTURE"
|
||||||
|
else
|
||||||
|
-- TODO: macos?
|
||||||
|
the_os, ext = "linux", "so"
|
||||||
|
arch = "x86_64" -- TODO: read ELF header from /proc/$PID/exe to get arch
|
||||||
|
end
|
||||||
|
|
||||||
|
if arch:find("64") ~= nil then
|
||||||
|
arch = "x64"
|
||||||
|
else
|
||||||
|
arch = "x86"
|
||||||
|
end
|
||||||
|
|
||||||
|
return the_os, ext, arch
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_socket_path()
|
||||||
|
local the_os, ext, arch = get_os()
|
||||||
|
-- for some reason ./ isn't working, so use a horrible hack to get the pwd
|
||||||
|
local pwd = (io.popen and io.popen("cd"):read'*l') or "."
|
||||||
|
return pwd .. "/" .. arch .. "/socket-" .. the_os .. "-" .. get_lua_version() .. "." .. ext
|
||||||
|
end
|
||||||
|
|
||||||
|
local socket_path = get_socket_path()
|
||||||
|
local socket = assert(package.loadlib(socket_path, "luaopen_socket_core"))()
|
||||||
|
|
||||||
|
-- http://lua-users.org/wiki/ModulesTutorial
|
||||||
|
local M = {}
|
||||||
|
if setfenv then
|
||||||
|
setfenv(1, M) -- for 5.1
|
||||||
|
else
|
||||||
|
_ENV = M -- for 5.2
|
||||||
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
-- Exported auxiliar functions
|
-- Exported auxiliar functions
|
||||||
|
@ -39,7 +84,7 @@ function bind(host, port, backlog)
|
||||||
return sock
|
return sock
|
||||||
end
|
end
|
||||||
|
|
||||||
try = newtry()
|
try = socket.newtry()
|
||||||
|
|
||||||
function choose(table)
|
function choose(table)
|
||||||
return function(name, opt1, opt2)
|
return function(name, opt1, opt2)
|
||||||
|
@ -130,3 +175,5 @@ end
|
||||||
sourcet["default"] = sourcet["until-closed"]
|
sourcet["default"] = sourcet["until-closed"]
|
||||||
|
|
||||||
source = choose(sourcet)
|
source = choose(sourcet)
|
||||||
|
|
||||||
|
return M
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
LuaSocket 3.0 license
|
||||||
|
Copyright <20> 2004-2013 Diego Nehab
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,20 @@
|
||||||
|
LuaSocket 3.0 license
|
||||||
|
Copyright <20> 2004-2013 Diego Nehab
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
Binary file not shown.
|
@ -181,7 +181,7 @@ adventure_options:
|
||||||
# For example, this can be used to autoload the connector script in BizHawk
|
# For example, this can be used to autoload the connector script in BizHawk
|
||||||
# (see BizHawk --lua= option)
|
# (see BizHawk --lua= option)
|
||||||
# Windows example:
|
# Windows example:
|
||||||
# rom_args: "--lua=C:/ProgramData/Archipelago/data/lua/ADVENTURE/adventure_connector.lua"
|
# rom_args: "--lua=C:/ProgramData/Archipelago/data/lua/connector_adventure.lua"
|
||||||
rom_args: " "
|
rom_args: " "
|
||||||
# Set this to true to display item received messages in Emuhawk
|
# Set this to true to display item received messages in Emuhawk
|
||||||
display_msgs: true
|
display_msgs: true
|
||||||
|
|
|
@ -27,10 +27,10 @@ Once Bizhawk has been installed, open Bizhawk and change the following settings:
|
||||||
BizHawk is running in the background.
|
BizHawk is running in the background.
|
||||||
|
|
||||||
- It is recommended that you provide a path to BizHawk in your host.yaml for Adventure so the client can start it automatically
|
- It is recommended that you provide a path to BizHawk in your host.yaml for Adventure so the client can start it automatically
|
||||||
- At the same time, you can set an option to automatically load the adventure_connector.lua script when launching BizHawk
|
- At the same time, you can set an option to automatically load the connector_adventure.lua script when launching BizHawk
|
||||||
from AdventureClient.
|
from AdventureClient.
|
||||||
Default Windows install example:
|
Default Windows install example:
|
||||||
```rom_args: "--lua=C:/ProgramData/Archipelago/data/lua/ADVENTURE/adventure_connector.lua"```
|
```rom_args: "--lua=C:/ProgramData/Archipelago/data/lua/connector_adventure.lua"```
|
||||||
|
|
||||||
## Configuring your YAML file
|
## Configuring your YAML file
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ path as recommended).
|
||||||
Once both the client and the emulator are started, you must connect them. Within the emulator click on the "Tools"
|
Once both the client and the emulator are started, you must connect them. Within the emulator click on the "Tools"
|
||||||
menu and select "Lua Console". Click the folder button or press Ctrl+O to open a Lua script.
|
menu and select "Lua Console". Click the folder button or press Ctrl+O to open a Lua script.
|
||||||
|
|
||||||
Navigate to your Archipelago install folder and open `data/lua/ADVENTURE/adventure_connector.lua`, if it is not
|
Navigate to your Archipelago install folder and open `data/lua/connector_adventure.lua`, if it is not
|
||||||
configured to do this automatically.
|
configured to do this automatically.
|
||||||
|
|
||||||
To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
|
To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
|
||||||
|
|
|
@ -58,7 +58,7 @@ Once the Archipelago server has been hosted:
|
||||||
extension `*.nes`
|
extension `*.nes`
|
||||||
2. Click on the Tools menu and click on **Lua Console**
|
2. Click on the Tools menu and click on **Lua Console**
|
||||||
3. Click the folder button to open a new Lua script. (CTL-O or **Script** -> **Open Script**)
|
3. Click the folder button to open a new Lua script. (CTL-O or **Script** -> **Open Script**)
|
||||||
4. Navigate to the location you installed Archipelago to. Open data/lua/FF1/ff1_connector.lua
|
4. Navigate to the location you installed Archipelago to. Open data/lua/connector_ff1.lua
|
||||||
1. If it gives a `NLua.Exceptions.LuaScriptException: .\socket.lua:13: module 'socket.core' not found:` exception
|
1. If it gives a `NLua.Exceptions.LuaScriptException: .\socket.lua:13: module 'socket.core' not found:` exception
|
||||||
close your emulator entirely, restart it and re-run these steps
|
close your emulator entirely, restart it and re-run these steps
|
||||||
2. If it says `Must use a version of bizhawk 2.3.1 or higher`, double-check your Bizhawk version by clicking **
|
2. If it says `Must use a version of bizhawk 2.3.1 or higher`, double-check your Bizhawk version by clicking **
|
||||||
|
|
|
@ -414,7 +414,7 @@ to the emulator as recommended).
|
||||||
Once both the client and the emulator are started, you must connect them. Within the emulator click on the "Tools"
|
Once both the client and the emulator are started, you must connect them. Within the emulator click on the "Tools"
|
||||||
menu and select "Lua Console". Click the folder button or press Ctrl+O to open a Lua script.
|
menu and select "Lua Console". Click the folder button or press Ctrl+O to open a Lua script.
|
||||||
|
|
||||||
Navigate to your Archipelago install folder and open `data/lua/OOT/oot_connector.lua`.
|
Navigate to your Archipelago install folder and open `data/lua/connector_oot.lua`.
|
||||||
|
|
||||||
To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
|
To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
|
||||||
server uses password, type in the bottom textfield `/connect <address>:<port> [password]`)
|
server uses password, type in the bottom textfield `/connect <address>:<port> [password]`)
|
||||||
|
|
|
@ -414,9 +414,9 @@ Double-cliquez sur votre fichier `.apz5` pour démarrer votre client et démarre
|
||||||
Une fois le client et l'émulateur démarrés, vous devez les connecter. Dans l'émulateur, cliquez sur "Outils"
|
Une fois le client et l'émulateur démarrés, vous devez les connecter. Dans l'émulateur, cliquez sur "Outils"
|
||||||
menu et sélectionnez "Console Lua". Cliquez sur le bouton du dossier ou appuyez sur Ctrl+O pour ouvrir un script Lua.
|
menu et sélectionnez "Console Lua". Cliquez sur le bouton du dossier ou appuyez sur Ctrl+O pour ouvrir un script Lua.
|
||||||
|
|
||||||
Accédez à votre dossier d'installation Archipelago et ouvrez `data/lua/OOT/oot_connector.lua`.
|
Accédez à votre dossier d'installation Archipelago et ouvrez `data/lua/connector_oot.lua`.
|
||||||
|
|
||||||
Pour connecter le client au multiserveur, mettez simplement `<adresse>:<port>` dans le champ de texte en haut et appuyez sur Entrée (si le
|
Pour connecter le client au multiserveur, mettez simplement `<adresse>:<port>` dans le champ de texte en haut et appuyez sur Entrée (si le
|
||||||
le serveur utilise un mot de passe, saisissez dans le champ de texte inférieur `/connect <adresse>:<port> [mot de passe]`)
|
le serveur utilise un mot de passe, saisissez dans le champ de texte inférieur `/connect <adresse>:<port> [mot de passe]`)
|
||||||
|
|
||||||
Vous êtes maintenant prêt à commencer votre aventure à Hyrule.
|
Vous êtes maintenant prêt à commencer votre aventure à Hyrule.
|
||||||
|
|
|
@ -86,7 +86,7 @@ to the emulator as recommended).
|
||||||
Once both the client and the emulator are started, you must connect them. Within the emulator click on the "Tools"
|
Once both the client and the emulator are started, you must connect them. Within the emulator click on the "Tools"
|
||||||
menu and select "Lua Console". Click the folder button or press Ctrl+O to open a Lua script.
|
menu and select "Lua Console". Click the folder button or press Ctrl+O to open a Lua script.
|
||||||
|
|
||||||
Navigate to your Archipelago install folder and open `data/lua/PKMN_RB/pkmr_rb.lua`.
|
Navigate to your Archipelago install folder and open `data/lua/connector_pkmn_rb.lua`.
|
||||||
|
|
||||||
To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
|
To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
|
||||||
server uses password, type in the bottom textfield `/connect <address>:<port> [password]`)
|
server uses password, type in the bottom textfield `/connect <address>:<port> [password]`)
|
||||||
|
|
|
@ -80,7 +80,7 @@ Once the Archipelago server has been hosted:
|
||||||
extension `*.nes`.
|
extension `*.nes`.
|
||||||
2. Click on the Tools menu and click on **Lua Console**.
|
2. Click on the Tools menu and click on **Lua Console**.
|
||||||
3. Click the folder button to open a new Lua script. (CTL-O or **Script** -> **Open Script**)
|
3. Click the folder button to open a new Lua script. (CTL-O or **Script** -> **Open Script**)
|
||||||
4. Navigate to the location you installed Archipelago to. Open `data/lua/TLOZ/tloz_connector.lua`.
|
4. Navigate to the location you installed Archipelago to. Open `data/lua/connector_tloz.lua`.
|
||||||
1. If it gives a `NLua.Exceptions.LuaScriptException: .\socket.lua:13: module 'socket.core' not found:` exception
|
1. If it gives a `NLua.Exceptions.LuaScriptException: .\socket.lua:13: module 'socket.core' not found:` exception
|
||||||
close your emulator entirely, restart it and re-run these steps.
|
close your emulator entirely, restart it and re-run these steps.
|
||||||
2. If it says `Must use a version of bizhawk 2.3.1 or higher`, double-check your Bizhawk version by clicking **
|
2. If it says `Must use a version of bizhawk 2.3.1 or higher`, double-check your Bizhawk version by clicking **
|
||||||
|
|
Loading…
Reference in New Issue