From 16ad10e62f4dcf620f9a962b07aa39f1c561f8dc Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Thu, 19 Jul 2012 14:09:16 +0300 Subject: [PATCH] Allow defining player's inventory form in Lua --- doc/lua_api.txt | 12 +++++++-- games/minimal/mods/experimental/init.lua | 10 ++++++++ src/client.cpp | 10 ++++++++ src/clientserver.h | 8 ++++++ src/game.cpp | 28 +++++++++++++++------ src/player.cpp | 7 ++++++ src/player.h | 2 ++ src/scriptapi.cpp | 28 +++++++++++++++++++++ src/server.cpp | 32 ++++++++++++++++++++++++ src/server.h | 2 ++ 10 files changed, 129 insertions(+), 10 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 511ec7c8..823b4b82 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -759,6 +759,10 @@ minetest.register_on_respawnplayer(func(ObjectRef)) ^ Called when player is to be respawned ^ Called _before_ repositioning of player occurs ^ return true in func to disable regular player placement +minetest.register_on_joinplayer(func(ObjectRef)) +^ Called when a player joins the game +minetest.register_on_leaveplayer(func(ObjectRef)) +^ Called when a player leaves the game minetest.register_on_chat_message(func(name, message)) Other registration functions: @@ -993,8 +997,8 @@ LuaEntitySAO-only: (no-op for other objects) - settexturemod(mod) - setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2, - select_horiz_by_yawpitch=false) -- ^ Select sprite from spritesheet with optional animation and DM-style -- texture selection based on yaw relative to camera + ^ Select sprite from spritesheet with optional animation and DM-style + texture selection based on yaw relative to camera - get_entity_name() (DEPRECATED: Will be removed in a future version) - get_luaentity() Player-only: (no-op for other objects) @@ -1003,6 +1007,10 @@ Player-only: (no-op for other objects) - get_look_dir(): get camera direction as a unit vector - get_look_pitch(): pitch in radians - get_look_yaw(): yaw in radians (wraps around pretty randomly as of now) +- set_inventory_formspec(formspec) + ^ Redefine player's inventory form + ^ Should usually be called in on_joinplayer +- get_inventory_formspec() -> formspec string InvRef: Reference to an inventory methods: diff --git a/games/minimal/mods/experimental/init.lua b/games/minimal/mods/experimental/init.lua index e8551034..fb331024 100644 --- a/games/minimal/mods/experimental/init.lua +++ b/games/minimal/mods/experimental/init.lua @@ -504,6 +504,16 @@ minetest.register_craft({ } }) +--[[minetest.register_on_joinplayer(function(player) + minetest.after(3, function() + player:set_inventory_formspec("invsize[8,7.5;]".. + "image[1,0.6;1,2;player.png]".. + "list[current_player;main;0,3.5;8,4;]".. + "list[current_player;craft;3,0;3,3;]".. + "list[current_player;craftpreview;7,1;1,1;]") + end) +end)]] + minetest.log("experimental modname="..dump(minetest.get_current_modname())) minetest.log("experimental modpath="..dump(minetest.get_modpath("experimental"))) minetest.log("experimental worldpath="..dump(minetest.get_worldpath())) diff --git a/src/client.cpp b/src/client.cpp index 1327feb1..fdfb49c8 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1688,6 +1688,16 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } infostream<inventory_formspec = deSerializeLongString(is); + } else { infostream<<"Client: Ignoring unknown command " diff --git a/src/clientserver.h b/src/clientserver.h index 559fb5b1..07e7b831 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -58,6 +58,7 @@ with this program; if not, write to the Free Software Foundation, Inc., PROTOCOL_VERSION 11: TileDef in ContentFeatures Nodebox drawtype + Added after a release: TOCLIENT_INVENTORY_FORMSPEC */ #define PROTOCOL_VERSION 11 @@ -308,6 +309,13 @@ enum ToClientCommand u16 len u8[len] privilege */ + + TOCLIENT_INVENTORY_FORMSPEC = 0x42, + /* + u16 command + u32 len + u8[len] formspec + */ }; enum ToServerCommand diff --git a/src/game.cpp b/src/game.cpp index 98ffac3d..b29d2d64 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -144,6 +144,22 @@ public: v3s16 m_p; }; +class PlayerInventoryFormSource: public IFormSource +{ +public: + PlayerInventoryFormSource(Client *client): + m_client(client) + { + } + std::string getForm() + { + LocalPlayer* player = m_client->getEnv().getLocalPlayer(); + return player->inventory_formspec; + } + + Client *m_client; +}; + /* Hotbar draw routine */ @@ -1463,14 +1479,10 @@ void the_game( InventoryLocation inventoryloc; inventoryloc.setCurrentPlayer(); - menu->setFormSpec( - "invsize[8,7.5;]" - //"image[1,0.6;1,2;player.png]" - "list[current_player;main;0,3.5;8,4;]" - "list[current_player;craft;3,0;3,3;]" - "list[current_player;craftpreview;7,1;1,1;]" - , inventoryloc); - + PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client); + assert(src); + menu->setFormSpec(src->getForm(), inventoryloc); + menu->setFormSource(new PlayerInventoryFormSource(&client)); menu->drop(); } else if(input->wasKeyDown(EscapeKey)) diff --git a/src/player.cpp b/src/player.cpp index 999d842f..6dd90e95 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -48,6 +48,13 @@ Player::Player(IGameDef *gamedef): inventory.addList("craft", 9); inventory.addList("craftpreview", 1); inventory.addList("craftresult", 1); + + // Can be redefined via Lua + inventory_formspec = "invsize[8,7.5;]" + //"image[1,0.6;1,2;player.png]" + "list[current_player;main;0,3.5;8,4;]" + "list[current_player;craft;3,0;3,3;]" + "list[current_player;craftpreview;7,1;1,1;]"; } Player::~Player() diff --git a/src/player.h b/src/player.h index c3ccc960..352b93e8 100644 --- a/src/player.h +++ b/src/player.h @@ -157,6 +157,8 @@ public: u16 peer_id; + std::string inventory_formspec; + protected: IGameDef *m_gamedef; diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index f0648545..25af2d10 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -2864,6 +2864,32 @@ private: return 1; } + // set_inventory_formspec(self, formspec) + static int l_set_inventory_formspec(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + std::string formspec = luaL_checkstring(L, 2); + + player->inventory_formspec = formspec; + get_server(L)->reportInventoryFormspecModified(player->getName()); + lua_pushboolean(L, true); + return 1; + } + + // get_inventory_formspec(self) -> formspec + static int l_get_inventory_formspec(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + + std::string formspec = player->inventory_formspec; + lua_pushlstring(L, formspec.c_str(), formspec.size()); + return 1; + } + public: ObjectRef(ServerActiveObject *object): m_object(object) @@ -2960,6 +2986,8 @@ const luaL_reg ObjectRef::methods[] = { method(ObjectRef, get_look_dir), method(ObjectRef, get_look_pitch), method(ObjectRef, get_look_yaw), + method(ObjectRef, set_inventory_formspec), + method(ObjectRef, get_inventory_formspec), {0,0} }; diff --git a/src/server.cpp b/src/server.cpp index f8eaaf9c..d703f7d9 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2243,6 +2243,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send privileges SendPlayerPrivileges(peer_id); + // Send inventory formspec + SendPlayerInventoryFormspec(peer_id); + // Send inventory UpdateCrafting(peer_id); SendInventory(peer_id); @@ -3573,6 +3576,9 @@ void Server::SendPlayerPrivileges(u16 peer_id) { Player *player = m_env->getPlayer(peer_id); assert(player); + if(player->peer_id == PEER_ID_INEXISTENT) + return; + std::set privs; scriptapi_get_auth(m_lua, player->getName(), NULL, &privs); @@ -3591,6 +3597,24 @@ void Server::SendPlayerPrivileges(u16 peer_id) m_con.Send(peer_id, 0, data, true); } +void Server::SendPlayerInventoryFormspec(u16 peer_id) +{ + Player *player = m_env->getPlayer(peer_id); + assert(player); + if(player->peer_id == PEER_ID_INEXISTENT) + return; + + std::ostringstream os(std::ios_base::binary); + writeU16(os, TOCLIENT_INVENTORY_FORMSPEC); + os<inventory_formspec); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + s32 Server::playSound(const SimpleSoundSpec &spec, const ServerSoundParams ¶ms) { @@ -4357,6 +4381,14 @@ void Server::reportPrivsModified(const std::string &name) } } +void Server::reportInventoryFormspecModified(const std::string &name) +{ + Player *player = m_env->getPlayer(name.c_str()); + if(!player) + return; + SendPlayerInventoryFormspec(player->peer_id); +} + // Saves g_settings to configpath given at initialization void Server::saveConfig() { diff --git a/src/server.h b/src/server.h index 4d93ae6f..36c243cc 100644 --- a/src/server.h +++ b/src/server.h @@ -505,6 +505,7 @@ public: std::set getPlayerEffectivePrivs(const std::string &name); bool checkPriv(const std::string &name, const std::string &priv); void reportPrivsModified(const std::string &name=""); // ""=all + void reportInventoryFormspecModified(const std::string &name); // Saves g_settings to configpath given at initialization void saveConfig(); @@ -602,6 +603,7 @@ private: void SendPlayerHP(u16 peer_id); void SendMovePlayer(u16 peer_id); void SendPlayerPrivileges(u16 peer_id); + void SendPlayerInventoryFormspec(u16 peer_id); /* Send a node removal/addition event to all clients except ignore_id. Additionally, if far_players!=NULL, players further away than -- 2.30.2