diff --git a/init.lua b/init.lua index 2470b57..c65b68c 100644 --- a/init.lua +++ b/init.lua @@ -4,17 +4,15 @@ local modpath = minetest.get_modpath("cartographer"); -- Includes local map_data = loadfile(modpath .. "/storage.lua") (); local chunk = loadfile(modpath .. "/chunk_api.lua") (); -local skin = loadfile(modpath .. "/skin_api.lua") (); local gui = loadfile(modpath .. "/formspec.lua") (); -local audio = loadfile(modpath .. "/audio.lua") (); +local skin = loadfile(modpath .. "/skin_api.lua") (); local util = loadfile(modpath .. "/util.lua") (); - +local audio = loadfile(modpath .. "/audio.lua") (); local biomes = loadfile(modpath .. "/biome_api.lua") (util); - +local markers = loadfile(modpath .. "/marker_api.lua") (); local scanner = loadfile(modpath .. "/scanner.lua") (map_data, chunk); local maps = loadfile(modpath .. "/map_api.lua") (map_data, chunk); local materials = loadfile(modpath .. "/material_api.lua") (); -local markers = loadfile(modpath .. "/marker_api.lua") (); local map_formspec = loadfile(modpath .. "/map_formspec.lua") (map_data, gui, skin, util, biomes, markers); local map_item = loadfile(modpath .. "/items.lua") (chunk, gui, skin, audio, maps, markers, map_formspec); loadfile(modpath .. "/commands.lua") (chunk, audio, map_formspec); diff --git a/items.lua b/items.lua index 7c94c1a..ad05968 100644 --- a/items.lua +++ b/items.lua @@ -1,9 +1,18 @@ +-- Arguments +-- chunk: The chunk coordinate conversion API +-- gui: The GUI API +-- skin: The GUI skin +-- audio: The audio playback API +-- maps: The map API +-- markers: The marker API +-- map_formspec: The map display API local chunk, gui, skin, audio, maps, markers, map_formspec = ...; -- The list of players looking at maps, and the map IDs that they're looking at local player_maps = {}; --- Generates formspec data for the map marker editor +-- Generate formspec data for the map marker editor +-- -- selected_id: The id of the currently selected marker, or nil if no marker is -- selected -- detail: The map's detail level @@ -90,23 +99,19 @@ local function marker_formspec(selected_id, detail, page) return table.concat(formspec); end --- Show a map to a player from the ID --- id: The map ID +-- Show a map to a player +-- +-- map: The map to display -- player_x: The X position (in world coordinates) -- player_z: The Z position (in world coordinates) -- player_name: The name of the player to show to -- height_mode: Whether or not to display the map in height mode -- (Optional) marker_page: The current page that the marker editor is on -local function show_map_id_formspec(id, player_x, player_z, player_name, height_mode, marker_page) - local map = maps.get(id); - if not map then - return - end - - map:fill_local(id, player_x, player_z); +local function show_map_formspec(map, player_x, player_z, player_name, height_mode, marker_page) + map:fill_local(player_x, player_z); player_maps[player_name] = { - id = id, + id = map.id, page = marker_page or 1, height_mode = height_mode, }; @@ -174,11 +179,14 @@ local function show_map_id_formspec(id, player_x, player_z, player_name, height_ end -- Get the description text for a map ID and dimensions +-- -- id: The map ID -- from_x: The x coordinate of the top-left corner of the map, in world coordinates -- from_z: The z coordinate of the top-left corner of the map, in world coordinates -- w: The width, in world coordinates -- h: The height, in world coordinates +-- +-- returns a string containing the description local function map_description(id, from_x, from_z, w, h) return string.format("Map #%d\n[%d,%d] - [%d,%d]", id, @@ -187,9 +195,12 @@ local function map_description(id, from_x, from_z, w, h) end -- Create a map from metadata, and assign the ID to the metadata +-- -- meta: A metadata object containing the map ID -- player_x: The X position (in map coordinates) -- player_z: The Z position (in map coordinates) +-- +-- Returns the id of the new map local function map_from_meta(meta, player_x, player_z) local size = meta:get_int("cartographer:size") or 10; local detail = meta:get_int("cartographer:detail") or 1; @@ -208,7 +219,8 @@ local function map_from_meta(meta, player_x, player_z) return id; end --- Show a map to a player from metadata, creating it if possible +-- Show a map to a player from metadata, creating it if necessary +-- -- meta: A metadata object containing the map ID -- player: The player to show the map to local function show_map_meta(meta, player) @@ -221,11 +233,15 @@ local function show_map_meta(meta, player) id = map_from_meta(meta, player_x, player_z); end - show_map_id_formspec(id, pos.x, pos.z, player:get_player_name(), true); + local map = maps.get(id); + if map then + show_map_formspec(map, pos.x, pos.z, player:get_player_name(), true); + end end -- Called when a player sends input to the server from a formspec -- This callback handles player input in the map formspec, for editing markers +-- -- player: The player who sent the input -- name: The formspec name -- fields: A table containing the input @@ -249,13 +265,13 @@ minetest.register_on_player_receive_fields(function(player, name, fields) map:set_marker(player_x, player_z, marker); audio.play_feedback("cartographer_write", player); - show_map_id_formspec(map.id, pos.x, pos.z, player:get_player_name(), data.page); + show_map_formspec(map, pos.x, pos.z, player:get_player_name(), data.page); elseif k == "prev_button" then - show_map_id_formspec(map.id, pos.x, pos.z, player:get_player_name(), data.height_mode, data.page - 1); + show_map_formspec(map, pos.x, pos.z, player:get_player_name(), data.height_mode, data.page - 1); elseif k == "next_button" then - show_map_id_formspec(map.id, pos.x, pos.z, player:get_player_name(), data.height_mode, data.page + 1); + show_map_formspec(map, pos.x, pos.z, player:get_player_name(), data.height_mode, data.page + 1); elseif k == "height_button" then - show_map_id_formspec(map.id, pos.x, pos.z, player:get_player_name(), not data.height_mode, data.page); + show_map_formspec(map, pos.x, pos.z, player:get_player_name(), not data.height_mode, data.page); elseif k == "quit" then player_maps[player:get_player_name()] = nil; end @@ -345,6 +361,13 @@ minetest.register_node("cartographer:map", { end, }); +-- Create an empty map item with the given parameters +-- +-- size: The size of the map +-- detail: The detail level of the map +-- scale: The scaling factor of the map +-- +-- Returns an ItemStack local function create_map_item(size, detail, scale) local map = ItemStack("cartographer:map"); local meta = map:get_meta(); @@ -357,9 +380,10 @@ local function create_map_item(size, detail, scale) end -- Create a copy of the given map +-- -- stack: An itemstack containing a map -- --- Returns an itemstack with the copied map +-- Returns a new ItemStack with the copied map local function copy_map_item(stack) local meta = stack:get_meta(); @@ -392,6 +416,10 @@ local function copy_map_item(stack) return copy; end +-- Resize the given map item +-- +-- meta: A metadata object containing the map data +-- size: The new size local function resize_map_item(meta, size) local old_size = meta:get_int("cartographer:size"); @@ -407,8 +435,8 @@ local function resize_map_item(meta, size) map:resize(size, size); meta:set_string("description", map_description(id, - chunk.from(map.x), chunk.from(map.z), - chunk.from(map.w), chunk.from(map.h))); + chunk.from(map.x), chunk.from(map.z), + chunk.from(map.w), chunk.from(map.h))); end end diff --git a/map_api.lua b/map_api.lua index 6990d03..43cdc55 100644 --- a/map_api.lua +++ b/map_api.lua @@ -1,5 +1,9 @@ +-- Arguments +-- map_data: The map data source +-- chunk: The chunk coordinate conversion API local map_data, chunk = ...; +-- The map 'class' local Map = {}; Map.__index = Map; @@ -7,6 +11,10 @@ for _,loaded_map in ipairs(map_data.maps) do setmetatable(loaded_map, Map); end +-- Resize this map +-- +-- w: The new width +-- h: The new height function Map.resize(self, w, h) if w >= self.w and h >= self.h then self.w = w; @@ -15,6 +23,13 @@ function Map.resize(self, w, h) end end + +-- Fill in a region of this map +-- +-- x: The x position, in map coordinates +-- z: The z position, in map coordinates +-- w: The width, in map coordinates +-- h: The height, in map coordinates function Map.fill_area(self, x, z, w, h) for i = math.max(x, self.x),math.min(x + w - 1, self.x + self.w),1 do for j = math.max(z, self.z),math.min(z + h - 1, self.z + self.h),1 do @@ -23,6 +38,11 @@ function Map.fill_area(self, x, z, w, h) end end +-- Set the marker at the given position +-- +-- x: The x position, in map coordinates +-- z: The z position, in map coordinates +-- marker: The marker ID to set, or nil to unset function Map.set_marker(self, x, z, marker) if x < self.x or x > self.x + self.w or z < self.z or z > self.z + self.h then return; @@ -37,6 +57,12 @@ function Map.set_marker(self, x, z, marker) end end +-- Get the marker at the given position +-- +-- x: The x position, in map coordinates +-- z: The z position, in map coordinates +-- +-- Returns a marker id function Map.get_marker(self, x, z) if x < self.x or x > self.x + self.w or z < self.z or z > self.z + self.h or not self.markers[x] then return nil; @@ -46,6 +72,7 @@ function Map.get_marker(self, x, z) end -- Fill in the local area of a map around a position +-- -- id: A map ID -- x: The x position, in world coordinates -- z: The z position, in world coordinates @@ -59,7 +86,7 @@ function Map.fill_local(self, x, z) end -- Convert a position in world coordinates to the given map's coordinate system --- self: The map to use as reference +-- -- x: The x position, in world coordinates -- z: The z position, in world coordinates -- @@ -72,11 +99,27 @@ function Map.to_coordinates(self, x, z) return math.floor(chunk.to(x) / self.scale + 0.5), math.floor(chunk.to(z) / self.scale + 0.5); end +-- Check if the given position on this map is filled +-- +-- x: The x position, in map coordinates +-- z: The z position, in map coordinates function Map.is_filled(self, x, z) return self.fill[(x - self.x) + ((z - self.z) * self.w)] ~= nil; end +-- The Map API local maps = { + -- Create a new map object with the given parameters + -- + -- x: The x position, in map coordinates + -- z: The z position, in map coordinates + -- w: The width, in map coordinates + -- h: The height, in map coordinates + -- filled: Whether or not the map is pre-filled + -- detail: The detail level + -- scale: The scale factor + -- + -- Returns the new map's id create = function(x, z, w, h, filled, detail, scale) local id = map_data.next_map_id; @@ -103,6 +146,11 @@ local maps = { return id; end, + -- Get the map objwct assigned to the given id + -- + -- id: The map id + -- + -- Returns a map object, or nil if the id is invalid get = function(id) return map_data.maps[id]; end, diff --git a/map_formspec.lua b/map_formspec.lua index d7ef870..bd48ff6 100644 --- a/map_formspec.lua +++ b/map_formspec.lua @@ -1,5 +1,10 @@ -- Arguments -- map_data: The cartographer map data table +-- gui: The GUI API +-- skin: The GUI skin +-- util: API for uncategorized utility methods +-- biomes: The biome API +-- markers: The marker API local map_data, gui, skin, util, biomes, markers = ...; -- Constants diff --git a/marker_api.lua b/marker_api.lua index 05ce59c..519228d 100644 --- a/marker_api.lua +++ b/marker_api.lua @@ -3,6 +3,7 @@ local marker_lookup = {}; -- Format marker ids to allow their use as formspec element ids. -- We're mostly concerned with guarding against the : character because it is -- common for ids and has an alternate meaning in formspecs. +-- -- id: The id to format -- -- Returns the formatted id @@ -11,6 +12,7 @@ local function format_marker_id(id) end -- Find the marker data for a given id +-- -- id: The id to search for -- -- Returns the marker data, or nil if not found @@ -44,6 +46,7 @@ local function get_registered_markers() end -- Register a marker with textures to display +-- -- id: A string containing the id of the marker -- name: A string containing the displayedname of the marker -- textures: A table of texture names. @@ -69,6 +72,7 @@ local function add_marker(id, name, textures) end -- Get the texture name (minus extension) for the given marker and detail level. +-- -- id: A string containing the marker id -- detail: The detail level -- Returns a string with a texture name, or nil if no matching marker was found. diff --git a/material_api.lua b/material_api.lua index c3a855d..76c1a32 100644 --- a/material_api.lua +++ b/material_api.lua @@ -3,6 +3,7 @@ local materials_by_group = {}; return { -- Get the converted material value of the given itemstack + -- -- stack: The itemstack to convert -- -- Returns a table with the material values @@ -34,6 +35,11 @@ return { }; end, + -- Register a material from an item name + -- + -- name: The name of the item + -- material: The material type to set + -- value: The material value register_by_name = function(name, material, value) if materials_by_name[name] then materials_by_name[name][material] = value or 1; @@ -44,6 +50,11 @@ return { end end, + -- Register a material from an item group + -- + -- group: The name of the group + -- material: The material type to set + -- value: The material value register_by_group = function(name, material, value) if materials_by_group[name] then materials_by_group[name][material] = value or 1; diff --git a/mod.conf b/mod.conf index 611eab3..b0dad78 100644 --- a/mod.conf +++ b/mod.conf @@ -1,2 +1,2 @@ name = cartographer -description = A game-agnostic mapmaking API. Needs additional mods to function. +description = A mapmaking API. Needs additional mods to function. diff --git a/scanner.lua b/scanner.lua index 7e8746d..58b3fff 100644 --- a/scanner.lua +++ b/scanner.lua @@ -1,5 +1,6 @@ -- Arguments -- map_data: The cartographer map data table +-- chunk: The chunk coordinate conversion API local map_data, chunk = ...; local scan_queue = {}; @@ -34,6 +35,14 @@ local function register_tile(x, y, biome, height, manual_scan) end end +-- Get the biome and height data for a region from mapgen data +-- +-- min: The min coord of the generated terrain +-- max: The max coord of the generated terrain +-- mmin: The min coord of the region to scan +-- mmax: The max coord of the region to scan +-- +-- Returns the biome and height of the scanned region local function get_mapgen_biome(min, max, mmin, mmax) local UNDERGROUND = minetest.get_biome_id("underground"); local DEFAULT = minetest.get_biome_id("default"); @@ -79,6 +88,12 @@ local function get_mapgen_biome(min, max, mmin, mmax) return biome, avg_height; end +-- Get the biome and height data for a region from existing terrain +-- +-- min: The min coord of the region to scan +-- max: The max coord of the region to scan +-- +-- Returns the biome and height of the scanned region local function get_biome(min, max) local UNDERGROUND = minetest.get_biome_id("underground"); local DEFAULT = minetest.get_biome_id("default"); @@ -122,6 +137,10 @@ local function get_biome(min, max) return biome, avg_height; end +-- Called when new terrain is generated +-- +-- min: The min coord of the generated terrain +-- max: The max coord of the generated terrain local function on_generated(min, max, _) for i = chunk.to(min.x),chunk.to(max.x),1 do for j = chunk.to(min.z),chunk.to(max.z),1 do @@ -144,10 +163,10 @@ local function on_generated(min, max, _) end end end - minetest.register_on_generated(on_generated); -- Is the scan of this position already handled? +-- -- x: The x position, in map coordinates -- y: The y position, in world coordinates -- x: The z position, in map coordinates @@ -166,6 +185,7 @@ end local scanner = {}; -- Queue a tile for manual scanning +-- -- pos: The position as a table, in world coordinates function scanner.queue_region(pos) local converted = { diff --git a/skin_api.lua b/skin_api.lua index f03f5b5..1722ce8 100644 --- a/skin_api.lua +++ b/skin_api.lua @@ -178,6 +178,9 @@ return { radius = 8, }, + -- The texture of the height toggle button when active height_button_texture = "cartographer_height_button", + + -- The texture of the height toggle button when inactive flat_button_texture = "cartographer_flat_button", }; diff --git a/storage.lua b/storage.lua index 7f498b6..c764f89 100644 --- a/storage.lua +++ b/storage.lua @@ -1,20 +1,32 @@ -- Storage and saving local mod_storage = minetest.get_mod_storage(); local map_data = { + -- Scanned map data generated = minetest.deserialize(mod_storage:get_string("map")) or {}, + -- Maps maps = minetest.deserialize(mod_storage:get_string("maps")) or {}, + + -- The next id next_map_id = mod_storage:get_int("next_map_id"), + + -- The version of the map api + api_version = mod_storage:get_int("api_version"), }; if map_data.next_map_id == 0 then map_data.next_map_id = 1; end +if map_data.api_version == 0 then + map_data.api_version = 1; +end + local function save() 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_string("api_version", minetest.serialize(map_data.api_version)); end minetest.register_on_shutdown(save); minetest.register_on_leaveplayer(save);