merged stuff from peterix
parent
9f95e67c75
commit
cf0d45be78
@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
IF EXIST DF_PATH.txt SET /P _DF_PATH=<DF_PATH.txt
|
||||||
|
IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
|
||||||
|
mkdir VC2010
|
||||||
|
cd VC2010
|
||||||
|
echo generating a build folder
|
||||||
|
for /f "delims=" %%a in ('DATE /T') do @set myvar=breakfast-%%a
|
||||||
|
cmake ..\.. -G"Visual Studio 10" -DDFHACK_RELEASE="%myvar%" -DCMAKE_INSTALL_PREFIX="%_DF_PATH%" -DBUILD_DEVEL=1 -DBUILD_DEV_PLUGINS=1 -DBUILD_DF2MC=1 -DBUILD_DFUSION=1 -DBUILD_STONESENSE=1 -DBUILD_SERVER=1
|
@ -1,396 +0,0 @@
|
|||||||
/*
|
|
||||||
https://github.com/peterix/dfhack
|
|
||||||
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any
|
|
||||||
damages arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any
|
|
||||||
purpose, including commercial applications, and to alter it and
|
|
||||||
redistribute it freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must
|
|
||||||
not claim that you wrote the original software. If you use this
|
|
||||||
software in a product, an acknowledgment in the product documentation
|
|
||||||
would be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and
|
|
||||||
must not be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Internal.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "MemAccess.h"
|
|
||||||
#include "Core.h"
|
|
||||||
#include "VersionInfo.h"
|
|
||||||
#include "tinythread.h"
|
|
||||||
// must be last due to MS stupidity
|
|
||||||
#include "DataDefs.h"
|
|
||||||
#include "DataIdentity.h"
|
|
||||||
|
|
||||||
#include "MiscUtils.h"
|
|
||||||
|
|
||||||
using namespace DFHack;
|
|
||||||
|
|
||||||
|
|
||||||
void *type_identity::do_allocate_pod() {
|
|
||||||
void *p = malloc(size);
|
|
||||||
memset(p, 0, size);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_identity::do_copy_pod(void *tgt, const void *src) {
|
|
||||||
memmove(tgt, src, size);
|
|
||||||
};
|
|
||||||
|
|
||||||
bool type_identity::do_destroy_pod(void *obj) {
|
|
||||||
free(obj);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *type_identity::allocate() {
|
|
||||||
if (can_allocate())
|
|
||||||
return do_allocate();
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool type_identity::copy(void *tgt, const void *src) {
|
|
||||||
if (can_allocate() && tgt && src)
|
|
||||||
{
|
|
||||||
do_copy(tgt, src);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool type_identity::destroy(void *obj) {
|
|
||||||
if (can_allocate() && obj)
|
|
||||||
return do_destroy(obj);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *enum_identity::do_allocate() {
|
|
||||||
void *p = malloc(byte_size());
|
|
||||||
memcpy(p, &first_item_value, std::min(byte_size(), sizeof(int64_t)));
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The order of global object constructor calls is
|
|
||||||
* undefined between compilation units. Therefore,
|
|
||||||
* this list has to be plain data, so that it gets
|
|
||||||
* initialized by the loader in the initial mmap.
|
|
||||||
*/
|
|
||||||
compound_identity *compound_identity::list = NULL;
|
|
||||||
std::vector<compound_identity*> compound_identity::top_scope;
|
|
||||||
|
|
||||||
compound_identity::compound_identity(size_t size, TAllocateFn alloc,
|
|
||||||
compound_identity *scope_parent, const char *dfhack_name)
|
|
||||||
: constructed_identity(size, alloc), scope_parent(scope_parent), dfhack_name(dfhack_name)
|
|
||||||
{
|
|
||||||
next = list; list = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void compound_identity::doInit(Core *)
|
|
||||||
{
|
|
||||||
if (scope_parent)
|
|
||||||
scope_parent->scope_children.push_back(this);
|
|
||||||
else
|
|
||||||
top_scope.push_back(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string compound_identity::getFullName()
|
|
||||||
{
|
|
||||||
if (scope_parent)
|
|
||||||
return scope_parent->getFullName() + "." + getName();
|
|
||||||
else
|
|
||||||
return getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
static tthread::mutex *known_mutex = NULL;
|
|
||||||
|
|
||||||
void compound_identity::Init(Core *core)
|
|
||||||
{
|
|
||||||
if (!known_mutex)
|
|
||||||
known_mutex = new tthread::mutex();
|
|
||||||
|
|
||||||
// This cannot be done in the constructors, because
|
|
||||||
// they are called in an undefined order.
|
|
||||||
for (compound_identity *p = list; p; p = p->next)
|
|
||||||
p->doInit(core);
|
|
||||||
|
|
||||||
//FIXME: ... nuked. the group was empty...
|
|
||||||
/*
|
|
||||||
// Read pre-filled vtable ptrs
|
|
||||||
OffsetGroup *ptr_table = core->vinfo->getGroup("vtable");
|
|
||||||
for (virtual_identity *p = list; p; p = p->next) {
|
|
||||||
void * tmp;
|
|
||||||
if (ptr_table->getSafeAddress(p->getName(),tmp))
|
|
||||||
p->vtable_ptr = tmp;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
bitfield_identity::bitfield_identity(size_t size,
|
|
||||||
compound_identity *scope_parent, const char *dfhack_name,
|
|
||||||
int num_bits, const bitfield_item_info *bits)
|
|
||||||
: compound_identity(size, NULL, scope_parent, dfhack_name), bits(bits), num_bits(num_bits)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
enum_identity::enum_identity(size_t size,
|
|
||||||
compound_identity *scope_parent, const char *dfhack_name,
|
|
||||||
type_identity *base_type,
|
|
||||||
int64_t first_item_value, int64_t last_item_value,
|
|
||||||
const char *const *keys,
|
|
||||||
const void *attrs, struct_identity *attr_type)
|
|
||||||
: compound_identity(size, NULL, scope_parent, dfhack_name),
|
|
||||||
first_item_value(first_item_value), last_item_value(last_item_value),
|
|
||||||
keys(keys), base_type(base_type), attrs(attrs), attr_type(attr_type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
struct_identity::struct_identity(size_t size, TAllocateFn alloc,
|
|
||||||
compound_identity *scope_parent, const char *dfhack_name,
|
|
||||||
struct_identity *parent, const struct_field_info *fields)
|
|
||||||
: compound_identity(size, alloc, scope_parent, dfhack_name),
|
|
||||||
parent(parent), has_children(false), fields(fields)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void struct_identity::doInit(Core *core)
|
|
||||||
{
|
|
||||||
compound_identity::doInit(core);
|
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
parent->children.push_back(this);
|
|
||||||
parent->has_children = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool struct_identity::is_subclass(struct_identity *actual)
|
|
||||||
{
|
|
||||||
if (!has_children && actual != this)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (; actual; actual = actual->getParent())
|
|
||||||
if (actual == this) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pointer_identity::getFullName()
|
|
||||||
{
|
|
||||||
return (target ? target->getFullName() : std::string("void")) + "*";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string container_identity::getFullName(type_identity *item)
|
|
||||||
{
|
|
||||||
return "<" + (item ? item->getFullName() : std::string("void")) + ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ptr_container_identity::getFullName(type_identity *item)
|
|
||||||
{
|
|
||||||
return "<" + (item ? item->getFullName() : std::string("void")) + "*>";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string bit_container_identity::getFullName(type_identity *)
|
|
||||||
{
|
|
||||||
return "<bool>";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string df::buffer_container_identity::getFullName(type_identity *item)
|
|
||||||
{
|
|
||||||
return (item ? item->getFullName() : std::string("void")) +
|
|
||||||
(size > 0 ? stl_sprintf("[%d]", size) : std::string("[]"));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual_identity::virtual_identity(size_t size, TAllocateFn alloc,
|
|
||||||
const char *dfhack_name, const char *original_name,
|
|
||||||
virtual_identity *parent, const struct_field_info *fields)
|
|
||||||
: struct_identity(size, alloc, NULL, dfhack_name, parent, fields), original_name(original_name),
|
|
||||||
vtable_ptr(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::map<std::string, virtual_identity*> name_lookup;
|
|
||||||
|
|
||||||
void virtual_identity::doInit(Core *core)
|
|
||||||
{
|
|
||||||
struct_identity::doInit(core);
|
|
||||||
|
|
||||||
name_lookup[getOriginalName()] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Vtable to identity lookup. */
|
|
||||||
std::map<void*, virtual_identity*> virtual_identity::known;
|
|
||||||
|
|
||||||
virtual_identity *virtual_identity::get(virtual_ptr instance_ptr)
|
|
||||||
{
|
|
||||||
if (!instance_ptr) return NULL;
|
|
||||||
|
|
||||||
// Actually, a reader/writer lock would be sufficient,
|
|
||||||
// since the table is only written once per class.
|
|
||||||
tthread::lock_guard<tthread::mutex> lock(*known_mutex);
|
|
||||||
|
|
||||||
void *vtable = get_vtable(instance_ptr);
|
|
||||||
std::map<void*, virtual_identity*>::iterator it = known.find(vtable);
|
|
||||||
|
|
||||||
if (it != known.end())
|
|
||||||
return it->second;
|
|
||||||
|
|
||||||
// If using a reader/writer lock, re-grab as write here, and recheck
|
|
||||||
Core &core = Core::getInstance();
|
|
||||||
std::string name = core.p->doReadClassName(vtable);
|
|
||||||
|
|
||||||
virtual_identity *actual = NULL;
|
|
||||||
|
|
||||||
auto name_it = name_lookup.find(name);
|
|
||||||
if (name_it != name_lookup.end()) {
|
|
||||||
virtual_identity *p = name_it->second;
|
|
||||||
|
|
||||||
if (p->vtable_ptr && p->vtable_ptr != vtable) {
|
|
||||||
std::cerr << "Conflicting vtable ptr for class '" << p->getName()
|
|
||||||
<< "': found 0x" << std::hex << unsigned(vtable)
|
|
||||||
<< ", previous 0x" << unsigned(p->vtable_ptr) << std::dec << std::endl;
|
|
||||||
abort();
|
|
||||||
} else if (!p->vtable_ptr) {
|
|
||||||
std::cerr << "class '" << p->getName() << "': vtable = 0x"
|
|
||||||
<< std::hex << unsigned(vtable) << std::dec << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
known[vtable] = p;
|
|
||||||
p->vtable_ptr = vtable;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cerr << "UNKNOWN CLASS '" << name << "': vtable = 0x"
|
|
||||||
<< std::hex << unsigned(vtable) << std::dec << std::endl;
|
|
||||||
|
|
||||||
known[vtable] = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void virtual_identity::adjust_vtable(virtual_ptr obj, virtual_identity *main)
|
|
||||||
{
|
|
||||||
if (vtable_ptr) {
|
|
||||||
*(void**)obj = vtable_ptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (main && main != this && is_subclass(main))
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::cerr << "Attempt to create class '" << getName() << "' without known vtable." << std::endl;
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual_ptr virtual_identity::clone(virtual_ptr obj)
|
|
||||||
{
|
|
||||||
virtual_identity *id = get(obj);
|
|
||||||
if (!id) return NULL;
|
|
||||||
virtual_ptr copy = id->instantiate();
|
|
||||||
if (!copy) return NULL;
|
|
||||||
id->do_copy(copy, obj);
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DFHack::findBitfieldField(unsigned *idx, const std::string &name,
|
|
||||||
unsigned size, const bitfield_item_info *items)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < size; i++) {
|
|
||||||
if (items[i].name && items[i].name == name)
|
|
||||||
{
|
|
||||||
*idx = i;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DFHack::setBitfieldField(void *p, unsigned idx, unsigned size, int value)
|
|
||||||
{
|
|
||||||
uint8_t *data = ((uint8_t*)p) + (idx/8);
|
|
||||||
unsigned shift = idx%8;
|
|
||||||
uint32_t mask = ((1<<size)-1) << shift;
|
|
||||||
uint32_t vmask = ((value << shift) & mask);
|
|
||||||
|
|
||||||
#define ACCESS(type) *(type*)data = type((*(type*)data & ~mask) | vmask)
|
|
||||||
|
|
||||||
if (!(mask & ~0xFFU)) ACCESS(uint8_t);
|
|
||||||
else if (!(mask & ~0xFFFFU)) ACCESS(uint16_t);
|
|
||||||
else ACCESS(uint32_t);
|
|
||||||
|
|
||||||
#undef ACCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
int DFHack::getBitfieldField(const void *p, unsigned idx, unsigned size)
|
|
||||||
{
|
|
||||||
const uint8_t *data = ((const uint8_t*)p) + (idx/8);
|
|
||||||
unsigned shift = idx%8;
|
|
||||||
uint32_t mask = ((1<<size)-1) << shift;
|
|
||||||
|
|
||||||
#define ACCESS(type) return int((*(type*)data & mask) >> shift)
|
|
||||||
|
|
||||||
if (!(mask & ~0xFFU)) ACCESS(uint8_t);
|
|
||||||
else if (!(mask & ~0xFFFFU)) ACCESS(uint16_t);
|
|
||||||
else ACCESS(uint32_t);
|
|
||||||
|
|
||||||
#undef ACCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
void DFHack::bitfieldToString(std::vector<std::string> *pvec, const void *p,
|
|
||||||
unsigned size, const bitfield_item_info *items)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < size; i++) {
|
|
||||||
int value = getBitfieldField(p, i, std::min(1,items[i].size));
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
std::string name = format_key(items[i].name, i);
|
|
||||||
|
|
||||||
if (items[i].size > 1)
|
|
||||||
name += stl_sprintf("=%u", value);
|
|
||||||
|
|
||||||
pvec->push_back(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items[i].size > 1)
|
|
||||||
i += items[i].size-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int DFHack::findEnumItem(const std::string &name, int size, const char *const *items)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
if (items[i] && items[i] == name)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DFHack::flagarrayToString(std::vector<std::string> *pvec, const void *p,
|
|
||||||
int bytes, int base, int size, const char *const *items)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < bytes*8; i++) {
|
|
||||||
int value = getBitfieldField(p, i, 1);
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
int ridx = int(i) - base;
|
|
||||||
const char *name = (ridx >= 0 && ridx < size) ? items[ridx] : NULL;
|
|
||||||
pvec->push_back(format_key(name, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,678 @@
|
|||||||
|
#include "Core.h"
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Export.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
#include "Error.h"
|
||||||
|
|
||||||
|
#include "DataFuncs.h"
|
||||||
|
|
||||||
|
#include "modules/Gui.h"
|
||||||
|
#include "modules/Job.h"
|
||||||
|
#include "modules/Maps.h"
|
||||||
|
#include "modules/MapCache.h"
|
||||||
|
#include "modules/World.h"
|
||||||
|
#include "modules/Units.h"
|
||||||
|
#include "TileTypes.h"
|
||||||
|
|
||||||
|
#include "DataDefs.h"
|
||||||
|
#include "df/ui.h"
|
||||||
|
#include "df/world.h"
|
||||||
|
#include "df/unit.h"
|
||||||
|
#include "df/burrow.h"
|
||||||
|
#include "df/map_block.h"
|
||||||
|
#include "df/block_burrow.h"
|
||||||
|
#include "df/job.h"
|
||||||
|
#include "df/job_list_link.h"
|
||||||
|
|
||||||
|
#include "MiscUtils.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
using std::string;
|
||||||
|
using std::endl;
|
||||||
|
using namespace DFHack;
|
||||||
|
using namespace df::enums;
|
||||||
|
using namespace dfproto;
|
||||||
|
|
||||||
|
using df::global::ui;
|
||||||
|
using df::global::world;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static command_result burrow(color_ostream &out, vector <string> & parameters);
|
||||||
|
|
||||||
|
DFHACK_PLUGIN("burrows");
|
||||||
|
|
||||||
|
static void init_map(color_ostream &out);
|
||||||
|
static void deinit_map(color_ostream &out);
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
|
||||||
|
{
|
||||||
|
commands.push_back(PluginCommand(
|
||||||
|
"burrow", "Miscellaneous burrow control.", burrow, false,
|
||||||
|
" burrow enable options...\n"
|
||||||
|
" burrow disable options...\n"
|
||||||
|
" Enable or disable features of the plugin.\n"
|
||||||
|
" See below for a list and explanation.\n"
|
||||||
|
" burrow clear-units burrow burrow...\n"
|
||||||
|
" burrow clear-tiles burrow burrow...\n"
|
||||||
|
" Removes all units or tiles from the burrows.\n"
|
||||||
|
" burrow set-units target-burrow src-burrow...\n"
|
||||||
|
" burrow add-units target-burrow src-burrow...\n"
|
||||||
|
" burrow remove-units target-burrow src-burrow...\n"
|
||||||
|
" Adds or removes units in source burrows to/from the target\n"
|
||||||
|
" burrow. Set is equivalent to clear and add.\n"
|
||||||
|
" burrow set-tiles target-burrow src-burrow...\n"
|
||||||
|
" burrow add-tiles target-burrow src-burrow...\n"
|
||||||
|
" burrow remove-tiles target-burrow src-burrow...\n"
|
||||||
|
" Adds or removes tiles in source burrows to/from the target\n"
|
||||||
|
" burrow. In place of a source burrow it is possible to use\n"
|
||||||
|
" one of the following keywords:\n"
|
||||||
|
" ABOVE_GROUND, SUBTERRANEAN, INSIDE, OUTSIDE,\n"
|
||||||
|
" LIGHT, DARK, HIDDEN, REVEALED\n"
|
||||||
|
"Implemented features:\n"
|
||||||
|
" auto-grow\n"
|
||||||
|
" When a wall inside a burrow with a name ending in '+' is dug\n"
|
||||||
|
" out, the burrow is extended to newly-revealed adjacent walls.\n"
|
||||||
|
" This final '+' may be omitted in burrow name args of commands above.\n"
|
||||||
|
" Note: Digging 1-wide corridors with the miner inside the burrow is SLOW.\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
if (Core::getInstance().isMapLoaded())
|
||||||
|
init_map(out);
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
|
||||||
|
{
|
||||||
|
deinit_map(out);
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case SC_MAP_LOADED:
|
||||||
|
deinit_map(out);
|
||||||
|
if (df::global::game_mode &&
|
||||||
|
*df::global::game_mode == GAMEMODE_DWARF)
|
||||||
|
init_map(out);
|
||||||
|
break;
|
||||||
|
case SC_MAP_UNLOADED:
|
||||||
|
deinit_map(out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* State change tracking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int name_burrow_id = -1;
|
||||||
|
|
||||||
|
static void handle_burrow_rename(color_ostream &out, df::burrow *burrow);
|
||||||
|
|
||||||
|
static void detect_burrow_renames(color_ostream &out)
|
||||||
|
{
|
||||||
|
if (ui->main.mode == ui_sidebar_mode::Burrows &&
|
||||||
|
ui->burrows.in_edit_name_mode &&
|
||||||
|
ui->burrows.sel_id >= 0)
|
||||||
|
{
|
||||||
|
name_burrow_id = ui->burrows.sel_id;
|
||||||
|
}
|
||||||
|
else if (name_burrow_id >= 0)
|
||||||
|
{
|
||||||
|
auto burrow = df::burrow::find(name_burrow_id);
|
||||||
|
name_burrow_id = -1;
|
||||||
|
if (burrow)
|
||||||
|
handle_burrow_rename(out, burrow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DigJob {
|
||||||
|
int id;
|
||||||
|
df::job_type job;
|
||||||
|
df::coord pos;
|
||||||
|
df::tiletype old_tile;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int next_job_id_save = 0;
|
||||||
|
static std::map<int,DigJob> diggers;
|
||||||
|
|
||||||
|
static void handle_dig_complete(color_ostream &out, df::job_type job, df::coord pos,
|
||||||
|
df::tiletype old_tile, df::tiletype new_tile);
|
||||||
|
|
||||||
|
static void detect_digging(color_ostream &out)
|
||||||
|
{
|
||||||
|
for (auto it = diggers.begin(); it != diggers.end();)
|
||||||
|
{
|
||||||
|
auto worker = df::unit::find(it->first);
|
||||||
|
|
||||||
|
if (!worker || !worker->job.current_job ||
|
||||||
|
worker->job.current_job->id != it->second.id)
|
||||||
|
{
|
||||||
|
//out.print("Dig job %d expired.\n", it->second.id);
|
||||||
|
|
||||||
|
df::coord pos = it->second.pos;
|
||||||
|
|
||||||
|
if (auto block = Maps::getTileBlock(pos))
|
||||||
|
{
|
||||||
|
df::tiletype new_tile = block->tiletype[pos.x&15][pos.y&15];
|
||||||
|
|
||||||
|
//out.print("Tile %d -> %d\n", it->second.old_tile, new_tile);
|
||||||
|
|
||||||
|
if (new_tile != it->second.old_tile)
|
||||||
|
{
|
||||||
|
handle_dig_complete(out, it->second.job, pos, it->second.old_tile, new_tile);
|
||||||
|
|
||||||
|
//if (worker && !worker->job.current_job)
|
||||||
|
// worker->counters.think_counter = worker->counters.job_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cur = it; ++it; diggers.erase(cur);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<df::job*> jvec;
|
||||||
|
|
||||||
|
if (Job::listNewlyCreated(&jvec, &next_job_id_save))
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < jvec.size(); i++)
|
||||||
|
{
|
||||||
|
auto job = jvec[i];
|
||||||
|
auto type = ENUM_ATTR(job_type, type, job->job_type);
|
||||||
|
if (type != job_type_class::Digging)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto worker = Job::getWorker(job);
|
||||||
|
if (!worker)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
df::coord pos = job->pos;
|
||||||
|
auto block = Maps::getTileBlock(pos);
|
||||||
|
if (!block)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto &info = diggers[worker->id];
|
||||||
|
|
||||||
|
//out.print("New dig job %d.\n", job->id);
|
||||||
|
|
||||||
|
info.id = job->id;
|
||||||
|
info.job = job->job_type;
|
||||||
|
info.pos = pos;
|
||||||
|
info.old_tile = block->tiletype[pos.x&15][pos.y&15];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool active = false;
|
||||||
|
static bool auto_grow = false;
|
||||||
|
static std::vector<int> grow_burrows;
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_onupdate(color_ostream &out)
|
||||||
|
{
|
||||||
|
if (!active)
|
||||||
|
return CR_OK;
|
||||||
|
|
||||||
|
detect_burrow_renames(out);
|
||||||
|
|
||||||
|
if (auto_grow)
|
||||||
|
detect_digging(out);
|
||||||
|
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Config and processing
|
||||||
|
*/
|
||||||
|
|
||||||
|
static std::map<std::string,int> name_lookup;
|
||||||
|
|
||||||
|
static void parse_names()
|
||||||
|
{
|
||||||
|
auto &list = ui->burrows.list;
|
||||||
|
|
||||||
|
grow_burrows.clear();
|
||||||
|
name_lookup.clear();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < list.size(); i++)
|
||||||
|
{
|
||||||
|
auto burrow = list[i];
|
||||||
|
|
||||||
|
std::string name = burrow->name;
|
||||||
|
|
||||||
|
if (!name.empty())
|
||||||
|
{
|
||||||
|
name_lookup[name] = burrow->id;
|
||||||
|
|
||||||
|
if (name[name.size()-1] == '+')
|
||||||
|
{
|
||||||
|
grow_burrows.push_back(burrow->id);
|
||||||
|
name.resize(name.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name.empty())
|
||||||
|
name_lookup[name] = burrow->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_tracking()
|
||||||
|
{
|
||||||
|
diggers.clear();
|
||||||
|
next_job_id_save = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_map(color_ostream &out)
|
||||||
|
{
|
||||||
|
auto config = Core::getInstance().getWorld()->GetPersistentData("burrows/config");
|
||||||
|
if (config.isValid())
|
||||||
|
{
|
||||||
|
auto_grow = !!(config.ival(0) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_names();
|
||||||
|
name_burrow_id = -1;
|
||||||
|
|
||||||
|
reset_tracking();
|
||||||
|
active = true;
|
||||||
|
|
||||||
|
if (auto_grow && !grow_burrows.empty())
|
||||||
|
out.print("Auto-growing %d burrows.\n", grow_burrows.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deinit_map(color_ostream &out)
|
||||||
|
{
|
||||||
|
active = false;
|
||||||
|
auto_grow = false;
|
||||||
|
reset_tracking();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PersistentDataItem create_config(color_ostream &out)
|
||||||
|
{
|
||||||
|
bool created;
|
||||||
|
auto rv = Core::getInstance().getWorld()->GetPersistentData("burrows/config", &created);
|
||||||
|
if (created && rv.isValid())
|
||||||
|
rv.ival(0) = 0;
|
||||||
|
if (!rv.isValid())
|
||||||
|
out.printerr("Could not write configuration.");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enable_auto_grow(color_ostream &out, bool enable)
|
||||||
|
{
|
||||||
|
if (enable == auto_grow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto config = create_config(out);
|
||||||
|
if (!config.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
config.ival(0) |= 1;
|
||||||
|
else
|
||||||
|
config.ival(0) &= ~1;
|
||||||
|
|
||||||
|
auto_grow = enable;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
reset_tracking();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_burrow_rename(color_ostream &out, df::burrow *burrow)
|
||||||
|
{
|
||||||
|
parse_names();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_to_burrows(std::vector<df::burrow*> &burrows, df::coord pos)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < burrows.size(); i++)
|
||||||
|
Maps::setBurrowTile(burrows[i], pos, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_walls_to_burrows(color_ostream &out, std::vector<df::burrow*> &burrows,
|
||||||
|
MapExtras::MapCache &mc, df::coord pos1, df::coord pos2)
|
||||||
|
{
|
||||||
|
for (int x = pos1.x; x <= pos2.x; x++)
|
||||||
|
{
|
||||||
|
for (int y = pos1.y; y <= pos2.y; y++)
|
||||||
|
{
|
||||||
|
for (int z = pos1.z; z <= pos2.z; z++)
|
||||||
|
{
|
||||||
|
df::coord pos(x,y,z);
|
||||||
|
|
||||||
|
auto tile = mc.tiletypeAt(pos);
|
||||||
|
|
||||||
|
if (isWallTerrain(tile))
|
||||||
|
add_to_burrows(burrows, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_dig_complete(color_ostream &out, df::job_type job, df::coord pos,
|
||||||
|
df::tiletype old_tile, df::tiletype new_tile)
|
||||||
|
{
|
||||||
|
if (!isWalkable(new_tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<df::burrow*> to_grow;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < grow_burrows.size(); i++)
|
||||||
|
{
|
||||||
|
auto b = df::burrow::find(grow_burrows[i]);
|
||||||
|
if (b && Maps::isBurrowTile(b, pos))
|
||||||
|
to_grow.push_back(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//out.print("%d to grow.\n", to_grow.size());
|
||||||
|
|
||||||
|
if (to_grow.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MapExtras::MapCache mc;
|
||||||
|
|
||||||
|
if (!isWalkable(old_tile))
|
||||||
|
{
|
||||||
|
add_walls_to_burrows(out, to_grow, mc, pos+df::coord(-1,-1,0), pos+df::coord(1,1,0));
|
||||||
|
|
||||||
|
if (isWalkableUp(new_tile))
|
||||||
|
add_to_burrows(to_grow, pos+df::coord(0,0,1));
|
||||||
|
|
||||||
|
if (tileShape(new_tile) == tiletype_shape::RAMP)
|
||||||
|
{
|
||||||
|
add_walls_to_burrows(out, to_grow, mc,
|
||||||
|
pos+df::coord(-1,-1,1), pos+df::coord(1,1,1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LowPassable(new_tile) && !LowPassable(old_tile))
|
||||||
|
{
|
||||||
|
add_to_burrows(to_grow, pos-df::coord(0,0,1));
|
||||||
|
|
||||||
|
if (tileShape(new_tile) == tiletype_shape::RAMP_TOP)
|
||||||
|
{
|
||||||
|
add_walls_to_burrows(out, to_grow, mc,
|
||||||
|
pos+df::coord(-1,-1,-1), pos+df::coord(1,1,-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static df::burrow *findByName(color_ostream &out, std::string name, bool silent = false)
|
||||||
|
{
|
||||||
|
int id = -1;
|
||||||
|
if (name_lookup.count(name))
|
||||||
|
id = name_lookup[name];
|
||||||
|
auto rv = df::burrow::find(id);
|
||||||
|
if (!rv && !silent)
|
||||||
|
out.printerr("Burrow not found: '%s'\n", name.c_str());
|
||||||
|
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)
|
||||||
|
Units::clearBurrowMembers(target);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < source->units.size(); i++)
|
||||||
|
{
|
||||||
|
auto unit = df::unit::find(source->units[i]);
|
||||||
|
|
||||||
|
if (unit)
|
||||||
|
Units::setInBurrow(unit, target, 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)
|
||||||
|
Maps::clearBurrowTiles(target);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<df::map_block*> pvec;
|
||||||
|
Maps::listBurrowBlocks(&pvec, source);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pvec.size(); i++)
|
||||||
|
{
|
||||||
|
auto block = pvec[i];
|
||||||
|
auto smask = Maps::getBlockBurrowMask(source, block);
|
||||||
|
if (!smask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto tmask = Maps::getBlockBurrowMask(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())
|
||||||
|
Maps::deleteBlockBurrowMask(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 = Maps::getBlockBurrowMask(target, block, enable);
|
||||||
|
if (!mask)
|
||||||
|
goto next_block;
|
||||||
|
|
||||||
|
mask->setassignment(x, y, enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask && !enable && !mask->has_assignments())
|
||||||
|
Maps::deleteBlockBurrowMask(target, block, mask);
|
||||||
|
|
||||||
|
next_block:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool setTilesByKeyword(df::burrow *target, std::string name, bool enable)
|
||||||
|
{
|
||||||
|
CHECK_NULL_POINTER(target);
|
||||||
|
|
||||||
|
df::tile_designation mask(0);
|
||||||
|
df::tile_designation value(0);
|
||||||
|
|
||||||
|
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_LUA_FUNCTION(findByName),
|
||||||
|
DFHACK_LUA_FUNCTION(copyUnits),
|
||||||
|
DFHACK_LUA_FUNCTION(copyTiles),
|
||||||
|
DFHACK_LUA_FUNCTION(setTilesByKeyword),
|
||||||
|
DFHACK_LUA_END
|
||||||
|
};
|
||||||
|
|
||||||
|
static command_result burrow(color_ostream &out, vector <string> ¶meters)
|
||||||
|
{
|
||||||
|
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 (int 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 (int i = 1; i < parameters.size(); i++)
|
||||||
|
{
|
||||||
|
auto target = findByName(out, parameters[i]);
|
||||||
|
if (!target)
|
||||||
|
return CR_WRONG_USAGE;
|
||||||
|
|
||||||
|
Units::clearBurrowMembers(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")
|
||||||
|
Units::clearBurrowMembers(target);
|
||||||
|
|
||||||
|
bool enable = (cmd != "remove-units");
|
||||||
|
|
||||||
|
for (int 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 (int i = 1; i < parameters.size(); i++)
|
||||||
|
{
|
||||||
|
auto target = findByName(out, parameters[i]);
|
||||||
|
if (!target)
|
||||||
|
return CR_WRONG_USAGE;
|
||||||
|
|
||||||
|
Maps::clearBurrowTiles(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")
|
||||||
|
Maps::clearBurrowTiles(target);
|
||||||
|
|
||||||
|
bool enable = (cmd != "remove-tiles");
|
||||||
|
|
||||||
|
for (int 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;
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
local _ENV = mkmodule('plugins.burrows')
|
||||||
|
|
||||||
|
--[[
|
||||||
|
|
||||||
|
Native functions:
|
||||||
|
|
||||||
|
* findByName(name) -> burrow
|
||||||
|
* copyUnits(dest,src,enable)
|
||||||
|
* copyTiles(dest,src,enable)
|
||||||
|
* setTilesByKeyword(dest,kwd,enable) -> success
|
||||||
|
|
||||||
|
'enable' selects between add and remove modes
|
||||||
|
|
||||||
|
--]]
|
||||||
|
|
||||||
|
clearUnits = dfhack.units.clearBurrowMembers
|
||||||
|
|
||||||
|
function isBurrowUnit(burrow,unit)
|
||||||
|
return dfhack.units.isInBurrow(unit,burrow)
|
||||||
|
end
|
||||||
|
function setBurrowUnit(burrow,unit,enable)
|
||||||
|
return dfhack.units.setInBurrow(unit,burrow,enable)
|
||||||
|
end
|
||||||
|
|
||||||
|
clearTiles = dfhack.maps.clearBurrowTiles
|
||||||
|
listBlocks = dfhack.maps.listBurrowBlocks
|
||||||
|
|
||||||
|
isBurrowTile = dfhack.maps.isBurrowTile
|
||||||
|
setBurrowTile = dfhack.maps.setBurrowTile
|
||||||
|
isBlockBurrowTile = dfhack.maps.isBlockBurrowTile
|
||||||
|
setBlockBurrowTile = dfhack.maps.setBlockBurrowTile
|
||||||
|
|
||||||
|
return _ENV
|
Loading…
Reference in New Issue