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)
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
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
@ -16,16 +20,33 @@ local get_gravity = function()
return tonumber(minetest.settings:get("movement_gravity")) or 9.81
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 itemname = ItemStack(object:get_luaentity().itemstring):get_name()
if minetest.get_item_group(itemname, "tree") ~= 0 then
awards.unlock(player:get_player_name(), "mcl:mineWood")
elseif itemname == "mcl_mobitems:blaze_rod" then
awards.unlock(player:get_player_name(), "mcl:blazeRod")
elseif itemname == "mcl_mobitems:leather" then
awards.unlock(player:get_player_name(), "mcl:killCow")
elseif itemname == "mcl_core:diamond" then
awards.unlock(player:get_player_name(), "mcl:diamonds")
if has_awards then
local itemname = ItemStack(object:get_luaentity().itemstring):get_name()
local playername = player:get_player_name()
for name,award in pairs(registered_pickup_achievement) do
if itemname == name or minetest.get_item_group(itemname, name) ~= 0 then
awards.unlock(playername, award)
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)
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,
collision_box = collision_box_bottom,
drop = "",
node_placement_prediction = "",
on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under

View File

@ -5,17 +5,17 @@ Add an API to register buckets to mcl
Register a new liquid
Accept folowing params:
* source_place = a string or function.
* source_place: a string or function.
* string: name of the node to place
* 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
* 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)
* name = user-visible bucket description
* longdesc = long explanatory description (for help)
* usagehelp = short usage explanation (for 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.
* groups = optional list of item groups
* source_take: table of liquid source node names to take
* 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)
* name: user-visible bucket description
* longdesc: long explanatory description (for help)
* usagehelp: short usage explanation (for 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.
* groups: optional list of item groups
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
if not minetest.is_creative_enabled(user:get_player_name()) then
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
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_hardness = 1.5,
_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", {
@ -814,6 +819,11 @@ minetest.register_node("mcl_core:obsidian", {
groups = {pickaxey=5, building_block=1, material_stone=1},
_mcl_blast_resistance = 1200,
_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", {

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))
end)
mcl_portals.get_node = function(pos)
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 get_node = mcl_vars.get_node
local set_node = minetest.set_node
local registered_nodes = minetest.registered_nodes
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.
-- If the verification passes - position adds to the table and saves to mod storage on exit.
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
local x, y, z = floor(p.x), floor(p.y), floor(p.z)
local p = {x = x, y = y, z = z}
@ -109,7 +103,7 @@ local function add_exit(p)
local e = exits[k]
for i = 1, #e do
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
end
end
@ -202,7 +196,6 @@ local function destroy_nether_portal(pos, node)
local nn, orientation = node.name, node.param2
local obsidian = nn == OBSIDIAN
local get_node = mcl_portals.get_node
local check_remove = function(pos, orientation)
local node = get_node(pos)
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,
})
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
if x1 == x2 then
orientation = 1
end
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
pos.x = x
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
local frame = (x < x1) or (x > x2) or (y < y1) or (y > y2) or (z < z1) or (z > z2)
if frame then
set_node(pos, {name = OBSIDIAN})
set_node(pos, node_frame)
else
set_node(pos, {name = PORTAL, param2 = orientation})
set_node(pos, node)
add_exit({x=pos.x, y=pos.y-1, z=pos.z})
end
end
@ -310,12 +305,13 @@ local function light_frame(x1, y1, z1, x2, y2, z2, name)
end
--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)
light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1))
local get_node = mcl_portals.get_node
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"})
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:
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)
end
end
build_nether_portal(pos, nil, nil, o, name)
build_nether_portal(pos, nil, nil, o, name, true)
end
-- 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
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
teleport_cooloff(obj)
@ -436,7 +438,8 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
local pos0, distance
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})
if portals and #portals>0 then
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"})
if nodes2 then
local nc2 = #nodes2
log("action", "[mcl_portals] nc2=" .. tostring(nc2))
if nc2 == 27 and not is_area_protected(node, node2, name) then
local distance0 = dist(pos, node)
if distance0 < 2 then
@ -522,7 +524,7 @@ local function create_portal(pos, limit1, limit2, name, obj)
end
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
if nn ~= "air" and minetest.get_item_group(nn, "fire") ~= 1 then
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
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)
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 max_y = mcl_vars.mg_overworld_max - 1
local get_node = mcl_vars.get_node
-- Calculate the number of dungeon spawn attempts
-- 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.
@ -49,8 +51,8 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
local y_floor = y
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 not minetest.registered_nodes[mcl_mapgen_core.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
if not minetest.registered_nodes[get_node({x = tx, y = y_floor , z = tz}).name].walkable
or not minetest.registered_nodes[get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end
end end end
-- 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
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
if not openings[x] then openings[x]={} end
openings[x][z] = true
table.insert(corners, {x=x, z=z})
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
if not openings[x2] then openings[x2]={} end
openings[x2][z] = true
table.insert(corners, {x=x2, z=z})
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
if not openings[x] then openings[x]={} end
openings[x][z2] = true
table.insert(corners, {x=x, z=z2})
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
if not openings[x2] then openings[x2]={} end
openings[x2][z2] = true
@ -89,13 +91,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
end
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
if check and openings_counter > 5 then return end
if not openings[wx] then openings[wx]={} end
openings[wx][z] = true
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
if check and openings_counter > 5 then return 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
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
if check and openings_counter > 5 then return end
if not openings[x] then openings[x]={} end
openings[x][wz] = true
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
if check and openings_counter > 5 then return 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
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
table.insert(spawner_posses, sp)
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)
-- 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
-- Floor
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
currentChest = currentChest + 1
table.insert(chests, {x=tx, y=ty, z=tz})
else
-- else
--minetest.swap_node(p, {name = "air"})
end
if forChest then
@ -263,8 +265,8 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Detect the 4 horizontal neighbors
local spos = vector.add(pos, surround_vectors[s])
local wpos = vector.subtract(pos, surround_vectors[s])
local nodename = minetest.get_node(spos).name
local nodename2 = minetest.get_node(wpos).name
local nodename = get_node(spos).name
local nodename2 = get_node(wpos).name
local nodedef = minetest.registered_nodes[nodename]
local nodedef2 = minetest.registered_nodes[nodename2]
-- 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
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)
end

View File

@ -1,45 +1,8 @@
mcl_mapgen_core = {}
mcl_mapgen_core.registered_generators = {}
local registered_generators = {}
local lvm, nodes, param2 = 0, 0, 0
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
local lvm_buffer = {}
--
-- Aliases for map generator outputs
@ -1850,24 +1813,22 @@ end
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))
add_chunk(minp)
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
local lvm_used, shadow = false, false
local lb = {} -- buffer
local lb2 = {} -- param2
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 data2
local data = vm:get_data(lb)
local data = vm:get_data(lvm_buffer)
if param2 > 0 then
data2 = vm:get_param2_data(lb2)
end
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
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
lvm_used = true
end
@ -1890,18 +1851,18 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
end
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
rec.nf(p1, p2, blockseed)
end
end
end
-- add_chunk(minp)
mcl_vars.add_chunk(minp)
end)
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
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,
}
mcl_mapgen_core.registered_generators[id] = new_record
registered_generators[id] = new_record
table.sort(
mcl_mapgen_core.registered_generators,
registered_generators,
function(a, b)
return (a.i < b.i) or ((a.i == b.i) and (a.vf ~= nil) and (b.vf == nil))
end)
end
function mcl_mapgen_core.unregister_generator(id)
if not mcl_mapgen_core.registered_generators[id] then return end
local rec = mcl_mapgen_core.registered_generators[id]
mcl_mapgen_core.registered_generators[id] = nil
if not registered_generators[id] then return end
local rec = registered_generators[id]
registered_generators[id] = nil
if rec.vf then lvm = lvm - 1 end
if rev.nf then nodes = nodes - 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:
-- * Replace water with Nether lava.
-- * 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
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
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
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
else
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining, param)
if calls_remaining > 0 then return end
-- local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"mcl_core:water_source"})
local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"group:water"})
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)})
local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"})
for _, n in pairs(nodes) do
data[area:index(n.x, n.y, n.z)] = c_nether_lava
end
end
-- 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.
-- * Generate spawn platform (End portal destination)
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
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=1, #nodes do
node = nodes[n]
data[area:index(node.x, node.y, node.z)] = c_air
for _, n in pairs(nodes) do
data[area:index(n.x, n.y, n.z)] = c_air
end
end
@ -2231,48 +2185,3 @@ end
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
local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree")
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
minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2})
end

View File

@ -4,7 +4,7 @@
-------------------------------------------------------------------------------
function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name)
-- 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
return
end

View File

@ -52,7 +52,7 @@ function settlements.terraform(settlement_info, pr)
else
-- write ground
-- 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
-- minetest.swap_node(p,{name="air"})
-- end

View File

@ -1,28 +1,5 @@
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
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")
local get_node = mcl_vars.get_node
-------------------------------------------------------------------------------
-- function to copy tables
-------------------------------------------------------------------------------
@ -53,9 +30,9 @@ function settlements.find_surface(pos, wait)
-- check, in which direction to look for surface
local surface_node
if wait then
surface_node = mcl_mapgen_core.get_node(p6, true, 10000000)
surface_node = get_node(p6, true, 10000000)
else
surface_node = mcl_mapgen_core.get_node(p6)
surface_node = get_node(p6)
end
if surface_node.name=="air" or surface_node.name=="ignore" then
itter = -1
@ -65,7 +42,7 @@ function settlements.find_surface(pos, wait)
-- Check Surface_node and Node above
--
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
(string.find(surface_node_plus_1.name,"air") or
string.find(surface_node_plus_1.name,"snow") or
@ -90,7 +67,7 @@ function settlements.find_surface(pos, wait)
return nil
end
cnt = cnt+1
surface_node = mcl_mapgen_core.get_node(p6)
surface_node = get_node(p6)
end
settlements.debug("find_surface5: cnt_max overflow")
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)
local keep = minetest.settings:get_bool("mcl_keepInventory", false)
if keep == false then
-- Drop inventory, crafting grid and armor
local inv = player:get_inventory()
local playerinv = player:get_inventory()
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
local void, void_deadly = mcl_worlds.is_in_void(pos)
local lists = {
{ inv = inv, listname = "main", drop = true },
{ inv = inv, listname = "craft", drop = true },
{ inv = player_armor_inv, listname = "armor", drop = true },
{ inv = armor_armor_inv, listname = "armor", drop = false },
}
for l=1,#lists do
local inv = lists[l].inv
local listname = lists[l].listname
local drop = lists[l].drop
for l=1,#mcl_death_drop.registered_dropped_lists do
local inv = mcl_death_drop.registered_dropped_lists[l].inv
if inv == "PLAYER" then
inv = playerinv
elseif type(inv) == "function" then
inv = inv(player)
end
local listname = mcl_death_drop.registered_dropped_lists[l].listname
local drop = mcl_death_drop.registered_dropped_lists[l].drop
if inv ~= nil then
for i, stack in ipairs(inv:get_list(listname)) do
local x = math.random(0, 9)/3
local z = math.random(0, 9)/3
local x = random(0, 9)/3
local z = random(0, 9)/3
pos.x = pos.x + x
pos.z = pos.z + z
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 emerge_pos1, emerge_pos2
-- Get world 'mapgen_limit' and 'chunksize' to calculate 'spawn_limit'.
-- 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)
local spawn_limit = mcl_vars.mapgen_edge_max
--Functions
@ -503,10 +497,17 @@ function mcl_spawn.shadow_worker()
mcl_spawn.search()
minetest.log("action", "[mcl_spawn] Started world spawn point search")
end
if success and ((not good_for_respawn(wsp)) or (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()
if success then
local wsp_node = minetest.get_node(wsp)
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
minetest.after(respawn_search_interval, mcl_spawn.shadow_worker)