Created
September 1, 2013 22:26
-
-
Save ColonelThirtyTwo/6407729 to your computer and use it in GitHub Desktop.
Library for calling E2 functions from Starfall. Hasn't been tested in awhile, and since it requires mocking the E2 entity, may not work with all functions.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
------------------------------------------------------------------------------- | |
-- Expression 2 Foreign Functions Interface Library | |
------------------------------------------------------------------------------- | |
local functions_cache = setmetatable({},{__mode="v"}) | |
local function identity(v) return v end | |
local lua2e2_converters = { | |
["number"] = identity, | |
["string"] = identity, | |
["boolean"] = function(v) return v and 1 or 0 end, | |
["Vector"] = function(v) return {v[1], v[2], v[3]} end, | |
["Angle"] = function(v) return {v[1], v[2], v[3]} end, | |
["table"] = function(v) return SF.Entities.Unwrap(v) end, | |
["nil"] = identity, | |
} | |
local e22lua_converters = { | |
["n"] = identity, | |
["s"] = identity, | |
["v"] = function(v) return Vector(v[1], v[2], v[3]) end, | |
["a"] = function(v) return Angle(v[1], v[2], v[3]) end, | |
["e"] = function(v) return SF.Entities.Unwrap(v) end, | |
} | |
local lua2e2_types = { | |
["number"] = "n", | |
["string"] = "s", | |
["boolean"] = "n", | |
["Vector"] = "v", | |
["Angle"] = "a", | |
["table"] = "e", | |
["nil"] = "e", | |
} | |
local container_metatable = { | |
__call = function(self) return self.val end, | |
} | |
SF.Libraries.AddHook("initialize", function(instance) | |
local fakecontext = { | |
data = {}, | |
funcs = nil, | |
funcs_ret = nil, | |
entity = instance.data.entity, | |
player = instance.player, | |
uid = instance.player and instance.player:UniqueID(), | |
prf = 0, | |
prfcount = 0, | |
prfbench = 0, | |
includes = nil, | |
Scopes = {[0]={}}, | |
ScopeID = 0, | |
} | |
fakecontext.Scope = fakecontext.Scopes[0] | |
fakecontext.GlobalScope = fakecontext.Scope | |
instance.data.e2ffi_fakeContext = fakecontext | |
wire_expression2_CallHook("construct", fakecontext) | |
end) | |
SF.Libraries.AddHook("deinitialize", function(instance) | |
if instance.data.e2ffi_fakeContext then | |
wire_expression2_CallHook("destruct", instance.data.e2ffi_fakeContext) | |
end | |
end) | |
--- Extension library that allows the use of certain E2 functions in Starfall. | |
-- Only the following types are supported: number, string, entity, vector, and angle. | |
-- true and false are converted to 1 and 0 respectively, and nil is a null entity. Any other | |
-- types will cause an error. Vararg functions are not supported. | |
-- Using the wrappers is somewhat expensive, so don't make heavy use of them. | |
local e2ffi_library, _ = SF.Libraries.Register("e2ffi") | |
--- Creates a wrapper function around an E2 function or method. This converts between E2 and SF types. | |
-- @param header The function definition string. This starts with the function name and an open | |
-- parenthesis, then zero or more 1 character E2 type strings ('n', 's', etc.), followed by a closing | |
-- parenthesis. Ex. 'holoPos(nv)'. Methods are formed like functions, but have a semicolon in the | |
-- type string. Ex. 'applyForce(e:v)'. | |
function e2ffi_library.getFunction(header) | |
if functions_cache[header] then return functions_cache[header] end | |
local funcdef = wire_expression2_funcs[header] | |
if not funcdef then error("No such E2 function: "..header,2) end | |
local e2function = funcdef[3] | |
local retconverter = e22lua_converters[funcdef[2]] | |
local funcname, typestr = string.match(header, "^(%l%a*)%((%l?:?%l*)%)$") | |
assert(funcname) | |
local types = {} | |
local fakefunc = {e2function} | |
for i=1,#typestr do | |
local e2type = typestr:sub(i,i) | |
if e2type ~= ":" then | |
if not e22lua_converters[e2type] then error("Incompatible E2 type: "..e2type, 2) end | |
local j = #types+1 | |
types[j] = e2type | |
fakefunc[j+1] = {setmetatable({},container_metatable)} | |
end | |
end | |
local wrapped = function(...) | |
for i=1,#types do | |
local v = select(i,...) | |
local t = type(v) | |
if lua2e2_types[t] ~= types[i] then | |
error(string.format("Type mismatch for argument %n of e2function %s", i, header),2) | |
end | |
fakefunc[i+1][1].val = lua2e2_converters[t](v) | |
end | |
local v = e2function(SF.instance.data.e2ffi_fakeContext, fakefunc) | |
if retconverter then return retconverter(v) end | |
end | |
functions_cache[header] = wrapped | |
return wrapped | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment