diff --git a/dfhack/DFHackAPI.cpp b/dfhack/DFHackAPI.cpp index 762cbca59..a1dbeddad 100644 --- a/dfhack/DFHackAPI.cpp +++ b/dfhack/DFHackAPI.cpp @@ -59,7 +59,6 @@ API::API (const string path_to_xml) API::~API() { - // FIXME: call all finishread* methods here Detach(); delete d; } diff --git a/dfhack/include/DFHackAPI.h b/dfhack/include/DFHackAPI.h index 2852ac155..f802e4b64 100644 --- a/dfhack/include/DFHackAPI.h +++ b/dfhack/include/DFHackAPI.h @@ -154,14 +154,6 @@ namespace DFHack bool ReadCurrentSettlement(t_settlement & settlement); void FinishReadSettlements(); */ - /* - * Hotkeys (DF's zoom locations) - */ - /* - bool InitReadHotkeys( ); - bool ReadHotkeys(t_hotkey hotkeys[]); - */ - /* * Item reading */ diff --git a/dfhack/include/DFTileTypes.h b/dfhack/include/DFTileTypes.h index 4ec224241..8931a8422 100644 --- a/dfhack/include/DFTileTypes.h +++ b/dfhack/include/DFTileTypes.h @@ -74,7 +74,8 @@ namespace DFHack CAMPFIRE, FIRE, ASHES, - CONSTRUCTED + CONSTRUCTED, + CYAN_GLOW }; enum TileVariant { @@ -410,11 +411,11 @@ namespace DFHack {"ice floor" ,FLOOR, ICE, VAR_4}, {"furrowed soil" ,FLOOR, SOIL, VAR_1}, {"ice floor" ,FLOOR, ICE, VAR_1}, - {0 ,EMPTY, AIR, VAR_1}, - {"magma" ,FLOOR, MAGMA, VAR_1}, // is it really a floor? + {"semi-molten rock" ,WALL, MAGMA, VAR_1},// unminable magma wall + {"magma" ,FLOOR, MAGMA, VAR_1}, {"soil wall" ,WALL, SOIL, VAR_1}, {0 ,EMPTY, AIR, VAR_1}, - {0 ,EMPTY, AIR, VAR_1}, + {"glowing floor" ,FLOOR, CYAN_GLOW, VAR_1}, {0 ,EMPTY, AIR, VAR_1}, {"smooth obsidian wall",WALL,OBSIDIAN,VAR_1}, diff --git a/dfhack/include/DFTypes.h b/dfhack/include/DFTypes.h index 40377dbdc..c1cf2186e 100644 --- a/dfhack/include/DFTypes.h +++ b/dfhack/include/DFTypes.h @@ -214,15 +214,6 @@ struct t_note uint16_t z; }; -#define NUM_HOTKEYS 16 -struct t_hotkey -{ - char name[10]; - int16_t mode; - int32_t x; - int32_t y; - int32_t z; -}; // local are numbered with top left as 0,0, name is indexes into the item vector struct t_settlement diff --git a/dfhack/include/modules/Maps.h b/dfhack/include/modules/Maps.h index f1d2fdce9..67b8f239d 100644 --- a/dfhack/include/modules/Maps.h +++ b/dfhack/include/modules/Maps.h @@ -300,15 +300,21 @@ namespace DFHack bool WriteDirtyBit(uint32_t blockx, uint32_t blocky, uint32_t blockz, bool dirtybit); /// read/write the block flags - bool ReadBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_blockflags &blockflags); - bool WriteBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_blockflags blockflags); + bool ReadBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, + t_blockflags &blockflags); + bool WriteBlockFlags(uint32_t blockx, uint32_t blocky, uint32_t blockz, + t_blockflags blockflags); /// read region offsets of a block - used for determining layer stone matgloss - bool ReadRegionOffsets(uint32_t blockx, uint32_t blocky, uint32_t blockz, biome_indices40d *buffer); + bool ReadRegionOffsets(uint32_t blockx, uint32_t blocky, uint32_t blockz, + biome_indices40d *buffer); - /// read aggregated veins of a block - bool ReadVeins(uint32_t blockx, uint32_t blocky, uint32_t blockz, std::vector & veins, std::vector & ices, std::vector & splatter); - + /// block event reading - mineral veins, what's under ice, blood smears and mud + bool ReadVeins(uint32_t x, uint32_t y, uint32_t z, + std::vector* veins, + std::vector* ices = 0, + std::vector* splatter = 0); + private: struct Private; Private *d; diff --git a/dfhack/include/modules/Position.h b/dfhack/include/modules/Position.h index 338316e3c..8ecf5bae6 100644 --- a/dfhack/include/modules/Position.h +++ b/dfhack/include/modules/Position.h @@ -6,6 +6,16 @@ #include "Export.h" namespace DFHack { + #define NUM_HOTKEYS 16 + struct t_hotkey + { + char name[10]; + int16_t mode; + int32_t x; + int32_t y; + int32_t z; + }; + class APIPrivate; class DFHACK_EXPORT Position { @@ -22,6 +32,11 @@ namespace DFHack bool getCursorCoords (int32_t &x, int32_t &y, int32_t &z); bool setCursorCoords (const int32_t x, const int32_t y, const int32_t z); + /* + * Hotkeys (DF's zoom locations) + */ + bool ReadHotkeys(t_hotkey hotkeys[]); + /* * Window size in tiles */ diff --git a/dfhack/modules/Maps.cpp b/dfhack/modules/Maps.cpp index fb5feb19e..e3e0f48d6 100644 --- a/dfhack/modules/Maps.cpp +++ b/dfhack/modules/Maps.cpp @@ -327,69 +327,73 @@ bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices4 // veins of a block, expects empty vein vectors -bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector & veins, vector & ices, vector &splatter) +bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector * veins, vector * ices, vector *splatter) { + t_vein v; + t_frozenliquidvein fv; + t_spattervein sv; + uint32_t addr = d->block[x*d->y_block_count*d->z_block_count + y*d->z_block_count + z]; - veins.clear(); - ices.clear(); + if(veins) veins->clear(); + if(ices) ices->clear(); + if(splatter) splatter->clear(); + Server::Maps::maps_offsets &off = d->offsets; - if (addr && off.veinvector) + if (addr) { // veins are stored as a vector of pointers to veins /*pointer is 4 bytes! we work with a 32bit program here, no matter what architecture we compile khazad for*/ DfVector p_veins (d->d->p, addr + off.veinvector, 4); uint32_t size = p_veins.getSize(); - veins.reserve (size); - // read all veins for (uint32_t i = 0; i < size;i++) { - t_vein v; - t_frozenliquidvein fv; - t_spattervein sv; - // read the vein pointer from the vector uint32_t temp = * (uint32_t *) p_veins[i]; uint32_t type = g_pProcess->readDWord(temp); try_again: - if(type == off.vein_mineral_vptr) + if(veins && type == off.vein_mineral_vptr) { // read the vein data (dereference pointer) g_pProcess->read (temp, sizeof(t_vein), (uint8_t *) &v); v.address_of = temp; // store it in the vector - veins.push_back (v); + veins->push_back (v); } - else if(type == off.vein_ice_vptr) + else if(ices && type == off.vein_ice_vptr) { // read the ice vein data (dereference pointer) g_pProcess->read (temp, sizeof(t_frozenliquidvein), (uint8_t *) &fv); fv.address_of = temp; // store it in the vector - ices.push_back (fv); + ices->push_back (fv); } - else if(type == off.vein_spatter_vptr) + else if(splatter && type == off.vein_spatter_vptr) { // read the splatter vein data (dereference pointer) g_pProcess->read (temp, sizeof(t_spattervein), (uint8_t *) &sv); sv.address_of = temp; // store it in the vector - splatter.push_back (sv); + splatter->push_back (sv); } - else if(g_pProcess->readClassName(type) == "block_square_event_frozen_liquidst") + else { - off.vein_ice_vptr = type; - goto try_again; - } - else if(g_pProcess->readClassName(type) == "block_square_event_mineralst") - { - off.vein_mineral_vptr = type; - goto try_again; - } - else if(g_pProcess->readClassName(type) == "block_square_event_material_spatterst") - { - off.vein_spatter_vptr = type; - goto try_again; + if(g_pProcess->readClassName(type) == "block_square_event_frozen_liquidst") + { + off.vein_ice_vptr = type; + goto try_again; + } + else if(g_pProcess->readClassName(type) == "block_square_event_mineralst") + { + off.vein_mineral_vptr = type; + goto try_again; + } + else if(g_pProcess->readClassName(type) == "block_square_event_material_spatterst") + { + off.vein_spatter_vptr = type; + goto try_again; + } + // or it was something we don't care about } } return true; @@ -397,7 +401,6 @@ try_again: return false; } - // getter for map size void Maps::getSize (uint32_t& x, uint32_t& y, uint32_t& z) { diff --git a/examples/materialtest.cpp b/examples/materialtest.cpp index 09f414fdf..db7e5d2a8 100644 --- a/examples/materialtest.cpp +++ b/examples/materialtest.cpp @@ -46,7 +46,7 @@ int main (int numargs, const char ** args) Materials->ReadInorganicMaterials (matgloss); for(uint32_t i = 0; i < matgloss.size();i++) { - cout << matgloss[i].id << endl; + cout << i << ": " << matgloss[i].id << endl; } cout << endl << "----==== Organic ====----" << endl; @@ -54,14 +54,14 @@ int main (int numargs, const char ** args) Materials->ReadOrganicMaterials (matgloss); for(uint32_t i = 0; i < matgloss.size();i++) { - cout << matgloss[i].id << endl; + cout << i << ": " << matgloss[i].id << endl; } cout << endl << "----==== Creature types ====----" << endl; vector creature; Materials->ReadCreatureTypes (matgloss); for(uint32_t i = 0; i < matgloss.size();i++) { - cout << matgloss[i].id << endl; + cout << i << ": " << matgloss[i].id << endl; } #ifndef LINUX_BUILD cout << "Done. Press any key to continue" << endl; diff --git a/examples/spatterdump.cpp b/examples/spatterdump.cpp index 3eae5a737..1f7aca438 100644 --- a/examples/spatterdump.cpp +++ b/examples/spatterdump.cpp @@ -124,7 +124,7 @@ int main (int numargs, const char ** args) if(Maps->isValidBlock(x,y,z)) { // look for splater veins - Maps->ReadVeins(x,y,z,veinVector,IceVeinVector,splatter); + Maps->ReadVeins(x,y,z,0,0,&splatter); if(splatter.size()) { printf("Block %d/%d/%d\n",x,y,z); @@ -159,7 +159,7 @@ int main (int numargs, const char ** args) by = cy / 16; bz = cz; // look for splater veins - Maps->ReadVeins(bx,by,bz,veinVector,IceVeinVector,splatter); + Maps->ReadVeins(bx,by,bz,0,0,&splatter); if(splatter.size()) { printf("Block %d/%d/%d\n",bx,by,bz); diff --git a/examples/veccheck.cpp b/examples/veccheck.cpp index 31f38f063..c20ec9742 100644 --- a/examples/veccheck.cpp +++ b/examples/veccheck.cpp @@ -18,6 +18,7 @@ using namespace std; #include #include #include +#include #include #include "miscutils.h" @@ -41,29 +42,22 @@ int main (int numargs, const char ** args) DFHack::Position *Pos = DF.getPosition(); - DFHack::Constructions *Cons = DF.getConstructions(); - uint32_t numConstr; - Cons->Start(numConstr); + DFHack::Maps *Maps = DF.getMaps(); + Maps->Start(); int32_t cx, cy, cz; Pos->getCursorCoords(cx,cy,cz); if(cx != -30000) { - t_construction con; - for(uint32_t i = 0; i < numConstr; i++) + uint32_t bx = cx / 16; + uint32_t tx = cx % 16; + uint32_t by = cy / 16; + uint32_t ty = cy % 16; + mapblock40d block; + if(Maps->ReadBlock40d(bx,by,cz,&block)) { - Cons->Read(i,con); - if(cx == con.x && cy == con.y && cz == con.z) - { - printf("Construction %d/%d/%d @ 0x%x - Material %d %d\n", con.x, con.y, con.z,con.origin, con.mat_type, con.mat_idx); - printf("Material form: %d ", con.form); - if(con.form == 4) - { - printf("It is rough."); - } - printf("\n"); - hexdump(DF,con.origin,2); - } + int16_t tiletype = block.tiletypes[tx][ty]; + cout << tiletype << endl; } } #ifndef LINUX_BUILD diff --git a/examples/veinlook.cpp b/examples/veinlook.cpp index 14f056d84..761d2359f 100644 --- a/examples/veinlook.cpp +++ b/examples/veinlook.cpp @@ -500,7 +500,7 @@ main(int argc, char *argv[]) if(i == 0 && j == 0) { // read veins - Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,veinVector,IceVeinVector,splatter); + Maps->ReadVeins(cursorX+i,cursorY+j,cursorZ,&veinVector,&IceVeinVector,&splatter); // get pointer to block blockaddr = Maps->getBlockPtr(cursorX+i,cursorY+j,cursorZ); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index caed672f1..5f6ac01f3 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -13,6 +13,10 @@ TARGET_LINK_LIBRARIES(dfreveal dfhack) ADD_EXECUTABLE(dfprospector prospector.cpp) TARGET_LINK_LIBRARIES(dfprospector dfhack) +# vdig - dig the vein under the cursor +ADD_EXECUTABLE(dfvdig vdig.cpp) +TARGET_LINK_LIBRARIES(dfvdig dfhack) + # cleanmap - removes mud, snow, blood and similar stuff from a map. farmers beware ADD_EXECUTABLE(dfcleanmap cleanmap.cpp) TARGET_LINK_LIBRARIES(dfcleanmap dfhack) diff --git a/tools/cleanmap.cpp b/tools/cleanmap.cpp index 8701cea18..e9a5b8e5a 100644 --- a/tools/cleanmap.cpp +++ b/tools/cleanmap.cpp @@ -16,8 +16,6 @@ int main (void) uint32_t x_max,y_max,z_max; uint32_t num_blocks = 0; uint32_t bytes_read = 0; - vector veinVector; - vector IceVeinVector; vector splatter; DFHack::API DF("Memory.xml"); @@ -58,7 +56,7 @@ int main (void) { if(Mapz->isValidBlock(x,y,z)) { - Mapz->ReadVeins(x,y,z,veinVector,IceVeinVector,splatter); + Mapz->ReadVeins(x,y,z,0,0,&splatter); for(uint32_t i = 0; i < splatter.size(); i++) { DFHack::t_spattervein & vein = splatter[i]; diff --git a/tools/prospector.cpp b/tools/prospector.cpp index f75cedd96..b64790793 100644 --- a/tools/prospector.cpp +++ b/tools/prospector.cpp @@ -109,8 +109,6 @@ int main (int argc, const char* argv[]) int16_t tempvein [16][16]; vector veins; - vector iceveins; - vector splatter; uint32_t maximum_regionoffset = 0; uint32_t num_overflows = 0; // walk the map! @@ -129,7 +127,7 @@ int main (int argc, const char* argv[]) memset(tempvein, -1, sizeof(tempvein)); veins.clear(); - Maps->ReadVeins(x,y,z,veins,iceveins,splatter); + Maps->ReadVeins(x,y,z,&veins); if(showbaselayers) { diff --git a/tools/vdig.cpp b/tools/vdig.cpp new file mode 100644 index 000000000..093eae8c4 --- /dev/null +++ b/tools/vdig.cpp @@ -0,0 +1,371 @@ +#include +#include +#include // for memset +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_DIM 0x300 +class Point +{ + public: + Point(uint32_t x, uint32_t y) + { + this->x = x; + this->y = y; + } + bool operator==(const Point &other) const + { + return (other.x == x && other.y == y); + } + bool operator<(const Point &other) const + { + return ( (y*MAX_DIM + x) < (other.y*MAX_DIM + other.x)); + } + Point operator/(int number) const + { + return Point(x/number, y/number); + } + Point operator%(int number) const + { + return Point(x%number, y%number); + } + uint32_t x; + uint32_t y; +}; + +class Block +{ + public: + Block(DFHack::Maps *_m, uint32_t x_, uint32_t y_, uint32_t z_) + { + vector veins; + m = _m; + dirty = false; + valid = false; + x = x_; + y = y_; + z = z_; + if(m->ReadBlock40d(x_,y_,z_,&raw)) + { + memset(materials,-1,sizeof(materials)); + memset(bitmap,0,sizeof(bitmap)); + m->ReadVeins(x,y,z,&veins); + // for each vein + for(int i = 0; i < (int)veins.size();i++) + { + //iterate through vein rows + for(uint32_t j = 0;j<16;j++) + { + //iterate through the bits + for (uint32_t k = 0; k< 16;k++) + { + // check if it's really a vein (FIXME: doing this too many times) + int16_t tt = raw.tiletypes[k][j]; + if(DFHack::isWallTerrain(tt) && DFHack::tileTypeTable[tt].m == DFHack::VEIN) + { + // and the bit array with a one-bit mask, check if the bit is set + bool set = !!(((1 << k) & veins[i].assignment[j]) >> k); + if(set) + { + // store matgloss + materials[k][j] = veins[i].type; + } + } + } + } + } + valid = true; + } + } + int16_t MaterialAt(Point p) + { + return materials[p.x][p.y]; + } + void ClearMaterialAt(Point p) + { + materials[p.x][p.y] = -1; + } + int16_t TileTypeAt(Point p) + { + return raw.tiletypes[p.x][p.y]; + } + DFHack::t_designation DesignationAt(Point p) + { + return raw.designation[p.x][p.y]; + } + DFHack::t_designation setDesignationAt(Point p, DFHack::t_designation des) + { + dirty = true; + //printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y); + raw.designation[p.x][p.y] = des; + } + bool WriteDesignations () + { + if(dirty) + { + //printf("writing %d/%d/%d\n",x,y,z); + m->WriteDesignations(x,y,z, &raw.designation); + m->WriteDirtyBit(x,y,z,true); + } + } + bool valid; + bool dirty; + DFHack::Maps * m; + DFHack::mapblock40d raw; + uint32_t x; + uint32_t y; + uint32_t z; + int16_t materials[16][16]; + int8_t bitmap[16][16]; +}; + +class Layer +{ + public: + Layer(DFHack::Maps * Maps, uint32_t _z) + { + valid = 0; + this->Maps = Maps; + z = _z; + uint32_t z_max; + Maps->getSize(x_bmax, y_bmax, z_max); + if(z < z_max) + valid = true; + }; + ~Layer() + { + map::iterator p; + for(p = blocks.begin(); p != blocks.end(); p++) + { + delete p->second; + //cout << stonetypes[p->first].id << " : " << p->second << endl; + } + } + bool isValid () + { + return valid; + } + + Block * BlockAt (Point blockcoord) + { + if(!valid) return 0; + + map ::iterator iter = blocks.find(blockcoord); + if(iter != blocks.end()) + { + return (*iter).second; + } + else + { + Block * nblo = new Block(Maps,blockcoord.x,blockcoord.y,z); + blocks[blockcoord] = nblo; + } + } + + uint16_t tiletypeAt (Point tilecoord) + { + Block * b= BlockAt(tilecoord / 16); + if(b && b->valid) + { + return b->TileTypeAt(tilecoord % 16); + } + return 0; + } + + int16_t materialAt (Point tilecoord) + { + Block * b= BlockAt(tilecoord / 16); + if(b && b->valid) + { + return b->MaterialAt(tilecoord % 16); + } + return 0; + } + bool clearMaterialAt (Point tilecoord) + { + Block * b= BlockAt(tilecoord / 16); + if(b && b->valid) + { + b->ClearMaterialAt(tilecoord % 16); + } + return 0; + } + + + DFHack::t_designation designationAt (Point tilecoord) + { + Block * b= BlockAt(tilecoord / 16); + if(b && b->valid) + { + return b->DesignationAt(tilecoord % 16); + } + DFHack:: t_designation temp; + temp.whole = 0; + return temp; + } + bool setDesignationAt (Point tilecoord, DFHack::t_designation des) + { + Block * b= BlockAt(tilecoord / 16); + if(b && b->valid) + { + b->setDesignationAt(tilecoord % 16, des); + return true; + } + return false; + } + + bool WriteAll() + { + map::iterator p; + for(p = blocks.begin(); p != blocks.end(); p++) + { + p->second->WriteDesignations(); + //cout << stonetypes[p->first].id << " : " << p->second << endl; + } + } + private: + bool valid; + uint32_t z; + uint32_t x_bmax; + uint32_t y_bmax; + uint32_t x_tmax; + uint32_t y_tmax; + DFHack::Maps * Maps; + map blocks; +}; + +int main (int argc, const char* argv[]) +{ + + DFHack::API DF("Memory.xml"); + try + { + DF.Attach(); + } + catch (exception& e) + { + cerr << e.what() << endl; + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + uint32_t x_max,y_max,z_max; + DFHack::Maps * Maps = DF.getMaps(); + DFHack::Materials * Mats = DF.getMaterials(); + DFHack::Position * Pos = DF.getPosition(); + + // init the map + if(!Maps->Start()) + { + cerr << "Can't init map." << endl; + DF.Detach(); + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + + int32_t cx, cy, cz; + Maps->getSize(x_max,y_max,z_max); + Pos->getCursorCoords(cx,cy,cz); + while(cx == -30000) + { + cerr << "Cursor is not active. Point the cursor at a vein." << endl; + DF.Resume(); + cin.ignore(); + DF.Suspend(); + Pos->getCursorCoords(cx,cy,cz); + } + + Layer * L = new Layer(Maps,cz); + + Point xy ((uint32_t)cx,(uint32_t)cy); + DFHack::t_designation des = L->designationAt(xy); + int16_t tt = L->tiletypeAt(xy); + int16_t veinmat = L->materialAt(xy); + + if( veinmat == -1 ) + { + cerr << "This tile is non-vein. Bye :)" << endl; + delete L; + DF.Detach(); + #ifndef LINUX_BUILD + cin.ignore(); + #endif + return 1; + } + printf("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x\n", cx,cy,cz, tt, veinmat, des.whole); + stack flood; + flood.push(xy); + uint32_t tx_max = x_max * 16; + uint32_t ty_max = y_max * 16; + + while( !flood.empty() ) + { + Point current = flood.top(); + flood.pop(); + int16_t vmat2 = L->materialAt(current); + + if(vmat2!=veinmat) + continue; + + // found a good tile, dig+unset material + DFHack::t_designation des = L->designationAt(current); + des.bits.dig = DFHack::designation_default; + if(L->setDesignationAt(current,des)) + { + L->clearMaterialAt(current); + if(current.x < tx_max) + { + flood.push(Point(current.x + 1, current.y)); + if(current.y < ty_max) + { + flood.push(Point(current.x + 1, current.y + 1)); + flood.push(Point(current.x, current.y + 1)); + } + if(current.y != 0) + { + flood.push(Point(current.x + 1, current.y - 1)); + flood.push(Point(current.x, current.y - 1)); + } + } + if(current.x != 0) + { + flood.push(Point(current.x - 1, current.y)); + if(current.y < ty_max) + { + flood.push(Point(current.x - 1, current.y + 1)); + flood.push(Point(current.x, current.y + 1)); + } + if(current.y != 0) + { + flood.push(Point(current.x - 1, current.y - 1)); + flood.push(Point(current.x, current.y - 1)); + } + } + } + } + L->WriteAll(); + delete L; + DF.Detach(); + #ifndef LINUX_BUILD + cout << "Done. Press any key to continue" << endl; + cin.ignore(); + #endif + return 0; +} +