diff --git a/src/client.cpp b/src/client.cpp
index 81dedd1446336f3b3fe0263ee49addd63b2e39fd..71a826a1fa5dc5b6aa9f68e88d9453beeb445d72 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -2004,6 +2004,14 @@ LocalPlayer* Client::getLocalPlayer()
 	return m_env.getLocalPlayer();
 }
 
+void Client::setPlayerWield(scene::ISceneNode *wield)
+{
+	//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
+	LocalPlayer *player = m_env.getLocalPlayer();
+	assert(player != NULL);
+	player->wield = wield;
+}
+
 void Client::setPlayerControl(PlayerControl &control)
 {
 	//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
diff --git a/src/client.h b/src/client.h
index 930987c02e7f676f1289626c4ad44bdb85dc5aef..e7a81a1112487dcdbf4974f2df299d864b11f472 100644
--- a/src/client.h
+++ b/src/client.h
@@ -210,6 +210,7 @@ class Client : public con::PeerHandler, public InventoryManager
 
 	LocalPlayer* getLocalPlayer();
 
+	void setPlayerWield(scene::ISceneNode *wield);
 	void setPlayerControl(PlayerControl &control);
 
 	void selectPlayerItem(u16 item);
diff --git a/src/game.cpp b/src/game.cpp
index 24f356e466ddda964a1c75d1c558aad3ed0c764b..af4886137ccf40d37ff36a5a83c67fe0d7ef1135 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -827,6 +827,44 @@ void the_game(
 	f32 camera_yaw = 0; // "right/left"
 	f32 camera_pitch = 0; // "up/down"
 
+	/*
+		Tool
+	*/
+	
+	v3f tool_wield_position(0.06*BS, 1.619*BS, 0.1*BS);
+	v3f tool_wield_rotation(-25, 180, -25);
+	float tool_wield_animation = 0.0;
+	scene::IMeshSceneNode *tool_wield;
+	{
+		scene::SMesh *mesh = new scene::SMesh();
+		scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+		video::SColor c(255,255,255,255);
+		video::S3DVertex vertices[4] =
+		{
+			video::S3DVertex(-0.5,0,0, 0,0,0, c, 0,1),
+			video::S3DVertex(0.5,0,0, 0,0,0, c, 1,1),
+			video::S3DVertex(0.5,0.5,0, 0,0,0, c, 1,0),
+			video::S3DVertex(-0.5,0.5,0, 0,0,0, c, 0,0),
+		};
+		u16 indices[] = {0,1,2,2,3,0};
+		buf->append(vertices, 4, indices, 6);
+		// Set material
+		buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
+		buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+		buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+		// Add to mesh
+		mesh->addMeshBuffer(buf);
+		buf->drop();
+	
+		tool_wield = smgr->addMeshSceneNode(mesh, camera.getPlayerNode());
+		mesh->drop();
+	}
+	tool_wield->setVisible(false);
+	tool_wield->setPosition(tool_wield_position);
+	tool_wield->setRotation(tool_wield_rotation);
+	
+	client.setPlayerWield(tool_wield);
+
 	/*
 		Clouds
 	*/
@@ -1765,6 +1803,7 @@ void the_game(
 				}
 			}
 			
+			
 			if(input->getRightClicked())
 			{
 				std::cout<<DTIME<<"Ground right-clicked"<<std::endl;
@@ -1831,6 +1870,14 @@ void the_game(
 		else{
 		}
 
+		
+		if(input->getLeftState())
+			// Tool animation loops 0.0 - 1.0 
+			tool_wield_animation = fmod(tool_wield_animation + dtime * 3.0, 1.0);
+		else
+			 // Return tool to holding position if not digging
+			tool_wield_animation /= 1.5;
+
 		} // selected_object == NULL
 		
 		input->resetLeftClicked();
@@ -1946,6 +1993,14 @@ void the_game(
 			);
 		}
 
+		/*
+			Animate tool
+		*/
+		{
+			tool_wield->setRotation(tool_wield_rotation - sin(tool_wield_animation * PI) * 40.0);
+			tool_wield->setPosition(tool_wield_position - sin(tool_wield_animation * PI) / 3.0);
+		}
+
 
 		/*
 			Update gui stuff (0ms)
diff --git a/src/inventory.h b/src/inventory.h
index 44ba6a5adf7cc3e5ebe5c56a943fc3137739a4f3..f70d69b6d71a33116cb575058234fc25aacdfc4e 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -53,6 +53,10 @@ class InventoryItem
 	// Shall make an exact clone of the item
 	virtual InventoryItem* clone() = 0;
 #ifndef SERVER
+	// Return the name of the image for this item
+	virtual std::string getBasename() { return ""; }
+	// Shall return an image of the item (or NULL)
+	virtual video::ITexture * getImageRaw() { return NULL; }
 	// Shall return an image to show in the GUI (or NULL)
 	virtual video::ITexture * getImage() { return NULL; }
 #endif
@@ -353,40 +357,53 @@ class ToolItem : public InventoryItem
 		return new ToolItem(m_toolname, m_wear);
 	}
 #ifndef SERVER
-	video::ITexture * getImage()
-	{
-		if(g_texturesource == NULL)
-			return NULL;
-		
-		std::string basename;
+	std::string getBasename() {
 		if(m_toolname == "WPick")
-			basename = "tool_woodpick.png";
+			return "tool_woodpick.png";
 		else if(m_toolname == "STPick")
-			basename = "tool_stonepick.png";
+			return "tool_stonepick.png";
 		else if(m_toolname == "SteelPick")
-			basename = "tool_steelpick.png";
+			return "tool_steelpick.png";
 		else if(m_toolname == "MesePick")
-			basename = "tool_mesepick.png";
+			return "tool_mesepick.png";
 		else if(m_toolname == "WShovel")
-			basename = "tool_woodshovel.png";
+			return "tool_woodshovel.png";
 		else if(m_toolname == "STShovel")
-			basename = "tool_stoneshovel.png";
+			return "tool_stoneshovel.png";
 		else if(m_toolname == "SteelShovel")
-			basename = "tool_steelshovel.png";
+			return "tool_steelshovel.png";
 		else if(m_toolname == "WAxe")
-			basename = "tool_woodaxe.png";
+			return "tool_woodaxe.png";
 		else if(m_toolname == "STAxe")
-			basename = "tool_stoneaxe.png";
+			return "tool_stoneaxe.png";
 		else if(m_toolname == "SteelAxe")
-			basename = "tool_steelaxe.png";
+			return "tool_steelaxe.png";
 		else if(m_toolname == "WSword")
-			basename = "tool_woodsword.png";
+			return "tool_woodsword.png";
 		else if(m_toolname == "STSword")
-			basename = "tool_stonesword.png";
+			return "tool_stonesword.png";
 		else if(m_toolname == "SteelSword")
-			basename = "tool_steelsword.png";
+			return "tool_steelsword.png";
 		else
-			basename = "cloud.png";
+			return "cloud.png";
+}
+	
+	video::ITexture * getImageRaw()
+	{
+		if(g_texturesource == NULL)
+			return NULL;
+		
+		return g_texturesource->getTextureRaw(getBasename());
+	}
+	
+	video::ITexture * getImage()
+	{
+		if(g_texturesource == NULL)
+			return NULL;
+		
+		std::string basename = getBasename();
+		
+		return g_texturesource->getTextureRaw(basename);
 		
 		/*
 			Calculate a progress value with sane amount of
diff --git a/src/player.cpp b/src/player.cpp
index 7cfdfebb69d45ebb739f50c43b51b5bd750b9e5a..03ae24f45b07de8734441a43be5c045082d16d98 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -309,12 +309,31 @@ LocalPlayer::LocalPlayer():
 	// Initialize hp to 0, so that no hearts will be shown if server
 	// doesn't support health points
 	hp = 0;
+	
+	// No tool wielded initially
+	wield = NULL;
 }
 
 LocalPlayer::~LocalPlayer()
 {
 }
 
+void LocalPlayer::wieldItem(u16 item)
+{
+	m_selected_item = item;
+	
+	if(wield) {
+		InventoryItem* i = inventory.getList("main")->getItem(m_selected_item);
+	
+		if(i && strcmp(i->getName(), "ToolItem") == 0) {
+			wield->getMaterial(0).setTexture(0, i->getImageRaw());
+			wield->setVisible(true);
+		}
+		else
+			wield->setVisible(false);
+	}
+}
+
 void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
 		core::list<CollisionInfo> *collision_info)
 {
diff --git a/src/player.h b/src/player.h
index 13cffa205a6986f802b77d0bd2fac2f7f486badd..0f2c400114c45508f92269ee2830fc22a520d9ad 100644
--- a/src/player.h
+++ b/src/player.h
@@ -356,6 +356,8 @@ class LocalPlayer : public Player
 	{
 		return true;
 	}
+	
+	void wieldItem(u16 item);
 
 	void move(f32 dtime, Map &map, f32 pos_max_d,
 			core::list<CollisionInfo> *collision_info);
@@ -365,6 +367,8 @@ class LocalPlayer : public Player
 	
 	PlayerControl control;
 
+	scene::ISceneNode *wield;
+
 private:
 	// This is used for determining the sneaking range
 	v3s16 m_sneak_node;