digSmart: added user interface and documentation.

develop
expwnent 2013-05-31 13:32:13 -04:00
parent b945b36016
commit b82b3f2283
2 changed files with 85 additions and 72 deletions

@ -1,6 +1,7 @@
DFHack future DFHack future
New commands: New commands:
- digSmart - automatically dig out specified veins as they are revealed
- restrictliquid - Restrict traffic on every visible square with liquid. - restrictliquid - Restrict traffic on every visible square with liquid.
- restrictice - Restrict traffic on squares above visible ice. - restrictice - Restrict traffic on squares above visible ice.
- treefarm - automatically chop trees and dig obsidian - treefarm - automatically chop trees and dig obsidian

@ -1,9 +1,6 @@
// some headers required for a plugin. Nothing special, just the basics.
#include "Core.h" #include "Core.h"
#include "Export.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "Export.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "modules/EventManager.h" #include "modules/EventManager.h"
@ -17,7 +14,8 @@
#include "df/tile_dig_designation.h" #include "df/tile_dig_designation.h"
#include "df/world.h" #include "df/world.h"
#include <map> #include <set>
#include <string>
#include <vector> #include <vector>
using namespace DFHack; using namespace DFHack;
@ -25,68 +23,43 @@ using namespace std;
command_result digSmart (color_ostream &out, std::vector <std::string> & parameters); command_result digSmart (color_ostream &out, std::vector <std::string> & parameters);
// A plugin must be able to return its name and version.
// The name string provided must correspond to the filename - skeleton.plug.so or skeleton.plug.dll in this case
DFHACK_PLUGIN("digSmart"); DFHACK_PLUGIN("digSmart");
void onDig(color_ostream& out, void* ptr); void onDig(color_ostream& out, void* ptr);
void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt, set<df::coord>& jobLocations); void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt, set<df::coord>& jobLocations);
EventManager::EventHandler digHandler(onDig, 0); EventManager::EventHandler digHandler(onDig, 0);
vector<df::coord> queue;
map<df::coord, int32_t> visitCount;
// Mandatory init function. If you have some global state, create it here. bool enabled = false;
bool digAll = false;
set<string> autodigMaterials;
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
// Fill the command list with your commands.
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"digSmart", "Automatically dig out veins as you discover them.", "digSmart", "Automatically dig out veins as you discover them.",
digSmart, false, /* true means that the command can't be used from non-interactive user interface */ digSmart, false,
// Extended help string. Used by CR_WRONG_USAGE and the help command:
" This command does nothing at all.\n"
"Example:\n" "Example:\n"
" digSmart\n" " digSmart 0\n"
" Does nothing.\n" " disable plugin\n"
" digSmart 1\n"
" enable plugin\n"
" digSmart 0 MICROCLINE COAL_BITUMINOUS 1\n"
" disable plugin and remove microcline and bituminous coal from being monitored, then re-enable plugin"
" digSmart 1 MICROCLINE 0 COAL_BITUMINOUS 1\n"
" don't monitor microcline, do monitor COAL_BITUMINOUS, then enable plugin\n"
" digSmart CLEAR\n"
" remove all inorganics from monitoring\n"
" digSmart digAll1\n"
" enable digAll mode: dig any vein, regardless of the monitor list\n"
" digSmart digAll0\n"
" disable digAll mode\n"
"\n"
"Note that while order matters, multiple commands can be sequenced in one line. It is recommended to alter your dfhack.init file so that you won't have to type in every mineral type you want to dig every time you start the game. Material names are case sensitive.\n"
)); ));
//digSmartPlugin = Core::getInstance().getPluginManager()->getPluginByName("digSmart");
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, digHandler, plugin_self); EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, digHandler, plugin_self);
return CR_OK; return CR_OK;
} }
void onTick(color_ostream& out, void* ptr) {
/*
MapExtras::MapCache cache;
for ( size_t a = 0; a < queue.size(); a++ ) {
df::coord pos = queue[a];
for ( int16_t a = -1; a <= 1; a++ ) {
for ( int16_t b = -1; b <= 1; b++ ) {
maybeExplore(out, cache, df::coord(pos.x+a,pos.y+b,pos.z));
}
}
}
cache.trash();
queue.clear();
*/
map<df::coord,int> toRemove;
for ( auto a = visitCount.begin(); a != visitCount.end(); a++ ) {
if ( (*a).second <= 0 )
continue;
df::coord pt = (*a).first;
df::map_block* block = Maps::getTileBlock(pt);
if ( block->designation[pt.x&0xF][pt.y&0xF].bits.dig != df::enums::tile_dig_designation::Default ) {
out.print("%d: %d,%d,%d: Default -> %d\n", __LINE__, pt.x,pt.y,pt.z, (int32_t)block->designation[pt.x&0xF][pt.y&0xF].bits.dig);
toRemove[pt]++;
}
}
for ( auto a = toRemove.begin(); a != toRemove.end(); a++ )
visitCount.erase((*a).first);
EventManager::EventHandler handler(onTick, 1);
EventManager::registerTick(handler, 1, plugin_self);
}
void onDig(color_ostream& out, void* ptr) { void onDig(color_ostream& out, void* ptr) {
CoreSuspender bob; CoreSuspender bob;
df::job* job = (df::job*)ptr; df::job* job = (df::job*)ptr;
@ -100,7 +73,6 @@ void onDig(color_ostream& out, void* ptr) {
job->job_type != df::enums::job_type::CarveRamp && job->job_type != df::enums::job_type::CarveRamp &&
job->job_type != df::enums::job_type::DigChannel ) job->job_type != df::enums::job_type::DigChannel )
return; return;
out.print("%d\n", __LINE__);
set<df::coord> jobLocations; set<df::coord> jobLocations;
for ( df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next ) { for ( df::job_list_link* link = &df::global::world->job_list; link != NULL; link = link->next ) {
@ -118,9 +90,6 @@ out.print("%d\n", __LINE__);
jobLocations.insert(link->item->pos); jobLocations.insert(link->item->pos);
} }
//queue.push_back(job->pos);
//EventManager::EventHandler handler(onTick, 1);
//EventManager::registerTick(handler, 5, plugin_self);
MapExtras::MapCache cache; MapExtras::MapCache cache;
df::coord pos = job->pos; df::coord pos = job->pos;
for ( int16_t a = -1; a <= 1; a++ ) { for ( int16_t a = -1; a <= 1; a++ ) {
@ -139,22 +108,16 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
df::map_block* block = Maps::getTileBlock(pt); df::map_block* block = Maps::getTileBlock(pt);
if (!block) if (!block)
return; return;
if ( block->designation[pt.x&0xF][pt.y&0xF].bits.hidden ) if ( block->designation[pt.x&0xF][pt.y&0xF].bits.hidden )
return; return;
df::tiletype type = block->tiletype[pt.x&0xF][pt.y&0xF]; df::tiletype type = block->tiletype[pt.x&0xF][pt.y&0xF];
if ( ENUM_ATTR(tiletype, material, type) != df::enums::tiletype_material::MINERAL ) if ( ENUM_ATTR(tiletype, material, type) != df::enums::tiletype_material::MINERAL )
return; return;
if ( ENUM_ATTR(tiletype, shape, type) != df::enums::tiletype_shape::WALL ) if ( ENUM_ATTR(tiletype, shape, type) != df::enums::tiletype_shape::WALL )
return; return;
int16_t mat = cache.veinMaterialAt(pt);
if ( mat == -1 )
return;
// if ( block->designation[pt.x&0xF][pt.y&0xF].bits.dig == df::enums::tile_dig_designation::Default )
// return;
if ( block->designation[pt.x&0xF][pt.y&0xF].bits.dig != df::enums::tile_dig_designation::No ) if ( block->designation[pt.x&0xF][pt.y&0xF].bits.dig != df::enums::tile_dig_designation::No )
return; return;
@ -166,23 +129,72 @@ void maybeExplore(color_ostream& out, MapExtras::MapCache& cache, df::coord pt,
return; return;
} }
df::enums::tile_dig_designation::tile_dig_designation dig1,dig2; int16_t mat = cache.veinMaterialAt(pt);
dig1 = block->designation[pt.x&0xF][pt.y&0xF].bits.dig; if ( mat == -1 )
return;
if ( !digAll ) {
df::inorganic_raw* inorganic = df::global::world->raws.inorganics[mat];
if ( autodigMaterials.find(inorganic->id) == autodigMaterials.end() ) {
out << __LINE__ << " " << inorganic->id << " not present." << endl;
return;
}
}
block->designation[pt.x&0xF][pt.y&0xF].bits.dig = df::enums::tile_dig_designation::Default; block->designation[pt.x&0xF][pt.y&0xF].bits.dig = df::enums::tile_dig_designation::Default;
dig2 = block->designation[pt.x&0xF][pt.y&0xF].bits.dig;
block->flags.bits.designated = true; block->flags.bits.designated = true;
// *df::global::process_dig = true; // *df::global::process_dig = true;
// *df::global::process_jobs = true; // *df::global::process_jobs = true;
out.print("%d: %d,%d,%d, %d. %d -> %d\n", __LINE__, pt.x,pt.y,pt.z, visitCount[pt]++, dig1, dig2);
//out.print("%d: unk9 %d, unk13 %d\n", __LINE__, (int32_t)block->unk9[pt.x&0xF][pt.y&0xF], (int32_t)block->unk13[pt.x&0xF][pt.y&0xF]);
} }
command_result digSmart (color_ostream &out, std::vector <std::string> & parameters) command_result digSmart (color_ostream &out, std::vector <std::string> & parameters)
{ {
if (!parameters.empty()) bool adding = true;
set<string> toAdd, toRemove;
for ( size_t a = 0; a < parameters.size(); a++ ) {
int32_t i = (int32_t)strtol(parameters[a].c_str(), NULL, 0);
if ( i == 0 && parameters[a] == "0" ) {
EventManager::unregisterAll(plugin_self);
adding = false;
continue;
} else if ( i == 1 ) {
EventManager::unregisterAll(plugin_self);
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, digHandler, plugin_self);
adding = true;
continue;
}
if ( parameters[a] == "CLEAR" )
autodigMaterials.clear();
if ( parameters[a] == "digAll0" ) {
digAll = false;
continue;
}
if ( parameters[a] == "digAll1" ) {
digAll = true;
continue;
}
for ( size_t b = 0; b < df::global::world->raws.inorganics.size(); b++ ) {
df::inorganic_raw* inorganic = df::global::world->raws.inorganics[b];
if ( parameters[a] == inorganic->id ) {
if ( adding )
toAdd.insert(parameters[a]);
else
toRemove.insert(parameters[a]);
goto loop;
}
}
out.print("Could not find material \"%s\".\n", parameters[a].c_str());
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
EventManager::EventHandler handler(onTick, 1);
EventManager::registerTick(handler, 1, plugin_self); loop: continue;
}
autodigMaterials.insert(toAdd.begin(), toAdd.end());
for ( auto a = toRemove.begin(); a != toRemove.end(); a++ )
autodigMaterials.erase(*a);
return CR_OK; return CR_OK;
} }