From 45b1f9336350f2d887620ab56b039313bf800e46 Mon Sep 17 00:00:00 2001 From: Axel Meyer Date: Sun, 24 May 2026 00:25:06 +0200 Subject: [PATCH] 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. --- init.lua | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/init.lua b/init.lua index 723a844..7d42935 100644 --- a/init.lua +++ b/init.lua @@ -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