From 92b45b2a189b703fc7cfc8ddbc09a7ad563a13bc Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Fri, 27 Jan 2017 07:41:10 +0100 Subject: [CSM] implement client side mod loading (#5123) * client side mods are located in clientmods/ * move builtin/preview.lua to clientmods/preview/init.lua as a preview mod * refactor ModConfiguration class to work properly with client and server using child objects * move some Server constructor mod load code to ModConfiguration to reduce code duplication between client and server * remove mods.{cpp,h} unused functions * use UNORDERED_SET instead of std::set in some modspec storages --- clientmods/preview/init.lua | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 clientmods/preview/init.lua (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua new file mode 100644 index 000000000..4c01d665f --- /dev/null +++ b/clientmods/preview/init.lua @@ -0,0 +1,42 @@ +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_on_shutdown(function() + print("[PREVIEW] shutdown client") +end) + +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_on_receiving_chat_messages(function(message) + print("[PREVIEW] Received message " .. message) + return false +end) + +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_on_sending_chat_messages(function(message) + print("[PREVIEW] Sending message " .. message) + return false +end) + +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_on_hp_modification(function(hp) + print("[PREVIEW] HP modified " .. hp) +end) + +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_on_damage_taken(function(hp) + print("[PREVIEW] Damage taken " .. hp) +end) + +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_globalstep(function(dtime) + -- print("[PREVIEW] globalstep " .. dtime) +end) + +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_chatcommand("dump", { + func = function(param) + return true, dump(_G) + end, +}) + +core.after(2, function() + print("After 2") +end) -- cgit v1.2.3 From ba66fce8339f818a638f97679bd29da064a8c1c6 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Sat, 28 Jan 2017 18:31:23 +0100 Subject: [CSM] storage + fixes --- clientmods/preview/init.lua | 4 +++- src/script/clientscripting.cpp | 2 ++ src/script/lua_api/CMakeLists.txt | 1 + src/script/lua_api/l_client.h | 3 +-- src/script/lua_api/l_util.cpp | 6 ------ src/server.cpp | 2 +- src/server.h | 2 +- 7 files changed, 9 insertions(+), 11 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 4c01d665f..f03e8e112 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -1,3 +1,5 @@ +local modname = core.get_current_modname() or "??" + -- This is an example function to ensure it's working properly, should be removed before merge core.register_on_shutdown(function() print("[PREVIEW] shutdown client") @@ -38,5 +40,5 @@ core.register_chatcommand("dump", { }) core.after(2, function() - print("After 2") + print("[PREVIEW] loaded " .. modname .. " mod") end) diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index 390d21a3a..aaed2865d 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "cpp_api/s_internal.h" #include "lua_api/l_client.h" +#include "lua_api/l_storage.h" #include "lua_api/l_sound.h" #include "lua_api/l_util.h" @@ -53,4 +54,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) ModApiUtil::InitializeClient(L, top); ModApiClient::Initialize(L, top); ModApiSound::Initialize(L, top); + ModApiStorage::Initialize(L, top); } diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index 17bcdde4c..2d25d845c 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -25,5 +25,6 @@ set(common_SCRIPT_LUA_API_SRCS set(client_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp PARENT_SCOPE) diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 14ef5aecc..d0e230630 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -23,8 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_base.h" -class ModApiClient: - public ModApiBase +class ModApiClient: public ModApiBase { private: // get_current_modname() diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index b9c334121..809a2eb68 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -532,12 +532,6 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(get_us_time); - API_FCT(setting_set); - API_FCT(setting_get); - API_FCT(setting_setbool); - API_FCT(setting_getbool); - API_FCT(setting_save); - API_FCT(parse_json); API_FCT(write_json); diff --git a/src/server.cpp b/src/server.cpp index dd6c9a418..293b32a81 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3400,7 +3400,7 @@ void Server::getModNames(std::vector &modlist) modlist.push_back(it->name); } -const std::string Server::getBuiltinLuaPath() +std::string Server::getBuiltinLuaPath() { return porting::path_share + DIR_DELIM + "builtin"; } diff --git a/src/server.h b/src/server.h index 417d31bd8..f0bab1bbf 100644 --- a/src/server.h +++ b/src/server.h @@ -299,7 +299,7 @@ public: virtual const ModSpec* getModSpec(const std::string &modname) const; void getModNames(std::vector &modlist); std::string getBuiltinLuaPath(); - inline const std::string &getWorldPath() const { return m_path_world; } + std::string getWorldPath() const { return m_path_world; } std::string getModStoragePath() const; inline bool isSingleplayer() -- cgit v1.2.3 From 073f5cf03d95ce1cdf04ce8a0adcaf1fc571d95f Mon Sep 17 00:00:00 2001 From: red-001 Date: Sun, 29 Jan 2017 17:43:44 +0000 Subject: [CSM] Add `on_dignode` callback (#5140) --- builtin/client/register.lua | 1 + clientmods/preview/init.lua | 6 ++++++ doc/client_lua_api.txt | 4 ++++ src/game.cpp | 34 +++++++++++++++++++++------------- src/script/cpp_api/s_client.cpp | 22 ++++++++++++++++++++++ src/script/cpp_api/s_client.h | 3 +++ 6 files changed, 57 insertions(+), 13 deletions(-) (limited to 'clientmods') diff --git a/builtin/client/register.lua b/builtin/client/register.lua index c932fb9f8..c8a5ddbda 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -66,5 +66,6 @@ core.registered_on_death, core.register_on_death = make_registration() core.registered_on_hp_modification, core.register_on_hp_modification = make_registration() core.registered_on_damage_taken, core.register_on_damage_taken = make_registration() core.registered_on_formspec_input, core.register_on_formspec_input = make_registration() +core.registered_on_dignode, core.register_on_dignode = make_registration() diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index f03e8e112..3085eda24 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -42,3 +42,9 @@ core.register_chatcommand("dump", { core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") end) + +core.register_on_dignode(function(pos, node) + print("pos:" .. dump(pos)) + print("node:" .. dump(node)) + return false +end) \ No newline at end of file diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 3170f4c84..886dbc6e1 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -703,6 +703,10 @@ Call these functions only at load time! * Called when a button is pressed in player's inventory form * Newest functions are called first * If function returns `true`, remaining functions are not called +* `minetest.register_on_dignode(func(pos, node))` + * Called when a player digs a node + * Newest functions are called first + * If any function returns true, the node isn't dug ### Sounds * `minetest.sound_play(spec, parameters)`: returns a handle * `spec` is a `SimpleSoundSpec` diff --git a/src/game.cpp b/src/game.cpp index c84e08b01..66c8859c8 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3967,20 +3967,8 @@ void Game::handleDigging(GameRunData *runData, client->setCrack(runData->dig_index, nodepos); } else { infostream << "Digging completed" << std::endl; - client->interact(2, pointed); client->setCrack(-1, v3s16(0, 0, 0)); - bool is_valid_position; - MapNode wasnode = map.getNodeNoEx(nodepos, &is_valid_position); - if (is_valid_position) - client->removeNode(nodepos); - - if (m_cache_enable_particles) { - const ContentFeatures &features = - client->getNodeDefManager()->get(wasnode); - client->getParticleManager()->addDiggingParticles(client, smgr, - player, nodepos, wasnode, features); - } - + runData->dig_time = 0; runData->digging = false; @@ -3999,6 +3987,26 @@ void Game::handleDigging(GameRunData *runData, if (runData->nodig_delay_timer < mindelay) runData->nodig_delay_timer = mindelay; + bool is_valid_position; + MapNode wasnode = map.getNodeNoEx(nodepos, &is_valid_position); + if (is_valid_position) { + bool block = client->getScript()->on_dignode(nodepos, wasnode); + if (block) { + return; + } + client->removeNode(nodepos); + } + + client->interact(2, pointed); + + if (m_cache_enable_particles) { + const ContentFeatures &features = + client->getNodeDefManager()->get(wasnode); + client->getParticleManager()->addDiggingParticles(client, smgr, + player, nodepos, wasnode, features); + } + + // Send event to trigger sound MtEvent *e = new NodeDugEvent(nodepos, wasnode); client->event()->put(e); diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 1827d483b..2c8fee334 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "s_client.h" #include "s_internal.h" #include "client.h" +#include "common/c_converter.h" +#include "common/c_content.h" void ScriptApiClient::on_shutdown() { @@ -136,3 +138,23 @@ void ScriptApiClient::on_formspec_input(const std::string &formname, } runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC); } + +bool ScriptApiClient::on_dignode(v3s16 p, MapNode node) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getClient()->ndef(); + + // Get core.registered_on_dignode + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_dignode"); + + // Push data + push_v3s16(L, p); + pushnode(L, node, ndef); + + // Call functions + runCallbacks(2, RUN_CALLBACKS_MODE_OR); + bool blocked = lua_toboolean(L, -1); + return blocked; +} \ No newline at end of file diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 42c41f8a4..09fd3a691 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_base.h" #include "util/string.h" +#include "mapnode.h" #ifdef _CRT_MSVCP_CURRENT #include @@ -43,5 +44,7 @@ public: void on_death(); void environment_step(float dtime); void on_formspec_input(const std::string &formname, const StringMap &fields); + + bool on_dignode(v3s16 p, MapNode node); }; #endif -- cgit v1.2.3 From 37df9cb7d764891f29b433e80a0d5663fee1a94f Mon Sep 17 00:00:00 2001 From: red-001 Date: Mon, 30 Jan 2017 19:10:37 +0000 Subject: [CSM] Add `get_node` and `get_node_or_nil` --- clientmods/preview/init.lua | 10 +++++++++- doc/client_lua_api.txt | 8 +++++++- src/client.cpp | 5 +++++ src/client.h | 1 + src/script/lua_api/l_client.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/script/lua_api/l_client.h | 8 ++++++++ 6 files changed, 67 insertions(+), 2 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 3085eda24..91b12d810 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -39,6 +39,14 @@ core.register_chatcommand("dump", { end, }) +core.register_chatcommand("test_node", { + func = function(param) + core.display_chat_message(dump(core.get_node({x=0, y=0, z=0}))) + core.display_chat_message(dump(core.get_node_or_nil({x=0, y=0, z=0}))) + end, +}) + + core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") end) @@ -47,4 +55,4 @@ core.register_on_dignode(function(pos, node) print("pos:" .. dump(pos)) print("node:" .. dump(node)) return false -end) \ No newline at end of file +end) diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 886dbc6e1..7b24452e8 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -717,7 +717,13 @@ Call these functions only at load time! * `minetest.after(time, func, ...)` * Call the function `func` after `time` seconds, may be fractional * Optional: Variable number of arguments that are passed to `func` - +### Map +* `minetest.get_node(pos)` + * Returns the node at the given position as table in the format + `{name="node_name", param1=0, param2=0}`, returns `{name="ignore", param1=0, param2=0}` + for unloaded areas. +* `minetest.get_node_or_nil(pos)` + * Same as `get_node` but returns `nil` for unloaded areas. ### Misc. * `minetest.parse_json(string[, nullvalue])`: returns something * Convert a string containing JSON data into the Lua equivalent diff --git a/src/client.cpp b/src/client.cpp index 4bb63fef1..049616c63 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1447,6 +1447,11 @@ void Client::removeNode(v3s16 p) } } +MapNode Client::getNode(v3s16 p, bool *is_valid_position) +{ + return m_env.getMap().getNodeNoEx(p, is_valid_position); +} + void Client::addNode(v3s16 p, MapNode n, bool remove_metadata) { //TimeTaker timer1("Client::addNode()"); diff --git a/src/client.h b/src/client.h index 9b7130268..dc4469350 100644 --- a/src/client.h +++ b/src/client.h @@ -441,6 +441,7 @@ public: // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent) void removeNode(v3s16 p); + MapNode getNode(v3s16 p, bool *is_valid_position); void addNode(v3s16 p, MapNode n, bool remove_metadata = true); void setPlayerControl(PlayerControl &control); diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 9a04bd02f..41e33889c 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "cpp_api/s_base.h" #include "gettext.h" +#include "common/c_converter.h" +#include "common/c_content.h" int ModApiClient::l_get_current_modname(lua_State *L) { @@ -97,6 +99,39 @@ int ModApiClient::l_gettext(lua_State *L) return 1; } +// get_node(pos) +// pos = {x=num, y=num, z=num} +int ModApiClient::l_get_node(lua_State *L) +{ + // pos + v3s16 pos = read_v3s16(L, 1); + // Do it + bool pos_ok; + MapNode n = getClient(L)->getNode(pos, &pos_ok); + // Return node + pushnode(L, n, getClient(L)->ndef()); + return 1; +} + +// get_node_or_nil(pos) +// pos = {x=num, y=num, z=num} +int ModApiClient::l_get_node_or_nil(lua_State *L) +{ + // pos + v3s16 pos = read_v3s16(L, 1); + // Do it + bool pos_ok; + MapNode n = getClient(L)->getNode(pos, &pos_ok); + if (pos_ok) { + // Return node + pushnode(L, n, getClient(L)->ndef()); + } + else { + lua_pushnil(L); + } + return 1; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -106,4 +141,6 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(show_formspec); API_FCT(send_respawn); API_FCT(gettext); + API_FCT(get_node); + API_FCT(get_node_or_nil); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index d0e230630..207a5bca0 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -47,6 +47,14 @@ private: // set_last_run_mod(modname) static int l_set_last_run_mod(lua_State *L); + // get_node(pos) + static int l_get_node(lua_State *L); + + // get_node_or_nil(pos) + static int l_get_node_or_nil(lua_State *L); + + + public: static void Initialize(lua_State *L, int top); }; -- cgit v1.2.3 From 0727bb3ddd9c550ff962af4546bac8cc058bce73 Mon Sep 17 00:00:00 2001 From: red-001 Date: Sun, 29 Jan 2017 18:28:38 +0000 Subject: [CSM] Add `on_punchnode` callback --- builtin/client/register.lua | 3 +-- clientmods/preview/init.lua | 8 ++++++++ doc/client_lua_api.txt | 12 ++++++++---- src/game.cpp | 11 +++++++---- src/script/cpp_api/s_client.cpp | 22 +++++++++++++++++++++- src/script/cpp_api/s_client.h | 1 + 6 files changed, 46 insertions(+), 11 deletions(-) (limited to 'clientmods') diff --git a/builtin/client/register.lua b/builtin/client/register.lua index c8a5ddbda..1c3966eda 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -67,5 +67,4 @@ core.registered_on_hp_modification, core.register_on_hp_modification = make_regi core.registered_on_damage_taken, core.register_on_damage_taken = make_registration() core.registered_on_formspec_input, core.register_on_formspec_input = make_registration() core.registered_on_dignode, core.register_on_dignode = make_registration() - - +core.registered_on_punchnode, core.register_on_punchnode = make_registration() diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 91b12d810..db4f28350 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -52,6 +52,14 @@ core.after(2, function() end) core.register_on_dignode(function(pos, node) + print("The local player dug a node!") + print("pos:" .. dump(pos)) + print("node:" .. dump(node)) + return false +end) + +core.register_on_punchnode(function(pos, node) + print("The local player punched a node!") print("pos:" .. dump(pos)) print("node:" .. dump(node)) return false diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 7b24452e8..5ffffe938 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -694,19 +694,23 @@ Call these functions only at load time! * `minetest.register_chatcommand(cmd, chatcommand definition)` * Adds definition to minetest.registered_chatcommands * `minetest.register_on_death(func())` - * Called when player die + * Called when the local player dies * `minetest.register_on_hp_modification(func(hp))` * Called when server modified player's HP * `minetest.register_on_damage_taken(func(hp))` - * Called when player take damages + * Called when the local player take damages * `minetest.register_on_formspec_input(func(formname, fields))` - * Called when a button is pressed in player's inventory form + * Called when a button is pressed in the local player's inventory form * Newest functions are called first * If function returns `true`, remaining functions are not called * `minetest.register_on_dignode(func(pos, node))` - * Called when a player digs a node + * Called when the local player digs a node * Newest functions are called first * If any function returns true, the node isn't dug +* `minetest.register_on_punchnode(func(pos, node))` + * Called when the local player punches a node + * Newest functions are called first + * If any function returns true, the punch is ignored ### Sounds * `minetest.sound_play(spec, parameters)`: returns a handle * `spec` is a `SimpleSoundSpec` diff --git a/src/game.cpp b/src/game.cpp index 66c8859c8..612bd2536 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3895,17 +3895,20 @@ void Game::handleDigging(GameRunData *runData, const PointedThing &pointed, const v3s16 &nodepos, const ToolCapabilities &playeritem_toolcap, f32 dtime) { + + LocalPlayer *player = client->getEnv().getLocalPlayer(); + ClientMap &map = client->getEnv().getClientMap(); + MapNode n = client->getEnv().getClientMap().getNodeNoEx(nodepos); + if (!runData->digging) { infostream << "Started digging" << std::endl; + if (client->getScript()->on_punchnode(nodepos, n)) + return; client->interact(0, pointed); runData->digging = true; runData->ldown_for_dig = true; } - LocalPlayer *player = client->getEnv().getLocalPlayer(); - ClientMap &map = client->getEnv().getClientMap(); - MapNode n = client->getEnv().getClientMap().getNodeNoEx(nodepos); - // NOTE: Similar piece of code exists on the server side for // cheat detection. // Get digging parameters diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 2c8fee334..8c5e3796b 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -157,4 +157,24 @@ bool ScriptApiClient::on_dignode(v3s16 p, MapNode node) runCallbacks(2, RUN_CALLBACKS_MODE_OR); bool blocked = lua_toboolean(L, -1); return blocked; -} \ No newline at end of file +} + +bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node) +{ + SCRIPTAPI_PRECHECKHEADER + + INodeDefManager *ndef = getClient()->ndef(); + + // Get core.registered_on_punchgnode + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_punchnode"); + + // Push data + push_v3s16(L, p); + pushnode(L, node, ndef); + + // Call functions + runCallbacks(2, RUN_CALLBACKS_MODE_OR); + bool blocked = lua_toboolean(L, -1); + return blocked; +} diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 09fd3a691..93e9558f2 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -46,5 +46,6 @@ public: void on_formspec_input(const std::string &formname, const StringMap &fields); bool on_dignode(v3s16 p, MapNode node); + bool on_punchnode(v3s16 p, MapNode node); }; #endif -- cgit v1.2.3 From 88df9fb5b6c78df9485e8bf3750e2608bd78e14c Mon Sep 17 00:00:00 2001 From: red-001 Date: Tue, 31 Jan 2017 13:18:52 +0000 Subject: Add `get_wielded_item` --- clientmods/preview/init.lua | 22 ++++++++++++++++++++++ doc/client_lua_api.txt | 6 ++++++ src/gamedef.h | 1 + src/script/clientscripting.cpp | 3 +++ src/script/common/c_content.cpp | 7 ++----- src/script/common/c_content.h | 3 ++- src/script/cpp_api/s_item.cpp | 12 ++++++------ src/script/lua_api/l_base.cpp | 6 ++++++ src/script/lua_api/l_base.h | 3 +++ src/script/lua_api/l_client.cpp | 19 +++++++++++++++++++ src/script/lua_api/l_client.h | 3 ++- src/script/lua_api/l_env.cpp | 2 +- src/script/lua_api/l_inventory.cpp | 10 +++++----- src/script/lua_api/l_item.cpp | 26 +++++++++++++------------- src/script/lua_api/l_object.cpp | 2 +- 15 files changed, 92 insertions(+), 33 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index db4f28350..2ca4594d3 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -60,6 +60,28 @@ end) core.register_on_punchnode(function(pos, node) print("The local player punched a node!") + local itemstack = core.get_wielded_item() + --[[ + -- getters + print(dump(itemstack:is_empty())) + print(dump(itemstack:get_name())) + print(dump(itemstack:get_count())) + print(dump(itemstack:get_wear())) + print(dump(itemstack:get_meta())) + print(dump(itemstack:get_metadata())) + print(dump(itemstack:is_known())) + --print(dump(itemstack:get_definition())) + print(dump(itemstack:get_tool_capabilities())) + print(dump(itemstack:to_string())) + print(dump(itemstack:to_table())) + -- setters + print(dump(itemstack:set_name("default:dirt"))) + print(dump(itemstack:set_count("95"))) + print(dump(itemstack:set_wear(934))) + print(dump(itemstack:get_meta())) + print(dump(itemstack:get_metadata())) + --]] + print(dump(itemstack:to_table())) print("pos:" .. dump(pos)) print("node:" .. dump(node)) return false diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 5ffffe938..7440c4014 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -721,6 +721,7 @@ Call these functions only at load time! * `minetest.after(time, func, ...)` * Call the function `func` after `time` seconds, may be fractional * Optional: Variable number of arguments that are passed to `func` + ### Map * `minetest.get_node(pos)` * Returns the node at the given position as table in the format @@ -728,6 +729,11 @@ Call these functions only at load time! for unloaded areas. * `minetest.get_node_or_nil(pos)` * Same as `get_node` but returns `nil` for unloaded areas. + +### Player +* `minetest.get_wielded_item()` + * Returns the itemstack the local player is holding + ### Misc. * `minetest.parse_json(string[, nullvalue])`: returns something * Convert a string containing JSON data into the Lua equivalent diff --git a/src/gamedef.h b/src/gamedef.h index 16b53e24f..593d27e30 100644 --- a/src/gamedef.h +++ b/src/gamedef.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define GAMEDEF_HEADER #include +#include #include "irrlichttypes.h" class IItemDefManager; diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index aaed2865d..c1e308012 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_storage.h" #include "lua_api/l_sound.h" #include "lua_api/l_util.h" +#include "lua_api/l_item.h" ClientScripting::ClientScripting(Client *client): ScriptApiBase() @@ -55,4 +56,6 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) ModApiClient::Initialize(L, top); ModApiSound::Initialize(L, top); ModApiStorage::Initialize(L, top); + + LuaItemStack::Register(L); } diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index a963856b7..99e12cd82 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_converter.h" #include "common/c_types.h" #include "nodedef.h" -#include "itemdef.h" #include "object_properties.h" #include "cpp_api/s_node.h" #include "lua_api/l_object.h" @@ -784,7 +783,7 @@ bool string_to_enum(const EnumString *spec, int &result, } /******************************************************************************/ -ItemStack read_item(lua_State* L, int index,Server* srv) +ItemStack read_item(lua_State* L, int index, IItemDefManager *idef) { if(index < 0) index = lua_gettop(L) + 1 + index; @@ -803,7 +802,6 @@ ItemStack read_item(lua_State* L, int index,Server* srv) { // Convert from itemstring std::string itemstring = lua_tostring(L, index); - IItemDefManager *idef = srv->idef(); try { ItemStack item; @@ -820,7 +818,6 @@ ItemStack read_item(lua_State* L, int index,Server* srv) else if(lua_istable(L, index)) { // Convert from table - IItemDefManager *idef = srv->idef(); std::string name = getstringfield_default(L, index, "name", ""); int count = getintfield_default(L, index, "count", 1); int wear = getintfield_default(L, index, "wear", 0); @@ -1187,7 +1184,7 @@ std::vector read_items(lua_State *L, int index, Server *srv) if (items.size() < (u32) key) { items.resize(key); } - items[key - 1] = read_item(L, -1, srv); + items[key - 1] = read_item(L, -1, srv->idef()); lua_pop(L, 1); } return items; diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 9641f5c9e..10cccbb01 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -38,6 +38,7 @@ extern "C" { #include "irrlichttypes_bloated.h" #include "util/string.h" #include "itemgroup.h" +#include "itemdef.h" namespace Json { class Value; } @@ -77,7 +78,7 @@ void push_dig_params (lua_State *L, void push_hit_params (lua_State *L, const HitParams ¶ms); -ItemStack read_item (lua_State *L, int index, Server *srv); +ItemStack read_item (lua_State *L, int index, IItemDefManager *idef); struct TileAnimationParams read_animation_definition(lua_State *L, int index); diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp index 3c84fb8cf..cbb833807 100644 --- a/src/script/cpp_api/s_item.cpp +++ b/src/script/cpp_api/s_item.cpp @@ -47,7 +47,7 @@ bool ScriptApiItem::item_OnDrop(ItemStack &item, PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if (!lua_isnil(L, -1)) { try { - item = read_item(L,-1, getServer()); + item = read_item(L, -1, getServer()->idef()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } @@ -74,7 +74,7 @@ bool ScriptApiItem::item_OnPlace(ItemStack &item, PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if (!lua_isnil(L, -1)) { try { - item = read_item(L,-1, getServer()); + item = read_item(L, -1, getServer()->idef()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } @@ -101,7 +101,7 @@ bool ScriptApiItem::item_OnUse(ItemStack &item, PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if(!lua_isnil(L, -1)) { try { - item = read_item(L,-1, getServer()); + item = read_item(L, -1, getServer()->idef()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } @@ -127,7 +127,7 @@ bool ScriptApiItem::item_OnSecondaryUse(ItemStack &item, ServerActiveObject *use PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if (!lua_isnil(L, -1)) { try { - item = read_item(L, -1, getServer()); + item = read_item(L, -1, getServer()->idef()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } @@ -159,7 +159,7 @@ bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user, PCALL_RES(lua_pcall(L, 4, 1, error_handler)); if (!lua_isnil(L, -1)) { try { - item = read_item(L,-1, getServer()); + item = read_item(L, -1, getServer()->idef()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } @@ -191,7 +191,7 @@ bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user, PCALL_RES(lua_pcall(L, 4, 1, error_handler)); if (!lua_isnil(L, -1)) { try { - item = read_item(L,-1, getServer()); + item = read_item(L, -1, getServer()->idef()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index f2703718a..dfe743b72 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -43,6 +43,12 @@ Client *ModApiBase::getClient(lua_State *L) return getScriptApiBase(L)->getClient(); } #endif + +IGameDef *ModApiBase::getGameDef(lua_State *L) +{ + return getScriptApiBase(L)->getGameDef(); +} + Environment *ModApiBase::getEnv(lua_State *L) { return getScriptApiBase(L)->getEnv(); diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index dc1b1b226..cd382629d 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_types.h" #include "common/c_internal.h" +#include "gamedef.h" extern "C" { #include @@ -46,6 +47,8 @@ public: static Client* getClient(lua_State *L); #endif // !SERVER + static IGameDef* getGameDef(lua_State *L); + static Environment* getEnv(lua_State *L); static GUIEngine* getGuiEngine(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 41e33889c..1673a62ce 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gettext.h" #include "common/c_converter.h" #include "common/c_content.h" +#include "lua_api/l_item.h" int ModApiClient::l_get_current_modname(lua_State *L) { @@ -132,6 +133,23 @@ int ModApiClient::l_get_node_or_nil(lua_State *L) return 1; } +int ModApiClient::l_get_wielded_item(lua_State *L) +{ + Client *client = getClient(L); + + Inventory local_inventory(client->idef()); + client->getLocalInventory(local_inventory); + + InventoryList *mlist = local_inventory.getList("main"); + + if (mlist && client->getPlayerItem() < mlist->getSize()) { + LuaItemStack::create(L, mlist->getItem(client->getPlayerItem())); + } else { + LuaItemStack::create(L, ItemStack()); + } + return 1; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -143,4 +161,5 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(gettext); API_FCT(get_node); API_FCT(get_node_or_nil); + API_FCT(get_wielded_item); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 207a5bca0..def9b48a3 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -53,7 +53,8 @@ private: // get_node_or_nil(pos) static int l_get_node_or_nil(lua_State *L); - + // get_wielded_item() + static int l_get_wielded_item(lua_State *L); public: static void Initialize(lua_State *L, int top); diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 442c4b99a..14df558d3 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -472,7 +472,7 @@ int ModApiEnvMod::l_add_item(lua_State *L) // pos //v3f pos = checkFloatPos(L, 1); // item - ItemStack item = read_item(L, 2,getServer(L)); + ItemStack item = read_item(L, 2,getServer(L)->idef()); if(item.empty() || !item.isKnown(getServer(L)->idef())) return 0; diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp index 38eade609..9a4aa845d 100644 --- a/src/script/lua_api/l_inventory.cpp +++ b/src/script/lua_api/l_inventory.cpp @@ -194,7 +194,7 @@ int InvRef::l_set_stack(lua_State *L) InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); int i = luaL_checknumber(L, 3) - 1; - ItemStack newitem = read_item(L, 4, getServer(L)); + ItemStack newitem = read_item(L, 4, getServer(L)->idef()); InventoryList *list = getlist(L, ref, listname); if(list != NULL && i >= 0 && i < (int) list->getSize()){ list->changeItem(i, newitem); @@ -295,7 +295,7 @@ int InvRef::l_add_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3, getServer(L)); + ItemStack item = read_item(L, 3, getServer(L)->idef()); InventoryList *list = getlist(L, ref, listname); if(list){ ItemStack leftover = list->addItem(item); @@ -315,7 +315,7 @@ int InvRef::l_room_for_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3, getServer(L)); + ItemStack item = read_item(L, 3, getServer(L)->idef()); InventoryList *list = getlist(L, ref, listname); if(list){ lua_pushboolean(L, list->roomForItem(item)); @@ -332,7 +332,7 @@ int InvRef::l_contains_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3, getServer(L)); + ItemStack item = read_item(L, 3, getServer(L)->idef()); InventoryList *list = getlist(L, ref, listname); if(list){ lua_pushboolean(L, list->containsItem(item)); @@ -349,7 +349,7 @@ int InvRef::l_remove_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3, getServer(L)); + ItemStack item = read_item(L, 3, getServer(L)->idef()); InventoryList *list = getlist(L, ref, listname); if(list){ ItemStack removed = list->removeItem(item); diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index 9638740e8..7e6f457e1 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -190,7 +190,7 @@ int LuaItemStack::l_replace(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); - o->m_stack = read_item(L,2,getServer(L)); + o->m_stack = read_item(L, 2, getGameDef(L)->idef()); lua_pushboolean(L, true); return 1; } @@ -250,7 +250,7 @@ int LuaItemStack::l_get_stack_max(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - lua_pushinteger(L, item.getStackMax(getServer(L)->idef())); + lua_pushinteger(L, item.getStackMax(getGameDef(L)->idef())); return 1; } @@ -260,7 +260,7 @@ int LuaItemStack::l_get_free_space(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - lua_pushinteger(L, item.freeSpace(getServer(L)->idef())); + lua_pushinteger(L, item.freeSpace(getGameDef(L)->idef())); return 1; } @@ -271,7 +271,7 @@ int LuaItemStack::l_is_known(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - bool is_known = item.isKnown(getServer(L)->idef()); + bool is_known = item.isKnown(getGameDef(L)->idef()); lua_pushboolean(L, is_known); return 1; } @@ -307,7 +307,7 @@ int LuaItemStack::l_get_tool_capabilities(lua_State *L) LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; const ToolCapabilities &prop = - item.getToolCapabilities(getServer(L)->idef()); + item.getToolCapabilities(getGameDef(L)->idef()); push_tool_capabilities(L, prop); return 1; } @@ -322,7 +322,7 @@ int LuaItemStack::l_add_wear(lua_State *L) LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; int amount = lua_tointeger(L, 2); - bool result = item.addWear(amount, getServer(L)->idef()); + bool result = item.addWear(amount, getGameDef(L)->idef()); lua_pushboolean(L, result); return 1; } @@ -334,8 +334,8 @@ int LuaItemStack::l_add_item(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L,-1, getServer(L)); - ItemStack leftover = item.addItem(newitem, getServer(L)->idef()); + ItemStack newitem = read_item(L, -1, getGameDef(L)->idef()); + ItemStack leftover = item.addItem(newitem, getGameDef(L)->idef()); create(L, leftover); return 1; } @@ -348,9 +348,9 @@ int LuaItemStack::l_item_fits(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2, getServer(L)); + ItemStack newitem = read_item(L, 2, getGameDef(L)->idef()); ItemStack restitem; - bool fits = item.itemFits(newitem, &restitem, getServer(L)->idef()); + bool fits = item.itemFits(newitem, &restitem, getGameDef(L)->idef()); lua_pushboolean(L, fits); // first return value create(L, restitem); // second return value return 2; @@ -407,7 +407,7 @@ ItemStack& LuaItemStack::getItem() int LuaItemStack::create_object(lua_State *L) { NO_MAP_LOCK_REQUIRED; - ItemStack item = read_item(L, 1, getServer(L)); + ItemStack item = read_item(L, 1, getGameDef(L)->idef()); LuaItemStack *o = new LuaItemStack(item); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); @@ -596,7 +596,7 @@ int ModApiItemMod::l_get_content_id(lua_State *L) NO_MAP_LOCK_REQUIRED; std::string name = luaL_checkstring(L, 1); - INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + INodeDefManager *ndef = getGameDef(L)->getNodeDefManager(); content_t c = ndef->getId(name); lua_pushinteger(L, c); @@ -609,7 +609,7 @@ int ModApiItemMod::l_get_name_from_content_id(lua_State *L) NO_MAP_LOCK_REQUIRED; content_t c = luaL_checkint(L, 1); - INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + INodeDefManager *ndef = getGameDef(L)->getNodeDefManager(); const char *name = ndef->get(c).name.c_str(); lua_pushstring(L, name); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index be454ad45..d5681b809 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -364,7 +364,7 @@ int ObjectRef::l_set_wielded_item(lua_State *L) ServerActiveObject *co = getobject(ref); if (co == NULL) return 0; // Do it - ItemStack item = read_item(L, 2, getServer(L)); + ItemStack item = read_item(L, 2, getServer(L)->idef()); bool success = co->setWieldedItem(item); if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { getServer(L)->SendInventory(((PlayerSAO*)co)); -- cgit v1.2.3 From eb88e5dd4b181a90b382c036cf6c4f42e63e8cc2 Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Thu, 16 Mar 2017 07:53:39 +0100 Subject: Add ModStorageAPI to client side modding (#5396) mod storage is located into user_path / client / mod_storage --- clientmods/preview/init.lua | 3 +++ src/client.cpp | 43 +++++++++++++++++++++++++++++++++++++++- src/client.h | 6 ++++++ src/gamedef.h | 4 ++++ src/script/clientscripting.cpp | 1 + src/script/lua_api/l_storage.cpp | 11 +++++----- src/server.h | 8 ++++---- src/unittest/test.cpp | 3 +++ 8 files changed, 68 insertions(+), 11 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 2ca4594d3..60dccf304 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -1,4 +1,5 @@ local modname = core.get_current_modname() or "??" +local modstorage = core.get_mod_storage() -- This is an example function to ensure it's working properly, should be removed before merge core.register_on_shutdown(function() @@ -49,6 +50,8 @@ core.register_chatcommand("test_node", { core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") + modstorage:set_string("current_mod", modname) + print(modstorage:get_string("current_mod")) end) core.register_on_dignode(function(pos, node) diff --git a/src/client.cpp b/src/client.cpp index 4ddabd814..567ee6dd7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -249,7 +249,8 @@ Client::Client( m_removed_sounds_check_timer(0), m_state(LC_Created), m_localdb(NULL), - m_script(NULL) + m_script(NULL), + m_mod_storage_save_timer(10.0f) { // Add local player m_env.setLocalPlayer(new LocalPlayer(this, playername)); @@ -730,6 +731,18 @@ void Client::step(float dtime) } } + m_mod_storage_save_timer -= dtime; + if (m_mod_storage_save_timer <= 0.0f) { + verbosestream << "Saving registered mod storages." << std::endl; + m_mod_storage_save_timer = g_settings->getFloat("server_map_save_interval"); + for (UNORDERED_MAP::const_iterator + it = m_mod_storages.begin(); it != m_mod_storages.end(); ++it) { + if (it->second->isModified()) { + it->second->save(getModStoragePath()); + } + } + } + // Write server map if (m_localdb && m_localdb_save_interval.step(dtime, m_cache_save_interval)) { @@ -1998,3 +2011,31 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename) smgr->getMeshCache()->removeMesh(mesh); return mesh; } + +bool Client::registerModStorage(ModMetadata *storage) +{ + if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) { + errorstream << "Unable to register same mod storage twice. Storage name: " + << storage->getModName() << std::endl; + return false; + } + + m_mod_storages[storage->getModName()] = storage; + return true; +} + +void Client::unregisterModStorage(const std::string &name) +{ + UNORDERED_MAP::const_iterator it = m_mod_storages.find(name); + if (it != m_mod_storages.end()) { + // Save unconditionaly on unregistration + it->second->save(getModStoragePath()); + m_mod_storages.erase(name); + } +} + +std::string Client::getModStoragePath() const +{ + return porting::path_user + DIR_DELIM + "client" + DIR_DELIM + "mod_storage"; +} + diff --git a/src/client.h b/src/client.h index 7f9cc559b..d72249315 100644 --- a/src/client.h +++ b/src/client.h @@ -554,6 +554,10 @@ public: { return checkPrivilege(priv); } virtual scene::IAnimatedMesh* getMesh(const std::string &filename); + virtual std::string getModStoragePath() const; + virtual bool registerModStorage(ModMetadata *meta); + virtual void unregisterModStorage(const std::string &name); + // The following set of functions is used by ClientMediaDownloader // Insert a media file appropriately into the appropriate manager bool loadMedia(const std::string &data, const std::string &filename); @@ -724,6 +728,8 @@ private: ClientScripting *m_script; bool m_modding_enabled; + UNORDERED_MAP m_mod_storages; + float m_mod_storage_save_timer; DISABLE_CLASS_COPY(Client); }; diff --git a/src/gamedef.h b/src/gamedef.h index 593d27e30..6cd01305f 100644 --- a/src/gamedef.h +++ b/src/gamedef.h @@ -34,6 +34,7 @@ class MtEventManager; class IRollbackManager; class EmergeManager; class Camera; +class ModMetadata; namespace irr { namespace scene { class IAnimatedMesh; @@ -75,6 +76,9 @@ public: virtual const std::vector &getMods() const = 0; virtual const ModSpec* getModSpec(const std::string &modname) const = 0; virtual std::string getWorldPath() const { return ""; } + virtual std::string getModStoragePath() const = 0; + virtual bool registerModStorage(ModMetadata *storage) = 0; + virtual void unregisterModStorage(const std::string &name) = 0; }; #endif diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index c1e308012..ccdcb928d 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -58,4 +58,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) ModApiStorage::Initialize(L, top); LuaItemStack::Register(L); + StorageRef::Register(L); } diff --git a/src/script/lua_api/l_storage.cpp b/src/script/lua_api/l_storage.cpp index 42928255f..867ab9c8d 100644 --- a/src/script/lua_api/l_storage.cpp +++ b/src/script/lua_api/l_storage.cpp @@ -33,10 +33,9 @@ int ModApiStorage::l_get_mod_storage(lua_State *L) std::string mod_name = lua_tostring(L, -1); ModMetadata *store = new ModMetadata(mod_name); - // For server side - if (Server *server = getServer(L)) { - store->load(server->getModStoragePath()); - server->registerModStorage(store); + if (IGameDef *gamedef = getGameDef(L)) { + store->load(gamedef->getModStoragePath()); + gamedef->registerModStorage(store); } else { assert(false); // this should not happen } @@ -70,8 +69,8 @@ int StorageRef::gc_object(lua_State *L) { StorageRef *o = *(StorageRef **)(lua_touserdata(L, 1)); // Server side - if (Server *server = getServer(L)) - server->unregisterModStorage(getobject(o)->getModName()); + if (IGameDef *gamedef = getGameDef(L)) + gamedef->unregisterModStorage(getobject(o)->getModName()); delete o; return 0; } diff --git a/src/server.h b/src/server.h index f0bab1bbf..e1e8f84dc 100644 --- a/src/server.h +++ b/src/server.h @@ -299,8 +299,8 @@ public: virtual const ModSpec* getModSpec(const std::string &modname) const; void getModNames(std::vector &modlist); std::string getBuiltinLuaPath(); - std::string getWorldPath() const { return m_path_world; } - std::string getModStoragePath() const; + virtual std::string getWorldPath() const { return m_path_world; } + virtual std::string getModStoragePath() const; inline bool isSingleplayer() { return m_simple_singleplayer_mode; } @@ -361,8 +361,8 @@ public: void SendInventory(PlayerSAO* playerSAO); void SendMovePlayer(u16 peer_id); - bool registerModStorage(ModMetadata *storage); - void unregisterModStorage(const std::string &name); + virtual bool registerModStorage(ModMetadata *storage); + virtual void unregisterModStorage(const std::string &name); // Bind address Address m_bind_addr; diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index 9beb0afa6..9d223b82d 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -65,6 +65,9 @@ public: return testmodspec; } virtual const ModSpec* getModSpec(const std::string &modname) const { return NULL; } + virtual std::string getModStoragePath() const { return "."; } + virtual bool registerModStorage(ModMetadata *meta) { return true; } + virtual void unregisterModStorage(const std::string &name) {} private: IItemDefManager *m_itemdef; -- cgit v1.2.3 From 40ce538aad9af8f7634c4ba7e9f12246fb23b31c Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Thu, 16 Mar 2017 10:34:54 +0100 Subject: [CSM] Add minimap API modifiers (#5399) * Rename Mapper (too generic) to Minimap * Add lua functions to get/set position, angle, mode for minimap * Client: rename m_mapper to m_minimap * Add minimap to core.ui namespace (core.ui.minimap) * Add various functions to manage minimap (show, hide, toggle_shape) * Cleanup trivial declaration in client --- clientmods/preview/init.lua | 12 +++ doc/client_lua_api.md | 18 ++++ src/client.cpp | 26 +++-- src/client.h | 21 ++-- src/drawscene.cpp | 2 +- src/drawscene.h | 2 +- src/game.cpp | 8 +- src/minimap.cpp | 33 +++--- src/minimap.h | 10 +- src/network/clientpackethandler.cpp | 2 +- src/script/clientscripting.cpp | 7 ++ src/script/lua_api/CMakeLists.txt | 1 + src/script/lua_api/l_minimap.cpp | 196 ++++++++++++++++++++++++++++++++++++ src/script/lua_api/l_minimap.h | 64 ++++++++++++ 14 files changed, 349 insertions(+), 53 deletions(-) create mode 100644 src/script/lua_api/l_minimap.cpp create mode 100644 src/script/lua_api/l_minimap.h (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 60dccf304..bdda7fe4e 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -47,9 +47,21 @@ core.register_chatcommand("test_node", { end, }) +local function preview_minimap() + local minimap = core.ui.minimap + minimap:show() + minimap:set_mode(4) + minimap:set_pos({x=5, y=50, z=5}) + minimap:toggle_shape() + + print("[PREVIEW] Minimap: mode => " .. dump(minimap:get_mode()) .. + " position => " .. dump(minimap:get_pos()) .. + " angle => " .. dump(minimap:get_angle())) +end core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") + preview_minimap() modstorage:set_string("current_mod", modname) print(modstorage:get_string("current_mod")) end) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index c07a1c55a..70716ee41 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -789,9 +789,27 @@ Call these functions only at load time! * same as fgettext_ne(), but calls core.formspec_escape before returning result * `show_formspec(formname, formspec)` : returns true on success * Shows a formspec to the player + +### UI +* `minetest.ui.minimap` + * Reference to the minimap object. See `Minimap` class reference for methods. + Class reference --------------- +### `Minimap` +An interface to manipulate minimap on client UI + +* `show()`: shows the minimap (if not disabled by server) +* `hide()`: hides the minimap +* `set_pos(pos)`: sets the minimap position on screen +* `get_pos()`: returns the minimap current position +* `set_angle(deg)`: sets the minimap angle in degrees +* `get_angle()`: returns the current minimap angle in degrees +* `set_mode(mode)`: sets the minimap mode (0 to 6) +* `get_mode()`: returns the current minimap mode +* `toggle_shape()`: toggles minimap shape to round or square. + ### `Settings` An interface to read config files in the format of `minetest.conf`. diff --git a/src/client.cpp b/src/client.cpp index 567ee6dd7..2491db704 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -224,6 +224,7 @@ Client::Client( m_device(device), m_camera(NULL), m_minimap_disabled_by_server(false), + m_minimap_shown_by_mod(false), m_server_ser_ver(SER_FMT_VER_INVALID), m_proto_ver(0), m_playeritem(0), @@ -255,7 +256,7 @@ Client::Client( // Add local player m_env.setLocalPlayer(new LocalPlayer(this, playername)); - m_mapper = new Mapper(device, this); + m_minimap = new Minimap(device, this); m_cache_save_interval = g_settings->getU16("server_map_save_interval"); m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); @@ -386,7 +387,7 @@ Client::~Client() m_device->getSceneManager()->getMeshCache()->removeMesh(mesh); } - delete m_mapper; + delete m_minimap; } void Client::connect(Address address, @@ -636,7 +637,7 @@ void Client::step(float dtime) } if (do_mapper_update) - m_mapper->addBlock(r.p, minimap_mapblock); + m_minimap->addBlock(r.p, minimap_mapblock); if (r.ack_block_to_server) { /* @@ -1859,23 +1860,17 @@ void Client::afterContentReceived(IrrlichtDevice *device) delete[] text; } -float Client::getRTT(void) +float Client::getRTT() { return m_con.getPeerStat(PEER_ID_SERVER,con::AVG_RTT); } -float Client::getCurRate(void) +float Client::getCurRate() { return ( m_con.getLocalStat(con::CUR_INC_RATE) + m_con.getLocalStat(con::CUR_DL_RATE)); } -float Client::getAvgRate(void) -{ - return ( m_con.getLocalStat(con::AVG_INC_RATE) + - m_con.getLocalStat(con::AVG_DL_RATE)); -} - void Client::makeScreenshot(IrrlichtDevice *device) { irr::video::IVideoDriver *driver = device->getVideoDriver(); @@ -1935,6 +1930,15 @@ void Client::makeScreenshot(IrrlichtDevice *device) raw_image->drop(); } +bool Client::shouldShowMinimap() const +{ + if (m_minimap_disabled_by_server) { + return false; + } + + return m_minimap_shown_by_mod; +} + // IGameDef interface // Under envlock IItemDefManager* Client::getItemDefManager() diff --git a/src/client.h b/src/client.h index d72249315..5c8a0ae25 100644 --- a/src/client.h +++ b/src/client.h @@ -49,7 +49,7 @@ struct MapDrawControl; class MtEventManager; struct PointedThing; class Database; -class Mapper; +class Minimap; struct MinimapMapblock; class Camera; class NetworkPacket; @@ -522,21 +522,17 @@ public: void afterContentReceived(IrrlichtDevice *device); - float getRTT(void); - float getCurRate(void); - float getAvgRate(void); + float getRTT(); + float getCurRate(); - Mapper* getMapper () - { return m_mapper; } - - void setCamera(Camera* camera) - { m_camera = camera; } + Minimap* getMinimap() { return m_minimap; } + void setCamera(Camera* camera) { m_camera = camera; } Camera* getCamera () { return m_camera; } - bool isMinimapDisabledByServer() - { return m_minimap_disabled_by_server; } + bool shouldShowMinimap() const; + void setMinimapShownByMod(bool state) { m_minimap_shown_by_mod = state; } // IGameDef interface virtual IItemDefManager* getItemDefManager(); @@ -636,8 +632,9 @@ private: con::Connection m_con; IrrlichtDevice *m_device; Camera *m_camera; - Mapper *m_mapper; + Minimap *m_minimap; bool m_minimap_disabled_by_server; + bool m_minimap_shown_by_mod; // Server serialization version u8 m_server_ser_ver; diff --git a/src/drawscene.cpp b/src/drawscene.cpp index e3e6301a8..3a03743ee 100644 --- a/src/drawscene.cpp +++ b/src/drawscene.cpp @@ -474,7 +474,7 @@ void draw_plain(Camera &camera, bool show_hud, Hud &hud, void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr, Camera &camera, Client& client, LocalPlayer *player, Hud &hud, - Mapper &mapper, gui::IGUIEnvironment *guienv, + Minimap &mapper, gui::IGUIEnvironment *guienv, const v2u32 &screensize, const video::SColor &skycolor, bool show_hud, bool show_minimap) { diff --git a/src/drawscene.h b/src/drawscene.h index 364fcd499..4965a0889 100644 --- a/src/drawscene.h +++ b/src/drawscene.h @@ -32,7 +32,7 @@ void draw_load_screen(const std::wstring &text, IrrlichtDevice *device, void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr, Camera &camera, Client &client, LocalPlayer *player, - Hud &hud, Mapper &mapper, gui::IGUIEnvironment *guienv, + Hud &hud, Minimap &mapper, gui::IGUIEnvironment *guienv, const v2u32 &screensize, const video::SColor &skycolor, bool show_hud, bool show_minimap); diff --git a/src/game.cpp b/src/game.cpp index 10ec5d594..386267017 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -715,7 +715,7 @@ public: m_eye_position_vertex.set(eye_position_array, services); float minimap_yaw_array[3]; - v3f minimap_yaw = m_client->getMapper()->getYawVec(); + v3f minimap_yaw = m_client->getMinimap()->getYawVec(); #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) minimap_yaw_array[0] = minimap_yaw.X; minimap_yaw_array[1] = minimap_yaw.Y; @@ -1473,7 +1473,7 @@ private: Sky *sky; // Free using ->Drop() Inventory *local_inventory; Hud *hud; - Mapper *mapper; + Minimap *mapper; GameRunData runData; VolatileRunFlags flags; @@ -1769,7 +1769,7 @@ void Game::run() updateProfilerGraphs(&graph); // Update if minimap has been disabled by the server - flags.show_minimap &= !client->isMinimapDisabledByServer(); + flags.show_minimap = client->shouldShowMinimap(); } } @@ -2029,7 +2029,7 @@ bool Game::createClient(const std::string &playername, return false; } - mapper = client->getMapper(); + mapper = client->getMinimap(); mapper->setMinimapMode(MINIMAP_MODE_OFF); return true; diff --git a/src/minimap.cpp b/src/minimap.cpp index cfc2c34b0..ee29c58ba 100644 --- a/src/minimap.cpp +++ b/src/minimap.cpp @@ -184,7 +184,7 @@ void MinimapUpdateThread::getMap(v3s16 pos, s16 size, s16 height) //// Mapper //// -Mapper::Mapper(IrrlichtDevice *device, Client *client) +Minimap::Minimap(IrrlichtDevice *device, Client *client) { this->client = client; this->driver = device->getVideoDriver(); @@ -238,7 +238,7 @@ Mapper::Mapper(IrrlichtDevice *device, Client *client) m_minimap_update_thread->start(); } -Mapper::~Mapper() +Minimap::~Minimap() { m_minimap_update_thread->stop(); m_minimap_update_thread->wait(); @@ -258,17 +258,12 @@ Mapper::~Mapper() delete m_minimap_update_thread; } -void Mapper::addBlock(v3s16 pos, MinimapMapblock *data) +void Minimap::addBlock(v3s16 pos, MinimapMapblock *data) { m_minimap_update_thread->enqueueBlock(pos, data); } -MinimapMode Mapper::getMinimapMode() -{ - return data->mode; -} - -void Mapper::toggleMinimapShape() +void Minimap::toggleMinimapShape() { MutexAutoLock lock(m_mutex); @@ -277,7 +272,7 @@ void Mapper::toggleMinimapShape() m_minimap_update_thread->deferUpdate(); } -void Mapper::setMinimapMode(MinimapMode mode) +void Minimap::setMinimapMode(MinimapMode mode) { static const MinimapModeDef modedefs[MINIMAP_MODE_COUNT] = { {false, 0, 0}, @@ -302,7 +297,7 @@ void Mapper::setMinimapMode(MinimapMode mode) m_minimap_update_thread->deferUpdate(); } -void Mapper::setPos(v3s16 pos) +void Minimap::setPos(v3s16 pos) { bool do_update = false; @@ -320,12 +315,12 @@ void Mapper::setPos(v3s16 pos) m_minimap_update_thread->deferUpdate(); } -void Mapper::setAngle(f32 angle) +void Minimap::setAngle(f32 angle) { m_angle = angle; } -void Mapper::blitMinimapPixelsToImageRadar(video::IImage *map_image) +void Minimap::blitMinimapPixelsToImageRadar(video::IImage *map_image) { for (s16 x = 0; x < data->map_size; x++) for (s16 z = 0; z < data->map_size; z++) { @@ -339,7 +334,7 @@ void Mapper::blitMinimapPixelsToImageRadar(video::IImage *map_image) } } -void Mapper::blitMinimapPixelsToImageSurface( +void Minimap::blitMinimapPixelsToImageSurface( video::IImage *map_image, video::IImage *heightmap_image) { for (s16 x = 0; x < data->map_size; x++) @@ -368,7 +363,7 @@ void Mapper::blitMinimapPixelsToImageSurface( } } -video::ITexture *Mapper::getMinimapTexture() +video::ITexture *Minimap::getMinimapTexture() { // update minimap textures when new scan is ready if (data->map_invalidated) @@ -418,7 +413,7 @@ video::ITexture *Mapper::getMinimapTexture() return data->texture; } -v3f Mapper::getYawVec() +v3f Minimap::getYawVec() { if (data->minimap_shape_round) { return v3f( @@ -430,7 +425,7 @@ v3f Mapper::getYawVec() } } -scene::SMeshBuffer *Mapper::getMinimapMeshBuffer() +scene::SMeshBuffer *Minimap::getMinimapMeshBuffer() { scene::SMeshBuffer *buf = new scene::SMeshBuffer(); buf->Vertices.set_used(4); @@ -452,7 +447,7 @@ scene::SMeshBuffer *Mapper::getMinimapMeshBuffer() return buf; } -void Mapper::drawMinimap() +void Minimap::drawMinimap() { video::ITexture *minimap_texture = getMinimapTexture(); if (!minimap_texture) @@ -550,7 +545,7 @@ void Mapper::drawMinimap() } } -void Mapper::updateActiveMarkers () +void Minimap::updateActiveMarkers() { video::IImage *minimap_mask = data->minimap_shape_round ? data->minimap_mask_round : data->minimap_mask_square; diff --git a/src/minimap.h b/src/minimap.h index 60b80d833..eb0ae1cf4 100644 --- a/src/minimap.h +++ b/src/minimap.h @@ -112,19 +112,21 @@ private: std::map m_blocks_cache; }; -class Mapper { +class Minimap { public: - Mapper(IrrlichtDevice *device, Client *client); - ~Mapper(); + Minimap(IrrlichtDevice *device, Client *client); + ~Minimap(); void addBlock(v3s16 pos, MinimapMapblock *data); v3f getYawVec(); - MinimapMode getMinimapMode(); void setPos(v3s16 pos); + v3s16 getPos() const { return data->pos; } void setAngle(f32 angle); + f32 getAngle() const { return m_angle; } void setMinimapMode(MinimapMode mode); + MinimapMode getMinimapMode() const { return data->mode; } void toggleMinimapShape(); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 9bcc58110..dfaebbe53 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1140,7 +1140,7 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) if (m_minimap_disabled_by_server && was_minimap_visible) { // defers a minimap update, therefore only call it if really // needed, by checking that minimap was visible before - m_mapper->setMinimapMode(MINIMAP_MODE_OFF); + m_minimap->setMinimapMode(MINIMAP_MODE_OFF); } } diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index ccdcb928d..1b73fdf0d 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "cpp_api/s_internal.h" #include "lua_api/l_client.h" +#include "lua_api/l_minimap.h" #include "lua_api/l_storage.h" #include "lua_api/l_sound.h" #include "lua_api/l_util.h" @@ -40,9 +41,14 @@ ClientScripting::ClientScripting(Client *client): lua_getglobal(L, "core"); int top = lua_gettop(L); + lua_newtable(L); + lua_setfield(L, -2, "ui"); + InitializeModApi(L, top); lua_pop(L, 1); + LuaMinimap::create(L, client->getMinimap()); + // Push builtin initialization type lua_pushstring(L, "client"); lua_setglobal(L, "INIT"); @@ -59,4 +65,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) LuaItemStack::Register(L); StorageRef::Register(L); + LuaMinimap::Register(L); } diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index 2d25d845c..f7f22870e 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -25,6 +25,7 @@ set(common_SCRIPT_LUA_API_SRCS set(client_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp PARENT_SCOPE) diff --git a/src/script/lua_api/l_minimap.cpp b/src/script/lua_api/l_minimap.cpp new file mode 100644 index 000000000..bbe9aef82 --- /dev/null +++ b/src/script/lua_api/l_minimap.cpp @@ -0,0 +1,196 @@ +/* +Minetest +Copyright (C) 2017 Loic Blot + +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_minimap.h" +#include "lua_api/l_internal.h" +#include "common/c_converter.h" +#include "minimap.h" + +LuaMinimap::LuaMinimap(Minimap *m) +{ + m_minimap = m; +} + +void LuaMinimap::create(lua_State *L, Minimap *m) +{ + LuaMinimap *o = new LuaMinimap(m); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + + // Keep minimap object stack id + int minimap_object = lua_gettop(L); + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "ui"); + luaL_checktype(L, -1, LUA_TTABLE); + int uitable = lua_gettop(L); + + lua_pushvalue(L, minimap_object); // Copy object to top of stack + lua_setfield(L, uitable, "minimap"); +} + +int LuaMinimap::l_get_pos(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + push_v3s16(L, m->getPos()); + return 1; +} + +int LuaMinimap::l_set_pos(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + m->setPos(read_v3s16(L, 2)); + return 1; +} + +int LuaMinimap::l_get_angle(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + lua_pushinteger(L, m->getAngle()); + return 1; +} + +int LuaMinimap::l_set_angle(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + m->setAngle(lua_tointeger(L, 2)); + return 1; +} + +int LuaMinimap::l_get_mode(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + lua_pushinteger(L, m->getMinimapMode()); + return 1; +} + +int LuaMinimap::l_set_mode(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + s32 mode = lua_tointeger(L, 2); + if (mode < MINIMAP_MODE_OFF || + mode >= MINIMAP_MODE_COUNT) { + return 0; + } + + m->setMinimapMode((MinimapMode) mode); + return 1; +} + +int LuaMinimap::l_toggle_shape(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + m->toggleMinimapShape(); + return 1; +} + +int LuaMinimap::l_show(lua_State *L) +{ + Client *client = getClient(L); + assert(client); + client->setMinimapShownByMod(true); + return 1; +} + +int LuaMinimap::l_hide(lua_State *L) +{ + Client *client = getClient(L); + assert(client); + client->setMinimapShownByMod(false); + return 1; +} + +LuaMinimap *LuaMinimap::checkobject(lua_State *L, int narg) +{ + NO_MAP_LOCK_REQUIRED; + + luaL_checktype(L, narg, LUA_TUSERDATA); + + void *ud = luaL_checkudata(L, narg, className); + if (!ud) + luaL_typerror(L, narg, className); + + return *(LuaMinimap **)ud; // unbox pointer +} + +Minimap* LuaMinimap::getobject(LuaMinimap *ref) +{ + return ref->m_minimap; +} + +int LuaMinimap::gc_object(lua_State *L) { + LuaMinimap *o = *(LuaMinimap **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +void LuaMinimap::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 LuaMinimap::className[] = "Minimap"; +const luaL_reg LuaMinimap::methods[] = { + luamethod(LuaMinimap, show), + luamethod(LuaMinimap, hide), + luamethod(LuaMinimap, get_pos), + luamethod(LuaMinimap, set_pos), + luamethod(LuaMinimap, get_angle), + luamethod(LuaMinimap, set_angle), + luamethod(LuaMinimap, get_mode), + luamethod(LuaMinimap, set_mode), + luamethod(LuaMinimap, toggle_shape), + {0,0} +}; diff --git a/src/script/lua_api/l_minimap.h b/src/script/lua_api/l_minimap.h new file mode 100644 index 000000000..d9bb8842c --- /dev/null +++ b/src/script/lua_api/l_minimap.h @@ -0,0 +1,64 @@ +/* +Minetest +Copyright (C) 2017 Loic Blot + +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. +*/ + +#ifndef L_MINIMAP_H_ +#define L_MINIMAP_H_ + +#include "l_base.h" + + +class Minimap; + +class LuaMinimap : public ModApiBase { +private: + + static const char className[]; + static const luaL_reg methods[]; + + // garbage collector + static int gc_object(lua_State *L); + + static int l_get_pos(lua_State *L); + static int l_set_pos(lua_State *L); + + static int l_get_angle(lua_State *L); + static int l_set_angle(lua_State *L); + + static int l_get_mode(lua_State *L); + static int l_set_mode(lua_State *L); + + static int l_show(lua_State *L); + static int l_hide(lua_State *L); + + static int l_toggle_shape(lua_State *L); + + Minimap *m_minimap; +public: + LuaMinimap(Minimap *m); + ~LuaMinimap() {} + + static void create(lua_State *L, Minimap *object); + + static LuaMinimap *checkobject(lua_State *L, int narg); + static Minimap* getobject(LuaMinimap *ref); + + static void Register(lua_State *L); +}; + +#endif // L_MINIMAP_H_ -- cgit v1.2.3 From 0891975ad6c8d6d3e15b20f33b22cf5baca7eb62 Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Fri, 17 Mar 2017 07:48:29 +0100 Subject: [CSM] Add core.get_timeofday & core.get_day_count env calls (#5401) * [CSM] Add core.get_timeofday & core.get_day_count env calls * [CSM] Add core.get_node_level, core.get_node_max_level, core.find_node_near --- clientmods/preview/init.lua | 9 +++++++++ src/client.cpp | 1 + src/clientenvironment.cpp | 1 + src/environment.cpp | 5 +++-- src/environment.h | 5 ++++- src/script/clientscripting.cpp | 2 ++ src/script/cpp_api/s_client.cpp | 5 +++++ src/script/cpp_api/s_client.h | 4 ++++ src/script/lua_api/l_env.cpp | 44 +++++++++++++++++++++++++++++++---------- src/script/lua_api/l_env.h | 1 + src/script/lua_api/l_internal.h | 10 ---------- src/serverenvironment.cpp | 3 ++- src/serverenvironment.h | 2 +- 13 files changed, 67 insertions(+), 25 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index bdda7fe4e..3f85d576d 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -64,6 +64,15 @@ core.after(2, function() preview_minimap() modstorage:set_string("current_mod", modname) print(modstorage:get_string("current_mod")) + + print("[PREVIEW] Day count: " .. core.get_day_count() .. + " time of day " .. core.get_timeofday()) + + print("[PREVIEW] Node level: " .. core.get_node_level({x=0, y=20, z=0}) .. + " max level " .. core.get_node_max_level({x=0, y=20, z=0})) + + print("[PREVIEW] Find node near: " .. dump(core.find_node_near({x=0, y=20, z=0}, 10, + {"group:tree", "default:dirt", "default:stone"}))) end) core.register_on_dignode(function(pos, node) diff --git a/src/client.cpp b/src/client.cpp index 2491db704..b355fa617 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -268,6 +268,7 @@ Client::Client( m_modding_enabled = g_settings->getBool("enable_client_modding"); m_script = new ClientScripting(this); m_env.setScript(m_script); + m_script->setEnv(&m_env); } void Client::initMods() diff --git a/src/clientenvironment.cpp b/src/clientenvironment.cpp index 7a74c897c..29ecd2dfe 100644 --- a/src/clientenvironment.cpp +++ b/src/clientenvironment.cpp @@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr, ITextureSource *texturesource, Client *client, IrrlichtDevice *irr): + Environment(client), m_map(map), m_local_player(NULL), m_smgr(smgr), diff --git a/src/environment.cpp b/src/environment.cpp index 737d93ecd..d1ea5f8bb 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -26,13 +26,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "daynightratio.h" #include "emerge.h" -Environment::Environment(): +Environment::Environment(IGameDef *gamedef): m_time_of_day_speed(0), m_time_of_day(9000), m_time_of_day_f(9000./24000), m_time_conversion_skew(0.0f), m_enable_day_night_ratio_override(false), - m_day_night_ratio_override(0.0f) + m_day_night_ratio_override(0.0f), + m_gamedef(gamedef) { m_cache_enable_shaders = g_settings->getBool("enable_shaders"); m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval"); diff --git a/src/environment.h b/src/environment.h index 5154bbdcb..52f369817 100644 --- a/src/environment.h +++ b/src/environment.h @@ -40,13 +40,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "threading/atomic.h" #include "network/networkprotocol.h" // for AccessDeniedCode +class IGameDef; class Map; class Environment { public: // Environment will delete the map passed to the constructor - Environment(); + Environment(IGameDef *gamedef); virtual ~Environment(); /* @@ -77,6 +78,7 @@ public: // counter used internally when triggering ABMs u32 m_added_objects; + IGameDef* getGameDef() { return m_gamedef; } protected: GenericAtomic m_time_of_day_speed; @@ -114,6 +116,7 @@ protected: float m_cache_abm_interval; float m_cache_nodetimer_interval; + IGameDef *m_gamedef; private: Mutex m_time_lock; diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index 8bf1b68b1..df30a7253 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "cpp_api/s_internal.h" #include "lua_api/l_client.h" +#include "lua_api/l_env.h" #include "lua_api/l_minimap.h" #include "lua_api/l_storage.h" #include "lua_api/l_sound.h" @@ -62,6 +63,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) ModApiClient::Initialize(L, top); ModApiSound::Initialize(L, top); ModApiStorage::Initialize(L, top); + ModApiEnvMod::InitializeClient(L, top); LuaItemStack::Register(L); StorageRef::Register(L); diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 154dd6194..666fd693d 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -177,3 +177,8 @@ bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node) bool blocked = lua_toboolean(L, -1); return blocked; } + +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 93e9558f2..2369efe3e 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif +class ClientEnvironment; + class ScriptApiClient: virtual public ScriptApiBase { public: @@ -47,5 +49,7 @@ public: bool on_dignode(v3s16 p, MapNode node); bool on_punchnode(v3s16 p, MapNode node); + + void setEnv(ClientEnvironment *env); }; #endif diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 14df558d3..4fad7b37c 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -347,7 +347,10 @@ int ModApiEnvMod::l_punch_node(lua_State *L) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_get_node_max_level(lua_State *L) { - GET_ENV_PTR; + Environment *env = getEnv(L); + if (!env) { + return 0; + } v3s16 pos = read_v3s16(L, 1); MapNode n = env->getMap().getNodeNoEx(pos); @@ -359,7 +362,10 @@ int ModApiEnvMod::l_get_node_max_level(lua_State *L) // pos = {x=num, y=num, z=num} int ModApiEnvMod::l_get_node_level(lua_State *L) { - GET_ENV_PTR; + Environment *env = getEnv(L); + if (!env) { + return 0; + } v3s16 pos = read_v3s16(L, 1); MapNode n = env->getMap().getNodeNoEx(pos); @@ -558,11 +564,14 @@ int ModApiEnvMod::l_set_timeofday(lua_State *L) // get_timeofday() -> 0...1 int ModApiEnvMod::l_get_timeofday(lua_State *L) { - GET_ENV_PTR; + Environment *env = getEnv(L); + if (!env) { + return 0; + } // Do it int timeofday_mh = env->getTimeOfDay(); - float timeofday_f = (float)timeofday_mh / 24000.0; + float timeofday_f = (float)timeofday_mh / 24000.0f; lua_pushnumber(L, timeofday_f); return 1; } @@ -570,7 +579,10 @@ int ModApiEnvMod::l_get_timeofday(lua_State *L) // get_day_count() -> int int ModApiEnvMod::l_get_day_count(lua_State *L) { - GET_ENV_PTR; + Environment *env = getEnv(L); + if (!env) { + return 0; + } lua_pushnumber(L, env->getDayCount()); return 1; @@ -591,9 +603,12 @@ int ModApiEnvMod::l_get_gametime(lua_State *L) // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" int ModApiEnvMod::l_find_node_near(lua_State *L) { - GET_ENV_PTR; + Environment *env = getEnv(L); + if (!env) { + return 0; + } - INodeDefManager *ndef = getServer(L)->ndef(); + INodeDefManager *ndef = getGameDef(L)->ndef(); v3s16 pos = read_v3s16(L, 1); int radius = luaL_checkinteger(L, 2); std::set filter; @@ -611,13 +626,13 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) ndef->getIds(lua_tostring(L, 3), filter); } - for(int d=1; d<=radius; d++){ + for (int d=1; d<=radius; d++){ std::vector list = FacePositionCache::getFacePositions(d); - for(std::vector::iterator i = list.begin(); + for (std::vector::iterator i = list.begin(); i != list.end(); ++i){ v3s16 p = pos + (*i); content_t c = env->getMap().getNodeNoEx(p).getContent(); - if(filter.count(c) != 0){ + if (filter.count(c) != 0){ push_v3s16(L, p); return 1; } @@ -1087,3 +1102,12 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(forceload_block); API_FCT(forceload_free_block); } + +void ModApiEnvMod::InitializeClient(lua_State *L, int top) +{ + API_FCT(get_timeofday); + API_FCT(get_day_count); + API_FCT(get_node_max_level); + API_FCT(get_node_level); + API_FCT(find_node_near); +} diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 322959411..38b2282d7 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -173,6 +173,7 @@ private: public: static void Initialize(lua_State *L, int top); + static void InitializeClient(lua_State *L, int top); static struct EnumString es_ClearObjectsMode[]; }; diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h index c610dc5a3..b7627619e 100644 --- a/src/script/lua_api/l_internal.h +++ b/src/script/lua_api/l_internal.h @@ -37,16 +37,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MAP_LOCK_REQUIRED #define NO_MAP_LOCK_REQUIRED -/* -#if (defined(WIN32) || defined(_WIN32_WCE)) - #define NO_MAP_LOCK_REQUIRED -#else - #include "profiler.h" - #define NO_MAP_LOCK_REQUIRED \ - ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD) -#endif -*/ - #define GET_ENV_PTR_NO_MAP_LOCK \ ServerEnvironment *env = (ServerEnvironment *)getEnv(L); \ if (env == NULL) \ diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index ecc7c3150..e09c7da16 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -353,7 +353,8 @@ void ActiveBlockList::update(std::vector &active_positions, ServerEnvironment::ServerEnvironment(ServerMap *map, ServerScripting *scriptIface, Server *server, - const std::string &path_world) : + const std::string &path_world): + Environment(server), m_map(map), m_script(scriptIface), m_server(server), diff --git a/src/serverenvironment.h b/src/serverenvironment.h index b7796b5f1..99110542a 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -320,7 +320,7 @@ public: //check if there's a line of sight between two positions bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0, v3s16 *p=NULL); - u32 getGameTime() { return m_game_time; } + u32 getGameTime() const { return m_game_time; } void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; } float getMaxLagEstimate() { return m_max_lag_estimate; } -- cgit v1.2.3 From 7b74f04a611ddaf36d79c0c9ebbf7f2b89c12a64 Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Fri, 17 Mar 2017 07:54:49 +0100 Subject: [CSM] Fix minimap problems (#5405) This fixes issue #5404 --- clientmods/preview/init.lua | 8 ++++++-- src/client.cpp | 7 +------ src/client.h | 2 -- src/game.cpp | 2 +- src/script/lua_api/l_minimap.cpp | 16 ++++++++++------ 5 files changed, 18 insertions(+), 17 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 3f85d576d..25a61da51 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -49,8 +49,8 @@ core.register_chatcommand("test_node", { local function preview_minimap() local minimap = core.ui.minimap - minimap:show() minimap:set_mode(4) + minimap:show() minimap:set_pos({x=5, y=50, z=5}) minimap:toggle_shape() @@ -61,9 +61,13 @@ end core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") - preview_minimap() modstorage:set_string("current_mod", modname) print(modstorage:get_string("current_mod")) + preview_minimap() +end) + +core.after(5, function() + core.ui.minimap:show() print("[PREVIEW] Day count: " .. core.get_day_count() .. " time of day " .. core.get_timeofday()) diff --git a/src/client.cpp b/src/client.cpp index b355fa617..e87c0ff94 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -224,7 +224,6 @@ Client::Client( m_device(device), m_camera(NULL), m_minimap_disabled_by_server(false), - m_minimap_shown_by_mod(false), m_server_ser_ver(SER_FMT_VER_INVALID), m_proto_ver(0), m_playeritem(0), @@ -1933,11 +1932,7 @@ void Client::makeScreenshot(IrrlichtDevice *device) bool Client::shouldShowMinimap() const { - if (m_minimap_disabled_by_server) { - return false; - } - - return m_minimap_shown_by_mod; + return !m_minimap_disabled_by_server; } // IGameDef interface diff --git a/src/client.h b/src/client.h index 5c8a0ae25..fc1cbe310 100644 --- a/src/client.h +++ b/src/client.h @@ -532,7 +532,6 @@ public: { return m_camera; } bool shouldShowMinimap() const; - void setMinimapShownByMod(bool state) { m_minimap_shown_by_mod = state; } // IGameDef interface virtual IItemDefManager* getItemDefManager(); @@ -634,7 +633,6 @@ private: Camera *m_camera; Minimap *m_minimap; bool m_minimap_disabled_by_server; - bool m_minimap_shown_by_mod; // Server serialization version u8 m_server_ser_ver; diff --git a/src/game.cpp b/src/game.cpp index 386267017..4a3acf493 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1769,7 +1769,7 @@ void Game::run() updateProfilerGraphs(&graph); // Update if minimap has been disabled by the server - flags.show_minimap = client->shouldShowMinimap(); + flags.show_minimap &= client->shouldShowMinimap(); } } diff --git a/src/script/lua_api/l_minimap.cpp b/src/script/lua_api/l_minimap.cpp index bbe9aef82..cb0245576 100644 --- a/src/script/lua_api/l_minimap.cpp +++ b/src/script/lua_api/l_minimap.cpp @@ -118,17 +118,21 @@ int LuaMinimap::l_toggle_shape(lua_State *L) int LuaMinimap::l_show(lua_State *L) { - Client *client = getClient(L); - assert(client); - client->setMinimapShownByMod(true); + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + if (m->getMinimapMode() == MINIMAP_MODE_OFF) + m->setMinimapMode(MINIMAP_MODE_SURFACEx1); return 1; } int LuaMinimap::l_hide(lua_State *L) { - Client *client = getClient(L); - assert(client); - client->setMinimapShownByMod(false); + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + + if (m->getMinimapMode() != MINIMAP_MODE_OFF) + m->setMinimapMode(MINIMAP_MODE_OFF); return 1; } -- cgit v1.2.3 From d31750cb9375a961bf225ede210435751edfe7c9 Mon Sep 17 00:00:00 2001 From: red-001 Date: Fri, 17 Mar 2017 18:20:13 +0000 Subject: Give CSM access to use `core.colorize()` (#5113) --- builtin/common/misc_helpers.lua | 32 ++++++++++++++++++++++++++++++++ builtin/game/misc.lua | 31 ------------------------------- clientmods/preview/init.lua | 6 ++++++ doc/client_lua_api.md | 38 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 74 insertions(+), 33 deletions(-) (limited to 'clientmods') diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index 70b23600a..e145a5bfc 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -638,3 +638,35 @@ if INIT == "client" or INIT == "mainmenu" then return core.formspec_escape(fgettext_ne(text, ...)) end end + +-- Client-sided mods don't have access to getbool +if core.setting_getbool and core.setting_getbool("disable_escape_sequences") then + + function core.get_color_escape_sequence(color) + return "" + end + + function core.get_background_escape_sequence(color) + return "" + end + + function core.colorize(color, message) + return message + end + +else + + local ESCAPE_CHAR = string.char(0x1b) + function core.get_color_escape_sequence(color) + return ESCAPE_CHAR .. "(c@" .. color .. ")" + end + + function core.get_background_escape_sequence(color) + return ESCAPE_CHAR .. "(b@" .. color .. ")" + end + + function core.colorize(color, message) + return core.get_color_escape_sequence(color) .. message .. core.get_color_escape_sequence("#ffffff") + end + +end diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua index 25376c180..618d4d97f 100644 --- a/builtin/game/misc.lua +++ b/builtin/game/misc.lua @@ -170,37 +170,6 @@ function core.http_add_fetch(httpenv) return httpenv end -if minetest.setting_getbool("disable_escape_sequences") then - - function core.get_color_escape_sequence(color) - return "" - end - - function core.get_background_escape_sequence(color) - return "" - end - - function core.colorize(color, message) - return message - end - -else - - local ESCAPE_CHAR = string.char(0x1b) - function core.get_color_escape_sequence(color) - return ESCAPE_CHAR .. "(c@" .. color .. ")" - end - - function core.get_background_escape_sequence(color) - return ESCAPE_CHAR .. "(b@" .. color .. ")" - end - - function core.colorize(color, message) - return core.get_color_escape_sequence(color) .. message .. core.get_color_escape_sequence("#ffffff") - end - -end - function core.close_formspec(player_name, formname) return minetest.show_formspec(player_name, formname, "") end diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 25a61da51..008f7ac14 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -40,6 +40,12 @@ core.register_chatcommand("dump", { end, }) +core.register_chatcommand("colorize_test", { + func = function(param) + return true, core.colorize("red", param) + end, +}) + core.register_chatcommand("test_node", { func = function(param) core.display_chat_message(dump(core.get_node({x=0, y=0, z=0}))) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 70716ee41..5fba66c69 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -787,12 +787,12 @@ Call these functions only at load time! extra arguments and return the result * `fgettext(string, ...)` : returns string * same as fgettext_ne(), but calls core.formspec_escape before returning result -* `show_formspec(formname, formspec)` : returns true on success - * Shows a formspec to the player ### UI * `minetest.ui.minimap` * Reference to the minimap object. See `Minimap` class reference for methods. +* `show_formspec(formname, formspec)` : returns true on success + * Shows a formspec to the player Class reference --------------- @@ -837,3 +837,37 @@ Definition tables func = function(name, param), -- Called when command is run. -- Returns boolean success and text output. } + +Escape sequences +---------------- +Most text can contain escape sequences, that can for example color the text. +There are a few exceptions: tab headers, dropdowns and vertical labels can't. +The following functions provide escape sequences: +* `core.get_color_escape_sequence(color)`: + * `color` is a ColorString + * The escape sequence sets the text color to `color` +* `core.colorize(color, message)`: + * Equivalent to: + `core.get_color_escape_sequence(color) .. + message .. + core.get_color_escape_sequence("#ffffff")` +* `color.get_background_escape_sequence(color)` + * `color` is a ColorString + * The escape sequence sets the background of the whole text element to + `color`. Only defined for item descriptions and tooltips. + +`ColorString` +------------- +`#RGB` defines a color in hexadecimal format. + +`#RGBA` defines a color in hexadecimal format and alpha channel. + +`#RRGGBB` defines a color in hexadecimal format. + +`#RRGGBBAA` defines a color in hexadecimal format and alpha channel. + +Named colors are also supported and are equivalent to +[CSS Color Module Level 4](http://dev.w3.org/csswg/css-color/#named-colors). +To specify the value of the alpha channel, append `#AA` to the end of the color name +(e.g. `colorname#08`). For named colors the hexadecimal string representing the alpha +value must (always) be two hexadecima \ No newline at end of file -- cgit v1.2.3 From 9efc5da0fb7d276deff55db6e4eb89d24ca72b5d Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Wed, 22 Mar 2017 15:13:03 -0500 Subject: [CSM] Add function to get player names in range (#5435) * [CSM] Add function to get currently connected player names --- clientmods/preview/init.lua | 9 ++++++++- doc/client_lua_api.md | 6 +++++- src/script/lua_api/l_client.cpp | 17 +++++++++++++++++ src/script/lua_api/l_client.h | 3 +++ 4 files changed, 33 insertions(+), 2 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 008f7ac14..c57a62155 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -102,7 +102,7 @@ core.register_on_punchnode(function(pos, node) print(dump(itemstack:get_count())) print(dump(itemstack:get_wear())) print(dump(itemstack:get_meta())) - print(dump(itemstack:get_metadata())) + print(dump(itemstack:get_metadata() print(dump(itemstack:is_known())) --print(dump(itemstack:get_definition())) print(dump(itemstack:get_tool_capabilities())) @@ -120,3 +120,10 @@ core.register_on_punchnode(function(pos, node) print("node:" .. dump(node)) return false end) + +-- This is an example function to ensure it's working properly, should be removed before merge +core.register_chatcommand("list_players", { + func = function(param) + core.display_chat_message(dump(core.get_player_names())) + end +}) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 5fba66c69..ced1a40a4 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -737,6 +737,10 @@ Call these functions only at load time! * `minetest.get_wielded_item()` * Returns the itemstack the local player is holding +### Client Environment +* `minetest.get_player_names()` + * Returns list of player names on server + ### Misc. * `minetest.parse_json(string[, nullvalue])`: returns something * Convert a string containing JSON data into the Lua equivalent @@ -870,4 +874,4 @@ Named colors are also supported and are equivalent to [CSS Color Module Level 4](http://dev.w3.org/csswg/css-color/#named-colors). To specify the value of the alpha channel, append `#AA` to the end of the color name (e.g. `colorname#08`). For named colors the hexadecimal string representing the alpha -value must (always) be two hexadecima \ No newline at end of file +value must (always) be two hexadecima diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 1673a62ce..52c7f6f30 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -69,6 +69,22 @@ int ModApiClient::l_display_chat_message(lua_State *L) return 1; } +// get_player_names() +int ModApiClient::l_get_player_names(lua_State *L) +{ + const std::list &plist = getClient(L)->getConnectedPlayerNames(); + lua_createtable(L, plist.size(), 0); + int newTable = lua_gettop(L); + int index = 1; + std::list::const_iterator iter; + for (iter = plist.begin(); iter != plist.end(); iter++) { + lua_pushstring(L, (*iter).c_str()); + lua_rawseti(L, newTable, index); + index++; + } + return 1; +} + // show_formspec(formspec) int ModApiClient::l_show_formspec(lua_State *L) { @@ -154,6 +170,7 @@ void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); API_FCT(display_chat_message); + API_FCT(get_player_names); API_FCT(set_last_run_mod); API_FCT(get_last_run_mod); API_FCT(show_formspec); diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index def9b48a3..fcf8c39ea 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -31,6 +31,9 @@ private: // display_chat_message(message) static int l_display_chat_message(lua_State *L); + + // get_player_names() + static int l_get_player_names(lua_State *L); // show_formspec(name, fornspec) static int l_show_formspec(lua_State *L); -- cgit v1.2.3 From 63ac62ec8abe30f0d6dd2cfe0ddaab291c36893f Mon Sep 17 00:00:00 2001 From: red-001 Date: Sat, 1 Apr 2017 12:40:56 +0100 Subject: [CSM] Add function and chat command to disconnect from server. (#5487) --- clientmods/preview/init.lua | 7 +++++++ doc/client_lua_api.md | 3 +++ src/client.cpp | 10 +++++----- src/client.h | 1 + src/script/lua_api/l_client.cpp | 18 ++++++++++++++++++ src/script/lua_api/l_client.h | 3 +++ 6 files changed, 37 insertions(+), 5 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index c57a62155..07464e927 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -127,3 +127,10 @@ core.register_chatcommand("list_players", { core.display_chat_message(dump(core.get_player_names())) end }) + +core.register_chatcommand("disconnect", { + description = "Exit to main menu", + func = function(param) + core.disconnect() + end, +}) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index d5ccef5d3..deb5bfb13 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -698,6 +698,9 @@ Call these functions only at load time! ### Client Environment * `minetest.get_player_names()` * Returns list of player names on server +* `minetest.disconnect()` + * Disconnect from the server and exit to main menu. + * Returns `false` if the client is already disconnecting otherwise returns `true`. ### Misc. * `minetest.parse_json(string[, nullvalue])`: returns something diff --git a/src/client.cpp b/src/client.cpp index 8bbaa83bd..e710624d5 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -260,7 +260,8 @@ Client::Client( m_localdb(NULL), m_script(NULL), m_mod_storage_save_timer(10.0f), - m_game_ui_flags(game_ui_flags) + m_game_ui_flags(game_ui_flags), + m_shutdown(false) { // Add local player m_env.setLocalPlayer(new LocalPlayer(this, playername)); @@ -346,6 +347,7 @@ const ModSpec* Client::getModSpec(const std::string &modname) const void Client::Stop() { + m_shutdown = true; // Don't disable this part when modding is disabled, it's used in builtin m_script->on_shutdown(); //request all client managed threads to stop @@ -361,14 +363,12 @@ void Client::Stop() bool Client::isShutdown() { - - if (!m_mesh_update_thread.isRunning()) return true; - - return false; + return m_shutdown || !m_mesh_update_thread.isRunning(); } Client::~Client() { + m_shutdown = true; m_con.Disconnect(); m_mesh_update_thread.stop(); diff --git a/src/client.h b/src/client.h index 84adf81d8..e565acd93 100644 --- a/src/client.h +++ b/src/client.h @@ -737,6 +737,7 @@ private: float m_mod_storage_save_timer; GameUIFlags *m_game_ui_flags; + bool m_shutdown; DISABLE_CLASS_COPY(Client); }; diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 7cb89188d..5f9474702 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -25,8 +25,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gettext.h" #include "l_internal.h" #include "lua_api/l_item.h" +#include "mainmenumanager.h" #include "util/string.h" +extern MainGameCallback *g_gamecallback; + int ModApiClient::l_get_current_modname(lua_State *L) { lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); @@ -107,6 +110,20 @@ int ModApiClient::l_send_respawn(lua_State *L) return 0; } +// disconnect() +int ModApiClient::l_disconnect(lua_State *L) +{ + // Stops badly written Lua code form causing boot loops + if (getClient(L)->isShutdown()) { + lua_pushboolean(L, false); + return 1; + } + + g_gamecallback->disconnect(); + lua_pushboolean(L, true); + return 1; +} + // gettext(text) int ModApiClient::l_gettext(lua_State *L) { @@ -178,4 +195,5 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_node); API_FCT(get_node_or_nil); API_FCT(get_wielded_item); + API_FCT(disconnect); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index b79cc670d..d7f92ac1c 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -41,6 +41,9 @@ private: // send_respawn() static int l_send_respawn(lua_State *L); + // disconnect() + static int l_disconnect(lua_State *L); + // gettext(text) static int l_gettext(lua_State *L); -- cgit v1.2.3 From 88b9b9652ab77f91eaa7c6e40b8a48e3a35a7948 Mon Sep 17 00:00:00 2001 From: red-001 Date: Thu, 6 Apr 2017 21:50:45 +0100 Subject: [CSM] Add function to get the server protocol version. (#5529) --- clientmods/preview/init.lua | 1 + doc/client_lua_api.md | 3 +++ src/script/lua_api/l_client.cpp | 8 ++++++++ src/script/lua_api/l_client.h | 3 +++ 4 files changed, 15 insertions(+) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 07464e927..3c96fae55 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -69,6 +69,7 @@ core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") modstorage:set_string("current_mod", modname) print(modstorage:get_string("current_mod")) + print("Server version:" .. core.get_protocol_version()) preview_minimap() end) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 25055c98a..6d62de8a2 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -696,6 +696,9 @@ Call these functions only at load time! * `minetest.disconnect()` * Disconnect from the server and exit to main menu. * Returns `false` if the client is already disconnecting otherwise returns `true`. +* `minetest.get_protocol_version()` + * Returns the protocol version of the server. + * Might not be accurate at start up as the client might not be connected to the server yet, in that case it will return 0. ### Misc. * `minetest.parse_json(string[, nullvalue])`: returns something diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 458c1d1f4..0f4d7eaae 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -234,6 +234,13 @@ int ModApiClient::l_sound_stop(lua_State *L) return 0; } +// get_protocol_version() +int ModApiClient::l_get_protocol_version(lua_State *L) +{ + lua_pushinteger(L, getClient(L)->getProtoVersion()); + return 1; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -251,4 +258,5 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_meta); API_FCT(sound_play); API_FCT(sound_stop); + API_FCT(get_protocol_version); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 4e7f63d6a..478b8ed6c 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -69,6 +69,9 @@ private: static int l_sound_stop(lua_State *L); + // get_protocol_version() + static int l_get_protocol_version(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; -- cgit v1.2.3 From f73534640a18709921519ee43110292cf658e67f Mon Sep 17 00:00:00 2001 From: Vincent Glize Date: Sat, 8 Apr 2017 08:20:30 +0200 Subject: [CSM] Add event on_connect player API lua (#5540) * Add event on_connect player API lua --- builtin/client/register.lua | 1 + clientmods/preview/init.lua | 4 ++++ doc/client_lua_api.md | 2 ++ src/client.cpp | 4 ++++ src/script/cpp_api/s_client.cpp | 11 +++++++++++ src/script/cpp_api/s_client.h | 2 ++ 6 files changed, 24 insertions(+) (limited to 'clientmods') diff --git a/builtin/client/register.lua b/builtin/client/register.lua index 1c3966eda..e6ce25654 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -60,6 +60,7 @@ end core.registered_globalsteps, core.register_globalstep = make_registration() core.registered_on_shutdown, core.register_on_shutdown = make_registration() +core.registered_on_connect, core.register_on_connect = make_registration() core.registered_on_receiving_chat_messages, core.register_on_receiving_chat_messages = make_registration() core.registered_on_sending_chat_messages, core.register_on_sending_chat_messages = make_registration() core.registered_on_death, core.register_on_death = make_registration() diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 3c96fae55..5c0628bfe 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -6,6 +6,10 @@ core.register_on_shutdown(function() print("[PREVIEW] shutdown client") end) +core.register_on_connect(function() + print("[PREVIEW] Player connection completed") +end) + -- This is an example function to ensure it's working properly, should be removed before merge core.register_on_receiving_chat_messages(function(message) print("[PREVIEW] Received message " .. message) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 6d62de8a2..d68f90dec 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -639,6 +639,8 @@ Call these functions only at load time! * **Warning**: If the client terminates abnormally (i.e. crashes), the registered callbacks **will likely not be run**. Data should be saved at semi-frequent intervals as well as on server shutdown. +* `minetest.register_on_connect(func())` + * Called at the end of client connection (when player is loaded onto map) * `minetest.register_on_receiving_chat_message(func(name, message))` * Called always when a client receive a message * Return `true` to mark the message as handled, which means that it will not be shown to chat diff --git a/src/client.cpp b/src/client.cpp index e710624d5..3a3e33cfd 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1864,6 +1864,10 @@ void Client::afterContentReceived(IrrlichtDevice *device) m_state = LC_Ready; sendReady(); + + if (g_settings->getBool("enable_client_modding")) + m_script->on_connect(); + text = wgettext("Done!"); draw_load_screen(text, device, guienv, 0, 100); infostream<<"Client::afterContentReceived() done"< Date: Mon, 10 Apr 2017 20:13:20 +0100 Subject: [CSM] Move `.list_players` and `.disconnect` to builtin. (#5550) --- builtin/client/chatcommands.lua | 15 +++++++++++++++ clientmods/preview/init.lua | 13 ------------- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'clientmods') diff --git a/builtin/client/chatcommands.lua b/builtin/client/chatcommands.lua index 7a1b4b6b7..bb5b905d8 100644 --- a/builtin/client/chatcommands.lua +++ b/builtin/client/chatcommands.lua @@ -34,3 +34,18 @@ core.register_on_sending_chat_messages(function(message) return true end) + +core.register_chatcommand("list_players", { + description = "List online players", + func = function(param) + local players = table.concat(core.get_player_names(), ", ") + core.display_chat_message("Online players: " .. players) + end +}) + +core.register_chatcommand("disconnect", { + description = "Exit to main menu", + func = function(param) + core.disconnect() + end, +}) diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 5c0628bfe..df07f8c3f 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -126,16 +126,3 @@ core.register_on_punchnode(function(pos, node) return false end) --- This is an example function to ensure it's working properly, should be removed before merge -core.register_chatcommand("list_players", { - func = function(param) - core.display_chat_message(dump(core.get_player_names())) - end -}) - -core.register_chatcommand("disconnect", { - description = "Exit to main menu", - func = function(param) - core.disconnect() - end, -}) -- cgit v1.2.3 From e80a83d1cb9d01273ddca1c075c25cd01c291ca7 Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Fri, 14 Apr 2017 02:04:41 -0500 Subject: [CSM] Add function to set minimap shape (#5569) * [CSM] Add function to set minimap shape Also deprecates `toggle_shape`. * Oh fish, I messed that one up! * Fix Style * Sorry, I missed something I still had the `luamethod` call in there! * Add getters * Remove extra line * Remove useless variable Please review again @nerzhul . Thanks! * Satisfy nerzhul --- clientmods/preview/init.lua | 2 +- doc/client_lua_api.md | 3 ++- src/minimap.cpp | 22 ++++++++++++++++++++++ src/minimap.h | 7 +++++++ src/script/lua_api/l_minimap.cpp | 18 +++++++++++++++--- src/script/lua_api/l_minimap.h | 3 ++- 6 files changed, 49 insertions(+), 6 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index df07f8c3f..4b31fa323 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -62,7 +62,7 @@ local function preview_minimap() minimap:set_mode(4) minimap:show() minimap:set_pos({x=5, y=50, z=5}) - minimap:toggle_shape() + minimap:set_shape(math.random(0, 1)) print("[PREVIEW] Minimap: mode => " .. dump(minimap:get_mode()) .. " position => " .. dump(minimap:get_pos()) .. diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 43a317a84..b2aeb3f25 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -779,7 +779,8 @@ An interface to manipulate minimap on client UI * `get_angle()`: returns the current minimap angle in degrees * `set_mode(mode)`: sets the minimap mode (0 to 6) * `get_mode()`: returns the current minimap mode -* `toggle_shape()`: toggles minimap shape to round or square. +* `set_shape(shape)`: Sets the minimap shape. (0 = square, 1 = round) +* `get_shape()`: Gets the minimap shape. (0 = square, 1 = round) ### LocalPlayer An interface to retrieve information about the player. The player is diff --git a/src/minimap.cpp b/src/minimap.cpp index a7f4822c9..500f49828 100644 --- a/src/minimap.cpp +++ b/src/minimap.cpp @@ -272,6 +272,28 @@ void Minimap::toggleMinimapShape() m_minimap_update_thread->deferUpdate(); } +void Minimap::setMinimapShape(MinimapShape shape) +{ + MutexAutoLock lock(m_mutex); + + if (shape == MINIMAP_SHAPE_SQUARE) + data->minimap_shape_round = false; + else if (shape == MINIMAP_SHAPE_ROUND) + data->minimap_shape_round = true; + + g_settings->setBool("minimap_shape_round", data->minimap_shape_round); + m_minimap_update_thread->deferUpdate(); +} + +MinimapShape Minimap::getMinimapShape() +{ + if (data->minimap_shape_round) { + return MINIMAP_SHAPE_ROUND; + } else { + return MINIMAP_SHAPE_SQUARE; + } +} + void Minimap::setMinimapMode(MinimapMode mode) { static const MinimapModeDef modedefs[MINIMAP_MODE_COUNT] = { diff --git a/src/minimap.h b/src/minimap.h index eb0ae1cf4..c50530335 100644 --- a/src/minimap.h +++ b/src/minimap.h @@ -45,6 +45,11 @@ enum MinimapMode { MINIMAP_MODE_COUNT, }; +enum MinimapShape { + MINIMAP_SHAPE_SQUARE, + MINIMAP_SHAPE_ROUND, +}; + struct MinimapModeDef { bool is_radar; u16 scan_height; @@ -128,6 +133,8 @@ public: void setMinimapMode(MinimapMode mode); MinimapMode getMinimapMode() const { return data->mode; } void toggleMinimapShape(); + void setMinimapShape(MinimapShape shape); + MinimapShape getMinimapShape(); video::ITexture *getMinimapTexture(); diff --git a/src/script/lua_api/l_minimap.cpp b/src/script/lua_api/l_minimap.cpp index c68602909..f32a07ce8 100644 --- a/src/script/lua_api/l_minimap.cpp +++ b/src/script/lua_api/l_minimap.cpp @@ -108,12 +108,23 @@ int LuaMinimap::l_set_mode(lua_State *L) return 1; } -int LuaMinimap::l_toggle_shape(lua_State *L) +int LuaMinimap::l_set_shape(lua_State *L) +{ + LuaMinimap *ref = checkobject(L, 1); + Minimap *m = getobject(ref); + if (!lua_isnumber(L, 2)) + return 0; + + m->setMinimapShape((MinimapShape)lua_tonumber(L, 2)); + return 0; +} + +int LuaMinimap::l_get_shape(lua_State *L) { LuaMinimap *ref = checkobject(L, 1); Minimap *m = getobject(ref); - m->toggleMinimapShape(); + lua_pushnumber(L, (int)m->getMinimapShape()); return 1; } @@ -210,6 +221,7 @@ const luaL_Reg LuaMinimap::methods[] = { luamethod(LuaMinimap, set_angle), luamethod(LuaMinimap, get_mode), luamethod(LuaMinimap, set_mode), - luamethod(LuaMinimap, toggle_shape), + luamethod(LuaMinimap, set_shape), + luamethod(LuaMinimap, get_shape), {0,0} }; diff --git a/src/script/lua_api/l_minimap.h b/src/script/lua_api/l_minimap.h index 8be72b8e7..ba702b0b1 100644 --- a/src/script/lua_api/l_minimap.h +++ b/src/script/lua_api/l_minimap.h @@ -45,7 +45,8 @@ private: static int l_show(lua_State *L); static int l_hide(lua_State *L); - static int l_toggle_shape(lua_State *L); + static int l_set_shape(lua_State *L); + static int l_get_shape(lua_State *L); Minimap *m_minimap; -- cgit v1.2.3 From dc5bc6cac7b81ab27e0064bc25b5fd1d8d617340 Mon Sep 17 00:00:00 2001 From: Vincent Glize Date: Sat, 29 Apr 2017 12:08:16 +0200 Subject: [CSM] Add event on_place_node API lua (#5548) * [CSM] Add event on_place_node API lua --- builtin/client/register.lua | 1 + clientmods/preview/init.lua | 7 +++++++ doc/client_lua_api.md | 2 ++ src/game.cpp | 3 +++ src/script/common/c_content.cpp | 44 +++++++++++++++++++++++++++++++++++++++++ src/script/common/c_content.h | 6 ++++++ src/script/cpp_api/s_base.cpp | 15 ++------------ src/script/cpp_api/s_base.h | 1 - src/script/cpp_api/s_client.cpp | 18 +++++++++++++++++ src/script/cpp_api/s_client.h | 3 +++ src/script/cpp_api/s_entity.cpp | 2 +- src/script/cpp_api/s_item.cpp | 23 +-------------------- 12 files changed, 88 insertions(+), 37 deletions(-) (limited to 'clientmods') diff --git a/builtin/client/register.lua b/builtin/client/register.lua index e6ce25654..b35ecc849 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -69,3 +69,4 @@ core.registered_on_damage_taken, core.register_on_damage_taken = make_registrati core.registered_on_formspec_input, core.register_on_formspec_input = make_registration() core.registered_on_dignode, core.register_on_dignode = make_registration() core.registered_on_punchnode, core.register_on_punchnode = make_registration() +core.registered_on_placenode, core.register_on_placenode = make_registration() diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 4b31fa323..255c0b83f 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -10,6 +10,13 @@ core.register_on_connect(function() print("[PREVIEW] Player connection completed") end) +core.register_on_placenode(function(pointed_thing, node) + print("The local player place a node!") + print("pointed_thing :" .. dump(pointed_thing)) + print("node placed :" .. dump(node)) + return false +end) + -- This is an example function to ensure it's working properly, should be removed before merge core.register_on_receiving_chat_messages(function(message) print("[PREVIEW] Received message " .. message) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 86fcd02a7..d435c4aae 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -667,6 +667,8 @@ Call these functions only at load time! * Called when the local player punches a node * Newest functions are called first * If any function returns true, the punch is ignored +* `minetest.register_on_placenode(function(pointed_thing, node))` + * Called when a node has been placed ### Sounds * `minetest.sound_play(spec, parameters)`: returns a handle * `spec` is a `SimpleSoundSpec` diff --git a/src/game.cpp b/src/game.cpp index eb59ee5ae..12fe6a6e9 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3730,6 +3730,9 @@ void Game::handlePointingAtNode(const PointedThing &pointed, const ItemDefinitio // Read the sound soundmaker->m_player_rightpunch_sound = playeritem_def.sound_place; + + if (client->moddingEnabled()) + client->getScript()->on_placenode(pointed, playeritem_def); } else { soundmaker->m_player_rightpunch_sound = SimpleSoundSpec(); diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 573347b4c..5fe5af58d 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "mg_schematic.h" #include "noise.h" +#include "util/pointedthing.h" #include struct EnumString es_TileAnimationType[] = @@ -117,6 +118,16 @@ void read_item_definition(lua_State* L, int index, def.node_placement_prediction); } +/******************************************************************************/ +void push_item_definition(lua_State *L, const ItemDefinition &i) +{ + lua_newtable(L); + lua_pushstring(L, i.name.c_str()); + lua_setfield(L, -2, "name"); + lua_pushstring(L, i.description.c_str()); + lua_setfield(L, -2, "description"); +} + /******************************************************************************/ void read_object_properties(lua_State *L, int index, ObjectProperties *prop, IItemDefManager *idef) @@ -1427,3 +1438,36 @@ void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion) } lua_pop(L, 1); // Pop value } + +void push_pointed_thing(lua_State *L, const PointedThing &pointed) +{ + lua_newtable(L); + if (pointed.type == POINTEDTHING_NODE) { + lua_pushstring(L, "node"); + lua_setfield(L, -2, "type"); + push_v3s16(L, pointed.node_undersurface); + lua_setfield(L, -2, "under"); + push_v3s16(L, pointed.node_abovesurface); + lua_setfield(L, -2, "above"); + } else if (pointed.type == POINTEDTHING_OBJECT) { + lua_pushstring(L, "object"); + lua_setfield(L, -2, "type"); + push_objectRef(L, pointed.object_id); + lua_setfield(L, -2, "ref"); + } else { + lua_pushstring(L, "nothing"); + lua_setfield(L, -2, "type"); + } +} + +void push_objectRef(lua_State *L, const u16 id) +{ + // Get core.object_refs[i] + lua_getglobal(L, "core"); + lua_getfield(L, -1, "object_refs"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnumber(L, id); + lua_gettable(L, -2); + lua_remove(L, -2); // object_refs + lua_remove(L, -2); // core +} diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index c701c0384..219c5eb7c 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -88,6 +88,8 @@ void push_tool_capabilities (lua_State *L, void read_item_definition (lua_State *L, int index, const ItemDefinition &default_def, ItemDefinition &def); +void push_item_definition (lua_State *L, + const ItemDefinition &i); void read_object_properties (lua_State *L, int index, ObjectProperties *prop, IItemDefManager *idef); @@ -162,6 +164,10 @@ bool push_json_value (lua_State *L, void read_json_value (lua_State *L, Json::Value &root, int index, u8 recursion = 0); +void push_pointed_thing (lua_State *L, const PointedThing &pointed); + +void push_objectRef (lua_State *L, const u16 id); + extern struct EnumString es_TileAnimationType[]; #endif /* C_CONTENT_H_ */ diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 6a843810f..e72af22c6 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -42,6 +42,7 @@ extern "C" { #include #include +#include "script/common/c_content.h" #include @@ -320,22 +321,10 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L, if (cobj == NULL || cobj->getId() == 0) { ObjectRef::create(L, cobj); } else { - objectrefGet(L, cobj->getId()); + push_objectRef(L, cobj->getId()); } } -void ScriptApiBase::objectrefGet(lua_State *L, u16 id) -{ - // Get core.object_refs[i] - lua_getglobal(L, "core"); - lua_getfield(L, -1, "object_refs"); - luaL_checktype(L, -1, LUA_TTABLE); - lua_pushnumber(L, id); - lua_gettable(L, -2); - lua_remove(L, -2); // object_refs - lua_remove(L, -2); // core -} - Server* ScriptApiBase::getServer() { return dynamic_cast(m_gamedef); diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 19d71df65..5b047a081 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -115,7 +115,6 @@ protected: void setGuiEngine(GUIEngine* guiengine) { m_guiengine = guiengine; } void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj); - void objectrefGet(lua_State *L, u16 id); RecursiveMutex m_luastackmutex; std::string m_last_run_mod; diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index a8a7d5e26..4bc368d1d 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "common/c_converter.h" #include "common/c_content.h" +#include "s_item.h" void ScriptApiClient::on_shutdown() { @@ -189,6 +190,23 @@ bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node) return blocked; } +bool ScriptApiClient::on_placenode(const PointedThing &pointed, const ItemDefinition &item) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_placenode + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_placenode"); + + // Push data + push_pointed_thing(L, pointed); + push_item_definition(L, item); + + // Call functions + runCallbacks(2, RUN_CALLBACKS_MODE_OR); + return lua_toboolean(L, -1); +} + 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 94a597b2c..f252cf499 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -21,8 +21,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef S_CLIENT_H_ #define S_CLIENT_H_ +#include "util/pointedthing.h" #include "cpp_api/s_base.h" #include "mapnode.h" +#include "itemdef.h" #include "util/string.h" #ifdef _CRT_MSVCP_CURRENT @@ -51,6 +53,7 @@ public: bool on_dignode(v3s16 p, MapNode node); bool on_punchnode(v3s16 p, MapNode node); + bool on_placenode(const PointedThing &pointed, const ItemDefinition &item); void setEnv(ClientEnvironment *env); }; diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp index 2e1d277e4..4c1e296d4 100644 --- a/src/script/cpp_api/s_entity.cpp +++ b/src/script/cpp_api/s_entity.cpp @@ -57,7 +57,7 @@ bool ScriptApiEntity::luaentity_Add(u16 id, const char *name) // Add object reference // This should be userdata with metatable ObjectRef - objectrefGet(L, id); + push_objectRef(L, id); luaL_checktype(L, -1, LUA_TUSERDATA); if (!luaL_checkudata(L, -1, "ObjectRef")) luaL_typerror(L, -1, "ObjectRef"); diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp index cbb833807..032018f2f 100644 --- a/src/script/cpp_api/s_item.cpp +++ b/src/script/cpp_api/s_item.cpp @@ -249,27 +249,6 @@ void ScriptApiItem::pushPointedThing(const PointedThing& pointed) { lua_State* L = getStack(); - lua_newtable(L); - if(pointed.type == POINTEDTHING_NODE) - { - lua_pushstring(L, "node"); - lua_setfield(L, -2, "type"); - push_v3s16(L, pointed.node_undersurface); - lua_setfield(L, -2, "under"); - push_v3s16(L, pointed.node_abovesurface); - lua_setfield(L, -2, "above"); - } - else if(pointed.type == POINTEDTHING_OBJECT) - { - lua_pushstring(L, "object"); - lua_setfield(L, -2, "type"); - objectrefGet(L, pointed.object_id); - lua_setfield(L, -2, "ref"); - } - else - { - lua_pushstring(L, "nothing"); - lua_setfield(L, -2, "type"); - } + push_pointed_thing(L, pointed); } -- cgit v1.2.3 From ae0d8f74d747fab2fbe5b4553818e0f938e3289d Mon Sep 17 00:00:00 2001 From: red-001 Date: Wed, 19 Apr 2017 14:16:54 +0100 Subject: Add function to get server info. --- clientmods/preview/init.lua | 6 +++++- doc/client_lua_api.md | 18 +++++++++++++----- src/client.cpp | 8 ++++---- src/client.h | 16 +++++++++++++--- src/game.cpp | 4 ++-- src/script/lua_api/l_client.cpp | 18 ++++++++++++++---- src/script/lua_api/l_client.h | 4 ++-- 7 files changed, 53 insertions(+), 21 deletions(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 255c0b83f..fb606b3f4 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -8,6 +8,11 @@ end) core.register_on_connect(function() print("[PREVIEW] Player connection completed") + local server_info = core.get_server_info() + print("Server version: " .. server_info.protocol_version) + print("Server ip: " .. server_info.ip) + print("Server address: " .. server_info.address) + print("Server port: " .. server_info.port) end) core.register_on_placenode(function(pointed_thing, node) @@ -80,7 +85,6 @@ core.after(2, function() print("[PREVIEW] loaded " .. modname .. " mod") modstorage:set_string("current_mod", modname) print(modstorage:get_string("current_mod")) - print("Server version:" .. core.get_protocol_version()) preview_minimap() end) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 3e81818ae..b76a406ea 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -702,11 +702,10 @@ Call these functions only at load time! * `minetest.disconnect()` * Disconnect from the server and exit to main menu. * Returns `false` if the client is already disconnecting otherwise returns `true`. -* `minetest.get_protocol_version()` - * Returns the protocol version of the server. - * Might not be accurate at start up as the client might not be connected to the server yet, in that case it will return 0. * `minetest.take_screenshot()` * Take a screenshot. +* `minetest.get_server_info()` + * Returns [server info](#server-info). ### Misc. * `minetest.parse_json(string[, nullvalue])`: returns something @@ -932,9 +931,18 @@ Can be obtained via `minetest.get_meta(pos)`. { params = " ", -- Short parameter description description = "Remove privilege from player", -- Full description - func = function(param), -- Called when command is run. - -- Returns boolean success and text output. + func = function(param), -- Called when command is run. + -- Returns boolean success and text output. } +### Server info +```lua +{ + address = "minetest.example.org", -- The domain name/IP address of a remote server or "" for a local server. + ip = "203.0.113.156", -- The IP address of the server. + port = 30000, -- The port the client is connected to. + protocol_version = 30 -- Will not be accurate at start up as the client might not be connected to the server yet, in that case it will be 0. +} +``` Escape sequences ---------------- diff --git a/src/client.cpp b/src/client.cpp index 3269c573a..1e17e7c11 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -58,6 +58,7 @@ Client::Client( IrrlichtDevice *device, const char *playername, const std::string &password, + const std::string &address_name, MapDrawControl &control, IWritableTextureSource *tsrc, IWritableShaderSource *shsrc, @@ -89,6 +90,7 @@ Client::Client( ), m_particle_manager(&m_env), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, ipv6, this), + m_address_name(address_name), m_device(device), m_camera(NULL), m_minimap_disabled_by_server(false), @@ -253,13 +255,11 @@ Client::~Client() delete m_minimap; } -void Client::connect(Address address, - const std::string &address_name, - bool is_local_server) +void Client::connect(Address address, bool is_local_server) { DSTACK(FUNCTION_NAME); - initLocalMapSaving(address, address_name, is_local_server); + initLocalMapSaving(address, m_address_name, is_local_server); m_con.SetTimeoutMs(0); m_con.Connect(address); diff --git a/src/client.h b/src/client.h index 0dd519308..11b670977 100644 --- a/src/client.h +++ b/src/client.h @@ -257,6 +257,7 @@ public: IrrlichtDevice *device, const char *playername, const std::string &password, + const std::string &address_name, MapDrawControl &control, IWritableTextureSource *tsrc, IWritableShaderSource *shsrc, @@ -284,9 +285,7 @@ public: The name of the local player should already be set when calling this, as it is sent in the initialization. */ - void connect(Address address, - const std::string &address_name, - bool is_local_server); + void connect(Address address, bool is_local_server); /* Stuff that references the environment is valid only as @@ -525,6 +524,16 @@ public: IrrlichtDevice *getDevice() const { return m_device; } + const Address getServerAddress() + { + return m_con.GetPeerAddress(PEER_ID_SERVER); + } + + const std::string &getAddressName() const + { + return m_address_name; + } + private: // Virtual methods from con::PeerHandler @@ -576,6 +585,7 @@ private: ClientEnvironment m_env; ParticleManager m_particle_manager; con::Connection m_con; + std::string m_address_name; IrrlichtDevice *m_device; Camera *m_camera; Minimap *m_minimap; diff --git a/src/game.cpp b/src/game.cpp index 7dd9c942d..be0cc8fd5 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2044,7 +2044,7 @@ bool Game::connectToServer(const std::string &playername, } client = new Client(device, - playername.c_str(), password, + playername.c_str(), password, *address, *draw_control, texture_src, shader_src, itemdef_manager, nodedef_manager, sound, eventmgr, connect_address.isIPv6(), &flags); @@ -2056,7 +2056,7 @@ bool Game::connectToServer(const std::string &playername, connect_address.print(&infostream); infostream << std::endl; - client->connect(connect_address, *address, + client->connect(connect_address, simple_singleplayer_mode || local_server_mode); /* diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index c982a2f11..7f89a4d5d 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -234,10 +234,20 @@ int ModApiClient::l_sound_stop(lua_State *L) return 0; } -// get_protocol_version() -int ModApiClient::l_get_protocol_version(lua_State *L) +// get_server_info() +int ModApiClient::l_get_server_info(lua_State *L) { - lua_pushinteger(L, getClient(L)->getProtoVersion()); + Client *client = getClient(L); + Address serverAddress = client->getServerAddress(); + lua_newtable(L); + lua_pushstring(L, client->getAddressName().c_str()); + lua_setfield(L, -2, "address"); + lua_pushstring(L, serverAddress.serializeString().c_str()); + lua_setfield(L, -2, "ip"); + lua_pushinteger(L, serverAddress.getPort()); + lua_setfield(L, -2, "port"); + lua_pushinteger(L, client->getProtoVersion()); + lua_setfield(L, -2, "protocol_version"); return 1; } @@ -265,6 +275,6 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_meta); API_FCT(sound_play); API_FCT(sound_stop); - API_FCT(get_protocol_version); + API_FCT(get_server_info); API_FCT(take_screenshot); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 6afcd996b..a36d7e51c 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -69,8 +69,8 @@ private: static int l_sound_stop(lua_State *L); - // get_protocol_version() - static int l_get_protocol_version(lua_State *L); + // get_server_info() + static int l_get_server_info(lua_State *L); static int l_take_screenshot(lua_State *L); -- cgit v1.2.3 From 5ebf8f945050e9c74a3bb6784a0844d1fb68bdff Mon Sep 17 00:00:00 2001 From: red-001 Date: Sat, 6 May 2017 20:12:44 +0100 Subject: [CSM] add `on_item_use` (#5544) --- builtin/client/register.lua | 1 + clientmods/preview/init.lua | 7 +++++++ doc/client_lua_api.md | 4 ++++ src/game.cpp | 3 ++- src/script/cpp_api/s_client.cpp | 17 +++++++++++++++++ src/script/cpp_api/s_client.h | 3 +++ 6 files changed, 34 insertions(+), 1 deletion(-) (limited to 'clientmods') diff --git a/builtin/client/register.lua b/builtin/client/register.lua index b35ecc849..6b12ddec8 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -70,3 +70,4 @@ core.registered_on_formspec_input, core.register_on_formspec_input = make_regist core.registered_on_dignode, core.register_on_dignode = make_registration() core.registered_on_punchnode, core.register_on_punchnode = make_registration() core.registered_on_placenode, core.register_on_placenode = make_registration() +core.registered_on_item_use, core.register_on_item_use = make_registration() diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index fb606b3f4..821f7c714 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -22,6 +22,13 @@ core.register_on_placenode(function(pointed_thing, node) return false end) +core.register_on_item_use(function(itemstack, pointed_thing) + print("The local player used an item!") + print("pointed_thing :" .. dump(pointed_thing)) + print("item = " .. itemstack:get_name()) + return false +end) + -- This is an example function to ensure it's working properly, should be removed before merge core.register_on_receiving_chat_messages(function(message) print("[PREVIEW] Received message " .. message) diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index a4293500f..19947a525 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -669,6 +669,10 @@ Call these functions only at load time! * If any function returns true, the punch is ignored * `minetest.register_on_placenode(function(pointed_thing, node))` * Called when a node has been placed +* `minetest.register_on_item_use(func(item, pointed_thing))` + * Called when the local player uses an item. + * Newest functions are called first. + * If any function returns true, the item use is not sent to server. ### Sounds * `minetest.sound_play(spec, parameters)`: returns a handle * `spec` is a `SimpleSoundSpec` diff --git a/src/game.cpp b/src/game.cpp index 416320e5d..61282b463 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3553,7 +3553,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) runData.repeat_rightclick_timer = 0; if (playeritem_def.usable && isLeftPressed()) { - if (getLeftClicked()) + if (getLeftClicked() && (!client->moddingEnabled() + || !client->getScript()->on_item_use(playeritem, pointed))) client->interact(4, pointed); } else if (pointed.type == POINTEDTHING_NODE) { ToolCapabilities playeritem_toolcap = diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 4bc368d1d..d5ec52407 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -207,6 +207,23 @@ bool ScriptApiClient::on_placenode(const PointedThing &pointed, const ItemDefini return lua_toboolean(L, -1); } +bool ScriptApiClient::on_item_use(const ItemStack &item, const PointedThing &pointed) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_item_use + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_item_use"); + + // Push data + LuaItemStack::create(L, item); + push_pointed_thing(L, pointed); + + // Call functions + runCallbacks(2, RUN_CALLBACKS_MODE_OR); + return lua_toboolean(L, -1); +} + 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 f252cf499..9133637a6 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -26,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapnode.h" #include "itemdef.h" #include "util/string.h" +#include "util/pointedthing.h" +#include "lua_api/l_item.h" #ifdef _CRT_MSVCP_CURRENT #include @@ -54,6 +56,7 @@ public: bool on_dignode(v3s16 p, MapNode node); 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); void setEnv(ClientEnvironment *env); }; -- cgit v1.2.3 From 673ac55a9db4728a6817e284196e7acdd8f3daaf Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 20 May 2017 10:12:37 +0200 Subject: [CSM] Fix crash when the minimap is disabled. Caused by e25a38e --- clientmods/preview/init.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'clientmods') diff --git a/clientmods/preview/init.lua b/clientmods/preview/init.lua index 821f7c714..f3992612a 100644 --- a/clientmods/preview/init.lua +++ b/clientmods/preview/init.lua @@ -78,6 +78,10 @@ core.register_chatcommand("test_node", { local function preview_minimap() local minimap = core.ui.minimap + if not minimap then + print("[PREVIEW] Minimap is disabled. Skipping.") + return + end minimap:set_mode(4) minimap:show() minimap:set_pos({x=5, y=50, z=5}) @@ -96,7 +100,9 @@ core.after(2, function() end) core.after(5, function() - core.ui.minimap:show() + if core.ui.minimap then + core.ui.minimap:show() + end print("[PREVIEW] Day count: " .. core.get_day_count() .. " time of day " .. core.get_timeofday()) -- cgit v1.2.3