From 96fe1de8322a57ad82fcab3540c1eb44f74b9989 Mon Sep 17 00:00:00 2001
From: Kahrl <kahrl@gmx.net>
Date: Sat, 4 May 2013 02:08:52 +0200
Subject: [PATCH] Add ObjectRef.hud_set_hotbar_itemcount and add
 TOCLIENT_HUD_SET_PARAM

---
 doc/lua_api.txt                 |  2 ++
 src/client.cpp                  | 17 +++++++++++++++++
 src/clientserver.h              |  8 ++++++++
 src/game.cpp                    |  4 ++--
 src/hud.cpp                     |  2 +-
 src/hud.h                       |  6 +++++-
 src/player.cpp                  |  2 ++
 src/player.h                    |  1 +
 src/script/lua_api/l_object.cpp | 18 ++++++++++++++++++
 src/script/lua_api/l_object.h   |  3 +++
 src/server.cpp                  | 28 ++++++++++++++++++++++++++++
 src/server.h                    |  2 ++
 12 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 260a62763..5143c2ef3 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1399,6 +1399,8 @@ Player-only: (no-op for other objects)
   ^ flags: (is visible) hotbar, healthbar, crosshair, wielditem
   ^ pass a table containing a true/false value of each flag to be set or unset
   ^ if a flag is nil, the flag is not modified
+- hud_set_hotbar_itemcount(count): sets number of items in builtin hotbar
+  ^ count: number of items, must be between 1 and 23
 
 InvRef: Reference to an inventory
 methods:
diff --git a/src/client.cpp b/src/client.cpp
index e4ca52dd5..6b1789fe0 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -2136,6 +2136,23 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 		player->hud_flags &= ~mask;
 		player->hud_flags |= flags;
 	}
+	else if(command == TOCLIENT_HUD_SET_PARAM)
+	{
+		std::string datastring((char *)&data[2], datasize - 2);
+		std::istringstream is(datastring, std::ios_base::binary);
+
+		Player *player = m_env.getLocalPlayer();
+		assert(player != NULL);
+
+		u16 param         = readU16(is);
+		std::string value = deSerializeString(is);
+
+		if(param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4){
+			s32 hotbar_itemcount = readS32((u8*) value.c_str());
+			if(hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX)
+				player->hud_hotbar_itemcount = hotbar_itemcount;
+		}
+	}
 	else
 	{
 		infostream<<"Client: Ignoring unknown command "
diff --git a/src/clientserver.h b/src/clientserver.h
index ee9271bbc..a43baab23 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -480,6 +480,14 @@ enum ToClientCommand
 		u32 flags
 		u32 mask
 	*/
+
+	TOCLIENT_HUD_SET_PARAM = 0x4d,
+	/*
+		u16 command
+		u16 param
+		u16 len
+		u8[len] value
+	*/
 };
 
 enum ToServerCommand
diff --git a/src/game.cpp b/src/game.cpp
index 921cce327..4f0d1b663 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -1987,7 +1987,7 @@ void the_game(
 		{
 			s32 wheel = input->getMouseWheel();
 			u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1,
-					hud.hotbar_itemcount-1);
+					player->hud_hotbar_itemcount-1);
 
 			if(wheel < 0)
 			{
@@ -2011,7 +2011,7 @@ void the_game(
 			const KeyPress *kp = NumberKey + (i + 1) % 10;
 			if(input->wasKeyDown(*kp))
 			{
-				if(i < PLAYER_INVENTORY_SIZE && i < hud.hotbar_itemcount)
+				if(i < PLAYER_INVENTORY_SIZE && i < player->hud_hotbar_itemcount)
 				{
 					new_playeritem = i;
 
diff --git a/src/hud.cpp b/src/hud.cpp
index 65c78ca50..a3ae38bcb 100644
--- a/src/hud.cpp
+++ b/src/hud.cpp
@@ -43,7 +43,6 @@ Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv,
 	screensize       = v2u32(0, 0);
 	displaycenter    = v2s32(0, 0);
 	hotbar_imagesize = 48;
-	hotbar_itemcount = 8;
 	
 	tsrc = gamedef->getTextureSource();
 	
@@ -286,6 +285,7 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
 		return;
 	}
 	
+	s32 hotbar_itemcount = player->hud_hotbar_itemcount;
 	s32 padding = hotbar_imagesize / 12;
 	s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2);
 	v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2);
diff --git a/src/hud.h b/src/hud.h
index 54b7e7f36..fa9d33f8b 100644
--- a/src/hud.h
+++ b/src/hud.h
@@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define HUD_FLAG_CROSSHAIR_VISIBLE (1 << 2)
 #define HUD_FLAG_WIELDITEM_VISIBLE (1 << 3)
 
+#define HUD_PARAM_HOTBAR_ITEMCOUNT 1
+
+#define HUD_HOTBAR_ITEMCOUNT_DEFAULT 8
+#define HUD_HOTBAR_ITEMCOUNT_MAX     23
+
 class Player;
 
 enum HudElementType {
@@ -102,7 +107,6 @@ class Hud {
 	v2u32 screensize;
 	v2s32 displaycenter;
 	s32 hotbar_imagesize;
-	s32 hotbar_itemcount;
 	
 	video::SColor crosshair_argb;
 	video::SColor selectionbox_argb;
diff --git a/src/player.cpp b/src/player.cpp
index 34f0fda08..4eb5955c0 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -81,6 +81,8 @@ Player::Player(IGameDef *gamedef):
 
 	hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
 			 HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE;
+
+	hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT;
 }
 
 Player::~Player()
diff --git a/src/player.h b/src/player.h
index 63e166b4b..d3738fd52 100644
--- a/src/player.h
+++ b/src/player.h
@@ -250,6 +250,7 @@ class Player
 	
 	std::vector<HudElement *> hud;
 	u32 hud_flags;
+	s32 hud_hotbar_itemcount;
 
 protected:
 	IGameDef *m_gamedef;
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 6dec3db85..1e45610a6 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -978,6 +978,23 @@ int ObjectRef::l_hud_set_flags(lua_State *L)
 	return 1;
 }
 
+// hud_set_hotbar_itemcount(self, hotbar_itemcount)
+int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
+{
+	ObjectRef *ref = checkobject(L, 1);
+	Player *player = getplayer(ref);
+	if (player == NULL)
+		return 0;
+
+	s32 hotbar_itemcount = lua_tonumber(L, 2);
+
+	if (!STACK_TO_SERVER(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
+		return 0;
+
+	lua_pushboolean(L, true);
+	return 1;
+}
+
 ObjectRef::ObjectRef(ServerActiveObject *object):
 	m_object(object)
 {
@@ -1089,6 +1106,7 @@ const luaL_reg ObjectRef::methods[] = {
 	luamethod(ObjectRef, hud_change),
 	luamethod(ObjectRef, hud_get),
 	luamethod(ObjectRef, hud_set_flags),
+	luamethod(ObjectRef, hud_set_hotbar_itemcount),
 	{0,0}
 };
 
diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h
index 88f980a27..57dac0e64 100644
--- a/src/script/lua_api/l_object.h
+++ b/src/script/lua_api/l_object.h
@@ -209,6 +209,9 @@ class ObjectRef
 	// hud_set_flags(self, flags)
 	static int l_hud_set_flags(lua_State *L);
 
+	// hud_set_hotbar_itemcount(self, hotbar_itemcount)
+	static int l_hud_set_hotbar_itemcount(lua_State *L);
+
 public:
 	ObjectRef(ServerActiveObject *object);
 
diff --git a/src/server.cpp b/src/server.cpp
index 12695e1b4..4268bb809 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -3687,6 +3687,22 @@ void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
 	m_con.Send(peer_id, 0, data, true);
 }
 
+void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
+{
+	std::ostringstream os(std::ios_base::binary);
+
+	// Write command
+	writeU16(os, TOCLIENT_HUD_SET_PARAM);
+	writeU16(os, param);
+	os<<serializeString(value);
+
+	// 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)
 {
 	for(std::map<u16, RemoteClient*>::iterator
@@ -4684,6 +4700,18 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
 	return true;
 }
 
+bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
+	if (!player)
+		return false;
+	if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
+		return false;
+
+	std::ostringstream os(std::ios::binary);
+	writeS32(os, hotbar_itemcount);
+	SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
+	return true;
+}
+
 void Server::notifyPlayers(const std::wstring msg)
 {
 	BroadcastChatMessage(msg);
diff --git a/src/server.h b/src/server.h
index 3906f43b8..edc5c4895 100644
--- a/src/server.h
+++ b/src/server.h
@@ -541,6 +541,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	bool hudRemove(Player *player, u32 id);
 	bool hudChange(Player *player, u32 id, HudElementStat stat, void *value);
 	bool hudSetFlags(Player *player, u32 flags, u32 mask);
+	bool hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount);
 	
 private:
 
@@ -585,6 +586,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	void SendHUDRemove(u16 peer_id, u32 id);
 	void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value);
 	void SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask);
+	void SendHUDSetParam(u16 peer_id, u16 param, const std::string &value);
 	
 	/*
 		Send a node removal/addition event to all clients except ignore_id.
-- 
GitLab