-- Manages grid loading, writing and generation local datapath = mapgen_rivers.world_data_path local registered_on_grid_loaded = {} function mapgen_rivers.register_on_grid_loaded(func) if type(func) == "function" then registered_on_grid_loaded[#registered_on_grid_loaded+1] = func else minetest.log("error", "[mapgen_rivers] register_on_grid_loaded can only register functions!") end end local function on_grid_loaded_callback(grid) for _, func in ipairs(registered_on_grid_loaded) do func(grid) end end local function offset_conv(o) return (o + 0.5) * (1/256) end local floor = math.floor local sbyte, schar = string.byte, string.char local unpk = unpack -- Loading files -- Never load the full map during mapgen. Instead, create an empty lookup table -- and read the file on-the-fly when an element is requested for the first time, -- using __index metamethod. local loader_mt = { __index = function(loader, i) -- Called when accessing a missing key local file = loader.file local bytes = loader.bytes file:seek('set', (i-1)*bytes) local strnum = file:read(bytes) local n = sbyte(strnum, 1) if loader.signed and n >= 128 then n = n - 256 end for j=2, bytes do n = n*256 + sbyte(strnum, j) end if loader.conv then n = loader.conv(n) end -- Cache key for next use loader[i] = n return n end, } local function load_file(filename, bytes, signed, size, converter) local file = io.open(datapath .. filename, 'rb') if file then converter = converter or false return setmetatable({file=file, bytes=bytes, signed=signed, size=size, conv=converter}, loader_mt) end end function mapgen_rivers.load_or_generate_grid() -- First, check whether a grid is already loaded if mapgen_rivers.grid then return true end -- If not, try to load the grid from the files local sfile = io.open(datapath .. 'size', 'r') if not sfile then dofile(mapgen_rivers.modpath .. "/pregenerate.lua") collectgarbage() sfile = io.open(datapath .. 'size', 'r') if not sfile then return false end end local x, z = sfile:read('*n'), sfile:read('*n') if not x or not z then return false end minetest.log("action", '[mapgen_rivers] Loading grid') local grid = { size = {x=x, y=z}, dem = load_file('dem', 2, true, x*z), lakes = load_file('lakes', 2, true, x*z), dirs = load_file('dirs', 1, false, x*z), rivers = load_file('rivers', 4, false, x*z), offset_x = load_file('offset_x', 1, true, x*z, offset_conv), offset_y = load_file('offset_y', 1, true, x*z, offset_conv), } mapgen_rivers.grid = grid on_grid_loaded_callback(grid) return true end