From c6754fd39ecf6ac5558f51f7f174f8cd0c76bcc4 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 12 Jan 2022 03:27:28 +0400 Subject: [PATCH] Start adding new structures API --- mods/CORE/mcl_mapgen/API.md | 2 +- mods/ITEMS/mcl_portals/portal_gateway.lua | 12 +- mods/MAPGEN/mcl_end_island/init.lua | 18 ++- mods/MAPGEN/mcl_structures/init.lua | 132 +++++++++++++++++----- mods/MAPGEN/mcl_structures/mod.conf | 6 +- mods/MAPGEN/mcl_villages/buildings.lua | 18 ++- 6 files changed, 131 insertions(+), 57 deletions(-) diff --git a/mods/CORE/mcl_mapgen/API.md b/mods/CORE/mcl_mapgen/API.md index 1587e19f4..bcd6d2f8f 100644 --- a/mods/CORE/mcl_mapgen/API.md +++ b/mods/CORE/mcl_mapgen/API.md @@ -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)`: diff --git a/mods/ITEMS/mcl_portals/portal_gateway.lua b/mods/ITEMS/mcl_portals/portal_gateway.lua index ca15a61d5..48d2b52fd 100644 --- a/mods/ITEMS/mcl_portals/portal_gateway.lua +++ b/mods/ITEMS/mcl_portals/portal_gateway.lua @@ -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() diff --git a/mods/MAPGEN/mcl_end_island/init.lua b/mods/MAPGEN/mcl_end_island/init.lua index b0e5e68eb..5a0bde2c7 100644 --- a/mods/MAPGEN/mcl_end_island/init.lua +++ b/mods/MAPGEN/mcl_end_island/init.lua @@ -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) diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index bb9e5e8df..d54cd600f 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -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) diff --git a/mods/MAPGEN/mcl_structures/mod.conf b/mods/MAPGEN/mcl_structures/mod.conf index 3150c7cec..f22f7c738 100644 --- a/mods/MAPGEN/mcl_structures/mod.conf +++ b/mods/MAPGEN/mcl_structures/mod.conf @@ -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 diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua index 69b1c84da..7c70e1d3b 100644 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ b/mods/MAPGEN/mcl_villages/buildings.lua @@ -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