Merge remote-tracking branch 'dfhack/develop' into remote_reader

develop
JapaMala 2018-12-26 00:23:05 -06:00
commit 45985fe5a9
21 changed files with 120 additions and 111 deletions

@ -1728,6 +1728,14 @@ Subcommands:
:import NAME: Imports manager orders from a file named ``dfhack-config/orders/NAME.json``. :import NAME: Imports manager orders from a file named ``dfhack-config/orders/NAME.json``.
:clear: Deletes all manager orders in the current embark. :clear: Deletes all manager orders in the current embark.
.. _nestboxes:
nestboxes
=========
Automatically scan for and forbid fertile eggs incubating in a nestbox.
Toggle status with `enable` or `disable`.
================ ================
Map modification Map modification
================ ================

@ -37,6 +37,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
================================================================================ ================================================================================
# Future # Future
## New Plugins
- `nestboxes`: automatically scan for and forbid fertile eggs incubating in a nestbox
## Fixes ## Fixes
- `building-hacks`: fixed error when dealing with custom animation tables - `building-hacks`: fixed error when dealing with custom animation tables
- `devel/test-perlin`: fixed Lua error (``math.pow()``) - `devel/test-perlin`: fixed Lua error (``math.pow()``)

@ -42,6 +42,7 @@ using namespace std;
#include "Core.h" #include "Core.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "Console.h" #include "Console.h"
#include "MiscUtils.h"
#include "Module.h" #include "Module.h"
#include "VersionInfoFactory.h" #include "VersionInfoFactory.h"
#include "VersionInfo.h" #include "VersionInfo.h"
@ -1522,7 +1523,7 @@ Core::~Core()
} }
Core::Core() : Core::Core() :
d{new Private}, d(dts::make_unique<Private>()),
script_path_mutex{}, script_path_mutex{},
HotkeyMutex{}, HotkeyMutex{},
HotkeyCond{}, HotkeyCond{},
@ -1535,10 +1536,7 @@ Core::Core() :
{ {
// init the console. This must be always the first step! // init the console. This must be always the first step!
plug_mgr = 0; plug_mgr = 0;
vif = 0;
p = 0;
errorstate = false; errorstate = false;
vinfo = 0;
started = false; started = false;
memset(&(s_mods), 0, sizeof(s_mods)); memset(&(s_mods), 0, sizeof(s_mods));
@ -1617,27 +1615,27 @@ bool Core::Init()
#else #else
const char * path = "hack\\symbols.xml"; const char * path = "hack\\symbols.xml";
#endif #endif
vif = new DFHack::VersionInfoFactory(); auto local_vif = dts::make_unique<DFHack::VersionInfoFactory>();
cerr << "Identifying DF version.\n"; cerr << "Identifying DF version.\n";
try try
{ {
vif->loadFile(path); local_vif->loadFile(path);
} }
catch(Error::All & err) catch(Error::All & err)
{ {
std::stringstream out; std::stringstream out;
out << "Error while reading symbols.xml:\n"; out << "Error while reading symbols.xml:\n";
out << err.what() << std::endl; out << err.what() << std::endl;
delete vif;
vif = NULL;
errorstate = true; errorstate = true;
fatal(out.str()); fatal(out.str());
return false; return false;
} }
p = new DFHack::Process(vif); vif = std::move(local_vif);
vinfo = p->getDescriptor(); auto local_p = dts::make_unique<DFHack::Process>(*vif);
local_p->ValidateDescriptionOS();
vinfo = local_p->getDescriptor();
if(!vinfo || !p->isIdentified()) if(!vinfo || !local_p->isIdentified())
{ {
if (!Version::git_xml_match()) if (!Version::git_xml_match())
{ {
@ -1668,23 +1666,10 @@ bool Core::Init()
fatal("Not a known DF version.\n"); fatal("Not a known DF version.\n");
} }
errorstate = true; errorstate = true;
delete p;
p = NULL;
return false; return false;
} }
cerr << "Version: " << vinfo->getVersion() << endl; cerr << "Version: " << vinfo->getVersion() << endl;
p = std::move(local_p);
#if defined(_WIN32)
const OSType expected = OS_WINDOWS;
#elif defined(_DARWIN)
const OSType expected = OS_APPLE;
#else
const OSType expected = OS_LINUX;
#endif
if (expected != vinfo->getOS()) {
cerr << "OS mismatch; resetting to " << int(expected) << endl;
vinfo->setOS(expected);
}
// Init global object pointers // Init global object pointers
df::global::InitGlobals(); df::global::InitGlobals();
@ -2319,14 +2304,9 @@ int Core::Shutdown ( void )
plug_mgr = 0; plug_mgr = 0;
} }
// invalidate all modules // invalidate all modules
for(size_t i = 0 ; i < allModules.size(); i++)
{
delete allModules[i];
}
allModules.clear(); allModules.clear();
memset(&(s_mods), 0, sizeof(s_mods)); memset(&(s_mods), 0, sizeof(s_mods));
delete d; d.reset();
d = nullptr;
return -1; return -1;
} }
@ -2755,7 +2735,7 @@ void ClassNameCheck::getKnownClassNames(std::vector<std::string> &names)
MemoryPatcher::MemoryPatcher(Process *p_) : p(p_) MemoryPatcher::MemoryPatcher(Process *p_) : p(p_)
{ {
if (!p) if (!p)
p = Core::getInstance().p; p = Core::getInstance().p.get();
} }
MemoryPatcher::~MemoryPatcher() MemoryPatcher::~MemoryPatcher()
@ -2846,9 +2826,9 @@ TYPE * Core::get##TYPE() \
if(errorstate) return NULL;\ if(errorstate) return NULL;\
if(!s_mods.p##TYPE)\ if(!s_mods.p##TYPE)\
{\ {\
Module * mod = create##TYPE();\ std::unique_ptr<Module> mod = create##TYPE();\
s_mods.p##TYPE = (TYPE *) mod;\ s_mods.p##TYPE = (TYPE *) mod.get();\
allModules.push_back(mod);\ allModules.push_back(std::move(mod));\
}\ }\
return s_mods.p##TYPE;\ return s_mods.p##TYPE;\
} }

@ -17,7 +17,7 @@ namespace {
} }
#define INIT_GLOBAL_FUNCTION_PREFIX \ #define INIT_GLOBAL_FUNCTION_PREFIX \
DFHack::VersionInfo *global_table_ = DFHack::Core::getInstance().vinfo; \ DFHack::VersionInfo *global_table_ = DFHack::Core::getInstance().vinfo.get(); \
void * tmp_; void * tmp_;
#define INIT_GLOBAL_FUNCTION_ITEM(type,name) \ #define INIT_GLOBAL_FUNCTION_ITEM(type,name) \

@ -2521,7 +2521,7 @@ static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
static int internal_getmd5(lua_State *L) static int internal_getmd5(lua_State *L)
{ {
auto p = Core::getInstance().p; auto& p = Core::getInstance().p;
if (p->getDescriptor()->getOS() == OS_WINDOWS) if (p->getDescriptor()->getOS() == OS_WINDOWS)
luaL_error(L, "process MD5 not available on Windows"); luaL_error(L, "process MD5 not available on Windows");
lua_pushstring(L, p->getMD5().c_str()); lua_pushstring(L, p->getMD5().c_str());
@ -2530,7 +2530,7 @@ static int internal_getmd5(lua_State *L)
static int internal_getPE(lua_State *L) static int internal_getPE(lua_State *L)
{ {
auto p = Core::getInstance().p; auto& p = Core::getInstance().p;
if (p->getDescriptor()->getOS() != OS_WINDOWS) if (p->getDescriptor()->getOS() != OS_WINDOWS)
luaL_error(L, "process PE timestamp not available on non-Windows"); luaL_error(L, "process PE timestamp not available on non-Windows");
lua_pushinteger(L, p->getPE()); lua_pushinteger(L, p->getPE());

@ -48,7 +48,7 @@ using namespace std;
#include <string.h> #include <string.h>
using namespace DFHack; using namespace DFHack;
Process::Process(VersionInfoFactory * known_versions) Process::Process(const VersionInfoFactory& known_versions) : identified(false), my_pe(0)
{ {
int target_result; int target_result;
@ -59,10 +59,6 @@ Process::Process(VersionInfoFactory * known_versions)
real_path = realpath(path, NULL); real_path = realpath(path, NULL);
} }
identified = false;
my_descriptor = 0;
my_pe = 0;
md5wrapper md5; md5wrapper md5;
uint32_t length; uint32_t length;
uint8_t first_kb [1024]; uint8_t first_kb [1024];
@ -70,10 +66,10 @@ Process::Process(VersionInfoFactory * known_versions)
// get hash of the running DF process // get hash of the running DF process
my_md5 = md5.getHashFromFile(real_path, length, (char *) first_kb); my_md5 = md5.getHashFromFile(real_path, length, (char *) first_kb);
// create linux process, add it to the vector // create linux process, add it to the vector
VersionInfo * vinfo = known_versions->getVersionInfoByMD5(my_md5); auto vinfo = known_versions.getVersionInfoByMD5(my_md5);
if(vinfo) if(vinfo)
{ {
my_descriptor = new VersionInfo(*vinfo); my_descriptor = std::make_shared<VersionInfo>(*vinfo);
identified = true; identified = true;
} }
else else
@ -112,8 +108,7 @@ Process::Process(VersionInfoFactory * known_versions)
Process::~Process() Process::~Process()
{ {
// destroy our copy of the memory descriptor // Nothing to do here
delete my_descriptor;
} }
string Process::doReadClassName (void * vptr) string Process::doReadClassName (void * vptr)

@ -46,7 +46,7 @@ using namespace std;
#include <string.h> #include <string.h>
using namespace DFHack; using namespace DFHack;
Process::Process(VersionInfoFactory * known_versions) Process::Process(const VersionInfoFactory& known_versions) : identified(false), my_pe(0)
{ {
const char * dir_name = "/proc/self/"; const char * dir_name = "/proc/self/";
const char * exe_link_name = "/proc/self/exe"; const char * exe_link_name = "/proc/self/exe";
@ -54,10 +54,6 @@ Process::Process(VersionInfoFactory * known_versions)
const char * cmdline_name = "/proc/self/cmdline"; const char * cmdline_name = "/proc/self/cmdline";
int target_result; int target_result;
identified = false;
my_descriptor = 0;
my_pe = 0;
// valgrind replaces readlink for /proc/self/exe, but not open. // valgrind replaces readlink for /proc/self/exe, but not open.
char self_exe[1024]; char self_exe[1024];
memset(self_exe, 0, sizeof(self_exe)); memset(self_exe, 0, sizeof(self_exe));
@ -74,10 +70,10 @@ Process::Process(VersionInfoFactory * known_versions)
// get hash of the running DF process // get hash of the running DF process
my_md5 = md5.getHashFromFile(self_exe_name, length, (char *) first_kb); my_md5 = md5.getHashFromFile(self_exe_name, length, (char *) first_kb);
// create linux process, add it to the vector // create linux process, add it to the vector
VersionInfo * vinfo = known_versions->getVersionInfoByMD5(my_md5); auto vinfo = known_versions.getVersionInfoByMD5(my_md5);
if(vinfo) if(vinfo)
{ {
my_descriptor = new VersionInfo(*vinfo); my_descriptor = std::make_shared<VersionInfo>(*vinfo);
identified = true; identified = true;
} }
else else
@ -116,8 +112,7 @@ Process::Process(VersionInfoFactory * known_versions)
Process::~Process() Process::~Process()
{ {
// destroy our copy of the memory descriptor // Nothing to do here
delete my_descriptor;
} }
string Process::doReadClassName (void * vptr) string Process::doReadClassName (void * vptr)

@ -62,13 +62,11 @@ namespace DFHack
char * base; char * base;
}; };
} }
Process::Process(VersionInfoFactory * factory) Process::Process(const VersionInfoFactory& factory) : identified(false)
{ {
HMODULE hmod = NULL; HMODULE hmod = NULL;
DWORD needed; DWORD needed;
bool found = false; bool found = false;
identified = false;
my_descriptor = NULL;
d = new PlatformSpecific(); d = new PlatformSpecific();
// open process // open process
@ -97,12 +95,12 @@ Process::Process(VersionInfoFactory * factory)
return; return;
} }
my_pe = d->pe_header.FileHeader.TimeDateStamp; my_pe = d->pe_header.FileHeader.TimeDateStamp;
VersionInfo* vinfo = factory->getVersionInfoByPETimestamp(my_pe); auto vinfo = factory.getVersionInfoByPETimestamp(my_pe);
if(vinfo) if(vinfo)
{ {
identified = true; identified = true;
// give the process a data model and memory layout fixed for the base of first module // give the process a data model and memory layout fixed for the base of first module
my_descriptor = new VersionInfo(*vinfo); my_descriptor = std::make_shared<VersionInfo>(*vinfo);
my_descriptor->rebaseTo(getBase()); my_descriptor->rebaseTo(getBase());
} }
else else
@ -115,7 +113,6 @@ Process::Process(VersionInfoFactory * factory)
Process::~Process() Process::~Process()
{ {
// destroy our rebased copy of the memory descriptor // destroy our rebased copy of the memory descriptor
delete my_descriptor;
if(d->sections != NULL) if(d->sections != NULL)
free(d->sections); free(d->sections);
} }

@ -52,33 +52,28 @@ VersionInfoFactory::~VersionInfoFactory()
void VersionInfoFactory::clear() void VersionInfoFactory::clear()
{ {
// for each stored version, delete
for(size_t i = 0; i < versions.size();i++)
{
delete versions[i];
}
versions.clear(); versions.clear();
error = false; error = false;
} }
VersionInfo * VersionInfoFactory::getVersionInfoByMD5(string hash) std::shared_ptr<const VersionInfo> VersionInfoFactory::getVersionInfoByMD5(string hash) const
{ {
for(size_t i = 0; i < versions.size();i++) for (const auto& version : versions)
{ {
if(versions[i]->hasMD5(hash)) if(version->hasMD5(hash))
return versions[i]; return version;
} }
return 0; return nullptr;
} }
VersionInfo * VersionInfoFactory::getVersionInfoByPETimestamp(uintptr_t timestamp) std::shared_ptr<const VersionInfo> VersionInfoFactory::getVersionInfoByPETimestamp(uintptr_t timestamp) const
{ {
for(size_t i = 0; i < versions.size();i++) for (const auto& version : versions)
{ {
if(versions[i]->hasPE(timestamp)) if(version->hasPE(timestamp))
return versions[i]; return version;
} }
return 0; return nullptr;
} }
void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem) void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
@ -230,8 +225,8 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
const char *name = pMemInfo->Attribute("name"); const char *name = pMemInfo->Attribute("name");
if(name) if(name)
{ {
VersionInfo *version = new VersionInfo(); auto version = std::make_shared<VersionInfo>();
ParseVersion( pMemInfo , version ); ParseVersion( pMemInfo , version.get() );
versions.push_back(version); versions.push_back(version);
} }
} }

@ -30,6 +30,7 @@ distribution.
#include <vector> #include <vector>
#include <stack> #include <stack>
#include <map> #include <map>
#include <memory>
#include <stdint.h> #include <stdint.h>
#include "Console.h" #include "Console.h"
#include "modules/Graphic.h" #include "modules/Graphic.h"
@ -135,7 +136,6 @@ namespace DFHack
/// Get the single Core instance or make one. /// Get the single Core instance or make one.
static Core& getInstance() static Core& getInstance()
{ {
// FIXME: add critical section for thread safety here.
static Core instance; static Core instance;
return instance; return instance;
} }
@ -191,8 +191,8 @@ namespace DFHack
DFHack::Console &getConsole() { return con; } DFHack::Console &getConsole() { return con; }
DFHack::Process * p; std::unique_ptr<DFHack::Process> p;
DFHack::VersionInfo * vinfo; std::shared_ptr<DFHack::VersionInfo> vinfo;
DFHack::Windows::df_window * screen_window; DFHack::Windows::df_window * screen_window;
static void print(const char *format, ...) Wformat(printf,1,2); static void print(const char *format, ...) Wformat(printf,1,2);
@ -209,7 +209,7 @@ namespace DFHack
~Core(); ~Core();
struct Private; struct Private;
Private *d; std::unique_ptr<Private> d;
bool Init(); bool Init();
int Update (void); int Update (void);
@ -235,7 +235,7 @@ namespace DFHack
struct Cond; struct Cond;
// FIXME: shouldn't be kept around like this // FIXME: shouldn't be kept around like this
DFHack::VersionInfoFactory * vif; std::unique_ptr<DFHack::VersionInfoFactory> vif;
// Module storage // Module storage
struct struct
{ {
@ -243,7 +243,7 @@ namespace DFHack
Notes * pNotes; Notes * pNotes;
Graphic * pGraphic; Graphic * pGraphic;
} s_mods; } s_mods;
std::vector <Module *> allModules; std::vector<std::unique_ptr<Module>> allModules;
DFHack::PluginManager * plug_mgr; DFHack::PluginManager * plug_mgr;
std::vector<std::string> script_paths[2]; std::vector<std::string> script_paths[2];

@ -33,10 +33,12 @@ distribution.
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <memory>
#include "VersionInfo.h"
namespace DFHack namespace DFHack
{ {
struct VersionInfo;
class Process; class Process;
//class Window; //class Window;
class DFVector; class DFVector;
@ -78,7 +80,7 @@ namespace DFHack
{ {
public: public:
/// this is the single most important destructor ever. ~px /// this is the single most important destructor ever. ~px
Process(VersionInfoFactory * known_versions); Process(const VersionInfoFactory& known_versions);
~Process(); ~Process();
/// read a 8-byte integer /// read a 8-byte integer
uint64_t readQuad(const void * address) uint64_t readQuad(const void * address)
@ -246,10 +248,15 @@ namespace DFHack
void getMemRanges(std::vector<t_memrange> & ranges ); void getMemRanges(std::vector<t_memrange> & ranges );
/// get the symbol table extension of this process /// get the symbol table extension of this process
VersionInfo *getDescriptor() std::shared_ptr<DFHack::VersionInfo> getDescriptor()
{ {
return my_descriptor; return my_descriptor;
}; };
void ValidateDescriptionOS() {
my_descriptor->ValidateOS();
};
uintptr_t getBase(); uintptr_t getBase();
/// get the DF Process ID /// get the DF Process ID
int getPID(); int getPID();
@ -291,7 +298,7 @@ namespace DFHack
std::string getMD5() { return my_md5; } std::string getMD5() { return my_md5; }
private: private:
VersionInfo * my_descriptor; std::shared_ptr<VersionInfo> my_descriptor;
PlatformSpecific *d; PlatformSpecific *d;
bool identified; bool identified;
uint32_t my_pid; uint32_t my_pid;

@ -27,13 +27,13 @@ distribution.
#ifndef MODULE_FACTORY_H_INCLUDED #ifndef MODULE_FACTORY_H_INCLUDED
#define MODULE_FACTORY_H_INCLUDED #define MODULE_FACTORY_H_INCLUDED
#include <memory>
namespace DFHack namespace DFHack
{ {
class Module; class Module;
Module* createGui(); std::unique_ptr<Module> createMaterials();
Module* createWorld(); std::unique_ptr<Module> createNotes();
Module* createMaterials(); std::unique_ptr<Module> createGraphic();
Module* createNotes();
Module* createGraphic();
} }
#endif #endif

@ -26,6 +26,7 @@ distribution.
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <iostream>
#include <map> #include <map>
#include <sys/types.h> #include <sys/types.h>
#include <vector> #include <vector>
@ -169,5 +170,19 @@ namespace DFHack
{ {
return OS; return OS;
}; };
void ValidateOS() {
#if defined(_WIN32)
const OSType expected = OS_WINDOWS;
#elif defined(_DARWIN)
const OSType expected = OS_APPLE;
#else
const OSType expected = OS_LINUX;
#endif
if (expected != getOS()) {
std::cerr << "OS mismatch; resetting to " << int(expected) << std::endl;
setOS(expected);
}
}
}; };
} }

@ -25,6 +25,8 @@ distribution.
#pragma once #pragma once
#include <memory>
#include "Pragma.h" #include "Pragma.h"
#include "Export.h" #include "Export.h"
@ -39,12 +41,12 @@ namespace DFHack
~VersionInfoFactory(); ~VersionInfoFactory();
bool loadFile( std::string path_to_xml); bool loadFile( std::string path_to_xml);
bool isInErrorState() const {return error;}; bool isInErrorState() const {return error;};
VersionInfo * getVersionInfoByMD5(std::string md5string); std::shared_ptr<const VersionInfo> getVersionInfoByMD5(std::string md5string) const;
VersionInfo * getVersionInfoByPETimestamp(uintptr_t timestamp); std::shared_ptr<const VersionInfo> getVersionInfoByPETimestamp(uintptr_t timestamp) const;
std::vector<VersionInfo*> versions;
// trash existing list // trash existing list
void clear(); void clear();
private: private:
std::vector<std::shared_ptr<const VersionInfo>> versions;
void ParseVersion (TiXmlElement* version, VersionInfo* mem); void ParseVersion (TiXmlElement* version, VersionInfo* mem);
bool error; bool error;
}; };

@ -36,14 +36,15 @@ using namespace std;
#include "Error.h" #include "Error.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "MiscUtils.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
using namespace DFHack; using namespace DFHack;
Module* DFHack::createGraphic() std::unique_ptr<Module> DFHack::createGraphic()
{ {
return new Graphic(); return dts::make_unique<Graphic>();
} }
struct Graphic::Private struct Graphic::Private

@ -592,12 +592,11 @@ bool DFHack::isStoneInorganic(int material)
return true; return true;
} }
Module* DFHack::createMaterials() std::unique_ptr<Module> DFHack::createMaterials()
{ {
return new Materials(); return dts::make_unique<Materials>();
} }
Materials::Materials() Materials::Materials()
{ {
} }

@ -33,6 +33,7 @@ using namespace std;
#include "Types.h" #include "Types.h"
#include "Error.h" #include "Error.h"
#include "MemAccess.h" #include "MemAccess.h"
#include "MiscUtils.h"
#include "ModuleFactory.h" #include "ModuleFactory.h"
#include "Core.h" #include "Core.h"
#include "modules/Notes.h" #include "modules/Notes.h"
@ -40,9 +41,9 @@ using namespace std;
#include "df/ui.h" #include "df/ui.h"
using namespace DFHack; using namespace DFHack;
Module* DFHack::createNotes() std::unique_ptr<Module> DFHack::createNotes()
{ {
return new Notes(); return dts::make_unique<Notes>();
} }
// FIXME: not even a wrapper now // FIXME: not even a wrapper now

@ -138,6 +138,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(misery misery.cpp) DFHACK_PLUGIN(misery misery.cpp)
DFHACK_PLUGIN(mode mode.cpp) DFHACK_PLUGIN(mode mode.cpp)
DFHACK_PLUGIN(mousequery mousequery.cpp) DFHACK_PLUGIN(mousequery mousequery.cpp)
DFHACK_PLUGIN(nestboxes nestboxes.cpp)
DFHACK_PLUGIN(orders orders.cpp LINK_LIBRARIES jsoncpp_lib_static) DFHACK_PLUGIN(orders orders.cpp LINK_LIBRARIES jsoncpp_lib_static)
DFHACK_PLUGIN(pathable pathable.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(pathable pathable.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(petcapRemover petcapRemover.cpp) DFHACK_PLUGIN(petcapRemover petcapRemover.cpp)

@ -11,7 +11,6 @@ DFHACK_PLUGIN(eventExample eventExample.cpp)
DFHACK_PLUGIN(frozen frozen.cpp) DFHACK_PLUGIN(frozen frozen.cpp)
DFHACK_PLUGIN(kittens kittens.cpp) DFHACK_PLUGIN(kittens kittens.cpp)
DFHACK_PLUGIN(memview memview.cpp memutils.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(memview memview.cpp memutils.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(nestboxes nestboxes.cpp)
DFHACK_PLUGIN(notes notes.cpp) DFHACK_PLUGIN(notes notes.cpp)
DFHACK_PLUGIN(onceExample onceExample.cpp) DFHACK_PLUGIN(onceExample onceExample.cpp)
DFHACK_PLUGIN(renderer-msg renderer-msg.cpp) DFHACK_PLUGIN(renderer-msg renderer-msg.cpp)

@ -1911,6 +1911,11 @@ public:
labors_changed = true; labors_changed = true;
} }
} }
else if (l == df::unit_labor::CLEAN && best_score < 0)
{
if (Units::isValidLabor((*bestdwarf)->dwarf, l))
set_labor(*bestdwarf, l, true);
}
else if ((*bestdwarf)->state == IDLE) else if ((*bestdwarf)->state == IDLE)
{ {
if (Units::isValidLabor((*bestdwarf)->dwarf, l)) if (Units::isValidLabor((*bestdwarf)->dwarf, l))
@ -1961,6 +1966,10 @@ public:
{ {
set_labor(*d, l, true); set_labor(*d, l, true);
} }
if (score < 0)
set_labor(*d, df::unit_labor::CLEAN, true);
if ((*d)->using_labor != df::unit_labor::NONE && if ((*d)->using_labor != df::unit_labor::NONE &&
(score > current_score + 5000 || base_priority[(*d)->using_labor] < base_priority[l]) && (score > current_score + 5000 || base_priority[(*d)->using_labor] < base_priority[l]) &&
default_labor_infos[(*d)->using_labor].tool == TOOL_NONE) default_labor_infos[(*d)->using_labor].tool == TOOL_NONE)
@ -1990,6 +1999,8 @@ public:
set_labor(canary_dwarf, l, true); set_labor(canary_dwarf, l, true);
} }
set_labor(canary_dwarf, df::unit_labor::CLEAN, true);
/* Also set the canary to remove constructions, because we have no way yet to tell if there are constructions needing removal */ /* Also set the canary to remove constructions, because we have no way yet to tell if there are constructions needing removal */
set_labor(canary_dwarf, df::unit_labor::REMOVE_CONSTRUCTION, true); set_labor(canary_dwarf, df::unit_labor::REMOVE_CONSTRUCTION, true);

@ -8,6 +8,7 @@
#include "df/ui.h" #include "df/ui.h"
#include "df/building_nest_boxst.h" #include "df/building_nest_boxst.h"
#include "df/building_type.h" #include "df/building_type.h"
#include "df/buildings_other_id.h"
#include "df/global_objects.h" #include "df/global_objects.h"
#include "df/item.h" #include "df/item.h"
#include "df/unit.h" #include "df/unit.h"
@ -37,7 +38,7 @@ static void eggscan(color_ostream &out)
{ {
CoreSuspender suspend; CoreSuspender suspend;
for (df::building *build : world->buildings.all) for (df::building *build : world->buildings.other[df::buildings_other_id::NEST_BOX])
{ {
auto type = build->getType(); auto type = build->getType();
if (df::enums::building_type::NestBox == type) if (df::enums::building_type::NestBox == type)
@ -68,9 +69,11 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
{ {
if (world && ui) { if (world && ui) {
commands.push_back( commands.push_back(
PluginCommand("nestboxes", "Derp.", PluginCommand("nestboxes", "Automatically scan for and forbid fertile eggs incubating in a nestbox.",
nestboxes, false, nestboxes, false,
"Derp.\n" "To enable: nestboxes enable\n"
"To disable: nestboxes disable\n"
"There is no other configuration.\n"
) )
); );
} }
@ -105,9 +108,6 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable)
static command_result nestboxes(color_ostream &out, vector <string> & parameters) static command_result nestboxes(color_ostream &out, vector <string> & parameters)
{ {
CoreSuspender suspend; CoreSuspender suspend;
bool clean = false;
int dump_count = 0;
int good_egg = 0;
if (parameters.size() == 1) { if (parameters.size() == 1) {
if (parameters[0] == "enable") if (parameters[0] == "enable")