diff options
Diffstat (limited to 'src/script')
30 files changed, 1519 insertions, 79 deletions
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index e3cb9042e..72361bdb5 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "object_properties.h" #include "collision.h" #include "cpp_api/s_node.h" +#include "lua_api/l_clientobject.h" #include "lua_api/l_object.h" #include "lua_api/l_item.h" #include "common/c_internal.h" @@ -173,10 +174,12 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i) } push_groups(L, i.groups); lua_setfield(L, -2, "groups"); + lua_newtable(L); push_soundspec(L, i.sound_place); - lua_setfield(L, -2, "sound_place"); + lua_setfield(L, -2, "place"); push_soundspec(L, i.sound_place_failed); - lua_setfield(L, -2, "sound_place_failed"); + lua_setfield(L, -2, "place_failed"); + lua_setfield(L, -2, "sounds"); lua_pushstring(L, i.node_placement_prediction.c_str()); lua_setfield(L, -2, "node_placement_prediction"); } @@ -916,11 +919,11 @@ void push_content_features(lua_State *L, const ContentFeatures &c) lua_setfield(L, -2, "collision_box"); lua_newtable(L); push_soundspec(L, c.sound_footstep); - lua_setfield(L, -2, "sound_footstep"); + lua_setfield(L, -2, "footstep"); push_soundspec(L, c.sound_dig); - lua_setfield(L, -2, "sound_dig"); + lua_setfield(L, -2, "dig"); push_soundspec(L, c.sound_dug); - lua_setfield(L, -2, "sound_dug"); + lua_setfield(L, -2, "dug"); lua_setfield(L, -2, "sounds"); lua_pushboolean(L, c.legacy_facedir_simple); lua_setfield(L, -2, "legacy_facedir_simple"); @@ -1308,17 +1311,17 @@ void push_tool_capabilities(lua_State *L, } /******************************************************************************/ -void push_inventory_list(lua_State *L, Inventory *inv, const char *name) +void push_inventory(lua_State *L, Inventory *inventory) { - InventoryList *invlist = inv->getList(name); - if(invlist == NULL){ - lua_pushnil(L); - return; + std::vector<const InventoryList*> lists = inventory->getLists(); + std::vector<const InventoryList*>::iterator iter = lists.begin(); + lua_createtable(L, 0, lists.size()); + for (; iter != lists.end(); iter++) { + const char* name = (*iter)->getName().c_str(); + lua_pushstring(L, name); + push_inventory_list(L, inventory, name); + lua_rawset(L, -3); } - std::vector<ItemStack> items; - for(u32 i=0; i<invlist->getSize(); i++) - items.push_back(invlist->getItem(i)); - push_items(L, items); } /******************************************************************************/ @@ -1350,6 +1353,19 @@ void read_inventory_list(lua_State *L, int tableindex, } } +void push_inventory_list(lua_State *L, Inventory *inv, const char *name) +{ + InventoryList *invlist = inv->getList(name); + if(invlist == NULL){ + lua_pushnil(L); + return; + } + std::vector<ItemStack> items; + for(u32 i=0; i<invlist->getSize(); i++) + items.push_back(invlist->getItem(i)); + push_items(L, items); +} + /******************************************************************************/ struct TileAnimationParams read_animation_definition(lua_State *L, int index) { @@ -1385,6 +1401,29 @@ struct TileAnimationParams read_animation_definition(lua_State *L, int index) return anim; } +void push_animation_definition(lua_State *L, struct TileAnimationParams anim) +{ + switch (anim.type) { + case TAT_NONE: + lua_pushnil(L); + break; + case TAT_VERTICAL_FRAMES: + lua_newtable(L); + setstringfield(L, -1, "type", "vertical_frames"); + setfloatfield(L, -1, "aspect_w", anim.vertical_frames.aspect_w); + setfloatfield(L, -1, "aspect_h", anim.vertical_frames.aspect_h); + setfloatfield(L, -1, "length", anim.vertical_frames.length); + break; + case TAT_SHEET_2D: + lua_newtable(L); + setstringfield(L, -1, "type", "sheet_2d"); + setintfield(L, -1, "frames_w", anim.sheet_2d.frames_w); + setintfield(L, -1, "frames_h", anim.sheet_2d.frames_h); + setintfield(L, -1, "frame_length", anim.sheet_2d.frame_length); + break; + } +} + /******************************************************************************/ ToolCapabilities read_tool_capabilities( lua_State *L, int table) @@ -1823,14 +1862,15 @@ void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm, } else if (pointed.type == POINTEDTHING_OBJECT) { lua_pushstring(L, "object"); lua_setfield(L, -2, "type"); - if (csm) { - lua_pushinteger(L, pointed.object_id); - lua_setfield(L, -2, "id"); +#ifndef SERVER + ClientObjectRef::create(L, pointed.object_id); +#endif } else { push_objectRef(L, pointed.object_id); - lua_setfield(L, -2, "ref"); } + + lua_setfield(L, -2, "ref"); } else { lua_pushstring(L, "nothing"); lua_setfield(L, -2, "type"); @@ -2084,3 +2124,27 @@ void push_collision_move_result(lua_State *L, const collisionMoveResult &res) lua_setfield(L, -2, "collisions"); /**/ } + +/******************************************************************************/ +void push_physics_override(lua_State *L, float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move) +{ + lua_createtable(L, 0, 6); + + lua_pushnumber(L, speed); + lua_setfield(L, -2, "speed"); + + lua_pushnumber(L, jump); + lua_setfield(L, -2, "jump"); + + lua_pushnumber(L, gravity); + lua_setfield(L, -2, "gravity"); + + lua_pushboolean(L, sneak); + lua_setfield(L, -2, "sneak"); + + lua_pushboolean(L, sneak_glitch); + lua_setfield(L, -2, "sneak_glitch"); + + lua_pushboolean(L, new_move); + lua_setfield(L, -2, "new_move"); +} diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 29d576355..10b77a116 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -98,6 +98,7 @@ void push_hit_params (lua_State *L, ItemStack read_item (lua_State *L, int index, IItemDefManager *idef); struct TileAnimationParams read_animation_definition(lua_State *L, int index); +void push_animation_definition(lua_State *L, struct TileAnimationParams anim); ToolCapabilities read_tool_capabilities (lua_State *L, int table); void push_tool_capabilities (lua_State *L, @@ -117,6 +118,9 @@ void read_object_properties (lua_State *L, int index, void push_object_properties (lua_State *L, ObjectProperties *prop); +void push_inventory (lua_State *L, + Inventory *inventory); + void push_inventory_list (lua_State *L, Inventory *inv, const char *name); @@ -200,3 +204,5 @@ void push_hud_element (lua_State *L, HudElement *elem); HudElementStat read_hud_change (lua_State *L, HudElement *elem, void **value); void push_collision_move_result(lua_State *L, const collisionMoveResult &res); + +void push_physics_override (lua_State *L, float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move); 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 f965975a3..1d62d8b65 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -83,9 +83,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); // Make the ScriptApiBase* accessible to ModApiBase diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 86f7f7bac..36331ad37 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -68,6 +68,7 @@ enum class ScriptingType: u8 { class Server; #ifndef SERVER class Client; +class Game; #endif class IGameDef; class Environment; @@ -106,6 +107,7 @@ public: ScriptingType getType() { return m_type; } #ifndef SERVER Client* getClient(); + Game *getGame() { return m_game; } #endif std::string getOrigin() { return m_last_run_mod; } @@ -132,6 +134,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; } @@ -159,6 +164,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 f2cc9730b..200a449ee 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -221,6 +221,75 @@ 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); +} + bool ScriptApiClient::on_inventory_open(Inventory *inventory) { SCRIPTAPI_PRECHECKHEADER @@ -228,20 +297,26 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory) lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_inventory_open"); - std::vector<const InventoryList*> lists = inventory->getLists(); - std::vector<const InventoryList*>::iterator iter = lists.begin(); - lua_createtable(L, 0, lists.size()); - for (; iter != lists.end(); iter++) { - const char* name = (*iter)->getName().c_str(); - lua_pushstring(L, name); - push_inventory_list(L, inventory, name); - lua_rawset(L, -3); - } + push_inventory(L, inventory); runCallbacks(1, RUN_CALLBACKS_MODE_OR); 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); +} + 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..26fa7abea 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,14 @@ 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); bool on_inventory_open(Inventory *inventory); + void open_enderchest(); void setEnv(ClientEnvironment *env); }; diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 01333b941..d5db43db9 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -90,6 +90,7 @@ void ScriptApiSecurity::initializeSecurity() "math", }; static const char *io_whitelist[] = { + "open", "close", "flush", "read", @@ -173,7 +174,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); @@ -267,7 +268,6 @@ void ScriptApiSecurity::initializeSecurityClient() "getinfo", "traceback" }; - #if USE_LUAJIT static const char *jit_whitelist[] = { "arch", @@ -287,6 +287,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); @@ -303,8 +307,6 @@ void ScriptApiSecurity::initializeSecurityClient() SECURE_API(g, require); lua_pop(L, 2); - - // Copy safe OS functions lua_getglobal(L, "os"); lua_newtable(L); @@ -319,6 +321,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 diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index 32f6a2793..3f1b89085 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -28,6 +28,8 @@ set(common_SCRIPT_LUA_API_SRCS set(client_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_clientobject.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_inventoryaction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index f842671b8..fce6282a5 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -55,6 +55,11 @@ Client *ModApiBase::getClient(lua_State *L) { return getScriptApiBase(L)->getClient(); } + +Game *ModApiBase::getGame(lua_State *L) +{ + return getScriptApiBase(L)->getGame(); +} #endif IGameDef *ModApiBase::getGameDef(lua_State *L) diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index aa5905d26..9ba50dabf 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -32,6 +32,7 @@ extern "C" { #ifndef SERVER class Client; +class Game; class GUIEngine; #endif @@ -47,11 +48,11 @@ public: static ServerInventoryManager *getServerInventoryMgr(lua_State *L); #ifndef SERVER static Client* getClient(lua_State *L); + static Game* getGame(lua_State *L); static GUIEngine* getGuiEngine(lua_State *L); #endif // !SERVER static IGameDef* getGameDef(lua_State *L); - static Environment* getEnv(lua_State *L); // When we are not loading the mod, this function returns "." diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index aaced7cd0..5e69d55dd 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -24,16 +24,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/clientevent.h" #include "client/sound.h" #include "client/clientenvironment.h" +#include "client/game.h" #include "common/c_content.h" #include "common/c_converter.h" #include "cpp_api/s_base.h" #include "gettext.h" #include "l_internal.h" +#include "l_clientobject.h" #include "lua_api/l_nodemeta.h" #include "gui/mainmenumanager.h" #include "map.h" #include "util/string.h" #include "nodedef.h" +#include "client/keycode.h" #define checkCSMRestrictionFlag(flag) \ ( getClient(L)->checkCSMRestrictionFlag(CSMRestrictionFlags::flag) ) @@ -414,6 +417,123 @@ int ModApiClient::l_get_csm_restrictions(lua_State *L) return 1; } +// send_damage(damage) +int ModApiClient::l_send_damage(lua_State *L) +{ + u16 damage = luaL_checknumber(L, 1); + getClient(L)->sendDamage(damage); + return 0; +} + +// place_node(pos) +int ModApiClient::l_place_node(lua_State *L) +{ + Client *client = getClient(L); + ClientMap &map = client->getEnv().getClientMap(); + LocalPlayer *player = client->getEnv().getLocalPlayer(); + ItemStack selected_item, hand_item; + player->getWieldedItem(&selected_item, &hand_item); + const ItemDefinition &selected_def = selected_item.getDefinition(getGameDef(L)->idef()); + v3s16 pos = read_v3s16(L, 1); + PointedThing pointed; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + pointed.node_undersurface = pos; + NodeMetadata *meta = map.getNodeMetadata(pos); + g_game->nodePlacement(selected_def, selected_item, pos, pos, pointed, meta); + return 0; +} + +// dig_node(pos) +int ModApiClient::l_dig_node(lua_State *L) +{ + Client *client = getClient(L); + v3s16 pos = read_v3s16(L, 1); + PointedThing pointed; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + pointed.node_undersurface = pos; + client->interact(INTERACT_START_DIGGING, pointed); + client->interact(INTERACT_DIGGING_COMPLETED, pointed); + return 0; +} + +// get_inventory(location) +int ModApiClient::l_get_inventory(lua_State *L) +{ + Client *client = getClient(L); + InventoryLocation inventory_location; + Inventory *inventory; + std::string location; + + location = readParam<std::string>(L, 1); + + try { + inventory_location.deSerialize(location); + inventory = client->getInventory(inventory_location); + if (! inventory) + throw SerializationError(std::string("Attempt to access nonexistant inventory (") + location + ")"); + push_inventory(L, inventory); + } catch (SerializationError &) { + lua_pushnil(L); + } + + return 1; +} + +// set_keypress(key_setting, pressed) -> returns true on success +int ModApiClient::l_set_keypress(lua_State *L) +{ + std::string setting_name = "keymap_" + readParam<std::string>(L, 1); + bool pressed = lua_isboolean(L, 2) && readParam<bool>(L, 2); + try { + KeyPress keyCode = getKeySetting(setting_name.c_str()); + if (pressed) + g_game->input->setKeypress(keyCode); + else + g_game->input->unsetKeypress(keyCode); + lua_pushboolean(L, true); + } catch (SettingNotFoundException &) { + lua_pushboolean(L, false); + } + return 1; +} + +// drop_selected_item() +int ModApiClient::l_drop_selected_item(lua_State *L) +{ + g_game->dropSelectedItem(); + return 0; +} + +// get_objects_inside_radius(pos, radius) +int ModApiClient::l_get_objects_inside_radius(lua_State *L) +{ + ClientEnvironment &env = getClient(L)->getEnv(); + + v3f pos = checkFloatPos(L, 1); + float radius = readParam<float>(L, 2) * BS; + + std::vector<DistanceSortedActiveObject> objs; + env.getActiveObjects(pos, radius, objs); + + int i = 0; + lua_createtable(L, objs.size(), 0); + for (const auto obj : objs) { + ClientObjectRef::create(L, obj.obj); // TODO: getObjectRefOrCreate + lua_rawseti(L, -2, ++i); + } + return 1; +} + +//make_screenshot() +int ModApiClient::l_make_screenshot(lua_State *L) +{ + getClient(L)->makeScreenshot(); + lua_pushboolean(L, true); + return 1; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -441,4 +561,13 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_builtin_path); API_FCT(get_language); API_FCT(get_csm_restrictions); + API_FCT(send_damage); + API_FCT(place_node); + API_FCT(dig_node); + API_FCT(get_inventory); + API_FCT(set_keypress); + API_FCT(drop_selected_item); + API_FCT(get_objects_inside_radius); + API_FCT(make_screenshot); + } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 5dc3efdad..845f09bc9 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -105,6 +105,30 @@ private: // get_csm_restrictions() static int l_get_csm_restrictions(lua_State *L); + // send_damage(damage) + static int l_send_damage(lua_State *L); + + // place_node(pos) + static int l_place_node(lua_State *L); + + // dig_node(pos) + static int l_dig_node(lua_State *L); + + // get_inventory(location) + static int l_get_inventory(lua_State *L); + + // set_keypress(key_setting, pressed) + static int l_set_keypress(lua_State *L); + + // drop_selected_item() + static int l_drop_selected_item(lua_State *L); + + // get_objects_inside_radius(pos, radius) + static int l_get_objects_inside_radius(lua_State *L); + + // make_screenshot() + static int l_make_screenshot(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_clientobject.cpp b/src/script/lua_api/l_clientobject.cpp new file mode 100644 index 000000000..70151ba40 --- /dev/null +++ b/src/script/lua_api/l_clientobject.cpp @@ -0,0 +1,236 @@ +/* +Dragonfire +Copyright (C) 2020 system32 + +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 "lua_api/l_clientobject.h" +#include "l_internal.h" +#include "common/c_converter.h" +#include "client/client.h" +#include "object_properties.h" +#include "util/pointedthing.h" + +ClientObjectRef *ClientObjectRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *userdata = luaL_checkudata(L, narg, className); + if (!userdata) + luaL_typerror(L, narg, className); + return *(ClientObjectRef **)userdata; +} + +ClientActiveObject *ClientObjectRef::get_cao(ClientObjectRef *ref) +{ + ClientActiveObject *obj = ref->m_object; + return obj; +} + +GenericCAO *ClientObjectRef::get_generic_cao(ClientObjectRef *ref, lua_State *L) +{ + ClientActiveObject *obj = get_cao(ref); + ClientEnvironment &env = getClient(L)->getEnv(); + GenericCAO *gcao = env.getGenericCAO(obj->getId()); + return gcao; +} + +int ClientObjectRef::l_get_pos(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + ClientActiveObject *cao = get_cao(ref); + push_v3f(L, cao->getPosition() / BS); + return 1; +} + +int ClientObjectRef::l_get_velocity(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + push_v3f(L, gcao->getVelocity() / BS); + return 1; +} + +int ClientObjectRef::l_get_acceleration(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + push_v3f(L, gcao->getAcceleration() / BS); + return 1; +} + +int ClientObjectRef::l_get_rotation(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + push_v3f(L, gcao->getRotation()); + return 1; +} + +int ClientObjectRef::l_is_player(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + lua_pushboolean(L, gcao->isPlayer()); + return 1; +} + +int ClientObjectRef::l_is_local_player(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + lua_pushboolean(L, gcao->isLocalPlayer()); + return 1; +} + +int ClientObjectRef::l_get_name(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + lua_pushstring(L, gcao->getName().c_str()); + return 1; +} + +int ClientObjectRef::l_get_attach(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + create(L, gcao->getParent()); + return 1; +} + +int ClientObjectRef::l_get_nametag(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + ObjectProperties *props = gcao->getProperties(); + lua_pushstring(L, props->nametag.c_str()); + return 1; +} + +int ClientObjectRef::l_get_item_textures(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + ObjectProperties *props = gcao->getProperties(); + lua_newtable(L); + + for (std::string &texture : props->textures) { + lua_pushstring(L, texture.c_str()); + } + return 1; +} + +int ClientObjectRef::l_get_hp(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + lua_pushnumber(L, gcao->getHp()); + return 1; +} + +int ClientObjectRef::l_get_max_hp(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + ObjectProperties *props = gcao->getProperties(); + lua_pushnumber(L, props->hp_max); + return 1; +} + +int ClientObjectRef::l_punch(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0); + getClient(L)->interact(INTERACT_START_DIGGING, pointed); + return 0; +} + +int ClientObjectRef::l_rightclick(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0); + getClient(L)->interact(INTERACT_PLACE, pointed); + return 0; +} + +ClientObjectRef::ClientObjectRef(ClientActiveObject *object) : m_object(object) +{ +} + +void ClientObjectRef::create(lua_State *L, ClientActiveObject *object) +{ + if (object) { + ClientObjectRef *o = new ClientObjectRef(object); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + } +} + +void ClientObjectRef::create(lua_State *L, s16 id) +{ + create(L, ((ClientEnvironment *)getEnv(L))->getActiveObject(id)); +} + +int ClientObjectRef::gc_object(lua_State *L) +{ + ClientObjectRef *obj = *(ClientObjectRef **)(lua_touserdata(L, 1)); + delete obj; + return 0; +} + +// taken from LuaLocalPlayer +void ClientObjectRef::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // Drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // Drop methodtable +} + +const char ClientObjectRef::className[] = "ClientObjectRef"; +luaL_Reg ClientObjectRef::methods[] = {luamethod(ClientObjectRef, get_pos), + luamethod(ClientObjectRef, get_velocity), + luamethod(ClientObjectRef, get_acceleration), + luamethod(ClientObjectRef, get_rotation), + luamethod(ClientObjectRef, is_player), + luamethod(ClientObjectRef, is_local_player), + luamethod(ClientObjectRef, get_name), + luamethod(ClientObjectRef, get_attach), + luamethod(ClientObjectRef, get_nametag), + luamethod(ClientObjectRef, get_item_textures), + luamethod(ClientObjectRef, get_hp), + luamethod(ClientObjectRef, get_max_hp), luamethod(ClientObjectRef, punch), + luamethod(ClientObjectRef, rightclick), {0, 0}}; diff --git a/src/script/lua_api/l_clientobject.h b/src/script/lua_api/l_clientobject.h new file mode 100644 index 000000000..d622dc3b2 --- /dev/null +++ b/src/script/lua_api/l_clientobject.h @@ -0,0 +1,90 @@ +/* +Dragonfire +Copyright (C) 2020 system32 + +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 "lua_api/l_base.h" +#include "client/clientobject.h" +#include "client/content_cao.h" + +class ClientObjectRef : public ModApiBase +{ +public: + ClientObjectRef(ClientActiveObject *object); + + ~ClientObjectRef() = default; + + static void Register(lua_State *L); + + static void create(lua_State *L, ClientActiveObject *object); + static void create(lua_State *L, s16 id); + + static ClientObjectRef *checkobject(lua_State *L, int narg); + +private: + ClientActiveObject *m_object = nullptr; + static const char className[]; + static luaL_Reg methods[]; + + static ClientActiveObject *get_cao(ClientObjectRef *ref); + static GenericCAO *get_generic_cao(ClientObjectRef *ref, lua_State *L); + + static int gc_object(lua_State *L); + + // get_pos(self) + // returns: {x=num, y=num, z=num} + static int l_get_pos(lua_State *L); + + // get_velocity(self) + static int l_get_velocity(lua_State *L); + + // get_acceleration(self) + static int l_get_acceleration(lua_State *L); + + // get_rotation(self) + static int l_get_rotation(lua_State *L); + + // is_player(self) + static int l_is_player(lua_State *L); + + // is_local_player(self) + static int l_is_local_player(lua_State *L); + + // get_name(self) + static int l_get_name(lua_State *L); + + // get_attach(self) + static int l_get_attach(lua_State *L); + + // get_nametag(self) + static int l_get_nametag(lua_State *L); + + // get_textures(self) + static int l_get_item_textures(lua_State *L); + + // get_hp(self) + static int l_get_hp(lua_State *L); + + // get_max_hp(self) + static int l_get_max_hp(lua_State *L); + + // punch(self) + static int l_punch(lua_State *L); + + // rightclick(self) + static int l_rightclick(lua_State *L); +}; diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 021ef2ea7..dbb0a5ab7 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -823,7 +823,6 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) int radius = luaL_checkinteger(L, 2); std::vector<content_t> filter; collectNodeIds(L, 3, ndef, filter); - int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; #ifndef SERVER @@ -846,6 +845,165 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) return 0; } +// find_nodes_near(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + auto it = std::find(filter.begin(), filter.end(), c); + if (it != filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + +// find_nodes_near_under_air(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near_under_air(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + v3s16 psurf(p.X, p.Y + 1, p.Z); + content_t csurf = map.getNode(psurf).getContent(); + if (c == CONTENT_AIR || csurf != CONTENT_AIR) + continue; + auto it = std::find(filter.begin(), filter.end(), c); + if (it != filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + +// find_nodes_near_under_air_except(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near_under_air_except(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + v3s16 psurf(p.X, p.Y + 1, p.Z); + content_t csurf = map.getNode(psurf).getContent(); + if (c == CONTENT_AIR || csurf != CONTENT_AIR) + continue; + auto it = std::find(filter.begin(), filter.end(), c); + if (it == filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + // find_nodes_in_area(minp, maxp, nodenames, [grouped]) int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) { @@ -1248,7 +1406,7 @@ int ModApiEnvMod::l_delete_area(lua_State *L) // max_jump, max_drop, algorithm) -> table containing path int ModApiEnvMod::l_find_path(lua_State *L) { - GET_ENV_PTR; + Environment *env = getEnv(L); v3s16 pos1 = read_v3s16(L, 1); v3s16 pos2 = read_v3s16(L, 2); @@ -1265,8 +1423,8 @@ int ModApiEnvMod::l_find_path(lua_State *L) if (algorithm == "Dijkstra") algo = PA_DIJKSTRA; } - - std::vector<v3s16> path = get_path(&env->getServerMap(), env->getGameDef()->ndef(), pos1, pos2, + + std::vector<v3s16> path = get_path(&env->getMap(), env->getGameDef()->ndef(), pos1, pos2, searchdistance, max_jump, max_drop, algo); if (!path.empty()) { @@ -1447,8 +1605,12 @@ void ModApiEnvMod::InitializeClient(lua_State *L, int top) API_FCT(get_node_level); API_FCT(find_nodes_with_meta); API_FCT(find_node_near); + API_FCT(find_nodes_near); + API_FCT(find_nodes_near_under_air); + API_FCT(find_nodes_near_under_air_except); API_FCT(find_nodes_in_area); API_FCT(find_nodes_in_area_under_air); + API_FCT(find_path); API_FCT(line_of_sight); API_FCT(raycast); } diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 7f212b5fc..ad9a0f509 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -131,6 +131,18 @@ private: // find_node_near(pos, radius, nodenames, search_center) -> pos or nil // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" static int l_find_node_near(lua_State *L); + + // find_nodes_near(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near(lua_State *L); + + // find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near_under_air(lua_State *L); + + // find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near_under_air_except(lua_State *L); // find_nodes_in_area(minp, maxp, nodenames) -> list of positions // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp index 5ea3b3f99..0bf9cfbad 100644 --- a/src/script/lua_api/l_http.cpp +++ b/src/script/lua_api/l_http.cpp @@ -239,18 +239,8 @@ int ModApiHttp::l_get_http_api(lua_State *L) void ModApiHttp::Initialize(lua_State *L, int top) { #if USE_CURL - - bool isMainmenu = false; -#ifndef SERVER - isMainmenu = ModApiBase::getGuiEngine(L) != nullptr; -#endif - - if (isMainmenu) { - API_FCT(get_http_api); - } else { - API_FCT(request_http_api); - } - + API_FCT(get_http_api); + API_FCT(request_http_api); #endif } diff --git a/src/script/lua_api/l_inventoryaction.cpp b/src/script/lua_api/l_inventoryaction.cpp new file mode 100644 index 000000000..f65137465 --- /dev/null +++ b/src/script/lua_api/l_inventoryaction.cpp @@ -0,0 +1,215 @@ +/* +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 "l_inventoryaction.h" +#include "l_internal.h" +#include "client/client.h" + +int LuaInventoryAction::gc_object(lua_State *L) +{ + LuaInventoryAction *o = *(LuaInventoryAction **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +int LuaInventoryAction::mt_tostring(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + std::ostringstream os(std::ios::binary); + o->m_action->serialize(os); + lua_pushfstring(L, "InventoryAction(\"%s\")", os.str().c_str()); + return 1; +} + +int LuaInventoryAction::l_apply(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + std::ostringstream os(std::ios::binary); + o->m_action->serialize(os); + + std::istringstream is(os.str(), std::ios_base::binary); + + InventoryAction *a = InventoryAction::deSerialize(is); + + getClient(L)->inventoryAction(a); + return 0; +} + +int LuaInventoryAction::l_from(lua_State *L) +{ + GET_MOVE_ACTION + readFullInventoryLocationInto(L, &act->from_inv, &act->from_list, &act->from_i); + return 0; +} + +int LuaInventoryAction::l_to(lua_State *L) +{ + GET_MOVE_ACTION + readFullInventoryLocationInto(L, &act->to_inv, &act->to_list, &act->to_i); + return 0; +} + +int LuaInventoryAction::l_craft(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + if (o->m_action->getType() != IAction::Craft) + return 0; + + std::string locStr; + InventoryLocation loc; + + locStr = readParam<std::string>(L, 2); + + try { + loc.deSerialize(locStr); + dynamic_cast<ICraftAction *>(o->m_action)->craft_inv = loc; + } catch (SerializationError &) { + } + + return 0; +} + +int LuaInventoryAction::l_set_count(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + s16 count = luaL_checkinteger(L, 2); + + switch (o->m_action->getType()) { + case IAction::Move: + ((IMoveAction *)o->m_action)->count = count; + break; + case IAction::Drop: + ((IDropAction *)o->m_action)->count = count; + break; + case IAction::Craft: + ((ICraftAction *)o->m_action)->count = count; + break; + } + + return 0; +} + +LuaInventoryAction::LuaInventoryAction(const IAction &type) : m_action(nullptr) +{ + switch (type) { + case IAction::Move: + m_action = new IMoveAction(); + break; + case IAction::Drop: + m_action = new IDropAction(); + break; + case IAction::Craft: + m_action = new ICraftAction(); + break; + } +} + +LuaInventoryAction::~LuaInventoryAction() +{ + delete m_action; +} + +void LuaInventoryAction::readFullInventoryLocationInto( + lua_State *L, InventoryLocation *loc, std::string *list, s16 *index) +{ + try { + loc->deSerialize(readParam<std::string>(L, 2)); + std::string l = readParam<std::string>(L, 3); + *list = l; + *index = luaL_checkinteger(L, 4) - 1; + } catch (SerializationError &) { + } +} + +int LuaInventoryAction::create_object(lua_State *L) +{ + IAction type; + std::string typeStr; + + typeStr = readParam<std::string>(L, 1); + + if (typeStr == "move") + type = IAction::Move; + else if (typeStr == "drop") + type = IAction::Drop; + else if (typeStr == "craft") + type = IAction::Craft; + else + return 0; + + LuaInventoryAction *o = new LuaInventoryAction(type); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +int LuaInventoryAction::create(lua_State *L, const IAction &type) +{ + LuaInventoryAction *o = new LuaInventoryAction(type); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaInventoryAction *LuaInventoryAction::checkobject(lua_State *L, int narg) +{ + return *(LuaInventoryAction **)luaL_checkudata(L, narg, className); +} + +void LuaInventoryAction::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, mt_tostring); + lua_settable(L, metatable); + + lua_pop(L, 1); + + luaL_openlib(L, 0, methods, 0); + lua_pop(L, 1); + + lua_register(L, className, create_object); +} + +const char LuaInventoryAction::className[] = "InventoryAction"; +const luaL_Reg LuaInventoryAction::methods[] = {luamethod(LuaInventoryAction, apply), + luamethod(LuaInventoryAction, from), luamethod(LuaInventoryAction, to), + luamethod(LuaInventoryAction, craft), + luamethod(LuaInventoryAction, set_count), {0, 0}}; diff --git a/src/script/lua_api/l_inventoryaction.h b/src/script/lua_api/l_inventoryaction.h new file mode 100644 index 000000000..a4cc6cbe5 --- /dev/null +++ b/src/script/lua_api/l_inventoryaction.h @@ -0,0 +1,74 @@ +/* +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 "inventorymanager.h" +#include "lua_api/l_base.h" + +#define GET_MOVE_ACTION \ + LuaInventoryAction *o = checkobject(L, 1); \ + if (o->m_action->getType() == IAction::Craft) \ + return 0; \ + MoveAction *act = dynamic_cast<MoveAction *>(o->m_action); + +class LuaInventoryAction : public ModApiBase +{ +private: + InventoryAction *m_action; + + static void readFullInventoryLocationInto(lua_State *L, InventoryLocation *loc, + std::string *list, s16 *index); + + static const char className[]; + static const luaL_Reg methods[]; + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // __tostring metamethod + static int mt_tostring(lua_State *L); + + // apply(self) + static int l_apply(lua_State *L); + + // from(self, location, list, index) + static int l_from(lua_State *L); + + // to(self, location, list, index) + static int l_to(lua_State *L); + + // craft(self, location) + static int l_craft(lua_State *L); + + // set_count(self, count) + static int l_set_count(lua_State *L); + +public: + LuaInventoryAction(const IAction &type); + ~LuaInventoryAction(); + + // LuaInventoryAction(inventory action type) + // Creates an LuaInventoryAction and leaves it on top of stack + static int create_object(lua_State *L); + // Not callable from Lua + static int create(lua_State *L, const IAction &type); + static LuaInventoryAction *checkobject(lua_State *L, int narg); + static void Register(lua_State *L); +}; diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index 9e0da4034..b098eccf0 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -27,7 +27,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server.h" #include "inventory.h" #include "log.h" - +#include "script/cpp_api/s_base.h" +#ifndef SERVER +#include "client/client.h" +#include "client/renderingengine.h" +#include "client/shader.h" +#endif // garbage collector int LuaItemStack::gc_object(lua_State *L) @@ -534,9 +539,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) // Get the writable item and node definition managers from the server IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); NodeDefManager *ndef = - getServer(L)->getWritableNodeDefManager(); + getGameDef(L)->getWritableNodeDefManager(); // Check if name is defined std::string name; @@ -584,8 +589,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) + itos(MAX_REGISTERED_CONTENT+1) + ") exceeded (" + name + ")"); } + } - + return 0; /* number of results */ } @@ -596,12 +602,12 @@ int ModApiItemMod::l_unregister_item_raw(lua_State *L) std::string name = luaL_checkstring(L, 1); IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); // Unregister the node if (idef->get(name).type == ITEM_NODE) { NodeDefManager *ndef = - getServer(L)->getWritableNodeDefManager(); + getGameDef(L)->getWritableNodeDefManager(); ndef->removeNode(name); } @@ -619,7 +625,7 @@ int ModApiItemMod::l_register_alias_raw(lua_State *L) // Get the writable item definition manager from the server IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); idef->registerAlias(name, convert_to); diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 33fa27c8b..3f4147227 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "l_clientobject.h" #include "l_localplayer.h" #include "l_internal.h" #include "lua_api/l_item.h" @@ -24,7 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/localplayer.h" #include "hud.h" #include "common/c_content.h" +#include "client/client.h" #include "client/content_cao.h" +#include "client/game.h" LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m) { @@ -60,6 +63,57 @@ int LuaLocalPlayer::l_get_velocity(lua_State *L) return 1; } +int LuaLocalPlayer::l_set_velocity(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + v3f pos = checkFloatPos(L, 2); + player->setSpeed(pos); + + return 0; +} + +int LuaLocalPlayer::l_get_yaw(lua_State *L) +{ + lua_pushnumber(L, wrapDegrees_0_360(g_game->cam_view.camera_yaw)); + return 1; +} + +int LuaLocalPlayer::l_set_yaw(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + if (lua_isnumber(L, 2)) { + int yaw = lua_tonumber(L, 2); + player->setYaw(yaw); + g_game->cam_view.camera_yaw = yaw; + g_game->cam_view_target.camera_yaw = yaw; + } + + return 0; +} + +int LuaLocalPlayer::l_get_pitch(lua_State *L) +{ + lua_pushnumber(L, -wrapDegrees_180(g_game->cam_view.camera_pitch) ); + return 1; +} + +int LuaLocalPlayer::l_set_pitch(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + if (lua_isnumber(L, 2)) { + int pitch = lua_tonumber(L, 2); + player->setPitch(pitch); + g_game->cam_view.camera_pitch = pitch; + g_game->cam_view_target.camera_pitch = pitch; + } + + return 0; +} + + int LuaLocalPlayer::l_get_hp(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -81,10 +135,24 @@ int LuaLocalPlayer::l_get_wield_index(lua_State *L) { LocalPlayer *player = getobject(L, 1); - lua_pushinteger(L, player->getWieldIndex()); + lua_pushinteger(L, player->getWieldIndex() + 1); return 1; } +// set_wield_index(self) +int LuaLocalPlayer::l_set_wield_index(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + u32 index = luaL_checkinteger(L, 2) - 1; + + player->setWieldIndex(index); + g_game->processItemSelection(&g_game->runData.new_playeritem); + ItemStack selected_item, hand_item; + ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); + g_game->camera->wield(tool_item); + return 0; +} + // get_wielded_item(self) int LuaLocalPlayer::l_get_wielded_item(lua_State *L) { @@ -157,26 +225,30 @@ int LuaLocalPlayer::l_get_physics_override(lua_State *L) { LocalPlayer *player = getobject(L, 1); - lua_newtable(L); - lua_pushnumber(L, player->physics_override_speed); - lua_setfield(L, -2, "speed"); - - lua_pushnumber(L, player->physics_override_jump); - lua_setfield(L, -2, "jump"); - - lua_pushnumber(L, player->physics_override_gravity); - lua_setfield(L, -2, "gravity"); - - lua_pushboolean(L, player->physics_override_sneak); - lua_setfield(L, -2, "sneak"); - - lua_pushboolean(L, player->physics_override_sneak_glitch); - lua_setfield(L, -2, "sneak_glitch"); + push_physics_override(L, player->physics_override_speed, player->physics_override_jump, player->physics_override_gravity, player->physics_override_sneak, player->physics_override_sneak_glitch, player->physics_override_new_move); + + return 1; +} - lua_pushboolean(L, player->physics_override_new_move); - lua_setfield(L, -2, "new_move"); +// set_physics_override(self, override) +int LuaLocalPlayer::l_set_physics_override(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + player->physics_override_speed = getfloatfield_default( + L, 2, "speed", player->physics_override_speed); + player->physics_override_jump = getfloatfield_default( + L, 2, "jump", player->physics_override_jump); + player->physics_override_gravity = getfloatfield_default( + L, 2, "gravity", player->physics_override_gravity); + player->physics_override_sneak = getboolfield_default( + L, 2, "sneak", player->physics_override_sneak); + player->physics_override_sneak_glitch = getboolfield_default( + L, 2, "sneak_glitch", player->physics_override_sneak_glitch); + player->physics_override_new_move = getboolfield_default( + L, 2, "new_move", player->physics_override_new_move); - return 1; + return 0; } int LuaLocalPlayer::l_get_last_pos(lua_State *L) @@ -255,6 +327,17 @@ int LuaLocalPlayer::l_get_pos(lua_State *L) return 1; } +// set_pos(self, pos) +int LuaLocalPlayer::l_set_pos(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + v3f pos = checkFloatPos(L, 2); + player->setPosition(pos); + getClient(L)->sendPlayerPos(); + return 0; +} + // get_movement_acceleration(self) int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L) { @@ -393,6 +476,17 @@ int LuaLocalPlayer::l_hud_get(lua_State *L) return 1; } +int LuaLocalPlayer::l_get_object(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + ClientEnvironment &env = getClient(L)->getEnv(); + ClientActiveObject *obj = env.getGenericCAO(player->getCAO()->getId()); + + ClientObjectRef::create(L, obj); + + return 1; +} + LuaLocalPlayer *LuaLocalPlayer::checkobject(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TUSERDATA); @@ -453,9 +547,15 @@ void LuaLocalPlayer::Register(lua_State *L) const char LuaLocalPlayer::className[] = "LocalPlayer"; const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_velocity), + luamethod(LuaLocalPlayer, set_velocity), + luamethod(LuaLocalPlayer, get_yaw), + luamethod(LuaLocalPlayer, set_yaw), + luamethod(LuaLocalPlayer, get_pitch), + luamethod(LuaLocalPlayer, set_pitch), luamethod(LuaLocalPlayer, get_hp), luamethod(LuaLocalPlayer, get_name), luamethod(LuaLocalPlayer, get_wield_index), + luamethod(LuaLocalPlayer, set_wield_index), luamethod(LuaLocalPlayer, get_wielded_item), luamethod(LuaLocalPlayer, is_attached), luamethod(LuaLocalPlayer, is_touching_ground), @@ -465,6 +565,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, is_climbing), luamethod(LuaLocalPlayer, swimming_vertical), luamethod(LuaLocalPlayer, get_physics_override), + luamethod(LuaLocalPlayer, set_physics_override), // TODO: figure our if these are useful in any way luamethod(LuaLocalPlayer, get_last_pos), luamethod(LuaLocalPlayer, get_last_velocity), @@ -474,6 +575,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_control), luamethod(LuaLocalPlayer, get_breath), luamethod(LuaLocalPlayer, get_pos), + luamethod(LuaLocalPlayer, set_pos), luamethod(LuaLocalPlayer, get_movement_acceleration), luamethod(LuaLocalPlayer, get_movement_speed), luamethod(LuaLocalPlayer, get_movement), @@ -482,6 +584,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, hud_remove), luamethod(LuaLocalPlayer, hud_change), luamethod(LuaLocalPlayer, hud_get), + luamethod(LuaLocalPlayer, get_object), {0, 0} }; diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h index 4413f2bdb..33e23d178 100644 --- a/src/script/lua_api/l_localplayer.h +++ b/src/script/lua_api/l_localplayer.h @@ -35,6 +35,21 @@ private: // get_velocity(self) static int l_get_velocity(lua_State *L); + // set_velocity(self, vel) + static int l_set_velocity(lua_State *L); + + // get_yaw(self) + static int l_get_yaw(lua_State *L); + + // set_yaw(self, yaw) + static int l_set_yaw(lua_State *L); + + // get_pitch(self) + static int l_get_pitch(lua_State *L); + + // set_pitch(self,pitch) + static int l_set_pitch(lua_State *L); + // get_hp(self) static int l_get_hp(lua_State *L); @@ -44,6 +59,9 @@ private: // get_wield_index(self) static int l_get_wield_index(lua_State *L); + // set_wield_index(self) + static int l_set_wield_index(lua_State *L); + // get_wielded_item(self) static int l_get_wielded_item(lua_State *L); @@ -56,6 +74,7 @@ private: static int l_swimming_vertical(lua_State *L); static int l_get_physics_override(lua_State *L); + static int l_set_physics_override(lua_State *L); static int l_get_override_pos(lua_State *L); @@ -73,6 +92,9 @@ private: // get_pos(self) static int l_get_pos(lua_State *L); + // set_pos(self, pos) + static int l_set_pos(lua_State *L); + // get_movement_acceleration(self) static int l_get_movement_acceleration(lua_State *L); @@ -96,6 +118,9 @@ private: // hud_get(self, id) static int l_hud_get(lua_State *L); + // get_object(self) + static int l_get_object(lua_State *L); + LocalPlayer *m_localplayer = nullptr; public: diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 0aa2760e9..2cf4a979b 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -902,6 +902,9 @@ bool ModApiMainMenu::mayModifyPath(const std::string &path) if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "mods"))) return true; + if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "clientmods"))) + return true; + if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "textures"))) return true; diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 6f934bb9d..64ae924d2 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -338,6 +338,7 @@ int ModApiServer::l_kick_player(lua_State *L) return 1; } +// remove_player(name) int ModApiServer::l_remove_player(lua_State *L) { NO_MAP_LOCK_REQUIRED; @@ -562,7 +563,6 @@ void ModApiServer::Initialize(lua_State *L, int top) API_FCT(get_ban_description); API_FCT(ban_player); API_FCT(kick_player); - API_FCT(remove_player); API_FCT(unban_player_or_ip); API_FCT(notify_authentication_modified); diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index cd63e20c2..4595dc1c1 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -527,15 +527,20 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(is_yes); API_FCT(is_nan); - + API_FCT(compress); API_FCT(decompress); + API_FCT(request_insecure_environment); + API_FCT(encode_base64); API_FCT(decode_base64); API_FCT(get_version); API_FCT(sha1); + + LuaSettings::create(L, g_settings, g_settings_path); + lua_setfield(L, top, "settings"); } void ModApiUtil::InitializeAsync(lua_State *L, int top) diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp index 6643a9509..729645678 100644 --- a/src/script/scripting_client.cpp +++ b/src/script/scripting_client.cpp @@ -20,9 +20,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "scripting_client.h" #include "client/client.h" +#include "client/game.h" #include "cpp_api/s_internal.h" #include "lua_api/l_client.h" +#include "lua_api/l_clientobject.h" #include "lua_api/l_env.h" +#include "lua_api/l_inventoryaction.h" #include "lua_api/l_item.h" #include "lua_api/l_itemstackmeta.h" #include "lua_api/l_minimap.h" @@ -35,11 +38,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_nodemeta.h" #include "lua_api/l_localplayer.h" #include "lua_api/l_camera.h" +#include "lua_api/l_settings.h" +#include "lua_api/l_http.h" ClientScripting::ClientScripting(Client *client): ScriptApiBase(ScriptingType::Client) { setGameDef(client); + setGame(g_game); SCRIPTAPI_PRECHECKHEADER @@ -73,8 +79,13 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) LuaLocalPlayer::Register(L); LuaCamera::Register(L); ModChannelRef::Register(L); + LuaSettings::Register(L); + ClientObjectRef::Register(L); + LuaInventoryAction::Register(L); + ModApiItemMod::Initialize(L, top); ModApiUtil::InitializeClient(L, top); + ModApiHttp::Initialize(L, top); ModApiClient::Initialize(L, top); ModApiStorage::Initialize(L, top); ModApiEnvMod::InitializeClient(L, top); diff --git a/src/script/scripting_client.h b/src/script/scripting_client.h index 3088029f0..e162f8bcf 100644 --- a/src/script/scripting_client.h +++ b/src/script/scripting_client.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_base.h" #include "cpp_api/s_client.h" +#include "cpp_api/s_cheats.h" #include "cpp_api/s_modchannels.h" #include "cpp_api/s_security.h" @@ -34,7 +35,8 @@ class ClientScripting: virtual public ScriptApiBase, public ScriptApiSecurity, public ScriptApiClient, - public ScriptApiModChannels + public ScriptApiModChannels, + public ScriptApiCheats { public: ClientScripting(Client *client); |