Fix potential crash when few loot items are registered
[oweals/minetest_game.git] / mods / sethome / init.lua
1
2 sethome = {}
3
4 local homes_file = minetest.get_worldpath() .. "/homes"
5 local homepos = {}
6
7 local function loadhomes()
8         local input = io.open(homes_file, "r")
9         if not input then
10                 return -- no longer an error
11         end
12
13         -- Iterate over all stored positions in the format "x y z player" for each line
14         for pos, name in input:read("*a"):gmatch("(%S+ %S+ %S+)%s([%w_-]+)[\r\n]") do
15                 homepos[name] = minetest.string_to_pos(pos)
16         end
17         input:close()
18 end
19
20 loadhomes()
21
22 sethome.set = function(name, pos)
23         local player = minetest.get_player_by_name(name)
24         if not player or not pos then
25                 return false
26         end
27         player:set_attribute("sethome:home", minetest.pos_to_string(pos))
28
29         -- remove `name` from the old storage file
30         local data = {}
31         local output = io.open(homes_file, "w")
32         if output then
33                 homepos[name] = nil
34                 for i, v in pairs(homepos) do
35                         table.insert(data, string.format("%.1f %.1f %.1f %s\n", v.x, v.y, v.z, i))
36                 end
37                 output:write(table.concat(data))
38                 io.close(output)
39                 return true
40         end
41         return true -- if the file doesn't exist - don't return an error.
42 end
43
44 sethome.get = function(name)
45         local player = minetest.get_player_by_name(name)
46         local pos = minetest.string_to_pos(player:get_attribute("sethome:home"))
47         if pos then
48                 return pos
49         end
50
51         -- fetch old entry from storage table
52         pos = homepos[name]
53         if pos then
54                 return vector.new(pos)
55         else
56                 return nil
57         end
58 end
59
60 sethome.go = function(name)
61         local pos = sethome.get(name)
62         local player = minetest.get_player_by_name(name)
63         if player and pos then
64                 player:set_pos(pos)
65                 return true
66         end
67         return false
68 end
69
70 minetest.register_privilege("home", {
71         description = "Can use /sethome and /home",
72         give_to_singleplayer = false
73 })
74
75 minetest.register_chatcommand("home", {
76         description = "Teleport you to your home point",
77         privs = {home = true},
78         func = function(name)
79                 if sethome.go(name) then
80                         return true, "Teleported to home!"
81                 end
82                 return false, "Set a home using /sethome"
83         end,
84 })
85
86 minetest.register_chatcommand("sethome", {
87         description = "Set your home point",
88         privs = {home = true},
89         func = function(name)
90                 name = name or "" -- fallback to blank name if nil
91                 local player = minetest.get_player_by_name(name)
92                 if player and sethome.set(name, player:get_pos()) then
93                         return true, "Home set!"
94                 end
95                 return false, "Player not found!"
96         end,
97 })