227 lines
No EOL
6.5 KiB
Lua
227 lines
No EOL
6.5 KiB
Lua
local modpath = minetest.get_modpath("abdecor")
|
|
|
|
abdecor = {}
|
|
abdecor.registered_names = {}
|
|
abdecor.registered_advanced_decorations = {}
|
|
abdecor.register_advanced_decoration = function(name, def)
|
|
-- Ensure that all necessary arguments are defined
|
|
if not name or not def.target or not def.fn then
|
|
minetest.warn("[abdecor] Advanced decoration '" .. (name or "???") .. "' was not provided with all necessary values.")
|
|
return false
|
|
end
|
|
|
|
-- Ensure that the name isn't already in use
|
|
local mapgen = nil
|
|
if abdecor.registered_names[name] then
|
|
minetest.warn("[abdecor] Advanced decoration '" .. name .. "' was already registered.")
|
|
return false
|
|
else
|
|
mapgen = {}
|
|
abdecor.registered_names[name] = true
|
|
end
|
|
|
|
-- Check for all_floors + all_ceilings flags which is unsupported due to
|
|
-- undefined mapgen node erasure
|
|
local is_ceiling = false
|
|
local is_water_surface = false
|
|
def.target.flags = def.target.flags or ""
|
|
if def.target.flags and def.target.flags:find("all_floors") and def.target.flags:find("all_ceilings") then
|
|
minetest.warn("[abdecor] Advanced decoration '" .. name .. "' specifies all_floors and all_ceilings which the abdecor API does not support.")
|
|
return false
|
|
else
|
|
is_ceiling = def.target.flags:find("all_ceilings") and true or false
|
|
is_water_surface = def.target.flags:find("water_surface") and true or false
|
|
end
|
|
|
|
-- Register node for targeted mapgen node
|
|
local mapgen_node_name = "abdecor:" .. name .. "_marker"
|
|
minetest.register_node(":" .. mapgen_node_name,{
|
|
drawtype = "airlike",
|
|
sunlight_propagates = true,
|
|
walkable = false,
|
|
pointable = true,
|
|
diggable = false,
|
|
climbable = false,
|
|
buildable_to = true,
|
|
floodable = false,
|
|
groups = { not_in_creative_inventory = 1 },
|
|
})
|
|
|
|
-- Register injected decor for targeted mapgen node placement
|
|
def.target.deco_type = "simple"
|
|
def.target.name = "abdecor:" .. name .. "_decoration"
|
|
def.target.decoration = mapgen_node_name
|
|
minetest.register_decoration(def.target)
|
|
|
|
local decoration_id = minetest.get_decoration_id(def.target.name)
|
|
minetest.set_gen_notify({ decoration = true },{decoration_id})
|
|
mapgen.decoration_id = "decoration#" .. decoration_id
|
|
abdecor.registered_advanced_decorations[mapgen.decoration_id] = mapgen
|
|
|
|
-- Compute decoration placement offset for automatic erasure during mapgen
|
|
mapgen.offset = (is_water_surface and 0 or 1) * (is_ceiling and -1 or 1) + (def.target.place_offset_y or 0)
|
|
|
|
-- Capture placement function and voxelmanip flags for later use
|
|
mapgen.fn = def.fn
|
|
|
|
if not def.flags then
|
|
def.flags = {}
|
|
end
|
|
|
|
if def.flags.param2 == nil then
|
|
def.flags.param2 = false
|
|
end
|
|
if def.flags.liquid == nil then
|
|
def.flags.liquid = false
|
|
end
|
|
if def.flags.schematic == nil then
|
|
def.flags.schematic = false
|
|
end
|
|
mapgen.flags = def.flags
|
|
|
|
-- Success!
|
|
return true
|
|
end
|
|
|
|
-- Schematic placement helper functions
|
|
abdecor._place_schematic_check = function(args)
|
|
-- Fail or set defaults for missing arguments
|
|
if not args.pos or not args.schematic then
|
|
return nil -- fail
|
|
end
|
|
|
|
args.rotation = args.rotation or "random"
|
|
args.replacements = args.replacements or {}
|
|
args.force_placement = (args.force_placement == nil) and false or true
|
|
args.flags = args.flags or ""
|
|
|
|
-- Arguments are good
|
|
return true
|
|
end
|
|
|
|
-- Register targeted mapgen generation
|
|
local vdata = {}
|
|
local vparam2 = {}
|
|
minetest.register_on_generated(function(minp, maxp, seed)
|
|
-- Lazy initializers for mapgen
|
|
local mapgen = {}
|
|
|
|
local is_mapgen_init = false
|
|
local function mapgen_init()
|
|
if not is_mapgen_init then
|
|
mapgen.vm, mapgen.emin, mapgen.emax = minetest.get_mapgen_object("voxelmanip")
|
|
mapgen.va = VoxelArea:new({MinEdge = mapgen.emin, MaxEdge = mapgen.emax})
|
|
is_mapgen_init = true
|
|
end
|
|
end
|
|
|
|
local is_vm_data_init = false
|
|
local function vm_data_init()
|
|
mapgen_init()
|
|
if not is_vm_data_init then
|
|
mapgen.vm:get_data(vdata)
|
|
is_vm_data_init = true
|
|
end
|
|
end
|
|
|
|
local is_vm_param2_init = false
|
|
local function vm_param2_init()
|
|
mapgen_init()
|
|
if not is_vm_param2_init then
|
|
mapgen.vm:get_param2_data(vparam2)
|
|
is_vm_param2_init = true
|
|
end
|
|
end
|
|
|
|
local is_schematic_init = false
|
|
local function schematic_init()
|
|
if not is_schematic_init then
|
|
mapgen.place_schematic = function(args)
|
|
mapgen.vm:set_data(vdata)
|
|
local retval = abdecor._place_schematic_check(args) and minetest.place_schematic_on_vmanip(mapgen.vm,args.pos,args.schematic,args.rotation,args.replacements,args.force_placement,args.flags)
|
|
if retval then
|
|
mapgen.vm:get_data(vdata)
|
|
end
|
|
return retval
|
|
end
|
|
is_schematic_init = true
|
|
end
|
|
end
|
|
|
|
mapgen.calc_lighting = function(p1,p2,propagate_shadow)
|
|
return mapgen.vm:calc_lighting(p1,p2,propagate_shadow)
|
|
end
|
|
|
|
local is_liquid = false
|
|
|
|
-- Place any targeted decorations that were generated
|
|
local gennotify = minetest.get_mapgen_object("gennotify")
|
|
for decoration_id,decorations in pairs(gennotify) do
|
|
local decoration = abdecor.registered_advanced_decorations[decoration_id]
|
|
if decoration then
|
|
-- Initialize vm data
|
|
vm_data_init()
|
|
|
|
-- Initialize param2 data if needed
|
|
if decoration.flags.param2 then
|
|
vm_param2_init()
|
|
end
|
|
|
|
-- Initialize schematic placement function if needed
|
|
if decoration.flags.schematic then
|
|
schematic_init()
|
|
end
|
|
|
|
-- Note liquid status
|
|
if decoration.flags.liquid then
|
|
is_liquid = true
|
|
end
|
|
|
|
-- Erase dummy mapgen nodes and process decorations
|
|
for i = 1, #decorations do
|
|
local pos = decorations[i]
|
|
vdata[mapgen.va:index(pos.x,pos.y + decoration.offset,pos.z)] = minetest.CONTENT_AIR
|
|
decoration.fn({
|
|
pos = pos,
|
|
voxelarea = mapgen.va,
|
|
data = vdata,
|
|
param2 = vparam2,
|
|
minp = minp,
|
|
maxp = maxp,
|
|
seed = seed,
|
|
place_schematic = mapgen.place_schematic,
|
|
calc_lighting = mapgen.calc_lighting,
|
|
index2d = function(x,z) -- (portions of this function © FaceDeer 2018, licensed MIT, copied from https://github.com/minetest-mods/mapgen_helper/blob/2521562a42472271d9d761f2b1e84ead59250a14/noise_manager.lua)
|
|
if type(x) == "table" then -- accept x/y/z pos table
|
|
z = x.z
|
|
x = x.x
|
|
end
|
|
return x - minp.x +
|
|
(maxp.x - minp.x + 1)
|
|
*(z - minp.z)
|
|
+ 1
|
|
end,
|
|
})
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Write data back to voxelmanip if necessary
|
|
if is_mapgen_init then
|
|
if is_vm_data_init then
|
|
mapgen.vm:set_data(vdata)
|
|
end
|
|
|
|
if is_vm_param2_init then
|
|
mapgen.vm:set_param2_data(vparam2)
|
|
end
|
|
|
|
if is_liquid then
|
|
mapgen.vm:update_liquids()
|
|
end
|
|
|
|
if is_vm_data_init or is_vm_param2_init then
|
|
mapgen.vm:write_to_map()
|
|
end
|
|
end
|
|
end) |