2021-05-30 03:21:05 +08:00
|
|
|
//
|
|
|
|
|
// Created on: 4/30/21
|
|
|
|
|
|
|
|
|
|
#include "MultiMul.hpp"
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <algorithm>
|
2022-06-12 16:54:32 -04:00
|
|
|
#include <unordered_map>
|
2022-06-15 11:24:57 -04:00
|
|
|
#include "mapstuff.h"
|
2021-06-04 02:47:37 +08:00
|
|
|
|
2022-06-12 16:54:32 -04:00
|
|
|
using namespace std::string_literals ;
|
2021-06-04 02:47:37 +08:00
|
|
|
|
2022-06-12 16:54:32 -04:00
|
|
|
//=========================================================
|
|
|
|
|
// multi_item
|
|
|
|
|
//=========================================================
|
|
|
|
|
multi_item::multi_item() :tileid(0xFFFF),altitude(0),offsetx(0),offsety(0),flag(0){
|
2022-06-15 11:24:57 -04:00
|
|
|
info = nullptr ;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
// collection_item
|
|
|
|
|
//=========================================================
|
2022-06-12 19:54:28 -04:00
|
|
|
//=========================================================
|
|
|
|
|
auto collection_item::itemsAt(int offsetx,int offsety) ->std::vector<multi_item> {
|
|
|
|
|
std::vector<multi_item> rvalue ;
|
|
|
|
|
for (auto &item:items){
|
|
|
|
|
if ( (item.offsetx == static_cast<std::int16_t>(offsetx)) && (item.offsety == static_cast<std::int16_t>(offsety))){
|
|
|
|
|
rvalue.push_back(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return rvalue ;
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
2022-06-12 16:54:32 -04:00
|
|
|
collection_item::collection_item() :min_y(0),min_x(0),max_x(0),max_y(0),min_alt(0),max_alt(0){
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto collection_item::name(int multi_id) ->std::string {
|
|
|
|
|
try {
|
|
|
|
|
auto name = collection_names.at(multi_id);
|
|
|
|
|
return name ;
|
|
|
|
|
}
|
|
|
|
|
catch(...) {
|
|
|
|
|
return "unknown - "s + std::to_string(multi_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
const std::unordered_map<int,std::string> collection_item::collection_names = {
|
|
|
|
|
{0,"Small Boat [north]"s},{1,"Small Boat [east]"s},
|
|
|
|
|
{2,"Small Boat [south]"s},{3,"Small Boat [west]"s},
|
|
|
|
|
{4,"Small Dragon Boat [north]"s},{5,"Small Dragon Boat [east]"s},
|
|
|
|
|
{6,"Small Dragon Boat [south]"s},{7,"Small Dragon Boat [west]"s},
|
|
|
|
|
{8,"Medium Boat [north]"s},{9,"Medium Boat [east]"s},
|
|
|
|
|
{10,"Medium Boat [south]"s},{11,"Medium Boat [west]"s},
|
|
|
|
|
{12,"Medium Dragon Boat [north]"s},{13,"Medium Dragon Boat [east]"s},
|
|
|
|
|
{14,"Medium Dragon Boat [south]"s},{15,"Medium Dragon Boat [west]"s},
|
|
|
|
|
{16,"Large Boat [north]"s},{17,"Large Boat [east]"s},
|
|
|
|
|
{18,"Large Boat [soutch]"s},{19,"Large Boat [west]"s},
|
|
|
|
|
{20,"Large Dragon Boat [north]"s},{21,"Large Dragon Boat [east]"s},
|
|
|
|
|
{22,"Large Dragon Boat [south]"s},{23,"Large Dragon Boat [west]"s},
|
|
|
|
|
{24,"Orcish Galleon [north]"s},{25,"Orcish Galleon [east]"s},
|
|
|
|
|
{26,"Orcish Galleon [south]"s},{27,"Orcish Galleon [west]"s},
|
|
|
|
|
{28,"Orcish Galleon [damaged][north]"s},{29,"Orcish Galleon [damaged][east]"s},
|
|
|
|
|
{30,"Orcish Galleon [damaged][south]"s},{31,"Orcish Galleon [damaged][west]"s},
|
|
|
|
|
{32,"Orcish Galleon [destroyed][north]"s},{33,"Orcish Galleon [destroyed][east]"s},
|
|
|
|
|
{34,"Orcish Galleon [destroyed][south]"s},{35,"Orcish Galleon [destroyed][west]"s},
|
|
|
|
|
|
|
|
|
|
{36,"Gargish Galleon [north]"s},{37,"Gargish Galleon [east]"s},
|
|
|
|
|
{38,"Gargish Galleon [south]"s},{39,"Gargish Galleon [west]"s},
|
|
|
|
|
{40,"Gargish Galleon [damaged][north]"s},{41,"Gargish Galleon [damaged][east]"s},
|
|
|
|
|
{42,"Gargish Galleon [damaged][south]"s},{43,"Gargish Galleon [damaged][west]"s},
|
|
|
|
|
{44,"Gargish Galleon [destroyed][north]"s},{45,"Gargish Galleon [destroyed][east]"s},
|
|
|
|
|
{46,"Gargish Galleon [destroyed][south]"s},{47,"Gargish Galleon [destroyed][west]"s},
|
|
|
|
|
|
|
|
|
|
{48,"Tokuno Galleon [north]"s},{49,"Tokuno Galleon [east]"s},
|
|
|
|
|
{50,"Tokuno Galleon [south]"s},{51,"Tokuno Galleon [west]"s},
|
|
|
|
|
{52,"Tokuno Galleon [damaged][north]"s},{53,"Tokuno Galleon [damaged][east]"s},
|
|
|
|
|
{54,"Tokuno Galleon [damaged][south]"s},{55,"Tokuno Galleon [damaged][west]"s},
|
|
|
|
|
{56,"Tokuno Galleon [destroyed][north]"s},{57,"Tokuno Galleon [destroyed][east]"s},
|
|
|
|
|
{58,"Tokuno Galleon [destroyed][south]"s},{59,"Tokuno Galleon [destroyed][west]"s},
|
|
|
|
|
|
|
|
|
|
{60,"Rowboat [north]"s},{61,"Rowboat [east]"s},
|
|
|
|
|
{62,"Rowboat [south]"s},{63,"Rowboat [west]"s},
|
|
|
|
|
|
|
|
|
|
{64,"British Galleon [north]"s},{65,"British Galleon [east]"s},
|
|
|
|
|
{66,"British Galleon [south]"s},{67,"British Galleon [west]"s},
|
|
|
|
|
{68,"British Galleon [damaged][north]"s},{69,"British Galleon [damaged][east]"s},
|
|
|
|
|
{70,"British Galleon [damaged][south]"s},{71,"British Galleon [damaged][west]"s},
|
|
|
|
|
|
|
|
|
|
{100,"Small Stone and Plaster House"s},{101,"Small Stone and Plaster House"s},
|
|
|
|
|
{102,"Small Fieldstone House"s},{103,"Small Fieldstone House"s},
|
|
|
|
|
{104,"Small Brick House"s},{105,"Small Brick House"s},
|
|
|
|
|
{106,"Small Wood House"s},{107,"Small Wood House"s},
|
|
|
|
|
{108,"Small Wood and Plaster House"s},{109,"Small Wood and Plaster House"s},
|
|
|
|
|
{110,"Small Thatched Roof Cottage"s},{111,"Small Thatched Roof Cottage"s},
|
|
|
|
|
{112,"Tent [blue]"s},{113,"Tent [blue]"s},
|
|
|
|
|
{114,"Tent [green]"s},{115,"Tent [green]"s},
|
|
|
|
|
{116,"Large Brick House"s},{117,"Large Brick House"s},
|
|
|
|
|
{118,"Two Story Wood and Plaster House"s},{119,"Two Story Wood and Plaster House"s},
|
|
|
|
|
{120,"Two Story Stone and Plaster House"s},{121,"Two Story Stone and Plaster House"s},
|
|
|
|
|
{122,"Large Tower"s},{123,"Large Tower"s},
|
|
|
|
|
{124,"Stone Keep"s},{125,"Stone Keep"s},
|
|
|
|
|
{126,"Castle"s},{127,"Castle"s},
|
|
|
|
|
{128,"Large Patio House"s},{129,"Large Patio House"s},
|
|
|
|
|
{141,"Large Patio House"s},{150,"Large Marble Patio House"s},
|
|
|
|
|
{152,"Small Tower"s},{154,"Log Cabin"s},
|
|
|
|
|
{156,"Sandstone Patio House"s},{158,"Two-Story Villa"s},
|
|
|
|
|
{160,"Small Stone Workshop"s},{162,"Small Marble Workshop"s},
|
|
|
|
|
{201,"Mine's Elevator"s},{202,"Lifting Bridge"s},
|
|
|
|
|
{500,"Wandering Healer Camp"s},{501,"Wandering Mage Camp"s},
|
|
|
|
|
{502,"Wandering Bank Camp"s},
|
|
|
|
|
|
|
|
|
|
{1000,"Treasure Pile"s},{1001,"Treasure Pile"s},
|
|
|
|
|
{1002,"Treasure Pile"s},{1003,"Treasure Pile"s},
|
|
|
|
|
|
|
|
|
|
{2000,"Wooden Supports"s},{2001,"Wooden Supports"s},
|
|
|
|
|
{2002,"Wooden Supports"s},{2003,"Wooden Supports"s},
|
|
|
|
|
{2004,"Wooden Supports"s},{2005,"Wooden Supports"s},
|
|
|
|
|
{2006,"Wooden Supports"s},{2007,"Wooden Supports"s},
|
|
|
|
|
|
|
|
|
|
{3000,"Farmer's Cabin"s},
|
|
|
|
|
|
|
|
|
|
{4000,"Exodus Generator"s},{4001,"Exodus Generator"s},
|
|
|
|
|
{4002,"Exodus Control Pylon"s},
|
|
|
|
|
|
|
|
|
|
{4003,"Nystul's Tower (stage 1)"s},{4004,"Nystul's Tower (stage 2)"s},
|
|
|
|
|
{4005,"Nystul's Tower (stage 3)"s},{4006,"Nystul's Tower (stage 4)"s},
|
|
|
|
|
{4007,"Nystul's Tower (stage 5)"s},{4008,"Nystul's Tower (stage 6)"s},
|
|
|
|
|
|
|
|
|
|
{4009,"Scaffold and Trailer"s},{4010,"Exodus Energy Tower"s},
|
|
|
|
|
{4011,"Exodus Barrier"s},{4012,"Exodus Control Device"s},
|
|
|
|
|
{5000,"Minax Stronghold"s},
|
|
|
|
|
|
|
|
|
|
{5100,"Foundation [7x7]"s},{5101,"Foundation [7x8]"s},
|
|
|
|
|
{5102,"Foundation [7x9]"s},{5103,"Foundation [7x10]"s},
|
|
|
|
|
{5104,"Foundation [7x11]"s},{5105,"Foundation [7x12]"s},
|
|
|
|
|
|
|
|
|
|
{5112,"Foundation [8x7]"s},{5113,"Foundation [8x8]"s},
|
|
|
|
|
{5114,"Foundation [8x9]"s},{5115,"Foundation [8x10]"s},
|
|
|
|
|
{5116,"Foundation [8x11]"s},{5117,"Foundation [8x12]"s},
|
|
|
|
|
{5118,"Foundation [8x13]"s},
|
|
|
|
|
|
|
|
|
|
{5124,"Foundation [9x7]"s},{5125,"Foundation [9x8]"s},
|
|
|
|
|
{5126,"Foundation [9x9]"s},{5127,"Foundation [9x10]"s},
|
|
|
|
|
{5128,"Foundation [9x11]"s},{5129,"Foundation [9x12]"s},
|
|
|
|
|
{5130,"Foundation [9x13]"s},{5131,"Foundation [9x14]"s},
|
|
|
|
|
|
|
|
|
|
{5136,"Foundation [10x7]"s},{5137,"Foundation [10x8]"s},
|
|
|
|
|
{5138,"Foundation [10x9]"s},{5139,"Foundation [10x10]"s},
|
|
|
|
|
{5140,"Foundation [10x11]"s},{5141,"Foundation [10x12]"s},
|
|
|
|
|
{5142,"Foundation [10x13]"s},{5143,"Foundation [10x14]"s},
|
|
|
|
|
{5144,"Foundation [10x15]"s},
|
|
|
|
|
|
|
|
|
|
{5148,"Foundation [11x7]"s},{5149,"Foundation [11x8]"s},
|
|
|
|
|
{5150,"Foundation [11x9]"s},{5151,"Foundation [11x10]"s},
|
|
|
|
|
{5152,"Foundation [11x11]"s},{5153,"Foundation [11x12]"s},
|
|
|
|
|
{5154,"Foundation [11x13]"s},{5155,"Foundation [11x14]"s},
|
|
|
|
|
{5156,"Foundation [11x15]"s},{5157,"Foundation [11x16]"s},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{5160,"Foundation [12x7]"s},{5161,"Foundation [12x8]"s},
|
|
|
|
|
{5162,"Foundation [12x9]"s},{5163,"Foundation [12x10]"s},
|
|
|
|
|
{5164,"Foundation [12x11]"s},{5165,"Foundation [12x12]"s},
|
|
|
|
|
{5166,"Foundation [12x13]"s},{5167,"Foundation [12x14]"s},
|
|
|
|
|
{5168,"Foundation [12x15]"s},{5169,"Foundation [12x16]"s},
|
|
|
|
|
{5170,"Foundation [12x17]"s},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{5173,"Foundation [13x8]"s}, {5174,"Foundation [13x9]"s},
|
|
|
|
|
{5175,"Foundation [13x10]"s},{5176,"Foundation [13x11]"s},
|
|
|
|
|
{5177,"Foundation [13x12]"s},{5178,"Foundation [13x13]"s},
|
|
|
|
|
{5179,"Foundation [13x14]"s},{5180,"Foundation [13x15]"s},
|
|
|
|
|
{5181,"Foundation [13x16]"s},{5182,"Foundation [13x17]"s},
|
|
|
|
|
{5183,"Foundation [13x18]"s},
|
|
|
|
|
|
|
|
|
|
{5186,"Foundation [14x9]"s}, {5187,"Foundation [14x10]"s},
|
|
|
|
|
{5188,"Foundation [14x11]"s},{5189,"Foundation [14x12]"s},
|
|
|
|
|
{5190,"Foundation [14x13]"s},{5191,"Foundation [14x14]"s},
|
|
|
|
|
{5192,"Foundation [14x15]"s},{5193,"Foundation [14x16]"s},
|
|
|
|
|
{5194,"Foundation [14x17]"s},{5195,"Foundation [14x18]"s},
|
|
|
|
|
|
|
|
|
|
{5199,"Foundation [15x10]"s},{5200,"Foundation [15x11]"s},
|
|
|
|
|
{5201,"Foundation [15x12]"s},{5202,"Foundation [15x13]"s},
|
|
|
|
|
{5203,"Foundation [15x14]"s},{5204,"Foundation [15x15]"s},
|
|
|
|
|
{5205,"Foundation [15x16]"s},{5206,"Foundation [15x17]"s},
|
|
|
|
|
{5207,"Foundation [15x18]"s},
|
|
|
|
|
|
|
|
|
|
{5212,"Foundation [16x11]"s},{5213,"Foundation [16x12]"s},
|
|
|
|
|
{5214,"Foundation [16x13]"s},{5215,"Foundation [16x14]"s},
|
|
|
|
|
{5216,"Foundation [16x15]"s},{5217,"Foundation [16x16]"s},
|
|
|
|
|
{5218,"Foundation [16x17]"s},{5219,"Foundation [16x18]"s},
|
|
|
|
|
|
|
|
|
|
{5225,"Foundation [17x12]"s},{5226,"Foundation [17x13]"s},
|
|
|
|
|
{5227,"Foundation [17x14]"s},{5228,"Foundation [17x15]"s},
|
|
|
|
|
{5229,"Foundation [17x16]"s},{5230,"Foundation [17x17]"s},
|
|
|
|
|
{5231,"Foundation [17x18]"s},
|
|
|
|
|
|
|
|
|
|
{5238,"Foundation [18x13]"s},{5239,"Foundation [18x14]"s},
|
|
|
|
|
{5240,"Foundation [18x15]"s},{5241,"Foundation [18x16]"s},
|
|
|
|
|
{5242,"Foundation [18x17]"s},{5243,"Foundation [18x18]"s},
|
|
|
|
|
|
|
|
|
|
{7500,"New Player Quest Camp"s}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
//=========================================================
|
|
|
|
|
// multicollection
|
|
|
|
|
//=========================================================
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
2022-06-15 11:24:57 -04:00
|
|
|
multicollection::multicollection(const std::filesystem::path &uodir,tileinfo *info ){
|
|
|
|
|
this->info = info ;
|
2022-06-12 16:54:32 -04:00
|
|
|
if (!uodir.empty()){
|
2022-06-15 11:24:57 -04:00
|
|
|
load(uodir,info);
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
2022-06-15 11:24:57 -04:00
|
|
|
auto multicollection::load(const std::filesystem::path &uodir,const std::string &housingbin,tileinfo *info) ->bool {
|
2022-06-12 16:54:32 -04:00
|
|
|
_multis.clear();
|
|
|
|
|
auto multifile = uodir / std::filesystem::path("MultiCollection.uop");
|
|
|
|
|
auto hash = "build/multicollection/%.6u.bin"s;
|
|
|
|
|
_housingbin = housingbin ;
|
2022-06-15 11:24:57 -04:00
|
|
|
this->info = info ;
|
2022-06-12 16:54:32 -04:00
|
|
|
return loadUOP(multifile.string(), 0x10000, hash);
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
2022-06-15 11:24:57 -04:00
|
|
|
auto multicollection::loadMul(const std::filesystem::path &uodir,tileinfo *info)->bool {
|
2022-06-12 16:54:32 -04:00
|
|
|
_multis.clear();
|
2022-06-15 11:24:57 -04:00
|
|
|
this->info = info ;
|
2022-06-12 16:54:32 -04:00
|
|
|
auto rvalue = false ;
|
|
|
|
|
auto idxfile = uodir / std::filesystem::path("multi.idx") ;
|
|
|
|
|
auto mulfile = uodir / std::filesystem::path("multi.mul") ;
|
|
|
|
|
auto isHS = true ;
|
|
|
|
|
if (std::filesystem::exists(mulfile)){
|
|
|
|
|
isHS = (std::filesystem::file_size(mulfile) >= hssize ? true:false);
|
|
|
|
|
}
|
|
|
|
|
auto idx = std::ifstream(idxfile, std::ios::binary);
|
|
|
|
|
auto mul = std::ifstream(mulfile, std::ios::binary);
|
|
|
|
|
if (mul.is_open() && idx.is_open()){
|
|
|
|
|
rvalue = true ;
|
|
|
|
|
auto offset = std::uint32_t(0);
|
|
|
|
|
auto length = std::uint32_t(0) ;
|
|
|
|
|
auto mulid = 0;
|
|
|
|
|
while (idx.good() && !idx.eof()){
|
|
|
|
|
idx.read(reinterpret_cast<char*>(&offset),4) ;
|
|
|
|
|
idx.read(reinterpret_cast<char*>(&length),4) ;
|
|
|
|
|
if (idx.gcount()== 4){
|
|
|
|
|
idx.seekg(4,std::ios::cur);
|
|
|
|
|
if ((offset <= 0xFFFFFFFE) && (length >0) && (length < 0xFFFFFFFF)){
|
|
|
|
|
// This is a valid entry ;
|
|
|
|
|
mul.seekg(offset,std::ios::beg) ;
|
|
|
|
|
auto data = std::vector<std::uint8_t>(length,0) ;
|
|
|
|
|
mul.read(reinterpret_cast<char*>(data.data()),length) ;
|
|
|
|
|
processData(isHS, mulid, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mulid += 1 ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return rvalue ;
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
2022-06-15 11:24:57 -04:00
|
|
|
auto multicollection::load(const std::filesystem::path &uodir,tileinfo *info) ->bool {
|
2022-06-12 16:54:32 -04:00
|
|
|
auto rvalue = false ;
|
|
|
|
|
// First, see if the uop exists?
|
|
|
|
|
auto multifile = uodir / std::filesystem::path("MultiCollection.uop");
|
|
|
|
|
if (std::filesystem::exists(multifile)) {
|
|
|
|
|
// It does, so lets load the uop
|
2022-06-15 11:24:57 -04:00
|
|
|
rvalue = load(uodir,"",info) ;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
else {
|
2022-06-15 11:24:57 -04:00
|
|
|
rvalue = loadMul(uodir,info);
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
return rvalue ;
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::processHash(std::uint64_t hash,std::size_t entry , std::vector<std::uint8_t> &data) ->bool {
|
|
|
|
|
if (hash == 0x126D1E99DDEDEE0ALL){
|
|
|
|
|
if (!_housingbin.empty()){
|
|
|
|
|
auto output = std::ofstream(_housingbin,std::ios::binary);
|
|
|
|
|
if (output.is_open()){
|
|
|
|
|
output.write(reinterpret_cast<char*>(data.data()),data.size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false ; // This is the hash for the housing.bin file
|
|
|
|
|
}
|
|
|
|
|
return true ;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::processEntry(std::size_t entry, std::size_t index, std::vector<std::uint8_t> &data) ->bool {
|
|
|
|
|
if (data.size()>8) {
|
|
|
|
|
auto offset = std::uint32_t(4) ;
|
|
|
|
|
// We skip the first 32 bit word (why offset is 4).
|
|
|
|
|
// The next 32 bit word is the number of entries in this data ;
|
|
|
|
|
|
|
|
|
|
auto count = std::int32_t(0) ;
|
|
|
|
|
std::copy(data.data()+offset,data.data()+offset+4,reinterpret_cast<std::uint8_t*>(&count));
|
|
|
|
|
offset += 4; ;
|
|
|
|
|
// we increment offfset now that we have read the count
|
|
|
|
|
// at this point,we are now looking at the data for each entry ;
|
|
|
|
|
// before we start looping, make some dummy read space we can get data
|
|
|
|
|
// out of the vector
|
|
|
|
|
auto flag = std::int16_t(0) ;
|
|
|
|
|
auto clilocs = std::uint32_t(0) ;
|
|
|
|
|
auto multi = collection_item() ;
|
|
|
|
|
multi.items.resize(count);
|
|
|
|
|
auto first = true ;
|
|
|
|
|
for (auto entry=0 ; entry < count ; ++entry) {
|
|
|
|
|
auto item = multi_item() ;
|
|
|
|
|
// Get the tileid
|
|
|
|
|
std::copy(data.begin()+offset, data.begin()+offset+2,reinterpret_cast<unsigned char*>(&item.tileid));
|
|
|
|
|
offset += 2 ;
|
2022-06-15 11:24:57 -04:00
|
|
|
if (info){
|
|
|
|
|
item.info = &info->art(item.tileid);
|
|
|
|
|
}
|
2022-06-12 16:54:32 -04:00
|
|
|
// Now get the xoffset --
|
|
|
|
|
std::copy(data.begin()+offset, data.begin()+offset+2,reinterpret_cast<unsigned char*>(&flag));
|
|
|
|
|
item.offsetx = static_cast<int>(flag) ;
|
|
|
|
|
offset +=2 ;
|
|
|
|
|
// Now get the yoffset
|
|
|
|
|
std::copy(data.begin()+offset, data.begin()+offset+2,reinterpret_cast<unsigned char*>(&flag));
|
|
|
|
|
item.offsety = static_cast<int>(flag) ;
|
|
|
|
|
offset +=2 ;
|
|
|
|
|
// Now get the z
|
|
|
|
|
std::copy(data.begin()+offset, data.begin()+offset+2,reinterpret_cast<unsigned char*>(&flag));
|
|
|
|
|
item.altitude = static_cast<int>(flag) ;
|
|
|
|
|
offset +=2 ;
|
|
|
|
|
// now we need to get the flag
|
|
|
|
|
std::copy(data.begin()+offset, data.begin()+offset+2,reinterpret_cast<unsigned char*>(&flag));
|
|
|
|
|
offset +=2 ;
|
|
|
|
|
switch (flag){
|
|
|
|
|
default:
|
|
|
|
|
case 0:
|
|
|
|
|
item.flag=1 ;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
break;
|
|
|
|
|
case 257:
|
|
|
|
|
item.flag = 0x800 ;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (flag ==0){
|
|
|
|
|
if (first){
|
|
|
|
|
multi.max_y = item.offsety ;
|
|
|
|
|
multi.min_y = item.offsety ;
|
|
|
|
|
multi.max_x = item.offsetx ;
|
|
|
|
|
multi.min_x = item.offsetx ;
|
|
|
|
|
multi.max_alt = item.altitude ;
|
|
|
|
|
multi.min_alt = item.altitude ;
|
|
|
|
|
first = false ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
multi.max_y = std::max(item.offsety,multi.max_y);
|
|
|
|
|
multi.min_y = std::max(item.offsety,multi.min_y);
|
|
|
|
|
multi.max_x = std::max(item.offsetx,multi.max_x);
|
|
|
|
|
multi.min_x = std::max(item.offsetx,multi.min_x);
|
|
|
|
|
multi.max_alt = std::max(item.altitude,multi.max_alt);
|
|
|
|
|
multi.min_alt = std::max(item.altitude,multi.min_alt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// we now have some clilocs to read past, have to find out how many
|
|
|
|
|
std::copy(data.begin()+offset, data.begin()+offset+4,reinterpret_cast<unsigned char*>(&clilocs));
|
|
|
|
|
offset += 4 ;
|
|
|
|
|
// Now skip past them;
|
|
|
|
|
offset += (clilocs*4) ;
|
|
|
|
|
multi.items[entry] = std::move(item) ;
|
|
|
|
|
}
|
|
|
|
|
_multis.insert_or_assign(static_cast<int>(index), std::move(multi));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//========================================================
|
|
|
|
|
auto multicollection::processData(bool isHS,int index, std::vector<std::uint8_t> &data) ->void {
|
|
|
|
|
|
|
|
|
|
auto size = (isHS?16:12) ;
|
|
|
|
|
auto count = static_cast<int>(data.size()) / size ;
|
|
|
|
|
auto multi = collection_item() ;
|
|
|
|
|
auto first = true ;
|
|
|
|
|
for (auto entry = 0; entry < count ; ++entry){
|
|
|
|
|
auto item = multi_item() ;
|
|
|
|
|
|
|
|
|
|
std::copy(data.data()+(entry*size),data.data()+(entry*size)+2,reinterpret_cast<std::uint8_t*>(&item.tileid));
|
2022-06-15 11:24:57 -04:00
|
|
|
if (info) {
|
|
|
|
|
item.info = &(info->art(item.tileid));
|
|
|
|
|
}
|
2022-06-12 16:54:32 -04:00
|
|
|
auto value = std::int16_t(0) ;
|
|
|
|
|
std::copy(data.data()+(entry*size)+2,data.data()+(entry*size)+2+2,reinterpret_cast<std::uint8_t*>(&value));
|
|
|
|
|
item.offsetx = value ;
|
|
|
|
|
std::copy(data.data()+(entry*size)+4,data.data()+(entry*size)+4+2,reinterpret_cast<std::uint8_t*>(&value));
|
|
|
|
|
item.offsety = value ;
|
|
|
|
|
std::copy(data.data()+(entry*size)+6,data.data()+(entry*size)+6+2,reinterpret_cast<std::uint8_t*>(&value));
|
|
|
|
|
item.altitude = value ;
|
|
|
|
|
|
|
|
|
|
if (isHS) {
|
|
|
|
|
auto flag = std::uint64_t(0);
|
|
|
|
|
std::copy(data.data()+(entry*size)+8,data.data()+(entry*size)+8+8,reinterpret_cast<std::uint8_t*>(&flag));
|
|
|
|
|
item.flag = static_cast<std::uint16_t>(flag) ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
auto flag = std::uint32_t(0);
|
|
|
|
|
std::copy(data.data()+(entry*size)+4,data.data()+(entry*size)+8+4,reinterpret_cast<std::uint8_t*>(&flag));
|
|
|
|
|
item.flag = static_cast<std::uint16_t>(flag) ;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (first){
|
|
|
|
|
multi.max_y = item.offsety ;
|
|
|
|
|
multi.min_y = item.offsety ;
|
|
|
|
|
multi.max_x = item.offsetx ;
|
|
|
|
|
multi.min_x = item.offsetx ;
|
|
|
|
|
multi.max_alt = item.altitude ;
|
|
|
|
|
multi.min_alt = item.altitude ;
|
|
|
|
|
first = false ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
multi.max_y = std::max(item.offsety,multi.max_y);
|
|
|
|
|
multi.min_y = std::max(item.offsety,multi.min_y);
|
|
|
|
|
multi.max_x = std::max(item.offsetx,multi.max_x);
|
|
|
|
|
multi.min_x = std::max(item.offsetx,multi.min_x);
|
|
|
|
|
multi.max_alt = std::max(item.altitude,multi.max_alt);
|
|
|
|
|
multi.min_alt = std::max(item.altitude,multi.min_alt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
multi.items.push_back(item);
|
|
|
|
|
}
|
|
|
|
|
_multis[index] = multi ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::size() const ->size_t {
|
|
|
|
|
return _multis.size();
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::multis() const -> const std::unordered_map<int, collection_item>& {
|
|
|
|
|
return _multis;
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::multis() -> std::unordered_map<int, collection_item>& {
|
|
|
|
|
return _multis;
|
|
|
|
|
}
|
2022-06-12 19:54:28 -04:00
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::multi(std::uint16_t multid) ->collection_item& {
|
|
|
|
|
return _multis.at(static_cast<int>(multid)) ;
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::multi(std::uint16_t multid) const ->const collection_item&{
|
|
|
|
|
return _multis.at(static_cast<int>(multid)) ;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
|
|
|
|
auto multicollection::exists(std::uint16_t multid) const ->bool {
|
|
|
|
|
auto rvalue = false ;
|
|
|
|
|
auto iter = _multis.find(multid) ;
|
|
|
|
|
if (iter != _multis.end()){
|
|
|
|
|
rvalue = true ;;
|
|
|
|
|
}
|
|
|
|
|
return rvalue ;
|
|
|
|
|
}
|