Start adding new structures API

This commit is contained in:
kay27 2022-01-12 03:27:28 +04:00
parent 16116df4c6
commit c6754fd39e
6 changed files with 131 additions and 57 deletions

View File

@ -71,7 +71,7 @@ Registers callback function to be called when current chunk generation is REALLY
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 = minetest.get_voxel_manip(vm_context.emin, vm_context.emax)`.
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)`:

View File

@ -29,9 +29,15 @@ local gateway_positions = {
local path_gateway_portal = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_gateway_portal.mts"
local function spawn_gateway_portal(pos, dest_str)
return mcl_structures.place_schematic(vector.add(pos, vector.new(-1, -2, -1)), path_gateway_portal, "0", nil, true, nil, dest_str and function()
minetest.get_meta(pos):set_string("mcl_portals:gateway_destination", dest_str)
end)
return mcl_structures.place_schematic({
pos = vector.add(pos, vector.new(-1, -2, -1)),
schematic = path_gateway_portal,
rotation = "0",
force_placement = true,
after_place = dest_str and function()
minetest.get_meta(pos):set_string("mcl_portals:gateway_destination", dest_str)
end,
})
end
function mcl_portals.spawn_gateway_portal()

View File

@ -10,25 +10,21 @@ local noisemap = PerlinNoiseMap({
local c_end_stone = minetest.get_content_id("mcl_end:end_stone")
local y_offset = -2
mcl_mapgen.register_mapgen(function(minp, maxp)
mcl_mapgen.register_on_generated(function(vm_context)
local minp, maxp = vm_context.minp, vm_context.maxp
if maxp.y < (-27025 + y_offset) or minp.y > (-27000 + y_offset + 4) or maxp.x < -75 or minp.x > 75 or maxp.z < -75 or minp.z > 75 then
return
end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm_context.data
local area = vm_context.area
local write = false
for idx in area:iter(math.max(minp.x, -75), math.max(minp.y, -27025 + y_offset + 4), math.max(minp.z, -75), math.min(maxp.x, 75), math.min(maxp.y, -27000 + y_offset), math.min(maxp.z, 75)) do
local pos = area:position(idx)
local y = 27025 + pos.y - y_offset
if noisemap[pos.x + 75 + 1][y + 1][pos.z + 75 + 1] > (math.abs(1 - y / 25) ^ 2 + math.abs(pos.x / 75) ^ 2 + math.abs(pos.z / 75) ^ 2) then
data[idx] = c_end_stone
write = true
end
end
vm:set_data(data)
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
vm_context.write = vm_context.write or write
end)

View File

@ -11,37 +11,106 @@ local rotations = {
"270"
}
local function ecb_place(blockpos, action, calls_remaining, param)
if calls_remaining >= 1 then return end
minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags)
if param.after_placement_callback and param.p1 and param.p2 then
param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param)
local registered_structures = {}
function mcl_structures.register_structure(def)
local name = def.name
if not name then
minetest.log('warning', 'Structure name is not passed for registering - ignoring')
return
end
if registered_structures[name] then
minetest.log('warning', 'Structure '..name..' is already registered - owerwriting')
end
registered_structures[name] = {
on_place = def.on_place,
decoration = def.decoration,
on_mapgen_prep = def.on_mapgen_prep,
on_generated = def.on_generated,
}
end
function mcl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param)
local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic")()
if s and s.size then
local x, z = s.size.x, s.size.z
if rotation then
if rotation == "random" and pr then
rotation = rotations[pr:next(1,#rotations)]
end
if rotation == "random" then
x = math.max(x, z)
z = x
elseif rotation == "90" or rotation == "270" then
x, z = z, x
end
end
local p1 = {x=pos.x , y=pos.y , z=pos.z }
local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1}
minetest.log("verbose", "[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param}
-- minetest.emerge_area(p1, p2, ecb_place, param)
-- TODO: Make it better
ecb_place(0, 0, 0, param)
function mcl_structures.unregister_structure(name)
if not registered_structures[name] then
minetest.log('warning','Structure '..name..' is not registered - skipping')
return
end
registered_structures[name] = nil
end
local function ecb_place(blockpos, action, calls_remaining, param)
if calls_remaining >= 1 then return end
local pos = param.pos
local rotation = param.rotation
minetest.place_schematic(pos, param.schematic, rotation, param.replacements, param.force_placement, param.flags)
local after_place = param.after_place
if not after_place then
return
end
after_place(pos, rotation, param.pr, param.param, param.size)
end
function mcl_structures.place_schematic(def)
local pos = def.pos
local schematic = def.schematic
local rotation = def.rotation
local pr = def.pr
if not pos then
minetest.log('warning', '[mcl_structures] No pos. specified to place schematic')
return
end
if not schematic then
minetest.log('warning', '[mcl_structures] No schematic specified to place at ' .. minetest.pos_to_string(pos))
return
end
if not rotation or rotation == 'random' then
if pr then
rotation = rotations[pr:next(1,#rotations)]
else
rotation = rotations[math.random(1,#rotations)]
end
end
if not def.emerge then
minetest.place_schematic(pos, schematic, rotation, def.replacements, def.force_placement, def.flags)
if not def.after_place then
return
end
def.after_place(pos, rotation, pr, def.after_place_param)
return
end
local loaded_schematic = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic")()
if not loaded_schematic then
minetest.log('warning', '[mcl_structures] Schematic ' .. schematic .. ' load serialized string problem at ' .. minetest.pos_to_string(pos))
return
end
local size = loaded_schematic.size
if not size then
minetest.log('warning', '[mcl_structures] Schematic ' .. schematic .. ' has no size at ' .. minetest.pos_to_string(pos))
return
end
local size_x, size_y, size_z = size.x, size.y, size.z
if rotation == "90" or rotation == "270" then
size_x, size_z = size_z, size_x
end
local x, y, z = pos.x, pos.y, pos.z
local p1 = {x = x, y = y, z = z}
local p2 = {x = x + size_x - 1, y = y + size_y - 1, z = size_z - 1}
minetest.log("verbose", "[mcl_structures] Emerge area " .. minetest.pos_to_string(p1) .. " - " .. minetest.pos_to_string(p2)
.. " of size " ..minetest.pos_to_string(size) .. " to place " .. schematic .. ", rotation " .. tostring(rotation))
local ecb_param = {
pos = vector.new(pos),
schematic = loaded_schematic,
rotation = rotation,
replacements = replacements,
force_placement = force_placement,
flags = flags,
after_place = after_place,
size = vector.new(size),
pr = pr,
param = param,
}
minetest.emerge_area(p1, p2, ecb_place, ecb_param)
end
function mcl_structures.get_struct(file)
@ -124,7 +193,12 @@ end
function mcl_structures.generate_desert_well(pos, rot)
local newpos = {x=pos.x,y=pos.y-2,z=pos.z}
local path = modpath.."/schematics/mcl_structures_desert_well.mts"
return mcl_structures.place_schematic(newpos, path, rot or "0", nil, true)
return mcl_structures.place_schematic({
pos = newpos,
schematic = path,
rotation = rot or "0",
force_placement = true
})
end
function mcl_structures.generate_igloo(pos, rotation, pr)
@ -227,7 +301,7 @@ end
function mcl_structures.generate_igloo_top(pos, pr)
-- FIXME: This spawns bookshelf instead of furnace. Fix this!
-- Furnace does ot work atm because apparently meta is not set. :-(
-- Furnace does not work atm because apparently meta is not set. :-(
local newpos = {x=pos.x,y=pos.y-1,z=pos.z}
local path = modpath.."/schematics/mcl_structures_igloo_top.mts"
local rotation = tostring(pr:next(0,3)*90)

View File

@ -1,4 +1,4 @@
name = mcl_structures
author = Wuzzy
description = Structures for MCL2
depends = mcl_loot
author = Wuzzy, kay27
description = Structures for MineClone 2/5
depends = mcl_loot, mcl_mapgen

View File

@ -268,15 +268,13 @@ function settlements.place_schematics(settlement_info, pr)
local schematic = loadstring(schem_lua)()
-- build foundation for the building an make room above
-- place schematic
mcl_structures.place_schematic(
pos,
schematic,
rotation,
nil,
true,
nil,
init_nodes,
pr
)
mcl_structures.place_schematic({
pos = pos,
schematic = schematic,
rotation = rotation,
force_placement = true,
on_place = init_nodes,
pr = pr,
})
end
end