Merge branch 'master' into dyable-leather-armor

This commit is contained in:
AFCMS 2021-03-29 18:50:52 +02:00
commit d7ae8c62db
19 changed files with 305 additions and 228 deletions

View File

@ -175,3 +175,86 @@ minetest.craftitemdef_default.stack_max = 64
-- Set random seed for all other mods (Remember to make sure no other mod calls this function) -- Set random seed for all other mods (Remember to make sure no other mod calls this function)
math.randomseed(os.time()) math.randomseed(os.time())
local chunks = {} -- intervals of chunks generated
function mcl_vars.add_chunk(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
local prev
for i, d in pairs(chunks) do
if n <= d[2] then -- we've found it
if (n == d[2]) or (n >= d[1]) then return end -- already here
if n == d[1]-1 then -- right before:
if prev and (prev[2] == n-1) then
prev[2] = d[2]
table.remove(chunks, i)
return
end
d[1] = n
return
end
if prev and (prev[2] == n-1) then --join to previous
prev[2] = n
return
end
table.insert(chunks, i, {n, n}) -- insert new interval before i
return
end
prev = d
end
chunks[#chunks+1] = {n, n}
end
function mcl_vars.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
for i, d in pairs(chunks) do
if n <= d[2] then
return (n >= d[1])
end
end
return false
end
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does.
-- p: Position, if it's wrong, {name="error"} node will return.
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
--
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
function mcl_vars.get_node(p, force, us_timeout)
-- check initial circumstances
if not p or not p.x or not p.y or not p.z then return {name="error"} end
-- try common way
local node = minetest.get_node(p)
if node.name ~= "ignore" then
return node
end
-- copy table to get sure it won't changed by other threads
local pos = {x=p.x,y=p.y,z=p.z}
-- try LVM
minetest.get_voxel_manip():read_from_map(pos, pos)
node = minetest.get_node(pos)
if node.name ~= "ignore" or not force then
return node
end
-- all ways failed - need to emerge (or forceload if generated)
local us_timeout = us_timeout or 244
if mcl_vars.is_generated(pos) then
minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!")
minetest.forceload_block(pos)
else
minetest.emerge_area(pos, pos)
end
local t = minetest.get_us_time()
node = minetest.get_node(pos)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
node = minetest.get_node(pos)
end
return node
-- it still can return "ignore", LOL, even if force = true, but only after time out
end

View File

@ -1,3 +1,7 @@
local has_awards = minetest.get_modpath("awards")
mcl_item_entity = {}
--basic settings --basic settings
local item_drop_settings = {} --settings table local item_drop_settings = {} --settings table
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
@ -16,16 +20,33 @@ local get_gravity = function()
return tonumber(minetest.settings:get("movement_gravity")) or 9.81 return tonumber(minetest.settings:get("movement_gravity")) or 9.81
end end
local registered_pickup_achievement = {}
--TODO: remove limitation of 1 award per itemname
function mcl_item_entity.register_pickup_achievement(itemname, award)
if not has_awards then
minetest.log("warning", "[mcl_item_entity] Trying to register pickup achievement ["..award.."] for ["..itemname.."] while awards missing")
elseif registered_pickup_achievement[itemname] then
minetest.log("error", "[mcl_item_entity] Trying to register already existing pickup achievement ["..award.."] for ["..itemname.."]")
else
registered_pickup_achievement[itemname] = award
end
end
mcl_item_entity.register_pickup_achievement("tree", "mcl:mineWood")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:blaze_rod", "mcl:blazeRod")
mcl_item_entity.register_pickup_achievement("mcl_mobitems:leather", "mcl:killCow")
mcl_item_entity.register_pickup_achievement("mcl_core:diamond", "mcl:diamonds")
local check_pickup_achievements = function(object, player) local check_pickup_achievements = function(object, player)
local itemname = ItemStack(object:get_luaentity().itemstring):get_name() if has_awards then
if minetest.get_item_group(itemname, "tree") ~= 0 then local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
awards.unlock(player:get_player_name(), "mcl:mineWood") local playername = player:get_player_name()
elseif itemname == "mcl_mobitems:blaze_rod" then for name,award in pairs(registered_pickup_achievement) do
awards.unlock(player:get_player_name(), "mcl:blazeRod") if itemname == name or minetest.get_item_group(itemname, name) ~= 0 then
elseif itemname == "mcl_mobitems:leather" then awards.unlock(playername, award)
awards.unlock(player:get_player_name(), "mcl:killCow") end
elseif itemname == "mcl_core:diamond" then end
awards.unlock(player:get_player_name(), "mcl:diamonds")
end end
end end

View File

@ -238,3 +238,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
awards.show_to(name, name, nil, false) awards.show_to(name, name, nil, false)
end end
end) end)
awards.register_achievement("mcl:stoneAge", {
title = S("Stone Age"),
description = S("Mine a stone with new pickaxe."),
icon = "default_cobble.png",
})
awards.register_achievement("mcl:hotStuff", {
title = S("Hot Stuff"),
description = S("Put lava in a bucket."),
icon = "bucket_lava.png",
})
awards.register_achievement("mcl:obsidian", {
title = S("Ice Bucket Challenge"),
description = S("Obtain an obsidian block."),
icon = "default_obsidian.png",
})

View File

@ -89,6 +89,7 @@ function mcl_beds.register_bed(name, def)
selection_box = selection_box_bottom, selection_box = selection_box_bottom,
collision_box = collision_box_bottom, collision_box = collision_box_bottom,
drop = "", drop = "",
node_placement_prediction = "",
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under local under = pointed_thing.under

View File

@ -5,17 +5,17 @@ Add an API to register buckets to mcl
Register a new liquid Register a new liquid
Accept folowing params: Accept folowing params:
* source_place = a string or function. * source_place: a string or function.
* string: name of the node to place * string: name of the node to place
* function(pos): will returns name of the node to place with pos being the placement position * function(pos): will returns name of the node to place with pos being the placement position
* source_take = table of liquid source node names to take * source_take: table of liquid source node names to take
* itemname = itemstring of the new bucket item (or nil if liquid is not takeable) * itemname: itemstring of the new bucket item (or nil if liquid is not takeable)
* inventory_image = texture of the new bucket item (ignored if itemname == nil) * inventory_image: texture of the new bucket item (ignored if itemname == nil)
* name = user-visible bucket description * name: user-visible bucket description
* longdesc = long explanatory description (for help) * longdesc: long explanatory description (for help)
* usagehelp = short usage explanation (for help) * usagehelp: short usage explanation (for help)
* tt_help = very short tooltip help * tt_help: very short tooltip help
* extra_check(pos, placer) = optional function(pos) which can returns false to avoid placing the liquid. Placer is object/player who is placing the liquid, can be nil. * extra_check(pos, placer): (optional) function(pos) which can returns false to avoid placing the liquid. Placer is object/player who is placing the liquid, can be nil.
* groups = optional list of item groups * groups: optional list of item groups
This function can be called from any mod (which depends on this one) This function can be called from any mod (which depends on this one)

View File

@ -207,6 +207,9 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
-- Fill bucket, but not in Creative Mode -- Fill bucket, but not in Creative Mode
if not minetest.is_creative_enabled(user:get_player_name()) then if not minetest.is_creative_enabled(user:get_player_name()) then
new_bucket = ItemStack({name = liquiddef.itemname}) new_bucket = ItemStack({name = liquiddef.itemname})
if liquiddef.itemname == "mcl_buckets:bucket_lava" and awards and awards.unlock and user and user:is_player() then
awards.unlock(user:get_player_name(), "mcl:hotStuff")
end
end end
minetest.add_node(pointed_thing.under, {name="air"}) minetest.add_node(pointed_thing.under, {name="air"})

View File

@ -33,6 +33,11 @@ minetest.register_node("mcl_core:stone", {
_mcl_blast_resistance = 6, _mcl_blast_resistance = 6,
_mcl_hardness = 1.5, _mcl_hardness = 1.5,
_mcl_silk_touch_drop = true, _mcl_silk_touch_drop = true,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if awards and awards.unlock and digger and digger:is_player() then
awards.unlock(digger:get_player_name(), "mcl:stoneAge")
end
end,
}) })
minetest.register_node("mcl_core:stone_with_coal", { minetest.register_node("mcl_core:stone_with_coal", {
@ -814,6 +819,11 @@ minetest.register_node("mcl_core:obsidian", {
groups = {pickaxey=5, building_block=1, material_stone=1}, groups = {pickaxey=5, building_block=1, material_stone=1},
_mcl_blast_resistance = 1200, _mcl_blast_resistance = 1200,
_mcl_hardness = 50, _mcl_hardness = 50,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if awards and awards.unlock and digger and digger:is_player() then
awards.unlock(digger:get_player_name(), "mcl:obsidian")
end
end,
}) })
minetest.register_node("mcl_core:ice", { minetest.register_node("mcl_core:ice", {

View File

@ -0,0 +1,6 @@
# mcl_crafting_table
Add a node which allow players to craft more complex things.
## mcl_crafting_table.show_crafting_form(player)
Show the crafting form to a player.
Used in the node registration, but can be used by external mods.

View File

@ -66,12 +66,7 @@ minetest.register_on_shutdown(function()
storage:set_string("nether_exits_keys", minetest.serialize(keys)) storage:set_string("nether_exits_keys", minetest.serialize(keys))
end) end)
mcl_portals.get_node = function(pos) local get_node = mcl_vars.get_node
if mcl_mapgen_core and mcl_mapgen_core.get_node then
mcl_portals.get_node = mcl_mapgen_core.get_node
end
return minetest.get_node(pos)
end
local set_node = minetest.set_node local set_node = minetest.set_node
local registered_nodes = minetest.registered_nodes local registered_nodes = minetest.registered_nodes
local is_protected = minetest.is_protected local is_protected = minetest.is_protected
@ -97,7 +92,6 @@ local limits = {
-- Incoming verification performed: two nodes must be portal nodes, and an obsidian below them. -- Incoming verification performed: two nodes must be portal nodes, and an obsidian below them.
-- If the verification passes - position adds to the table and saves to mod storage on exit. -- If the verification passes - position adds to the table and saves to mod storage on exit.
local function add_exit(p) local function add_exit(p)
local get_node = mcl_portals.get_node
if not p or not p.y or not p.z or not p.x then return end if not p or not p.y or not p.z or not p.x then return end
local x, y, z = floor(p.x), floor(p.y), floor(p.z) local x, y, z = floor(p.x), floor(p.y), floor(p.z)
local p = {x = x, y = y, z = z} local p = {x = x, y = y, z = z}
@ -109,7 +103,7 @@ local function add_exit(p)
local e = exits[k] local e = exits[k]
for i = 1, #e do for i = 1, #e do
local t = e[i] local t = e[i]
if t.x == p.x and t.y == p.y and t.z == p.z then if t and t.x == p.x and t.y == p.y and t.z == p.z then
return return
end end
end end
@ -202,7 +196,6 @@ local function destroy_nether_portal(pos, node)
local nn, orientation = node.name, node.param2 local nn, orientation = node.name, node.param2
local obsidian = nn == OBSIDIAN local obsidian = nn == OBSIDIAN
local get_node = mcl_portals.get_node
local check_remove = function(pos, orientation) local check_remove = function(pos, orientation)
local node = get_node(pos) local node = get_node(pos)
if node and (node.name == PORTAL and (orientation == nil or (node.param2 == orientation))) then if node and (node.name == PORTAL and (orientation == nil or (node.param2 == orientation))) then
@ -285,12 +278,14 @@ minetest.register_node(PORTAL, {
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
}) })
local function light_frame(x1, y1, z1, x2, y2, z2, name) local function light_frame(x1, y1, z1, x2, y2, z2, name, node, node_frame)
local orientation = 0 local orientation = 0
if x1 == x2 then if x1 == x2 then
orientation = 1 orientation = 1
end end
local pos = {} local pos = {}
local node = node or {name = PORTAL, param2 = orientation}
local node_frame = node_frame or {name = OBSIDIAN}
for x = x1 - 1 + orientation, x2 + 1 - orientation do for x = x1 - 1 + orientation, x2 + 1 - orientation do
pos.x = x pos.x = x
for z = z1 - orientation, z2 + orientation do for z = z1 - orientation, z2 + orientation do
@ -299,9 +294,9 @@ local function light_frame(x1, y1, z1, x2, y2, z2, name)
pos.y = y pos.y = y
local frame = (x < x1) or (x > x2) or (y < y1) or (y > y2) or (z < z1) or (z > z2) local frame = (x < x1) or (x > x2) or (y < y1) or (y > y2) or (z < z1) or (z > z2)
if frame then if frame then
set_node(pos, {name = OBSIDIAN}) set_node(pos, node_frame)
else else
set_node(pos, {name = PORTAL, param2 = orientation}) set_node(pos, node)
add_exit({x=pos.x, y=pos.y-1, z=pos.z}) add_exit({x=pos.x, y=pos.y-1, z=pos.z})
end end
end end
@ -310,12 +305,13 @@ local function light_frame(x1, y1, z1, x2, y2, z2, name)
end end
--Build arrival portal --Build arrival portal
function build_nether_portal(pos, width, height, orientation, name) function build_nether_portal(pos, width, height, orientation, name, clear_before_build)
local width, height, orientation = width or W_MIN - 2, height or H_MIN - 2, orientation or random(0, 1) local width, height, orientation = width or W_MIN - 2, height or H_MIN - 2, orientation or random(0, 1)
light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1)) if clear_before_build then
light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1), name, {name="air"}, {name="air"})
local get_node = mcl_portals.get_node end
light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1), name)
-- Build obsidian platform: -- Build obsidian platform:
for x = pos.x - orientation, pos.x + orientation + (width - 1) * (1 - orientation), 1 + orientation do for x = pos.x - orientation, pos.x + orientation + (width - 1) * (1 - orientation), 1 + orientation do
@ -345,7 +341,7 @@ function mcl_portals.spawn_nether_portal(pos, rot, pr, name)
o = random(0,1) o = random(0,1)
end end
end end
build_nether_portal(pos, nil, nil, o, name) build_nether_portal(pos, nil, nil, o, name, true)
end end
-- Teleportation cooloff for some seconds, to prevent back-and-forth teleportation -- Teleportation cooloff for some seconds, to prevent back-and-forth teleportation
@ -379,7 +375,13 @@ local function finalize_teleport(obj, exit)
-- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y -- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y
objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)} objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)}
if mcl_portals.get_node(objpos).name ~= PORTAL then return end if get_node(objpos).name ~= PORTAL then return end
-- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- 1 of 2 -- TODO: Remove --
-- Old worlds have no exits indexed - adding the exit to return here:
add_exit(objpos)
-- TEMPORATY CODE SECTION ENDS HERE --
-- Enable teleportation cooloff for some seconds, to prevent back-and-forth teleportation -- Enable teleportation cooloff for some seconds, to prevent back-and-forth teleportation
teleport_cooloff(obj) teleport_cooloff(obj)
@ -436,7 +438,8 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
local pos0, distance local pos0, distance
local lava = get_lava_level(pos, pos1, pos2) local lava = get_lava_level(pos, pos1, pos2)
-- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- -- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- 2 of 2 -- TODO: Remove --
-- Find portals for old worlds (new worlds keep them all in the table):
local portals = find_nodes_in_area(pos1, pos2, {PORTAL}) local portals = find_nodes_in_area(pos1, pos2, {PORTAL})
if portals and #portals>0 then if portals and #portals>0 then
for _, p in pairs(portals) do for _, p in pairs(portals) do
@ -463,7 +466,6 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
local nodes2 = find_nodes_in_area(node1, node2, {"air"}) local nodes2 = find_nodes_in_area(node1, node2, {"air"})
if nodes2 then if nodes2 then
local nc2 = #nodes2 local nc2 = #nodes2
log("action", "[mcl_portals] nc2=" .. tostring(nc2))
if nc2 == 27 and not is_area_protected(node, node2, name) then if nc2 == 27 and not is_area_protected(node, node2, name) then
local distance0 = dist(pos, node) local distance0 = dist(pos, node)
if distance0 < 2 then if distance0 < 2 then
@ -522,7 +524,7 @@ local function create_portal(pos, limit1, limit2, name, obj)
end end
local function available_for_nether_portal(p) local function available_for_nether_portal(p)
local nn = mcl_portals.get_node(p).name local nn = get_node(p).name
local obsidian = nn == OBSIDIAN local obsidian = nn == OBSIDIAN
if nn ~= "air" and minetest.get_item_group(nn, "fire") ~= 1 then if nn ~= "air" and minetest.get_item_group(nn, "fire") ~= 1 then
return false, obsidian return false, obsidian
@ -629,7 +631,7 @@ local function teleport_no_delay(obj, pos)
-- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y -- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y
objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)} objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)}
if mcl_portals.get_node(objpos).name ~= PORTAL then return end if get_node(objpos).name ~= PORTAL then return end
local target, dim = get_target(objpos) local target, dim = get_target(objpos)
if not target then return end if not target then return end

View File

@ -12,6 +12,8 @@ end
local min_y = math.max(mcl_vars.mg_overworld_min, mcl_vars.mg_bedrock_overworld_max) + 1 local min_y = math.max(mcl_vars.mg_overworld_min, mcl_vars.mg_bedrock_overworld_max) + 1
local max_y = mcl_vars.mg_overworld_max - 1 local max_y = mcl_vars.mg_overworld_max - 1
local get_node = mcl_vars.get_node
-- Calculate the number of dungeon spawn attempts -- Calculate the number of dungeon spawn attempts
-- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks). -- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks).
-- Minetest chunks don't have this size, so scale the number accordingly. -- Minetest chunks don't have this size, so scale the number accordingly.
@ -49,8 +51,8 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
local y_floor = y local y_floor = y
local y_ceiling = y + dim.y + 1 local y_ceiling = y + dim.y + 1
if check then for tx = x+1, x+dim.x do for tz = z+1, z+dim.z do if check then for tx = x+1, x+dim.x do for tz = z+1, z+dim.z do
if not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_floor , z = tz}).name].walkable if not minetest.registered_nodes[get_node({x = tx, y = y_floor , z = tz}).name].walkable
or not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end or not minetest.registered_nodes[get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end
end end end end end end
-- Check for air openings (2 stacked air at ground level) in wall positions -- Check for air openings (2 stacked air at ground level) in wall positions
@ -63,25 +65,25 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
local x2,z2 = x+dim.x+1, z+dim.z+1 local x2,z2 = x+dim.x+1, z+dim.z+1
if mcl_mapgen_core.get_node({x=x, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z}).name == "air" then if get_node({x=x, y=y+1, z=z}).name == "air" and get_node({x=x, y=y+2, z=z}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if not openings[x] then openings[x]={} end if not openings[x] then openings[x]={} end
openings[x][z] = true openings[x][z] = true
table.insert(corners, {x=x, z=z}) table.insert(corners, {x=x, z=z})
end end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z}).name == "air" then if get_node({x=x2, y=y+1, z=z}).name == "air" and get_node({x=x2, y=y+2, z=z}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if not openings[x2] then openings[x2]={} end if not openings[x2] then openings[x2]={} end
openings[x2][z] = true openings[x2][z] = true
table.insert(corners, {x=x2, z=z}) table.insert(corners, {x=x2, z=z})
end end
if mcl_mapgen_core.get_node({x=x, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z2}).name == "air" then if get_node({x=x, y=y+1, z=z2}).name == "air" and get_node({x=x, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if not openings[x] then openings[x]={} end if not openings[x] then openings[x]={} end
openings[x][z2] = true openings[x][z2] = true
table.insert(corners, {x=x, z=z2}) table.insert(corners, {x=x, z=z2})
end end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z2}).name == "air" then if get_node({x=x2, y=y+1, z=z2}).name == "air" and get_node({x=x2, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if not openings[x2] then openings[x2]={} end if not openings[x2] then openings[x2]={} end
openings[x2][z2] = true openings[x2][z2] = true
@ -89,13 +91,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
end end
for wx = x+1, x+dim.x do for wx = x+1, x+dim.x do
if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z}).name == "air" then if get_node({x=wx, y=y+1, z=z}).name == "air" and get_node({x=wx, y=y+2, z=z}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end if check and openings_counter > 5 then return end
if not openings[wx] then openings[wx]={} end if not openings[wx] then openings[wx]={} end
openings[wx][z] = true openings[wx][z] = true
end end
if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z2}).name == "air" then if get_node({x=wx, y=y+1, z=z2}).name == "air" and get_node({x=wx, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end if check and openings_counter > 5 then return end
if not openings[wx] then openings[wx]={} end if not openings[wx] then openings[wx]={} end
@ -103,13 +105,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
end end
end end
for wz = z+1, z+dim.z do for wz = z+1, z+dim.z do
if mcl_mapgen_core.get_node({x=x, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=wz}).name == "air" then if get_node({x=x, y=y+1, z=wz}).name == "air" and get_node({x=x, y=y+2, z=wz}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end if check and openings_counter > 5 then return end
if not openings[x] then openings[x]={} end if not openings[x] then openings[x]={} end
openings[x][wz] = true openings[x][wz] = true
end end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=wz}).name == "air" then if get_node({x=x2, y=y+1, z=wz}).name == "air" and get_node({x=x2, y=y+2, z=wz}).name == "air" then
openings_counter = openings_counter + 1 openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end if check and openings_counter > 5 then return end
if not openings[x2] then openings[x2]={} end if not openings[x2] then openings[x2]={} end
@ -185,7 +187,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Calculate the mob spawner position, to be re-used for later -- Calculate the mob spawner position, to be re-used for later
local sp = {x = x + math.ceil(dim.x/2), y = y+1, z = z + math.ceil(dim.z/2)} local sp = {x = x + math.ceil(dim.x/2), y = y+1, z = z + math.ceil(dim.z/2)}
local rn = minetest.registered_nodes[mcl_mapgen_core.get_node(sp).name] local rn = minetest.registered_nodes[get_node(sp).name]
if rn and rn.is_ground_content then if rn and rn.is_ground_content then
table.insert(spawner_posses, sp) table.insert(spawner_posses, sp)
end end
@ -200,7 +202,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Do not overwrite nodes with is_ground_content == false (e.g. bedrock) -- Do not overwrite nodes with is_ground_content == false (e.g. bedrock)
-- Exceptions: cobblestone and mossy cobblestone so neighborings dungeons nicely connect to each other -- Exceptions: cobblestone and mossy cobblestone so neighborings dungeons nicely connect to each other
local name = mcl_mapgen_core.get_node(p).name local name = get_node(p).name
if minetest.registered_nodes[name].is_ground_content or name == "mcl_core:cobble" or name == "mcl_core:mossycobble" then if minetest.registered_nodes[name].is_ground_content or name == "mcl_core:cobble" or name == "mcl_core:mossycobble" then
-- Floor -- Floor
if ty == y then if ty == y then
@ -245,7 +247,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
if forChest and (currentChest < totalChests + 1) and (chestSlots[currentChest] == chestSlotCounter) then if forChest and (currentChest < totalChests + 1) and (chestSlots[currentChest] == chestSlotCounter) then
currentChest = currentChest + 1 currentChest = currentChest + 1
table.insert(chests, {x=tx, y=ty, z=tz}) table.insert(chests, {x=tx, y=ty, z=tz})
else -- else
--minetest.swap_node(p, {name = "air"}) --minetest.swap_node(p, {name = "air"})
end end
if forChest then if forChest then
@ -263,8 +265,8 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Detect the 4 horizontal neighbors -- Detect the 4 horizontal neighbors
local spos = vector.add(pos, surround_vectors[s]) local spos = vector.add(pos, surround_vectors[s])
local wpos = vector.subtract(pos, surround_vectors[s]) local wpos = vector.subtract(pos, surround_vectors[s])
local nodename = minetest.get_node(spos).name local nodename = get_node(spos).name
local nodename2 = minetest.get_node(wpos).name local nodename2 = get_node(wpos).name
local nodedef = minetest.registered_nodes[nodename] local nodedef = minetest.registered_nodes[nodename]
local nodedef2 = minetest.registered_nodes[nodename2] local nodedef2 = minetest.registered_nodes[nodename2]
-- The chest needs an open space in front of it and a walkable node (except chest) behind it -- The chest needs an open space in front of it and a walkable node (except chest) behind it
@ -345,6 +347,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
}) })
end end
minetest.log("action", "[mcl_dungeons] Filling chest " .. tostring(c) .. " at " .. minetest.pos_to_string(pos))
mcl_loot.fill_inventory(meta:get_inventory(), "main", mcl_loot.get_multi_loot(loottable, pr), pr) mcl_loot.fill_inventory(meta:get_inventory(), "main", mcl_loot.get_multi_loot(loottable, pr), pr)
end end

View File

@ -1,45 +1,8 @@
mcl_mapgen_core = {} mcl_mapgen_core = {}
mcl_mapgen_core.registered_generators = {} local registered_generators = {}
local lvm, nodes, param2 = 0, 0, 0 local lvm, nodes, param2 = 0, 0, 0
local lvm_buffer = {}
local generating = {} -- generating chunks
local chunks = {} -- intervals of chunks generated
local function add_chunk(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
local prev
for i, d in pairs(chunks) do
if n <= d[2] then -- we've found it
if (n == d[2]) or (n >= d[1]) then return end -- already here
if n == d[1]-1 then -- right before:
if prev and (prev[2] == n-1) then
prev[2] = d[2]
table.remove(chunks, i)
return
end
d[1] = n
return
end
if prev and (prev[2] == n-1) then --join to previous
prev[2] = n
return
end
table.insert(chunks, i, {n, n}) -- insert new interval before i
return
end
prev = d
end
chunks[#chunks+1] = {n, n}
end
function mcl_mapgen_core.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
for i, d in pairs(chunks) do
if n <= d[2] then
return (n >= d[1])
end
end
return false
end
-- --
-- Aliases for map generator outputs -- Aliases for map generator outputs
@ -1850,24 +1813,22 @@ end
minetest.register_on_generated(function(minp, maxp, blockseed) minetest.register_on_generated(function(minp, maxp, blockseed)
minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp)) minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp))
add_chunk(minp)
local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z} local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z}
if lvm > 0 then if lvm > 0 then
local lvm_used, shadow = false, false local lvm_used, shadow = false, false
local lb = {} -- buffer
local lb2 = {} -- param2 local lb2 = {} -- param2
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z} local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z}
local data2 local data2
local data = vm:get_data(lb) local data = vm:get_data(lvm_buffer)
if param2 > 0 then if param2 > 0 then
data2 = vm:get_param2_data(lb2) data2 = vm:get_param2_data(lb2)
end end
local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2}) local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
for _, rec in pairs(mcl_mapgen_core.registered_generators) do for _, rec in pairs(registered_generators) do
if rec.vf then if rec.vf then
local lvm_used0, shadow0 = rec.vf(vm, data, data2, p1, p2, area, p1, p2, blockseed) local lvm_used0, shadow0 = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed)
if lvm_used0 then if lvm_used0 then
lvm_used = true lvm_used = true
end end
@ -1890,18 +1851,18 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
end end
if nodes > 0 then if nodes > 0 then
for _, rec in pairs(mcl_mapgen_core.registered_generators) do for _, rec in pairs(registered_generators) do
if rec.nf then if rec.nf then
rec.nf(p1, p2, blockseed) rec.nf(p1, p2, blockseed)
end end
end end
end end
-- add_chunk(minp) mcl_vars.add_chunk(minp)
end) end)
minetest.register_on_generated=function(node_function) minetest.register_on_generated=function(node_function)
mcl_mapgen_core.register_generator("mod_"..tostring(#mcl_mapgen_core.registered_generators+1), nil, node_function) mcl_mapgen_core.register_generator("mod_"..tostring(#registered_generators+1), nil, node_function)
end end
function mcl_mapgen_core.register_generator(id, lvm_function, node_function, priority, needs_param2) function mcl_mapgen_core.register_generator(id, lvm_function, node_function, priority, needs_param2)
@ -1920,18 +1881,18 @@ function mcl_mapgen_core.register_generator(id, lvm_function, node_function, pri
needs_param2 = needs_param2, needs_param2 = needs_param2,
} }
mcl_mapgen_core.registered_generators[id] = new_record registered_generators[id] = new_record
table.sort( table.sort(
mcl_mapgen_core.registered_generators, registered_generators,
function(a, b) function(a, b)
return (a.i < b.i) or ((a.i == b.i) and (a.vf ~= nil) and (b.vf == nil)) return (a.i < b.i) or ((a.i == b.i) and (a.vf ~= nil) and (b.vf == nil))
end) end)
end end
function mcl_mapgen_core.unregister_generator(id) function mcl_mapgen_core.unregister_generator(id)
if not mcl_mapgen_core.registered_generators[id] then return end if not registered_generators[id] then return end
local rec = mcl_mapgen_core.registered_generators[id] local rec = registered_generators[id]
mcl_mapgen_core.registered_generators[id] = nil registered_generators[id] = nil
if rec.vf then lvm = lvm - 1 end if rec.vf then lvm = lvm - 1 end
if rev.nf then nodes = nodes - 1 end if rev.nf then nodes = nodes - 1 end
if rec.needs_param2 then param2 = param2 - 1 end if rec.needs_param2 then param2 = param2 - 1 end
@ -2134,9 +2095,9 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- Nether block fixes: -- Nether block fixes:
-- * Replace water with Nether lava. -- * Replace water with Nether lava.
-- * Replace stone, sand dirt in v6 so the Nether works in v6. -- * Replace stone, sand dirt in v6 so the Nether works in v6.
elseif minp.y <= mcl_vars.mg_nether_max and maxp.y >= mcl_vars.mg_nether_min then elseif emin.y <= mcl_vars.mg_nether_max and emax.y >= mcl_vars.mg_nether_min then
if mg_name == "v6" then if mg_name == "v6" then
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
for n=1, #nodes do for n=1, #nodes do
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
if data[p_pos] == c_water then if data[p_pos] == c_water then
@ -2151,16 +2112,10 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
end end
end end
else else
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining, param) local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"})
if calls_remaining > 0 then return end for _, n in pairs(nodes) do
-- local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"mcl_core:water_source"}) data[area:index(n.x, n.y, n.z)] = c_nether_lava
local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"group:water"}) end
local sn=(mcl_observers and mcl_observers.swap_node) or minetest.swap_node
local l = {name="mcl_nether:nether_lava_source"}
for _, n in pairs(nodes) do
sn(n, l)
end
end, {minp=vector.new(minp), maxp=vector.new(maxp)})
end end
-- End block fixes: -- End block fixes:
@ -2168,17 +2123,16 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- * Remove stone, sand, dirt in v6 so our End map generator works in v6. -- * Remove stone, sand, dirt in v6 so our End map generator works in v6.
-- * Generate spawn platform (End portal destination) -- * Generate spawn platform (End portal destination)
elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then
local nodes, node local nodes, n
if mg_name == "v6" then if mg_name == "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 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 end
if #nodes > 0 then if #nodes > 0 then
lvm_used = true lvm_used = true
for n=1, #nodes do for _, n in pairs(nodes) do
node = nodes[n] data[area:index(n.x, n.y, n.z)] = c_air
data[area:index(node.x, node.y, node.z)] = c_air
end end
end end
@ -2231,48 +2185,3 @@ end
mcl_mapgen_core.register_generator("main", basic, nil, 1, true) mcl_mapgen_core.register_generator("main", basic, nil, 1, true)
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like 5.3.0 does.
-- p: Position, if it's wrong, {name="error"} node will return.
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
--
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
function mcl_mapgen_core.get_node(p, force, us_timeout)
-- check initial circumstances
if not p or not p.x or not p.y or not p.z then return {name="error"} end
-- try common way
local node = minetest.get_node(p)
if node.name ~= "ignore" then
return node
end
-- copy table to get sure it won't changed by other threads
local pos = {x=p.x,y=p.y,z=p.z}
-- try LVM
minetest.get_voxel_manip():read_from_map(pos, pos)
node = minetest.get_node(pos)
if node.name ~= "ignore" or not force then
return node
end
-- all ways failed - need to emerge (or forceload if generated)
local us_timeout = us_timeout or 244
if mcl_mapgen_core.is_generated(pos) then
minetest.forceload_block(pos)
else
minetest.emerge_area(pos, pos)
end
local t = minetest.get_us_time()
node = minetest.get_node(pos)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
node = minetest.get_node(pos)
end
return node
-- it still can return "ignore", LOL, even if force = true, but only after time out
end

View File

@ -272,7 +272,7 @@ local function hut_placement_callback(p1, p2, size, orientation, pr)
if not p1 or not p2 then return end if not p1 or not p2 then return end
local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree") local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree")
for i = 1, #legs do for i = 1, #legs do
while minetest.get_item_group(mcl_mapgen_core.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do while minetest.get_item_group(mcl_vars.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do
legs[i].y = legs[i].y - 1 legs[i].y = legs[i].y - 1
minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2}) minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2})
end end

View File

@ -4,7 +4,7 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name) function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name)
-- get building node material for better integration to surrounding -- get building node material for better integration to surrounding
local platform_material = mcl_mapgen_core.get_node(pos) local platform_material = mcl_vars.get_node(pos)
if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then
return return
end end

View File

@ -52,7 +52,7 @@ function settlements.terraform(settlement_info, pr)
else else
-- write ground -- write ground
-- local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi} -- local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi}
-- local node = mcl_mapgen_core.get_node(p) -- local node = mcl_vars.get_node(p)
-- if node and node.name ~= "air" then -- if node and node.name ~= "air" then
-- minetest.swap_node(p,{name="air"}) -- minetest.swap_node(p,{name="air"})
-- end -- end

View File

@ -1,28 +1,5 @@
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") local get_node = mcl_vars.get_node
local c_dirt_with_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow")
--local c_dirt_with_dry_grass = minetest.get_content_id("mcl_core:dirt_with_dry_grass")
local c_podzol = minetest.get_content_id("mcl_core:podzol")
local c_sand = minetest.get_content_id("mcl_core:sand")
local c_desert_sand = minetest.get_content_id("mcl_core:redsand")
--local c_silver_sand = minetest.get_content_id("mcl_core:silver_sand")
--
local c_air = minetest.get_content_id("air")
local c_snow = minetest.get_content_id("mcl_core:snow")
local c_fern_1 = minetest.get_content_id("mcl_flowers:fern")
local c_fern_2 = minetest.get_content_id("mcl_flowers:fern")
local c_fern_3 = minetest.get_content_id("mcl_flowers:fern")
local c_rose = minetest.get_content_id("mcl_flowers:poppy")
local c_viola = minetest.get_content_id("mcl_flowers:blue_orchid")
local c_geranium = minetest.get_content_id("mcl_flowers:allium")
local c_tulip = minetest.get_content_id("mcl_flowers:tulip_orange")
local c_dandelion_y = minetest.get_content_id("mcl_flowers:dandelion")
local c_dandelion_w = minetest.get_content_id("mcl_flowers:oxeye_daisy")
local c_bush_leaves = minetest.get_content_id("mcl_core:leaves")
local c_bush_stem = minetest.get_content_id("mcl_core:tree")
local c_a_bush_leaves = minetest.get_content_id("mcl_core:acacialeaves")
local c_a_bush_stem = minetest.get_content_id("mcl_core:acaciatree")
local c_water_source = minetest.get_content_id("mcl_core:water_source")
local c_water_flowing = minetest.get_content_id("mcl_core:water_flowing")
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- function to copy tables -- function to copy tables
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -53,9 +30,9 @@ function settlements.find_surface(pos, wait)
-- check, in which direction to look for surface -- check, in which direction to look for surface
local surface_node local surface_node
if wait then if wait then
surface_node = mcl_mapgen_core.get_node(p6, true, 10000000) surface_node = get_node(p6, true, 10000000)
else else
surface_node = mcl_mapgen_core.get_node(p6) surface_node = get_node(p6)
end end
if surface_node.name=="air" or surface_node.name=="ignore" then if surface_node.name=="air" or surface_node.name=="ignore" then
itter = -1 itter = -1
@ -65,7 +42,7 @@ function settlements.find_surface(pos, wait)
-- Check Surface_node and Node above -- Check Surface_node and Node above
-- --
if settlements.surface_mat[surface_node.name] then if settlements.surface_mat[surface_node.name] then
local surface_node_plus_1 = mcl_mapgen_core.get_node({ x=p6.x, y=p6.y+1, z=p6.z}) local surface_node_plus_1 = get_node({ x=p6.x, y=p6.y+1, z=p6.z})
if surface_node_plus_1 and surface_node and if surface_node_plus_1 and surface_node and
(string.find(surface_node_plus_1.name,"air") or (string.find(surface_node_plus_1.name,"air") or
string.find(surface_node_plus_1.name,"snow") or string.find(surface_node_plus_1.name,"snow") or
@ -90,7 +67,7 @@ function settlements.find_surface(pos, wait)
return nil return nil
end end
cnt = cnt+1 cnt = cnt+1
surface_node = mcl_mapgen_core.get_node(p6) surface_node = get_node(p6)
end end
settlements.debug("find_surface5: cnt_max overflow") settlements.debug("find_surface5: cnt_max overflow")
return nil return nil

16
mods/MISC/mcl_wip/API.md Normal file
View File

@ -0,0 +1,16 @@
# mcl_wip
Used to mark items or nodes as WIP.
## mcl_wip.register_wip_item(itemname)
Register <itemname> as a WIP item.
If <itemname> isn't a valid itemname, an error will be shown after mods loaded.
## mcl_wip.register_experimental_item(itemname)
Register <itemname> as a experimental item.
If <itemname> isn't a valid itemname, an error will be shown after mods loaded.
## mcl_wip.registered_wip_items
Table containing WIP items names.
## mcl_wip.registered_experimental_items
Table containing experimental items names.

View File

@ -0,0 +1,14 @@
# mcl_death_drop
Drop registered inventories on player death.
## mcl_death_drop.register_dropped_list(inv, listname, drop)
* inv: can be:
* "PLAYER": will be interpreted like player inventory (to avoid multiple calling to get_inventory())
* function(player): must return inventory
* listname: string
* drop: bool
* true: the entire list will be dropped
* false: items with curse_of_vanishing enchantement will be broken.
## mcl_death_drop.registered_dropped_lists
Table containing dropped list inventory, name and drop state.

View File

@ -1,26 +1,40 @@
local random = math.random
mcl_death_drop = {}
mcl_death_drop.registered_dropped_lists = {}
function mcl_death_drop.register_dropped_list(inv, listname, drop)
table.insert(mcl_death_drop.registered_dropped_lists, {inv=inv, listname=listname, drop=drop})
end
mcl_death_drop.register_dropped_list("PLAYER", "main", true)
mcl_death_drop.register_dropped_list("PLAYER", "craft", true)
mcl_death_drop.register_dropped_list("PLAYER", "armor", true)
mcl_death_drop.register_dropped_list(function(player) return select(3, armor:get_valid_player(player)) end , "armor", false)
minetest.register_on_dieplayer(function(player) minetest.register_on_dieplayer(function(player)
local keep = minetest.settings:get_bool("mcl_keepInventory", false) local keep = minetest.settings:get_bool("mcl_keepInventory", false)
if keep == false then if keep == false then
-- Drop inventory, crafting grid and armor -- Drop inventory, crafting grid and armor
local inv = player:get_inventory() local playerinv = player:get_inventory()
local pos = player:get_pos() local pos = player:get_pos()
local name, player_armor_inv, armor_armor_inv, pos = armor:get_valid_player(player, "[on_dieplayer]")
-- No item drop if in deep void -- No item drop if in deep void
local void, void_deadly = mcl_worlds.is_in_void(pos) local void, void_deadly = mcl_worlds.is_in_void(pos)
local lists = {
{ inv = inv, listname = "main", drop = true }, for l=1,#mcl_death_drop.registered_dropped_lists do
{ inv = inv, listname = "craft", drop = true }, local inv = mcl_death_drop.registered_dropped_lists[l].inv
{ inv = player_armor_inv, listname = "armor", drop = true }, if inv == "PLAYER" then
{ inv = armor_armor_inv, listname = "armor", drop = false }, inv = playerinv
} elseif type(inv) == "function" then
for l=1,#lists do inv = inv(player)
local inv = lists[l].inv end
local listname = lists[l].listname local listname = mcl_death_drop.registered_dropped_lists[l].listname
local drop = lists[l].drop local drop = mcl_death_drop.registered_dropped_lists[l].drop
if inv ~= nil then if inv ~= nil then
for i, stack in ipairs(inv:get_list(listname)) do for i, stack in ipairs(inv:get_list(listname)) do
local x = math.random(0, 9)/3 local x = random(0, 9)/3
local z = math.random(0, 9)/3 local z = random(0, 9)/3
pos.x = pos.x + x pos.x = pos.x + x
pos.z = pos.z + z pos.z = pos.z + z
if not void_deadly and drop and not mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then if not void_deadly and drop and not mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then

View File

@ -81,13 +81,7 @@ local dir_step = storage:get_int("mcl_spawn_dir_step") or 0
local dir_ind = storage:get_int("mcl_spawn_dir_ind") or 1 local dir_ind = storage:get_int("mcl_spawn_dir_ind") or 1
local emerge_pos1, emerge_pos2 local emerge_pos1, emerge_pos2
-- Get world 'mapgen_limit' and 'chunksize' to calculate 'spawn_limit'. local spawn_limit = mcl_vars.mapgen_edge_max
-- This accounts for how mapchunks are not generated if they or their shell exceed
-- 'mapgen_limit'.
local mapgen_limit = tonumber(minetest.get_mapgen_setting("mapgen_limit"))
local chunksize = tonumber(minetest.get_mapgen_setting("chunksize"))
local spawn_limit = math.max(mapgen_limit - (chunksize + 1) * 16, 0)
--Functions --Functions
@ -503,10 +497,17 @@ function mcl_spawn.shadow_worker()
mcl_spawn.search() mcl_spawn.search()
minetest.log("action", "[mcl_spawn] Started world spawn point search") minetest.log("action", "[mcl_spawn] Started world spawn point search")
end end
if success and ((not good_for_respawn(wsp)) or (not can_find_tree(wsp))) then
success = false if success then
minetest.log("action", "[mcl_spawn] World spawn position isn't safe anymore: "..minetest.pos_to_string(wsp)) local wsp_node = minetest.get_node(wsp)
mcl_spawn.search() if wsp_node and wsp_node.name == "ignore" then
-- special case - respawn area unloaded from memory - it's okay, skip for now
elseif ((not good_for_respawn(wsp)) or ((no_trees_area_counter >= 0) and not can_find_tree(wsp))) then
success = false
minetest.log("action", "[mcl_spawn] World spawn position isn't safe anymore: "..minetest.pos_to_string(wsp))
mcl_spawn.search()
end
end end
minetest.after(respawn_search_interval, mcl_spawn.shadow_worker) minetest.after(respawn_search_interval, mcl_spawn.shadow_worker)