diff --git a/.luacheckrc b/.luacheckrc index 4433696..17eb7be 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -14,5 +14,5 @@ read_globals = { "minetest", -- mods - "mapblock_lib", "mtt" + "mapblock_lib", "mtt", "Promise" } diff --git a/autoplace.lua b/autoplace.lua index 33e0c70..f7ce427 100644 --- a/autoplace.lua +++ b/autoplace.lua @@ -44,24 +44,21 @@ function building_lib.autoplace(mapblock_pos, playername, autoplacer_name, enabl return false, building_name end - local err - success, err = building_lib.build(mapblock_pos, playername, building_name, rotation) - if not success then - return success, err - end - - local autoplacer = building_lib.get_autoplacer(autoplacer_name) - if enable_propagation and autoplacer.propagate then - -- propagate changes - for _, dir in ipairs(autoplacer.propagation_dirs or default_propagation_dirs) do - local offset_mapblock_pos = vector.add(mapblock_pos, dir) - success = building_lib.check_condition_table(autoplacer.propagate, offset_mapblock_pos) - if success then - -- selector matches, propagate autobuild - building_lib.autoplace(offset_mapblock_pos, playername, autoplacer_name, false) + local p = building_lib.build(mapblock_pos, playername, building_name, rotation) + p:next(function() + local autoplacer = building_lib.get_autoplacer(autoplacer_name) + if enable_propagation and autoplacer.propagate then + -- propagate changes + for _, dir in ipairs(autoplacer.propagation_dirs or default_propagation_dirs) do + local offset_mapblock_pos = vector.add(mapblock_pos, dir) + success = building_lib.check_condition_table(autoplacer.propagate, offset_mapblock_pos) + if success then + -- selector matches, propagate autobuild + building_lib.autoplace(offset_mapblock_pos, playername, autoplacer_name, false) + end end end - end + end) - return true + return p end diff --git a/build.lua b/build.lua index 3861be0..c5df998 100644 --- a/build.lua +++ b/build.lua @@ -39,13 +39,12 @@ function building_lib.can_build(mapblock_pos, _, building_name, rotation) return true end -function building_lib.build(mapblock_pos, playername, building_name, rotation, callback) - callback = callback or function() 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 false, message + return Promise.rejected(message) end local building_def = building_lib.get_building(building_name) @@ -84,8 +83,11 @@ function building_lib.build(mapblock_pos, playername, building_name, rotation, c replacements = building_def.replace(mapblock_pos, building_def) end + local promise = Promise.new() + placement.place(placement, mapblock_pos, building_def, replacements, rotation, function() - callback() + promise:resolve() + if old_building_info then -- replacement local old_building_def = building_lib.get_building(old_building_info.name) @@ -111,7 +113,7 @@ function building_lib.build(mapblock_pos, playername, building_name, rotation, c }) end end) - return true + return promise end -- mapgen build shortcut, only for 1x1x1 sized buildings diff --git a/build.spec.lua b/build.spec.lua index 48bc8b5..ee4f7da 100644 --- a/build.spec.lua +++ b/build.spec.lua @@ -13,31 +13,29 @@ building_lib.register_building("building_lib:dummy_v2", { } }) +local mapblock_pos = {x=0, y=0, z=0} +local building_name = "building_lib:dummy" +local rotation = 0 +local playername = "singleplayer" + + mtt.register("build", function(callback) -- clear store building_lib.store:clear() - local mapblock_pos = {x=0, y=0, z=0} - local building_name = "building_lib:dummy" - local rotation = 0 - local playername = "singleplayer" - -- try to build local success, err = building_lib.can_build(mapblock_pos, playername, building_name, rotation) assert(not err) assert(success) -- build - local callback_called = false - success, err = building_lib.build(mapblock_pos, playername, building_name, rotation, - function() callback_called = true end - ) - assert(not err) - assert(success) - assert(callback_called) + building_lib.build(mapblock_pos, playername, building_name, rotation) + :next(callback) +end) +mtt.register("try build again", function(callback) -- try to build again - success, err = building_lib.can_build(mapblock_pos, playername, building_name, rotation) + local success, err = building_lib.can_build(mapblock_pos, playername, building_name, rotation) assert(err) assert(not success) @@ -56,16 +54,13 @@ mtt.register("build", function(callback) assert(success) -- build over - callback_called = false - success, err = building_lib.build(mapblock_pos, playername, "building_lib:dummy_v2", rotation, - function() callback_called = true end - ) - assert(not err) - assert(success) - assert(callback_called) + building_lib.build(mapblock_pos, playername, "building_lib:dummy_v2", rotation) + :next(callback) +end) +mtt.register("remove and verify", function(callback) -- try to remove - success, err = building_lib.can_remove(mapblock_pos) + local success, err = building_lib.can_remove(mapblock_pos) assert(not err) assert(success) @@ -75,7 +70,7 @@ mtt.register("build", function(callback) assert(success) -- check - info = building_lib.get_placed_building_info(mapblock_pos) + local info = building_lib.get_placed_building_info(mapblock_pos) assert(info == nil) callback() @@ -85,23 +80,12 @@ mtt.benchmark("build", function(callback, iterations) -- clear store building_lib.store:clear() - local mapblock_pos = {x=0, y=0, z=0} - local building_name = "building_lib:dummy" - local rotation = 0 - local playername = "singleplayer" - for _=1,iterations do -- build - local callback_called = false - local success, err = building_lib.build(mapblock_pos, playername, building_name, rotation, - function() callback_called = true end - ) - assert(not err) - assert(success) - assert(callback_called) + building_lib.build(mapblock_pos, playername, building_name, rotation) -- remove - success, err = building_lib.remove(mapblock_pos) + local success, err = building_lib.remove(mapblock_pos) assert(not err) assert(success) end diff --git a/build_over.spec.lua b/build_over.spec.lua index 384d6b3..b4a3650 100644 --- a/build_over.spec.lua +++ b/build_over.spec.lua @@ -15,41 +15,38 @@ building_lib.register_building("building_lib:dummy_extension", { } }) -mtt.register("build-over", function(callback) +local mapblock_pos = {x=0, y=0, z=0} +local playername = "singleplayer" + +mtt.register("build-over (success)", function(callback) -- clear store building_lib.store:clear() - local mapblock_pos = {x=0, y=0, z=0} - local rotation = 0 - local playername = "singleplayer" - -- build - local callback_called = false - local success, err = building_lib.build(mapblock_pos, playername, "building_lib:dummy_base", rotation, - function() callback_called = true end - ) - assert(not err) - assert(success) - assert(callback_called) - - -- build over (wrong angle) - success, err = building_lib.build(mapblock_pos, playername, "building_lib:dummy_extension", 90) - assert(err) - assert(not success) - - -- build over (wrong angle 2) - success, err = building_lib.build(mapblock_pos, playername, "building_lib:dummy_extension", 270) - assert(err) - assert(not success) - - -- build over (180° rotated) - callback_called = false - success, err = building_lib.build(mapblock_pos, playername, "building_lib:dummy_extension", 180, - function() callback_called = true end - ) - assert(not err) - assert(success) - assert(callback_called) - - callback() + building_lib.build(mapblock_pos, playername, "building_lib:dummy_base", 0) + :next(callback) + :catch(callback) end) + +mtt.register("build-over (wrong angle)", function(callback) + -- build + building_lib.build(mapblock_pos, playername, "building_lib:dummy_extension", 90) + :catch(function() + callback() + end) +end) + +mtt.register("build-over (wrong angle 2)", function(callback) + -- build + building_lib.build(mapblock_pos, playername, "building_lib:dummy_extension", 270) + :catch(function() + callback() + end) +end) + +mtt.register("build-over (180°)", function(callback) + -- build + building_lib.build(mapblock_pos, playername, "building_lib:dummy_extension", 180) + :next(callback) + :catch(callback) +end) \ No newline at end of file diff --git a/build_tool.lua b/build_tool.lua index 61ed690..998970c 100644 --- a/build_tool.lua +++ b/build_tool.lua @@ -107,10 +107,10 @@ minetest.register_tool("building_lib:place", { local meta = itemstack:get_meta() local buildingname = meta:get_string("buildingname") - local success, err = building_lib.build(pointed_mapblock_pos, playername, buildingname, rotation) - if not success then + building_lib.build(pointed_mapblock_pos, playername, buildingname, rotation) + :catch(function(err) minetest.chat_send_player(playername, err) - end + end) end, on_step = function(itemstack, player) local playername = player:get_player_name() diff --git a/mod.conf b/mod.conf index e11c322..245045a 100644 --- a/mod.conf +++ b/mod.conf @@ -1,4 +1,4 @@ name = building_lib description = Mapblock granular building placement and tools -depends = mapblock_lib +depends = mapblock_lib, promise optional_depends = mtt \ No newline at end of file diff --git a/readme.md b/readme.md index 4a2b848..640e31f 100644 --- a/readme.md +++ b/readme.md @@ -8,7 +8,12 @@ local success, message = building_lib.can_build(mapblock_pos, playername, building_name, rotation) -- build it there -local success, message = building_lib.build(mapblock_pos, playername, building_name, rotation, callback) +local promise = building_lib.build(mapblock_pos, playername, building_name, rotation, callback) +promise:next(function() + -- success +end):catch(function(e) + -- error +end) -- check if it can be removed local success, message = building_lib.can_remove(mapblock_pos) diff --git a/test/Dockerfile b/test/Dockerfile index f23e3d4..080d30d 100644 --- a/test/Dockerfile +++ b/test/Dockerfile @@ -7,6 +7,7 @@ RUN apk add git &&\ cd /root/.minetest/worlds/world/worldmods &&\ git clone https://github.com/BuckarooBanzay/mtt &&\ git clone https://github.com/BuckarooBanzay/mtzip &&\ + git clone https://github.com/BuckarooBanzay/promise &&\ git clone https://github.com/BuckarooBanzay/mapblock_lib ENTRYPOINT minetestserver --config /minetest.conf \ No newline at end of file