From 2efae3ffd720095222c800e016286a45c9fe1e5c Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Sat, 21 Jan 2017 15:02:08 +0100 Subject: [CSM] Client side modding * rename GameScripting to ServerScripting * Make getBuiltinLuaPath static serverside * Add on_shutdown callback * Add on_receiving_chat_message & on_sending_chat_message callbacks * ScriptApiBase: use IGameDef instead of Server This permits to share common attribute between client & server * Enable mod security in client side modding without conditions --- src/script/lua_api/l_client.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/script/lua_api/l_client.cpp (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp new file mode 100644 index 000000000..9c478602a --- /dev/null +++ b/src/script/lua_api/l_client.cpp @@ -0,0 +1,33 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola +Copyright (C) 2017 nerzhul, 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 "l_client.h" +#include "l_internal.h" + +int ModApiClient::l_get_current_modname(lua_State *L) +{ + lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); + return 1; +} + +void ModApiClient::Initialize(lua_State *L, int top) +{ + API_FCT(get_current_modname); +} -- cgit v1.2.3 From cb3a61f8db6b7020dd69f7786a1086f6fe014dfc Mon Sep 17 00:00:00 2001 From: red-001 Date: Sat, 21 Jan 2017 21:44:37 +0000 Subject: [CSM] Add method that display chat to client-sided lua. (#5089) (#5091) * squashed: [Client-sided scripting] Don't register functions that don't work. (#5091) --- src/client.cpp | 6 +++--- src/client.h | 5 +++++ src/network/clientpackethandler.cpp | 4 ++-- src/script/clientscripting.cpp | 2 +- src/script/lua_api/l_base.cpp | 6 ++++++ src/script/lua_api/l_base.h | 8 ++++++++ src/script/lua_api/l_client.cpp | 12 ++++++++++++ src/script/lua_api/l_client.h | 1 + src/script/lua_api/l_util.cpp | 26 ++++++++++++++++++++++++++ src/script/lua_api/l_util.h | 2 ++ 10 files changed, 66 insertions(+), 6 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/client.cpp b/src/client.cpp index faf454b35..0af6b4595 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1584,7 +1584,7 @@ void Client::typeChatMessage(const std::wstring &message) // Show locally if (message[0] == L'/') { - m_chat_queue.push((std::wstring)L"issued command: " + message); + pushToChatQueue((std::wstring)L"issued command: " + message); } else { @@ -1593,7 +1593,7 @@ void Client::typeChatMessage(const std::wstring &message) LocalPlayer *player = m_env.getLocalPlayer(); assert(player != NULL); std::wstring name = narrow_to_wide(player->getName()); - m_chat_queue.push((std::wstring)L"<" + name + L"> " + message); + pushToChatQueue((std::wstring)L"<" + name + L"> " + message); } } } @@ -1867,7 +1867,7 @@ void Client::makeScreenshot(IrrlichtDevice *device) } else { sstr << "Failed to save screenshot '" << filename << "'"; } - m_chat_queue.push(narrow_to_wide(sstr.str())); + pushToChatQueue(narrow_to_wide(sstr.str())); infostream << sstr.str() << std::endl; image->drop(); } diff --git a/src/client.h b/src/client.h index 2fdade61a..584b13a90 100644 --- a/src/client.h +++ b/src/client.h @@ -557,6 +557,11 @@ public: void makeScreenshot(IrrlichtDevice *device); + inline void pushToChatQueue(const std::wstring &input) + { + m_chat_queue.push(input); + } + private: // Virtual methods from con::PeerHandler diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index f1c44c7d8..d0642c86a 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -142,7 +142,7 @@ void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt) } void Client::handleCommand_DenySudoMode(NetworkPacket* pkt) { - m_chat_queue.push(L"Password change denied. Password NOT changed."); + pushToChatQueue(L"Password change denied. Password NOT changed."); // reset everything and be sad deleteAuthData(); } @@ -414,7 +414,7 @@ void Client::handleCommand_ChatMessage(NetworkPacket* pkt) // If chat message not consummed by client lua API if (!m_script->on_receiving_message(wide_to_utf8(message))) { - m_chat_queue.push(message); + pushToChatQueue(message); } } diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index 43bc6f94e..9bf93eb83 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -49,6 +49,6 @@ ClientScripting::ClientScripting(Client *client): void ClientScripting::InitializeModApi(lua_State *L, int top) { - ModApiUtil::Initialize(L, top); + ModApiUtil::InitializeClient(L, top); ModApiClient::Initialize(L, top); } diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index 515a7d933..f2703718a 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -37,6 +37,12 @@ Server *ModApiBase::getServer(lua_State *L) return getScriptApiBase(L)->getServer(); } +#ifndef SERVER +Client *ModApiBase::getClient(lua_State *L) +{ + return getScriptApiBase(L)->getClient(); +} +#endif 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 641013dfd..dc1b1b226 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -28,6 +28,10 @@ extern "C" { #include } +#ifndef SERVER +#include "client.h" +#endif + class ScriptApiBase; class Server; class Environment; @@ -38,6 +42,10 @@ class ModApiBase { public: static ScriptApiBase* getScriptApiBase(lua_State *L); static Server* getServer(lua_State *L); + #ifndef SERVER + static Client* getClient(lua_State *L); + #endif // !SERVER + 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 9c478602a..f4c3812ac 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "l_client.h" #include "l_internal.h" +#include "util/string.h" int ModApiClient::l_get_current_modname(lua_State *L) { @@ -27,7 +28,18 @@ int ModApiClient::l_get_current_modname(lua_State *L) return 1; } +// display_chat_message(message) +int ModApiClient::l_display_chat_message(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + std::string message = luaL_checkstring(L, 1); + getClient(L)->pushToChatQueue(utf8_to_wide(message)); + return 1; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); + API_FCT(display_chat_message); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 332f00132..b4a57cb61 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -28,6 +28,7 @@ class ModApiClient : public ModApiBase private: // get_current_modname() static int l_get_current_modname(lua_State *L); + static int l_display_chat_message(lua_State *L); public: static void Initialize(lua_State *L, int top); diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index c26791646..277a874bf 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -526,6 +526,32 @@ void ModApiUtil::Initialize(lua_State *L, int top) API_FCT(get_version); } +void ModApiUtil::InitializeClient(lua_State *L, int top) +{ + API_FCT(log); + + 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); + + API_FCT(is_yes); + + API_FCT(get_builtin_path); + + API_FCT(compress); + API_FCT(decompress); + + API_FCT(encode_base64); + API_FCT(decode_base64); + + API_FCT(get_version); +} + void ModApiUtil::InitializeAsync(AsyncEngine& engine) { ASYNC_API_FCT(log); diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h index 9910704b3..eef32c0a1 100644 --- a/src/script/lua_api/l_util.h +++ b/src/script/lua_api/l_util.h @@ -110,6 +110,8 @@ private: public: static void Initialize(lua_State *L, int top); + static void InitializeClient(lua_State *L, int top); + static void InitializeAsync(AsyncEngine& engine); }; -- cgit v1.2.3 From d7bc346981e189851e490f2417ed015a38bca79b Mon Sep 17 00:00:00 2001 From: red-001 Date: Sun, 22 Jan 2017 08:05:09 +0000 Subject: [CSM] Add client-sided chat commands (#5092) --- builtin/client/chatcommands.lua | 28 ++++++++++++++++++++++++++++ builtin/client/init.lua | 1 + builtin/client/preview.lua | 7 +++++++ builtin/common/chatcommands.lua | 30 ++++++++++++++++++++++++++++++ builtin/game/chatcommands.lua | 29 +---------------------------- builtin/game/init.lua | 1 + src/client.cpp | 6 +----- src/script/lua_api/l_client.cpp | 23 +++++++++++++++++++++++ src/script/lua_api/l_client.h | 8 ++++++++ 9 files changed, 100 insertions(+), 33 deletions(-) create mode 100644 builtin/client/chatcommands.lua create mode 100644 builtin/common/chatcommands.lua (limited to 'src/script/lua_api/l_client.cpp') diff --git a/builtin/client/chatcommands.lua b/builtin/client/chatcommands.lua new file mode 100644 index 000000000..b49c222ef --- /dev/null +++ b/builtin/client/chatcommands.lua @@ -0,0 +1,28 @@ +-- Minetest: builtin/client/chatcommands.lua + + +core.register_on_sending_chat_messages(function(message) + if not (message:sub(1,1) == "/") then + return false + end + + core.display_chat_message("issued command: " .. message) + + local cmd, param = string.match(message, "^/([^ ]+) *(.*)") + if not param then + param = "" + end + + local cmd_def = core.registered_chatcommands[cmd] + + if cmd_def then + core.set_last_run_mod(cmd_def.mod_origin) + local success, message = cmd_def.func(param) + if message then + core.display_chat_message(message) + end + return true + end + + return false +end) \ No newline at end of file diff --git a/builtin/client/init.lua b/builtin/client/init.lua index e06dfc995..4797ac4b6 100644 --- a/builtin/client/init.lua +++ b/builtin/client/init.lua @@ -1,6 +1,7 @@ -- Minetest: builtin/client/init.lua local scriptpath = core.get_builtin_path()..DIR_DELIM local clientpath = scriptpath.."client"..DIR_DELIM +local commonpath = scriptpath.."common"..DIR_DELIM dofile(clientpath .. "register.lua") dofile(clientpath .. "preview.lua") diff --git a/builtin/client/preview.lua b/builtin/client/preview.lua index 4b277b0c6..c421791f5 100644 --- a/builtin/client/preview.lua +++ b/builtin/client/preview.lua @@ -22,3 +22,10 @@ end) 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_chatcommand("dump", { + func = function(name, param) + return true, dump(_G) + end, +}) \ No newline at end of file diff --git a/builtin/common/chatcommands.lua b/builtin/common/chatcommands.lua new file mode 100644 index 000000000..ef3a24410 --- /dev/null +++ b/builtin/common/chatcommands.lua @@ -0,0 +1,30 @@ +-- Minetest: builtin/common/chatcommands.lua + +core.registered_chatcommands = {} + +function core.register_chatcommand(cmd, def) + def = def or {} + def.params = def.params or "" + def.description = def.description or "" + def.privs = def.privs or {} + def.mod_origin = core.get_current_modname() or "??" + core.registered_chatcommands[cmd] = def +end + +function core.unregister_chatcommand(name) + if core.registered_chatcommands[name] then + core.registered_chatcommands[name] = nil + else + core.log("warning", "Not unregistering chatcommand " ..name.. + " because it doesn't exist.") + end +end + +function core.override_chatcommand(name, redefinition) + local chatcommand = core.registered_chatcommands[name] + assert(chatcommand, "Attempt to override non-existent chatcommand "..name) + for k, v in pairs(redefinition) do + rawset(chatcommand, k, v) + end + core.registered_chatcommands[name] = chatcommand +end \ No newline at end of file diff --git a/builtin/game/chatcommands.lua b/builtin/game/chatcommands.lua index 5d5955972..745b012e6 100644 --- a/builtin/game/chatcommands.lua +++ b/builtin/game/chatcommands.lua @@ -1,37 +1,10 @@ --- Minetest: builtin/chatcommands.lua +-- Minetest: builtin/game/chatcommands.lua -- -- Chat command handler -- -core.registered_chatcommands = {} core.chatcommands = core.registered_chatcommands -- BACKWARDS COMPATIBILITY -function core.register_chatcommand(cmd, def) - def = def or {} - def.params = def.params or "" - def.description = def.description or "" - def.privs = def.privs or {} - def.mod_origin = core.get_current_modname() or "??" - core.registered_chatcommands[cmd] = def -end - -function core.unregister_chatcommand(name) - if core.registered_chatcommands[name] then - core.registered_chatcommands[name] = nil - else - core.log("warning", "Not unregistering chatcommand " ..name.. - " because it doesn't exist.") - end -end - -function core.override_chatcommand(name, redefinition) - local chatcommand = core.registered_chatcommands[name] - assert(chatcommand, "Attempt to override non-existent chatcommand "..name) - for k, v in pairs(redefinition) do - rawset(chatcommand, k, v) - end - core.registered_chatcommands[name] = chatcommand -end core.register_on_chat_message(function(name, message) local cmd, param = string.match(message, "^/([^ ]+) *(.*)") diff --git a/builtin/game/init.lua b/builtin/game/init.lua index b5e2f7cca..793d9fe2b 100644 --- a/builtin/game/init.lua +++ b/builtin/game/init.lua @@ -22,6 +22,7 @@ dofile(gamepath.."deprecated.lua") dofile(gamepath.."misc.lua") dofile(gamepath.."privileges.lua") dofile(gamepath.."auth.lua") +dofile(commonpath .. "chatcommands.lua") dofile(gamepath.."chatcommands.lua") dofile(gamepath.."static_spawn.lua") dofile(gamepath.."detached_inventory.lua") diff --git a/src/client.cpp b/src/client.cpp index 0af6b4595..3a3e0673e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1582,11 +1582,7 @@ void Client::typeChatMessage(const std::wstring &message) sendChatMessage(message); // Show locally - if (message[0] == L'/') - { - pushToChatQueue((std::wstring)L"issued command: " + message); - } - else + if (message[0] != L'/') { // compatibility code if (m_proto_ver < 29) { diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index f4c3812ac..7eb340d78 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "l_client.h" #include "l_internal.h" #include "util/string.h" +#include "cpp_api/s_base.h" int ModApiClient::l_get_current_modname(lua_State *L) { @@ -28,6 +29,26 @@ int ModApiClient::l_get_current_modname(lua_State *L) return 1; } +// get_last_run_mod() +int ModApiClient::l_get_last_run_mod(lua_State *L) +{ + lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); + const char *current_mod = lua_tostring(L, -1); + if (current_mod == NULL || current_mod[0] == '\0') { + lua_pop(L, 1); + lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str()); + } + return 1; +} + +// set_last_run_mod(modname) +int ModApiClient::l_set_last_run_mod(lua_State *L) +{ + const char *mod = lua_tostring(L, 1); + getScriptApiBase(L)->setOriginDirect(mod); + return 0; +} + // display_chat_message(message) int ModApiClient::l_display_chat_message(lua_State *L) { @@ -42,4 +63,6 @@ void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); API_FCT(display_chat_message); + API_FCT(set_last_run_mod); + API_FCT(get_last_run_mod); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index b4a57cb61..e3106e742 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -28,8 +28,16 @@ class ModApiClient : public ModApiBase private: // get_current_modname() static int l_get_current_modname(lua_State *L); + + // display_chat_message(message) static int l_display_chat_message(lua_State *L); + // get_last_run_mod(n) + static int l_get_last_run_mod(lua_State *L); + + // set_last_run_mod(modname) + static int l_set_last_run_mod(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; -- cgit v1.2.3 From c42c53fccf87a3819ca78de52f8f20c47c4fbb9f Mon Sep 17 00:00:00 2001 From: red-001 Date: Tue, 24 Jan 2017 16:26:15 +0000 Subject: [CSM] Add local formspecs. (#5094) --- builtin/client/init.lua | 10 ++++++ builtin/client/preview.lua | 2 +- builtin/client/register.lua | 1 + builtin/common/misc_helpers.lua | 3 +- doc/client_lua_api.txt | 15 +++++++-- src/client.h | 6 ++++ src/game.cpp | 67 ++++++----------------------------------- src/guiFormSpecMenu.h | 4 +-- src/script/cpp_api/s_client.cpp | 24 +++++++++++++++ src/script/cpp_api/s_client.h | 7 ++++- src/script/lua_api/l_client.cpp | 45 +++++++++++++++++++++++++-- src/script/lua_api/l_client.h | 9 ++++++ 12 files changed, 126 insertions(+), 67 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/builtin/client/init.lua b/builtin/client/init.lua index dd218aab6..b204ee5e6 100644 --- a/builtin/client/init.lua +++ b/builtin/client/init.lua @@ -6,8 +6,18 @@ local commonpath = scriptpath.."common"..DIR_DELIM dofile(clientpath .. "register.lua") dofile(commonpath .. "after.lua") dofile(commonpath .. "chatcommands.lua") +dofile(clientpath .. "chatcommands.lua") dofile(clientpath .. "preview.lua") core.register_on_death(function() core.display_chat_message("You died.") + local formspec = "size[11,5.5]bgcolor[#320000b4;true]" .. + "label[4.85,1.35;" .. fgettext("You died.") .. "]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]" + core.show_formspec("bultin:death", formspec) +end) + +core.register_on_formspec_input(function(formname, fields) + if formname == "bultin:death" then + core.send_respawn() + end end) diff --git a/builtin/client/preview.lua b/builtin/client/preview.lua index 22e8bb97f..4c01d665f 100644 --- a/builtin/client/preview.lua +++ b/builtin/client/preview.lua @@ -32,7 +32,7 @@ end) -- This is an example function to ensure it's working properly, should be removed before merge core.register_chatcommand("dump", { - func = function(name, param) + func = function(param) return true, dump(_G) end, }) diff --git a/builtin/client/register.lua b/builtin/client/register.lua index 8b60c1222..1e6ac4342 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -62,5 +62,6 @@ core.registered_on_sending_chat_messages, core.register_on_sending_chat_messages 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() diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index c2dc7514d..70b23600a 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -606,7 +606,9 @@ if INIT == "mainmenu" then return nil end +end +if INIT == "client" or INIT == "mainmenu" then function fgettext_ne(text, ...) text = core.gettext(text) local arg = {n=select('#', ...), ...} @@ -636,4 +638,3 @@ if INIT == "mainmenu" then return core.formspec_escape(fgettext_ne(text, ...)) end end - diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 8ce487bf8..3170f4c84 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -699,7 +699,10 @@ Call these functions only at load time! * Called when server modified player's HP * `minetest.register_on_damage_taken(func(hp))` * Called when player take damages - +* `minetest.register_on_formspec_input(func(formname, fields))` + * 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 ### Sounds * `minetest.sound_play(spec, parameters)`: returns a handle * `spec` is a `SimpleSoundSpec` @@ -754,7 +757,15 @@ Call these functions only at load time! * Encodes a string in base64. * `minetest.decode_base64(string)`: returns string * Decodes a string encoded in base64. - +* `core.gettext(string) : returns string + * look up the translation of a string in the gettext message catalog +* `fgettext_ne(string, ...)` + * call core.gettext(string), replace "$1"..."$9" with the given + 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 Class reference --------------- diff --git a/src/client.h b/src/client.h index ff8aea591..d170f9a07 100644 --- a/src/client.h +++ b/src/client.h @@ -142,6 +142,7 @@ enum ClientEventType CE_PLAYER_FORCE_MOVE, CE_DEATHSCREEN, CE_SHOW_FORMSPEC, + CE_SHOW_LOCAL_FORMSPEC, CE_SPAWN_PARTICLE, CE_ADD_PARTICLESPAWNER, CE_DELETE_PARTICLESPAWNER, @@ -570,6 +571,11 @@ public: ClientScripting *getScript() { return m_script; } + inline void pushToEventQueue(const ClientEvent &event) + { + m_client_event_queue.push(event); + } + private: // Virtual methods from con::PeerHandler diff --git a/src/game.cpp b/src/game.cpp index 2e2a8e0c1..c84e08b01 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -125,6 +125,7 @@ struct TextDestPlayerInventory : public TextDest { struct LocalFormspecHandler : public TextDest { LocalFormspecHandler(); + LocalFormspecHandler(std::string formname) : m_client(0) { @@ -178,39 +179,7 @@ struct LocalFormspecHandler : public TextDest { return; } } - - if (m_formname == "MT_DEATH_SCREEN") { - assert(m_client != 0); - - if ((fields.find("btn_respawn") != fields.end())) { - m_client->sendRespawn(); - return; - } - - if (fields.find("quit") != fields.end()) { - m_client->sendRespawn(); - return; - } - } - - // don't show error message for unhandled cursor keys - if ((fields.find("key_up") != fields.end()) || - (fields.find("key_down") != fields.end()) || - (fields.find("key_left") != fields.end()) || - (fields.find("key_right") != fields.end())) { - return; - } - - errorstream << "LocalFormspecHandler::gotText unhandled >" - << m_formname << "< event" << std::endl; - - int i = 0; - StringMap::const_iterator it; - for (it = fields.begin(); it != fields.end(); ++it) { - errorstream << "\t" << i << ": " << it->first - << "=" << it->second << std::endl; - i++; - } + m_client->getScript()->on_formspec_input(m_formname, fields); } Client *m_client; @@ -956,28 +925,6 @@ static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec, #define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop #endif -static void show_deathscreen(GUIFormSpecMenu **cur_formspec, - Client *client, - IWritableTextureSource *tsrc, IrrlichtDevice *device, - JoystickController *joystick) -{ - std::string formspec = - std::string(FORMSPEC_VERSION_STRING) + - SIZE_TAG - "bgcolor[#320000b4;true]" - "label[4.85,1.35;" + gettext("You died.") + "]" - "button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]" - ; - - /* Create menu */ - /* Note: FormspecFormSource and LocalFormspecHandler - * are deleted by guiFormSpecMenu */ - FormspecFormSource *fs_src = new FormspecFormSource(formspec); - LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client); - - create_formspec_menu(cur_formspec, client, device, joystick, fs_src, txt_dst); -} - /******************************************************************************/ static void show_pause_menu(GUIFormSpecMenu **cur_formspec, Client *client, @@ -3255,9 +3202,6 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash) cam->camera_yaw = event.player_force_move.yaw; cam->camera_pitch = event.player_force_move.pitch; } else if (event.type == CE_DEATHSCREEN) { - show_deathscreen(¤t_formspec, client, texture_src, - device, &input->joystick); - client->getScript()->on_death(); /* Handle visualization */ @@ -3283,6 +3227,13 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash) delete(event.show_formspec.formspec); delete(event.show_formspec.formname); + } else if (event.type == CE_SHOW_LOCAL_FORMSPEC) { + FormspecFormSource *fs_src = new FormspecFormSource(*event.show_formspec.formspec); + LocalFormspecHandler *txt_dst = new LocalFormspecHandler(*event.show_formspec.formname, client); + create_formspec_menu(¤t_formspec, client, device, &input->joystick, + fs_src, txt_dst); + delete event.show_formspec.formspec; + delete event.show_formspec.formname; } else if ((event.type == CE_SPAWN_PARTICLE) || (event.type == CE_ADD_PARTICLESPAWNER) || (event.type == CE_DELETE_PARTICLESPAWNER)) { diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index bbab9c164..35365a94b 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -548,7 +548,7 @@ private: class FormspecFormSource: public IFormSource { public: - FormspecFormSource(std::string formspec) + FormspecFormSource(const std::string &formspec) { m_formspec = formspec; } @@ -556,7 +556,7 @@ public: ~FormspecFormSource() {} - void setForm(std::string formspec) { + void setForm(const std::string &formspec) { m_formspec = FORMSPEC_VERSION_STRING + formspec; } diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index ce88d67e3..1827d483b 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -112,3 +112,27 @@ void ScriptApiClient::environment_step(float dtime) + script_get_backtrace(L)); } } + +void ScriptApiClient::on_formspec_input(const std::string &formname, + const StringMap &fields) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_chat_messages + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_formspec_input"); + // Call callbacks + // param 1 + lua_pushstring(L, formname.c_str()); + // param 2 + lua_newtable(L); + StringMap::const_iterator it; + for (it = fields.begin(); it != fields.end(); ++it) { + const std::string &name = it->first; + const std::string &value = it->second; + lua_pushstring(L, name.c_str()); + lua_pushlstring(L, value.c_str(), value.size()); + lua_settable(L, -3); + } + runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC); +} diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 3d373f97c..42c41f8a4 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -22,6 +22,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define S_CLIENT_H_ #include "cpp_api/s_base.h" +#include "util/string.h" + +#ifdef _CRT_MSVCP_CURRENT +#include +#endif class ScriptApiClient: virtual public ScriptApiBase { @@ -36,7 +41,7 @@ public: void on_damage_taken(int32_t damage_amount); void on_hp_modification(int32_t newhp); void on_death(); - void environment_step(float dtime); + void on_formspec_input(const std::string &formname, const StringMap &fields); }; #endif diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 7eb340d78..9a04bd02f 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "l_internal.h" #include "util/string.h" #include "cpp_api/s_base.h" +#include "gettext.h" int ModApiClient::l_get_current_modname(lua_State *L) { @@ -44,18 +45,55 @@ int ModApiClient::l_get_last_run_mod(lua_State *L) // set_last_run_mod(modname) int ModApiClient::l_set_last_run_mod(lua_State *L) { + if (!lua_isstring(L, 1)) + return 0; + const char *mod = lua_tostring(L, 1); getScriptApiBase(L)->setOriginDirect(mod); - return 0; + lua_pushboolean(L, true); + return 1; } // display_chat_message(message) int ModApiClient::l_display_chat_message(lua_State *L) { - NO_MAP_LOCK_REQUIRED; + if (!lua_isstring(L, 1)) + return 0; std::string message = luaL_checkstring(L, 1); getClient(L)->pushToChatQueue(utf8_to_wide(message)); + lua_pushboolean(L, true); + return 1; +} + +// show_formspec(formspec) +int ModApiClient::l_show_formspec(lua_State *L) +{ + if ( !lua_isstring(L, 1) || !lua_isstring(L, 2) ) + return 0; + + ClientEvent event; + event.type = CE_SHOW_LOCAL_FORMSPEC; + event.show_formspec.formname = new std::string(luaL_checkstring(L, 1)); + event.show_formspec.formspec = new std::string(luaL_checkstring(L, 2)); + getClient(L)->pushToEventQueue(event); + lua_pushboolean(L, true); + return 1; +} + +// send_respawn() +int ModApiClient::l_send_respawn(lua_State *L) +{ + getClient(L)->sendRespawn(); + return 0; +} + +// gettext(text) +int ModApiClient::l_gettext(lua_State *L) +{ + std::string text = strgettext(std::string(luaL_checkstring(L, 1))); + lua_pushstring(L, text.c_str()); + return 1; } @@ -65,4 +103,7 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(display_chat_message); API_FCT(set_last_run_mod); API_FCT(get_last_run_mod); + API_FCT(show_formspec); + API_FCT(send_respawn); + API_FCT(gettext); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 150880e3c..14ef5aecc 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -33,6 +33,15 @@ private: // display_chat_message(message) static int l_display_chat_message(lua_State *L); + // show_formspec(name, fornspec) + static int l_show_formspec(lua_State *L); + + // send_respawn() + static int l_send_respawn(lua_State *L); + + // gettext(text) + static int l_gettext(lua_State *L); + // get_last_run_mod(n) static int l_get_last_run_mod(lua_State *L); -- 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 'src/script/lua_api/l_client.cpp') 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 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 'src/script/lua_api/l_client.cpp') 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 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 'src/script/lua_api/l_client.cpp') 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 a4874270f791fae8745cac23e153c59bef81bd1e Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Fri, 31 Mar 2017 22:29:34 +0200 Subject: Fix clang-format Columns Width Also fix l_client.cpp/h and remove them from whitelist --- .clang-format | 1 + src/script/lua_api/l_client.cpp | 13 ++++++------- src/script/lua_api/l_client.h | 4 ++-- util/travis/clang-format-whitelist.txt | 2 -- 4 files changed, 9 insertions(+), 11 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/.clang-format b/.clang-format index 82e2abf15..547df6a95 100644 --- a/.clang-format +++ b/.clang-format @@ -5,6 +5,7 @@ BreakBeforeBraces: Linux AllowShortIfStatementsOnASingleLine: false IndentCaseLabels: false AccessModifierOffset: -8 +ColumnLimit: 90 IncludeCategories: - Regex: '^".*' Priority: 2 diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 52c7f6f30..7cb89188d 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -19,13 +19,13 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "l_client.h" -#include "l_internal.h" -#include "util/string.h" +#include "common/c_content.h" +#include "common/c_converter.h" #include "cpp_api/s_base.h" #include "gettext.h" -#include "common/c_converter.h" -#include "common/c_content.h" +#include "l_internal.h" #include "lua_api/l_item.h" +#include "util/string.h" int ModApiClient::l_get_current_modname(lua_State *L) { @@ -88,7 +88,7 @@ int ModApiClient::l_get_player_names(lua_State *L) // show_formspec(formspec) int ModApiClient::l_show_formspec(lua_State *L) { - if ( !lua_isstring(L, 1) || !lua_isstring(L, 2) ) + if (!lua_isstring(L, 1) || !lua_isstring(L, 2)) return 0; ClientEvent event; @@ -142,8 +142,7 @@ int ModApiClient::l_get_node_or_nil(lua_State *L) if (pos_ok) { // Return node pushnode(L, n, getClient(L)->ndef()); - } - else { + } else { lua_pushnil(L); } return 1; diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index fcf8c39ea..b79cc670d 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -23,7 +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() @@ -31,7 +31,7 @@ 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); diff --git a/util/travis/clang-format-whitelist.txt b/util/travis/clang-format-whitelist.txt index 519e594f9..0d99793b4 100644 --- a/util/travis/clang-format-whitelist.txt +++ b/util/travis/clang-format-whitelist.txt @@ -287,8 +287,6 @@ src/script/lua_api/l_areastore.cpp src/script/lua_api/l_areastore.h src/script/lua_api/l_base.cpp src/script/lua_api/l_base.h -src/script/lua_api/l_client.cpp -src/script/lua_api/l_client.h src/script/lua_api/l_craft.cpp src/script/lua_api/l_craft.h src/script/lua_api/l_env.cpp -- 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 'src/script/lua_api/l_client.cpp') 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 000ec260017256016b62bb9936bbda1ff969e252 Mon Sep 17 00:00:00 2001 From: red-001 Date: Tue, 4 Apr 2017 06:41:37 +0100 Subject: [CSM] Add local node meta reference. (#5508) --- doc/client_lua_api.md | 15 ++++++++++- src/script/clientscripting.cpp | 2 ++ src/script/lua_api/l_client.cpp | 13 ++++++++++ src/script/lua_api/l_client.h | 3 +++ src/script/lua_api/l_nodemeta.cpp | 54 +++++++++++++++++++++++++++++++++------ src/script/lua_api/l_nodemeta.h | 12 ++++++++- 6 files changed, 89 insertions(+), 10 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index c9ccbeefa..68156efd3 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -690,6 +690,8 @@ 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. +* `minetest.get_meta(pos)` + * Get a `NodeMetaRef` at that position ### Player * `minetest.get_wielded_item()` @@ -794,7 +796,18 @@ It can be created via `Settings(filename)`. * write changes to file * `to_table()`: returns `{[key1]=value1,...}` -Definition tables +### NodeMetaRef +Node metadata: reference extra data and functionality stored in a node. +Can be obtained via `minetest.get_meta(pos)`. + +#### Methods +* `get_string(name)` +* `get_int(name)` +* `get_float(name)` +* `to_table()`: returns `nil` or a table with keys: + * `fields`: key-value storage + * `inventory`: `{list1 = {}, ...}}` + ----------------- ### Chat command definition (`register_chatcommand`) diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index df30a7253..17c53985d 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_sound.h" #include "lua_api/l_util.h" #include "lua_api/l_item.h" +#include "lua_api/l_nodemeta.h" ClientScripting::ClientScripting(Client *client): ScriptApiBase() @@ -68,4 +69,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) LuaItemStack::Register(L); StorageRef::Register(L); LuaMinimap::Register(L); + NodeMetaRef::RegisterClient(L); } diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 5f9474702..5a0cd5cc3 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 "lua_api/l_nodemeta.h" #include "mainmenumanager.h" #include "util/string.h" +#include "clientenvironment.h" +#include "map.h" extern MainGameCallback *g_gamecallback; @@ -182,6 +185,15 @@ int ModApiClient::l_get_wielded_item(lua_State *L) return 1; } +// get_meta(pos) +int ModApiClient::l_get_meta(lua_State *L) +{ + v3s16 p = read_v3s16(L, 1); + NodeMetadata *meta = getClient(L)->getEnv().getMap().getNodeMetadata(p); + NodeMetaRef::createClient(L, meta); + return 1; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -196,4 +208,5 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_node_or_nil); API_FCT(get_wielded_item); API_FCT(disconnect); + API_FCT(get_meta); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index d7f92ac1c..94b154bb4 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -62,6 +62,9 @@ private: // get_wielded_item() static int l_get_wielded_item(lua_State *L); + // get_meta(pos) + static int l_get_meta(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index 4b2b392da..4368a8c50 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -38,6 +38,9 @@ NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg) Metadata* NodeMetaRef::getmeta(bool auto_create) { + if (m_is_local) + return m_meta; + NodeMetadata *meta = m_env->getMap().getNodeMetadata(m_p); if (meta == NULL && auto_create) { meta = new NodeMetadata(m_env->getGameDef()->idef()); @@ -142,7 +145,14 @@ bool NodeMetaRef::handleFromTable(lua_State *L, int table, Metadata *_meta) NodeMetaRef::NodeMetaRef(v3s16 p, ServerEnvironment *env): m_p(p), - m_env(env) + m_env(env), + m_is_local(false) +{ +} + +NodeMetaRef::NodeMetaRef(Metadata *meta): + m_meta(meta), + m_is_local(true) { } @@ -161,7 +171,17 @@ void NodeMetaRef::create(lua_State *L, v3s16 p, ServerEnvironment *env) lua_setmetatable(L, -2); } -void NodeMetaRef::Register(lua_State *L) +// Client-sided version of the above +void NodeMetaRef::createClient(lua_State *L, Metadata *meta) +{ + NodeMetaRef *o = new NodeMetaRef(meta); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); +} + +const char NodeMetaRef::className[] = "NodeMetaRef"; +void NodeMetaRef::RegisterCommon(lua_State *L) { lua_newtable(L); int methodtable = lua_gettop(L); @@ -185,16 +205,17 @@ void NodeMetaRef::Register(lua_State *L) lua_settable(L, metatable); lua_pop(L, 1); // drop metatable +} - luaL_openlib(L, 0, methods, 0); // fill methodtable +void NodeMetaRef::Register(lua_State *L) +{ + RegisterCommon(L); + luaL_openlib(L, 0, methodsServer, 0); // fill methodtable lua_pop(L, 1); // drop methodtable - - // Cannot be created from Lua - //lua_register(L, className, create_object); } -const char NodeMetaRef::className[] = "NodeMetaRef"; -const luaL_reg NodeMetaRef::methods[] = { + +const luaL_reg NodeMetaRef::methodsServer[] = { luamethod(MetaDataRef, get_string), luamethod(MetaDataRef, set_string), luamethod(MetaDataRef, get_int), @@ -206,3 +227,20 @@ const luaL_reg NodeMetaRef::methods[] = { luamethod(NodeMetaRef, get_inventory), {0,0} }; + + +void NodeMetaRef::RegisterClient(lua_State *L) +{ + RegisterCommon(L); + luaL_openlib(L, 0, methodsClient, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable +} + + +const luaL_reg NodeMetaRef::methodsClient[] = { + luamethod(MetaDataRef, get_string), + luamethod(MetaDataRef, get_int), + luamethod(MetaDataRef, get_float), + luamethod(MetaDataRef, to_table), + {0,0} +}; diff --git a/src/script/lua_api/l_nodemeta.h b/src/script/lua_api/l_nodemeta.h index d03f086c9..6d146416b 100644 --- a/src/script/lua_api/l_nodemeta.h +++ b/src/script/lua_api/l_nodemeta.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_base.h" #include "lua_api/l_metadata.h" #include "irrlichttypes_bloated.h" +#include "nodemetadata.h" class ServerEnvironment; class NodeMetadata; @@ -34,9 +35,12 @@ class NodeMetaRef : public MetaDataRef { private: v3s16 m_p; ServerEnvironment *m_env; + Metadata *m_meta; + bool m_is_local; static const char className[]; - static const luaL_reg methods[]; + static const luaL_reg methodsServer[]; + static const luaL_reg methodsClient[]; static NodeMetaRef *checkobject(lua_State *L, int narg); @@ -71,6 +75,7 @@ private: public: NodeMetaRef(v3s16 p, ServerEnvironment *env); + NodeMetaRef(Metadata *meta); ~NodeMetaRef(); @@ -78,7 +83,12 @@ public: // Not callable from Lua; all references are created on the C side. static void create(lua_State *L, v3s16 p, ServerEnvironment *env); + // Client-sided version of the above + static void createClient(lua_State *L, Metadata *meta); + + static void RegisterCommon(lua_State *L); static void Register(lua_State *L); + static void RegisterClient(lua_State *L); }; #endif /* L_NODEMETA_H_ */ -- cgit v1.2.3 From 4ee6be856d435dff010244c910d5dafe2bfbeb1e Mon Sep 17 00:00:00 2001 From: red-001 Date: Thu, 6 Apr 2017 07:14:31 +0100 Subject: [CSM] Add support for positional audio. (#5516) Fixes parts of #5389. --- doc/client_lua_api.md | 15 ++++----------- src/script/clientscripting.cpp | 1 - src/script/lua_api/l_client.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/script/lua_api/l_client.h | 4 ++++ src/script/lua_api/l_sound.cpp | 13 ++----------- 5 files changed, 51 insertions(+), 23 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 68156efd3..25055c98a 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -131,7 +131,7 @@ The `:` prefix can also be used for maintaining backwards compatibility. Sounds ------ -**NOTE: Not fully implemented yet.** +**NOTE: max_hear_distance and connecting to objects is not implemented.** Only Ogg Vorbis files are supported. @@ -158,18 +158,12 @@ from the available ones of the following files: Examples of sound parameter tables: - -- Play locationless on all clients + -- Play locationless { gain = 1.0, -- default } - -- Play locationless to one player + -- Play locationless, looped { - to_player = name, - gain = 1.0, -- default - } - -- Play locationless to one player, looped - { - to_player = name, gain = 1.0, -- default loop = true, } @@ -187,8 +181,7 @@ Examples of sound parameter tables: loop = true, } -Looped sounds must either be connected to an object or played locationless to -one player using `to_player = name,` +Looped sounds must either be connected to an object or played locationless. ### SimpleSoundSpec * e.g. `""` diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp index 17c53985d..6f91b82ec 100644 --- a/src/script/clientscripting.cpp +++ b/src/script/clientscripting.cpp @@ -62,7 +62,6 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) { ModApiUtil::InitializeClient(L, top); ModApiClient::Initialize(L, top); - ModApiSound::Initialize(L, top); ModApiStorage::Initialize(L, top); ModApiEnvMod::InitializeClient(L, top); diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 5a0cd5cc3..2d906985f 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -194,6 +194,45 @@ int ModApiClient::l_get_meta(lua_State *L) return 1; } +int ModApiClient::l_sound_play(lua_State *L) +{ + ISoundManager *sound = getClient(L)->getSoundManager(); + + SimpleSoundSpec spec; + read_soundspec(L, 1, spec); + float gain = 1.0 ; + bool looped = false; + s32 handle; + + if (lua_istable(L, 2)) { + getfloatfield(L, 2, "gain", gain); + getboolfield(L, 2, "loop", looped); + + lua_getfield(L, 2, "pos"); + if (!lua_isnil(L, -1)) { + v3f pos = read_v3f(L, -1) * BS; + lua_pop(L, 1); + handle = sound->playSoundAt(spec.name, looped, gain * spec.gain, pos); + lua_pushinteger(L, handle); + return 1; + } + } + + handle = sound->playSound(spec.name, looped, gain * spec.gain); + lua_pushinteger(L, handle); + + return 1; +} + +int ModApiClient::l_sound_stop(lua_State *L) +{ + u32 handle = luaL_checkinteger(L, 1); + + getClient(L)->getSoundManager()->stopSound(handle); + + return 0; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -209,4 +248,6 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_wielded_item); API_FCT(disconnect); API_FCT(get_meta); + API_FCT(sound_play); + API_FCT(sound_stop); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 94b154bb4..4e7f63d6a 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -65,6 +65,10 @@ private: // get_meta(pos) static int l_get_meta(lua_State *L); + static int l_sound_play(lua_State *L); + + static int l_sound_stop(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_sound.cpp b/src/script/lua_api/l_sound.cpp index 774b5be0c..07ce36daa 100644 --- a/src/script/lua_api/l_sound.cpp +++ b/src/script/lua_api/l_sound.cpp @@ -30,12 +30,7 @@ int ModApiSound::l_sound_play(lua_State *L) read_soundspec(L, 1, spec); bool looped = lua_toboolean(L, 2); - s32 handle; - if (Client *client = getClient(L)) - handle = client->getSoundManager()->playSound(spec, looped); - // Main menu doesn't have access to client, use guiEngine - else - handle = getGuiEngine(L)->playSound(spec, looped); + s32 handle = getGuiEngine(L)->playSound(spec, looped); lua_pushinteger(L, handle); @@ -46,11 +41,7 @@ int ModApiSound::l_sound_stop(lua_State *L) { u32 handle = luaL_checkinteger(L, 1); - if (Client *client = getClient(L)) - client->getSoundManager()->stopSound(handle); - // Main menu doesn't have access to client, use guiEngine - else - getGuiEngine(L)->stopSound(handle); + getGuiEngine(L)->stopSound(handle); return 1; } -- cgit v1.2.3 From 4b15f76ed163b1e0b95b50017bd39e73400601b4 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 6 Apr 2017 09:10:59 +0200 Subject: Move LINT process in dedicated shell & fix Move lint to dedicated shell permit to use it from your shell easily to check what is wrong Also fix recent regressions in code style --- src/script/lua_api/l_client.cpp | 9 ++++---- util/travis/lint.sh | 46 +++++++++++++++++++++++++++++++++++++++++ util/travis/script.sh | 46 +---------------------------------------- 3 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 util/travis/lint.sh (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 2d906985f..458c1d1f4 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "l_client.h" +#include "clientenvironment.h" #include "common/c_content.h" #include "common/c_converter.h" #include "cpp_api/s_base.h" @@ -27,9 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_item.h" #include "lua_api/l_nodemeta.h" #include "mainmenumanager.h" -#include "util/string.h" -#include "clientenvironment.h" #include "map.h" +#include "util/string.h" extern MainGameCallback *g_gamecallback; @@ -200,7 +200,7 @@ int ModApiClient::l_sound_play(lua_State *L) SimpleSoundSpec spec; read_soundspec(L, 1, spec); - float gain = 1.0 ; + float gain = 1.0; bool looped = false; s32 handle; @@ -212,7 +212,8 @@ int ModApiClient::l_sound_play(lua_State *L) if (!lua_isnil(L, -1)) { v3f pos = read_v3f(L, -1) * BS; lua_pop(L, 1); - handle = sound->playSoundAt(spec.name, looped, gain * spec.gain, pos); + handle = + sound->playSoundAt(spec.name, looped, gain * spec.gain, pos); lua_pushinteger(L, handle); return 1; } diff --git a/util/travis/lint.sh b/util/travis/lint.sh new file mode 100644 index 000000000..96026b247 --- /dev/null +++ b/util/travis/lint.sh @@ -0,0 +1,46 @@ +#! /bin/bash +function perform_lint() { + echo "Performing LINT..." + CLANG_FORMAT=clang-format + CLANG_FORMAT_WHITELIST="util/travis/clang-format-whitelist.txt" + + if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then + # Get list of every file modified in this pull request + files_to_lint="$(git diff --name-only --diff-filter=ACMRTUXB $TRAVIS_COMMIT_RANGE | grep '^src/[^.]*[.]\(cpp\|h\)$' | true)" + else + # Check everything for branch pushes + files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')" + fi + + local errorcount=0 + local fail=0 + for f in ${files_to_lint}; do + d=$(diff -u "$f" <(${CLANG_FORMAT} "$f") || true) + + if ! [ -z "$d" ]; then + whitelisted=$(egrep -c "^${f}" "${CLANG_FORMAT_WHITELIST}") + + # If file is not whitelisted, mark a failure + if [ ${whitelisted} -eq 0 ]; then + errorcount=$((errorcount+1)) + + printf "The file %s is not compliant with the coding style" "$f" + if [ ${errorcount} -gt 50 ]; then + printf "\nToo many errors encountered previously, this diff is hidden.\n" + else + printf ":\n%s\n" "$d" + fi + + fail=1 + fi + fi + done + + if [ "$fail" = 1 ]; then + echo "LINT reports failure." + exit 1 + fi + + echo "LINT OK" +} + diff --git a/util/travis/script.sh b/util/travis/script.sh index 44057352d..14b8dfb73 100755 --- a/util/travis/script.sh +++ b/util/travis/script.sh @@ -1,53 +1,9 @@ #!/bin/bash -e . util/travis/common.sh +. util/travis/lint.sh needs_compile || exit 0 -function perform_lint() { - echo "Performing LINT..." - CLANG_FORMAT=clang-format-3.9 - CLANG_FORMAT_WHITELIST="util/travis/clang-format-whitelist.txt" - - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then - # Get list of every file modified in this pull request - files_to_lint="$(git diff --name-only --diff-filter=ACMRTUXB $TRAVIS_COMMIT_RANGE | grep '^src/[^.]*[.]\(cpp\|h\)$' | true)" - else - # Check everything for branch pushes - files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')" - fi - - local errorcount=0 - local fail=0 - for f in ${files_to_lint}; do - d=$(diff -u "$f" <(${CLANG_FORMAT} "$f") || true) - - if ! [ -z "$d" ]; then - whitelisted=$(egrep -c "^${f}" "${CLANG_FORMAT_WHITELIST}") - - # If file is not whitelisted, mark a failure - if [ ${whitelisted} -eq 0 ]; then - errorcount=$((errorcount+1)) - - printf "The file %s is not compliant with the coding style" "$f" - if [ ${errorcount} -gt 50 ]; then - printf "\nToo many errors encountered previously, this diff is hidden.\n" - else - printf ":\n%s\n" "$d" - fi - - fail=1 - fi - fi - done - - if [ "$fail" = 1 ]; then - echo "LINT reports failure." - exit 1 - fi - - echo "LINT OK" -} - if [[ "$LINT" == "1" ]]; then # Lint with exit CI perform_lint -- 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 'src/script/lua_api/l_client.cpp') 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 3a90b78a037df3eb9098d4fddb1289ed8ee21329 Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Thu, 6 Apr 2017 16:03:29 +0200 Subject: LINT: Switch whitelist check from egrep to awk Bonus: make CI happy with the last rules fix --- src/client/keys.h | 3 ++- src/environment.cpp | 1 + src/gameparams.h | 3 ++- src/gettime.h | 3 ++- src/script/lua_api/l_client.cpp | 4 ++-- util/travis/lint.sh | 5 +++-- 6 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/client/keys.h b/src/client/keys.h index b446d3a1e..76ae38ff0 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -25,7 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., class KeyType { public: - enum T { + enum T + { // Player movement FORWARD, BACKWARD, diff --git a/src/environment.cpp b/src/environment.cpp index d1ea5f8bb..9c2ea8896 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "daynightratio.h" #include "emerge.h" + Environment::Environment(IGameDef *gamedef): m_time_of_day_speed(0), m_time_of_day(9000), diff --git a/src/gameparams.h b/src/gameparams.h index bf9953c39..4afc0fdce 100644 --- a/src/gameparams.h +++ b/src/gameparams.h @@ -24,7 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., struct SubgameSpec; -struct GameParams { +struct GameParams +{ u16 socket_port; std::string world_path; SubgameSpec game_spec; diff --git a/src/gettime.h b/src/gettime.h index 6e70b8533..b2f09a7bb 100644 --- a/src/gettime.h +++ b/src/gettime.h @@ -31,7 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc., Normal build: main.cpp Server build: servermain.cpp */ -enum TimePrecision { +enum TimePrecision +{ PRECISION_SECONDS = 0, PRECISION_MILLI, PRECISION_MICRO, diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 0f4d7eaae..be3a749de 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -212,8 +212,8 @@ int ModApiClient::l_sound_play(lua_State *L) if (!lua_isnil(L, -1)) { v3f pos = read_v3f(L, -1) * BS; lua_pop(L, 1); - handle = - sound->playSoundAt(spec.name, looped, gain * spec.gain, pos); + handle = sound->playSoundAt( + spec.name, looped, gain * spec.gain, pos); lua_pushinteger(L, handle); return 1; } diff --git a/util/travis/lint.sh b/util/travis/lint.sh index c1df2d5fa..4e816bd94 100644 --- a/util/travis/lint.sh +++ b/util/travis/lint.sh @@ -6,6 +6,7 @@ function perform_lint() { else CLANG_FORMAT=clang-format fi + echo "LINT: Using binary $CLANG_FORMAT" CLANG_FORMAT_WHITELIST="util/travis/clang-format-whitelist.txt" if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then @@ -22,10 +23,10 @@ function perform_lint() { d=$(diff -u "$f" <(${CLANG_FORMAT} "$f") || true) if ! [ -z "$d" ]; then - whitelisted=$(egrep -c "^${f}" "${CLANG_FORMAT_WHITELIST}") + whitelisted=$(awk '$1 == "'$f'" { print 1 }' "$CLANG_FORMAT_WHITELIST") # If file is not whitelisted, mark a failure - if [ ${whitelisted} -eq 0 ]; then + if [ -z ${whitelisted} ]; then errorcount=$((errorcount+1)) printf "The file %s is not compliant with the coding style" "$f" -- cgit v1.2.3 From a7e131f53e211ffbe38d34d23b33e13cc401f013 Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Tue, 25 Apr 2017 10:17:53 +0200 Subject: Fix various points reported by cppcheck (#5656) * Fix various performance issues reported by cppcheck + code style (CI) * Make CI happy with code style on master * guiFileSelectMenu: remove useless includes * some performance fixes pointed by cppcheck * remove some useless casts * TextDest: remove unused setFormSpec function * Fix various iterator post-increment reported by cppcheck --- src/game.cpp | 3 ++- src/guiFormSpecMenu.h | 2 +- src/map_settings_manager.cpp | 13 ++++++------- src/nodedef.cpp | 7 +++---- src/script/cpp_api/s_async.cpp | 10 +++++----- src/script/cpp_api/s_node.cpp | 2 +- src/script/lua_api/l_client.cpp | 2 +- src/script/lua_api/l_craft.cpp | 2 +- src/script/lua_api/l_env.cpp | 5 ++--- src/script/lua_api/l_mainmenu.cpp | 2 +- src/script/lua_api/l_nodemeta.cpp | 2 +- src/script/lua_api/l_server.cpp | 4 ++-- src/util/thread.h | 6 +++--- 13 files changed, 29 insertions(+), 31 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/game.cpp b/src/game.cpp index fbc0cf35f..31a48531c 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -202,7 +202,8 @@ public: return meta->getString("formspec"); } - std::string resolveText(std::string str) + + virtual std::string resolveText(const std::string &str) { NodeMetadata *meta = m_map->getNodeMetadata(m_p); diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index e30565be8..af2d3f45e 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -69,7 +69,7 @@ public: virtual ~IFormSource(){} virtual std::string getForm() = 0; // Fill in variables in field text - virtual std::string resolveText(std::string str){ return str; } + virtual std::string resolveText(const std::string &str) { return str; } }; class GUIFormSpecMenu : public GUIModalMenu diff --git a/src/map_settings_manager.cpp b/src/map_settings_manager.cpp index 53d17125c..52f88778c 100644 --- a/src/map_settings_manager.cpp +++ b/src/map_settings_manager.cpp @@ -25,14 +25,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map_settings_manager.h" -MapSettingsManager::MapSettingsManager( - Settings *user_settings, const std::string &map_meta_path) +MapSettingsManager::MapSettingsManager(Settings *user_settings, + const std::string &map_meta_path): + mapgen_params(NULL), + m_map_meta_path(map_meta_path), + m_map_settings(new Settings()), + m_user_settings(user_settings) { - m_map_meta_path = map_meta_path; - m_user_settings = user_settings; - m_map_settings = new Settings; - mapgen_params = NULL; - assert(m_user_settings != NULL); } diff --git a/src/nodedef.cpp b/src/nodedef.cpp index db28325aa..ce2834c91 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -1318,22 +1318,21 @@ void CNodeDefManager::removeNode(const std::string &name) // Erase node content from all groups it belongs to for (UNORDERED_MAP::iterator iter_groups = - m_group_to_items.begin(); - iter_groups != m_group_to_items.end();) { + m_group_to_items.begin(); iter_groups != m_group_to_items.end();) { GroupItems &items = iter_groups->second; for (GroupItems::iterator iter_groupitems = items.begin(); iter_groupitems != items.end();) { if (iter_groupitems->first == id) items.erase(iter_groupitems++); else - iter_groupitems++; + ++iter_groupitems; } // Check if group is empty if (items.size() == 0) m_group_to_items.erase(iter_groups++); else - iter_groups++; + ++iter_groups; } } diff --git a/src/script/cpp_api/s_async.cpp b/src/script/cpp_api/s_async.cpp index a1bec83bf..080ae887c 100644 --- a/src/script/cpp_api/s_async.cpp +++ b/src/script/cpp_api/s_async.cpp @@ -46,26 +46,26 @@ AsyncEngine::~AsyncEngine() // Request all threads to stop for (std::vector::iterator it = workerThreads.begin(); - it != workerThreads.end(); it++) { + it != workerThreads.end(); ++it) { (*it)->stop(); } // Wake up all threads for (std::vector::iterator it = workerThreads.begin(); - it != workerThreads.end(); it++) { + it != workerThreads.end(); ++it) { jobQueueCounter.post(); } // Wait for threads to finish for (std::vector::iterator it = workerThreads.begin(); - it != workerThreads.end(); it++) { + it != workerThreads.end(); ++it) { (*it)->wait(); } // Force kill all threads for (std::vector::iterator it = workerThreads.begin(); - it != workerThreads.end(); it++) { + it != workerThreads.end(); ++it) { delete *it; } @@ -205,7 +205,7 @@ void AsyncEngine::pushFinishedJobs(lua_State* L) { void AsyncEngine::prepareEnvironment(lua_State* L, int top) { for (UNORDERED_MAP::iterator it = functionList.begin(); - it != functionList.end(); it++) { + it != functionList.end(); ++it) { lua_pushstring(L, it->first.c_str()); lua_pushcfunction(L, it->second); lua_settable(L, top); diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index 2723f84e1..1ae8f58a5 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -263,7 +263,7 @@ void ScriptApiNode::node_on_receive_fields(v3s16 p, lua_pushstring(L, formname.c_str()); // formname lua_newtable(L); // fields StringMap::const_iterator it; - for (it = fields.begin(); it != fields.end(); it++) { + for (it = fields.begin(); it != fields.end(); ++it) { const std::string &name = it->first; const std::string &value = it->second; lua_pushstring(L, name.c_str()); diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index be3a749de..09ea5506b 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -83,7 +83,7 @@ int ModApiClient::l_get_player_names(lua_State *L) int newTable = lua_gettop(L); int index = 1; std::list::const_iterator iter; - for (iter = plist.begin(); iter != plist.end(); iter++) { + for (iter = plist.begin(); iter != plist.end(); ++iter) { lua_pushstring(L, (*iter).c_str()); lua_rawseti(L, newTable, index); index++; diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp index 2236566de..315391856 100644 --- a/src/script/lua_api/l_craft.cpp +++ b/src/script/lua_api/l_craft.cpp @@ -414,7 +414,7 @@ static void push_craft_recipe(lua_State *L, IGameDef *gdef, lua_newtable(L); // items std::vector::const_iterator iter = input.items.begin(); - for (u16 j = 1; iter != input.items.end(); iter++, j++) { + for (u16 j = 1; iter != input.items.end(); ++iter, j++) { if (iter->empty()) continue; lua_pushstring(L, iter->name.c_str()); diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 1fa7845b5..75b07fa37 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -534,7 +534,7 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L) ScriptApiBase *script = getScriptApiBase(L); lua_createtable(L, ids.size(), 0); std::vector::const_iterator iter = ids.begin(); - for(u32 i = 0; iter != ids.end(); iter++) { + for(u32 i = 0; iter != ids.end(); ++iter) { ServerActiveObject *obj = env->getActiveObject(*iter); // Insert object reference into table script->objectrefGetOrCreate(L, obj); @@ -985,8 +985,7 @@ int ModApiEnvMod::l_find_path(lua_State *L) lua_newtable(L); int top = lua_gettop(L); unsigned int index = 1; - for (std::vector::iterator i = path.begin(); i != path.end();i++) - { + for (std::vector::iterator i = path.begin(); i != path.end(); ++i) { lua_pushnumber(L,index); push_v3s16(L, *i); lua_settable(L, top); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 3d204db98..4d0be257c 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -297,7 +297,7 @@ int ModApiMainMenu::l_get_games(lua_State *L) int table2 = lua_gettop(L); int internal_index=1; for (std::set::iterator iter = games[i].addon_mods_paths.begin(); - iter != games[i].addon_mods_paths.end(); iter++) { + iter != games[i].addon_mods_paths.end(); ++iter) { lua_pushnumber(L,internal_index); lua_pushstring(L,(*iter).c_str()); lua_settable(L, table2); diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index c65d56f14..6232112c5 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -107,7 +107,7 @@ void NodeMetaRef::handleToTable(lua_State *L, Metadata *_meta) if (inv) { std::vector lists = inv->getLists(); for(std::vector::const_iterator - i = lists.begin(); i != lists.end(); i++) { + i = lists.begin(); i != lists.end(); ++i) { push_inventory_list(L, inv, (*i)->getName().c_str()); lua_setfield(L, -2, (*i)->getName().c_str()); } diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index d94f3e31d..813d5a945 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -103,7 +103,7 @@ int ModApiServer::l_get_player_privs(lua_State *L) int table = lua_gettop(L); std::set privs_s = server->getPlayerEffectivePrivs(name); for(std::set::const_iterator - i = privs_s.begin(); i != privs_s.end(); i++){ + i = privs_s.begin(); i != privs_s.end(); ++i){ lua_pushboolean(L, true); lua_setfield(L, table, i->c_str()); } @@ -417,7 +417,7 @@ int ModApiServer::l_get_modnames(lua_State *L) // Package them up for Lua lua_createtable(L, modlist.size(), 0); std::vector::iterator iter = modlist.begin(); - for (u16 i = 0; iter != modlist.end(); iter++) { + for (u16 i = 0; iter != modlist.end(); ++iter) { lua_pushstring(L, iter->c_str()); lua_rawseti(L, -2, ++i); } diff --git a/src/util/thread.h b/src/util/thread.h index f54b8b48f..b96f302f6 100644 --- a/src/util/thread.h +++ b/src/util/thread.h @@ -83,8 +83,8 @@ public: GetRequest() {} ~GetRequest() {} - GetRequest(Key a_key) { - key = a_key; + GetRequest(const Key &a_key): key(a_key) + { } Key key; @@ -106,7 +106,7 @@ public: return m_queue.empty(); } - void add(Key key, Caller caller, CallerData callerdata, + void add(const Key &key, Caller caller, CallerData callerdata, ResultQueue *dest) { typename std::deque >::iterator i; -- cgit v1.2.3 From 19960e26c672c6337f8c6ffbe27f2c6bca49750c Mon Sep 17 00:00:00 2001 From: Vincent Glize Date: Sat, 29 Apr 2017 09:16:06 +0200 Subject: [CSM] add screenshot api lua (#5674) * [CSM] add screenshot api lua --- doc/client_lua_api.md | 2 ++ src/client.h | 2 ++ src/script/lua_api/l_client.cpp | 8 ++++++++ src/script/lua_api/l_client.h | 2 ++ 4 files changed, 14 insertions(+) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index b2aeb3f25..86fcd02a7 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -703,6 +703,8 @@ Call these functions only at load time! * `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. ### Misc. * `minetest.parse_json(string[, nullvalue])`: returns something diff --git a/src/client.h b/src/client.h index 68953d402..699550eac 100644 --- a/src/client.h +++ b/src/client.h @@ -509,6 +509,8 @@ public: void showGameFog(const bool show = true); void showGameDebug(const bool show = true); + IrrlichtDevice *getDevice() const { return m_device; } + private: // Virtual methods from con::PeerHandler diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 09ea5506b..c982a2f11 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -241,6 +241,13 @@ int ModApiClient::l_get_protocol_version(lua_State *L) return 1; } +int ModApiClient::l_take_screenshot(lua_State *L) +{ + Client *client = getClient(L); + client->makeScreenshot(client->getDevice()); + return 0; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -259,4 +266,5 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(sound_play); API_FCT(sound_stop); API_FCT(get_protocol_version); + API_FCT(take_screenshot); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 478b8ed6c..6afcd996b 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -72,6 +72,8 @@ private: // get_protocol_version() static int l_get_protocol_version(lua_State *L); + static int l_take_screenshot(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; -- 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 'src/script/lua_api/l_client.cpp') 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 af2f02552f1999b9b491fc44386be5c1ea8a8882 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 20 May 2017 16:46:12 +0200 Subject: [CSM] Correct the log destination of print() (#5784) --- src/script/lua_api/l_client.cpp | 10 ++++++++++ src/script/lua_api/l_client.h | 3 +++ 2 files changed, 13 insertions(+) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 7f89a4d5d..22045e06d 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -63,6 +63,15 @@ int ModApiClient::l_set_last_run_mod(lua_State *L) return 1; } +// print(text) +int ModApiClient::l_print(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string text = luaL_checkstring(L, 1); + rawstream << text << std::endl; + return 0; +} + // display_chat_message(message) int ModApiClient::l_display_chat_message(lua_State *L) { @@ -261,6 +270,7 @@ int ModApiClient::l_take_screenshot(lua_State *L) void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); + API_FCT(print); API_FCT(display_chat_message); API_FCT(get_player_names); API_FCT(set_last_run_mod); diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index a36d7e51c..2267a4c9d 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -29,6 +29,9 @@ private: // get_current_modname() static int l_get_current_modname(lua_State *L); + // print(text) + static int l_print(lua_State *L); + // display_chat_message(message) static int l_display_chat_message(lua_State *L); -- cgit v1.2.3 From dfa0c15ce045705f05487d623dc7beca6c945b4b Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Sun, 21 May 2017 07:40:55 -0500 Subject: [CSM] Add function to get the definition of items (#5732) Add node def and item def documentation. Please be ready for merge! --- doc/client_lua_api.md | 98 ++++++++++++++- src/script/common/c_content.cpp | 255 ++++++++++++++++++++++++++++++++++++++++ src/script/common/c_content.h | 18 +++ src/script/lua_api/l_client.cpp | 47 ++++++++ src/script/lua_api/l_client.h | 10 +- 5 files changed, 425 insertions(+), 3 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index 5b70c2a67..ce0746df4 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -989,6 +989,96 @@ Can be obtained via `minetest.get_meta(pos)`. * `inventory`: `{list1 = {}, ...}}` ----------------- +### Definitions +* `minetest.get_node_def(nodename)` + * Returns [node definition](#node-definition) table of `nodename` +* `minetest.get_item_def(itemstring)` + * Returns item definition table of `itemstring` + +#### Node Definition + +```lua + { + has_on_construct = bool, -- Whether the node has the on_construct callback defined + has_on_destruct = bool, -- Whether the node has the on_destruct callback defined + has_after_destruct = bool, -- Whether the node has the after_destruct callback defined + name = string, -- The name of the node e.g. "air", "default:dirt" + groups = table, -- The groups of the node + paramtype = string, -- Paramtype of the node + paramtype2 = string, -- ParamType2 of the node + drawtype = string, -- Drawtype of the node + mesh = , -- Mesh name if existant + minimap_color = , -- Color of node on minimap *May not exist* + visual_scale = number, -- Visual scale of node + alpha = number, -- Alpha of the node. Only used for liquids + color = , -- Color of node *May not exist* + palette_name = , -- Filename of palette *May not exist* + palette = <{ -- List of colors + Color, + Color + }>, + waving = number, -- 0 of not waving, 1 if waving + connect_sides = number, -- Used for connected nodes + connects_to = { -- List of nodes to connect to + "node1", + "node2" + }, + post_effect_color = Color, -- Color overlayed on the screen when the player is in the node + leveled = number, -- Max level for node + sunlight_propogates = bool, -- Whether light passes through the block + light_source = number, -- Light emitted by the block + is_ground_content = bool, -- Whether caves should cut through the node + walkable = bool, -- Whether the player collides with the node + pointable = bool, -- Whether the player can select the node + diggable = bool, -- Whether the player can dig the node + climbable = bool, -- Whether the player can climb up the node + buildable_to = bool, -- Whether the player can replace the node by placing a node on it + rightclickable = bool, -- Whether the player can place nodes pointing at this node + damage_per_second = number, -- HP of damage per second when the player is in the node + liquid_type = , -- A string containing "none", "flowing", or "source" *May not exist* + liquid_alternative_flowing = , -- Alternative node for liquid *May not exist* + liquid_alternative_source = , -- Alternative node for liquid *May not exist* + liquid_viscosity = , -- How fast the liquid flows *May not exist* + liquid_renewable = , -- Whether the liquid makes an infinite source *May not exist* + liquid_range = , -- How far the liquid flows *May not exist* + drowning = bool, -- Whether the player will drown in the node + floodable = bool, -- Whether nodes will be replaced by liquids (flooded) + node_box = table, -- Nodebox to draw the node with + collision_box = table, -- Nodebox to set the collision area + selection_box = table, -- Nodebox to set the area selected by the player + sounds = { -- Table of sounds that the block makes + sound_footstep = SimpleSoundSpec, + sound_dig = SimpleSoundSpec, + sound_dug = SimpleSoundSpec + }, + legacy_facedir_simple = bool, -- Whether to use old facedir + legacy_wallmounted = bool -- Whether to use old wallmounted + } +``` + +#### Item Definition + +```lua + { + name = string, -- Name of the item e.g. "default:stone" + description = string, -- Description of the item e.g. "Stone" + type = string, -- Item type: "none", "node", "craftitem", "tool" + inventory_image = string, -- Image in the inventory + wield_image = string, -- Image in wieldmesh + palette_image = string, -- Image for palette + color = Color, -- Color for item + wield_scale = Vector, -- Wieldmesh scale + stack_max = number, -- Number of items stackable together + usable = bool, -- Has on_use callback defined + liquids_pointable = bool, -- Whether you can point at liquids with the item + tool_capabilities = , -- If the item is a tool, tool capabiltites of the item + groups = table, -- Groups of the item + sound_place = SimpleSoundSpec, -- Sound played when placed + sound_place_failed = SimpleSoundSpec, -- Sound played when placement failed + node_placement_prediction = string -- Node placed in client until server catches up + } +``` +----------------- ### Chat command definition (`register_chatcommand`) @@ -1014,7 +1104,7 @@ 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: * `minetest.get_color_escape_sequence(color)`: - * `color` is a ColorString + * `color` is a [ColorString](#colorstring) * The escape sequence sets the text color to `color` * `minetest.colorize(color, message)`: * Equivalent to: @@ -1022,7 +1112,7 @@ The following functions provide escape sequences: message .. minetest.get_color_escape_sequence("#ffffff")` * `color.get_background_escape_sequence(color)` - * `color` is a ColorString + * `color` is a [ColorString](#colorstring) * The escape sequence sets the background of the whole text element to `color`. Only defined for item descriptions and tooltips. * `color.strip_foreground_colors(str)` @@ -1047,3 +1137,7 @@ Named colors are also supported and are equivalent to 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 hexadecimal digits. + +`Color` +------------- +`{a = alpha, r = red, g = green, b = blue}` defines an ARGB8 color. diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 7eb1d094b..c0e29abf0 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_schematic.h" #include "noise.h" #include "util/pointedthing.h" +#include "debug.h" // For FATAL_ERROR #include struct EnumString es_TileAnimationType[] = @@ -128,6 +129,51 @@ void push_item_definition(lua_State *L, const ItemDefinition &i) lua_setfield(L, -2, "description"); } +void push_item_definition_full(lua_State *L, const ItemDefinition &i) +{ + std::string type(es_ItemType[(int)i.type].str); + + 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"); + lua_pushstring(L, type.c_str()); + lua_setfield(L, -2, "type"); + lua_pushstring(L, i.inventory_image.c_str()); + lua_setfield(L, -2, "inventory_image"); + lua_pushstring(L, i.wield_image.c_str()); + lua_setfield(L, -2, "wield_image"); + lua_pushstring(L, i.palette_image.c_str()); + lua_setfield(L, -2, "palette_image"); + push_ARGB8(L, i.color); + lua_setfield(L, -2, "color"); + push_v3f(L, i.wield_scale); + lua_setfield(L, -2, "wield_scale"); + lua_pushinteger(L, i.stack_max); + lua_setfield(L, -2, "stack_max"); + lua_pushboolean(L, i.usable); + lua_setfield(L, -2, "usable"); + lua_pushboolean(L, i.liquids_pointable); + lua_setfield(L, -2, "liquids_pointable"); + if (i.type == ITEM_TOOL) { + push_tool_capabilities(L, ToolCapabilities( + i.tool_capabilities->full_punch_interval, + i.tool_capabilities->max_drop_level, + i.tool_capabilities->groupcaps, + i.tool_capabilities->damageGroups)); + lua_setfield(L, -2, "tool_capabilities"); + } + push_groups(L, i.groups); + lua_setfield(L, -2, "groups"); + push_soundspec(L, i.sound_place); + lua_setfield(L, -2, "sound_place"); + push_soundspec(L, i.sound_place_failed); + lua_setfield(L, -2, "sound_place_failed"); + lua_pushstring(L, i.node_placement_prediction.c_str()); + lua_setfield(L, -2, "node_placement_prediction"); +} + /******************************************************************************/ void read_object_properties(lua_State *L, int index, ObjectProperties *prop, IItemDefManager *idef) @@ -669,6 +715,204 @@ ContentFeatures read_content_features(lua_State *L, int index) return f; } +void push_content_features(lua_State *L, const ContentFeatures &c) +{ + std::string paramtype(ScriptApiNode::es_ContentParamType[(int)c.param_type].str); + std::string paramtype2(ScriptApiNode::es_ContentParamType2[(int)c.param_type_2].str); + std::string drawtype(ScriptApiNode::es_DrawType[(int)c.drawtype].str); + std::string liquid_type(ScriptApiNode::es_LiquidType[(int)c.liquid_type].str); + + /* Missing "tiles" because I don't see a usecase (at least not yet). */ + + lua_newtable(L); + lua_pushboolean(L, c.has_on_construct); + lua_setfield(L, -2, "has_on_construct"); + lua_pushboolean(L, c.has_on_destruct); + lua_setfield(L, -2, "has_on_destruct"); + lua_pushboolean(L, c.has_after_destruct); + lua_setfield(L, -2, "has_after_destruct"); + lua_pushstring(L, c.name.c_str()); + lua_setfield(L, -2, "name"); + push_groups(L, c.groups); + lua_setfield(L, -2, "groups"); + lua_pushstring(L, paramtype.c_str()); + lua_setfield(L, -2, "paramtype"); + lua_pushstring(L, paramtype2.c_str()); + lua_setfield(L, -2, "paramtype2"); + lua_pushstring(L, drawtype.c_str()); + lua_setfield(L, -2, "drawtype"); + if (!c.mesh.empty()) { + lua_pushstring(L, c.mesh.c_str()); + lua_setfield(L, -2, "mesh"); + } +#ifndef SERVER + push_ARGB8(L, c.minimap_color); // I know this is not set-able w/ register_node, + lua_setfield(L, -2, "minimap_color"); // but the people need to know! +#endif + lua_pushnumber(L, c.visual_scale); + lua_setfield(L, -2, "visual_scale"); + lua_pushnumber(L, c.alpha); + lua_setfield(L, -2, "alpha"); + if (!c.palette_name.empty()) { + push_ARGB8(L, c.color); + lua_setfield(L, -2, "color"); + + lua_pushstring(L, c.palette_name.c_str()); + lua_setfield(L, -2, "palette_name"); + + push_palette(L, c.palette); + lua_setfield(L, -2, "palette"); + } + lua_pushnumber(L, c.waving); + lua_setfield(L, -2, "waving"); + lua_pushnumber(L, c.connect_sides); + lua_setfield(L, -2, "connect_sides"); + + lua_newtable(L); + u16 i = 1; + for (std::vector::const_iterator it = c.connects_to.begin(); + it != c.connects_to.end(); ++it) { + lua_pushlstring(L, it->c_str(), it->size()); + lua_rawseti(L, -2, i); + } + lua_setfield(L, -2, "connects_to"); + + push_ARGB8(L, c.post_effect_color); + lua_setfield(L, -2, "post_effect_color"); + lua_pushnumber(L, c.leveled); + lua_setfield(L, -2, "leveled"); + lua_pushboolean(L, c.sunlight_propagates); + lua_setfield(L, -2, "sunlight_propagates"); + lua_pushnumber(L, c.light_source); + lua_setfield(L, -2, "light_source"); + lua_pushboolean(L, c.is_ground_content); + lua_setfield(L, -2, "is_ground_content"); + lua_pushboolean(L, c.walkable); + lua_setfield(L, -2, "walkable"); + lua_pushboolean(L, c.pointable); + lua_setfield(L, -2, "pointable"); + lua_pushboolean(L, c.diggable); + lua_setfield(L, -2, "diggable"); + lua_pushboolean(L, c.climbable); + lua_setfield(L, -2, "climbable"); + lua_pushboolean(L, c.buildable_to); + lua_setfield(L, -2, "buildable_to"); + lua_pushboolean(L, c.rightclickable); + lua_setfield(L, -2, "rightclickable"); + lua_pushnumber(L, c.damage_per_second); + lua_setfield(L, -2, "damage_per_second"); + if (c.isLiquid()) { + lua_pushstring(L, liquid_type.c_str()); + lua_setfield(L, -2, "liquid_type"); + lua_pushstring(L, c.liquid_alternative_flowing.c_str()); + lua_setfield(L, -2, "liquid_alternative_flowing"); + lua_pushstring(L, c.liquid_alternative_source.c_str()); + lua_setfield(L, -2, "liquid_alternative_source"); + lua_pushnumber(L, c.liquid_viscosity); + lua_setfield(L, -2, "liquid_viscosity"); + lua_pushboolean(L, c.liquid_renewable); + lua_setfield(L, -2, "liquid_renewable"); + lua_pushnumber(L, c.liquid_range); + lua_setfield(L, -2, "liquid_range"); + } + lua_pushnumber(L, c.drowning); + lua_setfield(L, -2, "drowning"); + lua_pushboolean(L, c.floodable); + lua_setfield(L, -2, "floodable"); + push_nodebox(L, c.node_box); + lua_setfield(L, -2, "node_box"); + push_nodebox(L, c.selection_box); + lua_setfield(L, -2, "selection_box"); + push_nodebox(L, c.collision_box); + lua_setfield(L, -2, "collision_box"); + lua_newtable(L); + push_soundspec(L, c.sound_footstep); + lua_setfield(L, -2, "sound_footstep"); + push_soundspec(L, c.sound_dig); + lua_setfield(L, -2, "sound_dig"); + push_soundspec(L, c.sound_dug); + lua_setfield(L, -2, "sound_dug"); + lua_setfield(L, -2, "sounds"); + lua_pushboolean(L, c.legacy_facedir_simple); + lua_setfield(L, -2, "legacy_facedir_simple"); + lua_pushboolean(L, c.legacy_wallmounted); + lua_setfield(L, -2, "legacy_wallmounted"); +} + +/******************************************************************************/ +void push_nodebox(lua_State *L, const NodeBox &box) +{ + lua_newtable(L); + switch (box.type) + { + case NODEBOX_REGULAR: + lua_pushstring(L, "regular"); + lua_setfield(L, -2, "type"); + break; + case NODEBOX_LEVELED: + case NODEBOX_FIXED: + lua_pushstring(L, "fixed"); + lua_setfield(L, -2, "type"); + push_box(L, box.fixed); + lua_setfield(L, -2, "fixed"); + break; + case NODEBOX_WALLMOUNTED: + lua_pushstring(L, "wallmounted"); + lua_setfield(L, -2, "type"); + push_aabb3f(L, box.wall_top); + lua_setfield(L, -2, "wall_top"); + push_aabb3f(L, box.wall_bottom); + lua_setfield(L, -2, "wall_bottom"); + push_aabb3f(L, box.wall_side); + lua_setfield(L, -2, "wall_side"); + break; + case NODEBOX_CONNECTED: + lua_pushstring(L, "connected"); + lua_setfield(L, -2, "type"); + push_box(L, box.connect_top); + lua_setfield(L, -2, "connect_top"); + push_box(L, box.connect_bottom); + lua_setfield(L, -2, "connect_bottom"); + push_box(L, box.connect_front); + lua_setfield(L, -2, "connect_front"); + push_box(L, box.connect_back); + lua_setfield(L, -2, "connect_back"); + push_box(L, box.connect_left); + lua_setfield(L, -2, "connect_left"); + push_box(L, box.connect_right); + lua_setfield(L, -2, "connect_right"); + break; + default: + FATAL_ERROR("Invalid box.type"); + break; + } +} + +void push_box(lua_State *L, const std::vector &box) +{ + lua_newtable(L); + u8 i = 1; + for (std::vector::const_iterator it = box.begin(); + it != box.end(); ++it) { + push_aabb3f(L, (*it)); + lua_rawseti(L, -2, i); + } +} + +/******************************************************************************/ +void push_palette(lua_State *L, const std::vector *palette) +{ + lua_createtable(L, palette->size(), 0); + int newTable = lua_gettop(L); + int index = 1; + std::vector::const_iterator iter; + for (iter = palette->begin(); iter != palette->end(); ++iter) { + push_ARGB8(L, (*iter)); + lua_rawseti(L, newTable, index); + index++; + } +} + /******************************************************************************/ void read_server_sound_params(lua_State *L, int index, ServerSoundParams ¶ms) @@ -719,6 +963,17 @@ void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec) } } +void push_soundspec(lua_State *L, const SimpleSoundSpec &spec) +{ + lua_newtable(L); + lua_pushstring(L, spec.name.c_str()); + lua_setfield(L, -2, "name"); + lua_pushnumber(L, spec.gain); + lua_setfield(L, -2, "gain"); + lua_pushnumber(L, spec.fade); + lua_setfield(L, -2, "fade"); +} + /******************************************************************************/ NodeBox read_nodebox(lua_State *L, int index) { diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 28d8b1e8c..9b8796297 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -39,6 +39,7 @@ extern "C" { #include "util/string.h" #include "itemgroup.h" #include "itemdef.h" +#include "c_types.h" namespace Json { class Value; } @@ -64,8 +65,20 @@ class Schematic; ContentFeatures read_content_features (lua_State *L, int index); +void push_content_features (lua_State *L, + const ContentFeatures &c); + +void push_nodebox (lua_State *L, + const NodeBox &box); +void push_box (lua_State *L, + const std::vector &box); + +void push_palette (lua_State *L, + const std::vector *palette); + TileDef read_tiledef (lua_State *L, int index, u8 drawtype); + void read_soundspec (lua_State *L, int index, SimpleSoundSpec &spec); NodeBox read_nodebox (lua_State *L, int index); @@ -90,6 +103,9 @@ void read_item_definition (lua_State *L, int index, const ItemDefinition &defaul ItemDefinition &def); void push_item_definition (lua_State *L, const ItemDefinition &i); +void push_item_definition_full (lua_State *L, + const ItemDefinition &i); + void read_object_properties (lua_State *L, int index, ObjectProperties *prop, IItemDefManager *idef); @@ -147,6 +163,8 @@ std::vector read_items (lua_State *L, void read_soundspec (lua_State *L, int index, SimpleSoundSpec &spec); +void push_soundspec (lua_State *L, + const SimpleSoundSpec &spec); bool string_to_enum (const EnumString *spec, int &result, diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 22045e06d..87cfa00fe 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mainmenumanager.h" #include "map.h" #include "util/string.h" +#include "nodedef.h" extern MainGameCallback *g_gamecallback; @@ -260,6 +261,50 @@ int ModApiClient::l_get_server_info(lua_State *L) return 1; } +// get_item_def(itemstring) +int ModApiClient::l_get_item_def(lua_State *L) +{ + IGameDef *gdef = getGameDef(L); + assert(gdef); + + IItemDefManager *idef = gdef->idef(); + assert(idef); + + if (!lua_isstring(L, 1)) + return 0; + + const std::string &name(lua_tostring(L, 1)); + if (!idef->isKnown(name)) + return 0; + const ItemDefinition &def = idef->get(name); + + push_item_definition_full(L, def); + + return 1; +} + +// get_node_def(nodename) +int ModApiClient::l_get_node_def(lua_State *L) +{ + IGameDef *gdef = getGameDef(L); + assert(gdef); + + INodeDefManager *ndef = gdef->ndef(); + assert(ndef); + + if (!lua_isstring(L, 1)) + return 0; + + const std::string &name = lua_tostring(L, 1); + const ContentFeatures &cf = ndef->get(ndef->getId(name)); + if (cf.name != name) // Unknown node. | name = , cf.name = ignore + return 0; + + push_content_features(L, cf); + + return 1; +} + int ModApiClient::l_take_screenshot(lua_State *L) { Client *client = getClient(L); @@ -286,5 +331,7 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(sound_play); API_FCT(sound_stop); API_FCT(get_server_info); + API_FCT(get_item_def); + API_FCT(get_node_def); API_FCT(take_screenshot); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 2267a4c9d..9813a5604 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define L_CLIENT_H_ #include "lua_api/l_base.h" +#include "itemdef.h" +#include "tool.h" class ModApiClient : public ModApiBase { @@ -38,7 +40,7 @@ private: // get_player_names() static int l_get_player_names(lua_State *L); - // show_formspec(name, fornspec) + // show_formspec(name, formspec) static int l_show_formspec(lua_State *L); // send_respawn() @@ -74,6 +76,12 @@ private: // get_server_info() static int l_get_server_info(lua_State *L); + + // get_item_def(itemstring) + static int l_get_item_def(lua_State *L); + + // get_node_def(nodename) + static int l_get_node_def(lua_State *L); static int l_take_screenshot(lua_State *L); -- cgit v1.2.3 From de840fe271cce96eeb7534683edac7e81bbb2f61 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Sun, 21 May 2017 17:30:00 +0200 Subject: Fix LINT broken by dfa0c15ce045705f05487d623dc7beca6c945b4b --- src/script/lua_api/l_client.cpp | 18 +++++++++--------- src/script/lua_api/l_client.h | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 87cfa00fe..09b832ccf 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -269,7 +269,7 @@ int ModApiClient::l_get_item_def(lua_State *L) IItemDefManager *idef = gdef->idef(); assert(idef); - + if (!lua_isstring(L, 1)) return 0; @@ -277,10 +277,10 @@ int ModApiClient::l_get_item_def(lua_State *L) if (!idef->isKnown(name)) return 0; const ItemDefinition &def = idef->get(name); - - push_item_definition_full(L, def); - return 1; + push_item_definition_full(L, def); + + return 1; } // get_node_def(nodename) @@ -288,20 +288,20 @@ int ModApiClient::l_get_node_def(lua_State *L) { IGameDef *gdef = getGameDef(L); assert(gdef); - + INodeDefManager *ndef = gdef->ndef(); assert(ndef); - + if (!lua_isstring(L, 1)) return 0; - + const std::string &name = lua_tostring(L, 1); const ContentFeatures &cf = ndef->get(ndef->getId(name)); if (cf.name != name) // Unknown node. | name = , cf.name = ignore return 0; - + push_content_features(L, cf); - + return 1; } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 9813a5604..09b74addd 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -76,10 +76,10 @@ private: // get_server_info() static int l_get_server_info(lua_State *L); - + // get_item_def(itemstring) static int l_get_item_def(lua_State *L); - + // get_node_def(nodename) static int l_get_node_def(lua_State *L); -- cgit v1.2.3 From 39f4a2f607d44738d60db84eba4b30e3d7450204 Mon Sep 17 00:00:00 2001 From: Pierre-Adrien Langrognet Date: Sun, 21 May 2017 23:06:51 +0200 Subject: [CSM] Add send_chat_message and run_server_chatcommand API functions (#5747) * [CSM] Add send_chat_message and run_server_chatcommand API functions * Add client-side chat message rate limiting * Limit out chat queue size * [CSM] Add minetest.clear_out_chat_queue API function and .clear_chat_queue chatcommand * Last fixes/cleanups before merge --- builtin/client/chatcommands.lua | 12 +++++++++ builtin/settingtypes.txt | 3 +++ doc/client_lua_api.md | 10 ++++++-- minetest.conf.example | 4 +++ src/client.cpp | 54 ++++++++++++++++++++++++++++++++++++++--- src/client.h | 8 ++++++ src/defaultsettings.cpp | 1 + src/script/lua_api/l_client.cpp | 19 +++++++++++++++ src/script/lua_api/l_client.h | 6 +++++ 9 files changed, 111 insertions(+), 6 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/builtin/client/chatcommands.lua b/builtin/client/chatcommands.lua index f425216f5..2b8cc4acd 100644 --- a/builtin/client/chatcommands.lua +++ b/builtin/client/chatcommands.lua @@ -51,3 +51,15 @@ core.register_chatcommand("disconnect", { core.disconnect() end, }) + +core.register_chatcommand("clear_chat_queue", { + description = core.gettext("Clear the out chat queue"), + func = function(param) + core.clear_out_chat_queue() + return true, core.gettext("The out chat queue is now empty") + end, +}) + +function core.run_server_chatcommand(cmd, param) + core.send_chat_message("/" .. cmd .. " " .. param) +end diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 463ca0be9..0ec33c628 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -312,6 +312,9 @@ serverlist_url (Serverlist URL) string servers.minetest.net # File in client/serverlist/ that contains your favorite servers displayed in the Multiplayer Tab. serverlist_file (Serverlist file) string favoriteservers.txt +# Maximum size of the out chat queue. 0 to disable queueing and -1 to make the queue size unlimited +max_out_chat_queue_size (Maximum size of the out chat queue) int 20 + [*Graphics] [**In-Game] diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index ce0746df4..b3e494cc1 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -721,6 +721,12 @@ Call these functions only at load time! ### Player * `minetest.get_wielded_item()` * Returns the itemstack the local player is holding +* `minetest.send_chat_message(message)` + * Act as if `message` was typed by the player into the terminal. +* `minetest.run_server_chatcommand(cmd, param)` + * Alias for `minetest.send_chat_message("/" .. cmd .. " " .. param)` +* `minetest.clear_out_chat_queue()` + * Clears the out chat queue * `minetest.localplayer` * Reference to the LocalPlayer object. See [`LocalPlayer`](#localplayer) class reference for methods. @@ -836,7 +842,7 @@ Please do not try to access the reference until the camera is initialized, other * Returns with same syntax as above * `get_fov()` * Returns: - + ```lua { x = number, @@ -845,7 +851,7 @@ Please do not try to access the reference until the camera is initialized, other actual = number } ``` - + * `get_pos()` * Returns position of camera with view bobbing * `get_offset()` diff --git a/minetest.conf.example b/minetest.conf.example index e9add1597..5e1609de6 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -343,6 +343,10 @@ # type: string # serverlist_file = favoriteservers.txt +# Maximum size of the out chat queue. 0 to disable queueing and -1 to make the queue size unlimited +# type: int min: -1 +max_out_chat_queue_size = 20 + ## Graphics ### In-Game diff --git a/src/client.cpp b/src/client.cpp index a36f5413f..a5228132d 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -104,6 +104,8 @@ Client::Client( m_animation_time(0), m_crack_level(-1), m_crack_pos(0,0,0), + m_last_chat_message_sent(time(NULL)), + m_chat_message_allowance(5.0f), m_map_seed(0), m_password(password), m_chosen_auth_mech(AUTH_MECHANISM_NONE), @@ -400,6 +402,14 @@ void Client::step(float dtime) } } + /* + Send pending messages on out chat queue + */ + if (!m_out_chat_queue.empty() && canSendChatMessage()) { + sendChatMessage(m_out_chat_queue.front()); + m_out_chat_queue.pop(); + } + /* Handle environment */ @@ -1158,13 +1168,50 @@ void Client::sendInventoryAction(InventoryAction *a) Send(&pkt); } +bool Client::canSendChatMessage() const +{ + u32 now = time(NULL); + float time_passed = now - m_last_chat_message_sent; + + float virt_chat_message_allowance = m_chat_message_allowance + time_passed * + (CLIENT_CHAT_MESSAGE_LIMIT_PER_10S / 8.0f); + + if (virt_chat_message_allowance < 1.0f) + return false; + + return true; +} + void Client::sendChatMessage(const std::wstring &message) { - NetworkPacket pkt(TOSERVER_CHAT_MESSAGE, 2 + message.size() * sizeof(u16)); + const s16 max_queue_size = g_settings->getS16("max_out_chat_queue_size"); + if (canSendChatMessage()) { + u32 now = time(NULL); + float time_passed = now - m_last_chat_message_sent; + m_last_chat_message_sent = time(NULL); - pkt << message; + m_chat_message_allowance += time_passed * (CLIENT_CHAT_MESSAGE_LIMIT_PER_10S / 8.0f); + if (m_chat_message_allowance > CLIENT_CHAT_MESSAGE_LIMIT_PER_10S) + m_chat_message_allowance = CLIENT_CHAT_MESSAGE_LIMIT_PER_10S; - Send(&pkt); + m_chat_message_allowance -= 1.0f; + + NetworkPacket pkt(TOSERVER_CHAT_MESSAGE, 2 + message.size() * sizeof(u16)); + + pkt << message; + + Send(&pkt); + } else if (m_out_chat_queue.size() < (u16) max_queue_size || max_queue_size == -1) { + m_out_chat_queue.push(message); + } else { + infostream << "Could not queue chat message because maximum out chat queue size (" + << max_queue_size << ") is reached." << std::endl; + } +} + +void Client::clearOutChatQueue() +{ + m_out_chat_queue = std::queue(); } void Client::sendChangePassword(const std::string &oldpassword, @@ -1924,4 +1971,3 @@ 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 cc0d4699d..b4145c76f 100644 --- a/src/client.h +++ b/src/client.h @@ -38,6 +38,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "tileanimation.h" #include "mesh_generator_thread.h" +#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f + struct MeshMakeData; class MapBlockMesh; class IWritableTextureSource; @@ -360,6 +362,7 @@ public: const StringMap &fields); void sendInventoryAction(InventoryAction *a); void sendChatMessage(const std::wstring &message); + void clearOutChatQueue(); void sendChangePassword(const std::string &oldpassword, const std::string &newpassword); void sendDamage(u8 damage); @@ -565,6 +568,8 @@ private: inline std::string getPlayerName() { return m_env.getLocalPlayer()->getName(); } + bool canSendChatMessage() const; + float m_packetcounter_timer; float m_connection_reinit_timer; float m_avg_rtt_timer; @@ -612,6 +617,9 @@ private: //s32 m_daynight_i; //u32 m_daynight_ratio; std::queue m_chat_queue; + std::queue m_out_chat_queue; + u32 m_last_chat_message_sent; + float m_chat_message_allowance; // The authentication methods we can use to enter sudo mode (=change password) u32 m_sudo_auth_methods; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index c583220bd..0a44069fd 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -57,6 +57,7 @@ void set_default_settings(Settings *settings) settings->setDefault("curl_verify_cert", "true"); settings->setDefault("enable_remote_media_server", "true"); settings->setDefault("enable_client_modding", "false"); + settings->setDefault("max_out_chat_queue_size", "20"); // Keymap settings->setDefault("remote_port", "30000"); diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 09b832ccf..0b7450af2 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -85,6 +85,23 @@ int ModApiClient::l_display_chat_message(lua_State *L) return 1; } +// send_chat_message(message) +int ModApiClient::l_send_chat_message(lua_State *L) +{ + if (!lua_isstring(L,1)) + return 0; + std::string message = luaL_checkstring(L, 1); + getClient(L)->sendChatMessage(utf8_to_wide(message)); + return 0; +} + +// clear_out_chat_queue() +int ModApiClient::l_clear_out_chat_queue(lua_State *L) +{ + getClient(L)->clearOutChatQueue(); + return 0; +} + // get_player_names() int ModApiClient::l_get_player_names(lua_State *L) { @@ -317,6 +334,8 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_current_modname); API_FCT(print); API_FCT(display_chat_message); + API_FCT(send_chat_message); + API_FCT(clear_out_chat_queue); API_FCT(get_player_names); API_FCT(set_last_run_mod); API_FCT(get_last_run_mod); diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 09b74addd..fe5780fb1 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -37,6 +37,12 @@ private: // display_chat_message(message) static int l_display_chat_message(lua_State *L); + // send_chat_message(message) + static int l_send_chat_message(lua_State *L); + + // clear_out_chat_queue() + static int l_clear_out_chat_queue(lua_State *L); + // get_player_names() static int l_get_player_names(lua_State *L); -- cgit v1.2.3 From 05309229b847ea4f289328890176d22c4655348b Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Mon, 22 May 2017 07:28:35 +0200 Subject: LINT fix & check all files with clang-format Seems the diff mode doesn't work well, PR are detected as working whereas in master it's shown it's problematic (and really problematic). Use same check everywhere --- src/script/lua_api/l_client.cpp | 2 +- util/travis/lint.sh | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'src/script/lua_api/l_client.cpp') diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 0b7450af2..3c2955bcd 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -88,7 +88,7 @@ int ModApiClient::l_display_chat_message(lua_State *L) // send_chat_message(message) int ModApiClient::l_send_chat_message(lua_State *L) { - if (!lua_isstring(L,1)) + if (!lua_isstring(L, 1)) return 0; std::string message = luaL_checkstring(L, 1); getClient(L)->sendChatMessage(utf8_to_wide(message)); diff --git a/util/travis/lint.sh b/util/travis/lint.sh index 4e816bd94..cd5f41779 100644 --- a/util/travis/lint.sh +++ b/util/travis/lint.sh @@ -9,13 +9,7 @@ function perform_lint() { echo "LINT: Using binary $CLANG_FORMAT" CLANG_FORMAT_WHITELIST="util/travis/clang-format-whitelist.txt" - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then - # Get list of every file modified in this pull request - files_to_lint="$(git diff --name-only --diff-filter=ACMRTUXB $TRAVIS_COMMIT_RANGE | grep '^src/[^.]*[.]\(cpp\|h\)$' | true)" - else - # Check everything for branch pushes - files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')" - fi + files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')" local errorcount=0 local fail=0 -- cgit v1.2.3