smart_villages/homes.lua

214 lines
7.1 KiB
Lua
Raw Permalink Normal View History

2020-04-23 06:47:24 -07:00
-- smart_villages.homes represents a table that contains the villagers homes.
2018-01-13 06:45:17 -08:00
-- This table's keys are inventory names, and values are home objects.
2020-04-23 06:47:24 -07:00
smart_villages.homes = (function()
local file_name = minetest.get_worldpath() .. "/smart_villages_homes"
2018-01-13 06:45:17 -08:00
minetest.register_on_shutdown(function()
2018-04-10 22:55:34 -07:00
local save_data = {}
2020-04-23 06:47:24 -07:00
for k,v in pairs(smart_villages.homes) do
2018-04-10 22:55:34 -07:00
save_data[k]={marker=v.marker}
end
2018-01-13 06:45:17 -08:00
local file = io.open(file_name, "w")
2018-04-10 22:55:34 -07:00
file:write(minetest.serialize(save_data))
2018-01-13 06:45:17 -08:00
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) ()
2018-04-26 10:16:18 -07:00
local function out_of_limit(pos)
2018-04-29 10:33:53 -07:00
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
2018-04-26 10:16:18 -07:00
return false
end
return true
end
2020-04-23 06:47:24 -07:00
minetest.register_node("smart_villages:home_marker", {
description = "home marker for smart_villages",
2017-05-11 07:55:13 -07:00
drawtype = "nodebox",
2017-06-03 07:55:25 -07:00
tiles = {"default_sign_wall_wood.png"},
inventory_image = "default_sign_wood.png",
wield_image = "default_sign_wood.png",
2017-05-11 07:55:13 -07:00
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}]"..
2017-05-11 07:55:13 -07:00
"button_exit[1,4;2,1;ok;Write]")
end,
2018-04-23 06:20:40 -07:00
on_receive_fields = function(pos, _, fields, sender)
2017-05-11 07:55:13 -07:00
local meta = minetest.get_meta(pos)
local sender_name = sender:get_player_name()
2018-01-31 07:53:45 -08:00
local failed = false
2017-05-11 07:55:13 -07:00
if minetest.is_protected(pos, sender_name) then
minetest.record_protection_violation(pos, sender_name)
return
end
2018-04-23 06:20:40 -07:00
if (meta:get_string("bed")~="" and meta:get_string("door")~="")
or (fields.bed_pos == nil and fields.door_pos == nil) then
2017-05-11 07:55:13 -07:00
return
end
2018-04-09 22:58:59 -07:00
local coords = minetest.string_to_pos(fields.bed_pos)
2018-01-31 07:53:45 -08:00
if coords == nil then
2017-05-11 07:55:13 -07:00
-- fail on illegal input of coordinates
2018-04-23 06:20:40 -07:00
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.')
2018-01-31 07:53:45 -08:00
failed = true
2018-04-26 10:16:18 -07:00
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.')
2018-01-31 07:53:45 -08:00
failed = true
else
meta:set_string("bed", fields.bed_pos)
2017-05-11 07:55:13 -07:00
end
2018-04-09 22:58:59 -07:00
coords = minetest.string_to_pos(fields.door_pos)
2018-01-31 07:53:45 -08:00
if coords == nil then
2017-05-11 07:55:13 -07:00
-- fail on illegal input of coordinates
2018-04-23 06:20:40 -07:00
minetest.chat_send_player(sender_name, 'You failed to provide correct coordinates for the door position. '..
2018-04-29 10:33:53 -07:00
'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.')
2018-01-31 07:53:45 -08:00
failed = true
2018-04-26 10:16:18 -07:00
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.')
2018-01-31 07:53:45 -08:00
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]")
2017-05-11 07:55:13 -07:00
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,
})
2018-04-07 02:40:02 -07:00
-- home is a prototype home object
2020-04-23 06:47:24 -07:00
smart_villages.home = {version = 1}
2018-04-07 02:40:02 -07:00
2018-01-13 06:45:17 -08:00
-- get the home of a villager
2020-04-23 06:47:24 -07:00
function smart_villages.get_home(self)
return smart_villages.homes[self.inventory_name]
2018-01-13 06:45:17 -08:00
end
-- check whether a villager has a home
2020-04-23 06:47:24 -07:00
function smart_villages.is_valid_home(self)
local home = smart_villages.get_home(self)
2018-04-07 04:16:33 -07:00
if home == nil then
return false
end
2018-04-10 22:44:06 -07:00
if not home.version~=1 then --update home
2020-04-23 06:47:24 -07:00
for k, v in pairs(smart_villages.home) do
2018-04-07 04:16:33 -07:00
home[k] = v
end
2018-01-13 06:45:17 -08:00
end
2018-04-07 04:16:33 -07:00
return true
2018-01-13 06:45:17 -08:00
end
-- get the position of the home_marker
2020-04-23 06:47:24 -07:00
function smart_villages.home:get_marker()
2018-04-07 02:40:02 -07:00
return self.marker
2018-01-13 06:45:17 -08:00
end
2020-04-23 06:47:24 -07:00
function smart_villages.home:get_marker_meta()
2018-04-07 04:16:33 -07:00
local home_marker_pos = self:get_marker()
2018-01-13 06:45:17 -08:00
if minetest.get_node(home_marker_pos).name == "ignore" then
minetest.get_voxel_manip():read_from_map(home_marker_pos, home_marker_pos)
end
2020-04-23 06:47:24 -07:00
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
2017-05-11 07:55:13 -07:00
minetest.log("warning", "The door position of an invalid home was requested.")
2018-04-29 10:33:53 -07:00
minetest.log("warning", "Given home position:" .. minetest.pos_to_string(home_marker_pos))
2017-05-11 07:55:13 -07:00
end
return false
end
2018-04-07 02:40:02 -07:00
return minetest.get_meta(home_marker_pos)
end
-- get the position that marks "outside"
2020-04-23 06:47:24 -07:00
function smart_villages.home:get_door()
2018-04-07 02:40:02 -07:00
if self.door~=nil then
return self.door
end
local meta = self:get_marker_meta()
2017-05-11 07:55:13 -07:00
local door_pos = meta:get_string("door")
if not door_pos then
2020-04-23 06:47:24 -07:00
if smart_villages.debug_logging then
2018-04-10 22:44:06 -07:00
local home_marker_pos = self:get_marker()
2018-04-30 08:29:15 -07:00
minetest.log("warning", "The position outside the house was not entered for the home at:" ..
minetest.pos_to_string(home_marker_pos))
2017-05-11 07:55:13 -07:00
end
return false
end
2018-04-10 22:44:06 -07:00
self.door = minetest.string_to_pos(door_pos)
return self.door
2017-05-11 07:55:13 -07:00
end
2018-01-13 06:45:17 -08:00
-- get the bed of a villager
2020-04-23 06:47:24 -07:00
function smart_villages.home:get_bed()
2018-04-07 02:40:02 -07:00
if self.bed~=nil then
return self.bed
2018-01-12 07:41:47 -08:00
end
2018-04-07 02:40:02 -07:00
local meta = self:get_marker_meta()
2017-05-11 07:55:13 -07:00
local bed_pos = meta:get_string("bed")
if not bed_pos then
2020-04-23 06:47:24 -07:00
if smart_villages.debug_logging then
2018-04-10 22:44:06 -07:00
local home_marker_pos = self:get_marker()
2018-04-30 08:29:15 -07:00
minetest.log("warning", "The position of the bed was not entered for the home at:" ..
minetest.pos_to_string(home_marker_pos))
2018-04-07 02:40:02 -07:00
end
return false
end
2018-04-10 22:44:06 -07:00
self.bed = minetest.string_to_pos(bed_pos)
return self.bed
2018-04-07 02:40:02 -07:00
end
-- set the home of a villager
2020-04-23 06:47:24 -07:00
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
2017-05-11 07:55:13 -07:00
end