lua: added object support reding property and console
Dieser Commit ist enthalten in:
Ursprung
853ab3f1e0
Commit
9722c03f8d
@ -50,6 +50,8 @@ class IdObject : public Object
|
||||
Property<std::string> id;
|
||||
|
||||
~IdObject() override;
|
||||
|
||||
const std::weak_ptr<World>& world() const { return m_world; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
75
server/src/lua/console.cpp
Normale Datei
75
server/src/lua/console.cpp
Normale Datei
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* server/src/lua/console.cpp - Lua console wrapper
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "console.hpp"
|
||||
#include "readonlytable.hpp"
|
||||
#include "sandbox.hpp"
|
||||
#include "script.hpp"
|
||||
#include "../core/traintastic.hpp"
|
||||
|
||||
namespace Lua {
|
||||
|
||||
void Console::push(lua_State* L)
|
||||
{
|
||||
lua_createtable(L, 0, 7);
|
||||
|
||||
lua_pushcfunction(L, debug);
|
||||
lua_setfield(L, -2, "debug");
|
||||
lua_pushcfunction(L, info);
|
||||
lua_setfield(L, -2, "info");
|
||||
lua_pushcfunction(L, notice);
|
||||
lua_setfield(L, -2, "notice");
|
||||
lua_pushcfunction(L, warning);
|
||||
lua_setfield(L, -2, "warning");
|
||||
lua_pushcfunction(L, error);
|
||||
lua_setfield(L, -2, "error");
|
||||
lua_pushcfunction(L, critical);
|
||||
lua_setfield(L, -2, "critical");
|
||||
lua_pushcfunction(L, fatal);
|
||||
lua_setfield(L, -2, "fatal");
|
||||
|
||||
ReadOnlyTable::setMetatable(L, -1);
|
||||
}
|
||||
|
||||
void Console::log(lua_State* L, ::Console::Level level, const std::string& message)
|
||||
{
|
||||
Traintastic::instance->console->log(level, Sandbox::getStateData(L).script().id, message);
|
||||
}
|
||||
|
||||
int Console::log(lua_State* L, ::Console::Level level)
|
||||
{
|
||||
const int top = lua_gettop(L);
|
||||
|
||||
std::string message;
|
||||
for(int i = 1; i <= top; i++)
|
||||
{
|
||||
if(i != 1)
|
||||
message += " ";
|
||||
message += luaL_checkstring(L, i);
|
||||
}
|
||||
|
||||
log(L, level, message);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
60
server/src/lua/console.hpp
Normale Datei
60
server/src/lua/console.hpp
Normale Datei
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* server/src/lua/console.hpp - Lua console wrapper
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef SERVER_LUA_CONSOLE_HPP
|
||||
#define SERVER_LUA_CONSOLE_HPP
|
||||
|
||||
#include <lua.hpp>
|
||||
#include "../core/console.hpp"
|
||||
|
||||
namespace Lua {
|
||||
|
||||
class Console
|
||||
{
|
||||
private:
|
||||
static int log(lua_State* L, ::Console::Level level);
|
||||
|
||||
static int debug(lua_State* L) { return log(L, ::Console::Level::Debug); }
|
||||
static int info(lua_State* L) { return log(L, ::Console::Level::Info); }
|
||||
static int notice(lua_State* L) { return log(L, ::Console::Level::Notice); }
|
||||
static int warning(lua_State* L) { return log(L, ::Console::Level::Warning); }
|
||||
static int error(lua_State* L) { return log(L, ::Console::Level::Error); }
|
||||
static int critical(lua_State* L) { return log(L, ::Console::Level::Critical); }
|
||||
static int fatal(lua_State* L) { return log(L, ::Console::Level::Fatal); }
|
||||
|
||||
public:
|
||||
static void push(lua_State* L);
|
||||
|
||||
static void log(lua_State* L, ::Console::Level level, const std::string& message);
|
||||
|
||||
inline static void debug(lua_State* L, const std::string& message) { return log(L, ::Console::Level::Debug, message); }
|
||||
inline static void info(lua_State* L, const std::string& message) { return log(L, ::Console::Level::Info, message); }
|
||||
inline static void notice(lua_State* L, const std::string& message) { return log(L, ::Console::Level::Info, message); }
|
||||
inline static void warning(lua_State* L, const std::string& message) { return log(L, ::Console::Level::Warning, message); }
|
||||
inline static void error(lua_State* L, const std::string& message) { return log(L, ::Console::Level::Error, message); }
|
||||
inline static void critical(lua_State* L, const std::string& message) { return log(L, ::Console::Level::Critical, message); }
|
||||
inline static void fatal(lua_State* L, const std::string& message) { return log(L, ::Console::Level::Fatal, message); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
134
server/src/lua/object.cpp
Normale Datei
134
server/src/lua/object.cpp
Normale Datei
@ -0,0 +1,134 @@
|
||||
/**
|
||||
* server/src/lua/object.cpp - Lua object wrapper
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "object.hpp"
|
||||
#include "push.hpp"
|
||||
#include "../core/object.hpp"
|
||||
#include "../core/abstractproperty.hpp"
|
||||
|
||||
namespace Lua {
|
||||
|
||||
ObjectPtr Object::check(lua_State* L, int index)
|
||||
{
|
||||
ObjectPtrWeak& data = **static_cast<ObjectPtrWeak**>(luaL_checkudata(L, index, metaTableName));
|
||||
if(ObjectPtr object = data.lock())
|
||||
return object;
|
||||
else
|
||||
{
|
||||
luaL_error(L, "dead object");
|
||||
abort(); // never happens, luaL_error doesn't return
|
||||
}
|
||||
}
|
||||
|
||||
ObjectPtr Object::test(lua_State* L, int index)
|
||||
{
|
||||
ObjectPtrWeak* data = *static_cast<ObjectPtrWeak**>(luaL_testudata(L, index, metaTableName));
|
||||
if(!data)
|
||||
return ObjectPtr();
|
||||
else if(ObjectPtr object = data->lock())
|
||||
return object;
|
||||
else
|
||||
{
|
||||
luaL_error(L, "dead object");
|
||||
abort(); // never happens, luaL_error doesn't return
|
||||
}
|
||||
}
|
||||
|
||||
void Object::push(lua_State* L, const ObjectPtr& value)
|
||||
{
|
||||
if(value)
|
||||
{
|
||||
*static_cast<ObjectPtrWeak**>(lua_newuserdata(L, sizeof(ObjectPtrWeak*))) = new ObjectPtrWeak(value);
|
||||
luaL_getmetatable(L, metaTableName);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
void Object::registerType(lua_State* L)
|
||||
{
|
||||
luaL_newmetatable(L, metaTableName);
|
||||
lua_pushcfunction(L, __gc);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_pushcfunction(L, __index);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
int Object::__gc(lua_State* L)
|
||||
{
|
||||
delete *static_cast<ObjectPtrWeak**>(lua_touserdata(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Object::__index(lua_State* L)
|
||||
{
|
||||
ObjectPtr object{check(L, 1)};
|
||||
const std::string name{lua_tostring(L, 2)};
|
||||
|
||||
if(InterfaceItem* item = object->getItem(name))
|
||||
{
|
||||
// TODO: test scriptable
|
||||
|
||||
if(AbstractProperty* property = dynamic_cast<AbstractProperty*>(item))
|
||||
{
|
||||
switch(property->type())
|
||||
{
|
||||
case ValueType::Boolean:
|
||||
Lua::push(L, property->toBool());
|
||||
break;
|
||||
|
||||
//case ValueType::Enum:
|
||||
|
||||
case ValueType::Integer:
|
||||
Lua::push(L, property->toInt64());
|
||||
break;
|
||||
|
||||
case ValueType::Float:
|
||||
Lua::push(L, property->toDouble());
|
||||
break;
|
||||
|
||||
case ValueType::String:
|
||||
Lua::push(L, property->toString());
|
||||
break;
|
||||
|
||||
case ValueType::Object:
|
||||
push(L, property->toObject());
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
/**
|
||||
* server/src/lua/traintastic.hpp
|
||||
* server/src/lua/object.hpp - Lua object wrapper
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019 Reinder Feenstra
|
||||
* Copyright (C) 2019-2020 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -20,19 +20,32 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef SERVER_LUA_TRAINTASTIC_HPP
|
||||
#define SERVER_LUA_TRAINTASTIC_HPP
|
||||
#ifndef SERVER_LUA_OBJECT_HPP
|
||||
#define SERVER_LUA_OBJECT_HPP
|
||||
|
||||
#include <lua.hpp>
|
||||
#include <memory>
|
||||
#include "../core/objectptr.hpp"
|
||||
|
||||
namespace Lua {
|
||||
|
||||
struct Traintastic
|
||||
class Object
|
||||
{
|
||||
static int get_object(lua_State* L);
|
||||
private:
|
||||
static int __gc(lua_State* L);
|
||||
static int __index(lua_State* L);
|
||||
|
||||
public:
|
||||
static constexpr char const* metaTableName = "object";
|
||||
|
||||
static ObjectPtr check(lua_State* L, int index);
|
||||
static ObjectPtr test(lua_State* L, int index);
|
||||
|
||||
static void push(lua_State* L, const ObjectPtr& value);
|
||||
|
||||
static void registerType(lua_State* L);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include "enum.hpp"
|
||||
#include "object.hpp"
|
||||
|
||||
namespace Lua {
|
||||
|
||||
@ -50,6 +51,8 @@ void push(lua_State* L, const T& value)
|
||||
lua_pushnumber(L, value);
|
||||
else if constexpr(std::is_same_v<T, std::string>)
|
||||
lua_pushlstring(L, value.data(), value.size());
|
||||
else if constexpr(std::is_same_v<T, ObjectPtr>)
|
||||
Object::push(L, value);
|
||||
else
|
||||
static_assert(sizeof(T) != sizeof(T), "don't know how to push type");
|
||||
}
|
||||
|
||||
@ -21,11 +21,14 @@
|
||||
*/
|
||||
|
||||
#include "sandbox.hpp"
|
||||
#include "push.hpp"
|
||||
#include "object.hpp"
|
||||
#include "console.hpp"
|
||||
#include <utils/str.hpp>
|
||||
#include "../core/world.hpp"
|
||||
#include "../enum/traintasticmode.hpp"
|
||||
#include "../enum/decoderprotocol.hpp"
|
||||
#include "../enum/direction.hpp"
|
||||
// TODO: #include "object.hpp"
|
||||
|
||||
#define LUA_SANDBOX "_sandbox"
|
||||
|
||||
@ -38,10 +41,11 @@ namespace Lua {
|
||||
|
||||
void Sandbox::close(lua_State* L)
|
||||
{
|
||||
delete *static_cast<StateData**>(lua_getextraspace(L)); // free state data
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
SandboxPtr Sandbox::create()
|
||||
SandboxPtr Sandbox::create(Script& script)
|
||||
{
|
||||
lua_State* L = luaL_newstate();
|
||||
|
||||
@ -50,11 +54,14 @@ SandboxPtr Sandbox::create()
|
||||
lua_pushliteral(L, "");
|
||||
lua_call(L, 1, 0);
|
||||
|
||||
// create state data:
|
||||
*static_cast<StateData**>(lua_getextraspace(L)) = new StateData(script);
|
||||
|
||||
// register types:
|
||||
Enum<TraintasticMode>::registerType(L);
|
||||
Enum<DecoderProtocol>::registerType(L);
|
||||
Enum<Direction>::registerType(L);
|
||||
// TODO: Object::registerType(L);
|
||||
Object::registerType(L);
|
||||
|
||||
// setup sandbox:
|
||||
lua_newtable(L);
|
||||
@ -65,6 +72,18 @@ SandboxPtr Sandbox::create()
|
||||
ADD_GLOBAL_TO_SANDBOX("pairs")
|
||||
ADD_GLOBAL_TO_SANDBOX("ipairs")
|
||||
|
||||
// set VERSION:
|
||||
lua_pushliteral(L, STR(VERSION));
|
||||
lua_setfield(L, -2, "VERSION");
|
||||
|
||||
// add world:
|
||||
push(L, std::static_pointer_cast<::Object>(script.world().lock()));
|
||||
lua_setfield(L, -2, "world");
|
||||
|
||||
// add console:
|
||||
Console::push(L);
|
||||
lua_setfield(L, -2, "console");
|
||||
|
||||
// add enum values:
|
||||
lua_newtable(L);
|
||||
Enum<TraintasticMode>::registerValues(L);
|
||||
@ -83,6 +102,11 @@ SandboxPtr Sandbox::create()
|
||||
return SandboxPtr(L, close);
|
||||
}
|
||||
|
||||
Sandbox::StateData& Sandbox::getStateData(lua_State* L)
|
||||
{
|
||||
return **static_cast<StateData**>(lua_getextraspace(L));
|
||||
}
|
||||
|
||||
int Sandbox::getGlobal(lua_State* L, const char* name)
|
||||
{
|
||||
lua_getglobal(L, LUA_SANDBOX); // get the sandbox
|
||||
|
||||
@ -23,11 +23,13 @@
|
||||
#ifndef SERVER_LUA_SANDBOX_HPP
|
||||
#define SERVER_LUA_SANDBOX_HPP
|
||||
|
||||
#include <lua.hpp>
|
||||
#include <memory>
|
||||
#include <lua.hpp>
|
||||
|
||||
namespace Lua {
|
||||
|
||||
class Script;
|
||||
|
||||
using SandboxPtr = std::unique_ptr<lua_State, void(*)(lua_State*)>;
|
||||
|
||||
class Sandbox
|
||||
@ -36,7 +38,25 @@ class Sandbox
|
||||
static void close(lua_State* L);
|
||||
|
||||
public:
|
||||
static SandboxPtr create();
|
||||
class StateData
|
||||
{
|
||||
private:
|
||||
Script& m_script;
|
||||
|
||||
public:
|
||||
StateData(Script& script) :
|
||||
m_script{script}
|
||||
{
|
||||
}
|
||||
|
||||
inline Script& script() const
|
||||
{
|
||||
return m_script;
|
||||
}
|
||||
};
|
||||
|
||||
static SandboxPtr create(Script& script);
|
||||
static StateData& getStateData(lua_State* L);
|
||||
static int getGlobal(lua_State* L, const char* name);
|
||||
static int pcall(lua_State* L, int nargs = 0, int nresults = 0, int errfunc = 0);
|
||||
};
|
||||
|
||||
@ -82,7 +82,8 @@ void Script::modeChanged(TraintasticMode mode)
|
||||
void Script::init()
|
||||
{
|
||||
assert(!m_sandbox);
|
||||
if((m_sandbox = Sandbox::create()))
|
||||
auto world = m_world.lock();
|
||||
if(world && (m_sandbox = Sandbox::create(*this)))
|
||||
{
|
||||
lua_State* L = m_sandbox.get();
|
||||
const int error = luaL_loadbuffer(L, code.value().c_str(), code.value().size(), "=") || Sandbox::pcall(L, 0, LUA_MULTRET);
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren