diff --git a/data/apple.png b/data/apple.png
new file mode 100644
index 0000000000000000000000000000000000000000..9593f28f6068b7d932036f42b9eede227e1c1616
Binary files /dev/null and b/data/apple.png differ
diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp
index de8f8e397c06d2705efb7885439e2467e8dfcb4d..2b0dfcb3ae816385190d347d1fda23da14e9fb65 100644
--- a/src/content_inventory.cpp
+++ b/src/content_inventory.cpp
@@ -1,4 +1,4 @@
-/*
+ /*
 Minetest-c55
 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
@@ -71,6 +71,8 @@ std::string item_craft_get_image_name(const std::string &subname)
 		return "scorched_stuff.png";
 	else if(subname == "firefly")
 		return "firefly.png";
+	else if(subname == "apple")
+		return "apple.png";
 	else
 		return "cloud.png"; // just something
 }
@@ -94,7 +96,7 @@ ServerActiveObject* item_craft_create_object(const std::string &subname,
 
 s16 item_craft_get_drop_count(const std::string &subname)
 {
-	if(subname == "rat" || subname == "firefly")
+	if(subname == "rat" || subname == "firefly" || subname == "apple")
 		return 1;
 
 	return -1;
@@ -126,6 +128,8 @@ bool item_craft_is_eatable(const std::string &subname)
 {
 	if(subname == "cooked_rat")
 		return true;
+	else if(subname == "apple")
+		return true;
 	return false;
 }
 
@@ -133,6 +137,8 @@ s16 item_craft_eat_hp_change(const std::string &subname)
 {
 	if(subname == "cooked_rat")
 		return 6; // 3 hearts
+	else if(subname == "apple")
+		return 12; // 6 hearts
 	return 0;
 }
 
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index 482b9eb636236ef43abe967131f679269f3ee1c1..1ae6886a5b123322fa8bb319e584534cb8c18755 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -1,4 +1,4 @@
-/*
+ /*
 Minetest-c55
 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
@@ -188,6 +188,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 	AtlasPointer pa_papyrus = g_texturesource->getTexture(
 			g_texturesource->getTextureId("papyrus.png"));
 	material_papyrus.setTexture(0, pa_papyrus.atlas);
+	
+	// Apple material
+	video::SMaterial material_apple;
+	material_apple.setFlag(video::EMF_LIGHTING, false);
+	material_apple.setFlag(video::EMF_BILINEAR_FILTER, false);
+	material_apple.setFlag(video::EMF_FOG_ENABLE, true);
+	material_apple.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+	AtlasPointer pa_apple = g_texturesource->getTexture(
+			g_texturesource->getTextureId("apple.png"));
+	material_apple.setTexture(0, pa_apple.atlas);
 
 	// junglegrass material
 	video::SMaterial material_junglegrass;
@@ -1203,6 +1213,56 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 			// Add to mesh collector
 			collector.append(material_ladder, vertices, 4, indices, 6);
 		}
+		else if(n.getContent() == CONTENT_APPLE)
+		{
+			u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+			video::SColor c = MapBlock_LightColor(255, l);
+
+			for(u32 j=0; j<4; j++)
+			{
+				video::S3DVertex vertices[4] =
+				{
+					video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
+						pa_apple.x0(), pa_apple.y1()),
+					video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
+						pa_apple.x1(), pa_apple.y1()),
+					video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
+						pa_apple.x1(), pa_apple.y0()),
+					video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
+						pa_apple.x0(), pa_apple.y0()),
+				};
+
+				if(j == 0)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(45);
+				}
+				else if(j == 1)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(-45);
+				}
+				else if(j == 2)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(135);
+				}
+				else if(j == 3)
+				{
+					for(u16 i=0; i<4; i++)
+						vertices[i].Pos.rotateXZBy(-135);
+				}
+
+				for(u16 i=0; i<4; i++)
+				{
+					vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+				}
+
+				u16 indices[] = {0,1,2,2,3,0};
+				// Add to mesh collector
+				collector.append(material_apple, vertices, 4, indices, 6);
+			}
+		}
 	}
 }
 #endif
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index 51f2f97368e1d8da31ce77f324e7826e24878218..37e79829f102084e0b2827659b4e743313179ef5 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -1,4 +1,4 @@
-/*
+ /*
 Minetest-c55
 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
@@ -630,6 +630,18 @@ void content_mapnode_init()
 	f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
 	setStoneLikeDiggingProperties(f->digging_properties, 3.0);
 	
+	i = CONTENT_APPLE;
+	f = &content_features(i);
+	f->setInventoryTexture("apple.png");
+	f->param_type = CPT_LIGHT;
+	f->light_propagates = true;
+	f->sunlight_propagates = true;
+	f->solidness = 0; // drawn separately, makes no faces
+	f->walkable = false;
+	f->air_equivalent = true;
+	f->dug_item = std::string("CraftItem apple 1");
+	f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
+	
 	// NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
 	
 
diff --git a/src/content_mapnode.h b/src/content_mapnode.h
index 1f6292ba478db84db98fe0500a86a79c4b184b4f..639f572eb54f93a46fcd1c364390198d45ef6ca7 100644
--- a/src/content_mapnode.h
+++ b/src/content_mapnode.h
@@ -1,4 +1,4 @@
-/*
+ /*
 Minetest-c55
 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
@@ -83,6 +83,8 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
 #define CONTENT_JUNGLEGRASS 0x816
 #define CONTENT_NC 0x817
 #define CONTENT_NC_RB 0x818
+#define CONTENT_APPLE 0x819
+
 
 #endif
 
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index 0018b9919355a065cef2ca5270a96bbc3d075eee..6ac99aabdb17de9db7805c271bed6caf8cbc0867 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -1,4 +1,4 @@
-/*
+ /*
 Minetest-c55
 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
@@ -84,6 +84,11 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
 {
 	MapNode treenode(CONTENT_TREE);
 	MapNode leavesnode(CONTENT_LEAVES);
+	MapNode applenode(CONTENT_APPLE);
+	
+	bool is_apple_tree = myrand_range(0,100) < 35?true:false;
+	s16 apple_count = 0;
+	
 
 	s16 trunk_h = myrand_range(4, 5);
 	v3s16 p1 = p0;
@@ -138,6 +143,7 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
 	for(s16 y=leaves_a.MinEdge.Y; y<=leaves_a.MaxEdge.Y; y++)
 	for(s16 x=leaves_a.MinEdge.X; x<=leaves_a.MaxEdge.X; x++)
 	{
+		bool is_apple = myrand_range(0,100) < 50?true:false;
 		v3s16 p(x,y,z);
 		p += p1;
 		if(vmanip.m_area.contains(p) == false)
@@ -147,8 +153,14 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
 				&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
 			continue;
 		u32 i = leaves_a.index(x,y,z);
-		if(leaves_d[i] == 1)
-			vmanip.m_data[vi] = leavesnode;
+		if(leaves_d[i] == 1) {
+			if(is_apple_tree && is_apple && apple_count < 4) {
+				vmanip.m_data[vi] = applenode;
+				apple_count++;
+			} else {
+				vmanip.m_data[vi] = leavesnode;
+			}
+		}
 	}
 }