Add TOCLIENT_SHOW_FORMSPEC to display formspecs at client from lua

This commit is contained in:
sapier 2013-01-02 19:45:04 +00:00 committed by Perttu Ahola
parent 36f03a7f4a
commit da9707950e
8 changed files with 129 additions and 2 deletions

@ -888,6 +888,9 @@ minetest.get_inventory(location) -> InvRef
minetest.create_detached_inventory(name, callbacks) -> InvRef minetest.create_detached_inventory(name, callbacks) -> InvRef
^ callbacks: See "Detached inventory callbacks" ^ callbacks: See "Detached inventory callbacks"
^ Creates a detached inventory. If it already exists, it is cleared. ^ Creates a detached inventory. If it already exists, it is cleared.
minetest.show_formspec(playername, formspec)
^ playername: name of player to show formspec
^ formspec: formspec to display
Item handling: Item handling:
minetest.inventorycube(img1, img2, img3) minetest.inventorycube(img1, img2, img3)

@ -1900,6 +1900,20 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
} }
inv->deSerialize(is); inv->deSerialize(is);
} }
else if(command == TOCLIENT_SHOW_FORMSPEC)
{
std::string datastring((char*)&data[2], datasize-2);
std::istringstream is(datastring, std::ios_base::binary);
std::string formspec = deSerializeLongString(is);
ClientEvent event;
event.type = CE_SHOW_FORMSPEC;
// pointer is required as event is a struct only!
// adding a std:string to a struct isn't possible
event.show_formspec.formspec = new std::string(formspec);
m_client_event_queue.push_back(event);
}
else else
{ {
infostream<<"Client: Ignoring unknown command " infostream<<"Client: Ignoring unknown command "

@ -154,7 +154,8 @@ enum ClientEventType
CE_PLAYER_DAMAGE, CE_PLAYER_DAMAGE,
CE_PLAYER_FORCE_MOVE, CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN, CE_DEATHSCREEN,
CE_TEXTURES_UPDATED CE_TEXTURES_UPDATED,
CE_SHOW_FORMSPEC
}; };
struct ClientEvent struct ClientEvent
@ -176,6 +177,9 @@ struct ClientEvent
f32 camera_point_target_y; f32 camera_point_target_y;
f32 camera_point_target_z; f32 camera_point_target_z;
} deathscreen; } deathscreen;
struct{
std::string* formspec;
} show_formspec;
struct{ struct{
} textures_updated; } textures_updated;
}; };

@ -77,9 +77,11 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
GENERIC_CMD_SET_ATTACHMENT GENERIC_CMD_SET_ATTACHMENT
PROTOCOL_VERSION 15: PROTOCOL_VERSION 15:
Serialization format changes Serialization format changes
PROTOCOL_VERSION 16:
TOCLIENT_SHOW_FORMSPEC
*/ */
#define LATEST_PROTOCOL_VERSION 15 #define LATEST_PROTOCOL_VERSION 16
// Server's supported network protocol range // Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 13 #define SERVER_PROTOCOL_VERSION_MIN 13
@ -354,6 +356,12 @@ enum ToClientCommand
u8[len] name u8[len] name
[2] serialized inventory [2] serialized inventory
*/ */
TOCLIENT_SHOW_FORMSPEC = 0x44,
/*
[0] u16 command
u16 len
u8[len] formspec
*/
}; };
enum ToServerCommand enum ToServerCommand

@ -192,6 +192,32 @@ public:
Client *m_client; Client *m_client;
}; };
class FormspecFormSource: public IFormSource
{
public:
FormspecFormSource(std::string formspec,FormspecFormSource** game_formspec)
{
m_formspec = formspec;
m_game_formspec = game_formspec;
}
~FormspecFormSource()
{
*m_game_formspec = 0;
}
void setForm(std::string formspec) {
m_formspec = formspec;
}
std::string getForm()
{
return m_formspec;
}
std::string m_formspec;
FormspecFormSource** m_game_formspec;
};
/* /*
Hotbar draw routine Hotbar draw routine
*/ */
@ -901,6 +927,7 @@ void the_game(
bool simple_singleplayer_mode bool simple_singleplayer_mode
) )
{ {
FormspecFormSource* current_formspec = 0;
video::IVideoDriver* driver = device->getVideoDriver(); video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager(); scene::ISceneManager* smgr = device->getSceneManager();
@ -2067,6 +2094,27 @@ void the_game(
player->setPosition(player->getPosition() + v3f(0,-BS,0)); player->setPosition(player->getPosition() + v3f(0,-BS,0));
camera.update(player, busytime, screensize);*/ camera.update(player, busytime, screensize);*/
} }
else if (event.type == CE_SHOW_FORMSPEC)
{
if (current_formspec == 0)
{
/* Create menu */
current_formspec = new FormspecFormSource(*(event.show_formspec.formspec),&current_formspec);
GUIFormSpecMenu *menu =
new GUIFormSpecMenu(device, guiroot, -1,
&g_menumgr,
&client, gamedef);
menu->setFormSource(current_formspec);
menu->drop();
}
else
{
/* update menu */
current_formspec->setForm(*(event.show_formspec.formspec));
}
delete(event.show_formspec.formspec);
}
else if(event.type == CE_TEXTURES_UPDATED) else if(event.type == CE_TEXTURES_UPDATED)
{ {
update_wielded_item_trigger = true; update_wielded_item_trigger = true;

@ -4899,6 +4899,21 @@ static int l_create_detached_inventory_raw(lua_State *L)
return 1; return 1;
} }
// create_detached_formspec_raw(name)
static int l_show_formspec(lua_State *L)
{
const char *playername = luaL_checkstring(L, 1);
const char *formspec = luaL_checkstring(L, 2);
if(get_server(L)->showFormspec(playername,formspec))
{
lua_pushboolean(L, true);
}else{
lua_pushboolean(L, false);
}
return 1;
}
// get_dig_params(groups, tool_capabilities[, time_from_last_punch]) // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
static int l_get_dig_params(lua_State *L) static int l_get_dig_params(lua_State *L)
{ {
@ -5228,6 +5243,7 @@ static const struct luaL_Reg minetest_f [] = {
{"unban_player_or_ip", l_unban_player_of_ip}, {"unban_player_or_ip", l_unban_player_of_ip},
{"get_inventory", l_get_inventory}, {"get_inventory", l_get_inventory},
{"create_detached_inventory_raw", l_create_detached_inventory_raw}, {"create_detached_inventory_raw", l_create_detached_inventory_raw},
{"show_formspec", l_show_formspec},
{"get_dig_params", l_get_dig_params}, {"get_dig_params", l_get_dig_params},
{"get_hit_params", l_get_hit_params}, {"get_hit_params", l_get_hit_params},
{"get_current_modname", l_get_current_modname}, {"get_current_modname", l_get_current_modname},

@ -3638,6 +3638,24 @@ void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
// Send as reliable // Send as reliable
m_con.Send(peer_id, 0, data, true); m_con.Send(peer_id, 0, data, true);
} }
void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec)
{
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
u8 buf[12];
// Write command
writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
os.write((char*)buf, 2);
os<<serializeLongString(formspec);
// Make data buffer
std::string s = os.str();
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
// Send as reliable
m_con.Send(peer_id, 0, data, true);
}
void Server::BroadcastChatMessage(const std::wstring &message) void Server::BroadcastChatMessage(const std::wstring &message)
{ {
@ -4578,6 +4596,20 @@ void Server::notifyPlayer(const char *name, const std::wstring msg)
SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg); SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
} }
bool Server::showFormspec(const char *playername, const std::string &formspec)
{
Player *player = m_env->getPlayer(playername);
if(!player)
{
infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
return false;
}
SendShowFormspecMessage(player->peer_id,formspec);
return true;
}
void Server::notifyPlayers(const std::wstring msg) void Server::notifyPlayers(const std::wstring msg)
{ {
BroadcastChatMessage(msg); BroadcastChatMessage(msg);

@ -583,6 +583,7 @@ public:
m_async_fatal_error.set(error); m_async_fatal_error.set(error);
} }
bool showFormspec(const char *name, const std::string &formspec);
private: private:
// con::PeerHandler implementation. // con::PeerHandler implementation.
@ -620,6 +621,7 @@ private:
void SendMovePlayer(u16 peer_id); void SendMovePlayer(u16 peer_id);
void SendPlayerPrivileges(u16 peer_id); void SendPlayerPrivileges(u16 peer_id);
void SendPlayerInventoryFormspec(u16 peer_id); void SendPlayerInventoryFormspec(u16 peer_id);
void SendShowFormspecMessage(u16 peer_id, const std::string formspec);
/* /*
Send a node removal/addition event to all clients except ignore_id. Send a node removal/addition event to all clients except ignore_id.
Additionally, if far_players!=NULL, players further away than Additionally, if far_players!=NULL, players further away than