From b5a95b10dc9638050d3dbf34929960e649cb9011 Mon Sep 17 00:00:00 2001 From: Alexander Weber Date: Mon, 30 Jul 2018 22:32:40 +0200 Subject: [PATCH] schemlib update. Use persistance manager. Optimize formspecs --- chest.lua | 362 ++++++++++++++++------------------------------ init.lua | 64 ++------ npcf-worker.lua | 13 +- smartfs-forms.lua | 145 +++++++++++-------- 4 files changed, 228 insertions(+), 356 deletions(-) diff --git a/chest.lua b/chest.lua index 508e85e..fbda7d7 100644 --- a/chest.lua +++ b/chest.lua @@ -3,45 +3,36 @@ local dprint = townchest.dprint_off --debug local smartfs = townchest.smartfs -local ASYNC_WAIT=0.05 -- schould be > 0 to restrict performance consumption - -------------------------------------- -- Chest class and interface -------------------------------------- -local chest = { - list = {}, -} +local chest = {} townchest.chest = chest local chest_class = {} -chest_class.__index = chest_class +local chest_class_mt = {__index = chest_class} -------------------------------------- --- Get or create new chest for position +-- object constructor +-------------------------------------- +function chest.new() + return setmetatable({}, chest_class_mt) +end + +-------------------------------------- +-- Get or create new chest object for position -------------------------------------- function chest.get(pos) - local key = minetest.pos_to_string(pos) - local self = nil - if chest.list[key] then - self = chest.list[key] - self.info = minetest.deserialize(self.meta:get_string("chestinfo")) or {} - else - self = chest.new() - self.key = key - self.pos = pos - self.meta = minetest.get_meta(pos) --just pointer - self.info = minetest.deserialize(self.meta:get_string("chestinfo")) or {} - if not self.info.anchor_pos then - self.info.anchor_pos = pos - self:persist_info() - end - if not self.info.chest_facedir then - local chestnode = minetest.get_node(pos) - self.info.chest_facedir = chestnode.param2 - self.info.mirrored = false - end - townchest.chest.list[key] = self - self:restore() + local key = "townchest:"..minetest.pos_to_string(pos) + local self = chest.new() + self.pos = pos + self.meta = minetest.get_meta(pos) + self.plan = schemlib.plan_manager.get_plan(key) + if not self.plan then + self.plan = schemlib.plan.new(key, pos) + schemlib.plan_manager.set_plan(self.plan) end + self.info = self.plan.data + self.info.facedir = minetest.get_node(pos).param2 return self end @@ -49,239 +40,142 @@ end -- Initialize new chest object -------------------------------------- function chest.create(pos) - local key = minetest.pos_to_string(pos) - dprint("clean key", key) - chest.list[key] = nil --delete old reference - minetest.get_meta(pos):set_string("chestinfo","") + local key = "townchest:"..minetest.pos_to_string(pos) + schemlib.plan_manager.delete_plan(key) local self = chest.get(pos) - self.info.stage = "select" - dprint("created chest object", self) return self end -------------------------------------- --- object constructor --------------------------------------- -function chest.new() - local self = setmetatable({}, chest_class) - self.__index = chest_class - return self -end - - --------------------------------------- --- save persistant chest info to the chest metadata --------------------------------------- -function chest_class:persist_info() -- the read info is in get method - self.meta:set_string("chestinfo", minetest.serialize(self.info)) -end - --------------------------------------- --- set_plan_form - set formspec to specific widget in plan processing chaing +-- set_plan_form - set formspec to specific widget in plan processing chain -------------------------------------- function chest_class:set_plan_form() - self:persist_info() - if self.info.stage == "finished" then -- no updates if finished + local status = self.plan:get_status() + if status == "finished" then -- no updates if finished smartfs.get("townchest:build_finished"):attach_to_node(self.pos) self.meta:set_string("infotext", "Building finished") - elseif not self.plan then + elseif status == "build" or status == "pause" then + smartfs.get("townchest:build_status"):attach_to_node(self.pos) + self.meta:set_string("infotext", "Plan size:"..self.info.nodecount) + elseif self.info.nodecount > 0 then + smartfs.get("townchest:configure"):attach_to_node(self.pos) + self.meta:set_string("infotext", "Configure - Plan size:"..self.info.nodecount) + else smartfs.get("townchest:plan"):attach_to_node(self.pos) self.meta:set_string("infotext", "please select a building plan") - elseif self.plan:get_status() == "new" then - smartfs.get("townchest:configure"):attach_to_node(self.pos) - self.meta:set_string("infotext", "Configure - Plan size:"..self.plan.data.nodecount) - else - smartfs.get("townchest:build_status"):attach_to_node(self.pos) - self.meta:set_string("infotext", "Plan size:"..self.plan.data.nodecount) end end -------------------------------------- --- Show message - set formspec to specific widget +-- Show message - set formspec to specific widget for 2 seconds -------------------------------------- -function chest_class:show_message(message) - self.infotext = message - self:persist_info() - smartfs.get("townchest:status"):attach_to_node(self.pos) +function chest_class:show_message(message, stop) self.meta:set_string("infotext", message) - minetest.after(1.5, self.set_plan_form, self) + smartfs.get("townchest:status"):attach_to_node(self.pos) + + if stop == false then + self:run_async(function(chest) + chest:set_plan_form() + end, 2) + end end - -------------------------------------- --- update informations on formspecs +-- update informations on formspecs during build process (called by nodetimer) -------------------------------------- function chest_class:update_info() - if self.info.stage == "ready" then - self.meta:set_string("infotext", "Build in process - nodes left:"..self.plan.data.nodecount) - elseif self.infotext then - self.meta:set_string("infotext", self.infotext) + local status = self.plan:get_status() + if status == "pause" and self.info.npc_build and self.info.nodecount == 0 then + self.info.npc_build = false + self.plan:set_status("finished") end - self:persist_info() - -- send no data / do not change form, but triger onInput to update fields - smartfs.nodemeta_on_receive_fields(self.pos, "", {}) -end - --------------------------------------- --- Create the task that should be managed by chest --------------------------------------- -function chest_class:set_rawdata(taskname) - self.plan = schemlib.plan.new(minetest.pos_to_string(self.pos), self.pos) - self.plan.chest = self - self.plan.on_status = function(plan, status) -- hook to trigger chest update each node placement - if plan.chest then - dprint("hook called:", plan.plan_id, status) - if status == "finished" then - plan.chest:set_finished() - else - plan.chest:update_info() - end - end + if status == "build" or self.info.npc_build then + minetest.get_node_timer(self.pos):start(2) end - - self.info.taskname = taskname or self.info.taskname - - if self.info.taskname == "file" then - -- check if file could be read - if not self.info.filename then - -- something wrong, back to file selection - self:show_message("No file selected") - return - end - self.plan:read_from_schem_file(townchest.modpath.."/buildings/"..self.info.filename) - if self.plan.data.nodecount == 0 then - self:persist_info() - self:show_message("No building found in ".. self.info.filename) - return - end - self.info.stage = self.restore_stage or "loaded" -- do not override the restoral stage - self:show_message("Building Plan loaded ".. self.info.filename) - - elseif self.info.taskname == "generate" then - -- set directly instead of counting each step - self.plan.data.min_pos = { x=1, y=1, z=1 } - self.plan.data.max_pos = { x=self.info.genblock.x, y=self.info.genblock.y, z=self.info.genblock.z} - self.plan.data.ground_y = 0 - local filler_node = {name = "default:cobble"} - if self.info.genblock.variant == 1 then - -- nothing special, just let fill them with air - - elseif self.info.genblock.variant == 2 then - -- Fill with stone - for x = 1, self.info.genblock.x do - for y = 1, self.info.genblock.y do - for z = 1, self.info.genblock.z do - self.plan:add_node({x=x,y=y,z=z}, schemlib.node.new(filler_node)) - end - end - end - - elseif self.info.genblock.variant == 3 then - -- Build a box - for x = 1, self.info.genblock.x do - for y = 1, self.info.genblock.y do - for z = 1, self.info.genblock.z do - if x == 1 or x == self.info.genblock.x or - y == 1 or y == self.info.genblock.y or - z == 1 or z == self.info.genblock.z then - self.plan:add_node({x=x,y=y,z=z}, schemlib.node.new(filler_node)) - end - end - end - end - - -- build ground level under chest - self.plan.data.ground_y = 1 - - -- Build a plate - elseif self.info.genblock.variant == 4 then - local y = self.plan.data.min_pos.y - self.plan.data.max_pos.y = self.plan.data.min_pos.y - for x = 1, self.info.genblock.x do - for z = 1, self.info.genblock.z do - self.plan:add_node({x=x,y=y,z=z}, schemlib.node.new(filler_node)) - end - end - -- build ground level under chest - self.plan.data.ground_y = 1 - end - self.info.stage = self.restore_stage or "loaded" - self:show_message("Simple form loaded") - else - self:show_message("Unknown task") - end - - if not self.restore_stage or self.restore_stage == "loaded" then - self.restore_stage = nil - else - self:run_async(self.seal_building_plan) - end -end - - --------------------------------------- --- Call a task semi-async trough minetest.after() --------------------------------------- -function chest_class:run_async(func) - local function async_call(pos) - local chest = townchest.chest.get(pos) - chest.info = minetest.deserialize(chest.meta:get_string("chestinfo")) --get add info - if not chest.info then -- chest removed during the load, stop processing - townchest.chest.list[chest.key] = nil - return - end - if func(chest) then --call the next chain / repeat function call - chest:run_async(func) - end - end - self:persist_info() - minetest.after(ASYNC_WAIT, async_call, self.pos) -end - --------------------------------------- --- Post-processing of plan preparation --------------------------------------- -function chest_class:seal_building_plan() - -- apply configuration to the building - self.plan.anchor_pos = self.info.anchor_pos - self.plan.facedir = self.info.chest_facedir - self.plan.mirrored = self.info.mirrored - self.plan:apply_flood_with_air() - self.plan:del_node(self.plan:get_plan_pos(self.pos)) -- Do not override the chest node - self.info.stage = "ready" - self.restore_stage = nil - self.plan:set_status("build") - if self.info.npc_build == true then - townchest.npc.enable_build(self.plan) - end - if self.info.instantbuild == true then - self.plan:do_add_all_voxel_async() - end - self:set_plan_form() -end - --------------------------------------- --- restore chest state after shutdown (and maybe suspend if implemented) --------------------------------------- -function chest_class:restore() - dprint("restoral info", dump(self.info)) - if self.info.stage and self.info.stage ~= "select" - and self.info.stage ~= "finished" then -- do not restore finished plans - self.restore_stage = self.info.stage - self:persist_info() - self:set_rawdata() - else + if self.info.ui_updates then self:set_plan_form() end end -------------------------------------- --- Disable all and set the plan finished +-- Run chest method async -------------------------------------- -function chest_class:set_finished() - self.info.stage = "finished" - self.info.npc_build = false - self.info.instantbuild = false - self:set_plan_form() - townchest.npc.disable_build(self.plan) +function chest_class:run_async(func, delay) + local function async_call(pos) + local key = "townchest:"..minetest.pos_to_string(pos) + local plan = schemlib.plan_manager.get_plan(key) + if not plan then + return + end + local chest = townchest.chest.get(pos) + if func(chest) then + chest:run_async(func, delay or 0.2) + end + end + + minetest.after(delay or 0.2, async_call, self.pos) +end + +-------------------------------------- +-- Generate simple form +-------------------------------------- +function chest_class:generate_simple_form() + local genblock = self.info.genblock + -- set directly instead of counting each step + self.info.min_pos = { x=1, y=1, z=1 } + self.info.max_pos = { x=genblock.x, y=genblock.y, z=genblock.z} + self.info.ground_y = 0 + local filler_node = "default:cobble" + if genblock.variant == 1 then + for x = 1, genblock.x do + for y = 1, genblock.y do + for z = 1, genblock.z do + if x == 1 or x == genblock.x or + y == 1 or y == genblock.y or + z == 1 or z == genblock.z then + self.plan:add_node({x=x,y=y,z=z}, "air") + end + end + end + end + + elseif genblock.variant == 2 then + -- Fill with stone + for x = 1, genblock.x do + for y = 1, genblock.y do + for z = 1, genblock.z do + self.plan:add_node({x=x,y=y,z=z}, filler_node) + end + end + end + + elseif genblock.variant == 3 then + -- Build a box + for x = 1, genblock.x do + for y = 1, genblock.y do + for z = 1, genblock.z do + if x == 1 or x == genblock.x or + y == 1 or y == genblock.y or + z == 1 or z == genblock.z then + self.plan:add_node({x=x,y=y,z=z}, filler_node) + end + end + end + end + + -- build ground level under chest + self.info.ground_y = 1 + + -- Build a plate + elseif genblock.variant == 4 then + local y = self.info.min_pos.y + self.info.max_pos.y = self.info.min_pos.y + for x = 1, genblock.x do + for z = 1, genblock.z do + self.plan:add_node({x=x,y=y,z=z}, filler_node) + end + end + -- build ground level under chest + self.info.ground_y = 1 + end end diff --git a/init.lua b/init.lua index d993ae7..75031aa 100644 --- a/init.lua +++ b/init.lua @@ -10,7 +10,7 @@ townchest.dprint = dprint townchest.dprint_off = dprint_off -- UI tools/ formspec -local smartfs = dofile(townchest.modpath.."/smartfs.lua") +local smartfs = dofile(townchest.modpath.."/smartfs.lua") townchest.smartfs = smartfs dofile(townchest.modpath.."/smartfs-forms.lua") @@ -32,22 +32,11 @@ function townchest.files_get() return t end - - ------------------------------------------------ --- __cheststep - triggered building step ------------------------------------------------ ---[[ -local __cheststep = function(pos) - local chest = townchest.chest.get(pos) - chest:do_cheststep() -end -]] - ----------------------------------------------- -- on_construct - if the chest is placed ----------------------------------------------- local __on_construct = function(pos) + dprint("on_construct") local chest = townchest.chest.create(pos) --create new chest utils instance chest:set_plan_form() end @@ -57,23 +46,18 @@ end ----------------------------------------------- local __on_destruct = function(pos) dprint("on_destruct") - -- remove all cached chest references - local key = minetest.pos_to_string(pos) - local chest = townchest.chest.list[key] - if chest and chest.plan then - townchest.npc.disable_build(chest.plan) - townchest.chest.list[key] = nil --delete old reference + local key = "townchest:"..minetest.pos_to_string(pos) + local plan = schemlib.plan_manager.get_plan(key) + if plan then + plan:set_status("pause") + schemlib.plan_manager.delete_plan(key) end end ------------------------------------------------ --- restore - called in lbm, restore chest internal data if the server was restarted ------------------------------------------------ - -local __restore = function(pos, node) - local chest = townchest.chest.get(pos) --just get once to trigger restoral +local __on_timer = function(pos, elapsed) + local chest = townchest.chest.get(pos) + return chest:update_info() end - ----------------------------------------------- -- on_punch ----------------------------------------------- @@ -95,7 +79,6 @@ local __allow_metadata_inventory_move = function(pos, from_list, from_index, to_ return 0 end - ----------------------------------------------- -- allow_metadata_inventory_put ----------------------------------------------- @@ -123,42 +106,17 @@ minetest.register_node("townchest:chest", { sounds = default.node_sound_wood_defaults(), on_construct = __on_construct, on_receive_fields = function(pos, formname, fields, sender) - local chest = townchest.chest.get(pos) smartfs.nodemeta_on_receive_fields(pos, formname, fields, sender) - chest.meta:set_string("chestinfo", minetest.serialize(chest.info)) --save chest data end, after_dig_node = __on_destruct, on_punch = __on_punch, + on_timer = __on_timer, on_metadata_inventory_put = __on_metadata_inventory_put, allow_metadata_inventory_move = __allow_metadata_inventory_move, allow_metadata_inventory_put = __allow_metadata_inventory_put, allow_metadata_inventory_take = __allow_metadata_inventory_take, }) ---[[ ------------------------------------------------ --- register_abm - builds the building ------------------------------------------------ -minetest.register_abm({ - nodenames = {"townchest:chest"}, - interval = 1, - chance = 1, - action = __cheststep, -}) -]] - ------------------------------------------------ --- register_lbm - restore all chestinfo ------------------------------------------------ - -minetest.register_lbm({ - name = "townchest:chest", - nodenames = {"townchest:chest"}, - run_at_every_load = true, - action = __restore -}) - - ----------------------------------------------- -- register craft recipe for the chest ----------------------------------------------- diff --git a/npcf-worker.lua b/npcf-worker.lua index 0cae7ff..83eca52 100644 --- a/npcf-worker.lua +++ b/npcf-worker.lua @@ -3,12 +3,9 @@ local dprint = townchest.dprint_off --debug local function dummy_func() end townchest.npc = { - spawn_nearly = dummy_func, - enable_build = dummy_func, - disable_build = dummy_func, + spawn_nearly = dummy_func } - if minetest.global_exists("schemlib_builder_npcf") then townchest.npc.supported = true @@ -37,12 +34,4 @@ if minetest.global_exists("schemlib_builder_npcf") then npc:update() end end - - function townchest.npc.enable_build(plan) - schemlib_builder_npcf.plan_manager:add(plan) - end - - function townchest.npc.disable_build(plan) - schemlib_builder_npcf.plan_manager:set_finished(plan) - end end diff --git a/smartfs-forms.lua b/smartfs-forms.lua index 9a25dc0..89ccde2 100644 --- a/smartfs-forms.lua +++ b/smartfs-forms.lua @@ -9,11 +9,14 @@ townchest.specwidgets = {} local function allform_header(state) state:size(16,10) state:button(0,0,2,1,"allform_sel_plan", "Building Plan"):onClick(function(self) - townchest.chest.get(state.location.pos):set_plan_form() + local chest = townchest.chest.get(state.location.pos) + chest.info.ui_updates = true + chest:set_plan_form() end) if minetest.global_exists("schemlib_builder_npcf") then state:button(2,0,2,1,"allform_sel_npc", "NPC / Builder"):onClick(function(self) + townchest.chest.get(state.location.pos).info.ui_updates = false smartfs.get("townchest:npc_form"):attach_to_node(state.location.pos) end) end @@ -104,7 +107,6 @@ local function plan_form(state) chest.info.genblock.z = tonumber(state:get("z"):getText()) chest.info.genblock.variant = state:get("variant"):getSelected() chest.info.genblock.variant_name = state:get("variant"):getSelectedItem() - chest:persist_info() end) tab_controller:tab_add("tab2", tab2) @@ -112,12 +114,27 @@ local function plan_form(state) state:button(0,8.5,2,0.5,"load","Load"):onClick(function(self) local selected_tab = tab_controller:get_active_name() if selected_tab == "tab1" then - chest.info.filename = state:get("tab1_view"):getContainerState():get("fileslist"):getSelectedItem() - if chest.info.filename then - chest:set_rawdata("file") + local filename = state:get("tab1_view"):getContainerState():get("fileslist"):getSelectedItem() + if not filename then + chest:show_message("Please select a file") + return end + chest:run_async(function(chest) + chest.plan:read_from_schem_file(townchest.modpath.."/buildings/"..filename) + chest.info.townchest_filename = filename + if chest.info.nodecount == 0 then + chest:show_message("No building found in ".. filename) + else + chest:set_plan_form() + end + end) + chest:show_message("loading "..filename, false) elseif selected_tab == "tab2" then - chest:set_rawdata("generate") + chest:run_async(function(chest) + chest:generate_simple_form() + chest:set_plan_form() + end) + chest:show_message("Build simple form", false) end end) @@ -131,12 +148,9 @@ smartfs.create("townchest:plan", plan_form) ----------------------------------------------- local function status_form(state) local chest = townchest.chest.get(state.location.pos) - if not chest.infotext then - print("BUG: no infotext for status dialog!") - return false -- no update - end + local infotext = chest.meta:get_string("infotext") state:size(7,1) - state:label(0,0,"info", chest.infotext) + state:label(0,0,"info", infotext) end smartfs.create("townchest:status", status_form) @@ -146,10 +160,12 @@ local function plan_statistics_widget(state) if chest.plan then building_size = vector.add(vector.subtract(chest.plan.data.max_pos, chest.plan.data.min_pos),1) end - if chest.info.taskname == "file" then - l1_text = "Building "..chest.info.filename.." selected" - elseif chest.info.taskname == "generate" then + if chest.info.townchest_filename then + l1_text = "Building "..chest.info.townchest_filename.." selected" + elseif chest.info.genblock and chest.info.genblock.variant_name then l1_text = "Simple task: "..chest.info.genblock.variant_name + else + l1_text = "Unknown task" end state:label(1,1.5,"l1",l1_text) @@ -159,7 +175,7 @@ local function plan_statistics_widget(state) state:label(1,3.0,"l4","Nodes in plan: "..chest.plan.data.nodecount) end state:label(1,3.5,"l5","Schemlib Anchor high: "..chest.info.anchor_pos.y) - state:label(1,4,"l6","Facedir: "..chest.info.chest_facedir.." Mirror:"..tostring(chest.info.mirrored)) + state:label(1,4,"l6","Facedir: "..chest.info.facedir.." Mirror:"..tostring(chest.info.mirrored)) end ----------------------------------------------- @@ -177,24 +193,43 @@ local build_configuration_form = function(state) state:checkbox(6, 4, "ckb_mirror", "Mirror", chest.info.mirrored):onToggle(function(self,func) chest.info.mirrored = self:getValue() - state:get("l6"):setText("Facedir: "..chest.info.chest_facedir.." Mirror:"..tostring(chest.info.mirrored)) + state:get("l6"):setText("Facedir: "..chest.info.facedir.." Mirror:"..tostring(chest.info.mirrored)) end) - state:button(0,6,2,0.5,"go","Prepared"):onClick(function(self) - townchest.chest.get(state.location.pos):seal_building_plan() - end) - - state:button(2,6,2,0.5,"anchor","Propose Anchor"):onClick(function(self) + state:button(0,6,2,0.5,"flood_bt","Flood with air"):onClick(function(self) local chest = townchest.chest.get(state.location.pos) - chest.plan.facedir = chest.info.chest_facedir - chest.plan.mirrored = chest.info.mirrored - local pos, error = chest.plan:propose_anchor(state.location.pos) - if pos then - chest.info.anchor_pos = pos - state:get("l5"):setText("Schemlib Anchor high: "..pos.y) - else - chest:show_message("Anchor could not be proposed") - end + chest:run_async(function(chest) + chest.plan:apply_flood_with_air() + chest:set_plan_form() + end) + chest:show_message("Flood building with air", false) + end) + + state:button(2,6,2,0.5,"go_bt","Prepared"):onClick(function(self) + local chest = townchest.chest.get(state.location.pos) + chest.plan:set_status("pause") + chest.plan:del_node(chest.plan:get_plan_pos(state.location.pos)) + chest:run_async(function(chest) + schemlib.plan_manager.set_plan(chest.plan) + chest:set_plan_form() + end) + chest:show_message("Save data before run", false) + chest.info.ui_updates = true + chest:set_plan_form() + end) + + state:button(4,6,2,0.5,"anchor_bt","Propose Anchor"):onClick(function(self) + local chest = townchest.chest.get(state.location.pos) + chest:run_async(function(chest) + local pos, error = chest.plan:propose_anchor(state.location.pos) + if pos then + chest.info.anchor_pos = pos + state:get("l5"):setText("Schemlib Anchor high: "..pos.y) + else + chest:show_message("Anchor could not be proposed") + end + end) + chest:show_message("Check Anchor size", false) end) end @@ -216,9 +251,7 @@ local build_status_form = function(state) -- set dynamic values after actions local function set_dynamic_values(state, chest) - state:get("l4"):setText("Nodes left: "..chest.plan.data.nodecount) - if townchest.npc.supported then if chest.info.npc_build == true then state:get("npc_tg"):setId(2) @@ -226,48 +259,45 @@ local build_status_form = function(state) state:get("npc_tg"):setId(1) end end - if chest.info.instantbuild == true then + local status = chest.plan:get_status() + if status == "build" then state:get("inst_tg"):setId(2) else state:get("inst_tg"):setId(1) end - - if chest.info.npc_build == true or chest.info.instantbuild == true then - state:get("reload_bt"):setVisible(false) + if chest.info.npc_build or status == "build" then + state:get("reset_bt"):setVisible(false) else - state:get("reload_bt"):setVisible(true) + state:get("reset_bt"):setVisible(true) end end -- instant build toggle state:toggle(1,6,3,0.5,"inst_tg",{ "Start instant build", "Stop instant build"}):onToggle(function(self, state, player) - chest.info.instantbuild = not chest.info.instantbuild - if chest.info.instantbuild then + local status = chest.plan:get_status() + if status ~= "build" then chest.plan:set_status("build") - chest.plan:do_add_all_voxel_async() + chest:update_info() else chest.plan:set_status("pause") + chest:update_info() end + schemlib.plan_manager.set_plan(chest.plan) set_dynamic_values(state, chest) - chest:persist_info() end) -- refresh building button - state:button(5,6,3,0.5,"reload_bt", "Reload nodes"):onClick(function(self, state, player) - chest:set_rawdata() + state:button(5,6,3,0.5,"reset_bt", "Reset"):onClick(function(self, state, player) + local chest = townchest.chest.create(state.location.pos) + chest:set_plan_form() end) -- NPC build button if townchest.npc.supported then state:toggle(9,6,3,0.5,"npc_tg",{ "Start NPC build", "Stop NPC build"}):onToggle(function(self, state, player) chest.info.npc_build = not chest.info.npc_build - if chest.info.npc_build then - townchest.npc.enable_build(chest.plan) - else - townchest.npc.disable_build(chest.plan) - end + chest:update_info() set_dynamic_values(state, chest) - chest:persist_info() end) end @@ -290,17 +320,18 @@ local build_finished_form = function(state) local chest = townchest.chest.get(state.location.pos) allform_header(state) local l1_text - if chest.info.taskname == "file" then - l1_text = "Building "..chest.info.filename.." selected" - elseif chest.info.taskname == "generate" then - l1_text = "Simple task: "..chest.info.genblock.variant_name + if chest.info.townchest_filename then + l1_text = "Building "..chest.info.townchest_filename.." finished" + elseif chest.info.genblock and chest.info.genblock.variant_name then + l1_text = "Simple task: "..chest.info.genblock.variant_name.." finished" + else + l1_text = "Unknown task finished" end - state:label(1,1.5,"l1",l1_text) - -- refresh building button - state:button(5,4.5,3,0.5,"reload_bt", "Reload nodes"):onClick(function(self, state, player) - chest:set_rawdata() + state:button(5,6,3,0.5,"reset_bt", "Reset"):onClick(function(self, state, player) + local chest = townchest.chest.create(state.location.pos) + chest:set_plan_form() end) end smartfs.create("townchest:build_finished", build_finished_form)