forceload/init.lua
2015-08-04 08:44:02 +01:00

156 lines
4.0 KiB
Lua

local function pos_to_string_no_err(pos)
if not pos then
return "(-,-,-)"
end
return minetest.pos_to_string(pos)
end
-- Makes sure that force load areas are handled correctly
function ForceloadManager(filetoopen, hide_file_errors)
local blocks = {}
if filetoopen ~= nil then
local file = io.open(filetoopen, "r")
if file then
local table = minetest.deserialize(file:read("*all"))
file:close()
if type(table) == "table" then
blocks = table
end
elseif not hide_file_errors then
minetest.log("error", "File "..filetoopen.." does not exist!")
end
end
for i = 1, #blocks do
if not minetest.forceload_block(blocks[i]) then
minetest.log("error", "Failed to load block " .. pos_to_string_no_err(blocks[i]))
end
end
return {
_blocks = blocks,
load = function(self, pos)
if minetest.forceload_block(pos) then
table.insert(self._blocks, vector.new(pos))
return true
end
minetest.log("error", "Failed to load block " .. pos_to_string_no_err(pos))
return false
end,
unload = function(self, pos)
for i = 1, #self._blocks do
if vector.equals(pos, self._blocks[i]) then
minetest.forceload_free_block(pos)
table.remove(self._blocks, i)
return true
end
end
return false
end,
save = function(self, filename)
local file = io.open(filename, "w")
if file then
file:write(minetest.serialize(self._blocks))
file:close()
end
end,
verify = function(self)
return self:verify_each(function(pos, block)
local name = "ignore"
if block ~= nil then
name = block.name
end
if name == "ignore" then
if not pos.last or elapsed_time > pos.last + 15 then
pos.last = elapsed_time
if not minetest.forceload_block(pos) then
minetest.log("error", "Failed to force load " .. pos_to_string_no_err(pos))
pos.remove = true
end
end
return false
elseif name == "forceload:anchor" then
pos.last = elapsed_time
return true
else
minetest.log("error", pos_to_string_no_err(pos) .. " shouldn't be loaded")
pos.remove = true
return false
end
end)
end,
verify_each = function(self, func)
local not_loaded = {}
for i = 1, #self._blocks do
local res = minetest.get_node(self._blocks[i])
if not func(self._blocks[i], res) then
--[[table.insert(not_loaded, {
pos = self._blocks[i],
i = i,
b = res })]]--
end
end
return not_loaded
end,
clean = function(self)
local i = 1
while i <= #self._blocks do
if self._blocks[i].remove then
minetest.forceload_free_block(self._blocks[i])
table.remove(self._blocks, i)
else
i = i + 1
end
end
end
}
end
local flm = ForceloadManager(minetest.get_worldpath().."/flm.json", true)
minetest.register_privilege("forceload", "Allows players to use forceload block anchors")
minetest.register_node("forceload:anchor",{
description = "Block Anchor",
walkable = false,
tiles = {"forceload_anchor.png"},
groups = {cracky = 3, oddly_breakable_by_hand = 2},
after_destruct = function(pos)
flm:unload(pos)
flm:save(minetest.get_worldpath().."/flm.json")
end,
after_place_node = function(pos, placer)
if not minetest.check_player_privs(placer:get_player_name(),
{forceload = true}) then
minetest.chat_send_player(placer:get_player_name(), "The forceload privilege is required to do that.")
elseif flm:load(pos) then
flm:save(minetest.get_worldpath().."/flm.json")
return
end
minetest.set_node(pos, {name="air"})
return true
end
})
minetest.register_craft({
output = "forceload:anchor",
recipe = {
{"default:mese_crystal", "default:mese_crystal", "default:mese_crystal"},
{"default:mese_crystal", "wool:blue", "default:mese_crystal"},
{"default:mese_crystal", "default:mese_crystal", "default:mese_crystal"}
}
})
local elapsed_time = 0
local count = 0
minetest.register_globalstep(function(dtime)
count = count + dtime
elapsed_time = elapsed_time + dtime
if count > 5 then
count = 0
--print("Verifying...")
flm:verify()
flm:clean()
end
end)