summaryrefslogtreecommitdiff
path: root/subway/nodes/(-612,10,-248).lua
Commit message (Collapse)AuthorAge
* State at 2019-12-13autocommitter2024-04-22
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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
-- Prevent anyone else accessing those functions
local forceload_block = core.forceload_block
local forceload_free_block = core.forceload_free_block
core.forceload_block = nil
core.forceload_free_block = nil

local blocks_forceloaded
local blocks_temploaded = {}
local total_forceloaded = 0

-- true, if the forceloaded blocks got changed (flag for persistence on-disk)
local forceload_blocks_changed = false

local BLOCKSIZE = core.MAP_BLOCKSIZE
local function get_blockpos(pos)
	return {
		x = math.floor(pos.x/BLOCKSIZE),
		y = math.floor(pos.y/BLOCKSIZE),
		z = math.floor(pos.z/BLOCKSIZE)}
end

-- When we create/free a forceload, it's either transient or persistent. We want
-- to add to/remove from the table that corresponds to the type of forceload, but
-- we also need the other table because whether we forceload a block depends on
-- both tables.
-- This function returns the "primary" table we are adding to/removing from, and
-- the other table.
local function get_relevant_tables(transient)
	if transient then
		return blocks_temploaded, blocks_forceloaded
	else
		return blocks_forceloaded, blocks_temploaded
	end
end

function core.forceload_block(pos, transient)
	-- set changed flag
	forceload_blocks_changed = true

	local blockpos = get_blockpos(pos)
	local hash = core.hash_node_position(blockpos)
	local relevant_table, other_table = get_relevant_tables(transient)
	if relevant_table[hash] ~= nil then
		relevant_table[hash] = relevant_table[hash] + 1
		return true
	elseif other_table[hash] ~= nil then
		relevant_table[hash] = 1
	else
		if total_forceloaded >= (tonumber(core.settings:get("max_forceloaded_blocks")) or 16) then
			return false
		end
		total_forceloaded = total_forceloaded+1
		relevant_table[hash] = 1
		forceload_block(blockpos)
		return true
	end
end

function core.forceload_free_block(pos, transient)
	-- set changed flag
	forceload_blocks_changed = true

	local blockpos = get_blockpos(pos)
	local hash = core.hash_node_position(blockpos)
	local relevant_table, other_table = get_relevant_tables(transient)
	if relevant_table[hash] == nil then return end
	if relevant_table[hash] > 1 then
		relevant_table[hash] = relevant_table[hash] - 1
	elseif other_table[hash] ~= nil then
		relevant_table[hash] = nil
	else
		total_forceloaded = total_forceloaded-1
		relevant_table[hash] = nil
		forceload_free_block(blockpos)
	end
end

-- Keep the forceloaded areas after restart
local wpath = core.get_worldpath()
local function read_file(filename)
	local f = io.open(filename, "r")
	if f==nil then return {} end
	local t = f:read("*all")
	f:close()
	if t=="" or t==nil then return {} end
	return core.deserialize(t) or {}
end

local function write_file(filename, table)
	local f = io.open(filename, "w")
	f:write(core.serialize(table))
	f:close()
end

blocks_forceloaded = read_file(wpath.."/force_loaded.txt")
for _, __ in pairs(blocks_forceloaded) do
	total_forceloaded = total_forceloaded + 1
end

core.after(5, function()
	for hash, _ in pairs(blocks_forceloaded) do
		local blockpos = core.get_position_from_hash(hash)
		forceload_block(blockpos)
	end
end)

-- persists the currently forceloaded blocks to disk
local function persist_forceloaded_blocks()
	write_file(wpath.."/force_loaded.txt", blocks_forceloaded)
end

-- periodical forceload persistence
local function periodically_persist_forceloaded_blocks()

	-- only persist if the blocks actually changed
	if forceload_blocks_changed then
		persist_forceloaded_blocks()

		-- reset changed flag
		forceload_blocks_changed = false
	end

	-- recheck after some time
	core.after(10, periodically_persist_forceloaded_blocks)
end

-- persist periodically
core.after(5, periodically_persist_forceloaded_blocks)

-- persist on shutdown
core.register_on_shutdown(persist_forceloaded_blocks)