diff --git a/actions/actions.lua b/actions/actions.lua index a154839..fce6f47 100644 --- a/actions/actions.lua +++ b/actions/actions.lua @@ -664,19 +664,42 @@ local function get_pos_argument(self, pos, use_access_node) return pos elseif pos.place_type ~= nil then -- Received table in the following format: - -- {place_type = "", index = 1, use_access_node = false} + -- { + -- place_category = "", + -- place_type = "", + -- index = 1, + -- use_access_node = false|true, + -- try_alternative_if_used = true|false + -- } local index = pos.index or 1 local use_access_node = pos.use_access_node or false + local try_alternative_if_used = pos.try_alternative_if_used or false local places = npc.places.get_by_type(self, pos.place_type) + --minetest.log("Place type: "..dump(pos.place_type)) + --minetest.log("Places: "..dump(places)) -- Check index is valid on the places map if #places >= index then + local place = places[index] + -- Check if place is used, and if it is, find alternative if required + if try_alternative_if_used == true then + place = npc.places.find_unused_place(self, pos.place_category, pos.place_type, place) + + --minetest.log("Mark as used? "..dump(pos.mark_target_as_used)) + if pos.mark_target_as_used == true then + --minetest.log("Marking as used: "..minetest.pos_to_string(place.pos)) + npc.places.mark_place_used(place.pos, npc.places.USE_STATE.USED) + end + + npc.places.add_shared_accessible_place( + self, {owner="", node_pos=place.pos}, npc.places.PLACE_TYPE.CALCULATED.TARGET, true, {}) + end -- Check if access node is desired if use_access_node == true then -- Return actual node pos - return places[index].access_node, places[index].pos + return place.access_node, place.pos else -- Return node pos that allows access to node - return places[index].pos + return place.pos end end end @@ -722,6 +745,7 @@ function npc.actions.use_furnace(self, args) return end + local enable_usage_marking = args.enable_usage_marking or true local item = args.item local freeze = args.freeze -- Define which items are usable as fuels. The NPC @@ -775,6 +799,12 @@ function npc.actions.use_furnace(self, args) return cook_result.time - fuel_time end + -- Set furnace as used if flag is enabled + if enable_usage_marking then + -- Set place as used + npc.places.mark_place_used(pos, npc.places.USE_STATE.USED) + end + -- Calculate how much fuel is needed local fuel_amount = total_cook_time / fuel_time if fuel_amount < 1 then @@ -832,6 +862,12 @@ function npc.actions.use_furnace(self, args) npc.log("DEBUG", "Inventory: "..dump(self.inventory)) + -- Set furnace as unused if flag is enabled + if enable_usage_marking then + -- Set place as used + npc.places.mark_place_used(pos, npc.places.USE_STATE.NOT_USED) + end + return true end end @@ -848,6 +884,7 @@ function npc.actions.use_bed(self, args) return end local action = args.action + local enable_usage_marking = args.enable_usage_marking or true local node = minetest.get_node(pos) --minetest.log(dump(node)) local dir = minetest.facedir_to_dir(node.param2) @@ -863,6 +900,10 @@ function npc.actions.use_bed(self, args) npc.add_action(self, npc.actions.cmd.SIT, {pos=bed_pos, dir=(node.param2 + 2) % 4}) -- Lay down npc.add_action(self, npc.actions.cmd.LAY, {}) + if enable_usage_marking then + -- Set place as used + npc.places.mark_place_used(pos, npc.places.USE_STATE.USED) + end else -- Calculate position to get up -- Error here due to ignore. Need to come up with better solution @@ -906,9 +947,12 @@ function npc.actions.use_bed(self, args) end end - -- Stand out of bed npc.add_action(self, npc.actions.cmd.STAND, {pos=pos_out_of_bed, dir=dir}) + if enable_usage_marking then + -- Set place as unused + npc.places.mark_place_used(pos, npc.places.USE_STATE.NOT_USED) + end end end @@ -921,6 +965,7 @@ function npc.actions.use_sittable(self, args) return end local action = args.action + local enable_usage_marking = args.enable_usage_marking or true local node = minetest.get_node(pos) if action == npc.actions.const.sittable.SIT then @@ -932,6 +977,10 @@ function npc.actions.use_sittable(self, args) local sit_pos = npc.actions.nodes.sittable[node.name].get_sit_pos(pos, node.param2) -- Sit down on bench/chair/stairs npc.add_action(self, npc.actions.cmd.SIT, {pos=sit_pos, dir=(node.param2 + 2) % 4}) + if enable_usage_marking then + -- Set place as used + npc.places.mark_place_used(pos, npc.places.USE_STATE.USED) + end else -- Find empty areas around chair local dir = node.param2 + 2 % 4 @@ -951,6 +1000,11 @@ function npc.actions.use_sittable(self, args) end -- Stand npc.add_action(self, npc.actions.cmd.STAND, {pos=pos_out_of_sittable, dir=dir}) + minetest.log("Setting sittable at "..minetest.pos_to_string(pos).." as not used") + if enable_usage_marking then + -- Set place as unused + npc.places.mark_place_used(pos, npc.places.USE_STATE.NOT_USED) + end end end diff --git a/actions/places.lua b/actions/places.lua index 5516817..d20ccfa 100644 --- a/actions/places.lua +++ b/actions/places.lua @@ -63,6 +63,17 @@ npc.places.nodes = { npc.places.PLACE_TYPE = { + CATEGORIES = { + BED = "BED", + SITTABLE = "SITTABLE", + FURNACE = "FURNACE", + STORAGE = "STORAGE", + OPENABLE = "OPENABLE", + SCHEDULE = "SCHEDULE", + CALCULATED = "CALCULATED", + WORKPLACE = "WORKPLACE", + OTHER = "OTHER" + }, BED = { PRIMARY = "bed_primary" }, @@ -84,6 +95,9 @@ npc.places.PLACE_TYPE = { SCHEDULE = { TARGET = "schedule_target_pos" }, + CALCULATED = { + TARGET = "calculated_target_pos" + }, WORKPLACE = { PRIMARY = "workplace_primary", TOOL = "workplace_tool" @@ -92,14 +106,60 @@ npc.places.PLACE_TYPE = { HOME_PLOTMARKER = "home_plotmarker", HOME_INSIDE = "home_inside", HOME_OUTSIDE = "home_outside" - } + }, + is_primary = function(place_type) + local p1,p2 = string.find(place_type, "primary") + return p1 ~= nil + end, + -- Only works for place types where there is a "primary" and a "shared" + get_alternative = function(place_category, place_type) + local result = {} + local place_types = npc.places.PLACE_TYPE[place_category] + -- Determine search type + local search_shared = false + if npc.places.PLACE_TYPE.is_primary(place_type) then + search_shared = true + end + for key,place_type in pairs(place_types) do + if search_shared == true then + if npc.places.PLACE_TYPE.is_primary(place_type) == false then + return place_type + end + else + if npc.places.PLACE_TYPE.is_primary(place_type) == true then + return place_type + end + end + end + end +} + +npc.places.USE_STATE = { + USED = "true", + NOT_USED = "false" } function npc.places.add_shared(self, place_name, place_type, pos, access_node) + -- Set metadata of node + local meta = minetest.get_meta(pos) + if not meta:get_string("advanced_npc:used") then + meta:set_string("advanced_npc:used", npc.places.USE_STATE.NOT_USED) + end + meta:set_string("advanced_npc:owner", "") + -- This avoid lags + meta:mark_as_private({"advanced_npc:used", "advanced_npc:owner"}) self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="shared"} end function npc.places.add_owned(self, place_name, place_type, pos, access_node) + -- Set metadata of node + local meta = minetest.get_meta(pos) + if not meta:get_string("advanced_npc:used") then + meta:set_string("advanced_npc:used", npc.places.USE_STATE.NOT_USED) + end + meta:set_string("advanced_npc:owner", self.npc_id) + -- This avoid lags + meta:mark_as_private({"advanced_npc:used", "advanced_npc:owner"}) self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="owned"} end @@ -161,6 +221,48 @@ function npc.places.add_shared_accessible_place(self, nodes, place_type, overrid end end +function npc.places.mark_place_used(pos, value) + local meta = minetest.get_meta(pos) + local used = meta:get_string("advanced_npc:used") + if value == used then + npc.log("WARNING", "Attempted to set 'used' property of node at " + ..minetest.pos_to_string(pos).." to the same value: '"..dump(value).."'") + return false + else + meta:set_string("advanced_npc:used", value) + npc.log("DEBUG", "'Used' value at pos "..minetest.pos_to_string(pos)..": "..dump(meta:get_string("advanced_npc:used"))) + return true + end +end + +-- This function is to find an alternative place if the original is +-- not usable. If the original place is a "primary" place, it will +-- try to find a "shared" place. If it is a "shared" place, it will try +-- to find a "primary" place. If none is found, it retuns the given type. +function npc.places.find_unused_place(self, place_category, place_type, original_place) + local result = {} + -- Check if node is being used + local meta = minetest.get_meta(original_place.pos) + local used = meta:get_string("advanced_npc:used") + if used == npc.places.USE_STATE.USED then + -- Node is being used, try to find alternative + local alternative_place_type = npc.places.PLACE_TYPE.get_alternative(place_category, place_type) + --minetest.log("Alternative place type: "..dump(alternative_place_type)) + local alternative_places = npc.places.get_by_type(self, alternative_place_type) + --minetest.log("Alternatives: "..dump(alternative_places)) + for i = 1, #alternative_places do + meta = minetest.get_meta(alternative_places[i].pos) + local used = meta:get_string("advanced_npc:used") + if used == npc.places.USE_STATE.NOT_USED then + return alternative_places[i] + end + end + else + result = original_place + end + return result +end + function npc.places.get_by_type(self, place_type, exact_match) local result = {} for _, place_entry in pairs(self.places_map) do diff --git a/data/occupations/default.lua b/data/occupations/default.lua index 9102177..caa2965 100644 --- a/data/occupations/default.lua +++ b/data/occupations/default.lua @@ -55,17 +55,25 @@ local basic_def = { -- Schedule entry for 12 midday [12] = { -- Walk to a sittable node - [1] = {task = npc.actions.cmd.WALK_TO_POS, args = { - end_pos = {place_type=npc.places.PLACE_TYPE.SITTABLE.PRIMARY, use_access_node=true}, - walkable = {"cottages:bench"} - }, + [1] = {task = npc.actions.cmd.WALK_TO_POS, + args = { + end_pos = { + place_category=npc.places.PLACE_TYPE.CATEGORIES.SITTABLE, + place_type=npc.places.PLACE_TYPE.SITTABLE.PRIMARY, + use_access_node=true, + try_alternative_if_used=true, + mark_target_as_used = true + }, + walkable = {"cottages:bench"} + }, chance = 75 }, -- Sit on the node - [2] = {task = npc.actions.cmd.USE_SITTABLE, args = { - pos = npc.places.PLACE_TYPE.SITTABLE.PRIMARY, - action = npc.actions.const.sittable.SIT - }, + [2] = {task = npc.actions.cmd.USE_SITTABLE, + args = { + pos = npc.places.PLACE_TYPE.CALCULATED.TARGET, + action = npc.actions.const.sittable.SIT + }, depends = {1} }, -- Stay put into place @@ -83,10 +91,10 @@ local basic_def = { }, -- Get up from sit [5] = {action = npc.actions.cmd.USE_SITTABLE, args = { - pos = npc.places.PLACE_TYPE.SITTABLE.PRIMARY, + pos = npc.places.PLACE_TYPE.CALCULATED.TARGET, action = npc.actions.const.sittable.GET_UP }, - depends = {4} + --depends = {4} } }, -- Schedule entry for 1 in the afternoon @@ -142,10 +150,11 @@ local basic_def = { } }, -- Use bed - [2] = {task = npc.actions.cmd.USE_BED, args = { - pos = npc.places.PLACE_TYPE.BED.PRIMARY, - action = npc.actions.const.beds.LAY - } + [2] = {task = npc.actions.cmd.USE_BED, + args = { + pos = npc.places.PLACE_TYPE.BED.PRIMARY, + action = npc.actions.const.beds.LAY + } }, -- Stay put on bed [3] = {action = npc.actions.cmd.FREEZE, args = {freeze = true}} diff --git a/npc.lua b/npc.lua index 6bc1b96..dda0379 100755 --- a/npc.lua +++ b/npc.lua @@ -564,7 +564,7 @@ function npc.generate_trade_list_from_inventory(self) end function npc.set_trading_status(self, status) - minetest.log("Trader_data: "..dump(self.trader_data)) + --minetest.log("Trader_data: "..dump(self.trader_data)) -- Set status self.trader_data.trader_status = status -- Re-generate trade offers