client: Packet handling in Lua; extensions/cereal

This commit is contained in:
Perttu Ahola 2014-09-19 21:45:44 +03:00
parent e41f7ad8b8
commit 0c7d5602bb
7 changed files with 147 additions and 22 deletions

View File

@ -1,18 +1,25 @@
local log = buildat.Logger("__client/packet")
__buildat_packet_subs = {}
local packet_subs = {}
function buildat:sub_packet(name, cb)
__buildat_packet_subs[name] = cb
function __buildat_handle_packet(name, data)
local cb = packet_subs[name]
if cb then
cb(data)
end
end
function buildat:unsub_packet(cb)
function buildat.sub_packet(name, cb)
packet_subs[name] = cb
end
function buildat.unsub_packet(cb)
for name, cb1 in pairs(buildat.packet_subs) do
if cb1 == cb then
__buildat_packet_subs[cb] = nil
packet_subs[cb] = nil
end
end
end
function buildat:send_packet(name, data)
function buildat.send_packet(name, data)
__buildat_send_packet(name, data)
end

View File

@ -0,0 +1,11 @@
-- Buildat: extension/cereal/init.lua
local polybox = require("buildat/extension/polycode_sandbox")
local log = buildat.Logger("extension/cereal")
local M = {safe = {}}
function M.safe.binary_input(data, types)
return __buildat_cereal_binary_input(data, types)
end
return M

View File

@ -12,6 +12,8 @@
#include <OSBasics.h>
#pragma GCC diagnostic pop
#include <c55/getopt.h>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/types/string.hpp>
#include <core/log.h>
#include <signal.h>
#define MODULE "__main"
@ -283,6 +285,7 @@ struct CApp: public Polycode::EventHandler, public App
DEF_BUILDAT_FUNC(get_file_path)
DEF_BUILDAT_FUNC(get_path)
DEF_BUILDAT_FUNC(pcall)
DEF_BUILDAT_FUNC(cereal_binary_input)
ss_ init_lua_path = g_client_config.share_path+"/client/init.lua";
int error = luaL_dofile(L, init_lua_path.c_str());
@ -332,6 +335,16 @@ struct CApp: public Polycode::EventHandler, public App
}
}
void handle_packet(const ss_ &name, const ss_ &data)
{
log_v(MODULE, "handle_packet(): %s", cs(name));
lua_getfield(L, LUA_GLOBALSINDEX, "__buildat_handle_packet");
lua_pushlstring(L, name.c_str(), name.size());
lua_pushlstring(L, data.c_str(), data.size());
lua_call(L, 2, 0);
}
// Non-public methods
// send_packet(name: string, data: string)
@ -474,6 +487,66 @@ struct CApp: public Polycode::EventHandler, public App
lua_pushvalue(L, error_stack_i);
return 2;
}
// cereal_binary_input(data: string, types: table of strings)
// -> table of values
static int l_cereal_binary_input(lua_State *L)
{
size_t data_len = 0;
const char *data_c = lua_tolstring(L, 1, &data_len);
ss_ data(data_c, data_len);
int types_table_L = 2;
lua_newtable(L);
int result_table_L = lua_gettop(L);
std::istringstream is(data, std::ios::binary);
{
cereal::PortableBinaryInputArchive ar(is);
int output_index = 1;
lua_pushnil(L);
while(lua_next(L, types_table_L) != 0)
{
ss_ type = lua_tostring(L, -1);
lua_pop(L, 1);
log_t(MODULE, "type=%s", cs(type));
if(type == "byte"){
uchar b;
ar(b);
lua_pushinteger(L, b);
lua_rawseti(L, result_table_L, output_index++);
continue;
}
if(type == "int32"){
int32_t i;
ar(i);
lua_pushinteger(L, i);
lua_rawseti(L, result_table_L, output_index++);
continue;
}
if(type == "double"){
double d;
ar(d);
lua_pushnumber(L, d);
lua_rawseti(L, result_table_L, output_index++);
continue;
}
if(type == "string"){
ss_ s;
ar(s);
lua_pushlstring(L, s.c_str(), s.size());
lua_rawseti(L, result_table_L, output_index++);
continue;
}
throw Exception(ss_()+"Unknown type \""+type+"\""
"; known types are byte, int32, double, string");
}
}
// Result table is on top of stack
return 1;
}
};
App* createApp(Polycode::PolycodeView *view)

View File

@ -19,6 +19,7 @@ namespace app
virtual bool update() = 0;
virtual void shutdown() = 0;
virtual void run_script(const ss_ &script) = 0;
virtual void handle_packet(const ss_ &name, const ss_ &data) = 0;
};
App* createApp(Polycode::PolycodeView *view);

View File

@ -133,6 +133,11 @@ struct CState: public State
void handle_packet(const ss_ &packet_name, const ss_ &data)
{
if(packet_name.substr(0,5) != "core:"){
m_app->handle_packet(packet_name, data);
return;
}
if(packet_name == "core:run_script"){
log_i(MODULE, "Asked to run script:\n----\n%s\n----", cs(data));
if(m_app)

View File

@ -1,17 +1,9 @@
-- Buildat: test1/client_lua/init.lua
local log = buildat.Logger("test1")
local dump = buildat.dump
log:info("test1/init.lua loaded")
--[[
-- Temporary test
require "Polycode/Core"
scene = Scene(Scene.SCENE_2D)
scene:getActiveCamera():setOrthoSize(640, 480)
label = SceneLabel("Hello from remote module!", 32)
label:setPosition(0, -100, 0)
scene:addChild(label)
--]]
-- Test extension interface safety
local test = require("buildat/extension/test")
test.f()
@ -24,10 +16,35 @@ ground = g3d.ScenePrimitive(g3d.ScenePrimitive.TYPE_PLANE, 5,5)
ground:loadTexture("test1/green_texture.png")
scene:addEntity(ground)
box = g3d.ScenePrimitive(g3d.ScenePrimitive.TYPE_BOX, 1,1,1)
box:loadTexture("test1/pink_texture.png")
box:setPosition(0.0, 0.5, 0.0)
scene:addEntity(box)
scene:getDefaultCamera():setPosition(7,7,7)
scene:getDefaultCamera():lookAt(g3d.Vector3(0,0,0), g3d.Vector3(0,1,0))
local cereal = require("buildat/extension/cereal")
buildat.sub_packet("test1:add_box", function(data)
values = cereal.binary_input(data, {
"double", "double", "double",
"double", "double", "double"
})
local w = values[1]
local h = values[2]
local d = values[3]
local x = values[4]
local y = values[5]
local z = values[6]
log:info("values="..dump(values))
box = g3d.ScenePrimitive(g3d.ScenePrimitive.TYPE_BOX, w,h,d)
box:loadTexture("test1/pink_texture.png")
box:setPosition(x, y, z)
scene:addEntity(box)
end)
--[[
-- Temporary test
require "Polycode/Core"
scene = Scene(Scene.SCENE_2D)
scene:getActiveCamera():setOrthoSize(640, 480)
label = SceneLabel("Hello from remote module!", 32)
label:setPosition(0, -100, 0)
scene:addChild(label)
--]]

View File

@ -2,10 +2,10 @@
#include "interface/server.h"
#include "interface/event.h"
#include "test1/api.h"
//#include "client_lua/api.h"
#include "client_file/api.h"
#include "network/api.h"
#include "core/log.h"
#include <cereal/archives/portable_binary.hpp>
using interface::Event;
@ -71,10 +71,21 @@ struct Module: public interface::Module
void on_files_transmitted(const client_file::FilesTransmitted &event)
{
log_v(MODULE, "on_files_transmitted(): recipient=%zu", event.recipient);
network::access(m_server, [&](network::Interface * inetwork){
inetwork->send(event.recipient, "core:run_script",
"buildat:run_script_file(\"test1/init.lua\")");
});
network::access(m_server, [&](network::Interface * inetwork){
std::ostringstream os(std::ios::binary);
{
cereal::PortableBinaryOutputArchive ar(os);
ar(1.0, 1.0, 1.0);
ar(0.0, 0.5, 0.0);
}
inetwork->send(event.recipient, "test1:add_box", os.str());
});
}
void on_packet_received(const network::Packet &packet)