Merge pull request #3937 from myk002/myk_burrow

[burrow] finish implementing CLI
develop
Myk 2023-11-01 13:10:15 -07:00 committed by GitHub
commit b1ac7410fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 225 additions and 328 deletions

@ -85,10 +85,8 @@ Options
``-c``, ``--cursor <pos>`` ``-c``, ``--cursor <pos>``
Indicate the starting position of the box or flood fill. If not specified, Indicate the starting position of the box or flood fill. If not specified,
the position of the keyboard cursor is used. the position of the keyboard cursor is used.
``-d``, ``--dry-run``
Report what would be done, but don't actually change anything.
``-z``, ``--cur-zlevel`` ``-z``, ``--cur-zlevel``
Restricts the operation to the currently visible z-level. Restricts a flood fill operation to the currently visible z-level.
Note Note
---- ----

@ -8,8 +8,11 @@
#include "modules/Persistence.h" #include "modules/Persistence.h"
#include "modules/World.h" #include "modules/World.h"
#include "df/block_burrow.h"
#include "df/burrow.h" #include "df/burrow.h"
#include "df/map_block.h"
#include "df/tile_designation.h" #include "df/tile_designation.h"
#include "df/unit.h"
#include "df/world.h" #include "df/world.h"
using std::vector; using std::vector;
@ -194,10 +197,9 @@ static void get_bool_field(lua_State *L, int idx, const char *name, bool *dest)
lua_pop(L, 1); lua_pop(L, 1);
} }
static void get_opts(lua_State *L, int idx, bool &dry_run, bool &zlevel) { static void get_opts(lua_State *L, int idx, bool &zlevel) {
if (lua_gettop(L) < idx) if (lua_gettop(L) < idx)
return; return;
get_bool_field(L, idx, "dry_run", &dry_run);
get_bool_field(L, idx, "zlevel", &zlevel); get_bool_field(L, idx, "zlevel", &zlevel);
} }
@ -232,25 +234,151 @@ static df::burrow* get_burrow(lua_State *L, int idx) {
return burrow; return burrow;
} }
static void copyTiles(df::burrow *target, df::burrow *source, bool enable) {
CHECK_NULL_POINTER(target);
CHECK_NULL_POINTER(source);
if (source == target) {
if (!enable)
Burrows::clearTiles(target);
return;
}
vector<df::map_block*> pvec;
Burrows::listBlocks(&pvec, source);
for (auto block : pvec) {
auto smask = Burrows::getBlockMask(source, block);
if (!smask)
continue;
auto tmask = Burrows::getBlockMask(target, block, enable);
if (!tmask)
continue;
if (enable) {
for (int j = 0; j < 16; j++)
tmask->tile_bitmask[j] |= smask->tile_bitmask[j];
} else {
for (int j = 0; j < 16; j++)
tmask->tile_bitmask[j] &= ~smask->tile_bitmask[j];
if (!tmask->has_assignments())
Burrows::deleteBlockMask(target, block, tmask);
}
}
}
static void setTilesByDesignation(df::burrow *target, df::tile_designation d_mask,
df::tile_designation d_value, bool enable) {
CHECK_NULL_POINTER(target);
auto &blocks = world->map.map_blocks;
for (auto block : blocks) {
df::block_burrow *mask = NULL;
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
if ((block->designation[x][y].whole & d_mask.whole) != d_value.whole)
continue;
if (!mask)
mask = Burrows::getBlockMask(target, block, enable);
if (!mask)
goto next_block;
mask->setassignment(x, y, enable);
}
}
if (mask && !enable && !mask->has_assignments())
Burrows::deleteBlockMask(target, block, mask);
next_block:;
}
}
static bool setTilesByKeyword(df::burrow *target, std::string name, bool enable) {
CHECK_NULL_POINTER(target);
df::tile_designation mask;
df::tile_designation value;
if (name == "ABOVE_GROUND")
mask.bits.subterranean = true;
else if (name == "SUBTERRANEAN")
mask.bits.subterranean = value.bits.subterranean = true;
else if (name == "LIGHT")
mask.bits.light = value.bits.light = true;
else if (name == "DARK")
mask.bits.light = true;
else if (name == "OUTSIDE")
mask.bits.outside = value.bits.outside = true;
else if (name == "INSIDE")
mask.bits.outside = true;
else if (name == "HIDDEN")
mask.bits.hidden = value.bits.hidden = true;
else if (name == "REVEALED")
mask.bits.hidden = true;
else
return false;
setTilesByDesignation(target, mask, value, enable);
return true;
}
static void copyUnits(df::burrow *target, df::burrow *source, bool enable) {
CHECK_NULL_POINTER(target);
CHECK_NULL_POINTER(source);
if (source == target) {
if (!enable)
Burrows::clearUnits(target);
return;
}
for (size_t i = 0; i < source->units.size(); i++) {
if (auto unit = df::unit::find(source->units[i]))
Burrows::setAssignedUnit(target, unit, enable);
}
}
static int burrow_tiles_clear(lua_State *L) { static int burrow_tiles_clear(lua_State *L) {
color_ostream *out = Lua::GetOutput(L); color_ostream *out = Lua::GetOutput(L);
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_clear\n"); DEBUG(status,*out).print("entering burrow_tiles_clear\n");
int32_t count = 0;
lua_pushnil(L); // first key lua_pushnil(L); // first key
while (lua_next(L, 1)) { while (lua_next(L, 1)) {
df::burrow * burrow = get_burrow(L, -1); df::burrow * burrow = get_burrow(L, -1);
if (burrow) { if (burrow)
count += burrow->block_x.size();
Burrows::clearTiles(burrow); Burrows::clearTiles(burrow);
}
lua_pop(L, 1); // remove value, leave key lua_pop(L, 1); // remove value, leave key
} }
Lua::Push(L, count); return 0;
return 1; }
static void tiles_set_add_remove(lua_State *L, bool do_set, bool enable) {
df::burrow *target = get_burrow(L, 1);
if (!target) {
luaL_argerror(L, 1, "invalid burrow specifier or burrow not found");
return;
}
if (do_set)
Burrows::clearTiles(target);
lua_pushnil(L); // first key
while (lua_next(L, 2)) {
if (!lua_isstring(L, -1) || !setTilesByKeyword(target, luaL_checkstring(L, -1), enable)) {
if (auto burrow = get_burrow(L, -1))
copyTiles(target, burrow, enable);
}
lua_pop(L, 1); // remove value, leave key
}
} }
static int burrow_tiles_set(lua_State *L) { static int burrow_tiles_set(lua_State *L) {
@ -258,7 +386,7 @@ static int burrow_tiles_set(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_set\n"); DEBUG(status,*out).print("entering burrow_tiles_set\n");
// TODO tiles_set_add_remove(L, true, true);
return 0; return 0;
} }
@ -267,7 +395,7 @@ static int burrow_tiles_add(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_add\n"); DEBUG(status,*out).print("entering burrow_tiles_add\n");
// TODO tiles_set_add_remove(L, false, true);
return 0; return 0;
} }
@ -276,46 +404,31 @@ static int burrow_tiles_remove(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_remove\n"); DEBUG(status,*out).print("entering burrow_tiles_remove\n");
// TODO tiles_set_add_remove(L, false, false);
return 0; return 0;
} }
static int box_fill(lua_State *L, bool enable) { static void box_fill(lua_State *L, bool enable) {
df::coord pos_start, pos_end;
bool dry_run = false, zlevel = false;
df::burrow *burrow = get_burrow(L, 1); df::burrow *burrow = get_burrow(L, 1);
if (!burrow) { if (!burrow) {
luaL_argerror(L, 1, "invalid burrow specifier or burrow not found"); luaL_argerror(L, 1, "invalid burrow specifier or burrow not found");
return 0; return;
} }
df::coord pos_start, pos_end;
if (!get_bounds(L, 2, pos_start, pos_end)) { if (!get_bounds(L, 2, pos_start, pos_end)) {
luaL_argerror(L, 2, "invalid box bounds"); luaL_argerror(L, 2, "invalid box bounds");
return 0; return;
}
get_opts(L, 3, dry_run, zlevel);
if (zlevel) {
pos_start.z = *window_z;
pos_end.z = *window_z;
} }
int32_t count = 0;
for (int32_t z = pos_start.z; z <= pos_end.z; ++z) { for (int32_t z = pos_start.z; z <= pos_end.z; ++z) {
for (int32_t y = pos_start.y; y <= pos_end.y; ++y) { for (int32_t y = pos_start.y; y <= pos_end.y; ++y) {
for (int32_t x = pos_start.x; x <= pos_end.x; ++x) { for (int32_t x = pos_start.x; x <= pos_end.x; ++x) {
df::coord pos(x, y, z); df::coord pos(x, y, z);
if (enable != Burrows::isAssignedTile(burrow, pos)) Burrows::setAssignedTile(burrow, pos, enable);
++count;
if (!dry_run)
Burrows::setAssignedTile(burrow, pos, enable);
} }
} }
} }
Lua::Push(L, count);
return 1;
} }
static int burrow_tiles_box_add(lua_State *L) { static int burrow_tiles_box_add(lua_State *L) {
@ -323,7 +436,8 @@ static int burrow_tiles_box_add(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_box_add\n"); DEBUG(status,*out).print("entering burrow_tiles_box_add\n");
return box_fill(L, true); box_fill(L, true);
return 0;
} }
static int burrow_tiles_box_remove(lua_State *L) { static int burrow_tiles_box_remove(lua_State *L) {
@ -331,32 +445,45 @@ static int burrow_tiles_box_remove(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_box_remove\n"); DEBUG(status,*out).print("entering burrow_tiles_box_remove\n");
return box_fill(L, false); box_fill(L, false);
return 0;
}
// ramp tops inherit walkability group of the tile below
static uint16_t get_walk_group(const df::coord & pos) {
uint16_t walk = Maps::getWalkableGroup(pos);
if (walk)
return walk;
if (auto tt = Maps::getTileType(pos)) {
if (tileShape(*tt) == df::tiletype_shape::RAMP_TOP) {
df::coord pos_below(pos);
--pos_below.z;
walk = Maps::getWalkableGroup(pos_below);
}
}
return walk;
} }
static int flood_fill(lua_State *L, bool enable) { static void flood_fill(lua_State *L, bool enable) {
df::coord start_pos; df::coord start_pos;
bool dry_run = false, zlevel = false; bool zlevel = false;
df::burrow *burrow = get_burrow(L, 1); df::burrow *burrow = get_burrow(L, 1);
if (!burrow) { if (!burrow) {
luaL_argerror(L, 1, "invalid burrow specifier or burrow not found"); luaL_argerror(L, 1, "invalid burrow specifier or burrow not found");
return 0; return;
} }
Lua::CheckDFAssign(L, &start_pos, 2); Lua::CheckDFAssign(L, &start_pos, 2);
get_opts(L, 3, dry_run, zlevel); get_opts(L, 3, zlevel);
// record properties to match
df::tile_designation *start_des = Maps::getTileDesignation(start_pos); df::tile_designation *start_des = Maps::getTileDesignation(start_pos);
if (!start_des) { if (!start_des) {
luaL_argerror(L, 2, "invalid starting coordinates"); luaL_argerror(L, 2, "invalid starting coordinates");
return 0; return;
} }
uint16_t start_walk = Maps::getWalkableGroup(start_pos); uint16_t start_walk = Maps::getWalkableGroup(start_pos);
int32_t count = 0;
std::stack<df::coord> flood; std::stack<df::coord> flood;
flood.emplace(start_pos); flood.emplace(start_pos);
@ -372,18 +499,17 @@ static int flood_fill(lua_State *L, bool enable) {
continue; continue;
} }
if (!start_walk && Maps::getWalkableGroup(pos)) uint16_t walk = get_walk_group(pos);
if (!start_walk && walk)
continue; continue;
if (pos != start_pos && enable == Burrows::isAssignedTile(burrow, pos)) if (pos != start_pos && enable == Burrows::isAssignedTile(burrow, pos))
continue; continue;
++count; Burrows::setAssignedTile(burrow, pos, enable);
if (!dry_run)
Burrows::setAssignedTile(burrow, pos, enable);
// only go one tile outside of a walkability group // only go one tile outside of a walkability group
if (start_walk && start_walk != Maps::getWalkableGroup(pos)) if (start_walk && start_walk != walk)
continue; continue;
flood.emplace(pos.x-1, pos.y-1, pos.z); flood.emplace(pos.x-1, pos.y-1, pos.z);
@ -406,9 +532,6 @@ static int flood_fill(lua_State *L, bool enable) {
flood.emplace(pos.x, pos.y, pos.z-1); flood.emplace(pos.x, pos.y, pos.z-1);
} }
} }
Lua::Push(L, count);
return 1;
} }
static int burrow_tiles_flood_add(lua_State *L) { static int burrow_tiles_flood_add(lua_State *L) {
@ -416,7 +539,8 @@ static int burrow_tiles_flood_add(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_flood_add\n"); DEBUG(status,*out).print("entering burrow_tiles_flood_add\n");
return flood_fill(L, true); flood_fill(L, true);
return 0;
} }
static int burrow_tiles_flood_remove(lua_State *L) { static int burrow_tiles_flood_remove(lua_State *L) {
@ -424,7 +548,8 @@ static int burrow_tiles_flood_remove(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_tiles_flood_remove\n"); DEBUG(status,*out).print("entering burrow_tiles_flood_remove\n");
return flood_fill(L, false); flood_fill(L, false);
return 0;
} }
static int burrow_units_clear(lua_State *L) { static int burrow_units_clear(lua_State *L) {
@ -432,8 +557,38 @@ static int burrow_units_clear(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_units_clear\n"); DEBUG(status,*out).print("entering burrow_units_clear\n");
// TODO
return 0; int32_t count = 0;
lua_pushnil(L); // first key
while (lua_next(L, 1)) {
df::burrow * burrow = get_burrow(L, -1);
if (burrow) {
count += burrow->units.size();
Burrows::clearUnits(burrow);
}
lua_pop(L, 1); // remove value, leave key
}
Lua::Push(L, count);
return 1;
}
static void units_set_add_remove(lua_State *L, bool do_set, bool enable) {
df::burrow *target = get_burrow(L, 1);
if (!target) {
luaL_argerror(L, 1, "invalid burrow specifier or burrow not found");
return;
}
if (do_set)
Burrows::clearUnits(target);
lua_pushnil(L); // first key
while (lua_next(L, 2)) {
if (auto burrow = get_burrow(L, -1))
copyUnits(target, burrow, enable);
lua_pop(L, 1); // remove value, leave key
}
} }
static int burrow_units_set(lua_State *L) { static int burrow_units_set(lua_State *L) {
@ -441,7 +596,7 @@ static int burrow_units_set(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_units_set\n"); DEBUG(status,*out).print("entering burrow_units_set\n");
// TODO units_set_add_remove(L, true, true);
return 0; return 0;
} }
@ -450,7 +605,7 @@ static int burrow_units_add(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_units_add\n"); DEBUG(status,*out).print("entering burrow_units_add\n");
// TODO units_set_add_remove(L, false, true);
return 0; return 0;
} }
@ -459,7 +614,7 @@ static int burrow_units_remove(lua_State *L) {
if (!out) if (!out)
out = &Core::getInstance().getConsole(); out = &Core::getInstance().getConsole();
DEBUG(status,*out).print("entering burrow_units_remove\n"); DEBUG(status,*out).print("entering burrow_units_remove\n");
// TODO units_set_add_remove(L, false, false);
return 0; return 0;
} }
@ -480,17 +635,7 @@ DFHACK_PLUGIN_LUA_COMMANDS {
}; };
/* /*
#include "Core.h" #include "Core.h"
#include "Console.h" #include "Console.h"
#include "Export.h" #include "Export.h"
@ -892,136 +1037,6 @@ static df::burrow *findByName(color_ostream &out, std::string name, bool silent
return rv; return rv;
} }
static void copyUnits(df::burrow *target, df::burrow *source, bool enable)
{
CHECK_NULL_POINTER(target);
CHECK_NULL_POINTER(source);
if (source == target)
{
if (!enable)
Burrows::clearUnits(target);
return;
}
for (size_t i = 0; i < source->units.size(); i++)
{
auto unit = df::unit::find(source->units[i]);
if (unit)
Burrows::setAssignedUnit(target, unit, enable);
}
}
static void copyTiles(df::burrow *target, df::burrow *source, bool enable)
{
CHECK_NULL_POINTER(target);
CHECK_NULL_POINTER(source);
if (source == target)
{
if (!enable)
Burrows::clearTiles(target);
return;
}
std::vector<df::map_block*> pvec;
Burrows::listBlocks(&pvec, source);
for (size_t i = 0; i < pvec.size(); i++)
{
auto block = pvec[i];
auto smask = Burrows::getBlockMask(source, block);
if (!smask)
continue;
auto tmask = Burrows::getBlockMask(target, block, enable);
if (!tmask)
continue;
if (enable)
{
for (int j = 0; j < 16; j++)
tmask->tile_bitmask[j] |= smask->tile_bitmask[j];
}
else
{
for (int j = 0; j < 16; j++)
tmask->tile_bitmask[j] &= ~smask->tile_bitmask[j];
if (!tmask->has_assignments())
Burrows::deleteBlockMask(target, block, tmask);
}
}
}
static void setTilesByDesignation(df::burrow *target, df::tile_designation d_mask,
df::tile_designation d_value, bool enable)
{
CHECK_NULL_POINTER(target);
auto &blocks = world->map.map_blocks;
for (size_t i = 0; i < blocks.size(); i++)
{
auto block = blocks[i];
df::block_burrow *mask = NULL;
for (int x = 0; x < 16; x++)
{
for (int y = 0; y < 16; y++)
{
if ((block->designation[x][y].whole & d_mask.whole) != d_value.whole)
continue;
if (!mask)
mask = Burrows::getBlockMask(target, block, enable);
if (!mask)
goto next_block;
mask->setassignment(x, y, enable);
}
}
if (mask && !enable && !mask->has_assignments())
Burrows::deleteBlockMask(target, block, mask);
next_block:;
}
}
static bool setTilesByKeyword(df::burrow *target, std::string name, bool enable)
{
CHECK_NULL_POINTER(target);
df::tile_designation mask;
df::tile_designation value;
if (name == "ABOVE_GROUND")
mask.bits.subterranean = true;
else if (name == "SUBTERRANEAN")
mask.bits.subterranean = value.bits.subterranean = true;
else if (name == "LIGHT")
mask.bits.light = value.bits.light = true;
else if (name == "DARK")
mask.bits.light = true;
else if (name == "OUTSIDE")
mask.bits.outside = value.bits.outside = true;
else if (name == "INSIDE")
mask.bits.outside = true;
else if (name == "HIDDEN")
mask.bits.hidden = value.bits.hidden = true;
else if (name == "REVEALED")
mask.bits.hidden = true;
else
return false;
setTilesByDesignation(target, mask, value, enable);
return true;
}
DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(renameBurrow), DFHACK_LUA_FUNCTION(renameBurrow),
DFHACK_LUA_FUNCTION(findByName), DFHACK_LUA_FUNCTION(findByName),
@ -1037,121 +1052,4 @@ DFHACK_PLUGIN_LUA_EVENTS {
DFHACK_LUA_END DFHACK_LUA_END
}; };
static command_result burrow(color_ostream &out, vector <string> &parameters)
{
CoreSuspender suspend;
if (!active)
{
out.printerr("The plugin cannot be used without map.\n");
return CR_FAILURE;
}
string cmd;
if (!parameters.empty())
cmd = parameters[0];
if (cmd == "enable" || cmd == "disable")
{
if (parameters.size() < 2)
return CR_WRONG_USAGE;
bool state = (cmd == "enable");
for (size_t i = 1; i < parameters.size(); i++)
{
string &option = parameters[i];
if (option == "auto-grow")
enable_auto_grow(out, state);
else
return CR_WRONG_USAGE;
}
}
else if (cmd == "clear-units")
{
if (parameters.size() < 2)
return CR_WRONG_USAGE;
for (size_t i = 1; i < parameters.size(); i++)
{
auto target = findByName(out, parameters[i]);
if (!target)
return CR_WRONG_USAGE;
Burrows::clearUnits(target);
}
}
else if (cmd == "set-units" || cmd == "add-units" || cmd == "remove-units")
{
if (parameters.size() < 3)
return CR_WRONG_USAGE;
auto target = findByName(out, parameters[1]);
if (!target)
return CR_WRONG_USAGE;
if (cmd == "set-units")
Burrows::clearUnits(target);
bool enable = (cmd != "remove-units");
for (size_t i = 2; i < parameters.size(); i++)
{
auto source = findByName(out, parameters[i]);
if (!source)
return CR_WRONG_USAGE;
copyUnits(target, source, enable);
}
}
else if (cmd == "clear-tiles")
{
if (parameters.size() < 2)
return CR_WRONG_USAGE;
for (size_t i = 1; i < parameters.size(); i++)
{
auto target = findByName(out, parameters[i]);
if (!target)
return CR_WRONG_USAGE;
Burrows::clearTiles(target);
}
}
else if (cmd == "set-tiles" || cmd == "add-tiles" || cmd == "remove-tiles")
{
if (parameters.size() < 3)
return CR_WRONG_USAGE;
auto target = findByName(out, parameters[1]);
if (!target)
return CR_WRONG_USAGE;
if (cmd == "set-tiles")
Burrows::clearTiles(target);
bool enable = (cmd != "remove-tiles");
for (size_t i = 2; i < parameters.size(); i++)
{
if (setTilesByKeyword(target, parameters[i], enable))
continue;
auto source = findByName(out, parameters[i]);
if (!source)
return CR_WRONG_USAGE;
copyTiles(target, source, enable);
}
}
else
{
if (!parameters.empty() && cmd != "?")
out.printerr("Invalid command: %s\n", cmd.c_str());
return CR_WRONG_USAGE;
}
return CR_OK;
}
*/ */

@ -9,6 +9,7 @@ local _ENV = mkmodule('plugins.burrow')
--]] --]]
local argparse = require('argparse')
local overlay = require('plugins.overlay') local overlay = require('plugins.overlay')
local widgets = require('gui.widgets') local widgets = require('gui.widgets')
@ -164,9 +165,9 @@ rawset_default(_ENV, dfhack.burrows)
-- commandline handling -- commandline handling
-- --
local function set_add_remove(mode, which, params, opts) local function set_add_remove(mode, which, params, _)
local target_burrow = table.remove(params, 1) local target_burrow = table.remove(params, 1)
return _ENV[('burrow_%s_%s'):format(mode, which)](target_burrow, params, opts) _ENV[('burrow_%s_%s'):format(mode, which)](target_burrow, params)
end end
local function tiles_box_add_remove(which, params, opts) local function tiles_box_add_remove(which, params, opts)
@ -174,39 +175,40 @@ local function tiles_box_add_remove(which, params, opts)
local pos1 = argparse.coords(params[1] or 'here', 'pos') local pos1 = argparse.coords(params[1] or 'here', 'pos')
local pos2 = opts.cursor or argparse.coords(params[2] or 'here', 'pos') local pos2 = opts.cursor or argparse.coords(params[2] or 'here', 'pos')
local bounds = get_bounds(pos1, pos2) local bounds = get_bounds(pos1, pos2)
return _ENV['burrow_tiles_box_'..which](target_burrow, bounds, opts) _ENV['burrow_tiles_box_'..which](target_burrow, bounds)
end end
local function tiles_flood_add_remove(which, params, opts) local function tiles_flood_add_remove(which, params, opts)
local target_burrow = table.remove(params, 1) local target_burrow = table.remove(params, 1)
local pos = opts.cursor or argparse.coords('here', 'pos') local pos = opts.cursor or argparse.coords('here', 'pos')
return _ENV['burrow_tiles_flood_'..which](target_burrow, pos, opts) _ENV['burrow_tiles_flood_'..which](target_burrow, pos, opts)
end end
local function run_command(mode, command, params, opts) local function run_command(mode, command, params, opts)
if mode == 'tiles' then if mode == 'tiles' then
if command == 'clear' then if command == 'clear' then
return burrow_tiles_clear(params, opts) burrow_tiles_clear(params)
elseif command == 'set' or command == 'add' or command == 'remove' then elseif command == 'set' or command == 'add' or command == 'remove' then
return set_add_remove('tiles', command, params, opts) set_add_remove('tiles', command, params, opts)
elseif command == 'box-add' or command == 'box-remove' then elseif command == 'box-add' or command == 'box-remove' then
return tiles_box_add_remove(command:sub(5), params, opts) tiles_box_add_remove(command:sub(5), params, opts)
elseif command == 'flood-add' or command == 'flood-remove' then elseif command == 'flood-add' or command == 'flood-remove' then
return tiles_flood_add_remove(command:sub(7), params, opts) tiles_flood_add_remove(command:sub(7), params, opts)
else else
return false return false
end end
elseif mode == 'units' then elseif mode == 'units' then
if command == 'clear' then if command == 'clear' then
return burrow_units_clear(params) burrow_units_clear(params)
elseif command == 'set' or command == 'add' or command == 'remove' then elseif command == 'set' or command == 'add' or command == 'remove' then
return set_add_remove('units', command, params, opts) set_add_remove('units', command, params, opts)
else else
return false return false
end end
else else
return false return false
end end
return true
end end
function parse_commandline(...) function parse_commandline(...)
@ -219,7 +221,6 @@ function parse_commandline(...)
local positionals = argparse.processArgsGetopt(args, { local positionals = argparse.processArgsGetopt(args, {
{'c', 'cursor', hasArg=true, {'c', 'cursor', hasArg=true,
handler=function(optarg) opts.cursor = argparse.coords(optarg, 'cursor') end}, handler=function(optarg) opts.cursor = argparse.coords(optarg, 'cursor') end},
{'d', 'dry-run', handler=function() opts.dry_run = true end},
{'h', 'help', handler=function() opts.help = true end}, {'h', 'help', handler=function() opts.help = true end},
{'z', 'cur-zlevel', handler=function() opts.zlevel = true end}, {'z', 'cur-zlevel', handler=function() opts.zlevel = true end},
}) })
@ -234,7 +235,7 @@ function parse_commandline(...)
if not ret then return false end if not ret then return false end
print(('%d %s affected'):format(ret, mode)) print('done')
return true return true
end end