From d62ae0e18bc570033ada07454b1642f696fe17b1 Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Sat, 30 Jul 2011 18:51:15 +0300
Subject: [PATCH] Rats are now eatable. Also made their selection box move
 smoothly.

---
 src/content_cao.h         |   3 +-
 src/content_inventory.cpp |  15 +++++
 src/content_inventory.h   |   2 +
 src/content_sao.cpp       |  12 ++++
 src/content_sao.h         |   1 +
 src/game.cpp              |   2 +
 src/inventory.cpp         |  15 +++++
 src/inventory.h           |  15 ++++-
 src/server.cpp            | 123 ++++++++++++++++++++++----------------
 src/serverobject.h        |   5 ++
 10 files changed, 138 insertions(+), 55 deletions(-)

diff --git a/src/content_cao.h b/src/content_cao.h
index b984be136..319f90380 100644
--- a/src/content_cao.h
+++ b/src/content_cao.h
@@ -187,7 +187,8 @@ class RatCAO : public ClientActiveObject
 	core::aabbox3d<f32>* getSelectionBox()
 		{return &m_selection_box;}
 	v3f getPosition()
-		{return m_position;}
+		{return pos_translator.vect_show;}
+		//{return m_position;}
 
 private:
 	core::aabbox3d<f32> m_selection_box;
diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp
index 24840d6af..de8f8e397 100644
--- a/src/content_inventory.cpp
+++ b/src/content_inventory.cpp
@@ -122,3 +122,18 @@ InventoryItem* item_craft_create_cook_result(const std::string &subname)
 	return NULL;
 }
 
+bool item_craft_is_eatable(const std::string &subname)
+{
+	if(subname == "cooked_rat")
+		return true;
+	return false;
+}
+
+s16 item_craft_eat_hp_change(const std::string &subname)
+{
+	if(subname == "cooked_rat")
+		return 6; // 3 hearts
+	return 0;
+}
+
+
diff --git a/src/content_inventory.h b/src/content_inventory.h
index 0f410128b..91550bb9a 100644
--- a/src/content_inventory.h
+++ b/src/content_inventory.h
@@ -37,6 +37,8 @@ ServerActiveObject* item_craft_create_object(const std::string &subname,
 s16                 item_craft_get_drop_count(const std::string &subname);
 bool                item_craft_is_cookable(const std::string &subname);
 InventoryItem*      item_craft_create_cook_result(const std::string &subname);
+bool                item_craft_is_eatable(const std::string &subname);
+s16                 item_craft_eat_hp_change(const std::string &subname);
 
 #endif
 
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index eadaa6e5f..638f50c9d 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -215,6 +215,18 @@ InventoryItem * ItemSAO::createInventoryItem()
 	}
 }
 
+void ItemSAO::rightClick(Player *player)
+{
+	dstream<<__FUNCTION_NAME<<std::endl;
+	InventoryItem *item = createInventoryItem();
+	if(item == NULL)
+		return;
+	
+	bool to_be_deleted = item->use(m_env, player);
+
+	if(to_be_deleted)
+		m_removed = true;
+}
 
 /*
 	RatSAO
diff --git a/src/content_sao.h b/src/content_sao.h
index e5b1223d4..060c18341 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -51,6 +51,7 @@ class ItemSAO : public ServerActiveObject
 	std::string getStaticData();
 	InventoryItem* createInventoryItem();
 	InventoryItem* createPickedUpItem(){return createInventoryItem();}
+	void rightClick(Player *player);
 private:
 	std::string m_inventorystring;
 	v3f m_speed_f;
diff --git a/src/game.cpp b/src/game.cpp
index 0afb351d1..74b8e5029 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -1656,6 +1656,8 @@ void the_game(
 			else if(input->getRightClicked())
 			{
 				std::cout<<DTIME<<"Right-clicked object"<<std::endl;
+				client.clickActiveObject(1,
+						selected_active_object->getId(), g_selected_item);
 			}
 		}
 		else // selected_object == NULL
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 7ef7f0138..ca050614f 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "content_mapnode.h"
 #include "content_inventory.h"
 #include "content_sao.h"
+#include "player.h"
 
 /*
 	InventoryItem
@@ -168,6 +169,20 @@ InventoryItem *CraftItem::createCookResult()
 	return item_craft_create_cook_result(m_subname);
 }
 
+bool CraftItem::use(ServerEnvironment *env, Player *player)
+{
+	if(item_craft_is_eatable(m_subname))
+	{
+		s16 hp_change = item_craft_eat_hp_change(m_subname);
+		if(player->hp + hp_change > 20)
+			player->hp = 20;
+		else
+			player->hp += hp_change;
+		return true;
+	}
+	return false;
+}
+
 /*
 	MapBlockObjectItem DEPRECATED
 	TODO: Remove
diff --git a/src/inventory.h b/src/inventory.h
index 5c64f89bb..66b1cd1f0 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 class ServerActiveObject;
 class ServerEnvironment;
+class Player;
 
 class InventoryItem
 {
@@ -99,12 +100,19 @@ class InventoryItem
 	/*
 		Other properties
 	*/
+
 	// Whether it can be cooked
 	virtual bool isCookable(){return false;}
 	// Time of cooking
 	virtual float getCookTime(){return 3.0;}
-	// Result of cooking
+	// Result of cooking (can randomize)
 	virtual InventoryItem *createCookResult(){return NULL;}
+	
+	// Eat, press, activate, whatever.
+	// Called when item is right-clicked when lying on ground.
+	// If returns true, item shall be deleted.
+	virtual bool use(ServerEnvironment *env,
+			Player *player){return false;}
 
 protected:
 	u16 m_count;
@@ -298,11 +306,16 @@ class CraftItem : public InventoryItem
 			return 0;
 		return QUANTITY_ITEM_MAX_COUNT - m_count;
 	}
+
 	/*
 		Other properties
 	*/
+
 	bool isCookable();
 	InventoryItem *createCookResult();
+
+	bool use(ServerEnvironment *env, Player *player);
+	
 	/*
 		Special methods
 	*/
diff --git a/src/server.cpp b/src/server.cpp
index e2e6ce46b..ab60be5cc 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2368,77 +2368,94 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 			return;
 		}
 
+		// Skip if object has been removed
+		if(obj->m_removed)
+			return;
+		
 		//TODO: Check that object is reasonably close
 		
 		// Left click, pick object up (usually)
 		if(button == 0)
 		{
-			InventoryList *ilist = player->inventory.getList("main");
-			if(g_settings.getBool("creative_mode") == false && ilist != NULL)
-			{
+			/*
+				Try creating inventory item
+			*/
+			InventoryItem *item = obj->createPickedUpItem();
 			
-				// Skip if inventory has no free space
-				if(ilist->getUsedSlots() == ilist->getSize())
+			if(item)
+			{
+				if(g_settings.getBool("creative_mode") == false)
 				{
-					dout_server<<"Player inventory has no free space"<<std::endl;
-					return;
-				}
+					InventoryList *ilist = player->inventory.getList("main");
+					if(ilist != NULL)
+					{
+						// Skip if inventory has no free space
+						if(ilist->getUsedSlots() == ilist->getSize())
+						{
+							dout_server<<"Player inventory has no free space"<<std::endl;
+							return;
+						}
 
-				// Skip if object has been removed
-				if(obj->m_removed)
-					return;
-				
-				/*
-					Create the inventory item
-				*/
-				InventoryItem *item = obj->createPickedUpItem();
-				
-				if(item)
-				{
-					// Add to inventory and send inventory
-					ilist->addItem(item);
-					UpdateCrafting(player->peer_id);
-					SendInventory(player->peer_id);
+						// Add to inventory and send inventory
+						ilist->addItem(item);
+						UpdateCrafting(player->peer_id);
+						SendInventory(player->peer_id);
 
-					// Remove object from environment
-					obj->m_removed = true;
+						// Remove object from environment
+						obj->m_removed = true;
+					}
 				}
-				else
-				{
-					/*
-						Item cannot be picked up. Punch it instead.
-					*/
+			}
+			else
+			{
+				/*
+					Item cannot be picked up. Punch it instead.
+				*/
 
-					ToolItem *titem = NULL;
-					std::string toolname = "";
+				ToolItem *titem = NULL;
+				std::string toolname = "";
 
-					InventoryList *mlist = player->inventory.getList("main");
-					if(mlist != NULL)
+				InventoryList *mlist = player->inventory.getList("main");
+				if(mlist != NULL)
+				{
+					InventoryItem *item = mlist->getItem(item_i);
+					if(item && (std::string)item->getName() == "ToolItem")
 					{
-						InventoryItem *item = mlist->getItem(item_i);
-						if(item && (std::string)item->getName() == "ToolItem")
-						{
-							titem = (ToolItem*)item;
-							toolname = titem->getToolName();
-						}
+						titem = (ToolItem*)item;
+						toolname = titem->getToolName();
 					}
+				}
 
-					v3f playerpos = player->getPosition();
-					v3f objpos = obj->getBasePosition();
-					v3f dir = (objpos - playerpos).normalize();
-					
-					u16 wear = obj->punch(toolname, dir);
-					
-					if(titem)
-					{
-						bool weared_out = titem->addWear(wear);
-						if(weared_out)
-							mlist->deleteItem(item_i);
-						SendInventory(player->peer_id);
-					}
+				v3f playerpos = player->getPosition();
+				v3f objpos = obj->getBasePosition();
+				v3f dir = (objpos - playerpos).normalize();
+				
+				u16 wear = obj->punch(toolname, dir);
+				
+				if(titem)
+				{
+					bool weared_out = titem->addWear(wear);
+					if(weared_out)
+						mlist->deleteItem(item_i);
+					SendInventory(player->peer_id);
 				}
 			}
 		}
+		// Right click, do something with object
+		if(button == 1)
+		{
+			// Track hp changes super-crappily
+			u16 oldhp = player->hp;
+			
+			// Do stuff
+			obj->rightClick(player);
+			
+			// Send back stuff
+			if(player->hp != oldhp)
+			{
+				SendPlayerHP(player);
+			}
+		}
 	}
 	else if(command == TOSERVER_GROUND_ACTION)
 	{
diff --git a/src/serverobject.h b/src/serverobject.h
index c008bf93e..01f199a4b 100644
--- a/src/serverobject.h
+++ b/src/serverobject.h
@@ -42,6 +42,7 @@ Some planning
 
 class ServerEnvironment;
 class InventoryItem;
+class Player;
 
 class ServerActiveObject : public ActiveObject
 {
@@ -105,6 +106,10 @@ class ServerActiveObject : public ActiveObject
 	*/
 	virtual u16 punch(const std::string &toolname, v3f dir)
 	{return 0;}
+
+	/*
+	*/
+	virtual void rightClick(Player *player){}
 	
 	/*
 		Number of players which know about this object. Object won't be
-- 
GitLab