From c1e0685e9753962613389db5df2f4370df2983ab Mon Sep 17 00:00:00 2001 From: AverageConsumer <35539970+AverageConsumer@users.noreply.github.com> Date: Fri, 7 Aug 2026 20:20:57 +0200 Subject: [PATCH] feat(mods): expose read-only map overview --- src/world/WorldAPI.lua | 20 ++++++++++++++++++ tests/engine/world_map_overview_test.lua | 26 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/engine/world_map_overview_test.lua diff --git a/src/world/WorldAPI.lua b/src/world/WorldAPI.lua index 6adadc51..66aa493c 100644 --- a/src/world/WorldAPI.lua +++ b/src/world/WorldAPI.lua @@ -43,6 +43,26 @@ function WorldAPI:current() facing = p and p.facing } end +-- A compact, read-only view of the active map for minimaps and companion UIs. +-- Rows use " " for blocked terrain, "." for walkable land, "~" for water +-- and "+" for a door or warp. +function WorldAPI:mapOverview() + local ow = self:overworld() + if not ow or not ow.map then return nil, NO_OVERWORLD end + local map, rows = ow.map, {} + for y = 0, map.heightCells - 1 do + local row = {} + for x = 0, map.widthCells - 1 do + row[#row + 1] = map:isWarpTileCell(x, y) and "+" + or map:isWaterCell(x, y) and "~" + or map:isWalkableCell(x, y) and "." or " " + end + rows[#rows + 1] = table.concat(row) + end + return { mapId = map.id, width = map.widthCells, + height = map.heightCells, rows = rows } +end + -- opts.arrive = "fly" | "teleport" picks the arrival FX; anything else -- lands the player without one, like a scripted warp. function WorldAPI:warpTo(mapId, x, y, facing, opts) diff --git a/tests/engine/world_map_overview_test.lua b/tests/engine/world_map_overview_test.lua new file mode 100644 index 00000000..054fea68 --- /dev/null +++ b/tests/engine/world_map_overview_test.lua @@ -0,0 +1,26 @@ +package.path = "./?.lua;./?/init.lua;" .. package.path + +local T = require("tests.harness") +local WorldAPI = require("src.world.WorldAPI") + +local api = WorldAPI.new({ stack = { states = {} } }, "tester") +local overview, err = api:mapOverview() +T.eq(overview, nil, "map overview is unavailable outside the overworld") +T.eq(err, "no overworld", "map overview reports why it is unavailable") + +local map = { id = "TEST_MAP", widthCells = 2, heightCells = 2 } +function map:isWarpTileCell(x, y) return x == 1 and y == 0 end +function map:isWaterCell(x, y) return x == 0 and y == 1 end +function map:isWalkableCell(x, y) return x == 0 and y == 0 end + +api = WorldAPI.new({ stack = { states = { + { isOverworld = true, map = map }, +} } }, "tester") +overview = api:mapOverview() +T.eq(overview.mapId, "TEST_MAP", "map overview identifies the active map") +T.eq(overview.width, 2, "map overview reports its width") +T.eq(overview.height, 2, "map overview reports its height") +T.eq(overview.rows[1], ".+", "walkable land and warps are distinct") +T.eq(overview.rows[2], "~ ", "water and blocked terrain are distinct") + +T.finish("world map overview")