schemlib update. Use schemlib plan persistance manager
This commit is contained in:
parent
2a1bf33851
commit
63cacc2e5b
177
init.lua
177
init.lua
@ -2,6 +2,7 @@
|
||||
local dprint = function() return end
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
local filepath = modpath.."/buildings/"
|
||||
local plan_manager = schemlib.plan_manager
|
||||
|
||||
local BUILD_DISTANCE = 3
|
||||
|
||||
@ -11,110 +12,17 @@ schemlib_builder_npcf = {
|
||||
walk_around_rarity = 3, -- Rarity for direction change in walk around without job
|
||||
walk_around_duration = 10, -- Rarity for direction change in walk around without job
|
||||
plan_max_distance = 100, -- Maximal distance to the next plan
|
||||
check_anchor_rarity = 10, -- Rarity of check for anchor call --10
|
||||
--buildings = {} -- list with buildings {name=, filename=}
|
||||
check_anchor_rarity = 2, -- Rarity of check for anchor call --10
|
||||
}
|
||||
|
||||
local func = {} -- different functions
|
||||
local building_checktable = {}
|
||||
|
||||
local tmp_next_plan
|
||||
--------------------------------------
|
||||
-- Plan manager singleton
|
||||
--------------------------------------
|
||||
local plan_manager = {
|
||||
plan_list = {}
|
||||
}
|
||||
schemlib_builder_npcf.plan_manager = plan_manager
|
||||
|
||||
--------------------------------------
|
||||
-- Restore active WIP plan's
|
||||
--------------------------------------
|
||||
function plan_manager:restore()
|
||||
self.stored_list = schemlib.save_restore.restore_data("/schemlib_builder_npcf.store")
|
||||
for plan_id, entry in pairs(self.stored_list) do
|
||||
local filename = building_checktable[entry.filename]
|
||||
if filename then
|
||||
local plan = func.get_plan_from_file(entry.filename, modpath.."/buildings/"..entry.filename, plan_id, entry.anchor_pos)
|
||||
if entry.facedir ~= nil then
|
||||
plan.facedir = entry.facedir
|
||||
end
|
||||
if entry.mirrored ~= nil then
|
||||
plan.mirrored = entry.mirrored
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Save active WIP plan's
|
||||
--------------------------------------
|
||||
function plan_manager:save()
|
||||
self.stored_list = {}
|
||||
for plan_id, plan in pairs(self.plan_list) do
|
||||
if plan.schemlib_builder_npcf_building_filename then
|
||||
local entry = {
|
||||
anchor_pos = plan.anchor_pos,
|
||||
filename = plan.schemlib_builder_npcf_building_filename,
|
||||
facedir = plan.facedir,
|
||||
mirrored = plan.mirrored,
|
||||
}
|
||||
self.stored_list[plan_id] = entry
|
||||
end
|
||||
end
|
||||
schemlib.save_restore.save_data("/schemlib_builder_npcf.store", self.stored_list)
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Get known plan
|
||||
--------------------------------------
|
||||
function plan_manager:get(plan_id)
|
||||
local plan = self.plan_list[plan_id]
|
||||
if plan and plan:get_status() == "finished" then
|
||||
dprint(self.npc_id, "plan finished, remove from npc plan manager")
|
||||
self:set_finished(plan)
|
||||
return nil
|
||||
else
|
||||
return plan
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Set the plan finished
|
||||
--------------------------------------
|
||||
function plan_manager:set_finished(plan)
|
||||
self.plan_list[plan.plan_id] = nil
|
||||
plan_manager:save()
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Add new plan to the list
|
||||
--------------------------------------
|
||||
function plan_manager:add(plan)
|
||||
self.plan_list[plan.plan_id] = plan
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- set anchor and rename to get active
|
||||
--------------------------------------
|
||||
function plan_manager:activate_by_anchor(anchor_pos)
|
||||
local plan = tmp_next_plan
|
||||
tmp_next_plan = nil
|
||||
local new_plan_id = minetest.pos_to_string(anchor_pos)
|
||||
plan.plan_id = new_plan_id
|
||||
plan.anchor_pos = anchor_pos
|
||||
plan:set_status("build")
|
||||
self.plan_list[new_plan_id] = plan
|
||||
self:save()
|
||||
return plan
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- Functions
|
||||
--------------------------------------
|
||||
-- Get buildings list
|
||||
--------------------------------------
|
||||
function func.get_buildings_list()
|
||||
local function get_buildings_list()
|
||||
local list = {}
|
||||
local building_files = minetest.get_dir_list(modpath.."/buildings/", false)
|
||||
for _, file in ipairs(building_files) do
|
||||
@ -127,16 +35,10 @@ end
|
||||
--------------------------------------
|
||||
-- Load plan from file and configure them
|
||||
--------------------------------------
|
||||
function func.get_plan_from_file(name, filename, plan_id, anchor_pos)
|
||||
plan_id = plan_id or name
|
||||
local plan = schemlib.plan.new(plan_id, anchor_pos)
|
||||
plan.schemlib_builder_npcf_building_filename = name
|
||||
local function get_plan_from_file(filename)
|
||||
local plan = schemlib.plan.new()
|
||||
plan:read_from_schem_file(filename)
|
||||
plan:apply_flood_with_air()
|
||||
if anchor_pos then
|
||||
plan:set_status("build")
|
||||
plan_manager:add(plan)
|
||||
end
|
||||
return plan
|
||||
end
|
||||
|
||||
@ -144,16 +46,19 @@ end
|
||||
-- NPC Enhancements
|
||||
--------------------------------------
|
||||
-- Get exsisting plan prefering the already assigned
|
||||
function func.get_existing_plan(self)
|
||||
local function get_existing_plan(self)
|
||||
local mv_obj = npcf.movement.getControl(self)
|
||||
if self.metadata.build_plan_id and (not tmp_next_plan or self.build_plan ~= tmp_next_plan) then
|
||||
-- check if current plan is still valid / get them
|
||||
dprint(self.npc_id,"check existing plan", self.metadata.build_plan_id )
|
||||
self.build_plan = plan_manager:get(self.metadata.build_plan_id)
|
||||
self.build_plan = plan_manager:get_plan(self.metadata.build_plan_id)
|
||||
if not self.build_plan then
|
||||
self.metadata.build_plan_id = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- The NPC is not a workaholic
|
||||
if self.build_plan == nil and schemlib_builder_npcf.max_pause_duration > 0 then
|
||||
if not self.build_plan and schemlib_builder_npcf.max_pause_duration > 0 then
|
||||
dprint(self.npc_id,"check for pause")
|
||||
if not self.metadata.schemlib_pause then
|
||||
self.metadata.schemlib_pause = math.random(schemlib_builder_npcf.max_pause_duration)
|
||||
@ -174,18 +79,19 @@ function func.get_existing_plan(self)
|
||||
-- no plan assigned, check for neighboar plans / select existing plan
|
||||
dprint(self.npc_id,"select existing plan")
|
||||
local selected_plan = {}
|
||||
for plan_id, _ in pairs(plan_manager.plan_list) do
|
||||
local plan = plan_manager:get(plan_id)
|
||||
if plan then
|
||||
local distance = vector.distance(plan.anchor_pos, mv_obj.pos)
|
||||
dprint(self.npc_id,"plan exists:", plan_id, plan.anchor_pos, distance)
|
||||
for plan_id, meta in pairs(plan_manager.plan_meta_list) do
|
||||
if meta.npc_build and meta.anchor_pos then
|
||||
local distance = vector.distance(meta.anchor_pos, mv_obj.pos)
|
||||
dprint(self.npc_id,"plan exists:", plan_id, meta.anchor_pos, distance)
|
||||
if distance < schemlib_builder_npcf.plan_max_distance and (not selected_plan.distance or selected_plan.distance > distance) then
|
||||
selected_plan.distance = distance
|
||||
selected_plan.plan = plan
|
||||
selected_plan.plan_id = plan_id
|
||||
end
|
||||
end
|
||||
end
|
||||
self.build_plan = selected_plan.plan or self.build_plan
|
||||
if selected_plan.plan_id then
|
||||
self.build_plan = plan_manager.get_plan(selected_plan.plan_id)
|
||||
end
|
||||
if self.build_plan then
|
||||
self.metadata.build_plan_id = self.build_plan.plan_id
|
||||
dprint(self.npc_id,"Existing plan selected", selected_plan.plan_id)
|
||||
@ -194,28 +100,29 @@ function func.get_existing_plan(self)
|
||||
end
|
||||
|
||||
|
||||
function func.create_new_plan(self)
|
||||
local function create_new_plan(self)
|
||||
local mv_obj = npcf.movement.getControl(self)
|
||||
if not tmp_next_plan then
|
||||
-- no plan in list - and no plan temporary loaded - load them (maybe)
|
||||
local building = schemlib_builder_npcf.buildings[math.random(#schemlib_builder_npcf.buildings)]
|
||||
dprint(self.npc_id,"File selected for build", building.filename)
|
||||
tmp_next_plan = func.get_plan_from_file(building.name, building.filename)
|
||||
tmp_next_plan.facedir = math.random(4)-1
|
||||
tmp_next_plan.mirrored = (math.random(2) == 1)
|
||||
tmp_next_plan = get_plan_from_file(building.filename)
|
||||
tmp_next_plan.data.facedir = math.random(4)-1
|
||||
tmp_next_plan.data.mirrored = (math.random(2) == 1)
|
||||
dprint(self.npc_id,"building loaded. Nodes:", tmp_next_plan.data.nodecount)
|
||||
return
|
||||
end
|
||||
|
||||
if math.random(schemlib_builder_npcf.check_anchor_rarity) == 1 then
|
||||
-- dummy plan exists, search for anchor, but do not penetrate the map by propose_anchor()
|
||||
dprint(self.npc_id,"Check anchor")
|
||||
local chk_pos = vector.round(mv_obj.pos)
|
||||
local anchor_pos, error_pos
|
||||
-- check for possible overlaps with other plans
|
||||
for plan_id, _ in pairs(plan_manager.plan_list) do
|
||||
local plan = plan_manager:get(plan_id)
|
||||
if tmp_next_plan:check_overlap(plan:get_world_minp(), plan:get_world_maxp(), 3, chk_pos) then
|
||||
error_pos = plan:get_world_pos(plan:get_random_plan_pos())
|
||||
for plan_id, meta in pairs(plan_manager.plan_meta_list) do
|
||||
local plan_meta = plan_manager.get_plan_meta(plan_id)
|
||||
error_pos = tmp_next_plan:check_overlap(plan_meta:get_world_minp(), plan_meta:get_world_maxp(), 3, chk_pos)
|
||||
if error_pos then
|
||||
break
|
||||
end
|
||||
end
|
||||
@ -234,8 +141,14 @@ function func.create_new_plan(self)
|
||||
dprint(self.npc_id,"proposed anchor", minetest.pos_to_string(anchor_pos), "nearly", minetest.pos_to_string(mv_obj.pos))
|
||||
|
||||
-- Prepare building plan to be build
|
||||
self.build_plan = plan_manager:activate_by_anchor(anchor_pos)
|
||||
self.build_plan = tmp_next_plan
|
||||
self.build_plan.plan_id = "builder:"..minetest.pos_to_string(anchor_pos)
|
||||
self.build_plan.data.managed_by_schemlib_builder = true
|
||||
self.metadata.build_plan_id = self.build_plan.plan_id
|
||||
self.build_plan.data.anchor_pos = anchor_pos
|
||||
self.build_plan.data.npc_build = true
|
||||
tmp_next_plan = nil
|
||||
plan_manager.set_plan(self.build_plan)
|
||||
dprint(self.npc_id,"building ready to build at:", self.metadata.build_plan_id)
|
||||
end
|
||||
end
|
||||
@ -256,17 +169,26 @@ npcf:register_npc("schemlib_builder_npcf:builder" ,{
|
||||
mv_obj:mine_stop()
|
||||
|
||||
-- check plan
|
||||
func.get_existing_plan(self)
|
||||
get_existing_plan(self)
|
||||
if self.build_plan then
|
||||
dprint(self.npc_id,"plan ready for build, get the next node")
|
||||
if self.build_plan.data.nodecount == 0 then
|
||||
if self.build_plan.data.managed_by_schemlib_builder then
|
||||
plan_manager.delete_plan(self.build_plan.plan_id)
|
||||
end
|
||||
self.build_plan = nil
|
||||
self.metadata.build_plan_id = nil
|
||||
dprint(self.npc_id, "plan finished")
|
||||
return
|
||||
end
|
||||
dprint(self.npc_id,"plan ready for build, get the next node")
|
||||
if not self.build_npc_ai or self.build_npc_ai.plan ~= self.build_plan then
|
||||
self.build_npc_ai = schemlib.npc_ai.new(self.build_plan, BUILD_DISTANCE)
|
||||
end
|
||||
self.target_node = self.build_npc_ai:plan_target_get(mv_obj.pos)
|
||||
end
|
||||
if not self.build_plan and schemlib_builder_npcf.architect_rarity > 0 and
|
||||
if (not self.build_plan) and schemlib_builder_npcf.architect_rarity > 0 and
|
||||
math.random(schemlib_builder_npcf.architect_rarity) == 1 then
|
||||
func.create_new_plan(self)
|
||||
create_new_plan(self)
|
||||
self.target_node = nil
|
||||
end
|
||||
|
||||
@ -376,6 +298,5 @@ npcf:register_npc("schemlib_builder_npcf:builder" ,{
|
||||
})
|
||||
|
||||
-- Restore data at init
|
||||
schemlib_builder_npcf.buildings = func.get_buildings_list() -- at init!
|
||||
plan_manager:restore()
|
||||
schemlib_builder_npcf.buildings = get_buildings_list() -- at init!
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user