diff options
| author | Petr Mrázek | 2011-08-04 04:04:46 +0200 |
|---|---|---|
| committer | Petr Mrázek | 2011-08-04 04:04:46 +0200 |
| commit | a8543f5ef034774e026cf434c11055783a68c9d9 (patch) | |
| tree | 5c90de5546a604e3c080bf152ddf080b33c7f146 /plugins/autodump.cpp | |
| parent | ff4d545ae71eaf732afdb4200f6c409aebe91280 (diff) | |
| download | dfhack-a8543f5ef034774e026cf434c11055783a68c9d9.tar.gz dfhack-a8543f5ef034774e026cf434c11055783a68c9d9.tar.bz2 dfhack-a8543f5ef034774e026cf434c11055783a68c9d9.tar.xz | |
Ported autodump tool
Diffstat (limited to 'plugins/autodump.cpp')
| -rw-r--r-- | plugins/autodump.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp new file mode 100644 index 00000000..87e82314 --- /dev/null +++ b/plugins/autodump.cpp @@ -0,0 +1,215 @@ +// Quick Dumper : Moves items marked as "dump" to cursor +// FIXME: local item cache in map blocks needs to be fixed after teleporting items +#include <iostream> +#include <iomanip> +#include <sstream> +#include <climits> +#include <vector> +#include <set> +using namespace std; + +#include <dfhack/Core.h> +#include <dfhack/Console.h> +#include <dfhack/Export.h> +#include <dfhack/PluginManager.h> +#include <vector> +#include <string> +#include <dfhack/modules/Maps.h> +#include <dfhack/modules/Gui.h> +#include <dfhack/modules/Items.h> +#include <dfhack/modules/Materials.h> +#include <dfhack/extra/MapExtras.h> + +using namespace DFHack; +using MapExtras::Block; +using MapExtras::MapCache; + +DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "autodump"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("autodump", + "Teleport items marked for dumping to the cursor.", + df_autodump)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +typedef std::map <DFCoord, uint32_t> coordmap; + +DFhackCExport command_result df_autodump (Core * c, vector <string> & parameters) +{ + // Command line options + bool destroy = false; + if(parameters.size() > 0) + { + string & p = parameters[0]; + if(p == "destroy") + destroy = true; + else if(p == "?" || p == "help") + { + c->con.print( + "This utility lets you quickly move all items designated to be dumped.\n" + "Items are instantly moved to the cursor position, the dump flag is unset,\n" + "and the forbid flag is set, as if it had been dumped normally.\n" + "Be aware that any active dump item tasks still point at the item.\n\n" + ); + return CR_OK; + } + } + c->Suspend(); + DFHack::occupancies40d * occupancies; + DFHack::VersionInfo *mem = c->vinfo; + DFHack::Gui * Gui = c->getGui(); + DFHack::Items * Items = c->getItems(); + DFHack::Maps *Maps = c->getMaps(); + + vector <t_item*> p_items; + if(!Items->readItemVector(p_items)) + { + c->con.printerr("Can't access the item vector.\n"); + c->Resume(); + return CR_FAILURE; + } + std::size_t numItems = p_items.size(); + + // init the map + if(!Maps->Start()) + { + c->con.printerr("Can't initialize map.\n"); + c->Resume(); + return CR_FAILURE; + } + MapCache MC (Maps); + int i = 0; + int dumped_total = 0; + + int cx, cy, cz; + DFCoord pos_cursor; + if(!destroy) + { + if (!Gui->getCursorCoords(cx,cy,cz)) + { + c->con.printerr("Cursor position not found. Please enabled the cursor.\n"); + c->Resume(); + return CR_FAILURE; + } + pos_cursor = DFCoord(cx,cy,cz); + { + Block * b = MC.BlockAt(pos_cursor / 16); + if(!b) + { + c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n"); + c->Resume(); + return CR_FAILURE; + } + uint16_t ttype = MC.tiletypeAt(pos_cursor); + if(!DFHack::isFloorTerrain(ttype)) + { + c->con.printerr("Cursor should be placed over a floor.\n"); + c->Resume(); + return CR_FAILURE; + } + } + } + coordmap counts; + // proceed with the dumpification operation + for(std::size_t i=0; i< numItems; i++) + { + t_item * itm = p_items[i]; + DFCoord pos_item(itm->x, itm->y, itm->z); + + // keep track how many items are at places. all items. + coordmap::iterator it = counts.find(pos_item); + if(it == counts.end()) + { + std::pair< coordmap::iterator, bool > inserted = counts.insert(std::make_pair(pos_item,1)); + it = inserted.first; + } + else + { + it->second ++; + } + // iterator is valid here, we use it later to decrement the pile counter if the item is moved + + // only dump the stuff marked for dumping and laying on the ground + if ( !itm->flags.dump + || !itm->flags.on_ground + || itm->flags.construction + || itm->flags.hidden + || itm->flags.in_building + || itm->flags.in_chest + || itm->flags.in_inventory + || itm->flags.construction + ) + continue; + + if(!destroy) // move to cursor + { + // Change flags to indicate the dump was completed, as if by super-dwarfs + itm->flags.dump = false; + itm->flags.forbid = true; + + // Don't move items if they're already at the cursor + if (pos_cursor == pos_item) + continue; + + // Move the item + itm->x = pos_cursor.x; + itm->y = pos_cursor.y; + itm->z = pos_cursor.z; + } + else // destroy + { + itm->flags.garbage_colect = true; + } + // keeping track of item pile sizes ;) + it->second --; + dumped_total++; + } + if(!destroy) // TODO: do we have to do any of this when destroying items? + { + // for each item pile, see if it reached zero. if so, unset item flag on the tile it's on + coordmap::iterator it = counts.begin(); + coordmap::iterator end = counts.end(); + while(it != end) + { + if(it->second == 0) + { + t_occupancy occ = MC.occupancyAt(it->first); + occ.bits.item = false; + MC.setOccupancyAt(it->first, occ); + } + it++; + } + // Set "item here" flag on target tile, if we moved any items to the target tile. + if (dumped_total > 0) + { + // assume there is a possibility the cursor points at some weird location with missing block data + Block * b = MC.BlockAt(pos_cursor / 16); + if(b) + { + t_occupancy occ = MC.occupancyAt(pos_cursor); + occ.bits.item = 1; + MC.setOccupancyAt(pos_cursor,occ); + } + } + // write map changes back to DF. + MC.WriteAll(); + // Is this necessary? Is "forbid" a dirtyable attribute like "dig" is? + Maps->WriteDirtyBit(cx/16, cy/16, cz, true); + } + c->Resume(); + c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for desctruction" : "quickdumped"); + return CR_OK; +}
\ No newline at end of file |
