Skip to content

Commit 35d6590

Browse files
committed
Merge remote-tracking branch 'myk002/blueprint_in_blueprints' into develop
2 parents c858f33 + bb91fdc commit 35d6590

6 files changed

Lines changed: 100 additions & 25 deletions

File tree

docs/Authors.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ Milo Christiansen milochristiansen
100100
MithrilTuxedo MithrilTuxedo
101101
mizipzor mizipzor
102102
moversti moversti
103+
Myk Taylor myk002
103104
napagokc napagokc
104105
Neil Little nmlittle
105106
Nick Rart nickrart comestible

docs/changelog.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
4646
- `RemoteFortressReader`: fixed a couple crashes that could result from decoding invalid enum items (``site_realization_building_type`` and ``improvement_type``)
4747

4848
## Misc Improvements
49+
- `blueprint`: now writes blueprints to the ``blueprints/`` subfolder instead of the df root folder
50+
- `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
4951
- `confirm`: added a confirmation dialog for convicting dwarves of crimes
5052

5153
## Lua

library/LuaApi.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,6 +2365,7 @@ static const LuaWrapper::FunctionReg dfhack_filesystem_module[] = {
23652365
WRAPM(Filesystem, getcwd),
23662366
WRAPM(Filesystem, chdir),
23672367
WRAPM(Filesystem, mkdir),
2368+
WRAPM(Filesystem, mkdir_recursive),
23682369
WRAPM(Filesystem, rmdir),
23692370
WRAPM(Filesystem, exists),
23702371
WRAPM(Filesystem, isfile),

library/include/modules/Filesystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ namespace DFHack {
149149
DFHACK_EXPORT bool chdir (std::string path);
150150
DFHACK_EXPORT std::string getcwd ();
151151
DFHACK_EXPORT bool mkdir (std::string path);
152+
DFHACK_EXPORT bool mkdir_recursive (std::string path);
152153
DFHACK_EXPORT bool rmdir (std::string path);
153154
DFHACK_EXPORT bool stat (std::string path, STAT_STRUCT &info);
154155
DFHACK_EXPORT bool exists (std::string path);

library/modules/Filesystem.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4545
SOFTWARE.
4646
*/
4747

48+
#include <algorithm>
4849
#include <string>
4950

5051
#include "modules/Filesystem.h"
@@ -82,6 +83,37 @@ bool Filesystem::mkdir (std::string path)
8283
return fail == 0;
8384
}
8485

86+
static bool mkdir_recursive_impl (std::string path)
87+
{
88+
size_t last_slash = path.find_last_of("/");
89+
if (last_slash != std::string::npos)
90+
{
91+
std::string parent_path = path.substr(0, last_slash);
92+
bool parent_exists = mkdir_recursive_impl(parent_path);
93+
if (!parent_exists)
94+
{
95+
return false;
96+
}
97+
}
98+
return (Filesystem::mkdir(path) || errno == EEXIST) && Filesystem::isdir(path);
99+
}
100+
101+
bool Filesystem::mkdir_recursive (std::string path)
102+
{
103+
#ifdef _WIN32
104+
// normalize to forward slashes
105+
std::replace(path.begin(), path.end(), '\\', '/');
106+
#endif
107+
108+
if (path.size() > FILENAME_MAX)
109+
{
110+
// path too long
111+
return false;
112+
}
113+
114+
return mkdir_recursive_impl(path);
115+
}
116+
85117
bool Filesystem::rmdir (std::string path)
86118
{
87119
int fail;

plugins/blueprint.cpp

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
//Translates a region of tiles specified by the cursor and arguments/prompts into a series of blueprint files suitable for digfort/buildingplan/quickfort
44

55
#include <algorithm>
6+
#include <sstream>
67

78
#include <Console.h>
89
#include <PluginManager.h>
910
#include "LuaTools.h"
1011

1112
#include "modules/Buildings.h"
13+
#include "modules/Filesystem.h"
1214
#include "modules/Gui.h"
1315
#include "modules/MapCache.h"
1416

@@ -62,9 +64,10 @@ command_result help(color_ostream &out)
6264
<< " defaults to generating all blueprints" << endl
6365
<< endl
6466
<< "blueprint translates a portion of your fortress into blueprints suitable for" << endl
65-
<< " digfort/fortplan/quickfort. Blueprints are created in the DF folder with names" << endl
66-
<< " following a \"name-phase.csv\" pattern. Translation starts at the current" << endl
67-
<< " cursor location and includes all tiles in the range specified." << endl;
67+
<< " digfort/fortplan/quickfort. Blueprints are created in the \"blueprints\"" << endl
68+
<< " subdirectory of the DF folder with names following a \"name-phase.csv\" pattern." << endl
69+
<< " Translation starts at the current cursor location and includes all tiles in the" << endl
70+
<< " range specified." << endl;
6871
return CR_OK;
6972
}
7073

@@ -557,32 +560,55 @@ string get_tile_query(df::building* b)
557560
return " ";
558561
}
559562

560-
command_result do_transform(DFCoord start, DFCoord end, string name, uint32_t phases)
563+
void init_stream(ofstream &out, std::string basename, std::string target)
564+
{
565+
std::ostringstream out_path;
566+
out_path << basename << "-" << target << ".csv";
567+
out.open(out_path.str(), ofstream::trunc);
568+
out << "#" << target << endl;
569+
}
570+
571+
command_result do_transform(DFCoord start, DFCoord end, string name, uint32_t phases, std::ostringstream &err)
561572
{
562573
ofstream dig, build, place, query;
574+
575+
std::string basename = "blueprints/" + name;
576+
577+
#ifdef _WIN32
578+
// normalize to forward slashes
579+
std::replace(basename.begin(), basename.end(), '\\', '/');
580+
#endif
581+
582+
size_t last_slash = basename.find_last_of("/");
583+
std::string parent_path = basename.substr(0, last_slash);
584+
585+
// create output directory if it doesn't already exist
586+
std::error_code ec;
587+
if (!Filesystem::mkdir_recursive(parent_path))
588+
{
589+
err << "could not create output directory: '" << parent_path << "'";
590+
return CR_FAILURE;
591+
}
592+
563593
if (phases & QUERY)
564594
{
565595
//query = ofstream((name + "-query.csv").c_str(), ofstream::trunc);
566-
query.open(name+"-query.csv", ofstream::trunc);
567-
query << "#query" << endl;
596+
init_stream(query, basename, "query");
568597
}
569598
if (phases & PLACE)
570599
{
571600
//place = ofstream(name + "-place.csv", ofstream::trunc);
572-
place.open(name+"-place.csv", ofstream::trunc);
573-
place << "#place" << endl;
601+
init_stream(place, basename, "place");
574602
}
575603
if (phases & BUILD)
576604
{
577605
//build = ofstream(name + "-build.csv", ofstream::trunc);
578-
build.open(name+"-build.csv", ofstream::trunc);
579-
build << "#build" << endl;
606+
init_stream(build, basename, "build");
580607
}
581608
if (phases & DIG)
582609
{
583610
//dig = ofstream(name + "-dig.csv", ofstream::trunc);
584-
dig.open(name+"-dig.csv", ofstream::trunc);
585-
dig << "#dig" << endl;
611+
init_stream(dig, basename, "dig");
586612
}
587613
if (start.x > end.x)
588614
{
@@ -675,18 +701,27 @@ command_result blueprint(color_ostream &out, vector<string> &parameters)
675701
}
676702
DFCoord start (x, y, z);
677703
DFCoord end (x + stoi(parameters[0]), y + stoi(parameters[1]), z + stoi(parameters[2]));
678-
if (parameters.size() == 4)
679-
return do_transform(start, end, parameters[3], DIG | BUILD | PLACE | QUERY);
680704
uint32_t option = 0;
681-
if (cmd_option_exists(parameters, "dig"))
682-
option |= DIG;
683-
if (cmd_option_exists(parameters, "build"))
684-
option |= BUILD;
685-
if (cmd_option_exists(parameters, "place"))
686-
option |= PLACE;
687-
if (cmd_option_exists(parameters, "query"))
688-
option |= QUERY;
689-
return do_transform(start, end, parameters[3], option);
705+
if (parameters.size() == 4)
706+
{
707+
option = DIG | BUILD | PLACE | QUERY;
708+
}
709+
else
710+
{
711+
if (cmd_option_exists(parameters, "dig"))
712+
option |= DIG;
713+
if (cmd_option_exists(parameters, "build"))
714+
option |= BUILD;
715+
if (cmd_option_exists(parameters, "place"))
716+
option |= PLACE;
717+
if (cmd_option_exists(parameters, "query"))
718+
option |= QUERY;
719+
}
720+
std::ostringstream err;
721+
DFHack::command_result result = do_transform(start, end, parameters[3], option, err);
722+
if (result != CR_OK)
723+
out.printerr("%s\n", err.str().c_str());
724+
return result;
690725
}
691726

692727
static int create(lua_State *L, uint32_t options) {
@@ -701,9 +736,12 @@ static int create(lua_State *L, uint32_t options) {
701736
luaL_argerror(L, 2, "invalid end position");
702737
string filename(lua_tostring(L, 3));
703738

704-
lua_pushboolean(L, do_transform(start, end, filename, options));
739+
std::ostringstream err;
740+
DFHack::command_result result = do_transform(start, end, filename, options, err);
741+
if (result != CR_OK)
742+
luaL_error(L, "%s", err.str().c_str());
743+
lua_pushboolean(L, result);
705744
return 1;
706-
707745
}
708746

709747
static int dig(lua_State *L) {

0 commit comments

Comments
 (0)