smart_villages/homes.lua

214 lines
7.1 KiB
Lua

-- smart_villages.homes represents a table that contains the villagers homes.
-- This table's keys are inventory names, and values are home objects.
smart_villages.homes = (function()
local file_name = minetest.get_worldpath() .. "/smart_villages_homes"
minetest.register_on_shutdown(function()
local save_data = {}
for k,v in pairs(smart_villages.homes) do
save_data[k]={marker=v.marker}
end
local file = io.open(file_name, "w")
file:write(minetest.serialize(save_data))
file:close()
end)
local file = io.open(file_name, "r")
if file ~= nil then
local data = file:read("*a")
file:close()
return minetest.deserialize(data)
end
return {}
end) ()
local function out_of_limit(pos)
if (pos.x>30927 or pos.x<-30912
or pos.y>30927 or pos.y<-30912
or pos.z>30927 or pos.z<-30912) then
return false
end
return true
end
minetest.register_node("smart_villages:home_marker", {
description = "home marker for smart_villages",
drawtype = "nodebox",
tiles = {"default_sign_wall_wood.png"},
inventory_image = "default_sign_wood.png",
wield_image = "default_sign_wood.png",
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
is_ground_content = false,
walkable = false,
node_box = {
type = "wallmounted",
wall_top = {-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125},
wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125},
wall_side = {-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375},
},
groups = {choppy = 2, dig_immediate = 2, attached_node = 1},
legacy_wallmounted = true,
sounds = default.node_sound_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
local owner = placer:get_player_name()
meta:set_string("owner", owner)
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string(
"formspec",
"size[5,5]"..
"field[0.5,1;4,1;name;house label;${name}]"..
"field[0.5,2;4,1;bed_pos;bed position;${bed_pos}]"..
"field[0.5,3;4,1;door_pos;position outside the house;${door_pos}]"..
"button_exit[1,4;2,1;ok;Write]")
end,
on_receive_fields = function(pos, _, fields, sender)
local meta = minetest.get_meta(pos)
local sender_name = sender:get_player_name()
local failed = false
if minetest.is_protected(pos, sender_name) then
minetest.record_protection_violation(pos, sender_name)
return
end
if (meta:get_string("bed")~="" and meta:get_string("door")~="")
or (fields.bed_pos == nil and fields.door_pos == nil) then
return
end
local coords = minetest.string_to_pos(fields.bed_pos)
if coords == nil then
-- fail on illegal input of coordinates
minetest.chat_send_player(sender_name, 'You failed to provide correct coordinates for the bed position. '..
'Please enter the X, Y, and Z coordinates of the desired destination in a comma seperated list. '..
'Example: The input "10,20,30" means the destination at the coordinates X=10, Y=20 and Z=30.')
failed = true
elseif out_of_limit(coords) then
minetest.chat_send_player(sender_name, 'The coordinates of your bed position '..
'do not exist in our coordinate system. Correct coordinates range from -30912 to 30927 in all axes.')
failed = true
else
meta:set_string("bed", fields.bed_pos)
end
coords = minetest.string_to_pos(fields.door_pos)
if coords == nil then
-- fail on illegal input of coordinates
minetest.chat_send_player(sender_name, 'You failed to provide correct coordinates for the door position. '..
'Please enter the X, Y, and Z coordinates of the desired destination in a comma seperated list. '..
'Example: The input "10,20,30" means the destination at the coordinates X=10, Y=20 and Z=30.')
failed = true
elseif out_of_limit(coords) then
minetest.chat_send_player(sender_name, 'The coordinates of your bed position '..
'do not exist in our coordinate system. Correct coordinates range from -30912 to 30927 in all axes.')
failed = true
else
meta:set_string("door", fields.door_pos)
end
if not failed then
meta:set_string("infotext", fields.name)
meta:set_string("formspec",
"size[5,4]"..
"label[0.5,0.5;house label: ".. fields.name .."]"..
"label[0.5,1;bed position:".. fields.bed_pos .."]"..
"label[0.5,1.5;position outside:".. fields.door_pos .."]"..
"label[0.5,2;position of this marker:" .. pos.x .. "," .. pos.y .. "," .. pos.z .. "]"..
"button_exit[1,2.5;2,1;ok;exit]")
end
end,
can_dig = function(pos, player)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
local pname = player:get_player_name()
return pname == owner or pname == minetest.setting_get("name")
end,
})
-- home is a prototype home object
smart_villages.home = {version = 1}
-- get the home of a villager
function smart_villages.get_home(self)
return smart_villages.homes[self.inventory_name]
end
-- check whether a villager has a home
function smart_villages.is_valid_home(self)
local home = smart_villages.get_home(self)
if home == nil then
return false
end
if not home.version~=1 then --update home
for k, v in pairs(smart_villages.home) do
home[k] = v
end
end
return true
end
-- get the position of the home_marker
function smart_villages.home:get_marker()
return self.marker
end
function smart_villages.home:get_marker_meta()
local home_marker_pos = self:get_marker()
if minetest.get_node(home_marker_pos).name == "ignore" then
minetest.get_voxel_manip():read_from_map(home_marker_pos, home_marker_pos)
end
if minetest.get_node(home_marker_pos).name ~= "smart_villages:home_marker" then
if smart_villages.debug_logging and not(vector.equals(home_marker_pos,{x=0,y=0,z=0})) then
minetest.log("warning", "The door position of an invalid home was requested.")
minetest.log("warning", "Given home position:" .. minetest.pos_to_string(home_marker_pos))
end
return false
end
return minetest.get_meta(home_marker_pos)
end
-- get the position that marks "outside"
function smart_villages.home:get_door()
if self.door~=nil then
return self.door
end
local meta = self:get_marker_meta()
local door_pos = meta:get_string("door")
if not door_pos then
if smart_villages.debug_logging then
local home_marker_pos = self:get_marker()
minetest.log("warning", "The position outside the house was not entered for the home at:" ..
minetest.pos_to_string(home_marker_pos))
end
return false
end
self.door = minetest.string_to_pos(door_pos)
return self.door
end
-- get the bed of a villager
function smart_villages.home:get_bed()
if self.bed~=nil then
return self.bed
end
local meta = self:get_marker_meta()
local bed_pos = meta:get_string("bed")
if not bed_pos then
if smart_villages.debug_logging then
local home_marker_pos = self:get_marker()
minetest.log("warning", "The position of the bed was not entered for the home at:" ..
minetest.pos_to_string(home_marker_pos))
end
return false
end
self.bed = minetest.string_to_pos(bed_pos)
return self.bed
end
-- set the home of a villager
function smart_villages.set_home(inv_name,marker_pos)
smart_villages.homes[inv_name] = table.copy(smart_villages.home)
smart_villages.homes[inv_name].marker = marker_pos
end