]> git.lizzy.rs Git - skycraft.git/blob - src/main/plots.lua
Fixed Protection
[skycraft.git] / src / main / plots.lua
1 skycraft.savedata.plots = skycraft.savedata.plots or {}
2
3 skycraft.savedata.player_plotids = skycraft.savedata.player_plotids or {}
4
5 skycraft.savedata.pos_plotids = skycraft.savedata.pos_plotids or {}
6
7 skycraft.savedata.spiral = skycraft.savedata.spiral or {
8         x = 0,
9         y = 0,
10         d = 1,
11         m = 1,
12         s = true,
13 }
14
15 function skycraft.get_new_spiral_pos()
16         local sp = skycraft.savedata.spiral
17         local rpos = {x = sp.x, z = sp.y}
18         if sp.s then
19                 sp.x = sp.x + sp.d
20                 if not (2 * sp.x * sp.d < sp.m) then
21                         sp.s = false
22                 end
23         else
24                 sp.y = sp.y + sp.d
25                 if not (2 * sp.y * sp.d < sp.m) then
26                         sp.s = true
27                         sp.d = -1 * sp.d
28                         sp.m = sp.m + 1
29                 end
30         end
31         return rpos
32 end
33
34 function skycraft.get_plot_pos_string(pos)
35         return tostring(pos.x) .. "," .. tostring(pos.z)
36 end
37
38 function skycraft.get_plot_at_pos(pos)
39         return skycraft.savedata.plots[skycraft.savedata.pos_plotids[skycraft.get_plot_pos_string(vector.floor(vector.divide(pos, 62)))]]
40 end
41
42 function skycraft.get_plot_by_player(name)
43         return skycraft.savedata.plots[skycraft.savedata.player_plotids[name]]
44 end
45
46 function skycraft.claim_plot(name)
47         local plots = skycraft.savedata.plots
48         local plot = skycraft.get_new_spiral_pos()
49         plot.owner = name
50         plot.members = {}
51         plots[#plots + 1] = plot
52         skycraft.savedata.player_plotids[name] = #plots
53         skycraft.savedata.pos_plotids[skycraft.get_plot_pos_string(plot)] = #plots
54         return plot
55 end
56
57 local plot_commands = {
58         gui = function(name, message)
59                 message = message or ""
60                 local plot = skycraft.get_plot_by_player(name)
61                 if not plot then return false, "You don't have a plot yet" end
62                 local esc = minetest.formspec_escape
63                 local formspec = "size[8,10]"
64                         .. "label[2.5,0;" .. esc("-- Plot interface --") .. "]"
65                         .. "label[0,1;" .. esc(message or "") .. "]"
66                         .. "label[0,2;" .. esc("Members:") .. "]"
67                         .. "button_exit[2.5,9.2;3,0.5;close;" .. esc("Close") .. "]"
68                         .. "field_close_on_enter[add_member_input;false]"
69                 
70                 local n = 0
71                 for i, member in pairs(plot.members) do
72                         formspec = formspec
73                                 .. "button[" .. (n % 4 * 2)
74                                 .. "," .. math.floor(n / 4 + 3)
75                                 .. ";1.5,.5;;" .. esc(member) .. "]"
76                                 .. "button[" .. (n % 4 * 2 + 1.25) .. ","
77                                 .. math.floor(n / 4 + 3)
78                                 .. ";.75,.5;remove_member_" .. tostring(i) .. ";X]"
79                         n = i
80                 end
81                 formspec = formspec
82                         .. "field[" .. (n % 4 * 2 + 1 / 3) .. ","
83                         .. (math.floor(n / 4 + 3) + 1 / 3 - 0.02)
84                         .. ";1.433,.5;add_member_input;;]"
85                         .."button[" .. (n % 4 * 2 + 1.25) .. ","
86                         .. math.floor(n / 4 + 3) .. ";.75,.5;add_member;+]"
87                 minetest.show_formspec(name, "skycraft:plot_gui", formspec)
88         end,
89         help = function(name)
90                 local c = {
91                         {"", "Open the GUI"},
92                         {"gui", "Open the GUI"},
93                         {"help", "Show this help"},
94                         {"add_member <member>", "Add a player to your plot's members (Grant him/her permission to build on your island)"},
95                         {"remove_member <member>", "Remove a player from your plot's members (Revoke him/her permission to build on your island)"},
96                         {"list_members <member>", "List the members of your plot"},
97                         {"home", "Warp to your home plot (Only works if you aren't there already)"},
98                 }
99                 for k, v in pairs(c) do c[k] = minetest.colorize("#FFF83D", "/plot " .. v[1]) .. ": " .. v[2] end
100                 return true, table.concat(c, "\n")
101         end,
102         add_member = function(name, member)
103                 if not member then return false, "Usage: /plot add_member <member>" end
104                 local plot = skycraft.get_plot_by_player(name)
105                 if not plot then return false, "You don't have a plot yet" end
106                 local index = table.indexof(plot.members, member)
107                 if index ~= -1 then return false, member .. " is already a member of your plot" end
108                 table.insert(plot.members, member)
109                 return true, member .. " added to plot members"
110         end,
111         remove_member = function(name, member)
112                 if not member then return false, "Usage: /plot remove_member <member>" end
113                 local plot = skycraft.get_plot_by_player(name)
114                 if not plot then return false, "You don't have a plot yet" end
115                 local index = table.indexof(plot.members, member)
116                 if index == -1 then return false, member .. " isn't a member of your plot" end
117                 table.remove(plot.members, index)
118                 return true, member .. " removed from plot members"
119         end,
120         list_members = function(name, member)
121                 local plot = skycraft.get_plot_by_player(name)
122                 if not plot then return false, "You don't have a plot yet" end
123                 if #plot.members == 0 then return true, "You plot has no members" end
124                 return true, "Plot members: " .. table.concat(plot.members, ", ")
125         end,
126         home = function(name)
127                 local player = minetest.get_player_by_name(name)
128                 if not player then return false, "You have to be online to use this command" end
129                 local pos = player:get_pos()
130                 if pos.y > 5000 then return false, "You are not on the Skyblock map. Use /skyblock to get there" end
131                 if pos.y < -100 then return false, "You can only use this command in the Overworld" end
132                 local plot = skycraft.get_plot_at_pos(pos)
133                 if plot and plot.owner == name then return false, "You are already on your home plot" end
134                 skycraft.spawn_player(player)
135                 return true, "Warped to your home plot"
136         end
137 }
138
139 local plot_chatcommand_def = {
140         description = "Manage your plot. See /plot help for help",
141         param = "[<command> [...]]",
142         privs = {skycraft = true},
143         func = function(name, param)
144                 local cmd = param:split(" ")[1] or "gui"
145                 local cmd_param = param:split(" ")[2]
146                 local cmd_func = plot_commands[cmd]
147                 if not cmd_func then return false, "Invalid command /plot " .. param .. ". See /plot help for help" end
148                 return cmd_func(name, cmd_param)
149         end
150 }
151
152 minetest.register_chatcommand("p", plot_chatcommand_def)
153
154 minetest.register_chatcommand("plot", plot_chatcommand_def)
155
156 minetest.register_on_player_receive_fields(function(player, formname, fields)
157         if formname ~= "skycraft:plot_gui" then return end
158         local name = player:get_player_name()
159         local _, message
160         for i, member in pairs(skycraft.get_plot_by_player(name).members) do
161                 if fields["remove_member_" .. tostring(i)] then
162                         _, message = plot_commands.remove_member(name, member)
163                 end
164         end
165         if fields.add_member and fields.add_member_input ~= "" then
166                 _, message = plot_commands.add_member(name, fields.add_member_input)
167         end
168         if not fields.close and not fields.quit then
169                 plot_commands.gui(name, message)
170         end
171 end)
172
173 local old_is_protected = minetest.is_protected
174 function minetest.is_protected(pos, name)
175         local plot = skycraft.get_plot_at_pos(pos) or {members = {}}
176         if pos.y > 5000 or (pos.y < 1000 and pos.y > -100) or (pos.y > 1000 and plot.owner ~= name and table.indexof(plot.members, name) == -1) then
177                 return not minetest.check_player_privs(name, {protection_bypass = true})
178         else
179                 return old_is_protected(pos, name)
180         end
181 end