From 1cf96883490050a2ad89a61b0518764f57df427c Mon Sep 17 00:00:00 2001 From: Tachytaenius Date: Wed, 12 Oct 2022 21:10:22 +0100 Subject: [PATCH 01/18] Implement/change/expose constructions findAtTile & insert (not building) --- docs/Lua API.rst | 7 +++++++ library/LuaApi.cpp | 9 +++++++++ library/modules/Constructions.cpp | 15 +++++++++++---- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index c2b84f0f0..75196e7b9 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1906,6 +1906,13 @@ Constructions module coordinates, designates it for removal, or instantly cancels the planned one. Returns *true, was_only_planned* if removed; or *false* if none found. +* ``dfhack.constructions.findAtTile(pos)``, or ``findAtTile(x,y,z)`` + + Returns the construction at the given position, or ``nil`` if there isn't one. + +* ``dfhack.constructions.insert(construction)`` + + Properly inserts the given construction into the game. Kitchen module -------------- diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 3a83f7aef..463cf3fcc 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2276,8 +2276,17 @@ static int constructions_designateRemove(lua_State *L) return 2; } +static int constructions_findAtTile(lua_State *L) +{ + auto pos = CheckCoordXYZ(L, 1, true); + Lua::PushDFObject(L, Constructions::findAtTile(pos)); + return 1; +} + static const luaL_Reg dfhack_constructions_funcs[] = { { "designateRemove", constructions_designateRemove }, + { "findAtTile", constructions_findAtTile }, + WRAPM(Constructions, insert), { NULL, NULL } }; diff --git a/library/modules/Constructions.cpp b/library/modules/Constructions.cpp index 5fc632500..407e95f76 100644 --- a/library/modules/Constructions.cpp +++ b/library/modules/Constructions.cpp @@ -54,11 +54,18 @@ using df::global::world; df::construction * Constructions::findAtTile(df::coord pos) { - for (auto it = world->constructions.begin(); it != world->constructions.end(); ++it) { - if ((*it)->pos == pos) - return *it; + int index = binsearch_index(world->constructions, pos); + if (index == -1) { + return NULL; } - return NULL; + return world->constructions[index]; +} + +bool Constructions::insert(df::construction * constr) +{ + bool toInsert; + insert_into_vector(world->constructions, &df::construction::pos, constr, &toInsert); + return toInsert; } bool Constructions::designateNew(df::coord pos, df::construction_type type, From b78af724031723b7436ae122e0fb22e498769a5c Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 13:31:46 -0700 Subject: [PATCH 02/18] record built constructions in blueprint --- docs/plugins/blueprint.rst | 18 ++-- library/include/TileTypes.h | 2 +- plugins/blueprint.cpp | 163 ++++++++++++++++++++++++------------ plugins/lua/blueprint.lua | 1 + 4 files changed, 122 insertions(+), 62 deletions(-) diff --git a/docs/plugins/blueprint.rst b/docs/plugins/blueprint.rst index b999c0e99..bde5bb77e 100644 --- a/docs/plugins/blueprint.rst +++ b/docs/plugins/blueprint.rst @@ -7,11 +7,11 @@ blueprint With ``blueprint``, you can export the structure of a portion of your fortress in a blueprint file that you (or anyone else) can later play back with -`quickfort`. +`gui/quickfort`. Blueprints are ``.csv`` or ``.xlsx`` files created in the ``blueprints`` subdirectory of your DF folder. The map area to turn into a blueprint is either -selected interactively with the ``blueprint gui`` command or, if the GUI is not +selected interactively with the ``gui/blueprint`` command or, if the GUI is not used, starts at the active cursor location and extends right and down for the requested width and height. @@ -27,16 +27,16 @@ Examples -------- ``blueprint gui`` - Runs `gui/blueprint`, the interactive frontend, where all configuration for - a ``blueprint`` command can be set visually and interactively. + Runs `gui/blueprint`, the GUI frontend, where all configuration for a + ``blueprint`` command can be set visually and interactively. ``blueprint 30 40 bedrooms`` Generates blueprints for an area 30 tiles wide by 40 tiles tall, starting from the active cursor on the current z-level. Blueprints are written to ``bedrooms.csv`` in the ``blueprints`` directory. ``blueprint 30 40 bedrooms dig --cursor 108,100,150`` Generates only the ``#dig`` blueprint in the ``bedrooms.csv`` file, and - the start of the blueprint area is set to a specific value instead of using - the in-game cursor position. + the start of the blueprint area is set to a specific coordinate instead of + using the in-game cursor position. Positional parameters --------------------- @@ -66,8 +66,12 @@ phases; just separate them with a space. Generate quickfort ``#dig`` blueprints for digging natural stone. ``carve`` Generate quickfort ``#dig`` blueprints for smoothing and carving. +``construct`` + Generate quickfort ``#build`` blueprints for constructions (e.g. flooring + and walls). ``build`` - Generate quickfort ``#build`` blueprints for constructions and buildings. + Generate quickfort ``#build`` blueprints for buildings (including + furniture). ``place`` Generate quickfort ``#place`` blueprints for placing stockpiles. ``zone`` diff --git a/library/include/TileTypes.h b/library/include/TileTypes.h index 5dbc81d0d..8e5c82cb2 100644 --- a/library/include/TileTypes.h +++ b/library/include/TileTypes.h @@ -116,7 +116,7 @@ namespace DFHack //This is a static string, overwritten with every call! //Support values > 2 even though they should never happen. //Copy string if it will be used. - inline char * getStr() const + inline const char * getStr() const { static char str[16]; diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 20aa1aa99..3dd912d28 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -85,11 +85,12 @@ struct blueprint_options { bool auto_phase = false; // if not autodetecting, which phases to output - bool dig = false; + bool dig = false; bool carve = false; + bool construct = false; bool build = false; bool place = false; - bool zone = false; + bool zone = false; bool query = false; static struct_identity _identity; @@ -110,6 +111,7 @@ static const struct_field_info blueprint_options_fields[] = { { struct_field_info::PRIMITIVE, "auto_phase", offsetof(blueprint_options, auto_phase), &df::identity_traits::identity, 0, 0 }, { struct_field_info::PRIMITIVE, "dig", offsetof(blueprint_options, dig), &df::identity_traits::identity, 0, 0 }, { struct_field_info::PRIMITIVE, "carve", offsetof(blueprint_options, carve), &df::identity_traits::identity, 0, 0 }, + { struct_field_info::PRIMITIVE, "construct", offsetof(blueprint_options, construct), &df::identity_traits::identity, 0, 0 }, { struct_field_info::PRIMITIVE, "build", offsetof(blueprint_options, build), &df::identity_traits::identity, 0, 0 }, { struct_field_info::PRIMITIVE, "place", offsetof(blueprint_options, place), &df::identity_traits::identity, 0, 0 }, { struct_field_info::PRIMITIVE, "zone", offsetof(blueprint_options, zone), &df::identity_traits::identity, 0, 0 }, @@ -332,6 +334,108 @@ static const char * get_tile_carve(const df::coord &pos, const tile_context &tc) return NULL; } +static const char * get_construction_str(df::building *b) { + df::building_constructionst *cons = + virtual_cast(b); + if (!cons) + return "~"; + + switch (cons->type) { + case construction_type::Fortification: return "CF"; + case construction_type::Wall: return "Cw"; + case construction_type::Floor: return "Cf"; + case construction_type::UpStair: return "Cu"; + case construction_type::DownStair: return "Cd"; + case construction_type::UpDownStair: return "Cx"; + case construction_type::Ramp: return "Cr"; + case construction_type::TrackN: return "trackN"; + case construction_type::TrackS: return "trackS"; + case construction_type::TrackE: return "trackE"; + case construction_type::TrackW: return "trackW"; + case construction_type::TrackNS: return "trackNS"; + case construction_type::TrackNE: return "trackNE"; + case construction_type::TrackNW: return "trackNW"; + case construction_type::TrackSE: return "trackSE"; + case construction_type::TrackSW: return "trackSW"; + case construction_type::TrackEW: return "trackEW"; + case construction_type::TrackNSE: return "trackNSE"; + case construction_type::TrackNSW: return "trackNSW"; + case construction_type::TrackNEW: return "trackNEW"; + case construction_type::TrackSEW: return "trackSEW"; + case construction_type::TrackNSEW: return "trackNSEW"; + case construction_type::TrackRampN: return "trackrampN"; + case construction_type::TrackRampS: return "trackrampS"; + case construction_type::TrackRampE: return "trackrampE"; + case construction_type::TrackRampW: return "trackrampW"; + case construction_type::TrackRampNS: return "trackrampNS"; + case construction_type::TrackRampNE: return "trackrampNE"; + case construction_type::TrackRampNW: return "trackrampNW"; + case construction_type::TrackRampSE: return "trackrampSE"; + case construction_type::TrackRampSW: return "trackrampSW"; + case construction_type::TrackRampEW: return "trackrampEW"; + case construction_type::TrackRampNSE: return "trackrampNSE"; + case construction_type::TrackRampNSW: return "trackrampNSW"; + case construction_type::TrackRampNEW: return "trackrampNEW"; + case construction_type::TrackRampSEW: return "trackrampSEW"; + case construction_type::TrackRampNSEW: return "trackrampNSEW"; + case construction_type::NONE: + default: + return "~"; + } +} + +static const char * get_constructed_track_str(df::tiletype *tt, + const char * base) { + TileDirection dir = tileDirection(*tt); + if (!dir.whole) + return "~"; + + std::ostringstream str; + str << base; + if (dir.north) str << "N"; + if (dir.south) str << "S"; + if (dir.east) str << "E"; + if (dir.west) str << "W"; + + return cache(str); +} + +static const char * get_constructed_floor_str(df::tiletype *tt) { + if (tileSpecial(*tt) != df::tiletype_special::TRACK) + return "Cf"; + return get_constructed_track_str(tt, "track"); +} + +static const char * get_constructed_ramp_str(df::tiletype *tt) { + if (tileSpecial(*tt) != df::tiletype_special::TRACK) + return "Cr"; + return get_constructed_track_str(tt, "trackramp"); +} + +static const char * get_tile_construct(const df::coord &pos, + const tile_context &ctx) { + if (ctx.b && ctx.b->getType() == building_type::Construction) + return get_construction_str(ctx.b); + + df::tiletype *tt = Maps::getTileType(pos); + if (!tt || tileMaterial(*tt) != df::tiletype_material::CONSTRUCTION) + return NULL; + + switch (tileShape(*tt)) { + case tiletype_shape::WALL: return "Cw"; + case tiletype_shape::FLOOR: return get_constructed_floor_str(tt); + case tiletype_shape::RAMP: return get_constructed_ramp_str(tt); + case tiletype_shape::FORTIFICATION: return "CF"; + case tiletype_shape::STAIR_UP: return "Cu"; + case tiletype_shape::STAIR_DOWN: return "Cd"; + case tiletype_shape::STAIR_UPDOWN: return "Cx"; + default: + return "~"; + } + + return NULL; +} + static pair get_building_size(const df::building *b) { return pair(b->x2 - b->x1 + 1, b->y2 - b->y1 + 1); } @@ -461,56 +565,6 @@ static const char * get_furnace_str(df::building *b) { } } -static const char * get_construction_str(df::building *b) { - df::building_constructionst *cons = - virtual_cast(b); - if (!cons) - return "~"; - - switch (cons->type) { - case construction_type::Fortification: return "CF"; - case construction_type::Wall: return "Cw"; - case construction_type::Floor: return "Cf"; - case construction_type::UpStair: return "Cu"; - case construction_type::DownStair: return "Cd"; - case construction_type::UpDownStair: return "Cx"; - case construction_type::Ramp: return "Cr"; - case construction_type::TrackN: return "trackN"; - case construction_type::TrackS: return "trackS"; - case construction_type::TrackE: return "trackE"; - case construction_type::TrackW: return "trackW"; - case construction_type::TrackNS: return "trackNS"; - case construction_type::TrackNE: return "trackNE"; - case construction_type::TrackNW: return "trackNW"; - case construction_type::TrackSE: return "trackSE"; - case construction_type::TrackSW: return "trackSW"; - case construction_type::TrackEW: return "trackEW"; - case construction_type::TrackNSE: return "trackNSE"; - case construction_type::TrackNSW: return "trackNSW"; - case construction_type::TrackNEW: return "trackNEW"; - case construction_type::TrackSEW: return "trackSEW"; - case construction_type::TrackNSEW: return "trackNSEW"; - case construction_type::TrackRampN: return "trackrampN"; - case construction_type::TrackRampS: return "trackrampS"; - case construction_type::TrackRampE: return "trackrampE"; - case construction_type::TrackRampW: return "trackrampW"; - case construction_type::TrackRampNS: return "trackrampNS"; - case construction_type::TrackRampNE: return "trackrampNE"; - case construction_type::TrackRampNW: return "trackrampNW"; - case construction_type::TrackRampSE: return "trackrampSE"; - case construction_type::TrackRampSW: return "trackrampSW"; - case construction_type::TrackRampEW: return "trackrampEW"; - case construction_type::TrackRampNSE: return "trackrampNSE"; - case construction_type::TrackRampNSW: return "trackrampNSW"; - case construction_type::TrackRampNEW: return "trackrampNEW"; - case construction_type::TrackRampSEW: return "trackrampSEW"; - case construction_type::TrackRampNSEW: return "trackrampNSEW"; - case construction_type::NONE: - default: - return "~"; - } -} - static const char * get_trap_str(df::building *b) { df::building_trapst *trap = virtual_cast(b); if (!trap) @@ -622,6 +676,7 @@ static const char * get_build_keys(const df::coord &pos, bool at_center = static_cast(pos.x) == ctx.b->centerx && static_cast(pos.y) == ctx.b->centery; + // building_type::Construction is handled by the construction phase switch(ctx.b->getType()) { case building_type::Armorstand: return "a"; @@ -666,8 +721,6 @@ static const char * get_build_keys(const df::coord &pos, return "y"; case building_type::WindowGem: return "Y"; - case building_type::Construction: - return get_construction_str(ctx.b); case building_type::Shop: return do_block_building(ctx, "z", at_center); case building_type::AnimalTrap: @@ -1132,6 +1185,8 @@ static bool do_transform(color_ostream &out, smooth_get_tile_fn); add_processor(processors, opts, "dig", "carve", opts.carve, opts.engrave ? get_tile_carve : get_tile_carve_minimal); + add_processor(processors, opts, "build", "construct", opts.construct, + get_tile_construct, ensure_building); add_processor(processors, opts, "build", "build", opts.build, get_tile_build, ensure_building); add_processor(processors, opts, "place", "place", opts.place, diff --git a/plugins/lua/blueprint.lua b/plugins/lua/blueprint.lua index 5c73be7c0..564962448 100644 --- a/plugins/lua/blueprint.lua +++ b/plugins/lua/blueprint.lua @@ -6,6 +6,7 @@ local utils = require('utils') local valid_phase_list = { 'dig', 'carve', + 'construct', 'build', 'place', 'zone', From ded5f483d664fc9f804a7f3ca40f04032fcb7793 Mon Sep 17 00:00:00 2001 From: Tachytaenius Date: Wed, 12 Oct 2022 21:32:27 +0100 Subject: [PATCH 03/18] Fix issues in construction module --- docs/Lua API.rst | 3 ++- library/LuaApi.cpp | 2 +- library/include/modules/Constructions.h | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 75196e7b9..5cfd8cf09 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1912,7 +1912,8 @@ Constructions module * ``dfhack.constructions.insert(construction)`` - Properly inserts the given construction into the game. + Properly inserts the given construction into the game. Returns false and fails to + insert if there was already a construction at the position. Kitchen module -------------- diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 463cf3fcc..4a97a0502 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2264,6 +2264,7 @@ static const luaL_Reg dfhack_buildings_funcs[] = { static const LuaWrapper::FunctionReg dfhack_constructions_module[] = { WRAPM(Constructions, designateNew), + WRAPM(Constructions, insert), { NULL, NULL } }; @@ -2286,7 +2287,6 @@ static int constructions_findAtTile(lua_State *L) static const luaL_Reg dfhack_constructions_funcs[] = { { "designateRemove", constructions_designateRemove }, { "findAtTile", constructions_findAtTile }, - WRAPM(Constructions, insert), { NULL, NULL } }; diff --git a/library/include/modules/Constructions.h b/library/include/modules/Constructions.h index c7a1c048b..b152381c4 100644 --- a/library/include/modules/Constructions.h +++ b/library/include/modules/Constructions.h @@ -45,6 +45,8 @@ namespace Constructions DFHACK_EXPORT df::construction * findAtTile(df::coord pos); +DFHACK_EXPORT bool insert(df::construction * constr); + DFHACK_EXPORT bool designateNew(df::coord pos, df::construction_type type, df::item_type item = df::item_type::NONE, int mat_index = -1); From 754f1a2598167722c16e162026953e1ef10e5433 Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 13:33:29 -0700 Subject: [PATCH 04/18] update changelog --- docs/changelog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index f9b7accc5..37f3a1dd1 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -38,6 +38,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Fixes ## Misc Improvements +- `blueprint`: new ``--smooth`` option for recording all smoothed floors and walls instead of just the ones that require smoothing for later carving +- `blueprint`: record built constructions in blueprints - `ls`: indent tag listings and wrap them in the right column for better readability - `ls`: new ``--exclude`` option for hiding matched scripts from the output. this can be especially useful for modders who don't want their mod scripts to be included in ``ls`` output. - `digtype`: new ``-z`` option for digtype to restrict designations to the current z-level and down From aa83aa4e7161bf349dfb71131bdbe5d94108a01f Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 14:51:36 -0700 Subject: [PATCH 05/18] handle construct phase in ecosystem tests --- .../test/ecosystem/golden/transform-build.csv | 40 ++++++------- .../ecosystem/golden/transform-construct.csv | 28 +++++++++ .../test/ecosystem/in/buildings-build.csv | 60 +++++++++---------- .../test/ecosystem/in/buildings-construct.csv | 21 +++++++ .../test/ecosystem/in/transform-build.csv | 13 ---- .../test/ecosystem/in/transform-construct.csv | 23 +++++++ test/quickfort/ecosystem.lua | 1 + 7 files changed, 123 insertions(+), 63 deletions(-) create mode 100644 data/blueprints/library/test/ecosystem/golden/transform-construct.csv create mode 100644 data/blueprints/library/test/ecosystem/in/buildings-construct.csv create mode 100644 data/blueprints/library/test/ecosystem/in/transform-construct.csv diff --git a/data/blueprints/library/test/ecosystem/golden/transform-build.csv b/data/blueprints/library/test/ecosystem/golden/transform-build.csv index 2cab6e804..74434544a 100644 --- a/data/blueprints/library/test/ecosystem/golden/transform-build.csv +++ b/data/blueprints/library/test/ecosystem/golden/transform-build.csv @@ -1,28 +1,28 @@ #build label(build) start(14;14) -,trackNS,trackE,,trackW,trackS,trackN,,gs(1x2),ga(2x1),,gx(1x2),gw(1x2),,gw(1x2),gx(1x2),gd(2x1),,gs(1x2),,trackN,trackS,trackE,,trackW,trackNS -trackEW,,trackSE,,trackSW,trackNE,trackNW,,,gd(2x1),,,,,,,ga(2x1),,,,trackNE,trackNW,trackSE,,trackSW,,trackEW -trackS,trackSE,,,trackNSE,trackNSW,trackEW,,Mrsssqq(2x1),,,Msh,,,,,Msk,Mrsqq(2x1),,,trackEW,trackNSE,trackNSW,,,trackSW,trackS +,~,~,,~,~,~,,gs(1x2),ga(2x1),,gx(1x2),gw(1x2),,gw(1x2),gx(1x2),gd(2x1),,gs(1x2),,~,~,~,,~,~ +~,,~,,~,~,~,,,gd(2x1),,,,,,,ga(2x1),,,,~,~,~,,~,,~ +~,~,,,~,~,~,,Mrsssqq(2x1),,,Msh,,,,,Msk,Mrsqq(2x1),,,~,~,~,,,~,~ ,,,,,,,,CSdddaaaa,,Msk,,Mw,,Mw,,,Msh,CSddddaaaa -trackN,trackNE,trackSEW,,,trackSEW,trackNEW,,CSa,,Mrss(1x2),Mw,,,,Mw,Mrss(1x2),,CSa,,trackNEW,trackSEW,,,trackSEW,trackNW,trackN -trackE,trackSW,trackNEW,,trackNSE,,trackNSEW,,,Msm,,,Mhs(1x2),,Mhs(1x2),,,Msm,,,trackNSEW,,trackNSW,,trackNEW,trackSE,trackW -trackW,trackNW,trackNS,,trackNSW,trackNSEW,,,Msu,,Mws,,,,,,Mws,,Msu,,,trackNSEW,trackNSE,,trackNS,trackNE,trackE +~,~,~,,,~,~,,CSa,,Mrss(1x2),Mw,,,,Mw,Mrss(1x2),,CSa,,~,~,,,~,~,~ +~,~,~,,~,,~,,,Msm,,,Mhs(1x2),,Mhs(1x2),,,Msm,,,~,,~,,~,~,~ +~,~,~,,~,~,,,Msu,,Mws,,,,,,Mws,,Msu,,,~,~,,~,~,~ ,,,,,,,,,Mws,,Mh(2x1),,,Mh(2x1),,,Mws gs(2x1),,Mrqq(1x2),CSddaaaa,CSa,,Msh,,,,,,,,,,,,,,,Msk,CSa,CSddaaaa,Mrqq(1x2),gs(2x1) -gw(1x2),gx(1x2),,,,Msk,,Mw,,,trackrampNW,trackrampNS,trackrampN,,trackrampN,trackrampNS,trackrampNE,,,Mw,,,Msh,,,gx(1x2),gw(1x2) -,,,Msm,Mrs(2x1),,Mw,,,trackrampNW,,trackrampNSE,trackrampNSW,,trackrampNSE,trackrampNSW,,trackrampNE,,,Mw,Mrsss(2x1),,Msm -gd(2x1),,Msu,,Mws,,,Mhs(1x2),,trackrampEW,trackrampSEW,,trackrampNSEW,,trackrampNSEW,,trackrampSEW,trackrampEW,,Mhs(1x2),,,Mws,,Msu,ga(2x1) -ga(2x1),,,Mws,,Mh(2x1),,,,trackrampW,trackrampNEW,trackrampNSEW,,,,trackrampNSEW,trackrampNEW,trackrampE,,,Mh(2x1),,,Mws,,gd(2x1) +gw(1x2),gx(1x2),,,,Msk,,Mw,,,~,~,~,,~,~,~,,,Mw,,,Msh,,,gx(1x2),gw(1x2) +,,,Msm,Mrs(2x1),,Mw,,,~,,~,~,,~,~,,~,,,Mw,Mrsss(2x1),,Msm +gd(2x1),,Msu,,Mws,,,Mhs(1x2),,~,~,,~,,~,,~,~,,Mhs(1x2),,,Mws,,Msu,ga(2x1) +ga(2x1),,,Mws,,Mh(2x1),,,,~,~,~,,,,~,~,~,,,Mh(2x1),,,Mws,,gd(2x1) -ga(2x1),,,Mws,,Mh(2x1),,Mhs(1x2),,trackrampW,trackrampSEW,trackrampNSEW,,,,trackrampNSEW,trackrampSEW,trackrampE,,Mhs(1x2),Mh(2x1),,,Mws,,gd(2x1) -gd(2x1),,,,Mws,,,,,trackrampEW,trackrampNEW,,trackrampNSEW,,trackrampNSEW,,trackrampNEW,trackrampEW,,,,,Mws,,,ga(2x1) -gx(1x2),gw(1x2),Msm,,Mrs(2x1),,Mw,,,trackrampSW,,trackrampNSE,trackrampNSW,,trackrampNSE,trackrampNSW,,trackrampSE,,,Mw,Mrsss(2x1),,,Msm,gw(1x2),gx(1x2) -,,Mrssqq(1x2),Msu,,Msk,,Mw,,,trackrampSW,trackrampNS,trackrampS,,trackrampS,trackrampNS,trackrampSE,,,Mw,,,Msh,Msu,Mrssqq(1x2) +ga(2x1),,,Mws,,Mh(2x1),,Mhs(1x2),,~,~,~,,,,~,~,~,,Mhs(1x2),Mh(2x1),,,Mws,,gd(2x1) +gd(2x1),,,,Mws,,,,,~,~,,~,,~,,~,~,,,,,Mws,,,ga(2x1) +gx(1x2),gw(1x2),Msm,,Mrs(2x1),,Mw,,,~,,~,~,,~,~,,~,,,Mw,Mrsss(2x1),,,Msm,gw(1x2),gx(1x2) +,,Mrssqq(1x2),Msu,,Msk,,Mw,,,~,~,~,,~,~,~,,,Mw,,,Msh,Msu,Mrssqq(1x2) gs(2x1),,,CSdaaaa,CSa,,Msh,,,,,,,,,,,,,,,Msk,CSa,CSdaaaa,,gs(2x1) ,,,,,,,,,Mws,,Mh(2x1),,,Mh(2x1),,,Mws -trackW,trackSW,trackNS,,trackNSW,trackNSEW,,,,,Mws,,Mhs(1x2),,Mhs(1x2),,Mws,,,,,trackNSEW,trackNSE,,trackNS,trackSE,trackE -trackE,trackNW,trackSEW,,trackNSE,,trackNSEW,,Msm,,Mr(1x2),,,,,,Mr(1x2),,Msm,,trackNSEW,,trackNSW,,trackSEW,trackNE,trackW -trackS,trackSE,trackNEW,,,trackNEW,trackSEW,,CSa,Msu,,Mw,,,,Mw,,Msu,CSa,,trackSEW,trackNEW,,,trackNEW,trackSW,trackS +~,~,~,,~,~,,,,,Mws,,Mhs(1x2),,Mhs(1x2),,Mws,,,,,~,~,,~,~,~ +~,~,~,,~,,~,,Msm,,Mr(1x2),,,,,,Mr(1x2),,Msm,,~,,~,,~,~,~ +~,~,~,,,~,~,,CSa,Msu,,Mw,,,,Mw,,Msu,CSa,,~,~,,,~,~,~ ,,,,,,,,CSdddaaaa,,Msk,,Mw,,Mw,,,Msh,CSddddaaaa -trackN,trackNE,,,trackNSE,trackNSW,trackEW,,Mrsssqq(2x1),,,Msh,,,,,Msk,Mrsqq(2x1),,,trackEW,trackNSE,trackNSW,,,trackNW,trackN -trackEW,,trackNE,,trackNW,trackSE,trackSW,,gs(1x2),gd(2x1),,gw(1x2),gx(1x2),,gx(1x2),gw(1x2),ga(2x1),,gs(1x2),,trackSE,trackSW,trackNE,,trackNW,,trackEW -,trackNS,trackE,,trackW,trackN,trackS,,,ga(2x1),,,,,,,gd(2x1),,,,trackS,trackN,trackE,,trackW,trackNS +~,~,,,~,~,~,,Mrsssqq(2x1),,,Msh,,,,,Msk,Mrsqq(2x1),,,~,~,~,,,~,~ +~,,~,,~,~,~,,gs(1x2),gd(2x1),,gw(1x2),gx(1x2),,gx(1x2),gw(1x2),ga(2x1),,gs(1x2),,~,~,~,,~,,~ +,~,~,,~,~,~,,,ga(2x1),,,,,,,gd(2x1),,,,~,~,~,,~,~ diff --git a/data/blueprints/library/test/ecosystem/golden/transform-construct.csv b/data/blueprints/library/test/ecosystem/golden/transform-construct.csv new file mode 100644 index 000000000..9620c96c1 --- /dev/null +++ b/data/blueprints/library/test/ecosystem/golden/transform-construct.csv @@ -0,0 +1,28 @@ +#build label(construct) start(14;14) +,trackNS,trackE,,trackW,trackS,trackN,,,,,,,,,,,,,,trackN,trackS,trackE,,trackW,trackNS +trackEW,,trackSE,,trackSW,trackNE,trackNW,,,,,,,,,,,,,,trackNE,trackNW,trackSE,,trackSW,,trackEW +trackS,trackSE,,,trackNSE,trackNSW,trackEW,,,,,,,,,,,,,,trackEW,trackNSE,trackNSW,,,trackSW,trackS + +trackN,trackNE,trackSEW,,,trackSEW,trackNEW,,,,,,,,,,,,,,trackNEW,trackSEW,,,trackSEW,trackNW,trackN +trackE,trackSW,trackNEW,,trackNSE,,trackNSEW,,,,,,,,,,,,,,trackNSEW,,trackNSW,,trackNEW,trackSE,trackW +trackW,trackNW,trackNS,,trackNSW,trackNSEW,,,,,,,,,,,,,,,,trackNSEW,trackNSE,,trackNS,trackNE,trackE + + +,,,,,,,,,,trackrampNW,trackrampNS,trackrampN,,trackrampN,trackrampNS,trackrampNE +,,,,,,,,,trackrampNW,,trackrampNSE,trackrampNSW,,trackrampNSE,trackrampNSW,,trackrampNE +,,,,,,,,,trackrampEW,trackrampSEW,,trackrampNSEW,,trackrampNSEW,,trackrampSEW,trackrampEW +,,,,,,,,,trackrampW,trackrampNEW,trackrampNSEW,,,,trackrampNSEW,trackrampNEW,trackrampE + +,,,,,,,,,trackrampW,trackrampSEW,trackrampNSEW,,,,trackrampNSEW,trackrampSEW,trackrampE +,,,,,,,,,trackrampEW,trackrampNEW,,trackrampNSEW,,trackrampNSEW,,trackrampNEW,trackrampEW +,,,,,,,,,trackrampSW,,trackrampNSE,trackrampNSW,,trackrampNSE,trackrampNSW,,trackrampSE +,,,,,,,,,,trackrampSW,trackrampNS,trackrampS,,trackrampS,trackrampNS,trackrampSE + + +trackW,trackSW,trackNS,,trackNSW,trackNSEW,,,,,,,,,,,,,,,,trackNSEW,trackNSE,,trackNS,trackSE,trackE +trackE,trackNW,trackSEW,,trackNSE,,trackNSEW,,,,,,,,,,,,,,trackNSEW,,trackNSW,,trackSEW,trackNE,trackW +trackS,trackSE,trackNEW,,,trackNEW,trackSEW,,,,,,,,,,,,,,trackSEW,trackNEW,,,trackNEW,trackSW,trackS + +trackN,trackNE,,,trackNSE,trackNSW,trackEW,,,,,,,,,,,,,,trackEW,trackNSE,trackNSW,,,trackNW,trackN +trackEW,,trackNE,,trackNW,trackSE,trackSW,,,,,,,,,,,,,,trackSE,trackSW,trackNE,,trackNW,,trackEW +,trackNS,trackE,,trackW,trackN,trackS,,,,,,,,,,,,,,trackS,trackN,trackE,,trackW,trackNS diff --git a/data/blueprints/library/test/ecosystem/in/buildings-build.csv b/data/blueprints/library/test/ecosystem/in/buildings-build.csv index 89e066e80..f48457c0a 100644 --- a/data/blueprints/library/test/ecosystem/in/buildings-build.csv +++ b/data/blueprints/library/test/ecosystem/in/buildings-build.csv @@ -1,33 +1,33 @@ #build label(build) -a,Mg,,CS,trackN -b,Mh(1x1),S,CSa,trackS,,,,,,Mw,,,wm,,,wp -c,Mhs(1x1),m,CSaa,trackE,,,,,,,,,,,,,,,,,D -n,Mv,v,CSaaa,trackW,,Msu -,Mr(1x1),j,CSaaaa,trackNS,,,,,,Mws,,,wu,,,ew -d,Mrq(1x1),A,CSd,trackNE,,,Msk -,Mrqq(1x1),R,CSda,trackNW -l,Mrqqq(1x1),N,CSdaa,trackSE,,Msm,,,,we,,,wn,,,es,,,,,k -x,Mrqqqq(1x1),~h,CSdaaa,trackSW -H,Mrs(1x1),~a,CSdaaaa,trackEW,,,Msh -W,Mrsq(1x1),~c,CSdd,trackNSE,,,,,,wq,,,wr,,,el -G,Mrsqq(1x1),F,CSdda,trackNSW -B,Mrsqqq(1x1),o(1x1),CSddaa,trackNEW,,,,,,,,,,,,,,,,,ws -~b,Mrsqqqq(1x1),Cw,CSddaaa,trackSEW,,,,,,wM,,,wt,,,eg -f,Mrss(1x1),Cf,CSddaaaa,trackNSEW -h,Mrssq(1x1),Cr,CSddd,trackrampN -r,Mrssqq(1x1),Cu,CSddda,trackrampS,,,,,,wo,,,wl,,,ea,,,,gx(1x2),gx(1x2) -s,Mrssqqq(1x1),Cd,CSdddaa,trackrampE -~s,Mrssqqqq(1x1),Cx,CSdddaaa,trackrampW,,,,,,,,,,,,,,gd(2x1),,gs(2x1),,ga(2x1) -t,Mrsss(1x1),CF,CSdddaaaa,trackrampNS,,,,,,wk,,,ww,,,ek,,gd(2x1),,gs(2x1),,ga(2x1) -gs(1x1),Mrsssq(1x1),,CSdddd,trackrampNE,,,,,,,,,,,,,,,,gw(1x2),gw(1x2) -ga(1x1),Mrsssqq(1x1),,CSdddda,trackrampNW -gd(1x1),Mrsssqqq(1x1),,CSddddaa,trackrampSE,,,,,,wb,,,wz,,,en -gw(1x1),Mrsssqqqq(1x1),,CSddddaaa,trackrampSW,,,,,,,,,,,,,,Mh(2x1),,Mh(2x1),,Mhs(1x2),Mhs(1x2) -gx(1x1),,,CSddddaaaa,trackrampEW,,,,,,,,,,,,,,Mh(2x1),,Mh(2x1) -,,,Ts,trackrampNSE,,,,,,wc,,,wh,,,ib,,Mr(1x2),Mr(1x2),Mrs(2x1),,Mhs(1x2),Mhs(1x2) -y,,,Tw,trackrampNSW,,,,,,,,,,,,,,,,Mrs(2x1) -Y,,,Tl,trackrampNEW,,,,,,,,,,,,,,Mr(1x2),Mr(1x2),Mrsq(2x1),,Mrsq(2x1) -,,,Tp,trackrampSEW,,,,,,wf,,,wy,,,ic,,,,Mrsssqqqq(2x1),,Mrsssqqqq(2x1) -,,,Tc,trackrampNSEW +a,Mg,,CS +b,Mh(1x1),S,CSa,,,,,,Mw,,,wm,,,wp +c,Mhs(1x1),m,CSaa,,,,,,,,,,,,,,,,,D +n,Mv,v,CSaaa,,Msu +,Mr(1x1),j,CSaaaa,,,,,,Mws,,,wu,,,ew +d,Mrq(1x1),A,CSd,,,Msk +,Mrqq(1x1),R,CSda +l,Mrqqq(1x1),N,CSdaa,,Msm,,,,we,,,wn,,,es,,,,,k +x,Mrqqqq(1x1),~h,CSdaaa +H,Mrs(1x1),~a,CSdaaaa,,,Msh +W,Mrsq(1x1),~c,CSdd,,,,,,wq,,,wr,,,el +G,Mrsqq(1x1),F,CSdda +B,Mrsqqq(1x1),o(1x1),CSddaa,,,,,,,,,,,,,,,,,ws +~,~b,Mrsqqqq(1x1),CSddaaa,,,,,,wM,,,wt,,,eg +~,f,Mrss(1x1),CSddaaaa +~,h,Mrssq(1x1),CSddd +~,r,Mrssqq(1x1),CSddda,,,,,,wo,,,wl,,,ea,,,,gx(1x2),gx(1x2) +~,s,Mrssqqq(1x1),CSdddaa +~,~s,Mrssqqqq(1x1),CSdddaaa,,,,,,,,,,,,,,gd(2x1),,gs(2x1),,ga(2x1) +~,t,Mrsss(1x1),CSdddaaaa,,,,,,wk,,,ww,,,ek,,gd(2x1),,gs(2x1),,ga(2x1) +gs(1x1),Mrsssq(1x1),,CSdddd,,,,,,,,,,,,,,,,gw(1x2),gw(1x2) +ga(1x1),Mrsssqq(1x1),,CSdddda +gd(1x1),Mrsssqqq(1x1),,CSddddaa,,,,,,wb,,,wz,,,en +gw(1x1),Mrsssqqqq(1x1),,CSddddaaa,,,,,,,,,,,,,,Mh(2x1),,Mh(2x1),,Mhs(1x2),Mhs(1x2) +gx(1x1),,,CSddddaaaa,,,,,,,,,,,,,,Mh(2x1),,Mh(2x1) +,,,Ts,,,,,,wc,,,wh,,,ib,,Mr(1x2),Mr(1x2),Mrs(2x1),,Mhs(1x2),Mhs(1x2) +y,,,Tw,,,,,,,,,,,,,,,,Mrs(2x1) +Y,,,Tl,,,,,,,,,,,,,,Mr(1x2),Mr(1x2),Mrsq(2x1),,Mrsq(2x1) +,,,Tp,,,,,,wf,,,wy,,,ic,,,,Mrsssqqqq(2x1),,Mrsssqqqq(2x1) +,,,Tc ,,,TS ,,,,,,,,,,wv,,,wd,,,wj,,,wS diff --git a/data/blueprints/library/test/ecosystem/in/buildings-construct.csv b/data/blueprints/library/test/ecosystem/in/buildings-construct.csv new file mode 100644 index 000000000..e7e1d12bb --- /dev/null +++ b/data/blueprints/library/test/ecosystem/in/buildings-construct.csv @@ -0,0 +1,21 @@ +#build label(construct) + + + + + + + + + + + + + +Cw +Cf +Cr +Cu +Cd +Cx +CF diff --git a/data/blueprints/library/test/ecosystem/in/transform-build.csv b/data/blueprints/library/test/ecosystem/in/transform-build.csv index fdc2e18ce..7907220e7 100644 --- a/data/blueprints/library/test/ecosystem/in/transform-build.csv +++ b/data/blueprints/library/test/ecosystem/in/transform-build.csv @@ -7,21 +7,8 @@ Mw,,,Msh,CSddddaaaa Mhs(1x2),,,Msm ,,Mws,,Msu Mh(2x1),,,Mws -#build label(outer) hidden() -trackN,trackS,trackE,,trackW,trackNS -trackNE,trackNW,trackSE,,trackSW -trackEW,trackNSE,trackNSW - -trackNEW,trackSEW -trackNSEW -#build label(inner) hidden() -trackrampN,trackrampNS,trackrampNE -trackrampNSE,trackrampNSW -trackrampNSEW #meta label(chunk) hidden() /big shift(1 -13) -/outer shift(7 -13) -/inner shift(1 -4) #meta label(build) /chunk /chunk transform(cw) diff --git a/data/blueprints/library/test/ecosystem/in/transform-construct.csv b/data/blueprints/library/test/ecosystem/in/transform-construct.csv new file mode 100644 index 000000000..95717afa8 --- /dev/null +++ b/data/blueprints/library/test/ecosystem/in/transform-construct.csv @@ -0,0 +1,23 @@ +#build label(outer) hidden() +trackN,trackS,trackE,,trackW,trackNS +trackNE,trackNW,trackSE,,trackSW +trackEW,trackNSE,trackNSW + +trackNEW,trackSEW +trackNSEW +#build label(inner) hidden() +trackrampN,trackrampNS,trackrampNE +trackrampNSE,trackrampNSW +trackrampNSEW +#meta label(chunk) hidden() +/outer shift(7 -13) +/inner shift(1 -4) +#meta label(construct) +/chunk +/chunk transform(cw) +/chunk transform(cw cw) +/chunk transform(ccw) +/chunk transform(fliph) +/chunk transform(flipv) +/chunk transform(cw flipv) +/chunk transform(ccw flipv) diff --git a/test/quickfort/ecosystem.lua b/test/quickfort/ecosystem.lua index d55bc2389..b59b8909d 100644 --- a/test/quickfort/ecosystem.lua +++ b/test/quickfort/ecosystem.lua @@ -327,6 +327,7 @@ function test.end_to_end() do_dig_phase(phases.dig, area, spec) if phases.smooth then do_dig_phase(phases.smooth, area, spec) end if phases.carve then do_dig_phase(phases.carve, area, spec) end + if phases.construct then do_phase(phases.construct, area, spec) end if phases.build then do_phase(phases.build, area, spec) end if phases.place then do_phase(phases.place, area, spec) end if phases.zone then do_phase(phases.zone, area, spec) end From 80d993e7343a2b4fd6d714bedcdfd895811963cc Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 16:01:54 -0700 Subject: [PATCH 06/18] split rooms phase from query and record names --- docs/plugins/blueprint.rst | 5 +- plugins/blueprint.cpp | 93 +++++++++++++++++++++++++++--------- plugins/lua/blueprint.lua | 1 + test/quickfort/ecosystem.lua | 1 + 4 files changed, 76 insertions(+), 24 deletions(-) diff --git a/docs/plugins/blueprint.rst b/docs/plugins/blueprint.rst index bde5bb77e..262a3bd5b 100644 --- a/docs/plugins/blueprint.rst +++ b/docs/plugins/blueprint.rst @@ -77,7 +77,10 @@ phases; just separate them with a space. ``zone`` Generate quickfort ``#zone`` blueprints for designating zones. ``query`` - Generate quickfort ``#query`` blueprints for configuring rooms. + Generate quickfort ``#query`` blueprints for configuring stockpiles and + naming buildings. +``rooms`` + Generate quickfort ``#query`` blueprints for defining rooms. If no phases are specified, phases are autodetected. For example, a ``#place`` blueprint will be created only if there are stockpiles in the blueprint area. diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 3dd912d28..bb4d03d32 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -92,6 +93,7 @@ struct blueprint_options { bool place = false; bool zone = false; bool query = false; + bool rooms = false; static struct_identity _identity; }; @@ -116,6 +118,7 @@ static const struct_field_info blueprint_options_fields[] = { { struct_field_info::PRIMITIVE, "place", offsetof(blueprint_options, place), &df::identity_traits::identity, 0, 0 }, { struct_field_info::PRIMITIVE, "zone", offsetof(blueprint_options, zone), &df::identity_traits::identity, 0, 0 }, { struct_field_info::PRIMITIVE, "query", offsetof(blueprint_options, query), &df::identity_traits::identity, 0, 0 }, + { struct_field_info::PRIMITIVE, "rooms", offsetof(blueprint_options, rooms), &df::identity_traits::identity, 0, 0 }, { struct_field_info::END } }; struct_identity blueprint_options::_identity(sizeof(blueprint_options), &df::allocator_fn, NULL, "blueprint_options", NULL, blueprint_options_fields); @@ -134,11 +137,36 @@ DFhackCExport command_result plugin_shutdown(color_ostream &) { return CR_OK; } +struct blueprint_processor; struct tile_context { + blueprint_processor *processor; bool pretty = false; df::building* b = NULL; }; +typedef vector bp_row; // index is x coordinate +typedef map bp_area; // key is y coordinate +typedef map bp_volume; // key is z coordinate + +typedef const char * (get_tile_fn)(const df::coord &pos, + const tile_context &ctx); +typedef void (init_ctx_fn)(const df::coord &pos, tile_context &ctx); + +struct blueprint_processor { + bp_volume mapdata; + const string mode; + const string phase; + const bool force_create; + get_tile_fn * const get_tile; + init_ctx_fn * const init_ctx; + std::set seen; + blueprint_processor(const string &mode, const string &phase, + bool force_create, get_tile_fn *get_tile, + init_ctx_fn *init_ctx) + : mode(mode), phase(phase), force_create(force_create), + get_tile(get_tile), init_ctx(init_ctx) { } +}; + // global engravings cache, cleared when the string cache is cleared struct PosHash { size_t operator()(const df::coord &c) const { @@ -974,7 +1002,45 @@ static const char * get_tile_zone(const df::coord &pos, return add_expansion_syntax(zone, get_zone_keys(zone)); } -static const char * get_tile_query(const df::coord &, const tile_context &ctx) { +static string csv_sanitize(const string &str) { + static const std::regex pattern("\""); + static const string replacement("\"\""); + + return std::regex_replace(str, pattern, replacement); +} + +static const char * get_tile_query(const df::coord &pos, + const tile_context &ctx) { + string bld_name, zone_name; + auto & seen = ctx.processor->seen; + + if (ctx.b && !seen.count(ctx.b)) { + bld_name = ctx.b->name; + seen.emplace(ctx.b); + } + + vector civzones; + if (Buildings::findCivzonesAt(&civzones, pos)) { + auto civzone = civzones.back(); + if (!seen.count(civzone)) { + zone_name = civzone->name; + seen.emplace(civzone); + } + } + + if (!bld_name.size() && !zone_name.size()) + return NULL; + + std::ostringstream str; + if (bld_name.size()) + str << "{givename name=\"" << csv_sanitize(bld_name) << "\"}"; + if (zone_name.size()) + str << "{namezone name=\"" << csv_sanitize(zone_name) << "\"}"; + + return cache(str); +} + +static const char * get_tile_rooms(const df::coord &, const tile_context &ctx) { if (!ctx.b || !ctx.b->is_room) return NULL; return "r+"; @@ -1027,28 +1093,6 @@ static bool get_filename(string &fname, return true; } -typedef vector bp_row; // index is x coordinate -typedef map bp_area; // key is y coordinate -typedef map bp_volume; // key is z coordinate - -typedef const char * (get_tile_fn)(const df::coord &pos, - const tile_context &ctx); -typedef void (init_ctx_fn)(const df::coord &pos, tile_context &ctx); - -struct blueprint_processor { - bp_volume mapdata; - const string mode; - const string phase; - const bool force_create; - get_tile_fn * const get_tile; - init_ctx_fn * const init_ctx; - blueprint_processor(const string &mode, const string &phase, - bool force_create, get_tile_fn *get_tile, - init_ctx_fn *init_ctx) - : mode(mode), phase(phase), force_create(force_create), - get_tile(get_tile), init_ctx(init_ctx) { } -}; - static void write_minimal(ofstream &ofile, const blueprint_options &opts, const bp_volume &mapdata) { if (mapdata.begin() == mapdata.end()) @@ -1194,6 +1238,8 @@ static bool do_transform(color_ostream &out, add_processor(processors, opts, "zone", "zone", opts.zone, get_tile_zone); add_processor(processors, opts, "query", "query", opts.query, get_tile_query, ensure_building); + add_processor(processors, opts, "query", "rooms", opts.rooms, + get_tile_rooms, ensure_building); if (processors.empty()) { out.printerr("no phases requested! nothing to do!\n"); @@ -1212,6 +1258,7 @@ static bool do_transform(color_ostream &out, tile_context ctx; ctx.pretty = pretty; for (blueprint_processor &processor : processors) { + ctx.processor = &processor; if (processor.init_ctx) processor.init_ctx(pos, ctx); const char *tile_str = processor.get_tile(pos, ctx); diff --git a/plugins/lua/blueprint.lua b/plugins/lua/blueprint.lua index 564962448..6fe869d3b 100644 --- a/plugins/lua/blueprint.lua +++ b/plugins/lua/blueprint.lua @@ -11,6 +11,7 @@ local valid_phase_list = { 'place', 'zone', 'query', + 'rooms', } valid_phases = utils.invert(valid_phase_list) diff --git a/test/quickfort/ecosystem.lua b/test/quickfort/ecosystem.lua index b59b8909d..27dddc5d5 100644 --- a/test/quickfort/ecosystem.lua +++ b/test/quickfort/ecosystem.lua @@ -332,6 +332,7 @@ function test.end_to_end() if phases.place then do_phase(phases.place, area, spec) end if phases.zone then do_phase(phases.zone, area, spec) end if phases.query then do_phase(phases.query, area, spec) end + if phases.rooms then do_phase(phases.rooms, area, spec) end -- run any extra commands, if defined by the blueprint spec if spec.extra_fn then From b03911945d26e63b0f576f121429b5f79624ca12 Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 16:03:03 -0700 Subject: [PATCH 07/18] update changelog --- docs/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index 37f3a1dd1..70e144f3f 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -40,6 +40,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Misc Improvements - `blueprint`: new ``--smooth`` option for recording all smoothed floors and walls instead of just the ones that require smoothing for later carving - `blueprint`: record built constructions in blueprints +- `blueprint`: record stockpile/building/zone names in blueprints - `ls`: indent tag listings and wrap them in the right column for better readability - `ls`: new ``--exclude`` option for hiding matched scripts from the output. this can be especially useful for modders who don't want their mod scripts to be included in ``ls`` output. - `digtype`: new ``-z`` option for digtype to restrict designations to the current z-level and down From f411ba76ba9c161df755cbc03c726c19520fee32 Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 16:33:06 -0700 Subject: [PATCH 08/18] record accurate room sizes in blueprints --- docs/changelog.txt | 1 + plugins/blueprint.cpp | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 70e144f3f..71d843764 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -41,6 +41,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `blueprint`: new ``--smooth`` option for recording all smoothed floors and walls instead of just the ones that require smoothing for later carving - `blueprint`: record built constructions in blueprints - `blueprint`: record stockpile/building/zone names in blueprints +- `blueprint`: record room sizes in blueprints - `ls`: indent tag listings and wrap them in the right column for better readability - `ls`: new ``--exclude`` option for hiding matched scripts from the output. this can be especially useful for modders who don't want their mod scripts to be included in ``ls`` output. - `digtype`: new ``-z`` option for digtype to restrict designations to the current z-level and down diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index bb4d03d32..2f42e2798 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -1043,7 +1043,29 @@ static const char * get_tile_query(const df::coord &pos, static const char * get_tile_rooms(const df::coord &, const tile_context &ctx) { if (!ctx.b || !ctx.b->is_room) return NULL; - return "r+"; + + // get the maximum distance from the center of the building + df::building_extents &room = ctx.b->room; + int32_t x1 = room.x; + int32_t x2 = room.x + room.width - 1; + int32_t y1 = room.y; + int32_t y2 = room.y + room.height - 1; + + int32_t dimx = std::max(ctx.b->centerx - x1, x2 - ctx.b->centerx); + int32_t dimy = std::max(ctx.b->centery - y1, y2 - ctx.b->centery); + int32_t max_dim = std::max(dimx, dimy); + + switch (max_dim) { + case 0: return "r---&"; + case 1: return "r--&"; + case 2: return "r-&"; + case 3: return "r&"; + case 4: return "r+&"; + } + + std::ostringstream str; + str << "r{+ " << (max_dim - 3) << "}&"; + return cache(str); } static bool create_output_dir(color_ostream &out, From c52138b16874e59665dd75261132ca27167d0194 Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 17:42:36 -0700 Subject: [PATCH 09/18] generate meta blueprints --- docs/changelog.txt | 1 + docs/plugins/blueprint.rst | 10 ++++-- plugins/blueprint.cpp | 70 ++++++++++++++++++++++++++++++++++-- plugins/lua/blueprint.lua | 17 +++++++++ test/plugins/blueprint.lua | 6 ++++ test/quickfort/ecosystem.lua | 2 +- 6 files changed, 100 insertions(+), 6 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 71d843764..c2173d5e1 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -42,6 +42,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `blueprint`: record built constructions in blueprints - `blueprint`: record stockpile/building/zone names in blueprints - `blueprint`: record room sizes in blueprints +- `blueprint`: generate meta blueprints to reduce the number of blueprints you have to apply - `ls`: indent tag listings and wrap them in the right column for better readability - `ls`: new ``--exclude`` option for hiding matched scripts from the output. this can be especially useful for modders who don't want their mod scripts to be included in ``ls`` output. - `digtype`: new ``-z`` option for digtype to restrict designations to the current z-level and down diff --git a/docs/plugins/blueprint.rst b/docs/plugins/blueprint.rst index 262a3bd5b..3a5e5a0c5 100644 --- a/docs/plugins/blueprint.rst +++ b/docs/plugins/blueprint.rst @@ -99,8 +99,14 @@ Options Select the output format of the generated files. See the `Output formats`_ section below for options. If not specified, the output format defaults to "minimal", which will produce a small, fast ``.csv`` file. -``-h``, ``--help`` - Show command help text. +``--nometa`` + `Meta blueprints ` let you apply all blueprints that can be + replayed at the same time (without unpausing the game) with a single + command. This usually reduces the number of `quickfort` commands you need to + run to rebuild your fort from about 6 to 2 or 3. If you would rather just + have the low-level blueprints, this flag will prevent meta blueprints from + being generated and any low-level blueprints from being + `hidden ` from the ``quickfort list`` command. ``-s``, ``--playback-start ,,`` Specify the column and row offsets (relative to the upper-left corner of the blueprint, which is ``1,1``) where the player should put the cursor when the diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 2f42e2798..b08f4d074 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -14,6 +14,7 @@ #include "DataDefs.h" #include "DataFuncs.h" #include "DataIdentity.h" +#include "Debug.h" #include "LuaTools.h" #include "PluginManager.h" #include "TileTypes.h" @@ -47,6 +48,10 @@ using namespace DFHack; DFHACK_PLUGIN("blueprint"); REQUIRE_GLOBAL(world); +namespace DFHack { + DBG_DECLARE(blueprint,log); +} + struct blueprint_options { // whether to display help bool help = false; @@ -59,6 +64,9 @@ struct blueprint_options { // for it. string format; + // whether to skip generating meta blueprints + bool nometa = false; + // offset and comment to write in the quickfort start() modeline marker // if not set, coordinates are set to 0 and the comment will be empty df::coord2d playback_start = df::coord2d(0, 0); @@ -101,6 +109,7 @@ static const struct_field_info blueprint_options_fields[] = { { struct_field_info::PRIMITIVE, "help", offsetof(blueprint_options, help), &df::identity_traits::identity, 0, 0 }, { struct_field_info::SUBSTRUCT, "start", offsetof(blueprint_options, start), &df::coord::_identity, 0, 0 }, { struct_field_info::PRIMITIVE, "format", offsetof(blueprint_options, format), df::identity_traits::get(), 0, 0 }, + { struct_field_info::PRIMITIVE, "nometa", offsetof(blueprint_options, nometa), &df::identity_traits::identity, 0, 0 }, { struct_field_info::SUBSTRUCT, "playback_start", offsetof(blueprint_options, playback_start), &df::coord2d::_identity, 0, 0 }, { struct_field_info::PRIMITIVE, "playback_start_comment", offsetof(blueprint_options, playback_start_comment), df::identity_traits::get(), 0, 0 }, { struct_field_info::PRIMITIVE, "split_strategy", offsetof(blueprint_options, split_strategy), df::identity_traits::get(), 0, 0 }, @@ -1115,6 +1124,32 @@ static bool get_filename(string &fname, return true; } +// returns true if we could interface with lua and could verify that the given +// phase is a meta phase +static bool is_meta_phase(color_ostream &out, + blueprint_options opts, // copy because we can't const + const string &phase) { + auto L = Lua::Core::State; + Lua::StackUnwinder top(L); + + if (!lua_checkstack(L, 3) || + !Lua::PushModulePublic( + out, L, "plugins.blueprint", "is_meta_phase")) { + out.printerr("Failed to load blueprint Lua code\n"); + return false; + } + + Lua::Push(L, &opts); + Lua::Push(L, phase); + + if (!Lua::SafeCall(out, L, 2, 1)) { + out.printerr("Failed Lua call to is_meta_phase\n"); + return false; + } + + return lua_toboolean(L, -1); +} + static void write_minimal(ofstream &ofile, const blueprint_options &opts, const bp_volume &mapdata) { if (mapdata.begin() == mapdata.end()) @@ -1171,8 +1206,8 @@ static void write_pretty(ofstream &ofile, const blueprint_options &opts, } } -static string get_modeline(const blueprint_options &opts, const string &mode, - const string &phase) { +static string get_modeline(color_ostream &out, const blueprint_options &opts, + const string &mode, const string &phase) { std::ostringstream modeline; modeline << "#" << mode << " label(" << phase << ")"; if (opts.playback_start.x > 0) { @@ -1183,6 +1218,8 @@ static string get_modeline(const blueprint_options &opts, const string &mode, } modeline << ")"; } + if (is_meta_phase(out, opts, phase)) + modeline << " hidden()"; return modeline.str(); } @@ -1199,7 +1236,7 @@ static bool write_blueprint(color_ostream &out, output_files[fname] = new ofstream(fname, ofstream::trunc); ofstream &ofile = *output_files[fname]; - ofile << get_modeline(opts, processor.mode, processor.phase) << endl; + ofile << get_modeline(out, opts, processor.mode, processor.phase) << endl; if (pretty) write_pretty(ofile, opts, processor.mapdata); @@ -1209,6 +1246,27 @@ static bool write_blueprint(color_ostream &out, return true; } +static void write_meta_blueprint(color_ostream &out, + std::map &output_files, + const blueprint_options &opts, + const std::vector & meta_phases) { + string fname; + get_filename(fname, out, opts, meta_phases.front()); + ofstream &ofile = *output_files[fname]; + + ofile << "#meta label("; + for (string phase : meta_phases) { + ofile << phase; + if (phase != meta_phases.back()) + ofile << "_"; + } + ofile << ")" << endl; + + for (string phase : meta_phases) { + ofile << "/" << phase << endl; + } +} + static void ensure_building(const df::coord &pos, tile_context &ctx) { if (ctx.b) return; @@ -1301,12 +1359,18 @@ static bool do_transform(color_ostream &out, } std::map output_files; + std::vector meta_phases; for (blueprint_processor &processor : processors) { if (processor.mapdata.empty() && !processor.force_create) continue; + if (is_meta_phase(out, opts, processor.phase)) + meta_phases.push_back(processor.phase); if (!write_blueprint(out, output_files, opts, processor, pretty)) break; } + if (meta_phases.size()) { + write_meta_blueprint(out, output_files, opts, meta_phases); + } for (auto &it : output_files) { filenames.push_back(it.first); diff --git a/plugins/lua/blueprint.lua b/plugins/lua/blueprint.lua index 6fe869d3b..e3b36d9fe 100644 --- a/plugins/lua/blueprint.lua +++ b/plugins/lua/blueprint.lua @@ -15,6 +15,14 @@ local valid_phase_list = { } valid_phases = utils.invert(valid_phase_list) +local meta_phase_list = { + 'build', + 'place', + 'zone', + 'query', +} +meta_phases = utils.invert(meta_phase_list) + local valid_formats_list = { 'minimal', 'pretty', @@ -123,6 +131,7 @@ local function process_args(opts, args) {'f', 'format', hasArg=true, handler=function(optarg) parse_format(opts, optarg) end}, {'h', 'help', handler=function() opts.help = true end}, + {nil, 'nometa', handler=function() opts.nometa = true end}, {'s', 'playback-start', hasArg=true, handler=function(optarg) parse_start(opts, optarg) end}, {nil, 'smooth', handler=function() opts.smooth = true end}, @@ -185,6 +194,11 @@ function parse_commandline(opts, ...) parse_positionals(opts, positionals, depth and 4 or 3) end +function is_meta_phase(opts, phase) + -- this is called directly by cpp so ensure we return a boolean, not nil + return not opts.nometa and meta_phases[phase] or false +end + -- returns the name of the output file for the given context function get_filename(opts, phase) local fullname = 'blueprints/' .. opts.name @@ -197,6 +211,9 @@ function get_filename(opts, phase) fullname = fullname .. basename end if opts.split_strategy == 'phase' then + if is_meta_phase(opts, phase) then + phase = 'meta' + end return ('%s-%s.csv'):format(fullname, phase) end -- no splitting diff --git a/test/plugins/blueprint.lua b/test/plugins/blueprint.lua index a19d519b8..73ec33eda 100644 --- a/test/plugins/blueprint.lua +++ b/test/plugins/blueprint.lua @@ -20,6 +20,12 @@ function test.parse_gui_commandline() b.parse_gui_commandline(opts, {'-h'}) expect.table_eq({help=true, format='minimal', split_strategy='none'}, opts) + opts = {} + b.parse_gui_commandline(opts, {'--nometa'}) + expect.table_eq({auto_phase=true, format='minimal', split_strategy='none', + name='blueprint', nometa=true}, + opts) + opts = {} mock.patch(dfhack.maps, 'isValidTilePos', mock.func(true), function() diff --git a/test/quickfort/ecosystem.lua b/test/quickfort/ecosystem.lua index 27dddc5d5..05f531e2e 100644 --- a/test/quickfort/ecosystem.lua +++ b/test/quickfort/ecosystem.lua @@ -244,7 +244,7 @@ end local function run_blueprint(basename, spec, pos) local args = {tostring(spec.width), tostring(spec.height), tostring(-spec.depth), output_dir..basename, - get_cursor_arg(pos), '-tphase'} + get_cursor_arg(pos), '-tphase', '--nometa'} local playback_start_arg = get_playback_start_arg(spec.start) if playback_start_arg then table.insert(args, playback_start_arg) From b4986aad97f73c6f961874d6543001af1f9e08cf Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 12 Oct 2022 17:49:37 -0700 Subject: [PATCH 10/18] create meta bp only if it will reduce the bp count --- plugins/blueprint.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index b08f4d074..361aaa1ca 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -1285,7 +1285,7 @@ static void add_processor(vector &processors, static bool do_transform(color_ostream &out, const df::coord &start, const df::coord &end, - const blueprint_options &opts, + blueprint_options &opts, vector &filenames) { // empty map instances to pass to emplace() below static const bp_area EMPTY_AREA; @@ -1358,17 +1358,24 @@ static bool do_transform(color_ostream &out, } } - std::map output_files; std::vector meta_phases; for (blueprint_processor &processor : processors) { if (processor.mapdata.empty() && !processor.force_create) continue; if (is_meta_phase(out, opts, processor.phase)) meta_phases.push_back(processor.phase); + } + if (meta_phases.size() <= 1) + opts.nometa = true; + + std::map output_files; + for (blueprint_processor &processor : processors) { + if (processor.mapdata.empty() && !processor.force_create) + continue; if (!write_blueprint(out, output_files, opts, processor, pretty)) break; } - if (meta_phases.size()) { + if (!opts.nometa) { write_meta_blueprint(out, output_files, opts, meta_phases); } From e2953a840e3f4cdf89015d167d1f2d2c4bef2d15 Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Thu, 13 Oct 2022 07:33:58 +0000 Subject: [PATCH 11/18] Auto-update submodules scripts: master --- scripts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts b/scripts index 937cf27f9..c297cb6ea 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 937cf27f9b41301be6df0fe1d75d77b6f089f688 +Subproject commit c297cb6ea702213bfc22e2cdef47e580cff84f2b From 0b9b05e488e319fe7993464e3416dcfa8fad7525 Mon Sep 17 00:00:00 2001 From: Tachytaenius Date: Thu, 13 Oct 2022 20:51:01 +0100 Subject: [PATCH 12/18] Add changelog entries --- docs/changelog.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index f9b7accc5..4068edb36 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -44,13 +44,17 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - UX: List widgets now have mouse-interactive scrollbars - UX: You can now hold down the mouse button on a scrollbar to make it scroll multiple times. - UX: You can now drag the scrollbar to scroll to a specific spot +- Constructions module: ``findAtTile`` now uses a binary search intead of a linear search. ## Documentation ## API +- Constructions module: added ``insert()`` to insert constructions into the game's sorted list. ## Lua - ``widgets.Scrollbar``: new scrollbar widget that can be paired with an associated scrollable widget. Integrated with ``widgets.Label`` and ``widgets.List``. +- ``dfhack.constructions.findAtTile()``: exposed preexisting function to Lua. +- ``dfhack.constructions.insert()``: exposed new function to Lua. # 0.47.05-r7 From c238b7c651fe9a4ee1aa48dfebc37e2f21e1712c Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Fri, 14 Oct 2022 03:03:32 +0000 Subject: [PATCH 13/18] Auto-update submodules scripts: master --- scripts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts b/scripts index c297cb6ea..6f0d7ea22 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit c297cb6ea702213bfc22e2cdef47e580cff84f2b +Subproject commit 6f0d7ea22edcd68a1716d843e3ff439a75f23c35 From b1bf80e58588a3244980ec83ee0aac5755d356cf Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 14 Oct 2022 11:58:43 -0700 Subject: [PATCH 14/18] support "group" file split strategy for blueprint --- ...ntum-build.csv => gui_quantum-2-build.csv} | 0 ...ntum-place.csv => gui_quantum-3-place.csv} | 0 .../ecosystem/golden/gui_quantum-4-query.csv | 6 +++ .../golden/{meta-dig.csv => meta-1-dig.csv} | 0 .../{tracks-carve.csv => tracks-2-carve.csv} | 0 ...{transform-dig.csv => transform-1-dig.csv} | 0 ...onstruct.csv => transform-2-construct.csv} | 0 ...nsform-build.csv => transform-3-build.csv} | 0 .../in/{basic-dig.csv => basic-1-dig.csv} | 0 .../in/{basic-carve.csv => basic-2-carve.csv} | 0 .../in/{basic-build.csv => basic-3-build.csv} | 0 .../in/{basic-place.csv => basic-4-place.csv} | 0 .../in/{basic-zone.csv => basic-5-zone.csv} | 0 ...{buildings-dig.csv => buildings-1-dig.csv} | 0 ...onstruct.csv => buildings-2-construct.csv} | 0 ...ldings-build.csv => buildings-3-build.csv} | 0 ...tions-dig.csv => fortifications-1-dig.csv} | 0 ...smooth.csv => fortifications-2-smooth.csv} | 0 ...s-carve.csv => fortifications-3-carve.csv} | 0 ...ntum-build.csv => gui_quantum-2-build.csv} | 0 ...ntum-place.csv => gui_quantum-3-place.csv} | 0 .../test/ecosystem/in/gui_quantum-4-query.csv | 1 + .../in/{meta-dig.csv => meta-1-dig.csv} | 0 ...piles-place.csv => stockpiles-2-place.csv} | 0 .../in/{tracks-dig.csv => tracks-1-dig.csv} | 0 .../{tracks-carve.csv => tracks-2-carve.csv} | 0 .../{tracks-build.csv => tracks-3-build.csv} | 0 ...{transform-dig.csv => transform-1-dig.csv} | 0 ...onstruct.csv => transform-2-construct.csv} | 0 ...nsform-build.csv => transform-3-build.csv} | 0 .../in/{zones-zone.csv => zones-2-zone.csv} | 0 docs/plugins/blueprint.rst | 7 +++- plugins/blueprint.cpp | 37 +++++++++++++------ plugins/lua/blueprint.lua | 20 ++++++---- scripts | 2 +- test/plugins/blueprint.lua | 10 ++--- test/quickfort/ecosystem.lua | 4 +- 37 files changed, 58 insertions(+), 29 deletions(-) rename data/blueprints/library/test/ecosystem/golden/{gui_quantum-build.csv => gui_quantum-2-build.csv} (100%) rename data/blueprints/library/test/ecosystem/golden/{gui_quantum-place.csv => gui_quantum-3-place.csv} (100%) create mode 100644 data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv rename data/blueprints/library/test/ecosystem/golden/{meta-dig.csv => meta-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/golden/{tracks-carve.csv => tracks-2-carve.csv} (100%) rename data/blueprints/library/test/ecosystem/golden/{transform-dig.csv => transform-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/golden/{transform-construct.csv => transform-2-construct.csv} (100%) rename data/blueprints/library/test/ecosystem/golden/{transform-build.csv => transform-3-build.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{basic-dig.csv => basic-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{basic-carve.csv => basic-2-carve.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{basic-build.csv => basic-3-build.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{basic-place.csv => basic-4-place.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{basic-zone.csv => basic-5-zone.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{buildings-dig.csv => buildings-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{buildings-construct.csv => buildings-2-construct.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{buildings-build.csv => buildings-3-build.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{fortifications-dig.csv => fortifications-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{fortifications-smooth.csv => fortifications-2-smooth.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{fortifications-carve.csv => fortifications-3-carve.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{gui_quantum-build.csv => gui_quantum-2-build.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{gui_quantum-place.csv => gui_quantum-3-place.csv} (100%) create mode 100644 data/blueprints/library/test/ecosystem/in/gui_quantum-4-query.csv rename data/blueprints/library/test/ecosystem/in/{meta-dig.csv => meta-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{stockpiles-place.csv => stockpiles-2-place.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{tracks-dig.csv => tracks-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{tracks-carve.csv => tracks-2-carve.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{tracks-build.csv => tracks-3-build.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{transform-dig.csv => transform-1-dig.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{transform-construct.csv => transform-2-construct.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{transform-build.csv => transform-3-build.csv} (100%) rename data/blueprints/library/test/ecosystem/in/{zones-zone.csv => zones-2-zone.csv} (100%) diff --git a/data/blueprints/library/test/ecosystem/golden/gui_quantum-build.csv b/data/blueprints/library/test/ecosystem/golden/gui_quantum-2-build.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/golden/gui_quantum-build.csv rename to data/blueprints/library/test/ecosystem/golden/gui_quantum-2-build.csv diff --git a/data/blueprints/library/test/ecosystem/golden/gui_quantum-place.csv b/data/blueprints/library/test/ecosystem/golden/gui_quantum-3-place.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/golden/gui_quantum-place.csv rename to data/blueprints/library/test/ecosystem/golden/gui_quantum-3-place.csv diff --git a/data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv b/data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv new file mode 100644 index 000000000..e9d422551 --- /dev/null +++ b/data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv @@ -0,0 +1,6 @@ +#query label(query) + + + +,,{givename name="foo dumper"} +,,{givename name="foo"} diff --git a/data/blueprints/library/test/ecosystem/golden/meta-dig.csv b/data/blueprints/library/test/ecosystem/golden/meta-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/golden/meta-dig.csv rename to data/blueprints/library/test/ecosystem/golden/meta-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/golden/tracks-carve.csv b/data/blueprints/library/test/ecosystem/golden/tracks-2-carve.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/golden/tracks-carve.csv rename to data/blueprints/library/test/ecosystem/golden/tracks-2-carve.csv diff --git a/data/blueprints/library/test/ecosystem/golden/transform-dig.csv b/data/blueprints/library/test/ecosystem/golden/transform-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/golden/transform-dig.csv rename to data/blueprints/library/test/ecosystem/golden/transform-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/golden/transform-construct.csv b/data/blueprints/library/test/ecosystem/golden/transform-2-construct.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/golden/transform-construct.csv rename to data/blueprints/library/test/ecosystem/golden/transform-2-construct.csv diff --git a/data/blueprints/library/test/ecosystem/golden/transform-build.csv b/data/blueprints/library/test/ecosystem/golden/transform-3-build.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/golden/transform-build.csv rename to data/blueprints/library/test/ecosystem/golden/transform-3-build.csv diff --git a/data/blueprints/library/test/ecosystem/in/basic-dig.csv b/data/blueprints/library/test/ecosystem/in/basic-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/basic-dig.csv rename to data/blueprints/library/test/ecosystem/in/basic-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/in/basic-carve.csv b/data/blueprints/library/test/ecosystem/in/basic-2-carve.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/basic-carve.csv rename to data/blueprints/library/test/ecosystem/in/basic-2-carve.csv diff --git a/data/blueprints/library/test/ecosystem/in/basic-build.csv b/data/blueprints/library/test/ecosystem/in/basic-3-build.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/basic-build.csv rename to data/blueprints/library/test/ecosystem/in/basic-3-build.csv diff --git a/data/blueprints/library/test/ecosystem/in/basic-place.csv b/data/blueprints/library/test/ecosystem/in/basic-4-place.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/basic-place.csv rename to data/blueprints/library/test/ecosystem/in/basic-4-place.csv diff --git a/data/blueprints/library/test/ecosystem/in/basic-zone.csv b/data/blueprints/library/test/ecosystem/in/basic-5-zone.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/basic-zone.csv rename to data/blueprints/library/test/ecosystem/in/basic-5-zone.csv diff --git a/data/blueprints/library/test/ecosystem/in/buildings-dig.csv b/data/blueprints/library/test/ecosystem/in/buildings-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/buildings-dig.csv rename to data/blueprints/library/test/ecosystem/in/buildings-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/in/buildings-construct.csv b/data/blueprints/library/test/ecosystem/in/buildings-2-construct.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/buildings-construct.csv rename to data/blueprints/library/test/ecosystem/in/buildings-2-construct.csv diff --git a/data/blueprints/library/test/ecosystem/in/buildings-build.csv b/data/blueprints/library/test/ecosystem/in/buildings-3-build.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/buildings-build.csv rename to data/blueprints/library/test/ecosystem/in/buildings-3-build.csv diff --git a/data/blueprints/library/test/ecosystem/in/fortifications-dig.csv b/data/blueprints/library/test/ecosystem/in/fortifications-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/fortifications-dig.csv rename to data/blueprints/library/test/ecosystem/in/fortifications-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/in/fortifications-smooth.csv b/data/blueprints/library/test/ecosystem/in/fortifications-2-smooth.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/fortifications-smooth.csv rename to data/blueprints/library/test/ecosystem/in/fortifications-2-smooth.csv diff --git a/data/blueprints/library/test/ecosystem/in/fortifications-carve.csv b/data/blueprints/library/test/ecosystem/in/fortifications-3-carve.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/fortifications-carve.csv rename to data/blueprints/library/test/ecosystem/in/fortifications-3-carve.csv diff --git a/data/blueprints/library/test/ecosystem/in/gui_quantum-build.csv b/data/blueprints/library/test/ecosystem/in/gui_quantum-2-build.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/gui_quantum-build.csv rename to data/blueprints/library/test/ecosystem/in/gui_quantum-2-build.csv diff --git a/data/blueprints/library/test/ecosystem/in/gui_quantum-place.csv b/data/blueprints/library/test/ecosystem/in/gui_quantum-3-place.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/gui_quantum-place.csv rename to data/blueprints/library/test/ecosystem/in/gui_quantum-3-place.csv diff --git a/data/blueprints/library/test/ecosystem/in/gui_quantum-4-query.csv b/data/blueprints/library/test/ecosystem/in/gui_quantum-4-query.csv new file mode 100644 index 000000000..eb287fc8a --- /dev/null +++ b/data/blueprints/library/test/ecosystem/in/gui_quantum-4-query.csv @@ -0,0 +1 @@ +#query diff --git a/data/blueprints/library/test/ecosystem/in/meta-dig.csv b/data/blueprints/library/test/ecosystem/in/meta-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/meta-dig.csv rename to data/blueprints/library/test/ecosystem/in/meta-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/in/stockpiles-place.csv b/data/blueprints/library/test/ecosystem/in/stockpiles-2-place.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/stockpiles-place.csv rename to data/blueprints/library/test/ecosystem/in/stockpiles-2-place.csv diff --git a/data/blueprints/library/test/ecosystem/in/tracks-dig.csv b/data/blueprints/library/test/ecosystem/in/tracks-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/tracks-dig.csv rename to data/blueprints/library/test/ecosystem/in/tracks-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/in/tracks-carve.csv b/data/blueprints/library/test/ecosystem/in/tracks-2-carve.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/tracks-carve.csv rename to data/blueprints/library/test/ecosystem/in/tracks-2-carve.csv diff --git a/data/blueprints/library/test/ecosystem/in/tracks-build.csv b/data/blueprints/library/test/ecosystem/in/tracks-3-build.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/tracks-build.csv rename to data/blueprints/library/test/ecosystem/in/tracks-3-build.csv diff --git a/data/blueprints/library/test/ecosystem/in/transform-dig.csv b/data/blueprints/library/test/ecosystem/in/transform-1-dig.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/transform-dig.csv rename to data/blueprints/library/test/ecosystem/in/transform-1-dig.csv diff --git a/data/blueprints/library/test/ecosystem/in/transform-construct.csv b/data/blueprints/library/test/ecosystem/in/transform-2-construct.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/transform-construct.csv rename to data/blueprints/library/test/ecosystem/in/transform-2-construct.csv diff --git a/data/blueprints/library/test/ecosystem/in/transform-build.csv b/data/blueprints/library/test/ecosystem/in/transform-3-build.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/transform-build.csv rename to data/blueprints/library/test/ecosystem/in/transform-3-build.csv diff --git a/data/blueprints/library/test/ecosystem/in/zones-zone.csv b/data/blueprints/library/test/ecosystem/in/zones-2-zone.csv similarity index 100% rename from data/blueprints/library/test/ecosystem/in/zones-zone.csv rename to data/blueprints/library/test/ecosystem/in/zones-2-zone.csv diff --git a/docs/plugins/blueprint.rst b/docs/plugins/blueprint.rst index 3a5e5a0c5..6c38a6152 100644 --- a/docs/plugins/blueprint.rst +++ b/docs/plugins/blueprint.rst @@ -146,5 +146,10 @@ The ``--splitby`` flag can take any of the following values: ``none`` Writes all blueprints into a single file. This is the standard format for quickfort fortress blueprint bundles and is the default. +``group`` + Creates one file per group of blueprints that can be played back at the same + time (without have to unpause the game and let dwarves fulfill jobs between + blueprint runs). ``phase`` - Creates a separate file for each phase. + Creates a separate file for each phase. Implies ``--nometa`` since meta + blueprints can't combine blueprints that are in separate files. diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 361aaa1ca..330b61729 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -1095,11 +1095,12 @@ static bool create_output_dir(color_ostream &out, static bool get_filename(string &fname, color_ostream &out, blueprint_options opts, // copy because we can't const - const string &phase) { + const string &phase, + int32_t ordinal) { auto L = Lua::Core::State; Lua::StackUnwinder top(L); - if (!lua_checkstack(L, 3) || + if (!lua_checkstack(L, 4) || !Lua::PushModulePublic( out, L, "plugins.blueprint", "get_filename")) { out.printerr("Failed to load blueprint Lua code\n"); @@ -1108,8 +1109,9 @@ static bool get_filename(string &fname, Lua::Push(L, &opts); Lua::Push(L, phase); + Lua::Push(L, ordinal); - if (!Lua::SafeCall(out, L, 2, 1)) { + if (!Lua::SafeCall(out, L, 3, 1)) { out.printerr("Failed Lua call to get_filename\n"); return false; } @@ -1228,9 +1230,9 @@ static bool write_blueprint(color_ostream &out, std::map &output_files, const blueprint_options &opts, const blueprint_processor &processor, - bool pretty) { + bool pretty, int32_t ordinal) { string fname; - if (!get_filename(fname, out, opts, processor.phase)) + if (!get_filename(fname, out, opts, processor.phase, ordinal)) return false; if (!output_files.count(fname)) output_files[fname] = new ofstream(fname, ofstream::trunc); @@ -1249,9 +1251,10 @@ static bool write_blueprint(color_ostream &out, static void write_meta_blueprint(color_ostream &out, std::map &output_files, const blueprint_options &opts, - const std::vector & meta_phases) { + const std::vector & meta_phases, + int32_t ordinal) { string fname; - get_filename(fname, out, opts, meta_phases.front()); + get_filename(fname, out, opts, meta_phases.front(), ordinal); ofstream &ofile = *output_files[fname]; ofile << "#meta label("; @@ -1285,7 +1288,7 @@ static void add_processor(vector &processors, static bool do_transform(color_ostream &out, const df::coord &start, const df::coord &end, - blueprint_options &opts, + blueprint_options opts, // copy so we can munge it vector &filenames) { // empty map instances to pass to emplace() below static const bp_area EMPTY_AREA; @@ -1368,16 +1371,26 @@ static bool do_transform(color_ostream &out, if (meta_phases.size() <= 1) opts.nometa = true; + bool in_meta = false; + int32_t ordinal = 0; std::map output_files; for (blueprint_processor &processor : processors) { if (processor.mapdata.empty() && !processor.force_create) continue; - if (!write_blueprint(out, output_files, opts, processor, pretty)) + bool meta_phase = is_meta_phase(out, opts, processor.phase); + if (!in_meta) + ++ordinal; + if (in_meta && !meta_phase) { + write_meta_blueprint(out, output_files, opts, meta_phases, ordinal); + ++ordinal; + } + in_meta = meta_phase; + if (!write_blueprint(out, output_files, opts, processor, pretty, + ordinal)) break; } - if (!opts.nometa) { - write_meta_blueprint(out, output_files, opts, meta_phases); - } + if (in_meta) + write_meta_blueprint(out, output_files, opts, meta_phases, ordinal); for (auto &it : output_files) { filenames.push_back(it.first); diff --git a/plugins/lua/blueprint.lua b/plugins/lua/blueprint.lua index e3b36d9fe..718b211e8 100644 --- a/plugins/lua/blueprint.lua +++ b/plugins/lua/blueprint.lua @@ -31,6 +31,7 @@ valid_formats = utils.invert(valid_formats_list) local valid_split_strategies_list = { 'none', + 'group', 'phase', } valid_split_strategies = utils.invert(valid_split_strategies_list) @@ -143,6 +144,10 @@ local function process_args(opts, args) return end + if opts.split_strategy == 'phase' then + opts.nometa = true + end + return positionals end @@ -200,7 +205,7 @@ function is_meta_phase(opts, phase) end -- returns the name of the output file for the given context -function get_filename(opts, phase) +function get_filename(opts, phase, ordinal) local fullname = 'blueprints/' .. opts.name local _,_,basename = fullname:find('/([^/]+)/?$') if not basename then @@ -210,14 +215,13 @@ function get_filename(opts, phase) if fullname:endswith('/') then fullname = fullname .. basename end - if opts.split_strategy == 'phase' then - if is_meta_phase(opts, phase) then - phase = 'meta' - end - return ('%s-%s.csv'):format(fullname, phase) + if opts.split_strategy == 'none' then + return ('%s.csv'):format(fullname) + end + if is_meta_phase(opts, phase) then + phase = 'meta' end - -- no splitting - return ('%s.csv'):format(fullname) + return ('%s-%d-%s.csv'):format(fullname, ordinal, phase) end -- compatibility with old exported API. diff --git a/scripts b/scripts index 6f0d7ea22..0be5cc0ea 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 6f0d7ea22edcd68a1716d843e3ff439a75f23c35 +Subproject commit 0be5cc0eaf625029ef26392224db5c3d2822a63d diff --git a/test/plugins/blueprint.lua b/test/plugins/blueprint.lua index 73ec33eda..6146aea3f 100644 --- a/test/plugins/blueprint.lua +++ b/test/plugins/blueprint.lua @@ -101,7 +101,7 @@ function test.parse_gui_commandline() opts = {} b.parse_gui_commandline(opts, {'--splitby', 'phase'}) expect.table_eq({auto_phase=true, format='minimal', split_strategy='phase', - name='blueprint'}, + name='blueprint', nometa=true}, opts) expect.error_match('unknown split_strategy', @@ -241,16 +241,16 @@ end function test.get_filename() local opts = {name='a', split_strategy='none'} - expect.eq('blueprints/a.csv', b.get_filename(opts, 'dig')) + expect.eq('blueprints/a.csv', b.get_filename(opts, 'dig', 1)) opts = {name='a/', split_strategy='none'} - expect.eq('blueprints/a/a.csv', b.get_filename(opts, 'dig')) + expect.eq('blueprints/a/a.csv', b.get_filename(opts, 'dig', 1)) opts = {name='a', split_strategy='phase'} - expect.eq('blueprints/a-dig.csv', b.get_filename(opts, 'dig')) + expect.eq('blueprints/a-1-dig.csv', b.get_filename(opts, 'dig', 1)) opts = {name='a/', split_strategy='phase'} - expect.eq('blueprints/a/a-dig.csv', b.get_filename(opts, 'dig')) + expect.eq('blueprints/a/a-5-dig.csv', b.get_filename(opts, 'dig', 5)) expect.error_match('could not parse basename', function() b.get_filename({name='', split_strategy='none'}) diff --git a/test/quickfort/ecosystem.lua b/test/quickfort/ecosystem.lua index 05f531e2e..663bc353b 100644 --- a/test/quickfort/ecosystem.lua +++ b/test/quickfort/ecosystem.lua @@ -244,7 +244,7 @@ end local function run_blueprint(basename, spec, pos) local args = {tostring(spec.width), tostring(spec.height), tostring(-spec.depth), output_dir..basename, - get_cursor_arg(pos), '-tphase', '--nometa'} + get_cursor_arg(pos), '-tphase'} local playback_start_arg = get_playback_start_arg(spec.start) if playback_start_arg then table.insert(args, playback_start_arg) @@ -444,7 +444,7 @@ function extra_fns.gui_quantum(pos) view:onInput({_STRING=string.byte('f')}) view:onInput({_STRING=string.byte('o')}) view:onInput({_STRING=string.byte('o')}) - send_keys('SELECT') + view:onInput({SELECT=true}) -- rotate the dump direction to the south send_keys('CUSTOM_D') view:onRender() From fc926df59d8f5dae54e220358df2f41595614795 Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 14 Oct 2022 12:31:51 -0700 Subject: [PATCH 15/18] update changelog --- docs/changelog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index a28ae5f9f..c7c36ac8b 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -43,6 +43,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `blueprint`: record stockpile/building/zone names in blueprints - `blueprint`: record room sizes in blueprints - `blueprint`: generate meta blueprints to reduce the number of blueprints you have to apply +- `blueprint`: support splitting the output file into phases grouped by when they can be applied +- `blueprint`: when splitting output files, number them so they sort into the order you should apply them in - `ls`: indent tag listings and wrap them in the right column for better readability - `ls`: new ``--exclude`` option for hiding matched scripts from the output. this can be especially useful for modders who don't want their mod scripts to be included in ``ls`` output. - `digtype`: new ``-z`` option for digtype to restrict designations to the current z-level and down From fea0ce0718b463278c16567c02fbdbf9b1b31924 Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 14 Oct 2022 13:11:26 -0700 Subject: [PATCH 16/18] fix cvs quoting --- .../ecosystem/golden/gui_quantum-4-query.csv | 4 +-- plugins/blueprint.cpp | 28 +++++++++++++------ test/quickfort/ecosystem.lua | 2 +- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv b/data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv index e9d422551..811f7b3b0 100644 --- a/data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv +++ b/data/blueprints/library/test/ecosystem/golden/gui_quantum-4-query.csv @@ -2,5 +2,5 @@ -,,{givename name="foo dumper"} -,,{givename name="foo"} +,,"{givename name=""foo dumper""}" +,,"{givename name=""foo""}" diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 330b61729..509b1e6bc 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -5,8 +5,6 @@ * Written by cdombroski. */ -#include -#include #include #include @@ -1011,11 +1009,23 @@ static const char * get_tile_zone(const df::coord &pos, return add_expansion_syntax(zone, get_zone_keys(zone)); } -static string csv_sanitize(const string &str) { - static const std::regex pattern("\""); - static const string replacement("\"\""); +// surrounds the given string in quotes and replaces internal double quotes (") +// with double double quotes ("") (as per the csv spec) +static string csv_quote(const string &str) { + std::ostringstream outstr; + outstr << "\""; + + size_t start = 0; + auto end = str.find('"'); + while (end != std::string::npos) { + outstr << str.substr(start, end - start); + outstr << "\"\""; + start = end + 1; + end = str.find('"', start); + } + outstr << str.substr(start, end) << "\""; - return std::regex_replace(str, pattern, replacement); + return outstr.str(); } static const char * get_tile_query(const df::coord &pos, @@ -1042,11 +1052,11 @@ static const char * get_tile_query(const df::coord &pos, std::ostringstream str; if (bld_name.size()) - str << "{givename name=\"" << csv_sanitize(bld_name) << "\"}"; + str << "{givename name=" + csv_quote(bld_name) + "}"; if (zone_name.size()) - str << "{namezone name=\"" << csv_sanitize(zone_name) << "\"}"; + str << "{namezone name=" + csv_quote(zone_name) + "}"; - return cache(str); + return cache(csv_quote(str.str())); } static const char * get_tile_rooms(const df::coord &, const tile_context &ctx) { diff --git a/test/quickfort/ecosystem.lua b/test/quickfort/ecosystem.lua index 663bc353b..27dddc5d5 100644 --- a/test/quickfort/ecosystem.lua +++ b/test/quickfort/ecosystem.lua @@ -444,7 +444,7 @@ function extra_fns.gui_quantum(pos) view:onInput({_STRING=string.byte('f')}) view:onInput({_STRING=string.byte('o')}) view:onInput({_STRING=string.byte('o')}) - view:onInput({SELECT=true}) + send_keys('SELECT') -- rotate the dump direction to the south send_keys('CUSTOM_D') view:onRender() From 20c0b75f8b7a78c114a68812357c5770e3f92d15 Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 14 Oct 2022 13:20:50 -0700 Subject: [PATCH 17/18] reduce size of overlay button --- plugins/overlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/overlay.cpp b/plugins/overlay.cpp index 1a0cc7c02..dd7563112 100644 --- a/plugins/overlay.cpp +++ b/plugins/overlay.cpp @@ -99,7 +99,7 @@ namespace DFHack { DBG_DECLARE(overlay, log, DebugCategory::LINFO); } -static const std::string button_text = "[ DFHack Launcher ]"; +static const std::string button_text = "[ DFHack ]"; static bool clicked = false; static bool handle_click() { From fbb4b37493cadde3d2c90589ba40341059179fa2 Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 14 Oct 2022 13:22:05 -0700 Subject: [PATCH 18/18] update changelog --- docs/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index c7c36ac8b..a4fef7c57 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -51,6 +51,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - UX: List widgets now have mouse-interactive scrollbars - UX: You can now hold down the mouse button on a scrollbar to make it scroll multiple times. - UX: You can now drag the scrollbar to scroll to a specific spot +- `overlay`: reduce the size of the "DFHack Launcher" button - Constructions module: ``findAtTile`` now uses a binary search intead of a linear search. ## Documentation