|
@@ -45,9 +45,14 @@ DatFile::~DatFile() {
|
|
}
|
|
}
|
|
|
|
|
|
bool DatFile::Init(const std::string& filename) {
|
|
bool DatFile::Init(const std::string& filename) {
|
|
|
|
+ if (initialized_) {
|
|
|
|
+ Deinit();
|
|
|
|
+ }
|
|
|
|
+
|
|
if (api_.OpenDatFile(file_handle_, filename.c_str(), 130) == file_handle_) {
|
|
if (api_.OpenDatFile(file_handle_, filename.c_str(), 130) == file_handle_) {
|
|
initialized_ = true;
|
|
initialized_ = true;
|
|
filename_ = filename;
|
|
filename_ = filename;
|
|
|
|
+ LoadAllFilesInfo();
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -59,13 +64,14 @@ void DatFile::LoadAllFilesInfo() {
|
|
for (int i = 0; i < subfiles_num; ++i) {
|
|
for (int i = 0; i < subfiles_num; ++i) {
|
|
SubfileInfo file_info;
|
|
SubfileInfo file_info;
|
|
api_.GetSubfileSizes(file_handle_, &file_info.file_id, &file_info.size, &file_info.iteration, i, 1);
|
|
api_.GetSubfileSizes(file_handle_, &file_info.file_id, &file_info.size, &file_info.iteration, i, 1);
|
|
- files_info_.insert(file_info);
|
|
|
|
|
|
+ files_info_[file_info.file_id] = file_info;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void DatFile::Deinit() {
|
|
void DatFile::Deinit() {
|
|
if (initialized_) {
|
|
if (initialized_) {
|
|
api_.CloseDatFile(file_handle_);
|
|
api_.CloseDatFile(file_handle_);
|
|
|
|
+ files_info_.clear();
|
|
initialized_ = false;
|
|
initialized_ = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -78,6 +84,13 @@ const std::string& DatFile::GetFilename() const {
|
|
return filename_;
|
|
return filename_;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+SubfileInfo DatFile::getSubfileInfo(int file_id) const {
|
|
|
|
+ if (files_info_.count(file_id) == 0) {
|
|
|
|
+ return SubfileInfo();
|
|
|
|
+ } else {
|
|
|
|
+ return files_info_.at(file_id);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
size_t DatFile::GetFilesNumInDatFile() {
|
|
size_t DatFile::GetFilesNumInDatFile() {
|
|
return api_.GetNumSubfiles(file_handle_);
|
|
return api_.GetNumSubfiles(file_handle_);
|
|
@@ -107,21 +120,41 @@ size_t DatFile::PatchAllFilesFromDatabase(Database& db) {
|
|
return patched_files_num;
|
|
return patched_files_num;
|
|
}
|
|
}
|
|
|
|
|
|
-void DatFile::PatchFile(SubfileData file_data) {
|
|
|
|
|
|
+void DatFile::PatchFile(SubfileData file_data, int version, int iteration) {
|
|
|
|
+ if (!file_data.options["fid"]) {
|
|
|
|
+ LOG(ERROR) << "Trying to patch file, but file id is not specified, skipping!";
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
int file_id = file_data.options["fid"].as<int>();
|
|
int file_id = file_data.options["fid"].as<int>();
|
|
- int version = 0;
|
|
|
|
- int size = api_.GetSubfileData(file_handle_, file_id, export_data_buf_.data(), version);
|
|
|
|
|
|
+
|
|
|
|
+ if (files_info_.count(file_id) == 0) {
|
|
|
|
+ LOG(ERROR) << "Trying to patch file, not existing in files_info. File id = " << file_id;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const SubfileInfo& file_info = files_info_[file_id];
|
|
|
|
+
|
|
|
|
+ int existing_file_version = 0; // will be evaluated with api_.GetSubfileData
|
|
|
|
+ int size = api_.GetSubfileData(file_handle_, file_id, export_data_buf_.data(), existing_file_version);
|
|
if (size <= 0) {
|
|
if (size <= 0) {
|
|
LOG(ERROR) << "Trying to patch file, not existing in .dat file. File id = " << file_id;
|
|
LOG(ERROR) << "Trying to patch file, not existing in .dat file. File id = " << file_id;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
BinaryData old_data = export_data_buf_.CutData(0, size);
|
|
BinaryData old_data = export_data_buf_.CutData(0, size);
|
|
-
|
|
|
|
|
|
+
|
|
BinaryData file = BuildForImport(old_data, file_data);
|
|
BinaryData file = BuildForImport(old_data, file_data);
|
|
- api_.PutSubfileData(file_handle_, file_id, file.data(), 0, file.size(), 10, 99999);
|
|
|
|
|
|
+
|
|
|
|
+ if (version == -1) {
|
|
|
|
+ version = existing_file_version;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (iteration == -1) {
|
|
|
|
+ iteration = file_info.iteration;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ api_.PutSubfileData(file_handle_, file_id, file.data(), 0, file.size(), version, iteration);
|
|
}
|
|
}
|
|
|
|
|
|
-void DatFile::PatchFile(int file_id, FILE_TYPE type, std::string path_to_file) {
|
|
|
|
|
|
+void DatFile::PatchFile(int file_id, FILE_TYPE type, std::string path_to_file, int version, int iteration) {
|
|
BinaryData new_data(64 * 1024 * 1024);
|
|
BinaryData new_data(64 * 1024 * 1024);
|
|
std::ifstream in(path_to_file, std::ifstream::binary);
|
|
std::ifstream in(path_to_file, std::ifstream::binary);
|
|
in.read((char*)new_data.data(), new_data.size());
|
|
in.read((char*)new_data.data(), new_data.size());
|
|
@@ -133,7 +166,7 @@ void DatFile::PatchFile(int file_id, FILE_TYPE type, std::string path_to_file) {
|
|
imported_subfile.options["ext"] = StringFromFileType(type);
|
|
imported_subfile.options["ext"] = StringFromFileType(type);
|
|
imported_subfile.options["fid"] = file_id;
|
|
imported_subfile.options["fid"] = file_id;
|
|
|
|
|
|
- PatchFile(imported_subfile);
|
|
|
|
|
|
+ PatchFile(imported_subfile, version, iteration);
|
|
}
|
|
}
|
|
|
|
|
|
FILE_TYPE DatFile::GetExistingFileType(int file_id) {
|
|
FILE_TYPE DatFile::GetExistingFileType(int file_id) {
|
|
@@ -148,11 +181,11 @@ void DatFile::PerformOperationOnAllSubfiles(const SubfileOperation& operation) {
|
|
}
|
|
}
|
|
std::cout << "Performing operation on all files...";
|
|
std::cout << "Performing operation on all files...";
|
|
int i = 0;
|
|
int i = 0;
|
|
- for (const SubfileInfo& info : files_info_) {
|
|
|
|
|
|
+ for (const std::pair<int, SubfileInfo>& info : files_info_) {
|
|
if (i * 100 / files_info_.size() != (i - 1) * 100 / files_info_.size()) {
|
|
if (i * 100 / files_info_.size() != (i - 1) * 100 / files_info_.size()) {
|
|
std::cout << "Completed " << i * 100 / files_info_.size() << "%" << std::endl;
|
|
std::cout << "Completed " << i * 100 / files_info_.size() << "%" << std::endl;
|
|
}
|
|
}
|
|
- operation(info);
|
|
|
|
|
|
+ operation(info.second);
|
|
++i;
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -207,4 +240,15 @@ void DatFile::ExportFileById(int file_id, Database& db) {
|
|
db.PushFile(file);
|
|
db.PushFile(file);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int DatFile::GetFileVersion(int file_id) {
|
|
|
|
+ return api_.GetSubfileVersion(file_handle_, file_id);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+SubfileData DatFile::GetFile(int file_id) {
|
|
|
|
+ int version = 0;
|
|
|
|
+ int size = api_.GetSubfileData(file_handle_, file_id, export_data_buf_.data(), version);
|
|
|
|
+ auto data = export_data_buf_.CutData(0, size);
|
|
|
|
+ return BuildForExport(file_id, data);
|
|
|
|
+}
|
|
|
|
+
|
|
}; // namespace LOTRO_DAT
|
|
}; // namespace LOTRO_DAT
|