Add set_cell_gid write API to lib-core.maps

Validates layer name against VALID_LAYER_NAMES, bounds-checks the
target cell, auto-allocates the layer table if the caller writes
to a previously-empty layer. Marks the map as dirty for callers
that track in-memory mutations.
This commit is contained in:
Axel Meyer
2026-05-24 00:25:06 +02:00
parent b8705c0ec7
commit 45b1f93363

View File

@@ -12,6 +12,15 @@ local map_registry = {} -- map_id -> Map
local tilemap_registry = {} -- full_tilemap_id -> Tilemap
local current_map_id = nil
-- Internal: resolve and return map by id, or raise.
local function require_map(map_id)
local id = map_id or current_map_id
if not id then error("maps: no current map set") end
local m = map_registry[id]
if not m then error(string.format("maps: no map registered with id '%s'", id)) end
return m
end
-- =====================================================================
-- Packed-u32 GID encoding (Schema-v2)
-- Bit-Layout:
@@ -628,6 +637,49 @@ function M.cell_gid(layer_name, x, y, map_id)
return m.layers[layer_name].tiles[y * m.size.w + x + 1] or 0
end
-- =====================================================================
-- Write APIs (v0.4.0)
-- =====================================================================
-- Helper: gather valid layer names for error messages.
local function get_valid_layer_names_list()
local names = {}
for name, _ in pairs(VALID_LAYER_NAMES) do
table.insert(names, name)
end
table.sort(names)
return names
end
-- Internal: get-or-allocate a layer table for in-place writes.
local function get_or_alloc_layer(map, layer_name)
if not VALID_LAYER_NAMES[layer_name] then
error(string.format("maps: unknown layer '%s' (valid: %s)",
layer_name, table.concat(get_valid_layer_names_list(), ", ")))
end
local layer = map.layers[layer_name]
if not layer then
local cell_count = map.size.w * map.size.h
local tiles = {}
for i = 1, cell_count do tiles[i] = 0 end
layer = { tiles = tiles }
map.layers[layer_name] = layer
end
return layer
end
function M.set_cell_gid(layer_name, x, y, gid, map_id)
local map = require_map(map_id)
if x < 0 or y < 0 or x >= map.size.w or y >= map.size.h then
error(string.format("maps.set_cell_gid: cell (%d,%d) out of bounds for size %dx%d",
x, y, map.size.w, map.size.h))
end
local layer = get_or_alloc_layer(map, layer_name)
local idx = y * map.size.w + x + 1
layer.tiles[idx] = gid
map._dirty = true
end
function M.is_indoor(x, y, map_id)
local id = map_id or current_map_id
if not id then error("maps.is_indoor: no current map") end