diff --git a/builtin/game/item_entity.lua b/builtin/game/item_entity.lua
index d6781feca5f672828b1c4272f4546e0d80db6dce..d848fd8551a1884237518317f5bc9a671d0bc387 100644
--- a/builtin/game/item_entity.lua
+++ b/builtin/game/item_entity.lua
@@ -96,6 +96,56 @@ core.register_entity(":__builtin:item", {
 		self:set_item(self.itemstring)
 	end,
 
+	try_merge_with = function(self, own_stack, object, obj)
+		local stack = ItemStack(obj.itemstring)
+		if own_stack:get_name() == stack:get_name() and stack:get_free_space() > 0 then
+			local overflow = false
+			local count = stack:get_count() + own_stack:get_count()
+			local max_count = stack:get_stack_max()
+			if count > max_count then
+				overflow = true
+				count = count - max_count
+			else
+				self.itemstring = ''
+			end
+			local pos = object:getpos()
+			pos.y = pos.y + (count - stack:get_count()) / max_count * 0.15
+			object:moveto(pos, false)
+			local s, c
+			local max_count = stack:get_stack_max()
+			local name = stack:get_name()
+			if not overflow then
+				obj.itemstring = name .. " " .. count
+				s = 0.2 + 0.1 * (count / max_count)
+				c = s
+				object:set_properties({
+					visual_size = {x = s, y = s},
+					collisionbox = {-c, -c, -c, c, c, c}
+				})
+				self.object:remove()
+				-- merging succeeded
+				return true
+			else
+				s = 0.4
+				c = 0.3
+				object:set_properties({
+					visual_size = {x = s, y = s},
+					collisionbox = {-c, -c, -c, c, c, c}
+				})
+				obj.itemstring = name .. " " .. max_count
+				s = 0.2 + 0.1 * (count / max_count)
+				c = s
+				self.object:set_properties({
+					visual_size = {x = s, y = s},
+					collisionbox = {-c, -c, -c, c, c, c}
+				})
+				self.itemstring = name .. " " .. count
+			end
+		end
+		-- merging didn't succeed
+		return false
+	end,
+
 	on_step = function(self, dtime)
 		self.age = self.age + dtime
 		if time_to_live > 0 and self.age > time_to_live then
@@ -111,52 +161,13 @@ core.register_entity(":__builtin:item", {
 		if not core.registered_nodes[nn] or core.registered_nodes[nn].walkable and v.y == 0 then
 			if self.physical_state then
 				local own_stack = ItemStack(self.object:get_luaentity().itemstring)
-				for _,object in ipairs(core.get_objects_inside_radius(p, 0.8)) do
+				-- Merge with close entities of the same item
+				for _, object in ipairs(core.get_objects_inside_radius(p, 0.8)) do
 					local obj = object:get_luaentity()
-					if obj and obj.name == "__builtin:item" and obj.physical_state == false then
-						local stack = ItemStack(obj.itemstring)
-						if own_stack:get_name() == stack:get_name() and stack:get_free_space() > 0 then 
-							local overflow = false
-							local count = stack:get_count() + own_stack:get_count()
-							local max_count = stack:get_stack_max()
-							if count>max_count then
-								overflow = true
-								count = count - max_count
-							else
-								self.itemstring = ''
-							end	
-							local pos=object:getpos() 
-							pos.y = pos.y + (count - stack:get_count()) / max_count * 0.15
-							object:moveto(pos, false)
-							local s, c
-							local max_count = stack:get_stack_max()
-							local name = stack:get_name()
-							if not overflow then
-								obj.itemstring = name.." "..count
-								s = 0.2 + 0.1 * (count / max_count)
-								c = s
-								object:set_properties({
-									visual_size = {x = s, y = s},
-									collisionbox = {-c, -c, -c, c, c, c}
-								})
-								self.object:remove()
-								return
-							else
-								s = 0.4
-								c = 0.3
-								object:set_properties({
-									visual_size = {x = s, y = s},
-									collisionbox = {-c, -c, -c, c, c, c}
-								})
-								obj.itemstring = name.." "..max_count
-								s = 0.2 + 0.1 * (count / max_count)
-								c = s
-								self.object:set_properties({
-									visual_size = {x = s, y = s},
-									collisionbox = {-c, -c, -c, c, c, c}
-								})
-								self.itemstring = name.." "..count
-							end
+					if obj and obj.name == "__builtin:item"
+							and obj.physical_state == false then
+						if self:try_merge_with(own_stack, object, obj) then
+							return
 						end
 					end
 				end