631 lines
20 KiB
C++
631 lines
20 KiB
C++
/*******************************************************************************
|
|
M A P S
|
|
Read and write DF's map
|
|
*******************************************************************************/
|
|
#ifndef CL_MOD_MAPS
|
|
#define CL_MOD_MAPS
|
|
|
|
#include "dfhack/DFExport.h"
|
|
#include "dfhack/DFModule.h"
|
|
#include "Vegetation.h"
|
|
|
|
/**
|
|
* \defgroup grp_maps Maps module and its types
|
|
* @ingroup grp_modules
|
|
*/
|
|
|
|
namespace DFHack
|
|
{
|
|
/***************************************************************************
|
|
T Y P E S
|
|
***************************************************************************/
|
|
/**
|
|
* \ingroup grp_maps
|
|
*/
|
|
enum e_feature
|
|
{
|
|
feature_Other,
|
|
feature_Adamantine_Tube,
|
|
feature_Underworld,
|
|
feature_Hell_Temple
|
|
};
|
|
/**
|
|
* Function for translating feature index to its name
|
|
* \ingroup grp_maps
|
|
*/
|
|
extern DFHACK_EXPORT const char * sa_feature(e_feature index);
|
|
|
|
/**
|
|
* Class for holding a world coordinate. Can do math with coordinates and can be used as an index for std::map
|
|
* \ingroup grp_maps
|
|
*/
|
|
class DFCoord
|
|
{
|
|
public:
|
|
DFCoord(uint16_t _x, uint16_t _y, uint16_t _z = 0): x(_x), y(_y), z(_z) {}
|
|
DFCoord()
|
|
{
|
|
comparate = 0;
|
|
}
|
|
bool operator==(const DFCoord &other) const
|
|
{
|
|
return (other.comparate == comparate);
|
|
}
|
|
// FIXME: <tomprince> peterix_: you could probably get away with not defining operator< if you defined a std::less specialization for Vertex.
|
|
bool operator<(const DFCoord &other) const
|
|
{
|
|
return comparate < other.comparate;
|
|
}
|
|
DFCoord operator/(int number) const
|
|
{
|
|
return DFCoord(x/number, y/number, z);
|
|
}
|
|
DFCoord operator*(int number) const
|
|
{
|
|
return DFCoord(x*number, y*number, z);
|
|
}
|
|
DFCoord operator%(int number) const
|
|
{
|
|
return DFCoord(x%number, y%number, z);
|
|
}
|
|
DFCoord operator-(int number) const
|
|
{
|
|
return DFCoord(x,y,z-number);
|
|
}
|
|
DFCoord operator+(int number) const
|
|
{
|
|
return DFCoord(x,y,z+number);
|
|
}
|
|
// this is a hack. beware.
|
|
// x,y,z share the same space with comparate. comparate can be used for fast comparisons
|
|
union
|
|
{
|
|
// new shiny DFCoord struct. notice the ludicrous space for Z-levels
|
|
struct
|
|
{
|
|
uint16_t x;
|
|
uint16_t y;
|
|
uint32_t z;
|
|
};
|
|
// old planeccord struct for compatibility
|
|
struct
|
|
{
|
|
uint16_t x;
|
|
uint16_t y;
|
|
} dim;
|
|
// comparing thing
|
|
uint64_t comparate;
|
|
};
|
|
};
|
|
/**
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef DFCoord planecoord;
|
|
|
|
/**
|
|
* A local or global map feature
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct t_feature
|
|
{
|
|
e_feature type;
|
|
/// main material type - decides between stuff like bodily fluids, inorganics, vomit, amber, etc.
|
|
int16_t main_material;
|
|
/// generally some index to a vector of material types.
|
|
int32_t sub_material;
|
|
/// placeholder
|
|
bool discovered;
|
|
/// this is NOT part of the DF feature, but an address of the feature as seen by DFhack.
|
|
uint32_t origin;
|
|
};
|
|
|
|
/**
|
|
* mineral vein object - bitmap with a material type
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct t_vein
|
|
{
|
|
uint32_t vtable;
|
|
/// index into the inorganic material vector
|
|
int32_t type;
|
|
/// bit mask describing how the vein maps to the map block
|
|
/// assignment[y] & (1 << x) describes the tile (x, y) of the block
|
|
int16_t assignment[16];
|
|
uint32_t flags;
|
|
/// this is NOT part of the DF vein, but an address of the vein as seen by DFhack.
|
|
uint32_t address_of;
|
|
};
|
|
|
|
/**
|
|
* stores what tiles should appear when the ice melts - bitmap of material types
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct t_frozenliquidvein
|
|
{
|
|
uint32_t vtable;
|
|
/// a 16x16 array of the original tile types
|
|
int16_t tiles[16][16];
|
|
/// this is NOT part of the DF vein, but an address of the vein as seen by DFhack.
|
|
uint32_t address_of;
|
|
};
|
|
|
|
/**
|
|
* a 'spattervein' defines what coverings the individual map tiles have (snow, blood, etc)
|
|
* bitmap of intensity with matrial type
|
|
* \ingroup grp_maps
|
|
* @see PrintSplatterType
|
|
*/
|
|
struct t_spattervein
|
|
{
|
|
uint32_t vtable;
|
|
/// generic material.
|
|
uint16_t mat1;
|
|
uint16_t unk1;
|
|
/// material vector index
|
|
uint32_t mat2;
|
|
/// something even more specific?
|
|
uint16_t mat3;
|
|
/// 16x16 array of covering 'intensity'
|
|
uint8_t intensity[16][16];
|
|
/// this is NOT part of the DF vein, but an address of the vein as seen by DFhack.
|
|
uint32_t address_of;
|
|
};
|
|
/**
|
|
* a 'grass vein' defines the grass coverage of a map block
|
|
* bitmap of density (max = 100) with plant material type
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct t_grassvein
|
|
{
|
|
uint32_t vtable;
|
|
/// material vector index
|
|
uint32_t material;
|
|
/// 16x16 array of covering 'intensity'
|
|
uint8_t intensity[16][16];
|
|
/// this is NOT part of the DF vein, but an address of the vein as seen by DFhack.
|
|
uint32_t address_of;
|
|
};
|
|
/**
|
|
* defines the world constructions present. The material member is a mystery.
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct t_worldconstruction
|
|
{
|
|
uint32_t vtable;
|
|
/// material vector index
|
|
uint32_t material;
|
|
/// 16x16 array of bits
|
|
uint16_t assignment[16];
|
|
/// this is NOT part of the structure, but an address of it as seen by DFhack.
|
|
uint32_t address_of;
|
|
};
|
|
|
|
/**
|
|
* \ingroup grp_maps
|
|
*/
|
|
enum BiomeOffset
|
|
{
|
|
eNorthWest,
|
|
eNorth,
|
|
eNorthEast,
|
|
eWest,
|
|
eHere,
|
|
eEast,
|
|
eSouthWest,
|
|
eSouth,
|
|
eSouthEast,
|
|
eBiomeCount
|
|
};
|
|
|
|
/**
|
|
* \ingroup grp_maps
|
|
*/
|
|
enum e_traffic
|
|
{
|
|
traffic_normal,
|
|
traffic_low,
|
|
traffic_high,
|
|
traffic_restricted
|
|
};
|
|
|
|
/**
|
|
* type of a designation for a tile
|
|
* \ingroup grp_maps
|
|
*/
|
|
enum e_designation
|
|
{
|
|
/// no designation
|
|
designation_no,
|
|
/// dig walls, remove stairs and ramps, gather plants, fell trees. depends on tile type
|
|
designation_default,
|
|
/// dig up/down stairs
|
|
designation_ud_stair,
|
|
/// dig a channel
|
|
designation_channel,
|
|
/// dig ramp out of a wall
|
|
designation_ramp,
|
|
/// dig a stair down
|
|
designation_d_stair,
|
|
/// dig a stair up
|
|
designation_u_stair,
|
|
/// whatever. for completenes I guess
|
|
designation_7
|
|
};
|
|
|
|
/**
|
|
* type of liquid in a tile
|
|
* \ingroup grp_maps
|
|
*/
|
|
enum e_liquidtype
|
|
{
|
|
liquid_water,
|
|
liquid_magma
|
|
};
|
|
|
|
/**
|
|
* designation bit field
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct naked_designation
|
|
{
|
|
unsigned int flow_size : 3; // how much liquid is here?
|
|
unsigned int pile : 1; // stockpile?
|
|
/// All the different dig designations
|
|
e_designation dig : 3;
|
|
unsigned int smooth : 2;
|
|
unsigned int hidden : 1;
|
|
|
|
/**
|
|
* This one is rather involved, but necessary to retrieve the base layer matgloss index
|
|
* @see http://www.bay12games.com/forum/index.php?topic=608.msg253284#msg253284
|
|
*/
|
|
unsigned int geolayer_index :4;
|
|
unsigned int light : 1;
|
|
unsigned int subterranean : 1; // never seen the light of day?
|
|
unsigned int skyview : 1; // sky is visible now, it rains in here when it rains
|
|
|
|
/**
|
|
* Probably similar to the geolayer_index. Only with a different set of offsets and different data.
|
|
* we don't use this yet
|
|
*/
|
|
unsigned int biome : 4;
|
|
/**
|
|
* 0 = water
|
|
* 1 = magma
|
|
*/
|
|
e_liquidtype liquid_type : 1;
|
|
unsigned int water_table : 1; // srsly. wtf?
|
|
unsigned int rained : 1; // does this mean actual rain (as in the blue blocks) or a wet tile?
|
|
e_traffic traffic : 2;
|
|
/// the tile is not evaluated when calculating flows?
|
|
unsigned int flow_forbid : 1;
|
|
/// no liquid spreading
|
|
unsigned int liquid_static : 1;
|
|
/// this tile is a part of a local feature. can be combined with 'featstone' tiles
|
|
unsigned int feature_local : 1;
|
|
/// this tile is a part of a global feature. can be combined with 'featstone' tiles
|
|
unsigned int feature_global : 1;
|
|
unsigned int water_stagnant : 1;
|
|
unsigned int water_salt : 1;
|
|
};
|
|
/**
|
|
* designation bit field wrapper
|
|
* \ingroup grp_maps
|
|
*/
|
|
union t_designation
|
|
{
|
|
uint32_t whole;
|
|
naked_designation bits;
|
|
};
|
|
|
|
/*
|
|
* unsigned int mud : 1;
|
|
unsigned int vomit :1;*
|
|
unsigned int broken_arrows_color :4;
|
|
unsigned int blood_g : 1;
|
|
unsigned int blood_g2 : 1;
|
|
unsigned int blood_b : 1;
|
|
unsigned int blood_b2 : 1;
|
|
unsigned int blood_y : 1;
|
|
unsigned int blood_y2 : 1;
|
|
unsigned int blood_m : 1;
|
|
unsigned int blood_m2 : 1;
|
|
unsigned int blood_c : 1;
|
|
unsigned int blood_c2 : 1;
|
|
unsigned int blood_w : 1;
|
|
unsigned int blood_w2 : 1;
|
|
unsigned int blood_o : 1;
|
|
unsigned int blood_o2 : 1;
|
|
unsigned int slime : 1;
|
|
unsigned int slime2 : 1;
|
|
unsigned int blood : 1;
|
|
unsigned int blood2 : 1;
|
|
unsigned int broken_arrows_variant : 1;
|
|
unsigned int snow : 1;
|
|
*/
|
|
|
|
/**
|
|
* occupancy flags (rat,dwarf,horse,built wall,not build wall,etc)
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct naked_occupancy
|
|
{
|
|
/// 0-2: building type... should be an enum.
|
|
unsigned int building : 3;// 0-2
|
|
/// 3: the tile contains a standing creature
|
|
unsigned int unit : 1; // 3
|
|
/// 4: the tile contains a prone creature
|
|
unsigned int unit_grounded : 1;
|
|
/// 5: the tile contains an item
|
|
unsigned int item : 1;
|
|
/// 6
|
|
unsigned int unk6 : 1;
|
|
/// 7: mossy!
|
|
unsigned int moss : 1;
|
|
/// 8-11: arrow color related
|
|
unsigned int arrow_color : 4;
|
|
/// 12: arrow orientaton
|
|
unsigned int broken_arrows_variant : 1;
|
|
/// 13
|
|
unsigned int unk13 : 1;
|
|
/// 14: A monster lair. Items placed won't be moved.
|
|
unsigned int monster_lair : 1;
|
|
/**
|
|
* 15: seems to be set on terrain tiles where grass growth is impossible
|
|
* pebbles, boulders, rock floors in the middle of grass. also shrubs. but not trees
|
|
*/
|
|
unsigned int no_grow : 1;
|
|
/// 16
|
|
unsigned int unk16 : 1;
|
|
/// 17
|
|
unsigned int unk17 : 1;
|
|
/// 18
|
|
unsigned int unk18 : 1;
|
|
/// 19
|
|
unsigned int unk19 : 1;
|
|
|
|
/// 20
|
|
unsigned int unk20 : 1;
|
|
/// 21
|
|
unsigned int unk21 : 1;
|
|
/// 22
|
|
unsigned int unk22 : 1;
|
|
/// 23
|
|
unsigned int unk23 : 1;
|
|
|
|
/// 24
|
|
unsigned int unk24 : 1;
|
|
/// 25
|
|
unsigned int unk25 : 1;
|
|
/// 26
|
|
unsigned int unk26 : 1;
|
|
/// 27
|
|
unsigned int unk27 : 1;
|
|
|
|
/// 28
|
|
unsigned int unk28 : 1;
|
|
/// 29
|
|
unsigned int unk29 : 1;
|
|
/// 30
|
|
unsigned int unk30 : 1;
|
|
/// 31
|
|
unsigned int unk31 : 1;
|
|
};
|
|
/**
|
|
* occupancy flags (rat,dwarf,horse,built wall,not build wall,etc) wrapper
|
|
* \ingroup grp_maps
|
|
*/
|
|
union t_occupancy
|
|
{
|
|
uint32_t whole;
|
|
naked_occupancy bits;
|
|
};
|
|
|
|
/**
|
|
* map block flags
|
|
* \ingroup grp_maps
|
|
*/
|
|
struct naked_blockflags
|
|
{
|
|
/// designated for jobs (digging and stuff like that)
|
|
unsigned int designated : 1;
|
|
/// possibly related to the designated flag
|
|
unsigned int unk_1 : 1;
|
|
/// two flags required for liquid flow.
|
|
unsigned int liquid_1 : 1;
|
|
unsigned int liquid_2 : 1;
|
|
/// rest of the flags is completely unknown
|
|
unsigned int unk_2: 28;
|
|
// there's a possibility that this flags field is shorter than 32 bits
|
|
};
|
|
|
|
/**
|
|
* map block flags wrapper
|
|
* \ingroup grp_maps
|
|
*/
|
|
union t_blockflags
|
|
{
|
|
uint32_t whole;
|
|
naked_blockflags bits;
|
|
};
|
|
|
|
/**
|
|
* 16x16 array of tile types
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef int16_t tiletypes40d [16][16];
|
|
/**
|
|
* 16x16 array used for squashed block materials
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef int16_t t_blockmaterials [16][16];
|
|
/**
|
|
* 16x16 array of designation flags
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef DFHack::t_designation designations40d [16][16];
|
|
/**
|
|
* 16x16 array of occupancy flags
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef DFHack::t_occupancy occupancies40d [16][16];
|
|
/**
|
|
* array of 16 biome indexes valid for the block
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef uint8_t biome_indices40d [16];
|
|
/**
|
|
* 16x16 array of temperatures
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef uint16_t t_temperatures [16][16];
|
|
/**
|
|
* structure for holding whole blocks
|
|
* \ingroup grp_maps
|
|
*/
|
|
typedef struct
|
|
{
|
|
/// type of the tiles
|
|
tiletypes40d tiletypes;
|
|
/// flags determining the state of the tiles
|
|
designations40d designation;
|
|
/// flags determining what's on the tiles
|
|
occupancies40d occupancy;
|
|
/// values used for geology/biome assignment
|
|
biome_indices40d biome_indices;
|
|
/// the address where the block came from
|
|
uint32_t origin;
|
|
t_blockflags blockflags;
|
|
/// index into the global feature vector
|
|
int16_t global_feature;
|
|
/// index into the local feature vector... complicated
|
|
int16_t local_feature;
|
|
} mapblock40d;
|
|
|
|
class DFContextShared;
|
|
/**
|
|
* The Maps module
|
|
* \ingroup grp_modules
|
|
* \ingroup grp_maps
|
|
*/
|
|
class DFHACK_EXPORT Maps : public Module
|
|
{
|
|
public:
|
|
|
|
Maps(DFHack::DFContextShared * d);
|
|
~Maps();
|
|
bool Start();
|
|
bool Finish();
|
|
|
|
// read region surroundings, get their vectors of geolayers so we can do translation (or just hand the translation table to the client)
|
|
// returns an array of 9 vectors of indices into stone matgloss
|
|
/**
|
|
Method for reading the geological surrounding of the currently loaded region.
|
|
assign is a reference to an array of nine vectors of unsigned words that are to be filled with the data
|
|
array is indexed by the BiomeOffset enum
|
|
|
|
I omitted resolving the layer matgloss in this API, because it would
|
|
introduce overhead by calling some method for each tile. You have to do it
|
|
yourself.
|
|
|
|
First get the stuff from ReadGeology and then for each block get the RegionOffsets.
|
|
For each tile get the real region from RegionOffsets and cross-reference it with
|
|
the geology stuff (region -- array of vectors, depth -- vector).
|
|
I'm thinking about turning that Geology stuff into a two-dimensional array
|
|
with static size.
|
|
|
|
this is the algorithm for applying matgloss:
|
|
@code
|
|
void DfMap::applyGeoMatgloss(Block * b)
|
|
{
|
|
// load layer matgloss
|
|
for(int x_b = 0; x_b < BLOCK_SIZE; x_b++)
|
|
{
|
|
for(int y_b = 0; y_b < BLOCK_SIZE; y_b++)
|
|
{
|
|
int geolayer = b->designation[x_b][y_b].bits.geolayer_index;
|
|
int biome = b->designation[x_b][y_b].bits.biome;
|
|
b->material[x_b][y_b].type = Mat_Stone;
|
|
b->material[x_b][y_b].index = v_geology[b->RegionOffsets[biome]][geolayer];
|
|
}
|
|
}
|
|
}
|
|
@endcode
|
|
*/
|
|
bool ReadGeology( std::vector < std::vector <uint16_t> >& assign );
|
|
std::vector <t_feature> global_features;
|
|
// map between feature address and the read object
|
|
std::map <uint32_t, t_feature> local_feature_store;
|
|
// map between mangled coords and pointer to feature
|
|
|
|
bool ReadGlobalFeatures( std::vector <t_feature> & features);
|
|
bool ReadLocalFeatures( std::map <DFCoord, std::vector<t_feature *> > & local_features );
|
|
/*
|
|
* BLOCK DATA
|
|
*/
|
|
|
|
/// get size of the map in tiles
|
|
void getSize(uint32_t& x, uint32_t& y, uint32_t& z);
|
|
|
|
/**
|
|
* Return false/0 on failure, buffer allocated by client app, 256 items long
|
|
*/
|
|
bool isValidBlock(uint32_t blockx, uint32_t blocky, uint32_t blockz);
|
|
|
|
/**
|
|
* Get the address of a block or 0 if block is not valid
|
|
*/
|
|
uint32_t getBlockPtr (uint32_t blockx, uint32_t blocky, uint32_t blockz);
|
|
|
|
/// read the whole map block at block coords (see DFTypes.h for the block structure)
|
|
bool ReadBlock40d(uint32_t blockx, uint32_t blocky, uint32_t blockz, mapblock40d * buffer);
|
|
|
|
/// read/write block tile types
|
|
bool ReadTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, tiletypes40d *buffer);
|
|
bool WriteTileTypes(uint32_t blockx, uint32_t blocky, uint32_t blockz, tiletypes40d *buffer);
|
|
|
|
/// read/write block designations
|
|
bool ReadDesignations(uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer);
|
|
bool WriteDesignations (uint32_t blockx, uint32_t blocky, uint32_t blockz, designations40d *buffer);
|
|
|
|
/// read/write temperatures
|
|
bool ReadTemperatures(uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2);
|
|
bool WriteTemperatures (uint32_t blockx, uint32_t blocky, uint32_t blockz, t_temperatures *temp1, t_temperatures *temp2);
|
|
|
|
/// read/write block occupancies
|
|
bool ReadOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer);
|
|
bool WriteOccupancy(uint32_t blockx, uint32_t blocky, uint32_t blockz, occupancies40d *buffer);
|
|
|
|
/// read/write the block dirty bit - this is used to mark a map block so that DF scans it for designated jobs like digging
|
|
bool ReadDirtyBit(uint32_t blockx, uint32_t blocky, uint32_t blockz, bool &dirtybit);
|
|
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);
|
|
/// read/write features
|
|
bool ReadFeatures(uint32_t blockx, uint32_t blocky, uint32_t blockz, int16_t & local, int16_t & global);
|
|
bool WriteLocalFeature(uint32_t blockx, uint32_t blocky, uint32_t blockz, int16_t local = -1);
|
|
bool WriteGlobalFeature(uint32_t blockx, uint32_t blocky, uint32_t blockz, int16_t local = -1);
|
|
|
|
/// 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);
|
|
|
|
/// 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<t_vein>* veins,
|
|
std::vector<t_frozenliquidvein>* ices = 0,
|
|
std::vector<t_spattervein>* splatter = 0,
|
|
std::vector<t_grassvein>* grass = 0,
|
|
std::vector<t_worldconstruction>* constructions = 0
|
|
);
|
|
/// read all plants in this block
|
|
bool ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector<t_tree>* plants);
|
|
private:
|
|
struct Private;
|
|
Private *d;
|
|
};
|
|
}
|
|
#endif
|