Implement sign using form field protocol
parent
ff8d2bbc36
commit
d7447cdf9e
|
@ -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,33 +1740,23 @@ 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(buf, TOSERVER_SIGNNODETEXT);
|
|
||||||
os.write((char*)buf, 2);
|
|
||||||
|
|
||||||
// Write p
|
|
||||||
writeV3S16(buf, p);
|
|
||||||
os.write((char*)buf, 6);
|
|
||||||
|
|
||||||
u16 textlen = text.size();
|
writeU16(os, TOSERVER_NODEMETA_FIELDS);
|
||||||
// Write text length
|
writeV3S16(os, p);
|
||||||
writeS16(buf, textlen);
|
os<<serializeString(formname);
|
||||||
os.write((char*)buf, 2);
|
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
|
// Make data buffer
|
||||||
std::string s = os.str();
|
std::string s = os.str();
|
||||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||||
|
|
|
@ -210,11 +210,12 @@ 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,
|
||||||
const std::wstring newpassword);
|
const std::wstring newpassword);
|
||||||
void sendDamage(u8 damage);
|
void sendDamage(u8 damage);
|
||||||
void sendRespawn();
|
void sendRespawn();
|
||||||
|
|
||||||
|
|
|
@ -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 "
|
||||||
|
|
Loading…
Reference in New Issue