diff options
author | Perttu Ahola <celeron55@gmail.com> | 2012-06-01 20:51:15 +0300 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2012-06-03 22:31:01 +0300 |
commit | d7447cdf9e4df3c345218886ab2bae0e0cc4fc55 (patch) | |
tree | 4ebc1c2fd91d66f8711ed87013af80a4adf53cc0 | |
parent | ff8d2bbc3682b12d40d1dfb212d39a50c498fb93 (diff) | |
download | minetest-d7447cdf9e4df3c345218886ab2bae0e0cc4fc55.tar.gz minetest-d7447cdf9e4df3c345218886ab2bae0e0cc4fc55.tar.bz2 minetest-d7447cdf9e4df3c345218886ab2bae0e0cc4fc55.zip |
Implement sign using form field protocol
-rw-r--r-- | doc/lua_api.txt | 4 | ||||
-rw-r--r-- | games/minimal/mods/default/init.lua | 11 | ||||
-rw-r--r-- | src/client.cpp | 36 | ||||
-rw-r--r-- | src/client.h | 5 | ||||
-rw-r--r-- | src/clientserver.h | 16 | ||||
-rw-r--r-- | src/content_nodemeta.cpp | 4 | ||||
-rw-r--r-- | src/game.cpp | 4 | ||||
-rw-r--r-- | src/scriptapi.cpp | 45 | ||||
-rw-r--r-- | src/scriptapi.h | 5 | ||||
-rw-r--r-- | 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<std::string, std::string> &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<<serializeString(formname); + writeU16(os, fields.size()); + for(std::map<std::string, std::string>::const_iterator + i = fields.begin(); i != fields.end(); i++){ + const std::string &name = i->first; + const std::string &value = i->second; + os<<serializeString(name); + os<<serializeLongString(value); + } - // Write text - os.write((char*)text.c_str(), textlen); - // Make data buffer std::string s = os.str(); SharedBuffer<u8> 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<std::string, std::string> &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: " <<ntext<<std::endl; - m_client->sendSignNodeText(m_p, ntext); + std::map<std::string, std::string> 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<std::string, std::string> &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<std::string, std::string>::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 <string> #include "mapnode.h" #include <set> +#include <map> 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<std::string, std::string> &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<std::string, std::string> fields; + for(int k=0; k<num; k++){ + std::string fieldname = deSerializeString(is); + std::string fieldvalue = deSerializeLongString(is); + fields[fieldname] = fieldvalue; + } + + scriptapi_node_on_receive_fields(m_lua, p, formname, fields, + playersao); + } else { infostream<<"Server::ProcessData(): Ignoring " |