From d7447cdf9e4df3c345218886ab2bae0e0cc4fc55 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 1 Jun 2012 20:51:15 +0300 Subject: [PATCH] Implement sign using form field protocol --- doc/lua_api.txt | 4 +++ games/minimal/mods/default/init.lua | 11 ++++++- src/client.cpp | 36 +++++++++-------------- src/client.h | 5 ++-- src/clientserver.h | 16 +++++++++- src/content_nodemeta.cpp | 4 ++- src/game.cpp | 4 ++- src/scriptapi.cpp | 45 +++++++++++++++++++++++++++-- src/scriptapi.h | 5 ++++ src/server.cpp | 18 ++++++++++++ 10 files changed, 117 insertions(+), 31 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 58c260425..73d7b3641 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1036,6 +1036,10 @@ Node definition (register_node) on_dig = func(pos, node, digger), ^ default: minetest.node_dig ^ By default: checks privileges, wears out tool and removes node + + on_receive_fields = func(pos, formname, fields, sender), + ^ fields = {name1 = value1, name2 = value2, ...} + ^ default: nil } Recipe: (register_craft) diff --git a/games/minimal/mods/default/init.lua b/games/minimal/mods/default/init.lua index 9573db119..603380d5b 100644 --- a/games/minimal/mods/default/init.lua +++ b/games/minimal/mods/default/init.lua @@ -1116,7 +1116,16 @@ minetest.register_node("default:sign_wall", { --local n = minetest.env:get_node(pos) local meta = minetest.env:get_meta(pos) meta:set_string("formspec", "hack:sign_text_input") - meta:set_string("infotext", "\"${text}\"") + meta:set_string("infotext", "\"\"") + end, + on_receive_fields = function(pos, formname, fields, sender) + --print("Sign at "..minetest.pos_to_string(pos).." got "..dump(fields)) + local meta = minetest.env:get_meta(pos) + fields.text = fields.text or "" + print((sender:get_player_name() or "").." wrote \""..fields.text.. + "\" to sign at "..minetest.pos_to_string(pos)) + meta:set_string("text", fields.text) + meta:set_string("infotext", '"'..fields.text..'"') end, }) diff --git a/src/client.cpp b/src/client.cpp index 72667a528..84cae8f97 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1740,33 +1740,23 @@ void Client::interact(u8 action, const PointedThing& pointed) Send(0, data, true); } -void Client::sendSignNodeText(v3s16 p, std::string text) +void Client::sendNodemetaFields(v3s16 p, const std::string &formname, + const std::map &fields) { - /* - u16 command - v3s16 p - u16 textlen - textdata - */ std::ostringstream os(std::ios_base::binary); - u8 buf[12]; - - // Write command - writeU16(buf, TOSERVER_SIGNNODETEXT); - os.write((char*)buf, 2); - - // Write p - writeV3S16(buf, p); - os.write((char*)buf, 6); - u16 textlen = text.size(); - // Write text length - writeS16(buf, textlen); - os.write((char*)buf, 2); + writeU16(os, TOSERVER_NODEMETA_FIELDS); + writeV3S16(os, p); + os<::const_iterator + i = fields.begin(); i != fields.end(); i++){ + const std::string &name = i->first; + const std::string &value = i->second; + os< data((u8*)s.c_str(), s.size()); diff --git a/src/client.h b/src/client.h index 72ab70abd..0ed3eea3b 100644 --- a/src/client.h +++ b/src/client.h @@ -210,11 +210,12 @@ public: void interact(u8 action, const PointedThing& pointed); - void sendSignNodeText(v3s16 p, std::string text); + void sendNodemetaFields(v3s16 p, const std::string &formname, + const std::map &fields); void sendInventoryAction(InventoryAction *a); void sendChatMessage(const std::wstring &message); void sendChangePassword(const std::wstring oldpassword, - const std::wstring newpassword); + const std::wstring newpassword); void sendDamage(u8 damage); void sendRespawn(); diff --git a/src/clientserver.h b/src/clientserver.h index 461c13cd2..1b5a37848 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -415,7 +415,7 @@ enum ToServerCommand wstring message */ - TOSERVER_SIGNNODETEXT = 0x33, + TOSERVER_SIGNNODETEXT = 0x33, // obsolete /* u16 command v3s16 p @@ -484,6 +484,20 @@ enum ToServerCommand s32[len] sound_id */ + TOSERVER_NODEMETA_FIELDS = 0x3b, + /* + u16 command + v3s16 p + u16 len + u8[len] form name (reserved for future use) + u16 number of fields + for each field: + u16 len + u8[len] field name + u32 len + u8[len] field value + */ + TOSERVER_REQUEST_MEDIA = 0x40, /* u16 command diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp index ba4a0e513..a2a341ae0 100644 --- a/src/content_nodemeta.cpp +++ b/src/content_nodemeta.cpp @@ -57,7 +57,9 @@ static bool content_nodemeta_deserialize_legacy_body( else if(id == NODEMETA_SIGN) // SignNodeMetadata { meta->setString("text", deSerializeLongString(is)); - meta->setString("infotext","\"${text}\""); + //meta->setString("infotext","\"${text}\""); + meta->setString("infotext", + std::string("\"") + meta->getString("text") + "\""); meta->setString("formspec","field[text;;${text}]"); return false; } diff --git a/src/game.cpp b/src/game.cpp index 69fc601c3..815a5dd85 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -103,7 +103,9 @@ struct TextDestNodeMetadata : public TextDest std::string ntext = wide_to_narrow(text); infostream<<"Changing text of a sign node: " <sendSignNodeText(m_p, ntext); + std::map fields; + fields["text"] = ntext; + m_client->sendNodemetaFields(m_p, "", fields); } v3s16 m_p; diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 255d37fc2..f9ec58582 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -141,14 +141,14 @@ static Server* get_server(lua_State *L) return server; } -/*static ServerEnvironment* get_env(lua_State *L) +static ServerEnvironment* get_env(lua_State *L) { // Get environment from registry lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env"); ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1); lua_pop(L, 1); return env; -}*/ +} static void objectref_get(lua_State *L, u16 id) { @@ -4973,6 +4973,47 @@ void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node) script_error(L, "error: %s", lua_tostring(L, -1)); } +void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, + const std::string &formname, + const std::map &fields, + ServerActiveObject *sender) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); + + INodeDefManager *ndef = get_server(L)->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = get_env(L)->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return; + + // Push callback function on stack + if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_receive_fields")) + return; + + // Call function + // param 1 + push_v3s16(L, p); + // param 2 + lua_pushstring(L, formname.c_str()); + // param 3 + lua_newtable(L); + for(std::map::const_iterator + i = fields.begin(); i != fields.end(); i++){ + const std::string &name = i->first; + const std::string &value = i->second; + lua_pushstring(L, name.c_str()); + lua_pushlstring(L, value.c_str(), value.size()); + lua_settable(L, -3); + } + // param 4 + objectref_get_or_create(L, sender); + if(lua_pcall(L, 4, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); +} + /* environment */ diff --git a/src/scriptapi.h b/src/scriptapi.h index cd6a5614c..e6c16eba6 100644 --- a/src/scriptapi.h +++ b/src/scriptapi.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "mapnode.h" #include +#include class Server; class ServerEnvironment; @@ -83,6 +84,10 @@ bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node, ServerActiveObject *digger); void scriptapi_node_on_construct(lua_State *L, v3s16 p, MapNode node); void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node); +void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, + const std::string &formname, + const std::map &fields, + ServerActiveObject *sender); /* luaentity */ // Returns true if succesfully added into Lua; false otherwise. diff --git a/src/server.cpp b/src/server.cpp index 0ee0ef465..fbeff83bf 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3126,6 +3126,24 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) m_playing_sounds.erase(i++); } } + else if(command == TOSERVER_NODEMETA_FIELDS) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + v3s16 p = readV3S16(is); + std::string formname = deSerializeString(is); + int num = readU16(is); + std::map fields; + for(int k=0; k