Add Biome ID Lookup
This commit is contained in:
parent
f2035af4dc
commit
c7ae36a3c8
@ -1,9 +1,13 @@
|
|||||||
-- Arguments
|
-- Arguments
|
||||||
-- util: API for uncategorized utility methods
|
-- util: API for uncategorized utility methods
|
||||||
local util,skin = ...
|
local map_data,util,skin = ...
|
||||||
|
|
||||||
local biome_lookup = {}
|
local biome_lookup = {}
|
||||||
|
local biome_ids = {}
|
||||||
local fallback_biome_lookup = {}
|
local fallback_biome_lookup = {}
|
||||||
|
local biomes_ready = false
|
||||||
|
local ready_callbacks = {}
|
||||||
|
local biome_id_to_cartographer_id = {}
|
||||||
|
|
||||||
local function match_biome_metrics (biome, height, heat, humidity)
|
local function match_biome_metrics (biome, height, heat, humidity)
|
||||||
return (not height or not biome.min_height or height >= biome.min_height)
|
return (not height or not biome.min_height or height >= biome.min_height)
|
||||||
@ -14,6 +18,33 @@ local function match_biome_metrics (biome, height, heat, humidity)
|
|||||||
and (not humidity or not biome.max_humidity or humidity <= biome.max_humidity)
|
and (not humidity or not biome.max_humidity or humidity <= biome.max_humidity)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
minetest.after(0, function()
|
||||||
|
if map_data.api_version < 2 then
|
||||||
|
for k,_ in pairs(minetest.registered_biomes) do
|
||||||
|
local biome_id = minetest.get_biome_id(k)
|
||||||
|
map_data.biomes[biome_id] = k
|
||||||
|
biome_ids[k] = biome_id
|
||||||
|
biome_id_to_cartographer_id[biome_id] = biome_id
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for k,v in ipairs(map_data.biomes) do
|
||||||
|
biome_ids[v] = k
|
||||||
|
end
|
||||||
|
for k,_ in pairs(minetest.registered_biomes) do
|
||||||
|
if not biome_ids[k] then
|
||||||
|
table.insert(map_data.biomes, k)
|
||||||
|
biome_ids[k] = #map_data.biomes
|
||||||
|
biome_id_to_cartographer_id[minetest.get_biome_id(k)] = #map_data.biomes
|
||||||
|
else
|
||||||
|
biome_id_to_cartographer_id[minetest.get_biome_id(k)] = biome_ids[k]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _,cb in ipairs(ready_callbacks) do
|
||||||
|
cb()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
-- Contains functions for registering and getting biome-related mapping information
|
-- Contains functions for registering and getting biome-related mapping information
|
||||||
return {
|
return {
|
||||||
-- Register a biome with textures to display. Takes arguments as a table.
|
-- Register a biome with textures to display. Takes arguments as a table.
|
||||||
@ -50,6 +81,33 @@ return {
|
|||||||
table.insert(fallback_biome_lookup, table.copy(args))
|
table.insert(fallback_biome_lookup, table.copy(args))
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
-- Convert a minetest biome id (temporary) into a cartography biome id (permanent)
|
||||||
|
--
|
||||||
|
-- id: The biome id to convert
|
||||||
|
--
|
||||||
|
-- Returns the biome's permamnent id, or 0 if not registered
|
||||||
|
convert_biome_id = function(id)
|
||||||
|
return biome_id_to_cartographer_id[id] or 0
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Get the permanent id of a biome from its name
|
||||||
|
--
|
||||||
|
-- name: A string containing the biome name
|
||||||
|
--
|
||||||
|
-- Returns the biome's permamnent id, or 0 if not registered
|
||||||
|
get_biome_id = function(name)
|
||||||
|
return biome_ids[name] or 0
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Get the name of a biome from its permanent id
|
||||||
|
--
|
||||||
|
-- id: The biome id
|
||||||
|
--
|
||||||
|
-- Returns the name of the biome, or "" if not registered
|
||||||
|
get_biome_name = function(id)
|
||||||
|
return map_data.biomes[id] or ""
|
||||||
|
end,
|
||||||
|
|
||||||
-- Get the texture name (minus index/extension) for the given biome, height, and detail level.
|
-- Get the texture name (minus index/extension) for the given biome, height, and detail level.
|
||||||
--
|
--
|
||||||
-- name: A string containing the biome name
|
-- name: A string containing the biome name
|
||||||
@ -60,7 +118,7 @@ return {
|
|||||||
--
|
--
|
||||||
-- Always returns a string with a texture name, if the biome is unregistered it will fallback to other options
|
-- Always returns a string with a texture name, if the biome is unregistered it will fallback to other options
|
||||||
get_texture = function (name, height, heat, humidity, detail)
|
get_texture = function (name, height, heat, humidity, detail)
|
||||||
for _,biome in ipairs(biome_lookup) do
|
for _,biome in pairs(biome_lookup) do
|
||||||
if biome.name == name and match_biome_metrics (biome, height, heat, humidity) then
|
if biome.name == name and match_biome_metrics (biome, height, heat, humidity) then
|
||||||
return util.get_clamped(biome.textures, detail)
|
return util.get_clamped(biome.textures, detail)
|
||||||
end
|
end
|
||||||
@ -76,4 +134,17 @@ return {
|
|||||||
-- If we don't have any registered defaults, fallback to a texture
|
-- If we don't have any registered defaults, fallback to a texture
|
||||||
return util.get_clamped(skin.default_biome_textures, detail)
|
return util.get_clamped(skin.default_biome_textures, detail)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
-- Is this API ready, or still initializing?
|
||||||
|
is_ready = function()
|
||||||
|
return biomes_ready
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_ready = function(cb)
|
||||||
|
if biomes_ready then
|
||||||
|
cb()
|
||||||
|
else
|
||||||
|
table.insert(ready_callbacks, cb)
|
||||||
|
end
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
|
9
init.lua
9
init.lua
@ -10,15 +10,15 @@ local settings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
-- Includes
|
-- Includes
|
||||||
local map_data = loadfile(modpath .. "/storage.lua") (settings);
|
local map_data,private_storage = loadfile(modpath .. "/storage.lua") (settings);
|
||||||
local chunk = loadfile(modpath .. "/chunk_api.lua") ();
|
local chunk = loadfile(modpath .. "/chunk_api.lua") ();
|
||||||
local gui = loadfile(modpath .. "/formspec.lua") ();
|
local gui = loadfile(modpath .. "/formspec.lua") ();
|
||||||
local skin = loadfile(modpath .. "/skin_api.lua") ();
|
local skin = loadfile(modpath .. "/skin_api.lua") ();
|
||||||
local util = loadfile(modpath .. "/util.lua") ();
|
local util = loadfile(modpath .. "/util.lua") ();
|
||||||
local audio = loadfile(modpath .. "/audio.lua") ();
|
local audio = loadfile(modpath .. "/audio.lua") ();
|
||||||
local biomes = loadfile(modpath .. "/biome_api.lua") (util, skin);
|
local biomes = loadfile(modpath .. "/biome_api.lua") (map_data, util, skin);
|
||||||
local markers = loadfile(modpath .. "/marker_api.lua") ();
|
local markers = loadfile(modpath .. "/marker_api.lua") ();
|
||||||
local scanner = loadfile(modpath .. "/scanner.lua") (map_data, chunk, settings);
|
local scanner = loadfile(modpath .. "/scanner.lua") (map_data, chunk, settings, biomes);
|
||||||
local maps = loadfile(modpath .. "/map_api.lua") (map_data, chunk);
|
local maps = loadfile(modpath .. "/map_api.lua") (map_data, chunk);
|
||||||
local materials = loadfile(modpath .. "/material_api.lua") ();
|
local materials = loadfile(modpath .. "/material_api.lua") ();
|
||||||
local map_formspec = loadfile(modpath .. "/map_formspec.lua") (map_data, gui, skin, util, biomes, markers);
|
local map_formspec = loadfile(modpath .. "/map_formspec.lua") (map_data, gui, skin, util, biomes, markers);
|
||||||
@ -44,3 +44,6 @@ cartographer = {
|
|||||||
-- scanner.lua: Exposes functions for queuing and performing terrain scans
|
-- scanner.lua: Exposes functions for queuing and performing terrain scans
|
||||||
scanner = scanner,
|
scanner = scanner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- If the API is out of date, update it now
|
||||||
|
private_storage.migrate_data(map_data.api_version, cartographer)
|
||||||
|
@ -82,7 +82,7 @@ local function generate_map(x, y, w, h, player_x, player_y, detail, map_scale, h
|
|||||||
image = get_variant(unknown_tex, i, j, noise),
|
image = get_variant(unknown_tex, i, j, noise),
|
||||||
};
|
};
|
||||||
else
|
else
|
||||||
local name = minetest.get_biome_name(column[world_j].biome)
|
local name = biomes.get_biome_name(column[world_j].biome)
|
||||||
local height = column[world_j].height
|
local height = column[world_j].height
|
||||||
local heat = column[world_j].heat
|
local heat = column[world_j].heat
|
||||||
local humidity = column[world_j].humidity
|
local humidity = column[world_j].humidity
|
||||||
|
14
scanner.lua
14
scanner.lua
@ -2,7 +2,7 @@
|
|||||||
-- map_data: The cartographer map data table
|
-- map_data: The cartographer map data table
|
||||||
-- chunk: The chunk coordinate conversion API
|
-- chunk: The chunk coordinate conversion API
|
||||||
-- settings: The mod settings
|
-- settings: The mod settings
|
||||||
local map_data, chunk, settings = ...;
|
local map_data, chunk, settings, biome_api = ...;
|
||||||
|
|
||||||
local scan_queue = {};
|
local scan_queue = {};
|
||||||
|
|
||||||
@ -51,8 +51,8 @@ end
|
|||||||
--
|
--
|
||||||
-- Returns the biome, height, heat, and humidity of the scanned region
|
-- Returns the biome, height, heat, and humidity of the scanned region
|
||||||
local function get_mapgen_biome(min, max, mmin, mmax)
|
local function get_mapgen_biome(min, max, mmin, mmax)
|
||||||
local UNDERGROUND = minetest.get_biome_id("underground");
|
local UNDERGROUND = biome_api.get_biome_id("underground");
|
||||||
local DEFAULT = minetest.get_biome_id("default");
|
local DEFAULT = biome_api.get_biome_id("default");
|
||||||
|
|
||||||
local biomes = minetest.get_mapgen_object("biomemap");
|
local biomes = minetest.get_mapgen_object("biomemap");
|
||||||
local heights = minetest.get_mapgen_object("heightmap");
|
local heights = minetest.get_mapgen_object("heightmap");
|
||||||
@ -75,7 +75,7 @@ local function get_mapgen_biome(min, max, mmin, mmax)
|
|||||||
|
|
||||||
for i = startx,startx + xx,1 do
|
for i = startx,startx + xx,1 do
|
||||||
for k = startz,startz + zz,1 do
|
for k = startz,startz + zz,1 do
|
||||||
local b = biomes[i + (k * (xxx + 1))];
|
local b = biome_api.convert_biome_id(biomes[i + (k * (xxx + 1))])
|
||||||
if b ~= nil and b ~= UNDERGROUND and b ~= DEFAULT then
|
if b ~= nil and b ~= UNDERGROUND and b ~= DEFAULT then
|
||||||
scan_biomes[b] = (scan_biomes[b] or 0) + 1;
|
scan_biomes[b] = (scan_biomes[b] or 0) + 1;
|
||||||
scan_heights[b] = (scan_heights[b] or 0) + heights[i + (k * (xxx + 1))];
|
scan_heights[b] = (scan_heights[b] or 0) + heights[i + (k * (xxx + 1))];
|
||||||
@ -115,8 +115,8 @@ end
|
|||||||
--
|
--
|
||||||
-- Returns the biome, height, heat, and humidity of the scanned region
|
-- Returns the biome, height, heat, and humidity of the scanned region
|
||||||
local function get_biome(min, max)
|
local function get_biome(min, max)
|
||||||
local UNDERGROUND = minetest.get_biome_id("underground");
|
local UNDERGROUND = biome_api.get_biome_id("underground");
|
||||||
local DEFAULT = minetest.get_biome_id("default");
|
local DEFAULT = biome_api.get_biome_id("default");
|
||||||
local WATER_SOURCE = minetest.registered_aliases["mapgen_water_source"];
|
local WATER_SOURCE = minetest.registered_aliases["mapgen_water_source"];
|
||||||
|
|
||||||
local scan_biomes = {};
|
local scan_biomes = {};
|
||||||
@ -130,7 +130,7 @@ local function get_biome(min, max)
|
|||||||
for k = min.z,max.z,1 do
|
for k = min.z,max.z,1 do
|
||||||
local pos = { x=i, y=j, z=k };
|
local pos = { x=i, y=j, z=k };
|
||||||
local biome_data = minetest.get_biome_data(pos)
|
local biome_data = minetest.get_biome_data(pos)
|
||||||
local b = biome_data.biome
|
local b = biome_api.convert_biome_id(biome_data.biome)
|
||||||
local node = minetest.get_node(pos).name;
|
local node = minetest.get_node(pos).name;
|
||||||
if b ~= nil and b ~= UNDERGROUND and b ~= DEFAULT and node ~= "air" and node ~= WATER_SOURCE then
|
if b ~= nil and b ~= UNDERGROUND and b ~= DEFAULT and node ~= "air" and node ~= WATER_SOURCE then
|
||||||
pos.y = pos.y + 1;
|
pos.y = pos.y + 1;
|
||||||
|
66
storage.lua
66
storage.lua
@ -1,9 +1,12 @@
|
|||||||
-- Arguments
|
-- Arguments
|
||||||
-- settings: The mod settings
|
-- settings: The mod settings
|
||||||
local settings = ...;
|
local settings = ...
|
||||||
|
|
||||||
|
-- The current API version
|
||||||
|
local MAX_API_VERSION = 2
|
||||||
|
|
||||||
-- Storage and saving
|
-- Storage and saving
|
||||||
local mod_storage = minetest.get_mod_storage();
|
local mod_storage = minetest.get_mod_storage()
|
||||||
local map_data = {
|
local map_data = {
|
||||||
-- Scanned map data
|
-- Scanned map data
|
||||||
generated = minetest.deserialize(mod_storage:get_string("map")) or {},
|
generated = minetest.deserialize(mod_storage:get_string("map")) or {},
|
||||||
@ -11,26 +14,69 @@ local map_data = {
|
|||||||
-- Maps
|
-- Maps
|
||||||
maps = minetest.deserialize(mod_storage:get_string("maps")) or {},
|
maps = minetest.deserialize(mod_storage:get_string("maps")) or {},
|
||||||
|
|
||||||
|
biomes = minetest.deserialize(mod_storage:get_string("biomes")) or {},
|
||||||
|
|
||||||
-- The next id
|
-- The next id
|
||||||
next_map_id = mod_storage:get_int("next_map_id"),
|
next_map_id = mod_storage:get_int("next_map_id"),
|
||||||
|
|
||||||
-- The version of the map api
|
-- The version of the map api
|
||||||
api_version = mod_storage:get_int("api_version"),
|
api_version = mod_storage:get_int("api_version"),
|
||||||
};
|
}
|
||||||
|
|
||||||
|
-- Is this API ready, or still initializing?
|
||||||
|
--
|
||||||
|
-- self: The map_data instance
|
||||||
|
function map_data.is_ready(self)
|
||||||
|
return self.api_version == MAX_API_VERSION
|
||||||
|
end
|
||||||
|
|
||||||
if map_data.next_map_id == 0 then
|
if map_data.next_map_id == 0 then
|
||||||
map_data.next_map_id = 1;
|
map_data.next_map_id = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if map_data.api_version == 0 then
|
if map_data.api_version == 0 then
|
||||||
map_data.api_version = 1;
|
map_data.api_version = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert(map_data.api_version <= MAX_API_VERSION)
|
||||||
|
|
||||||
|
local private_storage = {
|
||||||
|
migrations = { },
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Update the API version, performing any necessary data migrations
|
||||||
|
function private_storage.migrate_data(version, api)
|
||||||
|
if version <= MAX_API_VERSION then
|
||||||
|
map_data.api_version = version
|
||||||
|
|
||||||
|
for i=version+1,MAX_API_VERSION do
|
||||||
|
if private_storage.migrations[i] then
|
||||||
|
private_storage.migrations[i](api)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.is_ready = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- API version 2: Generate biomes from existing IDs
|
||||||
|
table.insert(private_storage.migrations, 2, function(api)
|
||||||
|
-- Migration depends on async biome init, so we wait for that then increment the version
|
||||||
|
api.biomes.on_ready(function()
|
||||||
|
private_storage.migrate_data(2, api)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
local function save()
|
local function save()
|
||||||
mod_storage:set_string("maps", minetest.serialize(map_data.maps));
|
if not map_data:is_ready() then
|
||||||
mod_storage:set_int("next_map_id", map_data.next_map_id);
|
return
|
||||||
mod_storage:set_string("map", minetest.serialize(map_data.generated));
|
end
|
||||||
mod_storage:set_string("api_version", minetest.serialize(map_data.api_version));
|
mod_storage:set_string("biomes", minetest.serialize(map_data.biomes))
|
||||||
|
mod_storage:set_string("maps", minetest.serialize(map_data.maps))
|
||||||
|
mod_storage:set_int("next_map_id", map_data.next_map_id)
|
||||||
|
mod_storage:set_string("map", minetest.serialize(map_data.generated))
|
||||||
|
mod_storage:set_int("api_version", map_data.api_version)
|
||||||
end
|
end
|
||||||
minetest.register_on_shutdown(save);
|
minetest.register_on_shutdown(save);
|
||||||
minetest.register_on_leaveplayer(save);
|
minetest.register_on_leaveplayer(save);
|
||||||
@ -43,4 +89,4 @@ if settings.autosave_freq ~= 0 then
|
|||||||
minetest.after(settings.autosave_freq, periodic_save);
|
minetest.after(settings.autosave_freq, periodic_save);
|
||||||
end
|
end
|
||||||
|
|
||||||
return map_data;
|
return map_data,private_storage
|
||||||
|
Loading…
x
Reference in New Issue
Block a user