From 6aa85e359c20689ebd15f6ebc3ce0340bdcdedfc Mon Sep 17 00:00:00 2001 From: "Ben Russell (300178622)" Date: Sat, 14 Feb 2015 12:26:47 +1300 Subject: [PATCH] sandbox API, hopefully i didn't break anything --- pkg/base/lib_fastload.lua | 3 + pkg/base/main_client.lua | 7 + pkg/base/main_server.lua | 6 + pkg/base/network.lua | 6 + pkg/base/preconf.lua | 1 + pkg/base/sandbox/fetch.lua | 150 +++++++++++++++++++ pkg/base/sandbox/gfx.lua | 175 ++++++++++++++++++++++ pkg/base/sandbox/main.lua | 282 +++++++++++++++++++++++++++++++++++ pkg/base/sandbox/wav.lua | 87 +++++++++++ pkg/br/snake/mod.json | 3 + pkg/br/snake/mod_sandbox.lua | 52 +++++++ 11 files changed, 772 insertions(+) create mode 100644 pkg/base/sandbox/fetch.lua create mode 100644 pkg/base/sandbox/gfx.lua create mode 100644 pkg/base/sandbox/main.lua create mode 100644 pkg/base/sandbox/wav.lua create mode 100644 pkg/br/snake/mod.json create mode 100644 pkg/br/snake/mod_sandbox.lua diff --git a/pkg/base/lib_fastload.lua b/pkg/base/lib_fastload.lua index 6099019..82e4d12 100644 --- a/pkg/base/lib_fastload.lua +++ b/pkg/base/lib_fastload.lua @@ -135,6 +135,9 @@ function fastload_analyse_client() state.e.pcall = pcall state.e.pairs = pairs state.e.ipairs = ipairs + + -- Tell it there's a sandbox + state.e.sandbox = {} -- client.wav_play_local/global function state.e.client.wav_play_local(...) return 1 end diff --git a/pkg/base/main_client.lua b/pkg/base/main_client.lua index 77afa4e..8538b32 100644 --- a/pkg/base/main_client.lua +++ b/pkg/base/main_client.lua @@ -15,10 +15,16 @@ along with Ice Lua Components. If not, see . ]] +SANDBOX_CLIENT = true + if common.version.num < 8388608 then error("You need Iceball version 0.2 or later to connect to this server.") end +if SANDBOX_CLIENT and not sandbox then + return (loadfile("pkg/base/sandbox/main.lua"))(...) +end + if common.mk_compat_disable then common.mk_compat_disable() client.mk_set_title("Iceball") @@ -155,6 +161,7 @@ do local last_keepalive = common.time() function load_screen_fetch(ftype, fname) if string.sub(fname, 1,6) == "clsave" then return client.fetch_block(ftype, fname) end + --if true then return client.fetch_block(ftype, fname) end if widgets ~= nil then scene = gui_create_scene(w, h) img_loading_width, img_loading_height = client.img_get_dims(img_loading) diff --git a/pkg/base/main_server.lua b/pkg/base/main_server.lua index 1d76a76..a8e1ba9 100644 --- a/pkg/base/main_server.lua +++ b/pkg/base/main_server.lua @@ -15,10 +15,16 @@ along with Ice Lua Components. If not, see . ]] +SANDBOX_SERVER = false + if common.version.num < 8388608 then error("You need Iceball version 0.2 or later to run this code.") end +if SANDBOX_SERVER and not sandbox then + return (loadfile("pkg/base/sandbox/main.lua"))(...) +end + dofile("pkg/base/lib_fastload.lua") -- UDP port test. diff --git a/pkg/base/network.lua b/pkg/base/network.lua index 59fcb63..2860196 100644 --- a/pkg/base/network.lua +++ b/pkg/base/network.lua @@ -588,6 +588,12 @@ network.sys_handle_c2s(PKT_PLR_OFFER, "bbz", nwdec_plrset(function (neth, cli, p plr.wpn = weapons[wpn](plr) if plr.team ~= tidx then plr.set_health_damage(0, 0xFF800000, plr.name.." changed teams", nil) + if not teams[tidx] then + print("HACK ATTEMPT from neth "..tostring(neth)) + server.net_kick(neth, "Hack attempt") + return + end + print(plr, tidx, teams[tidx]) net_broadcast(nil, common.net_pack("BIz", PKT_CHAT_ADD_TEXT, 0xFF800000, "* Player "..plr.name.." has joined the "..teams[tidx].name.." team")) elseif plr.weapon ~= wpn then diff --git a/pkg/base/preconf.lua b/pkg/base/preconf.lua index a732bcd..b182c8b 100644 --- a/pkg/base/preconf.lua +++ b/pkg/base/preconf.lua @@ -20,6 +20,7 @@ MODE_NUB_KICKONJOIN = false -- skins allowed SKIN_ENABLE_SRC = {"pmf", "kv6", "tga", "png", "wav", "it"} +--SKIN_ENABLE_SRC = {} SKIN_ENABLE = {} do local i diff --git a/pkg/base/sandbox/fetch.lua b/pkg/base/sandbox/fetch.lua new file mode 100644 index 0000000..df580ef --- /dev/null +++ b/pkg/base/sandbox/fetch.lua @@ -0,0 +1,150 @@ +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +-- Wrappers for fetching stuff. + +do + +return function(sb_list, sb_aux, sb_ctl, name) + local SG = sb_list[name] + + -- Set up function wrapper + local function wrapfn(f) + setfenv(f, SG) + end + + local s_fetch_start = common.fetch_start + local s_fetch_poll = common.fetch_poll + local s_fetch_block = common.fetch_block + + local fetch_last_ftype = nil + local fetch_last_fname = nil + function SG.common.fetch_start(ftype, fname) + local obj = s_fetch_start(ftype, fname) + + if obj ~= true and obj ~= nil then + if ftype == "lua" and obj ~= nil then + wrapfn(obj) + end + end + + fetch_last_ftype = nil + fetch_last_fname = nil + if obj == true then + fetch_last_ftype = ftype + fetch_last_fname = fname + end + + return obj + end + + function SG.common.fetch_poll() + local oldmap = common.map_get() + sb_ctl.gfx_api_prerender() + + local function ff(obj, ...) + if obj ~= false then + if fetch_last_ftype == "lua" and obj ~= nil then + wrapfn(obj) + end + + fetch_last_ftype = nil + fetch_last_fname = nil + end + + sb_ctl.gfx_api_postrender(name) + + return obj, ... + end + + return ff(s_fetch_poll()) + end + + function SG.common.fetch_block(ftype, fname) + local fetch_start = common.fetch_start + local fetch_poll = common.fetch_poll + common.fetch_start = SG.common.fetch_start + common.fetch_poll = SG.common.fetch_poll + + --print("BLOCK", ftype, fname) + local obj = s_fetch_block(ftype, fname) + if ftype == "lua" and obj ~= nil then + wrapfn(obj) + end + --print("BLOCK END", ftype, fname, obj) + + common.fetch_start = fetch_start + common.fetch_poll = fetch_poll + + return obj + end + + function SG.loadstring(...) + local f = loadstring(...) + wrapfn(f) + return f + end + + function SG.loadfile(...) + return SG.common.fetch_block("lua", ...) + end + + function SG.dofile(...) + return SG.loadfile(...)() + end + + -- mirrors + if client then + SG.client.fetch_block = SG.common.fetch_block + SG.client.fetch_start = SG.common.fetch_start + SG.client.fetch_poll = SG.common.fetch_poll + end + + if server then + SG.server.fetch_block = SG.common.fetch_block + SG.server.fetch_start = SG.common.fetch_start + SG.server.fetch_poll = SG.common.fetch_poll + end + + -- other things that are basically fetch_block + function SG.common.bin_load(...) return SG.common.fetch_block("bin", ...) end + function SG.common.json_load(...) return SG.common.fetch_block("json", ...) end + function SG.common.wav_load(...) return SG.common.fetch_block("wav", ...) end + function SG.common.mus_load_it(...) return SG.common.fetch_block("it", ...) end + function SG.common.model_load_pmf(...) return SG.common.fetch_block("pmf", ...) end + function SG.common.map_load(fname, fmt) + if fmt == nil or fmt == "auto" then + fmt = "map" + end + return SG.common.fetch_block(fmt, fname) + end + function SG.common.img_load(fname, fmt) + print("IMG!", fmt, fname) + local img = SG.common.fetch_block(fmt or "tga", fname) + print("IMG!", img) + if not img then return nil, nil, nil end + return img, common.img_get_dims(img) + end + + -- more aliases + if client then + SG.client.img_load = SG.common.img_load + end +end + +end + diff --git a/pkg/base/sandbox/gfx.lua b/pkg/base/sandbox/gfx.lua new file mode 100644 index 0000000..e126e26 --- /dev/null +++ b/pkg/base/sandbox/gfx.lua @@ -0,0 +1,175 @@ + +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +-- Wrappers for graphical stuff. Also handles input. + +do + +local sb_list, sb_aux, sb_ctl = ... +sb_ctl.gfx_select = "root" +sb_ctl.gfx_map_stack = {idx = 0} + +-- Select sandbox to use for graphics and input. +function sandbox.gfx_select(name) + if not sb_list[name] then + error("invalid VM \""..tostring(name).."\" for gfx_select") + end + + sb_ctl.gfx_select = name + + client.mouse_lock_set(sb_aux[name].gfx_mouse_grab) + client.mouse_visible_set(sb_aux[name].gfx_mouse_vis) + local l = sb_aux[name].gfx_map_fog + client.map_fog_set(l[1], l[2], l[3], l[4]) +end + +-- INTERNAL API: Begin / end of hooks +function sb_ctl.gfx_api_push(name) + local map = nil + if sb_aux[name] then + map = sb_aux[name].gfx_map + end + + sb_ctl.gfx_map_stack.idx = sb_ctl.gfx_map_stack.idx + 1 + sb_ctl.gfx_map_stack[sb_ctl.gfx_map_stack.idx] = {name, common.map_get()} + common.map_set(map) +end +function sb_ctl.gfx_api_pop() + local name = sb_ctl.gfx_map_stack[sb_ctl.gfx_map_stack.idx][1] + if sb_aux[name] then + sb_aux[name].gfx_map = common.map_get() + end + common.map_set(sb_ctl.gfx_map_stack[sb_ctl.gfx_map_stack.idx][2]) + sb_ctl.gfx_map_stack[sb_ctl.gfx_map_stack.idx] = nil + sb_ctl.gfx_map_stack.idx = sb_ctl.gfx_map_stack.idx - 1 +end +function sb_ctl.gfx_api_prerender() + local map = nil + if sb_aux[sb_ctl.gfx_select] then + map = sb_aux[sb_ctl.gfx_select].gfx_map + end + common.map_set(map) +end +function sb_ctl.gfx_api_postrender(name) + local map = nil + if sb_aux[name] then + map = sb_aux[name].gfx_map + end + common.map_set(map) +end + +function sb_ctl.gfx_kill(name) + if name == sb_ctl.gfx_select then + -- TODO: properly return to parent + if name ~= "root" then + sandbox.gfx_select("root") + end + end +end + +return function(sb_list, sb_aux, sb_ctl, name) + local SG = sb_list[name] + + sb_aux[name].gfx_mouse_vis = true + sb_aux[name].gfx_mouse_grab = false + sb_aux[name].gfx_map_fog = {208, 224, 255, 60.0} + sb_aux[name].gfx_map = map + + if client then + local s_img_blit = SG.client.img_blit + function SG.client.img_blit(...) + if sb_ctl.gfx_select == name then + return s_img_blit(...) + end + end + + local s_va_render_global = SG.client.va_render_global + function SG.client.va_render_global(...) + if sb_ctl.gfx_select == name then + return s_va_render_global(...) + end + end + + local s_va_render_local = SG.client.va_render_local + function SG.client.va_render_local(...) + if sb_ctl.gfx_select == name then + return s_va_render_local(...) + end + end + + local s_model_render_bone_global = SG.client.model_render_bone_global + function SG.client.model_render_bone_global(...) + if sb_ctl.gfx_select == name then + return s_model_render_bone_global(...) + end + end + + local s_model_render_bone_local = SG.client.model_render_bone_local + function SG.client.model_render_bone_local(...) + if sb_ctl.gfx_select == name then + return s_model_render_bone_local(...) + end + end + + local s_mouse_lock_set = SG.client.mouse_lock_set + function SG.client.mouse_lock_set(state) + sb_aux[name].gfx_mouse_grab = state + if sb_ctl.gfx_select == name then + return s_mouse_lock_set(state) + end + end + + local s_mouse_visible_set = SG.client.mouse_visible_set + function SG.client.mouse_visible_set(state) + sb_aux[name].gfx_mouse_vis = state + if sb_ctl.gfx_select == name then + return s_mouse_visible_set(state) + end + end + + local s_map_set = SG.common.map_set + function SG.common.map_set(map) + print("map", name, map) + sb_aux[name].gfx_map = map + return s_map_set(map) + end + SG.client.map_set = SG.common.map_set + + local s_map_fog_set = SG.client.map_fog_set + function SG.client.map_fog_set(r, g, b, dist) + sb_aux[name].gfx_map_fog = {r, g, b, dist} + if sb_ctl.gfx_select == name then + return s_map_fog_set(r, g, b, dist) + end + end + + local s_map_fog_get = SG.client.map_fog_get + function SG.client.map_fog_get() + if sb_ctl.gfx_select == name then + return s_map_fog_get() + else + local l = sb_aux[name].gfx_map_fog + return l[1], l[2], l[3], l[4] + end + end + end + +end + +end + diff --git a/pkg/base/sandbox/main.lua b/pkg/base/sandbox/main.lua new file mode 100644 index 0000000..fb62e85 --- /dev/null +++ b/pkg/base/sandbox/main.lua @@ -0,0 +1,282 @@ +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +-- Simple, not necessarily secure sandbox. +-- More like a VM. +sandbox = {} + +do + +local sb_counter = 1 +local sb_list = {} +local sb_aux = {} +local sb_ctl = {} +local sb_current = "" + +local sb_wrap_fetch = loadfile("pkg/base/sandbox/fetch.lua")(sb_list, sb_aux, sb_ctl) +local sb_wrap_audio = loadfile("pkg/base/sandbox/wav.lua")(sb_list, sb_aux, sb_ctl) +local sb_wrap_gfx = loadfile("pkg/base/sandbox/gfx.lua")(sb_list, sb_aux, sb_ctl) + +local function table_dup(S) + if S == nil then return nil end + + local D = {} + local k, v + + for k, v in pairs(S) do + if type(v) == "table" then + D[k] = table_dup(v) + else + D[k] = v + end + end + + return D +end + +-- Creates a new sandbox with a given name. +-- Returns actual name in case of collision. +function sandbox.new(name, fname, ...) + -- Pick a name + if sb_list[name] then + while sb_list[name.."-"..sb_counter] do + sb_counter = sb_counter + 1 + end + + name = name.."-"..sb_counter + sb_counter = sb_counter + 1 + end + + print("Creating sandbox \""..name.."\"") + + -- Create new environment + local SG = {} + SG._G = SG + sb_list[name] = SG + sb_aux[name] = {} + + sb_aux[name].tick_enabled = true + + -- Copy some builtins + SG.string = string + SG.math = math + SG.table = table + + SG.assert = assert + SG.collectgarbage = collectgarbage + SG.error = error + SG.getfenv = getfenv + SG.getmetatable = getmetatable + SG.ipairs = ipairs + SG.next = next + SG.pairs = pairs + SG.pcall = pcall + SG.print = print + SG.rawequal = rawequal + SG.rawget = rawget + SG.rawset = rawset + SG.select = select + SG.setfenv = setfenv + SG.setmetatable = setmetatable + SG.tonumber = tonumber + SG.tostring = tostring + SG.type = type + SG.unpack = unpack + SG._VERSION = _VERSION + SG.xpcall = xpcall + + -- Copy main things + setfenv(table_dup, _G) + SG.client = table_dup(client) + SG.common = table_dup(common) + SG.server = table_dup(server) + SG.sandbox = table_dup(sandbox) + + -- Remove hooks + local k,v + local clsv = (SG.client or SG.server) + for k,v in pairs(clsv) do + if k:sub(1,5) == "hook_" then + clsv[k] = nil + end + end + + -- Enable wrappers + sb_wrap_fetch(sb_list, sb_aux, sb_ctl, name) + sb_wrap_audio(sb_list, sb_aux, sb_ctl, name) + sb_wrap_gfx(sb_list, sb_aux, sb_ctl, name) + + -- Do file + -- Return name + return name, (SG.loadfile(fname))(...) +end + +-- Kills a sandbox. +function sandbox.kill(name) + if not sb_list[name] then + error("nonexistant sandbox \""..tostring(name).."\"") + end + + if client then + sb_ctl.gfx_kill(name) + end + + sb_list[name] = nil + sb_aux[name] = nil +end + +if client then + function client.hook_tick(...) + local k, v + local hadf = false + local retacc = 1 + local kill_list = {} + for k, v in pairs(sb_list) do + if sb_aux[k].tick_enabled then + local f = v.client.hook_tick + if f then + hadf = true + sb_ctl.gfx_api_push(k) + retacc = math.min(retacc, f(...)) + sb_ctl.gfx_api_pop() + else + kill_list[1+#kill_list] = k + end + end + end + + for k, v in pairs(kill_list) do + print("Killing sandbox \""..tostring(v).."\"") + sandbox.kill(v) + end + + if not hadf then + client.hook_tick = nil + end + sb_ctl.gfx_api_prerender() + end + + function client.hook_key(...) + if not sb_list[sb_ctl.gfx_select] then return end + local f = sb_list[sb_ctl.gfx_select].client.hook_key + if f then + sb_ctl.gfx_api_push(sb_ctl.gfx_select) + f(...) + sb_ctl.gfx_api_pop() + end + sb_ctl.gfx_api_prerender() + end + + function client.hook_mouse_button(...) + if not sb_list[sb_ctl.gfx_select] then return end + local f = sb_list[sb_ctl.gfx_select].client.hook_mouse_button + if f then + sb_ctl.gfx_api_push(sb_ctl.gfx_select) + f(...) + sb_ctl.gfx_api_pop() + end + sb_ctl.gfx_api_prerender() + end + + function client.hook_mouse_motion(...) + if not sb_list[sb_ctl.gfx_select] then return end + local f = sb_list[sb_ctl.gfx_select].client.hook_mouse_motion + if f then + sb_ctl.gfx_api_push(sb_ctl.gfx_select) + f(...) + sb_ctl.gfx_api_pop() + end + sb_ctl.gfx_api_prerender() + end + + function client.hook_render(...) + if not sb_list[sb_ctl.gfx_select] then return end + local f = sb_list[sb_ctl.gfx_select].client.hook_render + + if f then + sb_ctl.gfx_api_push(sb_ctl.gfx_select) + f(...) + sb_ctl.gfx_api_pop() + end + sb_ctl.gfx_api_prerender() + end + + function client.hook_kick(...) + local k, v + for k, v in pairs(sb_list) do + local f = v.client.hook_kick + if f then + f(...) + end + end + end + +elseif server then + function server.hook_tick(...) + local k, v + local hadf = false + local retacc = 1 + for k, v in pairs(sb_list) do + if sb_aux[k].tick_enabled then + local f = v.server.hook_tick + if f then + hadf = true + retacc = math.min(retacc, f(...)) + end + end + end + + if not hadf then + server.hook_tick = nil + end + end + + function server.hook_file(...) + local f = sb_list[sb_current].server.hook_file + if f then + return f(...) + end + end + + function server.hook_connect(...) + local f = sb_list[sb_current].server.hook_connect + if f then + return f(...) + end + end + + function server.hook_disconnect(...) + local f = sb_list[sb_current].server.hook_disconnect + if f then + return f(...) + end + end +end + +sb_current = "root" -- TO BE PHASED OUT + +end + +-- Do initial sandbox +if client then + sandbox.new("root", "pkg/base/main_client.lua", ...) +elseif server then + sandbox.new("root", "pkg/base/main_server.lua", ...) +else + error("Cannot determine if client or server!") +end + diff --git a/pkg/base/sandbox/wav.lua b/pkg/base/sandbox/wav.lua new file mode 100644 index 0000000..a6059a4 --- /dev/null +++ b/pkg/base/sandbox/wav.lua @@ -0,0 +1,87 @@ +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +-- Wrappers for the audio system. + +do + +return function (sb_list, sb_aux, sb_ctl, name) + local SG = sb_list[name] + + sb_aux[name].mus_ref = nil + sb_aux[name].mus_order = 0 + sb_aux[name].mus_row = 0 + sb_aux[name].mus_vol = 1.0 + sb_aux[name].wav_enabled = true --(name == "root") + sb_aux[name].wav_cube_size = 1.0 + + if client then + function SG.client.wav_cube_size(size) + sb_aux[name].wav_cube_size = size + if sb_aux[name].wav_enabled then + return client.wav_cube_size(size) + end + end + + function SG.client.wav_play_global(...) + if sb_aux[name].wav_enabled then + return client.wav_play_global(...) + end + + return nil + end + + function SG.client.wav_play_local(...) + if sb_aux[name].wav_enabled then + return client.wav_play_local(...) + end + + return nil + end + + function SG.client.mus_play(mus, order, row) + order = order or 0 + row = row or 0 + + sb_aux[name].mus_ref = mus + sb_aux[name].mus_order = order + sb_aux[name].mus_row = row + if sb_aux[name].wav_enabled then + return client.mus_play(mus, order, row) + end + end + + function SG.client.mus_stop() + sb_aux[name].mus_ref = nil + sb_aux[name].mus_order = 0 + sb_aux[name].mus_row = 0 + if sb_aux[name].wav_enabled then + return client.mus_stop() + end + end + + function SG.client.mus_vol_set(vol) + sb_aux[name].mus_vol = vol + if sb_aux[name].wav_enabled then + return client.mus_vol_set(vol) + end + end + end +end + +end + diff --git a/pkg/br/snake/mod.json b/pkg/br/snake/mod.json new file mode 100644 index 0000000..cceba11 --- /dev/null +++ b/pkg/br/snake/mod.json @@ -0,0 +1,3 @@ +{ + "load_client": ["mod_sandbox.lua"] +} diff --git a/pkg/br/snake/mod_sandbox.lua b/pkg/br/snake/mod_sandbox.lua new file mode 100644 index 0000000..8b2f0cc --- /dev/null +++ b/pkg/br/snake/mod_sandbox.lua @@ -0,0 +1,52 @@ +--[[ + This file is part of Ice Lua Components. + + Ice Lua Components is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Ice Lua Components is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Ice Lua Components. If not, see . +]] + +-- Simple test of the sandbox API. + +local super = new_player +function new_player(...) + local this = super(...) + + local s_create_hud = this.create_hud + local function f_create_hud(...) + local ret = s_create_hud(...) + + local s_chat_on_return = this.typing_text.on_return + function this.typing_text.on_return(...) + if this.typing_text.text == "/snake" then + local snake = sandbox.new("snake", "pkg/br/snake/main_client.lua") + sandbox.gfx_select(snake) + this.typing_text.text = "" + end + + return s_chat_on_return(...) + end + end + + function this.create_hud(...) + local ret = s_create_hud(...) + f_create_hud(...) + return ret + end + + if this.scene then + f_create_hud(...) + end + + return this +end +