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. 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. It can't provide you access to mapgen objects. They are probably gone long ago.
Don't use it for accessing mapgen objects please. 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 Set
`callback_function`: callback function definition: `callback_function`: callback function definition:
`function(minp, maxp, seed, vm_context)`: `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 path_gateway_portal = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_gateway_portal.mts"
local function spawn_gateway_portal(pos, dest_str) 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() return mcl_structures.place_schematic({
minetest.get_meta(pos):set_string("mcl_portals:gateway_destination", dest_str) pos = vector.add(pos, vector.new(-1, -2, -1)),
end) 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 end
function mcl_portals.spawn_gateway_portal() 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 c_end_stone = minetest.get_content_id("mcl_end:end_stone")
local y_offset = -2 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 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 return
end end
local data = vm_context.data
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local area = vm_context.area
local data = vm:get_data() local write = false
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
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 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 pos = area:position(idx)
local y = 27025 + pos.y - y_offset 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 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 data[idx] = c_end_stone
write = true
end end
end end
vm_context.write = vm_context.write or write
vm:set_data(data)
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
end) end)

View File

@ -11,37 +11,106 @@ local rotations = {
"270" "270"
} }
local function ecb_place(blockpos, action, calls_remaining, param) local registered_structures = {}
if calls_remaining >= 1 then return end
minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags) function mcl_structures.register_structure(def)
if param.after_placement_callback and param.p1 and param.p2 then local name = def.name
param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param) if not name then
minetest.log('warning', 'Structure name is not passed for registering - ignoring')
return
end 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 end
function mcl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param) function mcl_structures.unregister_structure(name)
local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic")() if not registered_structures[name] then
if s and s.size then minetest.log('warning','Structure '..name..' is not registered - skipping')
local x, z = s.size.x, s.size.z return
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)
end 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 end
function mcl_structures.get_struct(file) function mcl_structures.get_struct(file)
@ -124,7 +193,12 @@ end
function mcl_structures.generate_desert_well(pos, rot) function mcl_structures.generate_desert_well(pos, rot)
local newpos = {x=pos.x,y=pos.y-2,z=pos.z} local newpos = {x=pos.x,y=pos.y-2,z=pos.z}
local path = modpath.."/schematics/mcl_structures_desert_well.mts" 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 end
function mcl_structures.generate_igloo(pos, rotation, pr) function mcl_structures.generate_igloo(pos, rotation, pr)
@ -227,7 +301,7 @@ end
function mcl_structures.generate_igloo_top(pos, pr) function mcl_structures.generate_igloo_top(pos, pr)
-- FIXME: This spawns bookshelf instead of furnace. Fix this! -- 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 newpos = {x=pos.x,y=pos.y-1,z=pos.z}
local path = modpath.."/schematics/mcl_structures_igloo_top.mts" local path = modpath.."/schematics/mcl_structures_igloo_top.mts"
local rotation = tostring(pr:next(0,3)*90) local rotation = tostring(pr:next(0,3)*90)

View File

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

View File

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