SmallJoker
2022-06-08 f9b0906a82382af30475dc3cb040c4686d54bcf8
commit | author | age
b001a6 1 local S = technic.getter
Z 2
3 local desc = S("Administrative World Anchor")
4
5 local function compute_forceload_positions(pos, meta)
6     local radius = meta:get_int("radius")
7     local minpos = vector.subtract(pos, vector.new(radius, radius, radius))
8     local maxpos = vector.add(pos, vector.new(radius, radius, radius))
9     local minbpos = {}
10     local maxbpos = {}
11     for _, coord in ipairs({"x","y","z"}) do
12         minbpos[coord] = math.floor(minpos[coord] / 16) * 16
13         maxbpos[coord] = math.floor(maxpos[coord] / 16) * 16
14     end
15     local flposes = {}
16     for x = minbpos.x, maxbpos.x, 16 do
17         for y = minbpos.y, maxbpos.y, 16 do
18             for z = minbpos.z, maxbpos.z, 16 do
19                 table.insert(flposes, vector.new(x, y, z))
20             end
21         end
22     end
23     return flposes
24 end
25
26 local function currently_forceloaded_positions(meta)
27     local ser = meta:get_string("forceloaded")
28     return ser == "" and {} or minetest.deserialize(ser)
29 end
30
31 local function forceload_off(meta)
32     local flposes = currently_forceloaded_positions(meta)
33     meta:set_string("forceloaded", "")
34     for _, p in ipairs(flposes) do
35         minetest.forceload_free_block(p)
36     end
37 end
38
39 local function forceload_on(pos, meta)
40     local want_flposes = compute_forceload_positions(pos, meta)
41     local have_flposes = {}
42     for _, p in ipairs(want_flposes) do
43         if minetest.forceload_block(p) then
44             table.insert(have_flposes, p)
45         end
46     end
47     meta:set_string("forceloaded", #have_flposes == 0 and "" or minetest.serialize(have_flposes))
48 end
49
50 local function set_display(pos, meta)
0f6bdb 51     local ESC = minetest.formspec_escape
b001a6 52     meta:set_string("infotext", S(meta:get_int("enabled") ~= 0 and "%s Enabled" or "%s Disabled"):format(desc))
Z 53     meta:set_string("formspec",
54         "size[5,3.5]"..
55         "item_image[0,0;1,1;technic:admin_anchor]"..
0f6bdb 56         "label[1,0;"..ESC(desc).."]"..
S 57         "label[0,1;"..ESC(S("Owner:").." "..meta:get_string("owner")).."]"..
b001a6 58         (meta:get_int("locked") == 0 and
0f6bdb 59             "button[3,1;2,1;lock;"..ESC(S("Unlocked")).."]" or
S 60             "button[3,1;2,1;unlock;"..ESC(S("Locked")).."]")..
61         "field[0.25,2.3;1,1;radius;"..ESC(S("Radius:"))..";"..meta:get_int("radius").."]"..
b001a6 62         (meta:get_int("enabled") == 0 and
0f6bdb 63             "button[3,2;2,1;enable;"..ESC(S("Disabled")).."]" or
S 64             "button[3,2;2,1;disable;"..ESC(S("Enabled")).."]")..
65         "label[0,3;"..ESC(S("Keeping %d/%d map blocks loaded"):format(
66             #currently_forceloaded_positions(meta), #compute_forceload_positions(pos, meta)
67         )).."]")
b001a6 68 end
Z 69
70 minetest.register_node("technic:admin_anchor", {
71     description = desc,
72     drawtype = "normal",
73     tiles = {"technic_admin_anchor.png"},
74     is_ground_content = true,
772c21 75     groups = {cracky=3, not_in_creative_inventory=1},
b001a6 76     sounds = default.node_sound_stone_defaults(),
Z 77     after_place_node = function (pos, placer)
78         local meta = minetest.get_meta(pos)
79         if placer and placer:is_player() then
80             meta:set_string("owner", placer:get_player_name())
81         end
82         set_display(pos, meta)
83     end,
84     can_dig = function (pos, player)
85         local meta = minetest.get_meta(pos)
0f6bdb 86         return meta:get_int("locked") == 0 or
S 87             (player and player:is_player() and player:get_player_name() == meta:get_string("owner"))
b001a6 88     end,
Z 89     on_destruct = function (pos)
90         local meta = minetest.get_meta(pos)
91         forceload_off(meta)
92     end,
93     on_receive_fields = function (pos, formname, fields, sender)
94         local meta = minetest.get_meta(pos)
95         if (meta:get_int("locked") ~= 0 or fields.lock) and
96                 not (sender and sender:is_player() and
97                     sender:get_player_name() == meta:get_string("owner")) then
98             return
99         end
100         if fields.unlock then meta:set_int("locked", 0) end
101         if fields.lock then meta:set_int("locked", 1) end
102         if fields.disable or fields.enable or fields.radius then
103             forceload_off(meta)
104             if fields.disable then meta:set_int("enabled", 0) end
105             if fields.enable then meta:set_int("enabled", 1) end
0f6bdb 106             if fields.radius
S 107                     and string.find(fields.radius, "^[0-9]+$")
108                     and tonumber(fields.radius) < 256 then
109                 meta:set_int("radius", fields.radius)
110             end
b001a6 111             if meta:get_int("enabled") ~= 0 then
Z 112                 forceload_on(pos, meta)
113             end
114         end
115         set_display(pos, meta)
116     end,
117 })