diff options
Diffstat (limited to 'src/script/cpp_api')
-rw-r--r-- | src/script/cpp_api/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.cpp | 24 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.h | 13 | ||||
-rw-r--r-- | src/script/cpp_api/s_cheats.cpp | 123 | ||||
-rw-r--r-- | src/script/cpp_api/s_cheats.h | 58 | ||||
-rw-r--r-- | src/script/cpp_api/s_client.cpp | 177 | ||||
-rw-r--r-- | src/script/cpp_api/s_client.h | 15 | ||||
-rw-r--r-- | src/script/cpp_api/s_security.cpp | 11 |
8 files changed, 408 insertions, 14 deletions
diff --git a/src/script/cpp_api/CMakeLists.txt b/src/script/cpp_api/CMakeLists.txt index 3cfd7709a..d2c55b7c5 100644 --- a/src/script/cpp_api/CMakeLists.txt +++ b/src/script/cpp_api/CMakeLists.txt @@ -15,6 +15,7 @@ set(common_SCRIPT_CPP_API_SRCS set(client_SCRIPT_CPP_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/s_client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/s_cheats.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_mainmenu.cpp PARENT_SCOPE) diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 595c9e540..ae4a16771 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" @@ -85,9 +86,9 @@ ScriptApiBase::ScriptApiBase(ScriptingType type): lua_atpanic(m_luastack, &luaPanic); - if (m_type == ScriptingType::Client) + /*if (m_type == ScriptingType::Client) clientOpenLibs(m_luastack); - else + else*/ luaL_openlibs(m_luastack); // Load bit library @@ -365,13 +366,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 @@ -386,7 +392,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; @@ -401,7 +407,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 @@ -424,7 +435,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 244d81605..19ae8783b 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -67,10 +67,12 @@ enum class ScriptingType: u8 { class Server; #ifndef SERVER class Client; +class Game; #endif class IGameDef; class Environment; class GUIEngine; +class ActiveObject; class ServerActiveObject; struct PlayerHPChangeReason; @@ -97,14 +99,15 @@ 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(); ScriptingType getType() { return m_type; } #ifndef SERVER Client* getClient(); + Game *getGame() { return m_game; } #endif // IMPORTANT: these cannot be used for any security-related uses, they exist @@ -145,6 +148,9 @@ protected: void stackDump(std::ostream &o); void setGameDef(IGameDef* gamedef) { m_gamedef = gamedef; } +#ifndef SERVER + void setGame(Game *game) { m_game = game; } +#endif Environment* getEnv() { return m_environment; } void setEnv(Environment* env) { m_environment = env; } @@ -172,6 +178,9 @@ private: lua_State *m_luastack = nullptr; IGameDef *m_gamedef = nullptr; +#ifndef SERVER + Game *m_game = nullptr; +#endif Environment *m_environment = nullptr; #ifndef SERVER GUIEngine *m_guiengine = nullptr; diff --git a/src/script/cpp_api/s_cheats.cpp b/src/script/cpp_api/s_cheats.cpp new file mode 100644 index 000000000..3d0c5e645 --- /dev/null +++ b/src/script/cpp_api/s_cheats.cpp @@ -0,0 +1,123 @@ +/* +Dragonfire +Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de> + +This program 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 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser 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 "cpp_api/s_cheats.h" +#include "cpp_api/s_base.h" +#include "cpp_api/s_internal.h" +#include "settings.h" + +ScriptApiCheatsCheat::ScriptApiCheatsCheat( + const std::string &name, const std::string &setting) : + m_name(name), + m_setting(setting), m_function_ref(0) +{ +} + +ScriptApiCheatsCheat::ScriptApiCheatsCheat(const std::string &name, const int &function) : + m_name(name), m_setting(""), m_function_ref(function) +{ +} + +bool ScriptApiCheatsCheat::is_enabled() +{ + try { + return !m_function_ref && g_settings->getBool(m_setting); + } catch (SettingNotFoundException &) { + return false; + } +} + +void ScriptApiCheatsCheat::toggle(lua_State *L, int error_handler) +{ + if (m_function_ref) { + lua_rawgeti(L, LUA_REGISTRYINDEX, m_function_ref); + lua_pcall(L, 0, 0, error_handler); + } else + g_settings->setBool(m_setting, !is_enabled()); +} + +ScriptApiCheatsCategory::ScriptApiCheatsCategory(const std::string &name) : m_name(name) +{ +} + +ScriptApiCheatsCategory::~ScriptApiCheatsCategory() +{ + for (auto i = m_cheats.begin(); i != m_cheats.end(); i++) + delete *i; +} + +void ScriptApiCheatsCategory::read_cheats(lua_State *L) +{ + lua_pushnil(L); + while (lua_next(L, -2)) { + ScriptApiCheatsCheat *cheat = nullptr; + std::string name = lua_tostring(L, -2); + if (lua_isstring(L, -1)) + cheat = new ScriptApiCheatsCheat(name, lua_tostring(L, -1)); + else if (lua_isfunction(L, -1)) { + cheat = new ScriptApiCheatsCheat( + name, luaL_ref(L, LUA_REGISTRYINDEX)); + lua_pushnil(L); + } + if (cheat) + m_cheats.push_back(cheat); + lua_pop(L, 1); + } +} + +ScriptApiCheats::~ScriptApiCheats() +{ + for (auto i = m_cheat_categories.begin(); i != m_cheat_categories.end(); i++) + delete *i; +} + +void ScriptApiCheats::init_cheats() +{ + SCRIPTAPI_PRECHECKHEADER + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "cheats"); + if (!lua_istable(L, -1)) { + lua_pop(L, 2); + return; + } + lua_pushnil(L); + while (lua_next(L, -2)) { + if (lua_istable(L, -1)) { + ScriptApiCheatsCategory *category = + new ScriptApiCheatsCategory(lua_tostring(L, -2)); + category->read_cheats(L); + m_cheat_categories.push_back(category); + } + lua_pop(L, 1); + } + lua_pop(L, 2); + m_cheats_loaded = true; +} + +void ScriptApiCheats::toggle_cheat(ScriptApiCheatsCheat *cheat) +{ + SCRIPTAPI_PRECHECKHEADER + + PUSH_ERROR_HANDLER(L); + int error_handler = lua_gettop(L) - 1; + lua_insert(L, error_handler); + + cheat->toggle(L, error_handler); +} diff --git a/src/script/cpp_api/s_cheats.h b/src/script/cpp_api/s_cheats.h new file mode 100644 index 000000000..9f36333b7 --- /dev/null +++ b/src/script/cpp_api/s_cheats.h @@ -0,0 +1,58 @@ +/* +Dragonfire +Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de> + +This program 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 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser 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. +*/ + +#pragma once + +#include "cpp_api/s_base.h" +#include <vector> +#include <string> + +class ScriptApiCheatsCheat +{ +public: + ScriptApiCheatsCheat(const std::string &name, const std::string &setting); + ScriptApiCheatsCheat(const std::string &name, const int &function); + std::string m_name; + bool is_enabled(); + void toggle(lua_State *L, int error_handler); + +private: + std::string m_setting; + int m_function_ref; +}; + +class ScriptApiCheatsCategory +{ +public: + ScriptApiCheatsCategory(const std::string &name); + ~ScriptApiCheatsCategory(); + std::string m_name; + void read_cheats(lua_State *L); + std::vector<ScriptApiCheatsCheat *> m_cheats; +}; + +class ScriptApiCheats : virtual public ScriptApiBase +{ +public: + virtual ~ScriptApiCheats(); + void init_cheats(); + void toggle_cheat(ScriptApiCheatsCheat *cheat); + bool m_cheats_loaded = false; + std::vector<ScriptApiCheatsCategory *> m_cheat_categories; +}; diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index b02a0c7be..e54a1361d 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -18,11 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "nodedef.h" +#include "itemdef.h" #include "s_client.h" #include "s_internal.h" #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() @@ -212,7 +215,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"); @@ -274,6 +277,121 @@ bool ScriptApiClient::on_item_use(const ItemStack &item, const PointedThing &poi return readParam<bool>(L, -1); } +bool ScriptApiClient::on_recieve_physics_override(float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_recieve_physics_override + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_recieve_physics_override"); + + // Push data + push_physics_override(L, speed, jump, gravity, sneak, sneak_glitch, new_move); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_OR); + return readParam<bool>(L, -1); +} + +bool ScriptApiClient::on_play_sound(SimpleSoundSpec spec) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_play_sound + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_play_sound"); + + // Push data + push_soundspec(L, spec); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_OR); + return readParam<bool>(L, -1); +} + +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"); + + // Push data + lua_newtable(L); + push_v3f(L, param.pos); + lua_setfield(L, -2, "pos"); + push_v3f(L, param.vel); + lua_setfield(L, -2, "velocity"); + push_v3f(L, param.acc); + lua_setfield(L, -2, "acceleration"); + setfloatfield(L, -1, "expirationtime", param.expirationtime); + setboolfield(L, -1, "collisiondetection", param.collisiondetection); + setboolfield(L, -1, "collision_removal", param.collision_removal); + setboolfield(L, -1, "object_collision", param.object_collision); + setboolfield(L, -1, "vertical", param.vertical); + push_animation_definition(L, param.animation); + lua_setfield(L, -2, "animation"); + setstringfield(L, -1, "texture", param.texture); + setintfield(L, -1, "glow", param.glow); + if (param.node.getContent() != CONTENT_IGNORE) { + pushnode(L, param.node, getGameDef()->ndef()); + lua_setfield(L, -2, "node"); + } + 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); +} + +bool 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_OR); + return readParam<bool>(L, -1); +} + bool ScriptApiClient::on_inventory_open(Inventory *inventory) { SCRIPTAPI_PRECHECKHEADER @@ -292,6 +410,63 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory) return readParam<bool>(L, -1); } +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()); +} + +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()); +} + void ScriptApiClient::setEnv(ClientEnvironment *env) { ScriptApiBase::setEnv(env); diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 93fe96791..6d1a05943 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "util/pointedthing.h" #include "lua_api/l_item.h" +#include "particles.h" #ifdef _CRT_MSVCP_CURRENT #include <cstdint> @@ -57,8 +58,22 @@ public: bool on_punchnode(v3s16 p, MapNode node); bool on_placenode(const PointedThing &pointed, const ItemDefinition &item); bool on_item_use(const ItemStack &item, const PointedThing &pointed); + bool on_recieve_physics_override(float override_speed, float override_jump, + float override_gravity, bool sneak, bool sneak_glitch, + 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); + bool 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); void setEnv(ClientEnvironment *env); }; diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 88e22f16f..037bd8cf9 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -111,6 +111,7 @@ void ScriptApiSecurity::initializeSecurity() "bit" }; static const char *io_whitelist[] = { + "open", "close", "flush", "read", @@ -199,7 +200,7 @@ void ScriptApiSecurity::initializeSecurity() copy_safe(L, io_whitelist, sizeof(io_whitelist)); // And replace unsafe ones - SECURE_API(io, open); + //SECURE_API(io, open); SECURE_API(io, input); SECURE_API(io, output); SECURE_API(io, lines); @@ -318,7 +319,6 @@ void ScriptApiSecurity::initializeSecurityClient() "getinfo", // used by builtin and unset before mods load "traceback" }; - #if USE_LUAJIT static const char *jit_whitelist[] = { "arch", @@ -338,6 +338,10 @@ void ScriptApiSecurity::initializeSecurityClient() lua_State *L = getStack(); int thread = getThread(L); + // Backup globals to the registry + lua_getglobal(L, "_G"); + lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP); + // create an empty environment createEmptyEnv(L); @@ -354,8 +358,6 @@ void ScriptApiSecurity::initializeSecurityClient() SECURE_API(g, require); lua_pop(L, 2); - - // Copy safe OS functions lua_getglobal(L, "os"); lua_newtable(L); @@ -370,6 +372,7 @@ void ScriptApiSecurity::initializeSecurityClient() copy_safe(L, debug_whitelist, sizeof(debug_whitelist)); lua_setfield(L, -3, "debug"); lua_pop(L, 1); // Pop old debug + #if USE_LUAJIT // Copy safe jit functions, if they exist |