building_lib/build.lua
BuckarooBanzay afee95e2d2 use promises
2023-04-17 07:42:43 +02:00

144 lines
4.2 KiB
Lua

local function apply_rotation_offset(building_def, rotation)
if building_def.rotation_offset then
rotation = rotation + building_def.rotation_offset
while rotation >= 360 do
rotation = rotation - 360
end
end
return rotation
end
function building_lib.can_build(mapblock_pos, _, building_name, rotation)
local building_def = building_lib.get_building(building_name)
if not building_def then
return false, "Building not found: '" .. building_name .. "'"
end
-- check placement definition
local placement = building_lib.get_placement(building_def.placement)
rotation = apply_rotation_offset(building_def, rotation)
-- check the conditions on every mapblock the building would occupy
local size, message = placement.get_size(placement, mapblock_pos, building_def, rotation)
if not size then
return false, message or "size check '" .. building_def.placement .. "' failed"
end
local mapblock_pos2 = vector.add(mapblock_pos, vector.subtract(size, 1))
local success
success, message = building_lib.check_condition_groups(mapblock_pos, mapblock_pos2, building_def.conditions)
if not success then
return false, message
end
-- all checks ok
return true
end
function building_lib.build(mapblock_pos, playername, building_name, rotation)
rotation = rotation or 0
local success, message = building_lib.can_build(mapblock_pos, playername, building_name, rotation)
if not success then
return Promise.rejected(message)
end
local building_def = building_lib.get_building(building_name)
assert(building_def)
rotation = apply_rotation_offset(building_def, rotation)
-- place into world
local placement = building_lib.get_placement(building_def.placement)
local size = placement.get_size(placement, mapblock_pos, building_def, rotation)
-- fetch current building-def, if any
local old_building_info = building_lib.get_placed_building_info(mapblock_pos)
-- write new data
mapblock_lib.for_each(mapblock_pos, vector.add(mapblock_pos, vector.subtract(size, 1)), function(offset_mapblock_pos)
if vector.equals(offset_mapblock_pos, mapblock_pos) then
-- origin
building_lib.store:merge(offset_mapblock_pos, {
building = {
name = building_def.name,
size = size,
rotation = rotation,
owner = playername
}
})
else
-- link to origin
building_lib.store:merge(offset_mapblock_pos, mapblock_lib.create_data_link(mapblock_pos))
end
end)
-- get or calculate replacements
local replacements = building_def.replace
if type(building_def.replace) == "function" then
replacements = building_def.replace(mapblock_pos, building_def)
end
local promise = Promise.new()
placement.place(placement, mapblock_pos, building_def, replacements, rotation, function()
promise:resolve()
if old_building_info then
-- replacement
local old_building_def = building_lib.get_building(old_building_info.name)
building_lib.fire_event("replaced", {
playername = playername,
mapblock_pos = mapblock_pos,
old_building_def = old_building_def,
old_building_info = old_building_info,
building_def = building_def,
replacements = replacements,
rotation = rotation,
size = size
})
else
-- new build
building_lib.fire_event("placed", {
playername = playername,
mapblock_pos = mapblock_pos,
building_def = building_def,
replacements = replacements,
rotation = rotation,
size = size
})
end
end)
return promise
end
-- mapgen build shortcut, only for 1x1x1 sized buildings
function building_lib.build_mapgen(mapblock_pos, building_name, rotation)
local building_def = building_lib.get_building(building_name)
local placement = building_lib.get_placement(building_def.placement)
-- get or calculate replacements
local replacements = building_def.replace
if type(building_def.replace) == "function" then
replacements = building_def.replace(mapblock_pos, building_def)
end
building_lib.store:merge(mapblock_pos, {
building = {
name = building_def.name,
rotation = rotation,
owner = building_lib.mapgen_owned
}
})
placement.place(placement, mapblock_pos, building_def, replacements, rotation)
building_lib.fire_event("placed_mapgen", {
mapblock_pos = mapblock_pos,
building_def = building_def,
rotation = rotation
})
end