Merge remote-tracking branch 'myk002/blueprint_in_blueprints' into develop

develop
lethosor 2020-07-17 17:32:59 -04:00
commit 35d659091d
No known key found for this signature in database
GPG Key ID: 76A269552F4F58C1
6 changed files with 100 additions and 25 deletions

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

@ -46,6 +46,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``) - `RemoteFortressReader`: fixed a couple crashes that could result from decoding invalid enum items (``site_realization_building_type`` and ``improvement_type``)
## Misc Improvements ## 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 - `confirm`: added a confirmation dialog for convicting dwarves of crimes
## Lua ## Lua

@ -2365,6 +2365,7 @@ static const LuaWrapper::FunctionReg dfhack_filesystem_module[] = {
WRAPM(Filesystem, getcwd), WRAPM(Filesystem, getcwd),
WRAPM(Filesystem, chdir), WRAPM(Filesystem, chdir),
WRAPM(Filesystem, mkdir), WRAPM(Filesystem, mkdir),
WRAPM(Filesystem, mkdir_recursive),
WRAPM(Filesystem, rmdir), WRAPM(Filesystem, rmdir),
WRAPM(Filesystem, exists), WRAPM(Filesystem, exists),
WRAPM(Filesystem, isfile), WRAPM(Filesystem, isfile),

@ -149,6 +149,7 @@ namespace DFHack {
DFHACK_EXPORT bool chdir (std::string path); DFHACK_EXPORT bool chdir (std::string path);
DFHACK_EXPORT std::string getcwd (); DFHACK_EXPORT std::string getcwd ();
DFHACK_EXPORT bool mkdir (std::string path); DFHACK_EXPORT bool mkdir (std::string path);
DFHACK_EXPORT bool mkdir_recursive (std::string path);
DFHACK_EXPORT bool rmdir (std::string path); DFHACK_EXPORT bool rmdir (std::string path);
DFHACK_EXPORT bool stat (std::string path, STAT_STRUCT &info); DFHACK_EXPORT bool stat (std::string path, STAT_STRUCT &info);
DFHACK_EXPORT bool exists (std::string path); DFHACK_EXPORT bool exists (std::string path);

@ -45,6 +45,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <algorithm>
#include <string> #include <string>
#include "modules/Filesystem.h" #include "modules/Filesystem.h"
@ -82,6 +83,37 @@ bool Filesystem::mkdir (std::string path)
return fail == 0; return fail == 0;
} }
static bool mkdir_recursive_impl (std::string path)
{
size_t last_slash = path.find_last_of("/");
if (last_slash != std::string::npos)
{
std::string parent_path = path.substr(0, last_slash);
bool parent_exists = mkdir_recursive_impl(parent_path);
if (!parent_exists)
{
return false;
}
}
return (Filesystem::mkdir(path) || errno == EEXIST) && Filesystem::isdir(path);
}
bool Filesystem::mkdir_recursive (std::string path)
{
#ifdef _WIN32
// normalize to forward slashes
std::replace(path.begin(), path.end(), '\\', '/');
#endif
if (path.size() > FILENAME_MAX)
{
// path too long
return false;
}
return mkdir_recursive_impl(path);
}
bool Filesystem::rmdir (std::string path) bool Filesystem::rmdir (std::string path)
{ {
int fail; int fail;

@ -3,12 +3,14 @@
//Translates a region of tiles specified by the cursor and arguments/prompts into a series of blueprint files suitable for digfort/buildingplan/quickfort //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 <algorithm>
#include <sstream>
#include <Console.h> #include <Console.h>
#include <PluginManager.h> #include <PluginManager.h>
#include "LuaTools.h" #include "LuaTools.h"
#include "modules/Buildings.h" #include "modules/Buildings.h"
#include "modules/Filesystem.h"
#include "modules/Gui.h" #include "modules/Gui.h"
#include "modules/MapCache.h" #include "modules/MapCache.h"
@ -62,9 +64,10 @@ command_result help(color_ostream &out)
<< " defaults to generating all blueprints" << endl << " defaults to generating all blueprints" << endl
<< endl << endl
<< "blueprint translates a portion of your fortress into blueprints suitable for" << 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 << " digfort/fortplan/quickfort. Blueprints are created in the \"blueprints\"" << endl
<< " following a \"name-phase.csv\" pattern. Translation starts at the current" << endl << " subdirectory of the DF folder with names following a \"name-phase.csv\" pattern." << endl
<< " cursor location and includes all tiles in the range specified." << endl; << " Translation starts at the current cursor location and includes all tiles in the" << endl
<< " range specified." << endl;
return CR_OK; return CR_OK;
} }
@ -557,32 +560,55 @@ string get_tile_query(df::building* b)
return " "; return " ";
} }
command_result do_transform(DFCoord start, DFCoord end, string name, uint32_t phases) void init_stream(ofstream &out, std::string basename, std::string target)
{
std::ostringstream out_path;
out_path << basename << "-" << target << ".csv";
out.open(out_path.str(), 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; ofstream dig, build, place, query;
std::string basename = "blueprints/" + name;
#ifdef _WIN32
// normalize to forward slashes
std::replace(basename.begin(), basename.end(), '\\', '/');
#endif
size_t last_slash = basename.find_last_of("/");
std::string parent_path = basename.substr(0, last_slash);
// create output directory if it doesn't already exist
std::error_code ec;
if (!Filesystem::mkdir_recursive(parent_path))
{
err << "could not create output directory: '" << parent_path << "'";
return CR_FAILURE;
}
if (phases & QUERY) if (phases & QUERY)
{ {
//query = ofstream((name + "-query.csv").c_str(), ofstream::trunc); //query = ofstream((name + "-query.csv").c_str(), ofstream::trunc);
query.open(name+"-query.csv", ofstream::trunc); init_stream(query, basename, "query");
query << "#query" << endl;
} }
if (phases & PLACE) if (phases & PLACE)
{ {
//place = ofstream(name + "-place.csv", ofstream::trunc); //place = ofstream(name + "-place.csv", ofstream::trunc);
place.open(name+"-place.csv", ofstream::trunc); init_stream(place, basename, "place");
place << "#place" << endl;
} }
if (phases & BUILD) if (phases & BUILD)
{ {
//build = ofstream(name + "-build.csv", ofstream::trunc); //build = ofstream(name + "-build.csv", ofstream::trunc);
build.open(name+"-build.csv", ofstream::trunc); init_stream(build, basename, "build");
build << "#build" << endl;
} }
if (phases & DIG) if (phases & DIG)
{ {
//dig = ofstream(name + "-dig.csv", ofstream::trunc); //dig = ofstream(name + "-dig.csv", ofstream::trunc);
dig.open(name+"-dig.csv", ofstream::trunc); init_stream(dig, basename, "dig");
dig << "#dig" << endl;
} }
if (start.x > end.x) if (start.x > end.x)
{ {
@ -675,18 +701,27 @@ command_result blueprint(color_ostream &out, vector<string> &parameters)
} }
DFCoord start (x, y, z); DFCoord start (x, y, z);
DFCoord end (x + stoi(parameters[0]), y + stoi(parameters[1]), z + stoi(parameters[2])); 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; uint32_t option = 0;
if (cmd_option_exists(parameters, "dig")) if (parameters.size() == 4)
option |= DIG; {
if (cmd_option_exists(parameters, "build")) option = DIG | BUILD | PLACE | QUERY;
option |= BUILD; }
if (cmd_option_exists(parameters, "place")) else
option |= PLACE; {
if (cmd_option_exists(parameters, "query")) if (cmd_option_exists(parameters, "dig"))
option |= QUERY; option |= DIG;
return do_transform(start, end, parameters[3], option); 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) { static int create(lua_State *L, uint32_t options) {
@ -701,9 +736,12 @@ static int create(lua_State *L, uint32_t options) {
luaL_argerror(L, 2, "invalid end position"); luaL_argerror(L, 2, "invalid end position");
string filename(lua_tostring(L, 3)); 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; return 1;
} }
static int dig(lua_State *L) { static int dig(lua_State *L) {