summaryrefslogtreecommitdiff
path: root/plugins/autodump.cpp
diff options
context:
space:
mode:
authorPetr Mrázek2011-08-04 04:04:46 +0200
committerPetr Mrázek2011-08-04 04:04:46 +0200
commita8543f5ef034774e026cf434c11055783a68c9d9 (patch)
tree5c90de5546a604e3c080bf152ddf080b33c7f146 /plugins/autodump.cpp
parentff4d545ae71eaf732afdb4200f6c409aebe91280 (diff)
downloaddfhack-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.cpp215
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