From e703c5b81f87550e636ebb1ebb1eb64027a44687 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Diego=20Mart=C3=ADnez?= <kaeza@users.sf.net>
Date: Wed, 24 Apr 2013 07:52:46 -0300
Subject: [PATCH] Added support to disable built-in HUD elements

---
 doc/lua_api.txt          |  3 +++
 src/client.cpp           | 14 ++++++++++++++
 src/client.h             |  7 ++++++-
 src/clientserver.h       | 12 ++++++++++--
 src/game.cpp             | 15 ++++++++++++---
 src/hud.cpp              |  8 +++++---
 src/hud.h                | 17 +++++++++++++++--
 src/player.cpp           |  6 ++++++
 src/player.h             |  1 +
 src/scriptapi_object.cpp | 37 +++++++++++++++++++++++++++++++++++++
 src/scriptapi_object.h   |  3 +++
 src/server.cpp           | 24 ++++++++++++++++++++++++
 src/server.h             |  2 ++
 13 files changed, 138 insertions(+), 11 deletions(-)

diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 42579fda3..b2106b64c 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1433,6 +1433,9 @@ Player-only: (no-op for other objects)
 - hud_change(id, stat, value): change a value of a previously added HUD element
   ^ element stat values: position, name, scale, text, number, item, dir
 - hud_get(id): gets the HUD element definition structure of the specified ID
+- hud_builtin_enable(what, flag): enable or disable built-in HUD items
+  ^ what: "hotbar", "healthbar", "crosshair", "wielditem"
+  ^ flag: true/false
 
 InvRef: Reference to an inventory
 methods:
diff --git a/src/client.cpp b/src/client.cpp
index 12ced17fe..941e9e882 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -2114,6 +2114,20 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 		event.hudchange.data    = intdata;
 		m_client_event_queue.push_back(event);
 	}
+	else if(command == TOCLIENT_HUD_BUILTIN_ENABLE)
+	{	
+		std::string datastring((char *)&data[2], datasize - 2);
+		std::istringstream is(datastring, std::ios_base::binary);
+
+		u32 id = readU8(is);
+		bool flag = (readU8(is) ? true : false);
+
+		ClientEvent event;
+		event.type = CE_HUD_BUILTIN_ENABLE;
+		event.hudbuiltin.id     = (HudBuiltinElement)id;
+		event.hudbuiltin.flag   = flag;
+		m_client_event_queue.push_back(event);
+	}
 	else
 	{
 		infostream<<"Client: Ignoring unknown command "
diff --git a/src/client.h b/src/client.h
index 67ba6c565..33872864e 100644
--- a/src/client.h
+++ b/src/client.h
@@ -163,7 +163,8 @@ enum ClientEventType
 	CE_DELETE_PARTICLESPAWNER,
 	CE_HUDADD,
 	CE_HUDRM,
-	CE_HUDCHANGE
+	CE_HUDCHANGE,
+	CE_HUD_BUILTIN_ENABLE
 };
 
 struct ClientEvent
@@ -243,6 +244,10 @@ struct ClientEvent
 			std::string *sdata;
 			u32 data;
 		} hudchange;
+		struct{
+			u32 id;
+			u32 flag;
+		} hudbuiltin;
 	};
 };
 
diff --git a/src/clientserver.h b/src/clientserver.h
index 5e981c202..114b04d13 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -94,6 +94,7 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
 		TOCLIENT_HUD_ADD
 		TOCLIENT_HUD_RM
 		TOCLIENT_HUD_CHANGE
+		TOCLIENT_HUD_BUILTIN_ENABLE
 */
 
 #define LATEST_PROTOCOL_VERSION 20
@@ -456,13 +457,13 @@ enum ToClientCommand
 		v2f1000 offset
 	*/
 
-	TOCLIENT_HUDRM = 0x50,
+	TOCLIENT_HUDRM = 0x4a,
 	/*
 		u16 command
 		u32 id
 	*/
 
-	TOCLIENT_HUDCHANGE = 0x51,
+	TOCLIENT_HUDCHANGE = 0x4b,
 	/*
 		u16 command
 		u32 id
@@ -472,6 +473,13 @@ enum ToClientCommand
 		 u8[len] data |
 		 u32 data]
 	*/
+
+	TOCLIENT_HUD_BUILTIN_ENABLE = 0x4c,
+	/*
+		u16 command
+		u8 id
+		u8 flag
+	*/
 };
 
 enum ToServerCommand
diff --git a/src/game.cpp b/src/game.cpp
index cbd9eab4d..e3251bf65 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -2186,6 +2186,14 @@ void the_game(
 					delete event.hudchange.v2fdata;
 					delete event.hudchange.sdata;
 				}
+				else if (event.type == CE_HUD_BUILTIN_ENABLE) {
+					u32 bit = (u32)event.hudbuiltin.id;
+					u32 mask = 1 << bit;
+					if (event.hudbuiltin.flag)
+						player->hud_flags |= mask;
+					else
+						player->hud_flags &= ~mask;
+				}
 			}
 		}
 		
@@ -3070,7 +3078,7 @@ void the_game(
 		/*
 			Wielded tool
 		*/
-		if(show_hud)
+		if(show_hud && (player->hud_flags & HUD_DRAW_WIELDITEM))
 		{
 			// Warning: This clears the Z buffer.
 			camera.drawWieldedTool();
@@ -3094,7 +3102,7 @@ void the_game(
 		/*
 			Draw crosshair
 		*/
-		if (show_hud)
+		if (show_hud && (player->hud_flags & HUD_DRAW_CROSSHAIR))
 			hud.drawCrosshair();
 			
 		} // timer
@@ -3109,7 +3117,8 @@ void the_game(
 		if (show_hud)
 		{
 			hud.drawHotbar(v2s32(displaycenter.X, screensize.Y),
-					client.getHP(), client.getPlayerItem());
+					client.getHP(), client.getPlayerItem(),
+					player->hud_flags);
 		}
 
 		/*
diff --git a/src/hud.cpp b/src/hud.cpp
index 9db92db52..8daadad37 100644
--- a/src/hud.cpp
+++ b/src/hud.cpp
@@ -277,7 +277,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s
 }
 
 
-void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
+void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, u32 flags) {
 	InventoryList *mainlist = inventory->getList("main");
 	if (mainlist == NULL) {
 		errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
@@ -288,8 +288,10 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
 	s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2);
 	v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2);
 	
-	drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0);
-	drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
+	if (flags & HUD_DRAW_HOTBAR)
+		drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0);
+	if (flags & HUD_DRAW_HEALTHBAR)
+		drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
 				"heart.png", halfheartcount, v2s32(0, 0));
 }
 
diff --git a/src/hud.h b/src/hud.h
index 104a2f00d..e0d7ccd6f 100644
--- a/src/hud.h
+++ b/src/hud.h
@@ -31,6 +31,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define HUD_CORNER_LOWER  1
 #define HUD_CORNER_CENTER 2
 
+#define HUD_DRAW_HOTBAR (1 << 0)
+#define HUD_DRAW_HEALTHBAR (1 << 1)
+#define HUD_DRAW_CROSSHAIR (1 << 2)
+#define HUD_DRAW_WIELDITEM (1 << 3)
+
 class Player;
 
 enum HudElementType {
@@ -66,6 +71,14 @@ struct HudElement {
 };
 
 
+enum HudBuiltinElement {
+	HUD_BUILTIN_HOTBAR = 0,
+	HUD_BUILTIN_HEALTHBAR,
+	HUD_BUILTIN_CROSSHAIR,
+	HUD_BUILTIN_WIELDITEM
+};
+
+
 inline u32 hud_get_free_id(Player *player) {
 	size_t size = player->hud.size();
 	for (size_t i = 0; i != size; i++) {
@@ -94,7 +107,7 @@ class Hud {
 	IGameDef *gamedef;
 	LocalPlayer *player;
 	Inventory *inventory;
-	
+
 	v2u32 screensize;
 	v2s32 displaycenter;
 	s32 hotbar_imagesize;
@@ -112,7 +125,7 @@ class Hud {
 	void drawLuaElements();
 	void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count, v2s32 offset);
 	
-	void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem);
+	void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, u32 flags);
 	void resizeHotbar();
 	
 	void drawCrosshair();
diff --git a/src/player.cpp b/src/player.cpp
index 1ca9423b0..e86b64206 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "player.h"
+#include "hud.h"
 #include "constants.h"
 #include "gamedef.h"
 #include "connection.h" // PEER_ID_INEXISTENT
@@ -76,6 +77,11 @@ Player::Player(IGameDef *gamedef):
 	physics_override_speed = 1;
 	physics_override_jump = 1;
 	physics_override_gravity = 1;
+
+	hud_flags = HUD_DRAW_HOTBAR
+			| HUD_DRAW_HEALTHBAR
+			| HUD_DRAW_CROSSHAIR
+			| HUD_DRAW_WIELDITEM;
 }
 
 Player::~Player()
diff --git a/src/player.h b/src/player.h
index d0e50d2c3..4e5b3af97 100644
--- a/src/player.h
+++ b/src/player.h
@@ -245,6 +245,7 @@ class Player
 	u32 keyPressed;
 	
 	std::vector<HudElement *> hud;
+	u32 hud_flags;
 
 protected:
 	IGameDef *m_gamedef;
diff --git a/src/scriptapi_object.cpp b/src/scriptapi_object.cpp
index 6669ad871..e2eec5104 100644
--- a/src/scriptapi_object.cpp
+++ b/src/scriptapi_object.cpp
@@ -52,6 +52,15 @@ struct EnumString es_HudElementStat[] =
 	{0, NULL},
 };
 
+struct EnumString es_HudBuiltinElement[] =
+{
+	{HUD_BUILTIN_HOTBAR,           "hotbar"},
+	{HUD_BUILTIN_HEALTHBAR,        "healthbar"},
+	{HUD_BUILTIN_CROSSHAIR,        "crosshair"},
+	{HUD_BUILTIN_WIELDITEM,        "wielditem"},
+	{0, NULL},
+};
+
 
 /*
 	ObjectRef
@@ -902,6 +911,33 @@ int ObjectRef::l_hud_get(lua_State *L)
 	return 1;
 }
 
+// hud_builtin_enable(self, id, flag)
+int ObjectRef::l_hud_builtin_enable(lua_State *L)
+{
+	ObjectRef *ref = checkobject(L, 1);
+	Player *player = getplayer(ref);
+	if (player == NULL)
+		return 0;
+
+	HudBuiltinElement id;
+	int id_i;
+	
+	std::string s(lua_tostring(L, 2));
+	
+	// Return nil if component is not in enum
+	if (!string_to_enum(es_HudBuiltinElement, id_i, s))
+		return 0;
+	
+	id = (HudBuiltinElement)id_i;
+
+	bool flag = (bool)lua_toboolean(L, 3);
+
+	bool ok = get_server(L)->hudBuiltinEnable(player, id, flag);
+
+	lua_pushboolean(L, (int)ok);
+	return 1;
+}
+
 ObjectRef::ObjectRef(ServerActiveObject *object):
 	m_object(object)
 {
@@ -1012,6 +1048,7 @@ const luaL_reg ObjectRef::methods[] = {
 	luamethod(ObjectRef, hud_remove),
 	luamethod(ObjectRef, hud_change),
 	luamethod(ObjectRef, hud_get),
+	luamethod(ObjectRef, hud_builtin_enable),
 	//luamethod(ObjectRef, hud_lock_next_bar),
 	//luamethod(ObjectRef, hud_unlock_bar),
 	{0,0}
diff --git a/src/scriptapi_object.h b/src/scriptapi_object.h
index fd46f2cf6..81e8cda33 100644
--- a/src/scriptapi_object.h
+++ b/src/scriptapi_object.h
@@ -202,6 +202,9 @@ class ObjectRef
 	// hud_get(self, id)
 	static int l_hud_get(lua_State *L);
 
+	// hud_builtin_enable(self, id, flag)
+	static int l_hud_builtin_enable(lua_State *L);
+
 public:
 	ObjectRef(ServerActiveObject *object);
 
diff --git a/src/server.cpp b/src/server.cpp
index 62c190036..a93d887e2 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -3675,6 +3675,22 @@ void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value
 	m_con.Send(peer_id, 0, data, true);
 }
 
+void Server::SendHUDBuiltinEnable(u16 peer_id, u32 id, bool flag)
+{
+	std::ostringstream os(std::ios_base::binary);
+
+	// Write command
+	writeU16(os, TOCLIENT_HUD_BUILTIN_ENABLE);
+	writeU8(os, id);
+	writeU8(os, (flag ? 1 : 0));
+
+	// 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
@@ -4664,6 +4680,14 @@ bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data)
 	return true;
 }
 
+bool Server::hudBuiltinEnable(Player *player, u32 id, bool flag) {
+	if (!player)
+		return false;
+
+	SendHUDBuiltinEnable(player->peer_id, id, flag);
+	return true;
+}
+
 void Server::notifyPlayers(const std::wstring msg)
 {
 	BroadcastChatMessage(msg);
diff --git a/src/server.h b/src/server.h
index b668ecae4..b951ae53f 100644
--- a/src/server.h
+++ b/src/server.h
@@ -540,6 +540,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	u32 hudAdd(Player *player, HudElement *element);
 	bool hudRemove(Player *player, u32 id);
 	bool hudChange(Player *player, u32 id, HudElementStat stat, void *value);
+	bool hudBuiltinEnable(Player *player, u32 id, bool flag);
 	
 private:
 
@@ -583,6 +584,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	void SendHUDAdd(u16 peer_id, u32 id, HudElement *form);
 	void SendHUDRemove(u16 peer_id, u32 id);
 	void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value);
+	void SendHUDBuiltinEnable(u16 peer_id, u32 id, bool flag);
 	/*
 		Send a node removal/addition event to all clients except ignore_id.
 		Additionally, if far_players!=NULL, players further away than
-- 
GitLab