minetest.create_detached_inventory(name, callbacks) -> InvRef
^ callbacks: See "Detached inventory callbacks"
^ 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:
minetest.inventorycube(img1, img2, img3)
}
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
{
infostream<<"Client: Ignoring unknown command "
CE_PLAYER_DAMAGE,
CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN,
- CE_TEXTURES_UPDATED
+ CE_TEXTURES_UPDATED,
+ CE_SHOW_FORMSPEC
};
struct ClientEvent
f32 camera_point_target_y;
f32 camera_point_target_z;
} deathscreen;
+ struct{
+ std::string* formspec;
+ } show_formspec;
struct{
} textures_updated;
};
GENERIC_CMD_SET_ATTACHMENT
PROTOCOL_VERSION 15:
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
#define SERVER_PROTOCOL_VERSION_MIN 13
u8[len] name
[2] serialized inventory
*/
+ TOCLIENT_SHOW_FORMSPEC = 0x44,
+ /*
+ [0] u16 command
+ u16 len
+ u8[len] formspec
+ */
};
enum ToServerCommand
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
*/
bool simple_singleplayer_mode
)
{
+ FormspecFormSource* current_formspec = 0;
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
player->setPosition(player->getPosition() + v3f(0,-BS,0));
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),¤t_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)
{
update_wielded_item_trigger = true;
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])
static int l_get_dig_params(lua_State *L)
{
{"unban_player_or_ip", l_unban_player_of_ip},
{"get_inventory", l_get_inventory},
{"create_detached_inventory_raw", l_create_detached_inventory_raw},
+ {"show_formspec", l_show_formspec},
{"get_dig_params", l_get_dig_params},
{"get_hit_params", l_get_hit_params},
{"get_current_modname", l_get_current_modname},
// Send as reliable
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)
{
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)
{
BroadcastChatMessage(msg);
m_async_fatal_error.set(error);
}
+ bool showFormspec(const char *name, const std::string &formspec);
private:
// con::PeerHandler implementation.
void SendMovePlayer(u16 peer_id);
void SendPlayerPrivileges(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.
Additionally, if far_players!=NULL, players further away than