diff --git a/gridio.lua b/gridio.lua index af50803..424917b 100644 --- a/gridio.lua +++ b/gridio.lua @@ -7,42 +7,12 @@ local sbyte, schar = string.byte, string.char local unpk = unpack -- Loading files -local function load_full_map(filename, bytes, signed, size, converter) - local file = io.open(worldpath .. filename, 'rb') - local data = file:read('*all') - if #data < bytes*size then - data = minetest.decompress(data) - end - - local map = {} - - for i=1, size do - local i0 = (i-1)*bytes+1 - local elements = {data:byte(i0, i1)} - local n = sbyte(data, i0) - if signed and n >= 128 then - n = n - 256 - end - - for j=1, bytes-1 do - n = n*256 + sbyte(data, i0+j) - end - - map[i] = n - end - file:close() - - if converter then - for i=1, size do - map[i] = converter(map[i]) - end - end - - return map -end +-- 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) + __index = function(loader, i) -- Called when accessing a missing key local file = loader.file local bytes = loader.bytes file:seek('set', (i-1)*bytes) @@ -60,12 +30,13 @@ local loader_mt = { if loader.conv then n = loader.conv(n) end + -- Cache key for next use loader[i] = n return n end, } -local function interactive_loader(filename, bytes, signed, size, converter) +function mapgen_rivers.load_file(filename, bytes, signed, size, converter) local file = io.open(worldpath .. filename, 'rb') if file then converter = converter or false @@ -73,24 +44,8 @@ local function interactive_loader(filename, bytes, signed, size, converter) end end -local load_methods = { - full = load_full_map, - interactive = interactive_loader, -} - -function mapgen_rivers.load_file(...) - local load_method = mapgen_rivers.settings.load_method - local load_func = load_methods[load_method] - if load_func then - return load_func(...) - else - minetest.log("error", ("[mapgen_rivers] Unknown load method %s"):format(load_method)) - end -end - -- Writing files function mapgen_rivers.write_file(filename, data, bytes) - local size = #data local file = io.open(worldpath .. filename, 'wb') local bytelist = {} @@ -98,7 +53,7 @@ function mapgen_rivers.write_file(filename, data, bytes) bytelist[j] = 0 end - for i=1, size do + for i=1, #data do local n = floor(data[i]) data[i] = n for j=bytes, 2, -1 do diff --git a/gridmanager.lua b/gridmanager.lua index be6cfdb..21c8bda 100644 --- a/gridmanager.lua +++ b/gridmanager.lua @@ -31,44 +31,12 @@ local grid_maps_list = { offset_y = {bytes=1, signed=true, conv=offset_conv}, } -local function apply_grid_conversion(grid) - if grid.load_method ~= "full" then - minetest.log("warning", ("Could not apply data conversion for load method %s"):format(grid.load_method)) - return false - end - if grid.conv_applied then - return true - end - - local size = grid.size.x * grid.size.y - for mapname, params in pairs(grid_maps_list) do - local conv = params.conv - if conv then - local map = grid[mapname] - for i=1, size do - map[i] = conv(map[i]) - end - end - end - grid.conv_applied = true - - return true -end - function mapgen_rivers.try_load_grid(grid) - local load_method = mapgen_rivers.settings.load_method - - -- First, check whether a grid is already loaded with the appropriate method - if mapgen_rivers.grid and mapgen_rivers.grid.load_method == load_method then - if not mapgen_rivers.grid.conv_applied then - apply_grid_conversion(mapgen_rivers.grid) - end + -- First, check whether a grid is already loaded + if mapgen_rivers.grid then return true -- Then, check the provided argument is a valid grid - elseif grid and grid.load_method == load_method then - if not mapgen_rivers.grid.conv_applied then - apply_grid_conversion(grid) - end + elseif grid then mapgen_rivers.grid = grid on_grid_loaded_callback(grid) return true @@ -85,21 +53,15 @@ function mapgen_rivers.try_load_grid(grid) return false end - if load_method == "full" then - minetest.log("action", '[mapgen_rivers] Loading full grid') - elseif load_method == "interactive" then - minetest.log("action", '[mapgen_rivers] Loading grid as interactive loaders') - end + minetest.log("action", '[mapgen_rivers] Loading grid') grid = { - load_method = load_method, size = {x=x, y=z}, } for map, params in pairs(grid_maps_list) do grid[map] = mapgen_rivers.load_file(map, params.bytes, params.signed, x*z, params.conv) end - grid.conv_applied = true mapgen_rivers.grid = grid on_grid_loaded_callback(grid) @@ -115,7 +77,6 @@ function mapgen_rivers.generate_grid() local xsize = math.floor(mapgen_rivers.settings.map_x_size / blocksize) local zsize = math.floor(mapgen_rivers.settings.map_z_size / blocksize) grid.size = {x=xsize, y=zsize} - grid.conv_applied = false if not mapgen_rivers.pregenerate then minetest.log("error", "[mapgen_rivers] Pre-generation function is not available.") @@ -130,11 +91,6 @@ end function mapgen_rivers.write_grid(grid) minetest.mkdir(world_data) - if grid.conv_applied then - minetest.log("error", '[mapgen_rivers] Could not write grid if data conversion is already done') - return false - end - for map, params in pairs(grid_maps_list) do mapgen_rivers.write_file(map, grid[map], params.bytes) end diff --git a/init.lua b/init.lua index 8b227a1..10d21cf 100644 --- a/init.lua +++ b/init.lua @@ -21,6 +21,6 @@ minetest.register_on_mods_loaded(function() local grid = mapgen_rivers.generate_grid() mapgen_rivers.write_grid(grid) - mapgen_rivers.try_load_grid(grid) -- Reload if needed + mapgen_rivers.try_load_grid() -- Reload if needed end end) diff --git a/pregenerate.lua b/pregenerate.lua index aba8bd0..593c781 100644 --- a/pregenerate.lua +++ b/pregenerate.lua @@ -110,7 +110,5 @@ function mapgen_rivers.pregenerate(grid) grid.offset_x = offset_x grid.offset_y = offset_y - grid.load_method = "full" - grid.conv_applied = false collectgarbage() end diff --git a/settings.lua b/settings.lua index ba3d062..538b25b 100644 --- a/settings.lua +++ b/settings.lua @@ -109,13 +109,8 @@ mapgen_rivers.settings = { tectonic_speed = def_setting('tectonic_speed', 'number'), evol_time = def_setting('evol_time', 'number'), evol_time_step = def_setting('evol_time_step', 'number'), - - load_all = mtsettings:get_bool('mapgen_rivers_load_all') } -mapgen_rivers.settings.load_method = - mapgen_rivers.settings.load_all and "full" or "interactive" - mapgen_rivers.noise_params = { base = def_setting("np_base", "noise"), distort_x = def_setting("np_distort_x", "noise"), diff --git a/settings_default.json b/settings_default.json index 3e937c7..cd79af4 100644 --- a/settings_default.json +++ b/settings_default.json @@ -25,7 +25,6 @@ "tectonic_speed": 70, "evol_time": 10, "evol_time_step": 1, - "load_all": false, "np_base": { "offset": 0, diff --git a/settingtypes.txt b/settingtypes.txt index 44b0290..5741736 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -70,11 +70,6 @@ mapgen_rivers_glacier_widening_factor (Glacier widening factor) float 8.0 1.0 20 # This results in mountains being more covered by snow. mapgen_rivers_elevation_chill (Elevation chill) float 0.25 0.0 5.0 -# If enabled, loads all grid data in memory at init time. -# If disabled, data will be loaded on request and cached in memory. -# It's recommended to disable it for very large maps (> 2000 grid nodes or so) -mapgen_rivers_load_all (Load all data in memory) bool false - [Landscape evolution parameters] # Modelled landscape evolution time, in arbitrary units