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