diff --git a/mods/ITEMS/mcl_ocean/kelp.lua b/mods/ITEMS/mcl_ocean/kelp.lua
index fca53cc48..63bb921c2 100644
--- a/mods/ITEMS/mcl_ocean/kelp.lua
+++ b/mods/ITEMS/mcl_ocean/kelp.lua
@@ -18,10 +18,10 @@ local mt_registered_items = minetest.registered_items
 local mt_registered_nodes = minetest.registered_nodes
 
 -- functions
-local mt_log = minetest.log
 local mt_add_item = minetest.add_item
 local mt_get_item_group = minetest.get_item_group
 local mt_get_node = minetest.get_node
+local mcl_get_node_name = mcl_vars.get_node_name
 local mt_get_node_level = minetest.get_node_level
 local mt_get_node_max_level = minetest.get_node_max_level
 local mt_get_node_or_nil = minetest.get_node_or_nil
@@ -35,13 +35,9 @@ local mt_record_protection_violation = minetest.record_protection_violation
 local mt_is_creative_enabled = minetest.is_creative_enabled
 local mt_sound_play = minetest.sound_play
 
-local math = math
---local string = string
-local table = table
-
--- DEBUG: functions
--- local log = minetest.log
--- local chatlog = minetest.chat_send_all
+local min = math.min
+local random = math.random
+local rshift, band = bit.rshift, bit.band
 
 --------------------------------------------------------------------------------
 -- Kelp API
@@ -54,6 +50,10 @@ mcl_ocean.kelp = kelp
 kelp.MIN_AGE = 0
 kelp.MAX_AGE = 25
 
+-- Named constant for maximum height the engine allows kelp to grow
+local MAX_HEIGHT = 16
+kelp.MAX_HEIGHT = MAX_HEIGHT
+
 kelp.TICK = 0.2 -- Tick interval (in seconds) for updating kelp.
 
 -- The average amount of growth for kelp in a day is 2.16 (https://youtu.be/5Bp4lAjAk3I)
@@ -82,26 +82,23 @@ end
 -- Returns the liquidtype, if indeed water.
 function kelp.is_submerged(node)
 	local g = mt_get_item_group(node.name, "water")
-	if g > 0 and g <= 3  then
-		-- Expected only "source" and "flowing" from water liquids
-		return mt_registered_nodes[node.name].liquidtype
-	end
-	return false
+	-- Expected only "source" and "flowing" from water liquids
+	return g > 0 and g <= 3 and mt_registered_nodes[node.name].liquidtype
 end
 
 
 -- Is the water downward flowing?
 -- (kelp can grow/be placed inside downward flowing water)
-function kelp.is_downward_flowing(pos, node, pos_above, node_above, __is_above__)
+function kelp.is_downward_flowing(pos, node, pos_above, node_above, is_above)
 	-- Function params: (pos[, node]) or (node, pos_above) or (node, node_above)
 	local node = node or mt_get_node(pos)
 
-	local result = (math.floor(node.param2 / 8) % 2) == 1
-	if not (result or __is_above__) then
+	local result = band(rshift(node.param2, 3), 1) == 1
+	if not result and not is_above then
 		-- If not, also check node above.
 		-- (this is needed due a weird quirk in the definition of "downwards flowing"
 		-- liquids in Luanti)
-		local pos_above = pos_above or {x=pos.x,y=pos.y+1,z=pos.z}
+		local pos_above = pos_above or vector.offset(pos, 0, 1, 0)
 		local node_above = node_above or mt_get_node(pos_above)
 		result = kelp.is_submerged(node_above)
 			or kelp.is_downward_flowing(nil, node_above, nil, nil, true)
@@ -124,7 +121,7 @@ function kelp.is_falling(pos, node, is_falling, pos_bottom, node_bottom, def_bot
 		return false
 	end
 
-	local pos_bottom = pos_bottom or {x = pos.x, y = pos.y - 1, z = pos.z}
+	local pos_bottom = pos_bottom or vector.offset(pos, 0, -1, 0)
 	-- get_node_or_nil: Only fall if node below is loaded
 	local node_bottom = node_bottom or mt_get_node_or_nil(pos_bottom)
 	local nodename_bottom = node_bottom.name
@@ -153,18 +150,10 @@ function kelp.is_falling(pos, node, is_falling, pos_bottom, node_bottom, def_bot
 end
 
 
--- Roll whether to grow kelp or not.
-function kelp.roll_growth(numerator, denominator)
-	-- Optional params: numerator, denominator
-	--return math.random(denominator or kelp.ROLL_GROWTH_DENOMINATOR) <= (numerator or kelp.ROLL_GROWTH_NUMERATOR)
-	return true -- probability done by ABM
-end
-
-
 -- Roll initial age for kelp.
 function kelp.roll_init_age(min, max)
 	-- Optional params
-	return math.random(min or kelp.MIN_AGE, (max or kelp.MAX_AGE)-1)
+	return random(min or kelp.MIN_AGE, (max or kelp.MAX_AGE)-1)
 end
 
 
@@ -172,7 +161,7 @@ end
 -- For the special case where the max param2 is reached, interpret that as the
 -- 16th kelp stem.
 function kelp.get_height(param2)
-	return math.floor(param2 / 16) + math.floor(param2 % 16 / 8)
+	return rshift(param2, 4) + band(rshift(param2, 3), 1)
 end
 
 
@@ -180,7 +169,7 @@ end
 function kelp.get_tip(pos, height)
 	-- Optional params: height
 	local height = height or kelp.get_height(mt_get_node(pos).param2)
-	local pos_tip = {x=pos.x, y=pos.y+height+1, z=pos.z}
+	local pos_tip = vector.offset(pos, 0, height + 1, 0)
 	return pos_tip, mt_get_node(pos_tip), height
 end
 
@@ -189,12 +178,11 @@ end
 function kelp.find_unsubmerged(pos, node, height)
 	-- Optional params: node, height
 	local node = node or mt_get_node(pos)
-	local height = height or ((node.param2 >= 0 and node.param2 < 16) and 1) or kelp.get_height(node.param2)
+	local height = height or (node.param2 < 16 and 1) or kelp.get_height(node.param2)
 
-	local walk_pos = {x=pos.x, z=pos.z}
-	local y = pos.y
+	local walk_pos = vector.copy(pos)
 	for i=1,height do
-		walk_pos.y = y + i
+		walk_pos.y = pos.y + i
 		local walk_node = mt_get_node(walk_pos)
 		if walk_node.name ~= "ignore" and not kelp.is_submerged(walk_node) then
 			return walk_pos, walk_node, height, i
@@ -207,43 +195,30 @@ end
 -- Obtain next param2.
 function kelp.next_param2(param2)
 	-- param2 max value is 255, so adding to 256 causes overflow.
-	return math.min(param2+16 - param2 % 16, 255);
+	return min(param2 + 16 - band(param2, 0xF), 255);
 end
 
-local function store_age (pos, age)
+local function store_age(pos, age)
 	if pos then
 		--minetest.log("age: ".. tostring(age) .. ", pos: ".. mt_pos_to_string(pos))
 		mt_get_meta(pos):set_int("mcl_ocean:kelp_age", age)
 	end
 end
 
-local function retrieve_age (pos)
+local function retrieve_age(pos)
 	local meta = mt_get_meta(pos)
 	local age_set = meta:contains("mcl_ocean:kelp_age")
-	if not age_set then
-		return nil
-	end
-
-	local age = meta:get_int("mcl_ocean:kelp_age")
-	--minetest.log("age: " .. tostring(age))
-	return age
+	return age_set and meta:get_int("mcl_ocean:kelp_age") or nil
 end
 
 -- Initialise a kelp's age.
 function kelp.init_age(pos)
-	-- Watched params: pos
-	-- Optional params: age, from_lbm
-
 	local age = retrieve_age(pos)
-
 	if not age then
 		age = kelp.roll_init_age()
 		--minetest.log("no kelp age set so init with: " .. tostring(new_age))
 		store_age(pos, age)
-	else
-		--minetest.log("stored_age: " .. tostring(age))
 	end
-
 	return age
 end
 
@@ -305,10 +280,9 @@ end
 function kelp.detach_drop(pos, height)
 	-- Optional params: height
 	local height = height or kelp.get_height(mt_get_node(pos).param2)
-	local y = pos.y
-	local walk_pos = {x=pos.x, z=pos.z}
+	local walk_pos = vector.copy(pos)
 	for i=1,height do
-		walk_pos.y = y+i
+		walk_pos.y = pos.y + i
 		mt_add_item(walk_pos, "mcl_ocean:kelp")
 	end
 	return true
@@ -334,8 +308,7 @@ function kelp.detach_dig(dig_pos, pos, drop, node, height)
 		end
 		mt_set_node(pos, {
 			name=mt_registered_nodes[node.name].node_dig_prediction,
-			param=node.param,
-			param2=0 })
+			param=node.param, param2=0 })
 
 	-- Digs the kelp beginning at a height.
 	else
@@ -372,6 +345,27 @@ local function detach_unsubmerged(pos)
 	end
 end
 
+function kelp.remove_kelp_below_structure(minp, maxp)
+	local minp = vector.offset(minp, 0, -MAX_HEIGHT - 1, 0)
+	local kelp_pos_list,_ = core.find_nodes_in_area(minp, maxp, {"group:kelp"})
+
+	for _,kelp_pos in ipairs(kelp_pos_list) do
+		local kelp_node = core.get_node(kelp_pos)
+
+		-- Convert kelp back to normal node
+		local dig_pos,_,_,new_height = kelp.find_unsubmerged(kelp_pos, kelp_node)
+		if dig_pos then
+			new_height = new_height - 1
+			if new_height <= 0 then
+				kelp_node.name = core.registered_nodes[kelp_node.name].node_dig_prediction
+			else
+				kelp_node.param2 = 16 * new_height
+			end
+			core.swap_node(kelp_pos, kelp_node)
+		end
+	end
+end
+
 local function grow_kelp (pos)
 	local node = mt_get_node(pos)
 	local age = retrieve_age(pos)
@@ -384,13 +378,10 @@ local function grow_kelp (pos)
 	if kelp.is_age_growable(age) then
 		--minetest.log("age growable: ".. tostring(age) .. ", pos: ".. mt_pos_to_string(pos))
 		kelp.next_grow(age+1, pos, node)
-	else
-		--minetest.log("age not: ".. tostring(age) .. ", pos: ".. mt_pos_to_string(pos))
 	end
 end
 
 function kelp.surface_on_construct(pos)
-	--minetest.log("on construct kelp called")
 	kelp.init_age(pos)
 end
 
@@ -435,7 +426,7 @@ function kelp.kelp_on_place(itemstack, placer, pointed_thing)
 	-- Protection
 	if mt_is_protected(pos_under, player_name) or
 			mt_is_protected(pos_above, player_name) then
-		mt_log("action", player_name
+		minetest.log("action", player_name
 			.. " tried to place " .. itemstack:get_name()
 			.. " at protected position "
 			.. mt_pos_to_string(pos_under))
diff --git a/mods/MAPGEN/mcl_biomes/init.lua b/mods/MAPGEN/mcl_biomes/init.lua
index bb238f551..df1a46e2b 100644
--- a/mods/MAPGEN/mcl_biomes/init.lua
+++ b/mods/MAPGEN/mcl_biomes/init.lua
@@ -3458,6 +3458,14 @@ local corals = {
 	"fire"
 }
 
+local function clear_kelp(t, minp, maxp, blockseed)
+	for _,pos in pairs(t) do
+		local pos_minp = vector.offset(pos, -8, -4, -8)
+		local pos_maxp = vector.offset(pos,  8,  2,  8)
+		mcl_ocean.kelp.remove_kelp_below_structure(pos_minp, pos_maxp)
+	end
+end
+
 local function register_coral_decos(ck)
 	local c = corals[ck]
 	local noise = {
@@ -3471,6 +3479,7 @@ local function register_coral_decos(ck)
 		flags = "absvalue"
 	}
 	mcl_mapgen_core.register_decoration({
+		name = "coral_deco_"..c.."_s1",
 		deco_type = "schematic",
 		place_on = {"group:sand", "mcl_core:gravel", "mcl_mud:mud"},
 		sidelen = 80,
@@ -3481,8 +3490,10 @@ local function register_coral_decos(ck)
 		schematic = mod_mcl_structures .. "/schematics/mcl_structures_coral_" .. c .. "_1.mts",
 		rotation = "random",
 		flags = "all_floors,force_placement",
+		gen_callback = clear_kelp,
 	})
 	mcl_mapgen_core.register_decoration({
+		name = "coral_deco_"..c.."_s2",
 		deco_type = "schematic",
 		place_on = {"group:sand", "mcl_core:gravel", "mcl_mud:mud"},
 		noise_params = noise,
@@ -3493,9 +3504,11 @@ local function register_coral_decos(ck)
 		schematic = mod_mcl_structures .. "/schematics/mcl_structures_coral_" .. c .. "_2.mts",
 		rotation = "random",
 		flags = "all_floors,force_placement",
+		gen_callback = clear_kelp,
 	})
 
 	mcl_mapgen_core.register_decoration({
+		name = "coral_deco_"..c.."_block",
 		deco_type = "simple",
 		place_on = {"mcl_ocean:" .. c .. "_coral_block"},
 		sidelen = 16,
@@ -3509,8 +3522,9 @@ local function register_coral_decos(ck)
 		height_max = 1,
 	})
 	mcl_mapgen_core.register_decoration({
+		name = "coral_deco_"..c.."_fan",
 		deco_type = "simple",
-		place_on = {"mcl_ocean:horn_coral_block"},
+		place_on = {"mcl_ocean:"..c.."_coral_block"},
 		sidelen = 16,
 		fill_ratio = 7,
 		y_min = coral_min,
@@ -3553,6 +3567,7 @@ local function register_decorations()
 		register_coral_decos(k)
 	end
 	mcl_mapgen_core.register_decoration({
+		name = "coral_dead_brain",
 		deco_type = "simple",
 		place_on = {"group:sand", "mcl_core:gravel", "mcl_mud:mud"},
 		sidelen = 16,
@@ -3577,6 +3592,7 @@ local function register_decorations()
 	})
 
 	mcl_mapgen_core.register_decoration({
+		name = "coral_pickled_dead_brain_1",
 		deco_type = "simple",
 		place_on = {"mcl_ocean:dead_brain_coral_block"},
 		sidelen = 16,
@@ -3591,6 +3607,7 @@ local function register_decorations()
 		place_offset_y = -1,
 	})
 	mcl_mapgen_core.register_decoration({
+		name = "coral_pickled_dead_brain_2",
 		deco_type = "simple",
 		place_on = {"mcl_ocean:dead_brain_coral_block"},
 		sidelen = 16,
@@ -3605,6 +3622,7 @@ local function register_decorations()
 		place_offset_y = -1,
 	})
 	mcl_mapgen_core.register_decoration({
+		name = "coral_pickled_dead_brain_3",
 		deco_type = "simple",
 		place_on = {"mcl_ocean:dead_brain_coral_block"},
 		sidelen = 16,
@@ -3619,6 +3637,7 @@ local function register_decorations()
 		place_offset_y = -1,
 	})
 	mcl_mapgen_core.register_decoration({
+		name = "coral_pickled_dead_brain_4",
 		deco_type = "simple",
 		place_on = {"mcl_ocean:dead_brain_coral_block"},
 		sidelen = 16,
@@ -3634,6 +3653,7 @@ local function register_decorations()
 	})
 	--rare CORAl
 	mcl_mapgen_core.register_decoration({
+		name = "coral_cora",
 		deco_type = "schematic",
 		place_on = {"group:sand", "mcl_core:gravel"},
 		fill_ratio = 0.0001,
@@ -3644,6 +3664,7 @@ local function register_decorations()
 		schematic = mod_mcl_structures .. "/schematics/coral_cora.mts",
 		rotation = "random",
 		flags = "place_center_x,place_center_z, force_placement",
+		gen_callback = clear_kelp,
 	})
 
 	mcl_mapgen_core.register_decoration({
diff --git a/mods/MAPGEN/mcl_structures/mod.conf b/mods/MAPGEN/mcl_structures/mod.conf
index 823714aad..8e5d50ad9 100644
--- a/mods/MAPGEN/mcl_structures/mod.conf
+++ b/mods/MAPGEN/mcl_structures/mod.conf
@@ -1,4 +1,4 @@
 name = mcl_structures
 author = Wuzzy, cora
 description = Structure placement for MCL2
-depends = mcl_init, mcl_loot
+depends = mcl_init, mcl_loot, mcl_ocean
diff --git a/mods/MAPGEN/mcl_structures/ocean_ruins.lua b/mods/MAPGEN/mcl_structures/ocean_ruins.lua
index 0b609aee7..88027aaf6 100644
--- a/mods/MAPGEN/mcl_structures/ocean_ruins.lua
+++ b/mods/MAPGEN/mcl_structures/ocean_ruins.lua
@@ -117,6 +117,11 @@ local cold = {
 			}
 		}
 	},
+	after_place = function(pos)
+		local minp = vector.offset(pos, -10, -4, -10)
+		local maxp = vector.offset(pos,  10,  2,  10)
+		mcl_ocean.kelp.remove_kelp_below_structure(minp, maxp)
+	end,
 }
 
 local warm = table.copy(cold)
diff --git a/mods/MAPGEN/mcl_structures/shipwrecks.lua b/mods/MAPGEN/mcl_structures/shipwrecks.lua
index 73e8af8c4..b45ac2927 100644
--- a/mods/MAPGEN/mcl_structures/shipwrecks.lua
+++ b/mods/MAPGEN/mcl_structures/shipwrecks.lua
@@ -171,7 +171,12 @@ mcl_structures.register_structure("shipwreck",{
 				}
 			},
 		}
-	}
+	},
+	after_place = function(pos)
+		local minp = vector.offset(pos, -20, -8, -20)
+		local maxp = vector.offset(pos,  20,  2,  20)
+		mcl_ocean.kelp.remove_kelp_below_structure(minp, maxp)
+	end,
 })
 
 local spawnon = { "mcl_stairs:slab_prismarine_dark"}
@@ -205,6 +210,10 @@ mcl_structures.register_structure("ocean_temple",{
 		mcl_structures.spawn_mobs("mobs_mc:guardian",spawnon,p1,p2,pr,5,true)
 		mcl_structures.spawn_mobs("mobs_mc:guardian_elder",spawnon,p1,p2,pr,1,true)
 		mcl_structures.construct_nodes(p1,p2,{"group:wall"})
+
+		local minp = vector.offset(p, -20, -4, -20)
+		local maxp = vector.offset(p,  20,  4,  20)
+		mcl_ocean.kelp.remove_kelp_below_structure(minp, maxp)
 	end,
 	loot = {
 		["mcl_chests:chest_small"] = {