[CSM] Add local formspecs. (#5094)
authorred-001 <red-001@outlook.ie>
Tue, 24 Jan 2017 16:26:15 +0000 (16:26 +0000)
committerLoïc Blot <nerzhul@users.noreply.github.com>
Mon, 13 Mar 2017 22:56:05 +0000 (23:56 +0100)
12 files changed:
builtin/client/init.lua
builtin/client/preview.lua
builtin/client/register.lua
builtin/common/misc_helpers.lua
doc/client_lua_api.txt
src/client.h
src/game.cpp
src/guiFormSpecMenu.h
src/script/cpp_api/s_client.cpp
src/script/cpp_api/s_client.h
src/script/lua_api/l_client.cpp
src/script/lua_api/l_client.h

index dd218aab66b9f40991edba96d212e43a71de6443..b204ee5e6c4388beeaf9aa51d00ff6ab082ceaf6 100644 (file)
@@ -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)
index 22e8bb97f647e9385b9b94d8eea4f20972d95654..4c01d665fe4a31479177a1ed3cd4dad5918fb583 100644 (file)
@@ -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,
 })
index 8b60c1222312c09b6f409535218da6abaf91a1d8..1e6ac434226fe8715c43d198f5eb20d604b32b91 100644 (file)
@@ -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()
 
 
index c2dc7514d71118dcdbb8d321ad67549676a59394..70b23600aab46423cd9dd97c1962246b25895ade 100644 (file)
@@ -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
-
index 8ce487bf8c8a92b635a60fe2fd191c684fa8507e..3170f4c84c18976c36eda37dd4c880b4e1918167 100644 (file)
@@ -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
 ---------------
 
index ff8aea5913c5decd6a2b59ff241910317b5c0b72..d170f9a07bdc198ecd0fe7669cbb19daed7b4d34 100644 (file)
@@ -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
index 2e2a8e0c10ad673f9129ee0b74e85d3f75412e6f..c84e08b01d8cc20d64d453774e717975bd9ce41e 100644 (file)
@@ -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(&current_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(&current_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)) {
index bbab9c16454b54c1a4b38ceaaa0d8a6f5a11e8ce..35365a94b63cbaa223a32c6b12298b0b8a28ae1f 100644 (file)
@@ -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;
        }
 
index ce88d67e38d874f0641b1473d272bfdd857cf8a0..1827d483bfa7280d66e9bce8eedef7ca7b5a5690 100644 (file)
@@ -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);
+}
index 3d373f97c6851e0f905a120ed4b15dede0e131fd..42c41f8a419952ae38a2275d354add18fbc9c5fe 100644 (file)
@@ -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 <cstdint>
+#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
index 7eb340d782e3a560b1abd8a1767d21f4ec6cc44b..9a04bd02ff9a8350e4f0ce848fa85bd760b7b24b 100644 (file)
@@ -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);
 }
index 150880e3c4b09643330afbc976bdc390ace73d82..14ef5aecce942338454952e35e2935c87253f091 100644 (file)
@@ -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);