Implement sign using form field protocol

This commit is contained in:
Perttu Ahola 2012-06-01 20:51:15 +03:00
parent ff8d2bbc36
commit d7447cdf9e
10 changed files with 117 additions and 31 deletions

@ -1036,6 +1036,10 @@ Node definition (register_node)
on_dig = func(pos, node, digger), on_dig = func(pos, node, digger),
^ default: minetest.node_dig ^ default: minetest.node_dig
^ By default: checks privileges, wears out tool and removes node ^ 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) Recipe: (register_craft)

@ -1116,7 +1116,16 @@ minetest.register_node("default:sign_wall", {
--local n = minetest.env:get_node(pos) --local n = minetest.env:get_node(pos)
local meta = minetest.env:get_meta(pos) local meta = minetest.env:get_meta(pos)
meta:set_string("formspec", "hack:sign_text_input") 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, end,
}) })

@ -1740,32 +1740,22 @@ void Client::interact(u8 action, const PointedThing& pointed)
Send(0, data, true); 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); std::ostringstream os(std::ios_base::binary);
u8 buf[12];
// Write command writeU16(os, TOSERVER_NODEMETA_FIELDS);
writeU16(buf, TOSERVER_SIGNNODETEXT); writeV3S16(os, p);
os.write((char*)buf, 2); os<<serializeString(formname);
writeU16(os, fields.size());
// Write p for(std::map<std::string, std::string>::const_iterator
writeV3S16(buf, p); i = fields.begin(); i != fields.end(); i++){
os.write((char*)buf, 6); const std::string &name = i->first;
const std::string &value = i->second;
u16 textlen = text.size(); os<<serializeString(name);
// Write text length os<<serializeLongString(value);
writeS16(buf, textlen); }
os.write((char*)buf, 2);
// Write text
os.write((char*)text.c_str(), textlen);
// Make data buffer // Make data buffer
std::string s = os.str(); std::string s = os.str();

@ -210,7 +210,8 @@ public:
void interact(u8 action, const PointedThing& pointed); 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 sendInventoryAction(InventoryAction *a);
void sendChatMessage(const std::wstring &message); void sendChatMessage(const std::wstring &message);
void sendChangePassword(const std::wstring oldpassword, void sendChangePassword(const std::wstring oldpassword,

@ -415,7 +415,7 @@ enum ToServerCommand
wstring message wstring message
*/ */
TOSERVER_SIGNNODETEXT = 0x33, TOSERVER_SIGNNODETEXT = 0x33, // obsolete
/* /*
u16 command u16 command
v3s16 p v3s16 p
@ -484,6 +484,20 @@ enum ToServerCommand
s32[len] sound_id 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, TOSERVER_REQUEST_MEDIA = 0x40,
/* /*
u16 command u16 command

@ -57,7 +57,9 @@ static bool content_nodemeta_deserialize_legacy_body(
else if(id == NODEMETA_SIGN) // SignNodeMetadata else if(id == NODEMETA_SIGN) // SignNodeMetadata
{ {
meta->setString("text", deSerializeLongString(is)); 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}]"); meta->setString("formspec","field[text;;${text}]");
return false; return false;
} }

@ -103,7 +103,9 @@ struct TextDestNodeMetadata : public TextDest
std::string ntext = wide_to_narrow(text); std::string ntext = wide_to_narrow(text);
infostream<<"Changing text of a sign node: " infostream<<"Changing text of a sign node: "
<<ntext<<std::endl; <<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; v3s16 m_p;

@ -141,14 +141,14 @@ static Server* get_server(lua_State *L)
return server; return server;
} }
/*static ServerEnvironment* get_env(lua_State *L) static ServerEnvironment* get_env(lua_State *L)
{ {
// Get environment from registry // Get environment from registry
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env"); lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1); ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
return env; return env;
}*/ }
static void objectref_get(lua_State *L, u16 id) 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)); 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 environment
*/ */

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string> #include <string>
#include "mapnode.h" #include "mapnode.h"
#include <set> #include <set>
#include <map>
class Server; class Server;
class ServerEnvironment; class ServerEnvironment;
@ -83,6 +84,10 @@ bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node,
ServerActiveObject *digger); ServerActiveObject *digger);
void scriptapi_node_on_construct(lua_State *L, v3s16 p, MapNode node); 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_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 */ /* luaentity */
// Returns true if succesfully added into Lua; false otherwise. // Returns true if succesfully added into Lua; false otherwise.

@ -3126,6 +3126,24 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
m_playing_sounds.erase(i++); 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 else
{ {
infostream<<"Server::ProcessData(): Ignoring " infostream<<"Server::ProcessData(): Ignoring "