From 64d760df017c0110b9048a38e6562ac6e6f8abfe Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 25 Jan 2022 20:32:14 +0400 Subject: [PATCH 01/22] #138 Skip nil index in mcl_shields --- mods/ITEMS/mcl_shields/init.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index dddaf24e5..9eebd3e80 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -173,9 +173,10 @@ local function set_shield(player, block, i) end end local shield = mcl_shields.players[player].shields[i] - if shield then - shield:get_luaentity()._blocking = block - end + if not shield then return end + local luaentity = shield:get_luaentity() + if not luaentity then return end + luaentity._blocking = block end local function set_interact(player, interact) From 39f6500061929efacf995e3e35abf40c27621f07 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 26 Jan 2022 03:07:01 +0400 Subject: [PATCH 02/22] Fix a typo --- mods/ITEMS/mcl_bows/crossbow.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_bows/crossbow.lua b/mods/ITEMS/mcl_bows/crossbow.lua index 3c92a4c92..49a434c5b 100644 --- a/mods/ITEMS/mcl_bows/crossbow.lua +++ b/mods/ITEMS/mcl_bows/crossbow.lua @@ -116,7 +116,7 @@ end -- Bow item, uncharged state minetest.register_tool("mcl_bows:crossbow", { - description = S("Corssbow"), + description = S("Crossbow"), _tt_help = S("Launches arrows"), _doc_items_longdesc = S("Bows are ranged weapons to shoot arrows at your foes.").."\n".. S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead."), @@ -151,11 +151,11 @@ S("The speed and damage of the arrow increases the longer you charge. The regula }) minetest.register_tool("mcl_bows:crossbow_loaded", { - description = S("Corssbow"), + description = S("Crossbow"), _tt_help = S("Launches arrows"), - _doc_items_longdesc = S("Corssbow are ranged weapons to shoot arrows at your foes.").."\n".. + _doc_items_longdesc = S("Crossbow is a ranged weapon to shoot arrows at your foes.").."\n".. S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead."), - _doc_items_usagehelp = S("To use the corssbow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to load an arrow into the chamber, then to shoot press left mouse."), + _doc_items_usagehelp = S("To use the crossbow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to load an arrow into the chamber, then to shoot press left mouse."), _doc_items_durability = BOW_DURABILITY, inventory_image = "mcl_bows_crossbow_3.png", wield_scale = mcl_vars.tool_wield_scale, From 5e58e7160280ef2d64a1b1e59933bdd41ae1601c Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 26 Jan 2022 03:35:05 +0400 Subject: [PATCH 03/22] #139 Fix crash on fly priv change for offline player --- mods/MISC/mcl_privs/init.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index f06ff3582..b0d7a5066 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -22,8 +22,10 @@ for _, action in pairs({"grant", "revoke"}) do minetest["register_on_priv_" .. action](function(name, _, priv) if priv == "fly" then local player = minetest.get_player_by_name(name) - local meta = player:get_meta() - meta:set_int("fly_changed", 1) + if player then + local meta = player:get_meta() + meta:set_int("fly_changed", 1) + end end end) end \ No newline at end of file From 8bfa248ef7a3a410d4531848cfce75d08a8c4ec7 Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 30 Jan 2022 01:07:26 +0100 Subject: [PATCH 04/22] set privs only when changed setting privileges causes mt to write to the player db. this changes shields so it only sets the interact privilege when it has actually changed. --- mods/ITEMS/mcl_shields/init.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 9eebd3e80..914b55755 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -182,8 +182,10 @@ end local function set_interact(player, interact) local player_name = player:get_player_name() local privs = minetest.get_player_privs(player_name) - privs.interact = interact - minetest.set_player_privs(player_name, privs) + if privs.interact ~= interact then + privs.interact = interact + minetest.set_player_privs(player_name, privs) + end end local shield_hud = {} From 5cda117073fe9729eba9486b4e50dd7afb8e8bc4 Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 30 Jan 2022 01:08:32 +0100 Subject: [PATCH 05/22] set hud flags only when changed Setting hud flags (and other player properties) when they have not changed results in unneccessary network traffic. --- mods/ITEMS/mcl_shields/init.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 914b55755..3ac58fc3c 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -197,7 +197,12 @@ local function remove_shield_hud(player) set_shield(player, false, 1) set_shield(player, false, 2) end - player:hud_set_flags({wielditem = true}) + + local hf=player:hud_get_flags() + if not hf.wielditem then + player:hud_set_flags({wielditem = true}) + end + playerphysics.remove_physics_factor(player, "speed", "shield_speed") set_interact(player, true) end From 70bf172d46895b2738025cfba98d173233412663 Mon Sep 17 00:00:00 2001 From: cora Date: Sat, 29 Jan 2022 23:08:06 +0100 Subject: [PATCH 06/22] reimplement mc firespread with abms --- mods/ITEMS/mcl_fire/init.lua | 252 ++++++++++++++--------------------- 1 file changed, 103 insertions(+), 149 deletions(-) diff --git a/mods/ITEMS/mcl_fire/init.lua b/mods/ITEMS/mcl_fire/init.lua index 9f1337a5d..31acdf3c4 100644 --- a/mods/ITEMS/mcl_fire/init.lua +++ b/mods/ITEMS/mcl_fire/init.lua @@ -37,7 +37,7 @@ local lava_fire= { x = 1, y = 1, z = 0}, { x = 1, y = 1, z = 1} } -local alldirs= +local adjacents = { { x =-1, y = 0, z = 0}, { x = 1, y = 0, z = 0}, @@ -87,7 +87,7 @@ else end local function fire_timer(pos) - minetest.get_node_timer(pos):start(math.random(3, 7)) + minetest.get_node_timer(pos):start(math.random(15, 45)) end local function spawn_fire(pos, age) @@ -95,6 +95,23 @@ local function spawn_fire(pos, age) minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z}) end +local function shuffle_adjacents() + for i = #adjacents, 1, -1 do + local r = math.random(i) + adjacents[i], adjacents[r] = adjacents[r], adjacents[i] + end +end + +local function has_flammable(pos) + for k,v in pairs(adjacents) do + local p=vector.add(pos,v) + local n=minetest.get_node_or_nil(p) + if n and minetest.get_item_group(n.name, "flammable") ~= 0 then + return p + end + end +end + minetest.register_node("mcl_fire:fire", { description = S("Fire"), _doc_items_longdesc = fire_help, @@ -125,80 +142,12 @@ minetest.register_node("mcl_fire:fire", { end end, on_timer = function(pos) - local node = get_node(pos) - -- Age is a number from 0 to 15 and is increased every timer step. - -- "old" fire is more likely to be extinguished - local age = node.param2 - local flammables = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"}) - local below = get_node({x=pos.x, y=pos.z-1, z=pos.z}) - local below_is_flammable = get_item_group(below.name, "flammable") > 0 - -- Extinguish fire - if (not fire_enabled) and (math.random(1,3) == 1) then - remove_node(pos) + local p=has_flammable(pos) + if not p or minetest.get_item_group(minetest.get_node(p).name, "flammable") == -1 then + minetest.remove_node(pos) return end - if age == 15 and not below_is_flammable then - remove_node(pos) - return - elseif age > 3 and #flammables == 0 and not below_is_flammable and math.random(1,4) == 1 then - remove_node(pos) - return - end - local age_add = 1 - -- If fire spread is disabled, we have to skip the "destructive" code - if (not fire_enabled) then - if age + age_add <= 15 then - node.param2 = age + age_add - set_node(pos, node) - end - -- Restart timer - fire_timer(pos) - return - end - -- Spawn fire to nearby flammable nodes - local is_next_to_flammable = find_node_near(pos, 2, {"group:flammable"}) ~= nil - if is_next_to_flammable and math.random(1,2) == 1 then - -- The fire we spawn copies the age of this fire. - -- This prevents fire from spreading infinitely far as the fire fire dies off - -- quicker the further it has spreaded. - local age_next = math.min(15, age + math.random(0, 1)) - -- Select random type of fire spread - local burntype = math.random(1,2) - if burntype == 1 then - -- Spawn fire in air - local nodes = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"}) - while #nodes > 0 do - local r = math.random(1, #nodes) - if find_node_near(nodes[r], 1, {"group:flammable"}) then - spawn_fire(nodes[r], age_next) - break - else - table.remove(nodes, r) - end - end - else - -- Burn flammable block - local nodes = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"}) - if #nodes > 0 then - local r = math.random(1, #nodes) - local nn = get_node(nodes[r]).name - local ndef = minetest.registered_nodes[nn] - local fgroup = get_item_group(nn, "flammable") - if ndef and ndef._on_burn then - ndef._on_burn(nodes[r]) - elseif fgroup ~= -1 then - spawn_fire(nodes[r], age_next) - end - end - end - end - -- Regular age increase - if age + age_add <= 15 then - node.param2 = age + age_add - set_node(pos, node) - end - -- Restart timer - fire_timer(pos) + return true --restart timer end, drop = "", sounds = {}, @@ -254,29 +203,8 @@ minetest.register_node("mcl_fire:eternal_fire", { minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) end end, - on_timer = function(pos) - if fire_enabled then - local airs = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"}) - while #airs > 0 do - local r = math.random(1, #airs) - if find_node_near(airs[r], 1, {"group:flammable"}) then - local node = get_node(airs[r]) - local age = node.param2 - local age_next = math.min(15, age + math.random(0, 1)) - spawn_fire(airs[r], age_next) - break - else - table.remove(airs, r) - end - end - end - -- Restart timer - fire_timer(pos) - end, - -- Start burning timer and light Nether portal (if possible) + -- light Nether portal (if possible) on_construct = function(pos) - fire_timer(pos) - if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time mcl_portals.light_nether_portal(pos) end @@ -421,21 +349,39 @@ minetest.register_abm({ end, }) +--- Fire spread logic --- Enable the following ABMs according to 'enable fire' setting +-- A fire that is not adjacent to any flammable block does not spread, even to another flammable block within the normal range. +-- A fire block can turn any air block that is adjacent to a flammable block into a fire block. This can happen at a distance of up to one block downward, one block sideways (including diagonals), and four blocks upward of the original fire block (not the block the fire is on/next to). +-- Fire spreads from a still lava block similarly: any air block one above and up to one block sideways (including diagonals) or two above and two blocks sideways (including diagonals) that is adjacent to a flammable block may be turned into a fire block. +-- https://minecraft.fandom.com/wiki/Fire#Spread -local function has_flammable(pos) - local npos, node - for n, v in ipairs(alldirs) do - npos = vector.add(pos, v) - node = get_node_or_nil(npos) - if node and node.name and get_item_group(node.name, "flammable") ~= 0 then - return npos - end +local function check_aircube(p1,p2) + local nds=minetest.find_nodes_in_area(p1,p2,{"air"}) + for k,v in pairs(nds) do + if has_flammable(v) then return v end end return false end +local function get_ignitable(pos) + return check_aircube(vector.add(pos,vector.new(-1,-1,-1)),vector.add(pos,vector.new(1,4,1))) +end + +local function get_ignitable_by_lava(pos) + return check_aircube(vector.add(pos,vector.new(-1,1,-1)),vector.add(pos,vector.new(1,1,1))) or check_aircube(vector.add(pos,vector.new(-2,2,-2)),vector.add(pos,vector.new(2,2,2))) or nil +end + +local function add_fire_particle(pos) + minetest.add_particle({ + pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), + velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z}, + expirationtime=1, size=1, collisiondetection=false, + glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" + }) +end + +-- Enable the following ABMs according to 'enable fire' setting if not fire_enabled then -- Occasionally remove fire if fire disabled @@ -451,62 +397,70 @@ if not fire_enabled then else -- Fire enabled + minetest.register_abm({ + label = "Ignite flame", + nodenames ={"mcl_fire:fire","mcl_fire:eternal_fire"}, + interval = 7, + chance = 12, + catch_up = false, + action = function(pos) + local p = get_ignitable(pos) + if p then + add_fire_particle(p) + spawn_fire(p) + shuffle_adjacents() + end + end + }) + + -- Set fire to air nodes minetest.register_abm({ label = "Ignite fire by lava", nodenames = {"group:lava"}, - neighbors = {"air"}, + nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"}, + neighbors = {"air","group:flammable"}, interval = 7, chance = 3, catch_up = false, action = function(pos) - local i, dir, target, node, i2, f - i = math.random(1,9) - dir = lava_fire[i] - target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} - node = get_node(target) - if not node or node.name ~= "air" then - i = ((i + math.random(0,7)) % 9) + 1 - dir = lava_fire[i] - target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} - node = get_node(target) - if not node or node.name ~= "air" then - return - end - end - i2 = math.random(1,15) - if i2 < 10 then - local dir2, target2, node2 - dir2 = lava_fire[i2] - target2 = {x=target.x+dir2.x, y=target.y+dir2.y, z=target.z+dir2.z} - node2 = get_node(target2) - if node2 and node2.name == "air" then - f = has_flammable(target2) - if f then - minetest.after(1, spawn_fire, {x=target2.x, y=target2.y, z=target2.z}) - minetest.add_particle({ - pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), - velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.7), z=f.z-pos.z}, - expirationtime=1, size=1.5, collisiondetection=false, - glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" - }) - return - end - end - end - f = has_flammable(target) - if f then - minetest.after(1, spawn_fire, {x=target.x, y=target.y, z=target.z}) - minetest.add_particle({ - pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), - velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z}, - expirationtime=1, size=1, collisiondetection=false, - glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" - }) + local p=get_ignitable_by_lava(pos) + if p then + add_fire_particle(p) + spawn_fire(p) end end, }) + -- Remove flammable nodes around basic flame + minetest.register_abm({ + label = "Remove flammable nodes", + nodenames = {"mcl_fire:fire","mcl_fire:eternal_fire"}, + neighbors = {"group:flammable"}, + interval = 5, + chance = 18, + catch_up = false, + action = function(pos) + local p = has_flammable(pos) + if not p then + return + end + + local nn = minetest.get_node(p).name + local def = minetest.registered_nodes[nn] + local fgroup = minetest.get_item_group(nn, "flammable") + + if def and def._on_burn then + def._on_burn(p) + elseif fgroup ~= -1 then + add_fire_particle(p) + spawn_fire(p) + fire_timer(p) + minetest.check_for_falling(p) + end + end + }) + end -- Set pointed_thing on (normal) fire. From b92fa67232f33fd2d81ea3d4a0f1afec5df7ec6d Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 30 Jan 2022 01:23:17 +0100 Subject: [PATCH 07/22] fix beds not to burn away and drop --- mods/ITEMS/mcl_beds/api.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_beds/api.lua b/mods/ITEMS/mcl_beds/api.lua index 85873f3c6..dc4527c78 100644 --- a/mods/ITEMS/mcl_beds/api.lua +++ b/mods/ITEMS/mcl_beds/api.lua @@ -248,7 +248,7 @@ function mcl_beds.register_bed(name, def) paramtype2 = "facedir", is_ground_content = false, -- FIXME: Should be bouncy=66, but this would be a higher bounciness than slime blocks! - groups = {handy = 1, flammable = 3, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1}, + groups = {handy = 1, flammable = -1, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1}, _mcl_hardness = 0.2, _mcl_blast_resistance = 1, sounds = def.sounds or default_sounds, @@ -275,5 +275,3 @@ function mcl_beds.register_bed(name, def) doc.add_entry_alias("nodes", name.."_bottom", "nodes", name.."_top") end - - From 3e0ae57459a46e303e7f2a750652381de013b15d Mon Sep 17 00:00:00 2001 From: cora Date: Sat, 29 Jan 2022 23:08:06 +0100 Subject: [PATCH 08/22] reimplement mc firespread with abms --- mods/ITEMS/mcl_fire/init.lua | 252 ++++++++++++++--------------------- 1 file changed, 103 insertions(+), 149 deletions(-) diff --git a/mods/ITEMS/mcl_fire/init.lua b/mods/ITEMS/mcl_fire/init.lua index 9f1337a5d..ee06c6e20 100644 --- a/mods/ITEMS/mcl_fire/init.lua +++ b/mods/ITEMS/mcl_fire/init.lua @@ -37,7 +37,7 @@ local lava_fire= { x = 1, y = 1, z = 0}, { x = 1, y = 1, z = 1} } -local alldirs= +local adjacents = { { x =-1, y = 0, z = 0}, { x = 1, y = 0, z = 0}, @@ -87,7 +87,7 @@ else end local function fire_timer(pos) - minetest.get_node_timer(pos):start(math.random(3, 7)) + minetest.get_node_timer(pos):start(math.random(15, 45)) end local function spawn_fire(pos, age) @@ -95,6 +95,23 @@ local function spawn_fire(pos, age) minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z}) end +local function shuffle_adjacents() + for i = #adjacents, 1, -1 do + local r = math.random(i) + adjacents[i], adjacents[r] = adjacents[r], adjacents[i] + end +end + +local function has_flammable(pos) + for k,v in pairs(adjacents) do + local p=vector.add(pos,v) + local n=minetest.get_node_or_nil(p) + if n and minetest.get_item_group(n.name, "flammable") ~= 0 then + return p + end + end +end + minetest.register_node("mcl_fire:fire", { description = S("Fire"), _doc_items_longdesc = fire_help, @@ -125,80 +142,12 @@ minetest.register_node("mcl_fire:fire", { end end, on_timer = function(pos) - local node = get_node(pos) - -- Age is a number from 0 to 15 and is increased every timer step. - -- "old" fire is more likely to be extinguished - local age = node.param2 - local flammables = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"}) - local below = get_node({x=pos.x, y=pos.z-1, z=pos.z}) - local below_is_flammable = get_item_group(below.name, "flammable") > 0 - -- Extinguish fire - if (not fire_enabled) and (math.random(1,3) == 1) then - remove_node(pos) + local p=has_flammable(pos) + if not p or minetest.get_item_group(minetest.get_node(p).name, "flammable") == -1 then + minetest.remove_node(pos) return end - if age == 15 and not below_is_flammable then - remove_node(pos) - return - elseif age > 3 and #flammables == 0 and not below_is_flammable and math.random(1,4) == 1 then - remove_node(pos) - return - end - local age_add = 1 - -- If fire spread is disabled, we have to skip the "destructive" code - if (not fire_enabled) then - if age + age_add <= 15 then - node.param2 = age + age_add - set_node(pos, node) - end - -- Restart timer - fire_timer(pos) - return - end - -- Spawn fire to nearby flammable nodes - local is_next_to_flammable = find_node_near(pos, 2, {"group:flammable"}) ~= nil - if is_next_to_flammable and math.random(1,2) == 1 then - -- The fire we spawn copies the age of this fire. - -- This prevents fire from spreading infinitely far as the fire fire dies off - -- quicker the further it has spreaded. - local age_next = math.min(15, age + math.random(0, 1)) - -- Select random type of fire spread - local burntype = math.random(1,2) - if burntype == 1 then - -- Spawn fire in air - local nodes = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"}) - while #nodes > 0 do - local r = math.random(1, #nodes) - if find_node_near(nodes[r], 1, {"group:flammable"}) then - spawn_fire(nodes[r], age_next) - break - else - table.remove(nodes, r) - end - end - else - -- Burn flammable block - local nodes = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"}) - if #nodes > 0 then - local r = math.random(1, #nodes) - local nn = get_node(nodes[r]).name - local ndef = minetest.registered_nodes[nn] - local fgroup = get_item_group(nn, "flammable") - if ndef and ndef._on_burn then - ndef._on_burn(nodes[r]) - elseif fgroup ~= -1 then - spawn_fire(nodes[r], age_next) - end - end - end - end - -- Regular age increase - if age + age_add <= 15 then - node.param2 = age + age_add - set_node(pos, node) - end - -- Restart timer - fire_timer(pos) + return true --restart timer end, drop = "", sounds = {}, @@ -254,29 +203,8 @@ minetest.register_node("mcl_fire:eternal_fire", { minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) end end, - on_timer = function(pos) - if fire_enabled then - local airs = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"}) - while #airs > 0 do - local r = math.random(1, #airs) - if find_node_near(airs[r], 1, {"group:flammable"}) then - local node = get_node(airs[r]) - local age = node.param2 - local age_next = math.min(15, age + math.random(0, 1)) - spawn_fire(airs[r], age_next) - break - else - table.remove(airs, r) - end - end - end - -- Restart timer - fire_timer(pos) - end, - -- Start burning timer and light Nether portal (if possible) + -- light Nether portal (if possible) on_construct = function(pos) - fire_timer(pos) - if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time mcl_portals.light_nether_portal(pos) end @@ -421,21 +349,39 @@ minetest.register_abm({ end, }) +--- Fire spread logic --- Enable the following ABMs according to 'enable fire' setting +-- A fire that is not adjacent to any flammable block does not spread, even to another flammable block within the normal range. +-- A fire block can turn any air block that is adjacent to a flammable block into a fire block. This can happen at a distance of up to one block downward, one block sideways (including diagonals), and four blocks upward of the original fire block (not the block the fire is on/next to). +-- Fire spreads from a still lava block similarly: any air block one above and up to one block sideways (including diagonals) or two above and two blocks sideways (including diagonals) that is adjacent to a flammable block may be turned into a fire block. +-- https://minecraft.fandom.com/wiki/Fire#Spread -local function has_flammable(pos) - local npos, node - for n, v in ipairs(alldirs) do - npos = vector.add(pos, v) - node = get_node_or_nil(npos) - if node and node.name and get_item_group(node.name, "flammable") ~= 0 then - return npos - end +local function check_aircube(p1,p2) + local nds=minetest.find_nodes_in_area(p1,p2,{"air"}) + for k,v in pairs(nds) do + if has_flammable(v) then return v end end return false end +local function get_ignitable(pos) + return check_aircube(vector.add(pos,vector.new(-1,-1,-1)),vector.add(pos,vector.new(1,4,1))) +end + +local function get_ignitable_by_lava(pos) + return check_aircube(vector.add(pos,vector.new(-1,1,-1)),vector.add(pos,vector.new(1,1,1))) or check_aircube(vector.add(pos,vector.new(-2,2,-2)),vector.add(pos,vector.new(2,2,2))) or nil +end + +local function add_fire_particle(pos,f) + minetest.add_particle({ + pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), + velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z}, + expirationtime=1, size=1, collisiondetection=false, + glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" + }) +end + +-- Enable the following ABMs according to 'enable fire' setting if not fire_enabled then -- Occasionally remove fire if fire disabled @@ -451,62 +397,70 @@ if not fire_enabled then else -- Fire enabled + minetest.register_abm({ + label = "Ignite flame", + nodenames ={"mcl_fire:fire","mcl_fire:eternal_fire"}, + interval = 7, + chance = 12, + catch_up = false, + action = function(pos) + local p = get_ignitable(pos) + if p then + add_fire_particle(p,pos) + spawn_fire(p) + shuffle_adjacents() + end + end + }) + + -- Set fire to air nodes minetest.register_abm({ label = "Ignite fire by lava", nodenames = {"group:lava"}, - neighbors = {"air"}, + nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"}, + neighbors = {"air","group:flammable"}, interval = 7, chance = 3, catch_up = false, action = function(pos) - local i, dir, target, node, i2, f - i = math.random(1,9) - dir = lava_fire[i] - target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} - node = get_node(target) - if not node or node.name ~= "air" then - i = ((i + math.random(0,7)) % 9) + 1 - dir = lava_fire[i] - target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} - node = get_node(target) - if not node or node.name ~= "air" then - return - end - end - i2 = math.random(1,15) - if i2 < 10 then - local dir2, target2, node2 - dir2 = lava_fire[i2] - target2 = {x=target.x+dir2.x, y=target.y+dir2.y, z=target.z+dir2.z} - node2 = get_node(target2) - if node2 and node2.name == "air" then - f = has_flammable(target2) - if f then - minetest.after(1, spawn_fire, {x=target2.x, y=target2.y, z=target2.z}) - minetest.add_particle({ - pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), - velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.7), z=f.z-pos.z}, - expirationtime=1, size=1.5, collisiondetection=false, - glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" - }) - return - end - end - end - f = has_flammable(target) - if f then - minetest.after(1, spawn_fire, {x=target.x, y=target.y, z=target.z}) - minetest.add_particle({ - pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), - velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z}, - expirationtime=1, size=1, collisiondetection=false, - glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" - }) + local p=get_ignitable_by_lava(pos) + if p then + add_fire_particle(p,pos) + spawn_fire(p) end end, }) + -- Remove flammable nodes around basic flame + minetest.register_abm({ + label = "Remove flammable nodes", + nodenames = {"mcl_fire:fire","mcl_fire:eternal_fire"}, + neighbors = {"group:flammable"}, + interval = 5, + chance = 18, + catch_up = false, + action = function(pos) + local p = has_flammable(pos) + if not p then + return + end + + local nn = minetest.get_node(p).name + local def = minetest.registered_nodes[nn] + local fgroup = minetest.get_item_group(nn, "flammable") + + if def and def._on_burn then + def._on_burn(p) + elseif fgroup ~= -1 then + add_fire_particle(p,pos) + spawn_fire(p) + fire_timer(p) + minetest.check_for_falling(p) + end + end + }) + end -- Set pointed_thing on (normal) fire. From 82ddeba826272fe59ef269ad753ce8e7feb50784 Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 30 Jan 2022 01:23:17 +0100 Subject: [PATCH 09/22] fix beds not to burn away and drop --- mods/ITEMS/mcl_beds/api.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_beds/api.lua b/mods/ITEMS/mcl_beds/api.lua index 85873f3c6..dc4527c78 100644 --- a/mods/ITEMS/mcl_beds/api.lua +++ b/mods/ITEMS/mcl_beds/api.lua @@ -248,7 +248,7 @@ function mcl_beds.register_bed(name, def) paramtype2 = "facedir", is_ground_content = false, -- FIXME: Should be bouncy=66, but this would be a higher bounciness than slime blocks! - groups = {handy = 1, flammable = 3, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1}, + groups = {handy = 1, flammable = -1, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1}, _mcl_hardness = 0.2, _mcl_blast_resistance = 1, sounds = def.sounds or default_sounds, @@ -275,5 +275,3 @@ function mcl_beds.register_bed(name, def) doc.add_entry_alias("nodes", name.."_bottom", "nodes", name.."_top") end - - From cbe9f7252600f4e10cd6fc4dced73821d8697ad9 Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 30 Jan 2022 20:09:38 +0100 Subject: [PATCH 10/22] add simple weather particlespawner manager --- mods/ENVIRONMENT/mcl_weather/weather_core.lua | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/mods/ENVIRONMENT/mcl_weather/weather_core.lua b/mods/ENVIRONMENT/mcl_weather/weather_core.lua index 34f69406d..7aec1a9ff 100644 --- a/mods/ENVIRONMENT/mcl_weather/weather_core.lua +++ b/mods/ENVIRONMENT/mcl_weather/weather_core.lua @@ -47,6 +47,29 @@ local function save_weather() end minetest.register_on_shutdown(save_weather) +local particlespawners={} +function mcl_weather.add_spawner_player(pl,id,ps) + local name=pl:get_player_name() + if not particlespawners[name] then + particlespawners[name] = {} + end + if not particlespawners[name][id] then + ps.playername =name + ps.attached = pl + particlespawners[name][id]=minetest.add_particlespawner(ps) + return particlespawners[name][id] + end +end +function mcl_weather.remove_spawners_player(pl) + local name=pl:get_player_name() + if not particlespawners[name] then return end + for k,v in pairs(particlespawners[name]) do + minetest.delete_particlespawner(v) + end + particlespawners[name] = nil + return true +end + function mcl_weather.get_rand_end_time(min_duration, max_duration) local r if min_duration and max_duration then From 3312b703211a4e55c97cbe291b7ed1513bacf8b3 Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 30 Jan 2022 20:09:58 +0100 Subject: [PATCH 11/22] let snow use particlespawners --- mods/ENVIRONMENT/mcl_weather/snow.lua | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/mods/ENVIRONMENT/mcl_weather/snow.lua b/mods/ENVIRONMENT/mcl_weather/snow.lua index 9f89a3a0a..f01d1d1b7 100644 --- a/mods/ENVIRONMENT/mcl_weather/snow.lua +++ b/mods/ENVIRONMENT/mcl_weather/snow.lua @@ -5,6 +5,26 @@ mcl_weather.snow = {} mcl_weather.snow.particles_count = 15 mcl_weather.snow.init_done = false +local psdef= { + amount = 99, + time = 0, --stay on til we turn it off + minpos = vector.new(-15,-5,-15), + maxpos =vector.new(15,10,15), + minvel = vector.new(0,-1,0), + maxvel = vector.new(0,-4,0), + minacc = vector.new(0,-1,0), + maxacc = vector.new(0,-4,0), + minexptime = 1, + maxexptime = 1, + minsize = 0.5, + maxsize = 5, + collisiondetection = true, + collision_removal = true, + object_collision = true, + vertical = true, + glow = 1 +} + -- calculates coordinates and draw particles for snow weather function mcl_weather.snow.add_snow_particles(player) mcl_weather.rain.last_rp_count = 0 @@ -75,9 +95,13 @@ minetest.register_globalstep(function(dtime) for _, player in pairs(get_connected_players()) do if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then + mcl_weather.remove_spawners_player(player) return false end - mcl_weather.snow.add_snow_particles(player) + for i=1,2 do + psdef.texture="weather_pack_snow_snowflake"..i..".png" + mcl_weather.add_spawner_player(player,"snow"..i,psdef) + end end end) From f4f4156420b07860b9b03346654c988e29ec1603 Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 30 Jan 2022 21:15:51 +0100 Subject: [PATCH 12/22] let rain and thunder use particlespawners --- mods/ENVIRONMENT/mcl_weather/rain.lua | 100 ++++++++++++++++---------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/rain.lua b/mods/ENVIRONMENT/mcl_weather/rain.lua index 220b61006..191062bcd 100644 --- a/mods/ENVIRONMENT/mcl_weather/rain.lua +++ b/mods/ENVIRONMENT/mcl_weather/rain.lua @@ -1,5 +1,5 @@ -local PARTICLES_COUNT_RAIN = 30 -local PARTICLES_COUNT_THUNDER = 45 +local PARTICLES_COUNT_RAIN = 100 +local PARTICLES_COUNT_THUNDER = 300 local get_connected_players = minetest.get_connected_players @@ -19,6 +19,45 @@ mcl_weather.rain = { init_done = false, } +local update_sound={} +local vel=math.random(0,3) +local falling_speed=math.random(10,15) +local size = math.random(1,3) +local psdef= { + amount = mcl_weather.rain.particles_count, + time=0, + minpos = vector.new(-6,3,-6), + maxpos = vector.new(6,15,6), + minvel = vector.new(-vel,-falling_speed,-vel), + maxvel = math.random(vel,-falling_speed+vel,vel), + minacc = vector.new(0,0,0), + maxacc = vector.new(0,-0.4,0), + minexptime = 0.5, + maxexptime = 2, + minsize = size, + maxsize= size*2, + collisiondetection = true, + collision_removal = true, + vertical = true, +} +local psdef_backsplash= { + amount = 10, + time=0, + minpos = vector.new(-3,-1,-3), + maxpos = vector.new(3,0,3), + minvel = vector.new(-vel,falling_speed*2,-vel), + maxvel = math.random(vel,falling_speed*2+vel,vel), + minacc = vector.new(0,0,0), + maxacc = vector.new(0,0,0), + minexptime = 0.1, + maxexptime = 0.2, + minsize = size*0.1, + maxsize= size*0.5, + collisiondetection = true, + collision_removal = true, + vertical = true, +} +local textures = {"weather_pack_rain_raindrop_1.png", "weather_pack_rain_raindrop_2.png", "weather_pack_rain_raindrop_1.png"} function mcl_weather.rain.sound_handler(player) return minetest.sound_play("weather_rain", { @@ -44,42 +83,18 @@ function mcl_weather.rain.set_sky_box() end end --- creating manually parctiles instead of particles spawner because of easier to control --- spawn position. +-- no no no NO NO f*.. no. no manual particle creatin' PLS!! this sends EVERY particle over the net. function mcl_weather.rain.add_rain_particles(player) - mcl_weather.rain.last_rp_count = 0 - for i=mcl_weather.rain.particles_count, 1,-1 do - local random_pos_x, random_pos_y, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player) - if mcl_weather.is_outdoor({x=random_pos_x, y=random_pos_y, z=random_pos_z}) then - mcl_weather.rain.last_rp_count = mcl_weather.rain.last_rp_count + 1 - minetest.add_particle({ - pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z}, - velocity = {x=0, y=-10, z=0}, - acceleration = {x=0, y=-30, z=0}, - expirationtime = 1.0, - size = math.random(0.5, 3), - collisiondetection = true, - collision_removal = true, - vertical = true, - texture = mcl_weather.rain.get_texture(), - playername = player:get_player_name() - }) - end + mcl_weather.rain.last_rp_count = mcl_weather.rain.particles_count + for k,v in pairs(textures) do + psdef.texture=v + mcl_weather.add_spawner_player(player,"rain"..k,psdef) end -end - --- Simple random texture getter -function mcl_weather.rain.get_texture() - local texture_name - local random_number = math.random() - if random_number > 0.33 then - texture_name = "weather_pack_rain_raindrop_1.png" - elseif random_number > 0.66 then - texture_name = "weather_pack_rain_raindrop_2.png" - else - texture_name = "weather_pack_rain_raindrop_3.png" + psdef_backsplash.texture=textures[math.random(1,#textures)] + local l=mcl_weather.add_spawner_player(player,"rainbacksplash",psdef_backsplash) + if l then + update_sound[player:get_player_name()]=true end - return texture_name; end -- register player for rain weather. @@ -89,6 +104,7 @@ function mcl_weather.rain.add_player(player) local player_meta = {} player_meta.origin_sky = {player:get_sky()} mcl_weather.players[player:get_player_name()] = player_meta + update_sound[player:get_player_name()]=true end end @@ -99,6 +115,7 @@ function mcl_weather.rain.remove_player(player) if player_meta and player_meta.origin_sky then player:set_clouds({color="#FFF0F0E5"}) mcl_weather.players[player:get_player_name()] = nil + update_sound[player:get_player_name()]=true end end @@ -119,6 +136,7 @@ end) -- have few seconds delay before each check to avoid on/off sound too often -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance. function mcl_weather.rain.update_sound(player) + if not update_sound[player:get_player_name()] then return end local player_meta = mcl_weather.players[player:get_player_name()] if player_meta then if player_meta.sound_updated and player_meta.sound_updated + 5 > minetest.get_gametime() then @@ -136,6 +154,7 @@ function mcl_weather.rain.update_sound(player) player_meta.sound_updated = minetest.get_gametime() end + update_sound[player:get_player_name()]=false end -- rain sound removed from player. @@ -158,7 +177,8 @@ function mcl_weather.rain.clear() for _, player in pairs(get_connected_players()) do mcl_weather.rain.remove_sound(player) mcl_weather.rain.remove_player(player) - end + mcl_weather.remove_spawners_player(player) + end end minetest.register_globalstep(function(dtime) @@ -177,8 +197,10 @@ function mcl_weather.rain.make_weather() end for _, player in pairs(get_connected_players()) do - if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then + local pos=player:get_pos() + if mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(pos) or not mcl_weather.is_outdoor(pos) then mcl_weather.rain.remove_sound(player) + mcl_weather.remove_spawners_player(player) return false end mcl_weather.rain.add_player(player) @@ -190,8 +212,12 @@ end -- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops function mcl_weather.rain.set_particles_mode(mode) if mode == "thunder" then + psdef.amount=PARTICLES_COUNT_THUNDER + psdef_backsplash.amount=PARTICLES_COUNT_THUNDER mcl_weather.rain.particles_count = PARTICLES_COUNT_THUNDER else + psdef.amount=PARTICLES_COUNT_RAIN + psdef_backsplash.amount=PARTICLES_COUNT_RAIN mcl_weather.rain.particles_count = PARTICLES_COUNT_RAIN end end From 89be677f8ac35e475a5d72342b9ac240cec44f21 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 31 Jan 2022 00:22:16 +0100 Subject: [PATCH 13/22] remove unneccessary particle logic --- mods/ENVIRONMENT/mcl_weather/snow.lua | 25 ---------------- mods/ENVIRONMENT/mcl_weather/weather_core.lua | 30 ------------------- 2 files changed, 55 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/snow.lua b/mods/ENVIRONMENT/mcl_weather/snow.lua index f01d1d1b7..4d9fda928 100644 --- a/mods/ENVIRONMENT/mcl_weather/snow.lua +++ b/mods/ENVIRONMENT/mcl_weather/snow.lua @@ -25,31 +25,6 @@ local psdef= { glow = 1 } --- calculates coordinates and draw particles for snow weather -function mcl_weather.snow.add_snow_particles(player) - mcl_weather.rain.last_rp_count = 0 - for i=mcl_weather.snow.particles_count, 1,-1 do - local random_pos_x, _, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player) - local random_pos_y = math.random() + math.random(player:get_pos().y - 1, player:get_pos().y + 7) - if minetest.get_node_light({x=random_pos_x, y=random_pos_y, z=random_pos_z}, 0.5) == 15 then - mcl_weather.rain.last_rp_count = mcl_weather.rain.last_rp_count + 1 - minetest.add_particle({ - pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z}, - velocity = {x = math.random(-100,100)*0.001, y = math.random(-300,-100)*0.004, z = math.random(-100,100)*0.001}, - acceleration = {x = 0, y=0, z = 0}, - expirationtime = 8.0, - size = 1, - collisiondetection = true, - collision_removal = true, - object_collision = false, - vertical = false, - texture = mcl_weather.snow.get_texture(), - playername = player:get_player_name() - }) - end - end -end - function mcl_weather.snow.set_sky_box() mcl_weather.skycolor.add_layer( "weather-pack-snow-sky", diff --git a/mods/ENVIRONMENT/mcl_weather/weather_core.lua b/mods/ENVIRONMENT/mcl_weather/weather_core.lua index 7aec1a9ff..ef3c8b883 100644 --- a/mods/ENVIRONMENT/mcl_weather/weather_core.lua +++ b/mods/ENVIRONMENT/mcl_weather/weather_core.lua @@ -115,36 +115,6 @@ function mcl_weather.is_underwater(player) return false end --- trying to locate position for particles by player look direction for performance reason. --- it is costly to generate many particles around player so goal is focus mainly on front view. -function mcl_weather.get_random_pos_by_player_look_dir(player) - local look_dir = player:get_look_dir() - local player_pos = player:get_pos() - - local random_pos_x, random_pos_y, random_pos_z - - if look_dir.x > 0 then - if look_dir.z > 0 then - random_pos_x = math.random() + math.random(player_pos.x - 2.5, player_pos.x + 5) - random_pos_z = math.random() + math.random(player_pos.z - 2.5, player_pos.z + 5) - else - random_pos_x = math.random() + math.random(player_pos.x - 2.5, player_pos.x + 5) - random_pos_z = math.random() + math.random(player_pos.z - 5, player_pos.z + 2.5) - end - else - if look_dir.z > 0 then - random_pos_x = math.random() + math.random(player_pos.x - 5, player_pos.x + 2.5) - random_pos_z = math.random() + math.random(player_pos.z - 2.5, player_pos.z + 5) - else - random_pos_x = math.random() + math.random(player_pos.x - 5, player_pos.x + 2.5) - random_pos_z = math.random() + math.random(player_pos.z - 5, player_pos.z + 2.5) - end - end - - random_pos_y = math.random() + math.random(player_pos.y + 10, player_pos.y + 15) - return random_pos_x, random_pos_y, random_pos_z -end - local t, wci = 0, mcl_weather.check_interval minetest.register_globalstep(function(dtime) From 6220ef4205a21513b23d6f016d05761319f85016 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 31 Jan 2022 00:22:46 +0100 Subject: [PATCH 14/22] add indoor detection for snow --- mods/ENVIRONMENT/mcl_weather/snow.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENVIRONMENT/mcl_weather/snow.lua b/mods/ENVIRONMENT/mcl_weather/snow.lua index 4d9fda928..8de38ea98 100644 --- a/mods/ENVIRONMENT/mcl_weather/snow.lua +++ b/mods/ENVIRONMENT/mcl_weather/snow.lua @@ -69,7 +69,7 @@ minetest.register_globalstep(function(dtime) end for _, player in pairs(get_connected_players()) do - if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then + if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos()) or not mcl_weather.is_outoor(player:get_pos())) then mcl_weather.remove_spawners_player(player) return false end From 5f910e38031cb2d50d2feb355d250cdd97994da9 Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 31 Jan 2022 00:35:26 +0100 Subject: [PATCH 15/22] fix snow not being properly removed --- mods/ENVIRONMENT/mcl_weather/snow.lua | 3 ++- mods/ENVIRONMENT/mcl_weather/weather_core.lua | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mods/ENVIRONMENT/mcl_weather/snow.lua b/mods/ENVIRONMENT/mcl_weather/snow.lua index 8de38ea98..b60283127 100644 --- a/mods/ENVIRONMENT/mcl_weather/snow.lua +++ b/mods/ENVIRONMENT/mcl_weather/snow.lua @@ -43,6 +43,7 @@ end function mcl_weather.snow.clear() mcl_weather.skycolor.remove_layer("weather-pack-snow-sky") mcl_weather.snow.init_done = false + mcl_weather.remove_all_spawners() end -- Simple random texture getter @@ -69,7 +70,7 @@ minetest.register_globalstep(function(dtime) end for _, player in pairs(get_connected_players()) do - if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos()) or not mcl_weather.is_outoor(player:get_pos())) then + if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos()) or not mcl_weather.is_outdoor(player:get_pos())) then mcl_weather.remove_spawners_player(player) return false end diff --git a/mods/ENVIRONMENT/mcl_weather/weather_core.lua b/mods/ENVIRONMENT/mcl_weather/weather_core.lua index ef3c8b883..f7316bcfb 100644 --- a/mods/ENVIRONMENT/mcl_weather/weather_core.lua +++ b/mods/ENVIRONMENT/mcl_weather/weather_core.lua @@ -70,6 +70,12 @@ function mcl_weather.remove_spawners_player(pl) return true end +function mcl_weather.remove_all_spawners() + for k,v in pairs(minetest.get_connected_players()) do + mcl_weather.remove_spawners_player(v) + end +end + function mcl_weather.get_rand_end_time(min_duration, max_duration) local r if min_duration and max_duration then From e6bef672750e77d820269b5386ce0a966633cc62 Mon Sep 17 00:00:00 2001 From: NO411 Date: Mon, 31 Jan 2022 17:42:20 +0100 Subject: [PATCH 16/22] Remove unnecessary code --- mods/ITEMS/mcl_shields/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 3ac58fc3c..57701345d 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -464,6 +464,5 @@ minetest.register_on_joinplayer(function(player) shields = {}, blocking = 0, } - mcl_shields.players[player].blocking = 0 remove_shield_hud(player) end) From 33c7ce16103537b074dea98854477a3792ccf37e Mon Sep 17 00:00:00 2001 From: NO411 Date: Mon, 31 Jan 2022 18:08:43 +0100 Subject: [PATCH 17/22] Fix interact behavior to prevent hackers from get interact back through shields --- mods/ENVIRONMENT/mcl_weather/rain.lua | 4 ++-- mods/ITEMS/mcl_shields/init.lua | 7 +++++-- mods/MISC/mcl_privs/init.lua | 24 +++++++++++++++++++----- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/rain.lua b/mods/ENVIRONMENT/mcl_weather/rain.lua index 191062bcd..7efc866bf 100644 --- a/mods/ENVIRONMENT/mcl_weather/rain.lua +++ b/mods/ENVIRONMENT/mcl_weather/rain.lua @@ -29,7 +29,7 @@ local psdef= { minpos = vector.new(-6,3,-6), maxpos = vector.new(6,15,6), minvel = vector.new(-vel,-falling_speed,-vel), - maxvel = math.random(vel,-falling_speed+vel,vel), + maxvel = vector.new(vel,-falling_speed+vel,vel), minacc = vector.new(0,0,0), maxacc = vector.new(0,-0.4,0), minexptime = 0.5, @@ -46,7 +46,7 @@ local psdef_backsplash= { minpos = vector.new(-3,-1,-3), maxpos = vector.new(3,0,3), minvel = vector.new(-vel,falling_speed*2,-vel), - maxvel = math.random(vel,falling_speed*2+vel,vel), + maxvel = vector.new(vel,falling_speed*2+vel,vel), minacc = vector.new(0,0,0), maxacc = vector.new(0,0,0), minexptime = 0.1, diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 57701345d..f742bc760 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -183,8 +183,11 @@ local function set_interact(player, interact) local player_name = player:get_player_name() local privs = minetest.get_player_privs(player_name) if privs.interact ~= interact then - privs.interact = interact - minetest.set_player_privs(player_name, privs) + local meta = player:get_meta() + if meta:get_int("ineract_revoked") ~= 1 then + privs.interact = interact + minetest.set_player_privs(player_name, privs) + end end end diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index b0d7a5066..bbf75f37b 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -20,12 +20,26 @@ end) for _, action in pairs({"grant", "revoke"}) do minetest["register_on_priv_" .. action](function(name, _, priv) - if priv == "fly" then - local player = minetest.get_player_by_name(name) - if player then - local meta = player:get_meta() + local player = minetest.get_player_by_name(name) + if player then + local meta = player:get_meta() + + if priv == "fly" then meta:set_int("fly_changed", 1) end + + --[[ + so e.g. hackers who have been revoked of the interact privilege + will not automatically get the interact privilege through the mcl shields code back + ]] + + if priv == "interact" then + if action == "revoke" then + meta:set_int("ineract_revoked", 1) + else + meta:set_int("ineract_revoked", 0) + end + end end end) -end \ No newline at end of file +end From 04146d98b0ad3b4103b8111d8576659b88e1679d Mon Sep 17 00:00:00 2001 From: cora Date: Mon, 31 Jan 2022 21:35:21 +0100 Subject: [PATCH 18/22] remove unnecessary on_dimensionchange --- mods/ENVIRONMENT/mcl_weather/rain.lua | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/rain.lua b/mods/ENVIRONMENT/mcl_weather/rain.lua index 7efc866bf..0caef5c6f 100644 --- a/mods/ENVIRONMENT/mcl_weather/rain.lua +++ b/mods/ENVIRONMENT/mcl_weather/rain.lua @@ -119,19 +119,6 @@ function mcl_weather.rain.remove_player(player) end end -mcl_worlds.register_on_dimension_change(function(player, dimension) - if dimension ~= "overworld" and dimension ~= "void" then - mcl_weather.rain.remove_sound(player) - mcl_weather.rain.remove_player(player) - elseif dimension == "overworld" then - mcl_weather.rain.update_sound(player) - if mcl_weather.rain.raining then - mcl_weather.rain.add_rain_particles(player) - mcl_weather.rain.add_player(player) - end - end -end) - -- adds and removes rain sound depending how much rain particles around player currently exist. -- have few seconds delay before each check to avoid on/off sound too often -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance. From 2f6242e04f9d70234b4195d0de0936f21a0044d1 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 03:11:53 +0400 Subject: [PATCH 19/22] Fix biomes 1/3 --- mods/CORE/mcl_mapgen/init.lua | 23 +- mods/MAPGEN/mcl_mapgen_core/biomes.lua | 46 ++++ mods/MAPGEN/mcl_mapgen_core/init.lua | 301 +++++-------------------- mods/MAPGEN/mcl_mapgen_core/light.lua | 27 +++ mods/MAPGEN/mcl_mapgen_core/nether.lua | 80 +++++++ mods/MAPGEN/mcl_mapgen_core/v6.lua | 36 +++ 6 files changed, 261 insertions(+), 252 deletions(-) create mode 100644 mods/MAPGEN/mcl_mapgen_core/biomes.lua create mode 100644 mods/MAPGEN/mcl_mapgen_core/light.lua create mode 100644 mods/MAPGEN/mcl_mapgen_core/nether.lua create mode 100644 mods/MAPGEN/mcl_mapgen_core/v6.lua diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index aa2630411..9a0fcf196 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -52,13 +52,14 @@ local seed = minetest.get_mapgen_setting("seed") mcl_mapgen.seed = seed mcl_mapgen.name = minetest.get_mapgen_setting("mg_name") mcl_mapgen.v6 = mcl_mapgen.name == "v6" -mcl_mapgen.superflat = mcl_mapgen.name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" +mcl_mapgen.flat = mcl_mapgen.name == "flat" +mcl_mapgen.superflat = mcl_mapgen.flat and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" mcl_mapgen.singlenode = mcl_mapgen.name == "singlenode" mcl_mapgen.normal = not mcl_mapgen.superflat and not mcl_mapgen.singlenode -local superflat, singlenode, normal = mcl_mapgen.superflat, mcl_mapgen.singlenode, mcl_mapgen.normal +local flat, superflat, singlenode, normal = mcl_mapgen.flat, mcl_mapgen.superflat, mcl_mapgen.singlenode, mcl_mapgen.normal -minetest_log("action", "[mcl_mapgen] Mapgen mode: " .. (normal and "normal" or (superflat and "superflat" or "singlenode"))) ----------------------------------------------------------------------------------------------------------------------------- +minetest_log("action", "[mcl_mapgen] Mapgen mode: " .. (normal and "normal" or (superflat and "superflat" or (flat and "flat" or "singlenode")))) +------------------------------------------------------------------------------------------------------------------------------------------------- -- Generator queues local queue_unsafe_engine = {} @@ -430,14 +431,12 @@ else nether.bedrock_top_min = nether.bedrock_top_max nether.lava_max = nether.min + 2 end -if mcl_mapgen.name == "flat" then - if superflat then - nether.flat_floor = nether.bedrock_bottom_max + 4 - nether.flat_ceiling = nether.bedrock_bottom_max + 52 - else - nether.flat_floor = nether.lava_max + 4 - nether.flat_ceiling = nether.lava_max + 52 - end +if superflat then + nether.flat_floor = nether.bedrock_bottom_max + 4 + nether.flat_ceiling = nether.bedrock_bottom_max + 52 +elseif flat then + nether.flat_floor = nether.lava_max + 4 + nether.flat_ceiling = nether.lava_max + 52 end -- The End (surface at ca. Y = -27000) diff --git a/mods/MAPGEN/mcl_mapgen_core/biomes.lua b/mods/MAPGEN/mcl_mapgen_core/biomes.lua new file mode 100644 index 000000000..955c73a90 --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/biomes.lua @@ -0,0 +1,46 @@ +local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow") +local c_top_snow = minetest.get_content_id("mcl_core:snow") +local c_snow_block = minetest.get_content_id("mcl_core:snowblock") + +mcl_mapgen.register_on_generated(function(vm_context) + local minp, maxp = vm_context.minp, vm_context.maxp + local min_y = minp.y + if min_y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end + vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer) + vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") + local param2_data = vm_context.param2_data + local biomemap = vm_context.biomemap + local vm, data, area = vm_context.vm, vm_context.data, vm_context.area + + ----- Interactive block fixing section ----- + ----- The section to perform basic block overrides of the core mapgen generated world. ----- + + -- Snow and sand fixes. This code implements snow consistency + -- and fixes floating sand and cut plants. + -- A snowy grass block must be below a top snow or snow block at all times. + + -- Set param2 (=color) of grass blocks. + -- Clear snowy grass blocks without snow above to ensure consistency. + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"}) + + -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: + local aream = VoxelArea:new({MinEdge={x=minp.x, y=min_y, z=minp.z}, MaxEdge={x=maxp.x, y=min_y, z=maxp.z}}) + for n=1, #nodes do + local n = nodes[n] + local p_pos = area:index(n.x, n.y, n.z) + local p_pos_above = area:index(n.x, n.y+1, n.z) + local b_pos = aream:index(n.x, min_y, n.z) + local bn = minetest.get_biome_name(biomemap[b_pos]) + if bn then + local biome = minetest.registered_biomes[bn] + if biome and biome._mcl_biome_type then + param2_data[p_pos] = biome._mcl_palette_index + vm_context.write_param2 = true + end + end + if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then + data[p_pos] = c_dirt_with_grass + vm_context.write = true + end + end +end, 999999999) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 88fa0dabf..403282deb 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -56,6 +56,7 @@ local mg_name = mcl_mapgen.name local superflat = mcl_mapgen.superflat local v6 = mcl_mapgen.v6 local singlenode = mcl_mapgen.singlenode +local flat = mcl_mapgen.flat -- Content IDs local c_bedrock = minetest.get_content_id("mcl_core:bedrock") @@ -63,7 +64,6 @@ local c_obsidian = minetest.get_content_id("mcl_core:obsidian") local c_stone = minetest.get_content_id("mcl_core:stone") local c_dirt = minetest.get_content_id("mcl_core:dirt") local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") -local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow") local c_sand = minetest.get_content_id("mcl_core:sand") --local c_sandstone = minetest.get_content_id("mcl_core:sandstone") local c_void = minetest.get_content_id("mcl_core:void") @@ -79,12 +79,7 @@ if minetest.get_modpath("mcl_nether") then } end ---local c_end_stone = minetest.get_content_id("mcl_end:end_stone") local c_realm_barrier = minetest.get_content_id("mcl_core:realm_barrier") -local c_top_snow = minetest.get_content_id("mcl_core:snow") -local c_snow_block = minetest.get_content_id("mcl_core:snowblock") -local c_clay = minetest.get_content_id("mcl_core:clay") ---local c_jungletree = minetest.get_content_id("mcl_core:jungletree") local c_air = minetest.CONTENT_AIR -- @@ -1338,268 +1333,94 @@ end -- lvm_used: Set to true if any node in this on_generated has been set before. -- -- returns true if any node was set and lvm_used otherwise -local function set_layers(data, area, content_id, check, min, max, minp, maxp, lvm_used, pr) +local function set_layers(vm_context, pr, min, max, content_id, check) + local minp, maxp = vm_context.minp, vm_context.maxp if (maxp.y >= min and minp.y <= max) then for y = math.max(min, minp.y), math.min(max, maxp.y) do for x = minp.x, maxp.x do for z = minp.z, maxp.z do - local p_pos = area:index(x, y, z) + local p_pos = vm_context.area:index(x, y, z) if check then if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then - data[p_pos] = content_id - lvm_used = true + vm_context.data[p_pos] = content_id + vm_context.write = true elseif check == data[p_pos] then - data[p_pos] = content_id - lvm_used = true + vm_context.data[p_pos] = content_id + vm_context.write = true end else - data[p_pos] = content_id - lvm_used = true + vm_context.data[p_pos] = content_id + vm_context.write = true end end end end end - return lvm_used end --- Below the bedrock, generate air/void -local function basic_safe(vm_context) - local vm, data, emin, emax, area, minp, maxp, chunkseed, blockseed = vm_context.vm, vm_context.data, vm_context.emin, vm_context.emax, vm_context.area, vm_context.minp, vm_context.maxp, vm_context.chunkseed, vm_context.blockseed +---- Generate layers of air, void, etc +local air_layers = { + {mcl_mapgen.nether.max + 1, mcl_mapgen.nether.max + 128} -- on Nether Roof +} +if flat then + air_layers[#air_layers + 1] = {mcl_mapgen.nether.flat_floor, mcl_mapgen.nether.flat_ceiling} -- Flat Nether +end + +-- Realm barrier between the Overworld void and the End +local barrier_min = mcl_mapgen.realm_barrier_overworld_end_min +local barrier_max = mcl_mapgen.realm_barrier_overworld_end_max + +local void_layers = { + {mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min - 1 }, -- below Nether + {mcl_mapgen.nether.max + 129, mcl_mapgen.end_.min - 1 }, -- below End (above Nether) + {mcl_mapgen.end_.max + 1 , barrier_min - 1 }, -- below Realm Barrier, above End + {barrier_max + 1 , mcl_mapgen.overworld.min - 1}, -- below Overworld, above Realm Barrier +} + +local bedrock_layers = {} +if not singlelayer then + bedrock_layers = { + {mcl_mapgen.overworld.bedrock_min , mcl_mapgen.overworld.bedrock_max }, + {mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_bottom_max}, + {mcl_mapgen.nether.bedrock_top_min , mcl_mapgen.nether.bedrock_top_max }, + } +end + +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local vm, data, area, minp, maxp, chunkseed, blockseed = vm_context.vm, vm_context.data, vm_context.area, vm_context.minp, vm_context.maxp, vm_context.chunkseed, vm_context.blockseed vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer) local param2_data = vm_context.param2_data - - local lvm_used = false local pr = PseudoRandom(blockseed) - - -- The Void below the Nether: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min -1, minp, maxp, lvm_used, pr) - - -- [[ THE NETHER: mcl_mapgen.nether.min mcl_mapgen.nether.max ]] - - -- The Air on the Nether roof, https://git.minetest.land/MineClone2/MineClone2/issues/1186 - lvm_used = set_layers(data, area, c_air , nil, mcl_mapgen.nether.max +1, mcl_mapgen.nether.max + 128 , minp, maxp, lvm_used, pr) - -- The Void above the Nether below the End: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.nether.max + 128 +1, mcl_mapgen.end_.min -1, minp, maxp, lvm_used, pr) - - -- [[ THE END: mcl_mapgen.end_.min mcl_mapgen.end_.max ]] - - -- The Void above the End below the Realm barrier: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.end_.max +1, mcl_mapgen.realm_barrier_overworld_end_min-1, minp, maxp, lvm_used, pr) - -- Realm barrier between the Overworld void and the End - lvm_used = set_layers(data, area, c_realm_barrier, nil, mcl_mapgen.realm_barrier_overworld_end_min , mcl_mapgen.realm_barrier_overworld_end_max , minp, maxp, lvm_used, pr) - -- The Void above Realm barrier below the Overworld: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.realm_barrier_overworld_end_max+1, mcl_mapgen.overworld.min -1, minp, maxp, lvm_used, pr) - - + for _, layer in pairs(void_layers) do + set_layers(vm_context, pr, layer[1], layer[2], c_void) + end + for _, layer in pairs(air_layers) do + set_layers(vm_context, pr, layer[1], layer[2], c_air) + end + set_layers(vm_context, pr, barrier_min, barrier_max, c_realm_barrier) + for _, layer in pairs(bedrock_layers) do + set_layers(vm_context, pr, layer[1], layer[2], c_bedrock, bedrock_check) + end if not singlenode then - -- Bedrock - lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.overworld.bedrock_min, mcl_mapgen.overworld.bedrock_max, minp, maxp, lvm_used, pr) - lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_bottom_max, minp, maxp, lvm_used, pr) - lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_top_min, mcl_mapgen.nether.bedrock_top_max, minp, maxp, lvm_used, pr) - - -- Flat Nether - if mg_name == "flat" then - lvm_used = set_layers(data, area, c_air, nil, mcl_mapgen.nether.flat_floor, mcl_mapgen.nether.flat_ceiling, minp, maxp, lvm_used, pr) - end - -- Big lava seas by replacing air below a certain height if mcl_mapgen.lava then - lvm_used = set_layers(data, area, c_lava, c_air, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, minp, maxp, lvm_used, pr) + set_layers(vm_context, pr, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, c_lava, c_air) if c_nether then - lvm_used = set_layers(data, area, c_nether.lava, c_air, mcl_mapgen.nether.min, mcl_mapgen.nether.lava_max, minp, maxp, lvm_used, pr) - end - end - - vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") - local biomemap = vm_context.biomemap - - ----- Interactive block fixing section ----- - ----- The section to perform basic block overrides of the core mapgen generated world. ----- - - -- Snow and sand fixes. This code implements snow consistency - -- and fixes floating sand and cut plants. - -- A snowy grass block must be below a top snow or snow block at all times. - if minp.y <= mcl_mapgen.overworld.max and maxp.y >= mcl_mapgen.overworld.min then - -- v6 mapgen: - if v6 then - - --[[ Remove broken double plants caused by v6 weirdness. - v6 might break the bottom part of double plants because of how it works. - There are 3 possibilities: - 1) Jungle: Top part is placed on top of a jungle tree or fern (=v6 jungle grass). - This is because the schematic might be placed even if some nodes of it - could not be placed because the destination was already occupied. - TODO: A better fix for this would be if schematics could abort placement - altogether if ANY of their nodes could not be placed. - 2) Cavegen: Removes the bottom part, the upper part floats - 3) Mudflow: Same as 2) ]] - local plants = minetest.find_nodes_in_area(minp, maxp, "group:double_plant") - for n = 1, #plants do - local node = vm:get_node_at(plants[n]) - local is_top = minetest.get_item_group(node.name, "double_plant") == 2 - if is_top then - local p_pos = area:index(plants[n].x, plants[n].y-1, plants[n].z) - if p_pos then - node = vm:get_node_at({x=plants[n].x, y=plants[n].y-1, z=plants[n].z}) - local is_bottom = minetest.get_item_group(node.name, "double_plant") == 1 - if not is_bottom then - p_pos = area:index(plants[n].x, plants[n].y, plants[n].z) - data[p_pos] = c_air - lvm_used = true - end - end - end - end - - - -- Non-v6 mapgens: - else - -- Set param2 (=color) of grass blocks. - -- Clear snowy grass blocks without snow above to ensure consistency. - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"}) - - -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: - local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) - for n=1, #nodes do - local n = nodes[n] - local p_pos = area:index(n.x, n.y, n.z) - local p_pos_above = area:index(n.x, n.y+1, n.z) - --local p_pos_below = area:index(n.x, n.y-1, n.z) - local b_pos = aream:index(n.x, 0, n.z) - local bn = minetest.get_biome_name(biomemap[b_pos]) - if bn then - local biome = minetest.registered_biomes[bn] - if biome and biome._mcl_biome_type then - param2_data[p_pos] = biome._mcl_palette_index - vm_context.write_param2 = true - end - end - if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then - data[p_pos] = c_dirt_with_grass - lvm_used = true - end - end - - end - - -- Nether block fixes: - -- * Replace water with Nether lava. - -- * Replace stone, sand dirt in v6 so the Nether works in v6. - elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then - -- elseif emin.y <= mcl_mapgen.nether.max and emax.y >= mcl_mapgen.nether.min then - if c_nether then - if v6 then - -- local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - for n=1, #nodes do - local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) - if data[p_pos] == c_water then - data[p_pos] = c_nether.lava - lvm_used = true - elseif data[p_pos] == c_stone then - data[p_pos] = c_netherrack - lvm_used = true - elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then - data[p_pos] = c_soul_sand - lvm_used = true - end - end - else - -- local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"}) - local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) - for _, n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_nether.lava - end - end - end - - -- End block fixes: - -- * Replace water with end stone or air (depending on height). - -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. - -- * Generate spawn platform (End portal destination) - elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then - local nodes - if v6 then - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - -- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - else - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) - -- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"}) - end - if #nodes > 0 then - lvm_used = true - for _,n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_air - end - end - - -- Obsidian spawn platform - if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and - minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and - minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.end_.platform_pos.z then - - --local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)} - --local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2)} - - for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do - for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do - for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do - local p_pos = area:index(x, y, z) - if y == mcl_mapgen.end_.platform_pos.y then - data[p_pos] = c_obsidian - else - data[p_pos] = c_air - end - end - end - end - lvm_used = true + set_layers(vm_context, pr, mcl_mapgen.nether.min, mcl_mapgen.nether.lava_max, c_nether.lava, c_air) end end end - - - if not singlenode then - -- Generate special decorations - generate_underground_mushrooms(minp, maxp, blockseed) - generate_nether_decorations(minp, maxp, blockseed) - end - - vm_context.write = vm_context.write or lvm_used -end - -mcl_mapgen.register_mapgen_block_lvm(basic_safe, 1) +end, 1) local modpath = minetest.get_modpath(minetest.get_current_modname()) + dofile(modpath .. "/clay.lua") dofile(modpath .. "/tree_decoration.lua") dofile(modpath .. "/nether_wart.lua") - --- Nether Roof Light: -mcl_mapgen.register_mapgen_block_lvm(function(vm_context) - local minp = vm_context.minp - local miny = minp.y - if miny > mcl_mapgen.nether.max+127 then return end - local maxp = vm_context.maxp - local maxy = maxp.y - if maxy <= mcl_mapgen.nether.max then return end - local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z} - local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z} - vm_context.vm:set_lighting({day=15, night=15}, p1, p2) - vm_context.write = true -end, 999999999) - --- End Light: -mcl_mapgen.register_mapgen_block_lvm(function(vm_context) - local minp = vm_context.minp - local miny = minp.y - if miny > mcl_mapgen.end_.max then return end - local maxp = vm_context.maxp - local maxy = maxp.y - if maxy <= mcl_mapgen.end_.min then return end - local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.end_.min), z = minp.z} - local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.end_.max), z = maxp.z} - vm_context.vm:set_lighting({day=15, night=15}, p1, p2) - vm_context.write = true -end, 9999999999) +dofile(modpath .. "/light.lua") +if v6 then + dofile(modpath .. "/v6.lua") +elseif not singlenode then + dofile(modpath .. "/biomes.lua") +end +-- dofile(modpath .. "/nether.lua") diff --git a/mods/MAPGEN/mcl_mapgen_core/light.lua b/mods/MAPGEN/mcl_mapgen_core/light.lua new file mode 100644 index 000000000..adf5029b9 --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/light.lua @@ -0,0 +1,27 @@ +-- Nether Roof Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.nether.max+127 then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy <= mcl_mapgen.nether.max then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z} + vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.write = true +end, 999999999) + +-- End Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.end_.max then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy <= mcl_mapgen.end_.min then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.end_.min), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.end_.max), z = maxp.z} + vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.write = true +end, 9999999999) diff --git a/mods/MAPGEN/mcl_mapgen_core/nether.lua b/mods/MAPGEN/mcl_mapgen_core/nether.lua new file mode 100644 index 000000000..025232e5b --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/nether.lua @@ -0,0 +1,80 @@ + + -- Nether block fixes: + -- * Replace water with Nether lava. + -- * Replace stone, sand dirt in v6 so the Nether works in v6. + elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then + if c_nether then + if v6 then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + for n=1, #nodes do + local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) + if data[p_pos] == c_water then + data[p_pos] = c_nether.lava + lvm_used = true + elseif data[p_pos] == c_stone then + data[p_pos] = c_netherrack + lvm_used = true + elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then + data[p_pos] = c_soul_sand + lvm_used = true + end + end + else + local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_nether.lava + end + end + end + + -- End block fixes: + -- * Replace water with end stone or air (depending on height). + -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. + -- * Generate spawn platform (End portal destination) + elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then + local nodes + if v6 then + nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + else + nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) + end + if #nodes > 0 then + lvm_used = true + for _,n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_air + end + end + + -- Obsidian spawn platform + if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and + minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and + minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.end_.platform_pos.z then + + --local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)} + --local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2)} + + for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do + for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do + for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do + local p_pos = area:index(x, y, z) + if y == mcl_mapgen.end_.platform_pos.y then + data[p_pos] = c_obsidian + else + data[p_pos] = c_air + end + end + end + end + lvm_used = true + end + end + end + + + if not singlenode then + -- Generate special decorations + generate_underground_mushrooms(minp, maxp, blockseed) + generate_nether_decorations(minp, maxp, blockseed) + end + +end, 1) diff --git a/mods/MAPGEN/mcl_mapgen_core/v6.lua b/mods/MAPGEN/mcl_mapgen_core/v6.lua new file mode 100644 index 000000000..fb9ffcdbf --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/v6.lua @@ -0,0 +1,36 @@ +local c_air = minetest.CONTENT_AIR + +mcl_mapgen.register_on_generated(function(vm_context) + local minp, maxp = vm_context.minp, vm_context.maxp + if minp.y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end + local vm, data, area = vm_context.vm, vm_context.data, vm_context.area + + --[[ Remove broken double plants caused by v6 weirdness. + v6 might break the bottom part of double plants because of how it works. + There are 3 possibilities: + 1) Jungle: Top part is placed on top of a jungle tree or fern (=v6 jungle grass). + This is because the schematic might be placed even if some nodes of it + could not be placed because the destination was already occupied. + TODO: A better fix for this would be if schematics could abort placement + altogether if ANY of their nodes could not be placed. + 2) Cavegen: Removes the bottom part, the upper part floats + 3) Mudflow: Same as 2) ]] + local plants = minetest.find_nodes_in_area(minp, maxp, "group:double_plant") + for n = 1, #plants do + local node = vm:get_node_at(plants[n]) + local is_top = minetest.get_item_group(node.name, "double_plant") == 2 + if is_top then + local p_pos = area:index(plants[n].x, plants[n].y-1, plants[n].z) + if p_pos then + node = vm:get_node_at({x=plants[n].x, y=plants[n].y-1, z=plants[n].z}) + local is_bottom = minetest.get_item_group(node.name, "double_plant") == 1 + if not is_bottom then + p_pos = area:index(plants[n].x, plants[n].y, plants[n].z) + data[p_pos] = c_air + vm_context.write = true + end + end + end + end + +end, 999999999) From 7b47e4d12bae69fe69c3343b6ade8916b12dd8b4 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 04:44:05 +0400 Subject: [PATCH 20/22] Fix biomes 2/3 --- mods/CORE/mcl_mapgen/init.lua | 1 + mods/MAPGEN/mcl_mapgen_core/biomes.lua | 26 ++-- mods/MAPGEN/mcl_mapgen_core/init.lua | 101 +--------------- mods/MAPGEN/mcl_mapgen_core/nether.lua | 158 +++++++++++++++++++++---- 4 files changed, 151 insertions(+), 135 deletions(-) diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index 9a0fcf196..71442dbaf 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -264,6 +264,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed) end if #queue_unsafe_engine > 0 then + vm_context.minp, vm_context.maxp = minp, maxp for _, v in pairs(queue_unsafe_engine) do v.f(vm_context) end diff --git a/mods/MAPGEN/mcl_mapgen_core/biomes.lua b/mods/MAPGEN/mcl_mapgen_core/biomes.lua index 955c73a90..d50f4da56 100644 --- a/mods/MAPGEN/mcl_mapgen_core/biomes.lua +++ b/mods/MAPGEN/mcl_mapgen_core/biomes.lua @@ -4,14 +4,18 @@ local c_snow_block = minetest.get_content_id("mcl_core:snowblock") mcl_mapgen.register_on_generated(function(vm_context) local minp, maxp = vm_context.minp, vm_context.maxp - local min_y = minp.y - if min_y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end + local min_y, max_y = minp.y, maxp.y + if min_y > mcl_mapgen.overworld.max or max_y < mcl_mapgen.overworld.min then return end + vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer) vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") local param2_data = vm_context.param2_data local biomemap = vm_context.biomemap local vm, data, area = vm_context.vm, vm_context.data, vm_context.area + local min_x, min_z = minp.x, minp.z + local chunksize = max_y - min_y + 1 + ----- Interactive block fixing section ----- ----- The section to perform basic block overrides of the core mapgen generated world. ----- @@ -23,16 +27,16 @@ mcl_mapgen.register_on_generated(function(vm_context) -- Clear snowy grass blocks without snow above to ensure consistency. local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"}) - -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: - local aream = VoxelArea:new({MinEdge={x=minp.x, y=min_y, z=minp.z}, MaxEdge={x=maxp.x, y=min_y, z=maxp.z}}) for n=1, #nodes do - local n = nodes[n] - local p_pos = area:index(n.x, n.y, n.z) - local p_pos_above = area:index(n.x, n.y+1, n.z) - local b_pos = aream:index(n.x, min_y, n.z) - local bn = minetest.get_biome_name(biomemap[b_pos]) - if bn then - local biome = minetest.registered_biomes[bn] + local pos = nodes[n] + local x, y, z = pos.x, pos.y, pos.z + local p_pos = area:index(x, y, z) + local p_pos_above = area:index(x, y + 1, z) + local biomemap_offset = (z - min_z) * chunksize + x - min_x + 1 + local biome_id = biomemap[biomemap_offset] + local biome_name = minetest.get_biome_name(biome_id) + if biome_name then + local biome = minetest.registered_biomes[biome_name] if biome and biome._mcl_biome_type then param2_data[p_pos] = biome._mcl_palette_index vm_context.write_param2 = true diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 403282deb..73699db1f 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -65,7 +65,6 @@ local c_stone = minetest.get_content_id("mcl_core:stone") local c_dirt = minetest.get_content_id("mcl_core:dirt") local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") local c_sand = minetest.get_content_id("mcl_core:sand") ---local c_sandstone = minetest.get_content_id("mcl_core:sandstone") local c_void = minetest.get_content_id("mcl_core:void") local c_lava = minetest.get_content_id("mcl_core:lava_source") local c_water = minetest.get_content_id("mcl_core:water_source") @@ -1189,100 +1188,6 @@ function mcl_mapgen_core.generate_end_exit_portal(pos) portal_generated = true end --- Generate mushrooms in caves manually. --- Minetest's API does not support decorations in caves yet. :-( -local function generate_underground_mushrooms(minp, maxp, seed) - if not mcl_mushrooms then return end - - local pr_shroom = PseudoRandom(seed-24359) - -- Generate rare underground mushrooms - -- TODO: Make them appear in groups, use Perlin noise - local min, max = mcl_mapgen.overworld.lava_max + 4, 0 - if minp.y > max or maxp.y < min then - return - end - - local bpos - local stone = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_core:stone", "mcl_core:dirt", "mcl_core:mycelium", "mcl_core:podzol", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:stone_with_iron", "mcl_core:stone_with_gold"}) - - for n = 1, #stone do - bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z } - - local l = minetest.get_node_light(bpos, 0.5) - if bpos.y >= min and bpos.y <= max and l and l <= 12 and pr_shroom:next(1,1000) < 4 then - if pr_shroom:next(1,2) == 1 then - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) - else - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) - end - end - end -end - --- Generate Nether decorations manually: Eternal fire, mushrooms --- Minetest's API does not support decorations in caves yet. :-( -local function generate_nether_decorations(minp, maxp, seed) - if c_nether == nil then - return - end - - local pr_nether = PseudoRandom(seed+667) - - if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then - return - end - - minetest.log("action", "[mcl_mapgen_core] Nether decorations " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp)) - - -- TODO: Generate everything based on Perlin noise instead of PseudoRandom - - local bpos - local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"}) - local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"}) - local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"}) - - -- Helper function to spawn “fake” decoration - local function special_deco(nodes, spawn_func) - for n = 1, #nodes do - bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z } - - spawn_func(bpos) - end - - end - - -- Eternal fire on netherrack - special_deco(rack, function(bpos) - -- Eternal fire on netherrack - if pr_nether:next(1,100) <= 3 then - minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) - end - end) - - -- Eternal fire on magma cubes - special_deco(magma, function(bpos) - if pr_nether:next(1,150) == 1 then - minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) - end - end) - - -- Mushrooms on netherrack - -- Note: Spawned *after* the fire because of light level checks - if mcl_mushrooms then - special_deco(rack, function(bpos) - local l = minetest.get_node_light(bpos, 0.5) - if bpos.y > mcl_mapgen.nether.lava_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then - -- TODO: Make mushrooms appear in groups, use Perlin noise - if pr_nether:next(1,2) == 1 then - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) - else - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) - end - end - end) - end -end - -- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc. -- Also perform some basic node replacements. @@ -1334,7 +1239,7 @@ end -- -- returns true if any node was set and lvm_used otherwise local function set_layers(vm_context, pr, min, max, content_id, check) - local minp, maxp = vm_context.minp, vm_context.maxp + local minp, maxp, data, area = vm_context.minp, vm_context.maxp, vm_context.data, vm_context.area if (maxp.y >= min and minp.y <= max) then for y = math.max(min, minp.y), math.min(max, maxp.y) do for x = minp.x, maxp.x do @@ -1342,10 +1247,10 @@ local function set_layers(vm_context, pr, min, max, content_id, check) local p_pos = vm_context.area:index(x, y, z) if check then if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then - vm_context.data[p_pos] = content_id + data[p_pos] = content_id vm_context.write = true elseif check == data[p_pos] then - vm_context.data[p_pos] = content_id + data[p_pos] = content_id vm_context.write = true end else diff --git a/mods/MAPGEN/mcl_mapgen_core/nether.lua b/mods/MAPGEN/mcl_mapgen_core/nether.lua index 025232e5b..c2c1524e3 100644 --- a/mods/MAPGEN/mcl_mapgen_core/nether.lua +++ b/mods/MAPGEN/mcl_mapgen_core/nether.lua @@ -1,31 +1,137 @@ +local v6 = mcl_mapgen.v6 - -- Nether block fixes: - -- * Replace water with Nether lava. - -- * Replace stone, sand dirt in v6 so the Nether works in v6. - elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then - if c_nether then - if v6 then - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - for n=1, #nodes do - local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) - if data[p_pos] == c_water then - data[p_pos] = c_nether.lava - lvm_used = true - elseif data[p_pos] == c_stone then - data[p_pos] = c_netherrack - lvm_used = true - elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then - data[p_pos] = c_soul_sand - lvm_used = true - end - end +local mcl_mushrooms = minetest.get_modpath("mcl_mushrooms") + +local c_nether = minetest.get_modpath("mcl_nether") and { + soul_sand = minetest.get_content_id("mcl_nether:soul_sand"), + netherrack = minetest.get_content_id("mcl_nether:netherrack"), + lava = minetest.get_content_id("mcl_nether:nether_lava_source") +} + +-- Generate mushrooms in caves manually. +-- Minetest's API does not support decorations in caves yet. :-( +local function generate_underground_mushrooms(minp, maxp, seed) + if not mcl_mushrooms then return end + + local pr_shroom = PseudoRandom(seed-24359) + -- Generate rare underground mushrooms + -- TODO: Make them appear in groups, use Perlin noise + local min, max = mcl_mapgen.overworld.lava_max + 4, 0 + if minp.y > max or maxp.y < min then + return + end + + local bpos + local stone = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_core:stone", "mcl_core:dirt", "mcl_core:mycelium", "mcl_core:podzol", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:stone_with_iron", "mcl_core:stone_with_gold"}) + + for n = 1, #stone do + bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z } + + local l = minetest.get_node_light(bpos, 0.5) + if bpos.y >= min and bpos.y <= max and l and l <= 12 and pr_shroom:next(1,1000) < 4 then + if pr_shroom:next(1,2) == 1 then + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) + else + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) + end + end + end +end + +-- Generate Nether decorations manually: Eternal fire, mushrooms +-- Minetest's API does not support decorations in caves yet. :-( +local function generate_nether_decorations(minp, maxp, seed) + if c_nether == nil then + return + end + + local pr_nether = PseudoRandom(seed+667) + + if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then + return + end + + minetest.log("action", "[mcl_mapgen_core] Nether decorations " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp)) + + -- TODO: Generate everything based on Perlin noise instead of PseudoRandom + + local bpos + local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"}) + local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"}) + local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"}) + + -- Helper function to spawn “fake” decoration + local function special_deco(nodes, spawn_func) + for n = 1, #nodes do + bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z } + + spawn_func(bpos) + end + + end + + -- Eternal fire on netherrack + special_deco(rack, function(bpos) + -- Eternal fire on netherrack + if pr_nether:next(1,100) <= 3 then + minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) + end + end) + + -- Eternal fire on magma cubes + special_deco(magma, function(bpos) + if pr_nether:next(1,150) == 1 then + minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) + end + end) + + -- Mushrooms on netherrack + -- Note: Spawned *after* the fire because of light level checks + if mcl_mushrooms then + special_deco(rack, function(bpos) + local l = minetest.get_node_light(bpos, 0.5) + if bpos.y > mcl_mapgen.nether.lava_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then + -- TODO: Make mushrooms appear in groups, use Perlin noise + if pr_nether:next(1,2) == 1 then + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) else - local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) - for _, n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_nether.lava - end + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) end end + end) + end +end + +mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) + local min_y, max_y = minp.y, maxp.y + + -- Nether block fixes: + -- * Replace water with Nether lava. + -- * Replace stone, sand dirt in v6 so the Nether works in v6. + if min_y <= mcl_mapgen.nether.max and max_y >= mcl_mapgen.nether.min then + if c_nether then + if v6 then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + for n=1, #nodes do + local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) + if data[p_pos] == c_water then + data[p_pos] = c_nether.lava + lvm_used = true + elseif data[p_pos] == c_stone then + data[p_pos] = c_netherrack + lvm_used = true + elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then + data[p_pos] = c_soul_sand + lvm_used = true + end + end + else + local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_nether.lava + end + end + end -- End block fixes: -- * Replace water with end stone or air (depending on height). @@ -73,8 +179,8 @@ if not singlenode then -- Generate special decorations - generate_underground_mushrooms(minp, maxp, blockseed) - generate_nether_decorations(minp, maxp, blockseed) + generate_underground_mushrooms(minp, maxp, chunkseed) + generate_nether_decorations(minp, maxp, chunkseed) end end, 1) From e023b9687799d1af3de9f4007c3cdf66b6d88116 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 06:33:03 +0400 Subject: [PATCH 21/22] Fix biomes 3/3 --- mods/MAPGEN/mcl_mapgen_core/init.lua | 8 +- mods/MAPGEN/mcl_mapgen_core/light.lua | 16 +++- mods/MAPGEN/mcl_mapgen_core/nether.lua | 105 ++++++------------------- mods/MAPGEN/mcl_mapgen_core/v6.lua | 13 +++ 4 files changed, 56 insertions(+), 86 deletions(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 73699db1f..93c1f23bb 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -60,14 +60,10 @@ local flat = mcl_mapgen.flat -- Content IDs local c_bedrock = minetest.get_content_id("mcl_core:bedrock") -local c_obsidian = minetest.get_content_id("mcl_core:obsidian") -local c_stone = minetest.get_content_id("mcl_core:stone") local c_dirt = minetest.get_content_id("mcl_core:dirt") local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") -local c_sand = minetest.get_content_id("mcl_core:sand") local c_void = minetest.get_content_id("mcl_core:void") local c_lava = minetest.get_content_id("mcl_core:lava_source") -local c_water = minetest.get_content_id("mcl_core:water_source") local c_nether = nil if minetest.get_modpath("mcl_nether") then @@ -1328,4 +1324,6 @@ if v6 then elseif not singlenode then dofile(modpath .. "/biomes.lua") end --- dofile(modpath .. "/nether.lua") +if not singlenode and c_nether then + dofile(modpath .. "/nether.lua") +end diff --git a/mods/MAPGEN/mcl_mapgen_core/light.lua b/mods/MAPGEN/mcl_mapgen_core/light.lua index adf5029b9..a0b503352 100644 --- a/mods/MAPGEN/mcl_mapgen_core/light.lua +++ b/mods/MAPGEN/mcl_mapgen_core/light.lua @@ -1,3 +1,17 @@ +-- Nether Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.nether.max then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy < mcl_mapgen.nether.min then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.min), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max), z = maxp.z} + vm_context.vm:set_lighting({day = 3, night = 4}, p1, p2) + vm_context.write = true +end, 999999999) + -- Nether Roof Light: mcl_mapgen.register_mapgen_block_lvm(function(vm_context) local minp = vm_context.minp @@ -8,7 +22,7 @@ mcl_mapgen.register_mapgen_block_lvm(function(vm_context) if maxy <= mcl_mapgen.nether.max then return end local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z} local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z} - vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.vm:set_lighting({day = 15, night = 15}, p1, p2) vm_context.write = true end, 999999999) diff --git a/mods/MAPGEN/mcl_mapgen_core/nether.lua b/mods/MAPGEN/mcl_mapgen_core/nether.lua index c2c1524e3..1b05d32bf 100644 --- a/mods/MAPGEN/mcl_mapgen_core/nether.lua +++ b/mods/MAPGEN/mcl_mapgen_core/nether.lua @@ -2,11 +2,13 @@ local v6 = mcl_mapgen.v6 local mcl_mushrooms = minetest.get_modpath("mcl_mushrooms") -local c_nether = minetest.get_modpath("mcl_nether") and { - soul_sand = minetest.get_content_id("mcl_nether:soul_sand"), - netherrack = minetest.get_content_id("mcl_nether:netherrack"), - lava = minetest.get_content_id("mcl_nether:nether_lava_source") -} +local c_water = minetest.get_content_id("mcl_core:water_source") +local c_stone = minetest.get_content_id("mcl_core:stone") +local c_sand = minetest.get_content_id("mcl_core:sand") + +local c_soul_sand = minetest.get_content_id("mcl_nether:soul_sand") +local c_netherrack = minetest.get_content_id("mcl_nether:netherrack") +local c_nether_lava = minetest.get_content_id("mcl_nether:nether_lava_source") -- Generate mushrooms in caves manually. -- Minetest's API does not support decorations in caves yet. :-( @@ -41,10 +43,6 @@ end -- Generate Nether decorations manually: Eternal fire, mushrooms -- Minetest's API does not support decorations in caves yet. :-( local function generate_nether_decorations(minp, maxp, seed) - if c_nether == nil then - return - end - local pr_nether = PseudoRandom(seed+667) if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then @@ -108,79 +106,26 @@ mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) -- Nether block fixes: -- * Replace water with Nether lava. -- * Replace stone, sand dirt in v6 so the Nether works in v6. - if min_y <= mcl_mapgen.nether.max and max_y >= mcl_mapgen.nether.min then - if c_nether then - if v6 then - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - for n=1, #nodes do - local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) - if data[p_pos] == c_water then - data[p_pos] = c_nether.lava - lvm_used = true - elseif data[p_pos] == c_stone then - data[p_pos] = c_netherrack - lvm_used = true - elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then - data[p_pos] = c_soul_sand - lvm_used = true - end - end - else - local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) - for _, n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_nether.lava + if min_y > mcl_mapgen.nether.max or max_y < mcl_mapgen.nether.min then return end + if v6 then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + if #nodes < 1 then return end + vm_context.write = true + local data = vm_context.data + local area = vm_context.area + for n = 1, #nodes do + local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) + if data[p_pos] == c_water then + data[p_pos] = c_nether_lava + elseif data[p_pos] == c_stone then + data[p_pos] = c_netherrack + elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then + data[p_pos] = c_soul_sand end end - end - - -- End block fixes: - -- * Replace water with end stone or air (depending on height). - -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. - -- * Generate spawn platform (End portal destination) - elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then - local nodes - if v6 then - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - else - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) - end - if #nodes > 0 then - lvm_used = true - for _,n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_air - end - end - - -- Obsidian spawn platform - if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and - minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and - minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.end_.platform_pos.z then - - --local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)} - --local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2)} - - for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do - for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do - for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do - local p_pos = area:index(x, y, z) - if y == mcl_mapgen.end_.platform_pos.y then - data[p_pos] = c_obsidian - else - data[p_pos] = c_air - end - end - end - end - lvm_used = true - end - end - end - - - if not singlenode then - -- Generate special decorations - generate_underground_mushrooms(minp, maxp, chunkseed) - generate_nether_decorations(minp, maxp, chunkseed) + else end + generate_underground_mushrooms(minp, maxp, seed) + generate_nether_decorations(minp, maxp, seed) end, 1) diff --git a/mods/MAPGEN/mcl_mapgen_core/v6.lua b/mods/MAPGEN/mcl_mapgen_core/v6.lua index fb9ffcdbf..19fd44647 100644 --- a/mods/MAPGEN/mcl_mapgen_core/v6.lua +++ b/mods/MAPGEN/mcl_mapgen_core/v6.lua @@ -2,6 +2,19 @@ local c_air = minetest.CONTENT_AIR mcl_mapgen.register_on_generated(function(vm_context) local minp, maxp = vm_context.minp, vm_context.maxp + + if minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + if #nodes > 0 then + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_air + end + end + vm_context.write = true + return + end + + if minp.y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end local vm, data, area = vm_context.vm, vm_context.data, vm_context.area From e10715aa590a98782b21927d33192bcf22af09bd Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 06:36:19 +0400 Subject: [PATCH 22/22] Fix mapgen API.md --- mods/CORE/mcl_mapgen/API.md | 151 ++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/mods/CORE/mcl_mapgen/API.md b/mods/CORE/mcl_mapgen/API.md index 23365b357..d489b3ad5 100644 --- a/mods/CORE/mcl_mapgen/API.md +++ b/mods/CORE/mcl_mapgen/API.md @@ -1,101 +1,120 @@ # mcl_mapgen -============ +------------ Helps to avoid problems caused by 'chunk-in-shell' feature of mapgen.cpp. + It also queues your generators to run them in proper order: ### mcl_mapgen.register_on_generated(lvm_callback_function, order_number) -========================================================================= +------------------------------------------------------------------------- Replacement of engine API function `minetest.register_on_generated(function(vm_context))` + It is still unsafe. Cavegen part can and will overwrite outer 1-block layer of the chunk which is expected to be generated. + Nodes marked as `is_ground_content` could be overwritten. Air and water are usually 'ground content' too. For Minetest 5.4 it doesn't recommended to place blocks within lvm callback function. + See https://git.minetest.land/MineClone2/MineClone2/issues/1395 - `lvm_callback_function`: chunk callback LVM function definition: - `function(vm_context)`: - `vm_context` will pass into next lvm callback function from the queue! - `vm_context`: a table which already contains some LVM data as the fields, and some of them can be added in your lvm callback function: - `vm`: curent voxel manipulator object itself; - `chunkseed`: seed of this mapchunk; - `minp` & `maxp`: minimum and maximum chunk position; - `emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT; - `area`: voxel area, can be helpful to access data; - `data`: LVM buffer data array, data loads into it before the callbacks; - `write`: set it to true in your lvm callback functionm, if you changed `data` and want to write it; - `param2_data`: LVM buffer data array of `param2`, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself: - `vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer)` - `write_param2`: set it to true in your lvm callback function, if you used `param2_data` and want to write it; - `light`: LVM buffer data array of light, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself: - `vm_context.light = vm_context.light or vm_context.vm.get_light_data(vm_context.lvm_light_buffer)` - `write_light`: set it to true in your lvm callback function, if you used `light` and want to write it; - `lvm_param2_buffer`: static `param2` buffer pointer, used to load `param2_data` array; - `shadow`: set it to false to disable shadow propagation; - `heightmap`: mapgen object contanting y coordinates of ground level, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')` - `biomemap`: mapgen object contanting biome IDs of nodes, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')` - `heatmap`: mapgen object contanting temperature values of nodes, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')` - `humiditymap`: mapgen object contanting humidity values of nodes, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')` - `gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')` - `order_number` (optional): the less, the earlier, - e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + + * `lvm_callback_function`: chunk callback LVM function definition: + * `function(vm_context)`: + * `vm_context` will pass into next lvm callback function from the queue! + * `vm_context`: a table which already contains some LVM data as the fields, and some of them can be added in your lvm callback function: + * `vm`: curent voxel manipulator object itself; + * `chunkseed`: seed of this mapchunk; + * `minp` & `maxp`: minimum and maximum chunk position; + * `emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT; + * `area`: voxel area, can be helpful to access data; + * `data`: LVM buffer data array, data loads into it before the callbacks; + * `write`: set it to true in your lvm callback functionm, if you changed `data` and want to write it; + * `param2_data`: LVM buffer data array of `param2`, *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - you load it yourself: + * `vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer)` + * `write_param2`: set it to true in your lvm callback function, if you used `param2_data` and want to write it; + * `light`: LVM buffer data array of light, *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - you load it yourself: + * `vm_context.light = vm_context.light or vm_context.vm.get_light_data(vm_context.lvm_light_buffer)` + * `write_light`: set it to true in your lvm callback function, if you used `light` and want to write it; + * `lvm_param2_buffer`: static `param2` buffer pointer, used to load `param2_data` array; + * `shadow`: set it to false to disable shadow propagation; + * `heightmap`: mapgen object contanting y coordinates of ground level, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')` + * `biomemap`: mapgen object contanting biome IDs of nodes, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')` + * `heatmap`: mapgen object contanting temperature values of nodes, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')` + * `humiditymap`: mapgen object contanting humidity values of nodes, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')` + * `gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')` + * `order_number` (optional): the less, the earlier, + * e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` ### mcl_mapgen.register_mapgen_block_lvm(lvm_callback_function, order_number) -============================================================================= +----------------------------------------------------------------------------- Registers lvm callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished. + `vm_context` passes into lvm callback function. - `lvm_callback_function`: the block callback LVM function definition - same as for chunks - see definition example above; - `order_number` (optional): the less, the earlier, - e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + * `lvm_callback_function`: the block callback LVM function definition - same as for chunks - see definition example above; + * `order_number` (optional): the less, the earlier, + * e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` ### mcl_mapgen.register_mapgen_block(node_callback_function, order_number) -========================================================================== +-------------------------------------------------------------------------- Registers node_callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished. - `node_callback_function`: node callback function definition: - `function(minp, maxp, seed)`: - `minp` & `maxp`: minimum and maximum block position; - `seed`: seed of this mapblock; - `order_number` (optional): the less, the earlier, - e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + * `node_callback_function`: node callback function definition: + * `function(minp, maxp, seed)`: + * `minp` & `maxp`: minimum and maximum block position; + * `seed`: seed of this mapblock; + * `order_number` (optional): the less, the earlier, + * e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` ### mcl_mapgen.register_mapgen(callback_function, order_number) -==================================================================== +--------------------------------------------------------------- Registers callback function to be called when current chunk generation is REALLY 100% finished. + For LVM it's the most frustrating function from this mod. + It can't provide you access to mapgen objects. They are probably gone long ago. + Don't use it for accessing mapgen objects please. + To use VM you have to run `vm_context.vm = mcl_mapgen.get_voxel_manip(vm_context.emin, vm_context.emax)`. -Set - `callback_function`: callback function definition: - `function(minp, maxp, seed, vm_context)`: - `minp` & `maxp`: minimum and maximum block position; - `seed`: seed of this mapblock; - `vm_context`: a table - see description above. - `order_number` (optional): the less, the earlier. + * `callback_function`: callback function definition: + * `function(minp, maxp, seed, vm_context)`: + * `minp` & `maxp`: minimum and maximum block position; + * `seed`: seed of this mapblock; + * `vm_context`: a table - see description above. + * `order_number` (optional): the less, the earlier. ### mcl_mapgen.register_mapgen_lvm(lvm_callback_function, order_number) -======================================================================= +----------------------------------------------------------------------- Registers lvm callback function to be called when current chunk generation is REALLY 100% finished. + It's the most frustrating function from this mod. It can't provide you access to mapgen objects. They are probably gone long ago. + Don't use it for accessing mapgen objects please. + `vm_context` passes into lvm callback function. - `lvm_callback_function`: the block callback LVM function definition - same as above; - `order_number` (optional): the less, the earlier. + * `lvm_callback_function`: the block callback LVM function definition - same as above; + * `order_number` (optional): the less, the earlier. ### mcl_mapgen.get_far_node(pos) -================================ +-------------------------------- Returns node if it is generated, otherwise returns `{name = "ignore"}`. -## Constants: +### mcl_mapgen.clamp_to_chunk(x, size) +-------------------------------------- +Returns new `x`, slighty tuned to make structure of size `size` be within single chunk side of 80 nodes. -* `mcl_mapgen.EDGE_MIN`, `mcl_mapgen.EDGE_MAX` - world edges, min & max. -* `mcl_mapgen.seed`, `mcl_mapgen.name` - mapgen seed & name. -* `mcl_mapgen.v6`, `mcl_mapgen.superflat`, `mcl_mapgen.singlenode` - is mapgen v6, superflat, singlenode. -* `mcl_mapgen.normal` is mapgen normal (not superflat or singlenode). +### function mcl_mapgen.get_chunk_beginning(x) +---------------------------------------------- +Returns chunk beginning of `x`. It is the same as `minp.axis` for per-chunk callbacks, but we don't always have `minp`. + +## Constants: + * `mcl_mapgen.EDGE_MIN`, `mcl_mapgen.EDGE_MAX` - world edges, min & max. + * `mcl_mapgen.seed`, `mcl_mapgen.name` - mapgen seed & name. + * `mcl_mapgen.v6`, `mcl_mapgen.superflat`, `mcl_mapgen.singlenode` - is mapgen v6, superflat, singlenode. + * `mcl_mapgen.normal` is mapgen normal (not superflat or singlenode).