From c971a819def1c5cc29dc926f62456c336a1dfa17 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 6 Sep 2012 22:45:19 +0400 Subject: [PATCH] Experimental creation of map blocks in gui/liquids script. --- LUA_API.rst | 4 +++ Lua API.html | 3 ++ library/LuaApi.cpp | 8 +++++ library/include/modules/MapCache.h | 10 ++++++ library/include/modules/Maps.h | 2 ++ library/modules/Maps.cpp | 58 +++++++++++++++++++++++++++++- library/xml | 2 +- scripts/gui/liquids.lua | 41 ++++++++++++++++++++- 8 files changed, 125 insertions(+), 3 deletions(-) diff --git a/LUA_API.rst b/LUA_API.rst index 799f623eb..d13c1e52e 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -995,6 +995,10 @@ Maps module Returns a map block object for given df::coord or x,y,z in local tile coordinates. +* ``dfhack.maps.ensureTileBlock(coords)``, or ``ensureTileBlock(x,y,z)`` + + Like ``getTileBlock``, but if the block is not allocated, try creating it. + * ``dfhack.maps.getRegionBiome(region_coord2d)``, or ``getRegionBiome(x,y)`` Returns the biome info struct for the given global map region. diff --git a/Lua API.html b/Lua API.html index f05ee5511..546d27403 100644 --- a/Lua API.html +++ b/Lua API.html @@ -1207,6 +1207,9 @@ Returns false in case of error.

  • dfhack.maps.getTileBlock(coords), or getTileBlock(x,y,z)

    Returns a map block object for given df::coord or x,y,z in local tile coordinates.

  • +
  • dfhack.maps.ensureTileBlock(coords), or ensureTileBlock(x,y,z)

    +

    Like getTileBlock, but if the block is not allocated, try creating it.

    +
  • dfhack.maps.getRegionBiome(region_coord2d), or getRegionBiome(x,y)

    Returns the biome info struct for the given global map region.

  • diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 1dcb001f1..63838d356 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -935,6 +935,13 @@ static int maps_getTileBlock(lua_State *L) return 1; } +static int maps_ensureTileBlock(lua_State *L) +{ + auto pos = CheckCoordXYZ(L, 1, true); + Lua::PushDFObject(L, Maps::ensureTileBlock(pos)); + return 1; +} + static int maps_getRegionBiome(lua_State *L) { auto pos = CheckCoordXY(L, 1, true); @@ -951,6 +958,7 @@ static int maps_getTileBiomeRgn(lua_State *L) static const luaL_Reg dfhack_maps_funcs[] = { { "isValidTilePos", maps_isValidTilePos }, { "getTileBlock", maps_getTileBlock }, + { "ensureTileBlock", maps_ensureTileBlock }, { "getRegionBiome", maps_getRegionBiome }, { "getTileBiomeRgn", maps_getTileBiomeRgn }, { NULL, NULL } diff --git a/library/include/modules/MapCache.h b/library/include/modules/MapCache.h index 109a20a41..262e70bbf 100644 --- a/library/include/modules/MapCache.h +++ b/library/include/modules/MapCache.h @@ -253,6 +253,8 @@ public: bool is_valid() { return valid; } df::map_block *getRaw() { return block; } + bool Allocate(); + MapCache *getParent() { return parent; } private: @@ -262,6 +264,8 @@ private: MapCache *parent; df::map_block *block; + void init(); + int biomeIndexAt(df::coord2d p); bool valid; @@ -347,6 +351,12 @@ class DFHACK_EXPORT MapCache return BlockAt(df::coord(coord.x>>4,coord.y>>4,coord.z)); } + bool ensureBlockAt(df::coord coord) + { + Block *b = BlockAtTile(coord); + return b ? b->Allocate() : false; + } + df::tiletype baseTiletypeAt (DFCoord tilecoord) { Block *b = BlockAtTile(tilecoord); diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 984cf16cf..869b21580 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -241,9 +241,11 @@ inline bool isValidTilePos(df::coord pos) { return isValidTilePos(pos.x, pos.y, */ extern DFHACK_EXPORT df::map_block * getBlock (int32_t blockx, int32_t blocky, int32_t blockz); extern DFHACK_EXPORT df::map_block * getTileBlock (int32_t x, int32_t y, int32_t z); +extern DFHACK_EXPORT df::map_block * ensureTileBlock (int32_t x, int32_t y, int32_t z); inline df::map_block * getBlock (df::coord pos) { return getBlock(pos.x, pos.y, pos.z); } inline df::map_block * getTileBlock (df::coord pos) { return getTileBlock(pos.x, pos.y, pos.z); } +inline df::map_block * ensureTileBlock (df::coord pos) { return ensureTileBlock(pos.x, pos.y, pos.z); } extern DFHACK_EXPORT df::tiletype *getTileType(int32_t x, int32_t y, int32_t z); extern DFHACK_EXPORT df::tile_designation *getTileDesignation(int32_t x, int32_t y, int32_t z); diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 305f1296d..d0401164a 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -157,6 +157,39 @@ df::map_block *Maps::getTileBlock (int32_t x, int32_t y, int32_t z) return world->map.block_index[x >> 4][y >> 4][z]; } +df::map_block *Maps::ensureTileBlock (int32_t x, int32_t y, int32_t z) +{ + if (!isValidTilePos(x,y,z)) + return NULL; + + auto column = world->map.block_index[x >> 4][y >> 4]; + auto &slot = column[z]; + if (slot) + return slot; + + // Find another block below + int z2 = z; + while (z2 >= 0 && !column[z2]) z2--; + if (z2 < 0) + return NULL; + + slot = new df::map_block(); + slot->region_pos = column[z2]->region_pos; + slot->map_pos = column[z2]->map_pos; + slot->map_pos.z = z; + + // Assume sky + df::tile_designation dsgn(0); + dsgn.bits.light = true; + dsgn.bits.outside = true; + + for (int tx = 0; tx < 16; tx++) + for (int ty = 0; ty < 16; ty++) + slot->designation[tx][ty] = dsgn; + + return slot; +} + df::tiletype *Maps::getTileType(int32_t x, int32_t y, int32_t z) { df::map_block *block = getTileBlock(x,y,z); @@ -513,8 +546,14 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent) valid = false; bcoord = _bcoord; block = Maps::getBlock(bcoord); - item_counts = NULL; tags = NULL; + + init(); +} + +void MapExtras::Block::init() +{ + item_counts = NULL; tiles = NULL; basemats = NULL; @@ -537,6 +576,23 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent) } } +bool MapExtras::Block::Allocate() +{ + if (block) + return true; + + block = Maps::ensureTileBlock(bcoord.x*16, bcoord.y*16, bcoord.z); + if (!block) + return false; + + delete item_counts; + delete tiles; + delete basemats; + init(); + + return true; +} + MapExtras::Block::~Block() { delete[] item_counts; diff --git a/library/xml b/library/xml index df8178a98..a914f3b75 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit df8178a989373ec7868d9195d82ae5f85145ef81 +Subproject commit a914f3b7558335d53c0ac93f6e7267906a33cd29 diff --git a/scripts/gui/liquids.lua b/scripts/gui/liquids.lua index 869cac908..89f08b7cf 100644 --- a/scripts/gui/liquids.lua +++ b/scripts/gui/liquids.lua @@ -3,6 +3,7 @@ local utils = require 'utils' local gui = require 'gui' local guidm = require 'gui.dwarfmode' +local dlg = require 'gui.dialogs' local liquids = require('plugins.liquids') @@ -199,6 +200,42 @@ function LiquidsUI:onRenderBody(dc) dc:string("Enter", COLOR_LIGHTGREEN):string(": Paint") end +function ensure_blocks(cursor, size, cb) + local cx,cy,cz = pos2xyz(cursor) + local all = true + for x=1,size.x or 1,16 do + for y=1,size.y or 1,16 do + for z=1,size.z do + if not dfhack.maps.getTileBlock(cx+x-1, cy+y-1, cz+z-1) then + all = false + end + end + end + end + if all then + cb() + return + end + dlg.showYesNoPrompt( + 'Instantiate Blocks', + 'Not all map blocks are allocated - instantiate?\n\nWarning: new untested feature.', + COLOR_YELLOW, + function() + for x=1,size.x or 1,16 do + for y=1,size.y or 1,16 do + for z=1,size.z do + dfhack.maps.ensureTileBlock(cx+x-1, cy+y-1, cz+z-1) + end + end + end + cb() + end, + function() + cb() + end + ) +end + function LiquidsUI:onInput(keys) local paint = self.paint:get() local liquid = paint.liquid @@ -239,13 +276,15 @@ function LiquidsUI:onInput(keys) else guidm.clearSelection() end - liquids.paint( + local cb = curry( + liquids.paint, cursor, self.brush:get().tag, self.paint:get().tag, self.amount, size, self.set:get().tag, self.flow:get().tag, self.permaflow:get().tag ) + ensure_blocks(cursor, size, cb) elseif self:propagateMoveKeys(keys) then return elseif keys.D_LOOK_ARENA_WATER then