dfhack/library/include/modules/MapCache.h

460 lines
12 KiB
C++

/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#ifndef MAPEXTRAS_H
#define MAPEXTRAS_H
#include "modules/Maps.h"
#include "TileTypes.h"
#include <stdint.h>
#include <cstring>
#include "df/map_block.h"
#include "df/block_square_event_mineralst.h"
using namespace DFHack;
using namespace DFHack::Simple;
namespace MapExtras
{
void SquashVeins (DFCoord bcoord, mapblock40d & mb, t_blockmaterials & materials)
{
memset(materials,-1,sizeof(materials));
std::vector <df::block_square_event_mineralst *> veins;
Maps::SortBlockEvents(bcoord.x,bcoord.y,bcoord.z,&veins);
//iterate through block rows
for(uint32_t j = 0;j<16;j++)
{
//iterate through columns
for (uint32_t k = 0; k< 16;k++)
{
int16_t tt = mb.tiletypes[k][j];
if(DFHack::tileMaterial(tt) == DFHack::VEIN)
{
for(int i = (int) veins.size() - 1; i >= 0;i--)
{
if(!!(((1 << k) & veins[i]->tile_bitmask[j]) >> k))
{
materials[k][j] = veins[i]->inorganic_mat;
i = -1;
}
}
}
}
}
}
void SquashRocks ( std::vector< std::vector <uint16_t> > * layerassign, DFHack::mapblock40d & mb, DFHack::t_blockmaterials & materials)
{
// get the layer materials
for(uint32_t xx = 0;xx<16;xx++)
{
for (uint32_t yy = 0; yy< 16;yy++)
{
uint8_t test = mb.designation[xx][yy].bits.biome;
if( test >= sizeof(mb.biome_indices))
{
materials[xx][yy] = -1;
continue;
}
materials[xx][yy] =
layerassign->at(mb.biome_indices[test])[mb.designation[xx][yy].bits.geolayer_index];
}
}
}
class Block
{
public:
Block(DFHack::DFCoord _bcoord, std::vector< std::vector <uint16_t> > * layerassign = 0)
{
dirty_designations = false;
dirty_tiletypes = false;
dirty_temperatures = false;
dirty_blockflags = false;
dirty_occupancies = false;
valid = false;
bcoord = _bcoord;
if(Maps::ReadBlock40d(bcoord.x,bcoord.y,bcoord.z,&raw))
{
Maps::ReadTemperatures(bcoord.x,bcoord.y, bcoord.z,&temp1,&temp2);
SquashVeins(bcoord,raw,veinmats);
if(layerassign)
SquashRocks(layerassign,raw,basemats);
else
memset(basemats,-1,sizeof(basemats));
valid = true;
}
}
int16_t veinMaterialAt(df::coord2d p)
{
return veinmats[p.x][p.y];
}
int16_t baseMaterialAt(df::coord2d p)
{
return basemats[p.x][p.y];
}
void ClearMaterialAt(df::coord2d p)
{
veinmats[p.x][p.y] = -1;
}
uint16_t TileTypeAt(df::coord2d p)
{
return raw.tiletypes[p.x][p.y];
}
bool setTiletypeAt(df::coord2d p, uint16_t tiletype)
{
if(!valid) return false;
dirty_tiletypes = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
raw.tiletypes[p.x][p.y] = tiletype;
return true;
}
uint16_t temperature1At(df::coord2d p)
{
return temp1[p.x][p.y];
}
bool setTemp1At(df::coord2d p, uint16_t temp)
{
if(!valid) return false;
dirty_temperatures = true;
temp1[p.x][p.y] = temp;
return true;
}
uint16_t temperature2At(df::coord2d p)
{
return temp2[p.x][p.y];
}
bool setTemp2At(df::coord2d p, uint16_t temp)
{
if(!valid) return false;
dirty_temperatures = true;
temp2[p.x][p.y] = temp;
return true;
}
df::tile_designation DesignationAt(df::coord2d p)
{
return raw.designation[p.x][p.y];
}
bool setDesignationAt(df::coord2d p, df::tile_designation des)
{
if(!valid) return false;
dirty_designations = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
raw.designation[p.x][p.y] = des;
if(des.bits.dig)
{
dirty_blockflags = true;
raw.blockflags.bits.designated = true;
}
return true;
}
df::tile_occupancy OccupancyAt(df::coord2d p)
{
return raw.occupancy[p.x][p.y];
}
bool setOccupancyAt(df::coord2d p, df::tile_occupancy des)
{
if(!valid) return false;
dirty_occupancies = true;
raw.occupancy[p.x][p.y] = des;
return true;
}
DFHack::t_blockflags BlockFlags()
{
return raw.blockflags;
}
bool setBlockFlags(DFHack::t_blockflags des)
{
if(!valid) return false;
dirty_blockflags = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
raw.blockflags = des;
return true;
}
bool Write ()
{
if(!valid) return false;
if(dirty_designations)
{
Maps::WriteDesignations(bcoord.x,bcoord.y,bcoord.z, &raw.designation);
Maps::WriteDirtyBit(bcoord.x,bcoord.y,bcoord.z,true);
dirty_designations = false;
}
if(dirty_tiletypes)
{
Maps::WriteTileTypes(bcoord.x,bcoord.y,bcoord.z, &raw.tiletypes);
dirty_tiletypes = false;
}
if(dirty_temperatures)
{
Maps::WriteTemperatures(bcoord.x,bcoord.y,bcoord.z, &temp1, &temp2);
dirty_temperatures = false;
}
if(dirty_blockflags)
{
Maps::WriteBlockFlags(bcoord.x,bcoord.y,bcoord.z,raw.blockflags);
dirty_blockflags = false;
}
if(dirty_occupancies)
{
Maps::WriteOccupancy(bcoord.x,bcoord.y,bcoord.z,&raw.occupancy);
dirty_occupancies = false;
}
return true;
}
bool valid:1;
bool dirty_designations:1;
bool dirty_tiletypes:1;
bool dirty_temperatures:1;
bool dirty_blockflags:1;
bool dirty_occupancies:1;
DFHack::mapblock40d raw;
DFHack::DFCoord bcoord;
DFHack::t_blockmaterials veinmats;
DFHack::t_blockmaterials basemats;
DFHack::t_temperatures temp1;
DFHack::t_temperatures temp2;
};
class MapCache
{
public:
MapCache()
{
valid = 0;
Maps::getSize(x_bmax, y_bmax, z_max);
validgeo = Maps::ReadGeology( layerassign );
valid = true;
};
~MapCache()
{
trash();
}
bool isValid ()
{
return valid;
}
/// get the map block at a *block* coord. Block coord = tile coord / 16
Block * BlockAt (DFHack::DFCoord blockcoord)
{
if(!valid)
return 0;
std::map <DFHack::DFCoord, Block*>::iterator iter = blocks.find(blockcoord);
if(iter != blocks.end())
{
return (*iter).second;
}
else
{
if(blockcoord.x < x_bmax && blockcoord.y < y_bmax && blockcoord.z < z_max)
{
Block * nblo;
if(validgeo)
nblo = new Block(blockcoord, &layerassign);
else
nblo = new Block(blockcoord);
blocks[blockcoord] = nblo;
return nblo;
}
return 0;
}
}
uint16_t tiletypeAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->TileTypeAt(tilecoord % 16);
}
return 0;
}
bool setTiletypeAt(DFHack::DFCoord tilecoord, uint16_t tiletype)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setTiletypeAt(tilecoord % 16, tiletype);
return true;
}
return false;
}
uint16_t temperature1At (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->temperature1At(tilecoord % 16);
}
return 0;
}
bool setTemp1At(DFHack::DFCoord tilecoord, uint16_t temperature)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setTemp1At(tilecoord % 16, temperature);
return true;
}
return false;
}
uint16_t temperature2At (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->temperature2At(tilecoord % 16);
}
return 0;
}
bool setTemp2At(DFHack::DFCoord tilecoord, uint16_t temperature)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setTemp2At(tilecoord % 16, temperature);
return true;
}
return false;
}
int16_t veinMaterialAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->veinMaterialAt(tilecoord % 16);
}
return 0;
}
int16_t baseMaterialAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->baseMaterialAt(tilecoord % 16);
}
return 0;
}
bool clearMaterialAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->ClearMaterialAt(tilecoord % 16);
}
return 0;
}
df::tile_designation designationAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->DesignationAt(tilecoord % 16);
}
df::tile_designation temp;
temp.whole = 0;
return temp;
}
bool setDesignationAt (DFHack::DFCoord tilecoord, df::tile_designation des)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setDesignationAt(tilecoord % 16, des);
return true;
}
return false;
}
df::tile_occupancy occupancyAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->OccupancyAt(tilecoord % 16);
}
df::tile_occupancy temp;
temp.whole = 0;
return temp;
}
bool setOccupancyAt (DFHack::DFCoord tilecoord, df::tile_occupancy occ)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setOccupancyAt(tilecoord % 16, occ);
return true;
}
return false;
}
bool testCoord (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return true;
}
return false;
}
bool WriteAll()
{
std::map<DFHack::DFCoord, Block *>::iterator p;
for(p = blocks.begin(); p != blocks.end(); p++)
{
p->second->Write();
}
return true;
}
void trash()
{
std::map<DFHack::DFCoord, Block *>::iterator p;
for(p = blocks.begin(); p != blocks.end(); p++)
{
delete p->second;
}
blocks.clear();
}
private:
volatile bool valid;
volatile bool validgeo;
uint32_t x_bmax;
uint32_t y_bmax;
uint32_t x_tmax;
uint32_t y_tmax;
uint32_t z_max;
std::vector< std::vector <uint16_t> > layerassign;
std::map<DFHack::DFCoord, Block *> blocks;
};
}
#endif