Villagers can claim any bed. Player can steal villager bed. Villager won't take player bed

This commit is contained in:
ancientmarinerdev 2022-11-08 22:58:47 +00:00 committed by cora
parent 3e1a475442
commit 3000a378f3
3 changed files with 150 additions and 24 deletions

View File

@ -45,10 +45,9 @@ local PATHFINDING = "gowp"
-- will be much easier.
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_villager",false)
local LOG_MODULE = "[Mobs - Villager]"
local function mcl_log (message)
if LOGGING_ON and message then
minetest.log(LOG_MODULE .. " " .. message)
if LOGGING_ON then
mcl_util.mcl_log (message, "[Mobs - Villager]", true)
end
end
@ -578,9 +577,6 @@ end
jobsites = populate_jobsites()
local spawnable_bed={}
table.insert(spawnable_bed, "mcl_beds:bed_red_bottom")
local function stand_still(self)
self.walk_chance = 0
self.jump = false
@ -651,6 +647,8 @@ end
local function find_closest_bed (self)
local p = self.object:get_pos()
--local spawnable_bed={}
--table.insert(spawnable_bed, "mcl_beds:bed_red_bottom")
--local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), spawnable_bed)
--if nn then
-- mcl_log("Red beds: " .. #nn)
@ -659,30 +657,52 @@ local function find_closest_bed (self)
local unclaimed_beds = {}
local nn2 = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), {"group:bed"})
if nn2 then
mcl_log("All bed parts: " .. #nn2)
--mcl_log("All bed parts: " .. #nn2)
for a,b in pairs(nn2) do
mcl_log("b: " .. minetest.pos_to_string(b))
local bed_node = minetest.get_node(b)
local bed_meta = minetest.get_meta(b)
local bed_name = bed_node.name
--mcl_log("bed_node name: " .. bed_name)
local is_bed_bottom = string.find(bed_name,"_bottom")
local owned_by = bed_meta:get_string("villager")
if owned_by and owned_by == self._id then
mcl_log("Weird. I own this, but don't know it.")
local bed_meta = minetest.get_meta(b)
local owned_by = bed_meta:get_string("villager")
--mcl_log("Owned by villager: ".. tostring(owned_by))
if (owned_by and owned_by == self._id) then
mcl_log("Clear as already owned by me.")
bed_meta:set_string("villager", nil)
owned_by = nil
end
if is_bed_bottom and owned_by == "" then
table.insert(unclaimed_beds, b)
mcl_log("is an unowned bed bottom")
if is_bed_bottom then
local bed_top = mcl_beds.get_bed_top (b)
mcl_log("bed_top: " .. tostring(bed_top))
local bed_top_node = minetest.get_node(bed_top)
if bed_top_node then
mcl_log("There is a block here for bed top: ".. bed_top_node.name)
else
mcl_log("There is no block here for bed top")
end
local bed_top_meta = minetest.get_meta(bed_top)
local owned_by_player = bed_top_meta:get_string("player")
if bed_top_meta then
mcl_log("Player: " .. tostring(owned_by_player))
else
mcl_log("No bed top meta")
end
if owned_by == "" and (not owned_by_player or owned_by_player == "") then
table.insert(unclaimed_beds, b)
mcl_log("is an unowned bed bottom")
else
end
else
mcl_log("Not bottom or is claimed, remove. Owned: ".. owned_by)
--mcl_log("bed_node name: " .. bed_name)
end
end
end
@ -817,7 +837,6 @@ local function take_bed (entity)
local p = entity.object:get_pos()
--local closest_block = find_closest_unclaimed_block (p, spawnable_bed)
local closest_block = find_closest_bed (entity)
if closest_block then
@ -1177,11 +1196,46 @@ local function go_to_town_bell(self)
return nil
end
local function validate_bed(self)
if not self or not self._bed then
return false
end
local n = mcl_vars.get_node(self._bed)
if not n then
self._bed = nil
return false
end
local bed_valid = true
local m = minetest.get_meta(self._bed)
local owned_by_player = m:get_string("player")
mcl_log("Player owner: " .. owned_by_player)
if owned_by_player ~= "" then
mcl_log("Player owns this. Villager won't take this.")
m:set_string("villager", nil)
self._bed = nil
bed_valid = false
return
end
if m:get_string("villager") ~= self._id then
mcl_log("This bed is owned by another player. I'll unclaim.")
self._bed = nil
return false
else
mcl_log("Bed is valid")
return true
end
end
local function do_activity (self)
-- Maybe just check we're pathfinding first?
if not self._bed and self.state ~= PATHFINDING then
--mcl_log("Villager has no bed. Currently at location: "..minetest.pos_to_string(self.object:get_pos()))
if not validate_bed(self) and self.state ~= PATHFINDING then
if self.order == SLEEP then self.order = nil end
mcl_log("Villager has no bed. Currently at location: "..minetest.pos_to_string(self.object:get_pos()))
take_bed (self)
end

View File

@ -10,6 +10,10 @@ local explosions_mod = minetest.get_modpath("mcl_explosions")
local spawn_mod = minetest.get_modpath("mcl_spawn")
local worlds_mod = minetest.get_modpath("mcl_worlds")
local function mcl_log (message)
mcl_util.mcl_log (message, "[Beds]")
end
-- Helper functions
local function get_look_yaw(pos)
@ -300,6 +304,37 @@ function mcl_beds.skip_night()
minetest.set_timeofday(0.25) -- tod = 6000
end
function mcl_beds.get_bed_top (pos)
local node = minetest.get_node(pos)
local dir = minetest.facedir_to_dir(node.param2)
local bed_top_pos = vector.add(pos, dir)
local bed_top = minetest.get_node(bed_top_pos)
if bed_top then
mcl_log("Has a bed top")
else
mcl_log("No bed top")
end
return bed_top_pos
end
function mcl_beds.get_bed_bottom (pos)
local node = minetest.get_node(pos)
local dir = minetest.facedir_to_dir(node.param2)
mcl_log("Dir: " .. tostring(dir))
local bed_bottom = vector.add(pos, -dir)
mcl_log("bed_bottom: " .. tostring(bed_bottom))
local bed_bottom_node = minetest.get_node(bed_bottom)
if bed_bottom_node then
mcl_log("Bed bottom node name:" .. bed_bottom_node.name)
else
mcl_log("Didn't get bed bottom")
end
return bed_bottom
end
function mcl_beds.on_rightclick(pos, player, is_top)
-- Anti-Inception: Don't allow to sleep while you're sleeping
if player:get_meta():get_string("mcl_beds:sleeping") == "true" then
@ -329,9 +364,7 @@ function mcl_beds.on_rightclick(pos, player, is_top)
if is_top then
message = select(2, lay_down(player, ppos, pos))
else
local node = minetest.get_node(pos)
local dir = minetest.facedir_to_dir(node.param2)
local other = vector.add(pos, dir)
local other = mcl_beds.get_bed_top (pos)
message = select(2, lay_down(player, ppos, other))
end
if message then

View File

@ -4,6 +4,10 @@ local S = minetest.get_translator(minetest.get_current_modname())
local mg_name = minetest.get_mapgen_setting("mg_name")
local storage = minetest.get_mod_storage()
local function mcl_log (message)
mcl_util.mcl_log (message, "[Spawn]")
end
-- Parameters
-------------
@ -429,6 +433,41 @@ function mcl_spawn.set_spawn_pos(player, pos, message)
else
local oldpos = minetest.string_to_pos(meta:get_string("mcl_beds:spawn"))
meta:set_string("mcl_beds:spawn", minetest.pos_to_string(pos))
-- Set player ownership on bed
local bed_node = minetest.get_node(pos)
local bed_meta = minetest.get_meta(pos)
local bed_bottom = mcl_beds.get_bed_bottom (pos)
local bed_bottom_meta = minetest.get_meta(bed_bottom)
if bed_meta then
if bed_node then
mcl_log("Bed name: " .. bed_node.name)
end
mcl_log("Setting bed meta: " .. player:get_player_name())
bed_meta:set_string("player", player:get_player_name())
-- Pass in villager as arg. Shouldn't know about villagers
if bed_bottom_meta then
mcl_log("Removing villager from bed bottom meta")
bed_bottom_meta:set_string("villager", nil)
else
mcl_log("Cannot remove villager from bed bottom meta")
end
local old_bed_meta = minetest.get_meta(oldpos)
if oldpos ~= pos and old_bed_meta then
mcl_log("Removing old bed meta")
old_bed_meta:set_string("player", "")
else
mcl_log("No old bed meta to remove or same as current")
end
end
if oldpos then
-- We don't bother sending a message if the new spawn pos is basically the same
spawn_changed = vector.distance(pos, oldpos) > 0.1