blueprint: write blueprints to blueprints/ subdir

to enable writing to a subdir that may not exist, blueprint now automatically
creates folder trees. E.g. ``blueprint 30 30 1 rooms/dining dig`` will create
the file ``blueprints/rooms/dining-dig.csv``). Previously it would fail if the
``blueprints/rooms/`` directory didn't already exist.
develop
Myk Taylor 2020-07-15 16:57:14 -07:00
parent 89283026ae
commit e2334387a9
4 changed files with 67 additions and 26 deletions

@ -100,6 +100,7 @@ Milo Christiansen milochristiansen
MithrilTuxedo MithrilTuxedo
mizipzor mizipzor
moversti moversti
Myk Taylor myk002
napagokc napagokc
Neil Little nmlittle
Nick Rart nickrart comestible

@ -41,6 +41,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- `RemoteFortressReader`: fixed a couple crashes that could result from decoding invalid enum items (``site_realization_building_type`` and ``improvement_type``)
## Misc Improvements
- `blueprint`: now writes blueprints to the ``blueprints/`` subfolder instead of the df root folder
- `blueprint`: now automatically creates folder trees when organizing blueprints into subfolders (e.g. ``blueprint 30 30 1 rooms/dining dig`` will create the file ``blueprints/rooms/dining-dig.csv``); previously it would fail if the ``blueprints/rooms/`` directory didn't already exist
- `confirm`: added a confirmation dialog for convicting dwarves of crimes
## Ruby

@ -93,7 +93,8 @@ if(BUILD_SUPPORTED)
dfhack_plugin(automaterial automaterial.cpp)
dfhack_plugin(automelt automelt.cpp)
dfhack_plugin(autotrade autotrade.cpp)
dfhack_plugin(blueprint blueprint.cpp LINK_LIBRARIES lua)
# stdc++fs required for std::experimental::filesystem; once we move to c++17 this can be removed since it's in the STL there
dfhack_plugin(blueprint blueprint.cpp LINK_LIBRARIES lua stdc++fs)
dfhack_plugin(burrows burrows.cpp LINK_LIBRARIES lua)
dfhack_plugin(building-hacks building-hacks.cpp LINK_LIBRARIES lua)
dfhack_plugin(buildingplan buildingplan.cpp LINK_LIBRARIES buildingplan-lib)

@ -3,6 +3,8 @@
//Translates a region of tiles specified by the cursor and arguments/prompts into a series of blueprint files suitable for digfort/buildingplan/quickfort
#include <algorithm>
#include <experimental/filesystem> // This is just <filesystem> in c++17, but we're currently compiling with c++11
#include <sstream>
#include <Console.h>
#include <PluginManager.h>
@ -33,6 +35,8 @@ using std::pair;
using namespace DFHack;
using namespace df::enums;
namespace filesystem = std::experimental::filesystem;
DFHACK_PLUGIN("blueprint");
enum phase {DIG=1, BUILD=2, PLACE=4, QUERY=8};
@ -62,9 +66,10 @@ command_result help(color_ostream &out)
<< " defaults to generating all blueprints" << endl
<< endl
<< "blueprint translates a portion of your fortress into blueprints suitable for" << endl
<< " digfort/fortplan/quickfort. Blueprints are created in the DF folder with names" << endl
<< " following a \"name-phase.csv\" pattern. Translation starts at the current" << endl
<< " cursor location and includes all tiles in the range specified." << endl;
<< " digfort/fortplan/quickfort. Blueprints are created in the \"blueprints\"" << endl
<< " subdirectory of the DF folder with names following a \"name-phase.csv\" pattern." << endl
<< " Translation starts at the current cursor location and includes all tiles in the" << endl
<< " range specified." << endl;
return CR_OK;
}
@ -557,32 +562,52 @@ string get_tile_query(df::building* b)
return " ";
}
command_result do_transform(DFCoord start, DFCoord end, string name, uint32_t phases)
void init_stream(ofstream &out, filesystem::path basename, std::string target)
{
filesystem::path out_path(basename);
out_path += "-";
out_path += target;
out_path += ".csv";
out.open(out_path, ofstream::trunc);
out << "#" << target << endl;
}
command_result do_transform(DFCoord start, DFCoord end, string name, uint32_t phases, std::ostringstream &err)
{
ofstream dig, build, place, query;
filesystem::path basename = "blueprints";
basename /= name;
basename.make_preferred();
// create output directory if it doesn't already exist
std::error_code ec;
if (!filesystem::create_directories(basename.parent_path(), ec) && ec)
{
err << "could not create output directory: " << basename.parent_path()
<< " (" << ec.message() << ")";
return CR_FAILURE;
}
if (phases & QUERY)
{
//query = ofstream((name + "-query.csv").c_str(), ofstream::trunc);
query.open(name+"-query.csv", ofstream::trunc);
query << "#query" << endl;
init_stream(query, basename, "query");
}
if (phases & PLACE)
{
//place = ofstream(name + "-place.csv", ofstream::trunc);
place.open(name+"-place.csv", ofstream::trunc);
place << "#place" << endl;
init_stream(place, basename, "place");
}
if (phases & BUILD)
{
//build = ofstream(name + "-build.csv", ofstream::trunc);
build.open(name+"-build.csv", ofstream::trunc);
build << "#build" << endl;
init_stream(build, basename, "build");
}
if (phases & DIG)
{
//dig = ofstream(name + "-dig.csv", ofstream::trunc);
dig.open(name+"-dig.csv", ofstream::trunc);
dig << "#dig" << endl;
init_stream(dig, basename, "dig");
}
if (start.x > end.x)
{
@ -675,18 +700,27 @@ command_result blueprint(color_ostream &out, vector<string> &parameters)
}
DFCoord start (x, y, z);
DFCoord end (x + stoi(parameters[0]), y + stoi(parameters[1]), z + stoi(parameters[2]));
if (parameters.size() == 4)
return do_transform(start, end, parameters[3], DIG | BUILD | PLACE | QUERY);
uint32_t option = 0;
if (cmd_option_exists(parameters, "dig"))
option |= DIG;
if (cmd_option_exists(parameters, "build"))
option |= BUILD;
if (cmd_option_exists(parameters, "place"))
option |= PLACE;
if (cmd_option_exists(parameters, "query"))
option |= QUERY;
return do_transform(start, end, parameters[3], option);
if (parameters.size() == 4)
{
option = DIG | BUILD | PLACE | QUERY;
}
else
{
if (cmd_option_exists(parameters, "dig"))
option |= DIG;
if (cmd_option_exists(parameters, "build"))
option |= BUILD;
if (cmd_option_exists(parameters, "place"))
option |= PLACE;
if (cmd_option_exists(parameters, "query"))
option |= QUERY;
}
std::ostringstream err;
DFHack::command_result result = do_transform(start, end, parameters[3], option, err);
if (result != CR_OK)
out.printerr("%s\n", err.str().c_str());
return result;
}
static int create(lua_State *L, uint32_t options) {
@ -701,9 +735,12 @@ static int create(lua_State *L, uint32_t options) {
luaL_argerror(L, 2, "invalid end position");
string filename(lua_tostring(L, 3));
lua_pushboolean(L, do_transform(start, end, filename, options));
std::ostringstream err;
DFHack::command_result result = do_transform(start, end, filename, options, err);
if (result != CR_OK)
luaL_error(L, "%s", err.str().c_str());
lua_pushboolean(L, result);
return 1;
}
static int dig(lua_State *L) {