bool ConvertItem(ReaderItem *Reader, WriterItem *Writer) { bool Status = false; if (Reader && Writer) { // convert object across if (Prog) { Prog->Value(Prog->Value() + Reader->Len); LgiYield(); } Converted++; Status = true; // do children for (StorageItem *ri = Reader->Store->GetChild(); ri; ri = ri->GetNext()) { ReaderItem *Reader1 = new ReaderItem(ri); if (Reader1 && Reader1->Len > 0) { WriterItem *Writer2 = new WriterItem(Reader1); StorageItem *wi = Writer->Store->CreateSub(Writer2); if (Writer2 && wi) { wi->Object = Writer2; Writer2->Store = wi; Status &= ConvertItem(Reader1, Writer2); Writer2->Store->Object = 0; Writer2->Store = 0; DeleteObj(Writer2); } Reader1->Store->Object = 0; Reader1->Store = 0; DeleteObj(Reader1); } } } return Status; }
/** * reads one 16x16 map block into stonesense tiles * attempts to only read as much information as is necessary to do the tile optimization */ void readBlockToSegment(DFHack::Core& DF, WorldSegment& segment, int BlockX, int BlockY, int BlockZ, uint32_t BoundrySX, uint32_t BoundrySY, uint32_t BoundryEX, uint32_t BoundryEY, vector< vector <int16_t> >* allLayers) { if(ssConfig.skipMaps) { return; } //boundry check int blockDimX, blockDimY, blockDimZ; Maps::getSize((unsigned int &)blockDimX, (unsigned int &)blockDimY, (unsigned int &)blockDimZ); if( BlockX < 0 || BlockX >= blockDimX || BlockY < 0 || BlockY >= blockDimY || BlockZ < 0 || BlockZ >= blockDimZ ) { return; } //make boundries local BoundrySX -= BlockX * BLOCKEDGESIZE; BoundryEX -= BlockX * BLOCKEDGESIZE; BoundrySY -= BlockY * BLOCKEDGESIZE; BoundryEY -= BlockY * BLOCKEDGESIZE; //read block data df::map_block *trueBlock; trueBlock = Maps::getBlock(BlockX, BlockY, BlockZ); if(!trueBlock) { return; } //read the map features t_feature local, global; Maps::ReadFeatures(BlockX,BlockY,BlockZ,&local,&global); //read local vein data vector <df::block_square_event_mineralst * > veins; vector <df::block_square_event_frozen_liquidst * > ices; vector <df::block_square_event_material_spatterst * > splatter; vector <df::block_square_event_grassst * > grass; vector <df::block_square_event_world_constructionst * > worldconstructions; Maps::SortBlockEvents( trueBlock, &veins, &ices, &splatter, &grass, &worldconstructions); //parse block for(uint32_t ly = BoundrySY; ly <= BoundryEY; ly++) { for(uint32_t lx = BoundrySX; lx <= BoundryEX; lx++) { uint32_t gx = lx + (BlockX * BLOCKEDGESIZE); uint32_t gy = ly + (BlockY * BLOCKEDGESIZE); if( !segment.CoordinateInsideSegment( gx, gy, BlockZ) ) { continue; } bool shouldBeIncluded = true; //open terrain needs to be included to make blackboxes if // we are shading but not showing hidden tiles if(isOpenTerrain(trueBlock->tiletype[lx][ly]) && trueBlock->tiletype[lx][ly] != tiletype::RampTop) { if(!ssConfig.show_hidden_tiles && ssConfig.shade_hidden_tiles && trueBlock->designation[lx][ly].bits.hidden) { shouldBeIncluded = true; } else { shouldBeIncluded = false; } //all other terrain needs including, except for hidden tiles // when we are neither showing nor shading hidden tiles } else if(!ssConfig.show_hidden_tiles && !ssConfig.shade_hidden_tiles && trueBlock->designation[lx][ly].bits.hidden) { shouldBeIncluded = false; } //add back in any liquid tiles, in case they can be seen from above // as well as any hanging buildings if(trueBlock->designation[lx][ly].bits.flow_size || trueBlock->occupancy[lx][ly].bits.building) { shouldBeIncluded = true; } //add back in any tiles that are constructions or designations if( ssConfig.show_designations && containsDesignations( trueBlock->designation[lx][ly], trueBlock->occupancy[lx][ly] ) ) { shouldBeIncluded = true; } if(!shouldBeIncluded){ continue; } Tile * b = segment.ResetTile(gx, gy, BlockZ, trueBlock->tiletype[lx][ly]); b->occ.bits.unit = false;//this will be set manually when we read the creatures vector b->occ = trueBlock->occupancy[lx][ly]; b->designation = trueBlock->designation[lx][ly]; //if the tile has designations, read them and nothing else if( ssConfig.show_designations && readDesignationsToTile( b, trueBlock->designation[lx][ly], trueBlock->occupancy[lx][ly] ) ) { continue; } //set whether the tile is hidden b->fog_of_war = !b->designation.bits.pile; //don't read detailed information for blackbox tiles if(!ssConfig.show_hidden_tiles && ssConfig.shade_hidden_tiles && b->designation.bits.hidden && !b->designation.bits.flow_size) { continue; } //read the grasses b->grasslevel = 0; b->grassmat = -1; //b->grasslevels.clear(); //b->grassmats.clear(); for(int i = 0; i < grass.size(); i++) { if(grass[i]->amount[lx][ly] > 0 && b->grasslevel == 0) { //b->grasslevel) b->grasslevel = grass[i]->amount[lx][ly]; b->grassmat = grass[i]->plant_index; //b->grasslevels.push_back(grass[i].intensity[lx][ly]); //b->grassmats.push_back(grass[i].material); } } //read the water flows and direction. b->flow_direction = trueBlock->liquid_flow[lx][ly].bits.perm_flow_dir; //read the tile spatter readSpatterToTile(b, lx, ly, splatter); //read the tile material readMaterialToTile(b, lx, ly, trueBlock, local, global, veins, allLayers); } } //add trees and other vegetation for(auto iter = trueBlock->plants.begin(); iter != trueBlock->plants.end(); iter++) { df::plant * wheat = *iter; assert(wheat != NULL); Tile* b = segment.getTile( wheat->pos.x, wheat->pos.y, wheat->pos.z); if(!b) { b = segment.ResetTile(wheat->pos.x, wheat->pos.y, wheat->pos.z, tiletype::OpenSpace); if(!b) { continue; } } if( b->tileShape() == tiletype_shape::TREE || b->tileShape() == tiletype_shape::SAPLING || b->tileShape() == tiletype_shape::SHRUB) { b->tree.type = wheat->flags.whole; b->tree.index = wheat->material; } } //add items for(auto iter = trueBlock->items.begin(); iter != trueBlock->items.end(); iter++) { int32_t item_index = *iter; df::item * found_item = df::item::find(item_index); if(!found_item) { continue; } Tile* b = segment.getTile( found_item->pos.x, found_item->pos.y, found_item->pos.z); if(!b) { b = segment.ResetTile(found_item->pos.x, found_item->pos.y, found_item->pos.z, tiletype::OpenSpace); if(!b) { continue; } } b->Item = ConvertItem(found_item, segment); } //add effects for(auto iter = trueBlock->flows.begin(); iter != trueBlock->flows.end(); iter++) { df::flow_info * eff = *iter; if(eff == NULL || eff->density <= 0) { continue; } Tile* b = segment.getTile( eff->pos.x, eff->pos.y, eff->pos.z); if(segment.CoordinateInsideSegment(eff->pos.x, eff->pos.y, eff->pos.z)) { if(!b) { b = segment.ResetTile(eff->pos.x, eff->pos.y, eff->pos.z, tiletype::OpenSpace); if(!b) { continue; } } if(eff->density > b->tileeffect.density || b->tileeffect.type == (df::flow_type) INVALID_INDEX) { b->tileeffect.type = eff->type; b->tileeffect.density = eff->density; b->tileeffect.matt.index = eff->mat_index; b->tileeffect.matt.type = eff->mat_type; } } } }
bool Convert(GView *Parent) { bool Status = false; GProgressDlg Dlg(Parent); if (Store1 && Store2) { if (Store1->GetStatus()) { Prog = Dlg.ItemAt(0); Dlg.SetDescription("Converting items..."); Dlg.SetLimits(0, Store1->GetFileSize()); Dlg.SetScale(1.0 / 1024.0); Dlg.SetType("K"); StorageItem *Item1 = Store1->GetRoot(); ReaderItem *Reader1 = new ReaderItem(Item1); if (Reader1) { // The storage1 code didn't set the root object's type // correctly, leaving it as -1. So on the way over lets // correct this little mistake and make it into a folder. Reader1->Store->SetType(0xAAFF0003); // magic # for a folder } WriterItem *Writer2 = new WriterItem(Reader1); StorageItem *Item2 = Store2->CreateRoot(Writer2); if (Writer2 && Item2) { Writer2->Store = Item2; Item2->Object = Writer2; } if (Reader1 && Writer2) { Status = ConvertItem(Reader1, Writer2); Reader1->Store->Object = 0; Reader1->Store = 0; Writer2->Store->Object = 0; Writer2->Store = 0; } } else { GStatusPane *Wnd = dynamic_cast<GStatusPane*>(Prog); LgiMsg( Wnd, "The input folders failed to load correctly.\n" "Most likely because they are not v1 folders or\n" "are corrupt.", "Scribe: Folder Compact", MB_OK); } DeleteObj(Store1); DeleteObj(Store2); } return Status; }