aboutsummaryrefslogtreecommitdiff
path: root/src/script/cpp_api
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/cpp_api')
-rw-r--r--src/script/cpp_api/s_base.cpp20
-rw-r--r--src/script/cpp_api/s_base.h5
-rw-r--r--src/script/cpp_api/s_client.cpp87
-rw-r--r--src/script/cpp_api/s_client.h5
-rw-r--r--src/script/cpp_api/s_node.cpp1
-rw-r--r--src/script/cpp_api/s_security.cpp44
6 files changed, 144 insertions, 18 deletions
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp
index 1d62d8b65..5711ccbfd 100644
--- a/src/script/cpp_api/s_base.cpp
+++ b/src/script/cpp_api/s_base.cpp
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_internal.h"
#include "cpp_api/s_security.h"
#include "lua_api/l_object.h"
+#include "lua_api/l_clientobject.h"
#include "common/c_converter.h"
#include "server/player_sao.h"
#include "filesys.h"
@@ -354,13 +355,18 @@ void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn)
* since we lose control over the ref and the contained pointer.
*/
-void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
+void ScriptApiBase::addObjectReference(ActiveObject *cobj)
{
SCRIPTAPI_PRECHECKHEADER
//infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
// Create object on stack
- ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
+#ifndef SERVER
+ if (m_type == ScriptingType::Client)
+ ClientObjectRef::create(L, dynamic_cast<ClientActiveObject *>(cobj));
+ else
+#endif
+ ObjectRef::create(L, dynamic_cast<ServerActiveObject *>(cobj)); // Puts ObjectRef (as userdata) on stack
int object = lua_gettop(L);
// Get core.object_refs table
@@ -375,7 +381,7 @@ void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
lua_settable(L, objectstable);
}
-void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
+void ScriptApiBase::removeObjectReference(ActiveObject *cobj)
{
SCRIPTAPI_PRECHECKHEADER
//infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
@@ -390,7 +396,12 @@ void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
lua_pushnumber(L, cobj->getId()); // Push id
lua_gettable(L, objectstable);
// Set object reference to NULL
- ObjectRef::set_null(L);
+#ifndef SERVER
+ if (m_type == ScriptingType::Client)
+ ClientObjectRef::set_null(L);
+ else
+#endif
+ ObjectRef::set_null(L);
lua_pop(L, 1); // pop object
// Set object_refs[id] = nil
@@ -413,7 +424,6 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L,
<< ", this is probably a bug." << std::endl;
}
}
-
void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason)
{
if (reason.hasLuaReference())
diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h
index 36331ad37..a7a2c7203 100644
--- a/src/script/cpp_api/s_base.h
+++ b/src/script/cpp_api/s_base.h
@@ -73,6 +73,7 @@ class Game;
class IGameDef;
class Environment;
class GUIEngine;
+class ActiveObject;
class ServerActiveObject;
struct PlayerHPChangeReason;
@@ -99,8 +100,8 @@ public:
RunCallbacksMode mode, const char *fxn);
/* object */
- void addObjectReference(ServerActiveObject *cobj);
- void removeObjectReference(ServerActiveObject *cobj);
+ void addObjectReference(ActiveObject *cobj);
+ void removeObjectReference(ActiveObject *cobj);
IGameDef *getGameDef() { return m_gamedef; }
Server* getServer();
diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp
index b90decfb5..b0e7a073e 100644
--- a/src/script/cpp_api/s_client.cpp
+++ b/src/script/cpp_api/s_client.cpp
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/client.h"
#include "common/c_converter.h"
#include "common/c_content.h"
+#include "lua_api/l_clientobject.h"
#include "s_item.h"
void ScriptApiClient::on_mods_loaded()
@@ -176,7 +177,7 @@ bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node)
const NodeDefManager *ndef = getClient()->ndef();
- // Get core.registered_on_punchgnode
+ // Get core.registered_on_punchnode
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_on_punchnode");
@@ -260,7 +261,7 @@ bool ScriptApiClient::on_spawn_particle(struct ParticleParameters param)
SCRIPTAPI_PRECHECKHEADER
// Get core.registered_on_play_sound
-
+
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_on_spawn_particle");
@@ -285,13 +286,58 @@ bool ScriptApiClient::on_spawn_particle(struct ParticleParameters param)
pushnode(L, param.node, getGameDef()->ndef());
lua_setfield(L, -2, "node");
}
- setintfield(L, -1, "node_tile", param.node_tile);
-
+ setintfield(L, -1, "node_tile", param.node_tile);
+
// Call functions
runCallbacks(1, RUN_CALLBACKS_MODE_OR);
return readParam<bool>(L, -1);
}
+void ScriptApiClient::on_object_properties_change(s16 id)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_object_properties_change
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_object_properties_change");
+
+ // Push data
+ push_objectRef(L, id);
+
+ // Call functions
+ runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+}
+
+void ScriptApiClient::on_object_hp_change(s16 id)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_object_hp_change
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_object_hp_change");
+
+ // Push data
+ push_objectRef(L, id);
+
+ // Call functions
+ runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+}
+
+void ScriptApiClient::on_object_add(s16 id)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_object_add
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_object_add");
+
+ // Push data
+ push_objectRef(L, id);
+
+ // Call functions
+ runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+}
+
bool ScriptApiClient::on_inventory_open(Inventory *inventory)
{
SCRIPTAPI_PRECHECKHEADER
@@ -308,24 +354,45 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory)
void ScriptApiClient::open_enderchest()
{
SCRIPTAPI_PRECHECKHEADER
-
+
PUSH_ERROR_HANDLER(L);
int error_handler = lua_gettop(L) - 1;
lua_insert(L, error_handler);
-
+
lua_getglobal(L, "core");
lua_getfield(L, -1, "open_enderchest");
if (lua_isfunction(L, -1))
lua_pcall(L, 0, 0, error_handler);
}
+v3f ScriptApiClient::get_send_speed(v3f speed)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ PUSH_ERROR_HANDLER(L);
+ int error_handler = lua_gettop(L) - 1;
+ lua_insert(L, error_handler);
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "get_send_speed");
+ if (lua_isfunction(L, -1)) {
+ speed /= BS;
+ push_v3f(L, speed);
+ lua_pcall(L, 1, 1, error_handler);
+ speed = read_v3f(L, -1);
+ speed *= BS;
+ }
+
+ return speed;
+}
+
void ScriptApiClient::set_node_def(const ContentFeatures &f)
{
SCRIPTAPI_PRECHECKHEADER
-
+
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_nodes");
-
+
push_content_features(L, f);
lua_setfield(L, -2, f.name.c_str());
}
@@ -333,10 +400,10 @@ void ScriptApiClient::set_node_def(const ContentFeatures &f)
void ScriptApiClient::set_item_def(const ItemDefinition &i)
{
SCRIPTAPI_PRECHECKHEADER
-
+
lua_getglobal(L, "core");
lua_getfield(L, -1, "registered_items");
-
+
push_item_definition(L, i);
lua_setfield(L, -2, i.name.c_str());
}
diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h
index 9f68a14fc..2f9ce7aa3 100644
--- a/src/script/cpp_api/s_client.h
+++ b/src/script/cpp_api/s_client.h
@@ -63,10 +63,15 @@ public:
bool new_move);
bool on_play_sound(SimpleSoundSpec spec);
bool on_spawn_particle(struct ParticleParameters param);
+ void on_object_properties_change(s16 id);
+ void on_object_hp_change(s16 id);
+ void on_object_add(s16 id);
bool on_inventory_open(Inventory *inventory);
void open_enderchest();
+ v3f get_send_speed(v3f speed);
+
void set_node_def(const ContentFeatures &f);
void set_item_def(const ItemDefinition &i);
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index f23fbfbde..029cb6308 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -65,6 +65,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
{CPT2_COLORED_FACEDIR, "colorfacedir"},
{CPT2_COLORED_WALLMOUNTED, "colorwallmounted"},
{CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"},
+ {CPT2_COLORED_DEGROTATE, "colordegrotate"},
{0, NULL},
};
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index 37c5b61dc..8fe5d2c5a 100644
--- a/src/script/cpp_api/s_security.cpp
+++ b/src/script/cpp_api/s_security.cpp
@@ -45,6 +45,21 @@ static inline void copy_safe(lua_State *L, const char *list[], unsigned len, int
}
}
+static void shallow_copy_table(lua_State *L, int from=-2, int to=-1)
+{
+ if (from < 0) from = lua_gettop(L) + from + 1;
+ if (to < 0) to = lua_gettop(L) + to + 1;
+ lua_pushnil(L);
+ while (lua_next(L, from) != 0) {
+ assert(lua_type(L, -1) != LUA_TTABLE);
+ // duplicate key and value for lua_rawset
+ lua_pushvalue(L, -2);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, to);
+ lua_pop(L, 1);
+ }
+}
+
// Pushes the original version of a library function on the stack, from the old version
static inline void push_original(lua_State *L, const char *lib, const char *func)
{
@@ -83,7 +98,10 @@ void ScriptApiSecurity::initializeSecurity()
"unpack",
"_VERSION",
"xpcall",
- // Completely safe libraries
+ };
+ static const char *whitelist_tables[] = {
+ // These libraries are completely safe BUT we need to duplicate their table
+ // to ensure the sandbox can't affect the insecure env
"coroutine",
"string",
"table",
@@ -168,6 +186,17 @@ void ScriptApiSecurity::initializeSecurity()
lua_pop(L, 1);
+ // Copy safe libraries
+ for (const char *libname : whitelist_tables) {
+ lua_getfield(L, old_globals, libname);
+ lua_newtable(L);
+ shallow_copy_table(L);
+
+ lua_setglobal(L, libname);
+ lua_pop(L, 1);
+ }
+
+
// Copy safe IO functions
lua_getfield(L, old_globals, "io");
lua_newtable(L);
@@ -223,6 +252,19 @@ void ScriptApiSecurity::initializeSecurity()
#endif
lua_pop(L, 1); // Pop globals_backup
+
+
+ /*
+ * In addition to copying the tables in whitelist_tables, we also need to
+ * replace the string metatable. Otherwise old_globals.string would
+ * be accessible via getmetatable("").__index from inside the sandbox.
+ */
+ lua_pushliteral(L, "");
+ lua_newtable(L);
+ lua_getglobal(L, "string");
+ lua_setfield(L, -2, "__index");
+ lua_setmetatable(L, -2);
+ lua_pop(L, 1); // Pop empty string
}
void ScriptApiSecurity::initializeSecurityClient()