diff --git a/game_api.txt b/game_api.txt
index 27d5b33979d596551513d0cac932f39adfdcd0ab..47df8e7fc352fbc6a9d191d9afda43821bc18afe 100644
--- a/game_api.txt
+++ b/game_api.txt
@@ -927,10 +927,13 @@ Trees
 
  * `default.grow_acacia_bush(pos)`
   * Grows an acaia bush at pos
-  
+
  * `default.grow_pine_bush(pos)`
   * Grows a pine bush at pos
 
+ * `default.grow_blueberry_bush(pos)`
+  * Grows a blueberry bush at pos
+
 
 Carts
 -----
diff --git a/mods/default/README.txt b/mods/default/README.txt
index 474ef0ecd490fdecb96d90916aafc982550eb9aa..3d33e31cf1351b46d98b7f7c302b0becf4aae4da 100644
--- a/mods/default/README.txt
+++ b/mods/default/README.txt
@@ -230,6 +230,10 @@ Mossmanikin (CC BY-SA 3.0):
   default_fern_*.png
 
 random-geek (CC BY-SA 3.0):
+  default_blueberries.png
+  default_blueberry_overlay.png
+  default_blueberry_bush_leaves.png, derived from default_bush_leaves (by paramat)
+  default_blueberry_bush_sapling.png
   default_dirt.png -- Derived from a texture by Neuromancer (CC BY-SA 3.0)
 
 
@@ -359,3 +363,6 @@ sofar (CC BY-SA 3.0):
 
 TumeniNodes (CC BY-SA 3.0):
   pine_bush.mts
+
+random-geek (CC BY-SA 3.0):
+  blueberry_bush.mts
diff --git a/mods/default/craftitems.lua b/mods/default/craftitems.lua
index 6c07934970e609053cf234b96444d65f4f46a4e3..3e3852ce2b0f96c5a7cf55f62d959b3aca093a1e 100644
--- a/mods/default/craftitems.lua
+++ b/mods/default/craftitems.lua
@@ -341,3 +341,9 @@ minetest.register_craftitem("default:flint", {
 	description = "Flint",
 	inventory_image = "default_flint.png"
 })
+
+minetest.register_craftitem("default:blueberries", {
+	description = "Blueberries",
+	inventory_image = "default_blueberries.png",
+	on_use = minetest.item_eat(2),
+})
diff --git a/mods/default/mapgen.lua b/mods/default/mapgen.lua
index 7e1cf7df42cb547b25aff574be148e5f8a953962..d53467d334db19c095aba11e86ccb9020e090e41 100644
--- a/mods/default/mapgen.lua
+++ b/mods/default/mapgen.lua
@@ -1964,6 +1964,29 @@ function default.register_decorations()
 		flags = "place_center_x, place_center_z",
 	})
 
+	-- Blueberry bush
+
+	minetest.register_decoration({
+		name = "default:blueberry_bush",
+		deco_type = "schematic",
+		place_on = {"default:dirt_with_grass", "default:dirt_with_snow"},
+		sidelen = 16,
+		noise_params = {
+			offset = -0.004,
+			scale = 0.01,
+			spread = {x = 100, y = 100, z = 100},
+			seed = 697,
+			octaves = 3,
+			persist = 0.7,
+		},
+		biomes = {"grassland", "snowy_grassland"},
+		y_max = 31000,
+		y_min = 1,
+		place_offset_y = 1,
+		schematic = minetest.get_modpath("default") .. "/schematics/blueberry_bush.mts",
+		flags = "place_center_x, place_center_z",
+	})
+
 	-- Acacia bush
 
 	minetest.register_decoration({
diff --git a/mods/default/nodes.lua b/mods/default/nodes.lua
index 9aa3606f27514ff4e85de934b69cba6258608ea7..c8020127f5b1d9fc67175ba1137fb533d61f0fab 100644
--- a/mods/default/nodes.lua
+++ b/mods/default/nodes.lua
@@ -165,6 +165,9 @@ default:acacia_bush_sapling
 default:pine_bush_stem
 default:pine_bush_needles
 default:pine_bush_sapling
+default:blueberry_bush_leaves_with_berries
+default:blueberry_bush_leaves
+default:blueberry_bush_sapling
 
 default:sand_with_kelp
 
@@ -1614,6 +1617,85 @@ minetest.register_node("default:bush_sapling", {
 	end,
 })
 
+minetest.register_node("default:blueberry_bush_leaves_with_berries", {
+	description = "Blueberry Bush Leaves with Berries",
+	drawtype = "allfaces_optional",
+	waving = 1,
+	tiles = {"default_blueberry_bush_leaves.png^default_blueberry_overlay.png"},
+	paramtype = "light",
+	groups = {snappy = 3, flammable = 2, leaves = 1, dig_immediate = 3},
+	drop = "default:blueberries",
+	sounds = default.node_sound_leaves_defaults(),
+	node_dig_prediction = "default:blueberry_bush_leaves",
+
+	after_dig_node = function(pos, oldnode, oldmetadata, digger)
+		minetest.set_node(pos, {name = "default:blueberry_bush_leaves"})
+		minetest.get_node_timer(pos):start(math.random(300, 1500))
+	end,
+})
+
+minetest.register_node("default:blueberry_bush_leaves", {
+	description = "Blueberry Bush Leaves",
+	drawtype = "allfaces_optional",
+	waving = 1,
+	tiles = {"default_blueberry_bush_leaves.png"},
+	paramtype = "light",
+	groups = {snappy = 3, flammable = 2, leaves = 1},
+	drop = {
+		max_items = 1,
+		items = {
+			{items = {"default:blueberry_bush_sapling"}, rarity = 5},
+			{items = {"default:blueberry_bush_leaves"}}
+		}
+	},
+	sounds = default.node_sound_leaves_defaults(),
+
+	on_timer = function(pos, elapsed)
+		if minetest.get_node_light(pos) < 11 then
+			minetest.get_node_timer(pos):start(200)
+		else
+			minetest.set_node(pos, {name = "default:blueberry_bush_leaves_with_berries"})
+		end
+	end,
+
+	after_place_node = default.after_place_leaves,
+})
+
+minetest.register_node("default:blueberry_bush_sapling", {
+	description = "Blueberry Bush Sapling",
+	drawtype = "plantlike",
+	tiles = {"default_blueberry_bush_sapling.png"},
+	inventory_image = "default_blueberry_bush_sapling.png",
+	wield_image = "default_blueberry_bush_sapling.png",
+	paramtype = "light",
+	sunlight_propagates = true,
+	walkable = false,
+	on_timer = default.grow_sapling,
+	selection_box = {
+		type = "fixed",
+		fixed = {-4 / 16, -0.5, -4 / 16, 4 / 16, 2 / 16, 4 / 16}
+	},
+	groups = {snappy = 2, dig_immediate = 3, flammable = 2,
+		attached_node = 1, sapling = 1},
+	sounds = default.node_sound_leaves_defaults(),
+
+	on_construct = function(pos)
+		minetest.get_node_timer(pos):start(math.random(300, 1500))
+	end,
+
+	on_place = function(itemstack, placer, pointed_thing)
+		itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
+			"default:blueberry_bush_sapling",
+			-- minp, maxp to be checked, relative to sapling pos
+			{x = -1, y = 0, z = -1},
+			{x = 1, y = 1, z = 1},
+			-- maximum interval of interior volume check
+			2)
+
+		return itemstack
+	end,
+})
+
 minetest.register_node("default:acacia_bush_stem", {
 	description = "Acacia Bush Stem",
 	drawtype = "plantlike",
diff --git a/mods/default/schematics/blueberry_bush.mts b/mods/default/schematics/blueberry_bush.mts
new file mode 100644
index 0000000000000000000000000000000000000000..cf4d8ef84af1d3cec7e274013bf59dc56173cf6f
Binary files /dev/null and b/mods/default/schematics/blueberry_bush.mts differ
diff --git a/mods/default/textures/default_blueberries.png b/mods/default/textures/default_blueberries.png
new file mode 100644
index 0000000000000000000000000000000000000000..1dbb0d64fd3a6eb38944c124c3ce257bb23559bb
Binary files /dev/null and b/mods/default/textures/default_blueberries.png differ
diff --git a/mods/default/textures/default_blueberry_bush_leaves.png b/mods/default/textures/default_blueberry_bush_leaves.png
new file mode 100644
index 0000000000000000000000000000000000000000..2cd112c8c3a8792bb5d63652bd723b21e414229b
Binary files /dev/null and b/mods/default/textures/default_blueberry_bush_leaves.png differ
diff --git a/mods/default/textures/default_blueberry_bush_sapling.png b/mods/default/textures/default_blueberry_bush_sapling.png
new file mode 100644
index 0000000000000000000000000000000000000000..5d7393f7b2a69abe041cd7912df8ae681058674b
Binary files /dev/null and b/mods/default/textures/default_blueberry_bush_sapling.png differ
diff --git a/mods/default/textures/default_blueberry_overlay.png b/mods/default/textures/default_blueberry_overlay.png
new file mode 100644
index 0000000000000000000000000000000000000000..de9de623497f7a0488c1e278d5e7913182451baa
Binary files /dev/null and b/mods/default/textures/default_blueberry_overlay.png differ
diff --git a/mods/default/trees.lua b/mods/default/trees.lua
index dc18ea41945047a6450d0743dd6f7ddb3080f1a6..c9eabaa83ec44759b7240009fd6f30e0b70abdc1 100644
--- a/mods/default/trees.lua
+++ b/mods/default/trees.lua
@@ -81,6 +81,10 @@ function default.grow_sapling(pos)
 		minetest.log("action", "A bush sapling grows into a bush at "..
 			minetest.pos_to_string(pos))
 		default.grow_bush(pos)
+	elseif node.name == "default:blueberry_bush_sapling" then
+		minetest.log("action", "A blueberry bush sapling grows into a bush at "..
+			minetest.pos_to_string(pos))
+		default.grow_blueberry_bush(pos)
 	elseif node.name == "default:acacia_bush_sapling" then
 		minetest.log("action", "An acacia bush sapling grows into a bush at "..
 			minetest.pos_to_string(pos))
@@ -476,6 +480,15 @@ function default.grow_bush(pos)
 		path, "0", nil, false)
 end
 
+-- Blueberry bush
+
+function default.grow_blueberry_bush(pos)
+	local path = minetest.get_modpath("default") ..
+		"/schematics/blueberry_bush.mts"
+	minetest.place_schematic({x = pos.x - 1, y = pos.y, z = pos.z - 1},
+		path, "0", nil, false)
+end
+
 
 -- Acacia bush
 
diff --git a/mods/dye/init.lua b/mods/dye/init.lua
index f094dd2ff77478f01b4952fd41221dea3870dc5e..c25981115c269e62ed30ed4a4381bd6f88e7476e 100644
--- a/mods/dye/init.lua
+++ b/mods/dye/init.lua
@@ -49,6 +49,14 @@ minetest.register_craft({
 	recipe = {"group:coal"},
 })
 
+-- Manually add blueberries->violet dye
+
+minetest.register_craft({
+	type = "shapeless",
+	output = "dye:violet 2",
+	recipe = {"default:blueberries"},
+})
+
 -- Mix recipes
 
 local dye_recipes = {
diff --git a/schematic_tables.txt b/schematic_tables.txt
index ee25b8228e918cc56c47fe3e7bd56e9d28895be4..261dcf198f32b7d591d0d0ec8ddc6d58aeef8015 100644
--- a/schematic_tables.txt
+++ b/schematic_tables.txt
@@ -9,7 +9,7 @@ The following tables are for pasting into mods that contain a function to
 convert the Lua tables into .mts files. Such mods often have two functions to
 process two formats of the 'data' table:
 
-The standard table format is described in the 'Schematic specifier' section of 
+The standard table format is described in the 'Schematic specifier' section of
 the lua_api.txt file in the Minetest Engine.
 The 'data' table appears as a sequence of vertical slices through the structure
 the schematic describes.
@@ -2146,6 +2146,24 @@ mts_save("bush", {
 })
 
 
+-- Blueberry bush
+
+local L = {name = "default:blueberry_bush_leaves_with_berries", prob = 255, force_place = true}
+local M = {name = "default:blueberry_bush_leaves_with_berries", prob = 223}
+local N = {name = "default:blueberry_bush_leaves_with_berries", prob = 95}
+
+mts_save("blueberry_bush", {
+	size = {x = 3, y = 1, z = 3},
+	data = {
+		N, M, N,
+
+		M, L, M,
+
+		N, M, N,
+	},
+})
+
+
 -- Acacia bush
 
 local L = {name = "default:acacia_bush_leaves", prob = 255}