|
@@ -8,18 +8,48 @@
|
|
|
#include "../Common/DatException.h"
|
|
|
#include "../SubfileData.h"
|
|
|
#include <algorithm>
|
|
|
+#include <codecvt>
|
|
|
+#include <locale>
|
|
|
|
|
|
-std::u16string to_utf16(long long x)
|
|
|
-{
|
|
|
+std::u16string to_utf16(long long x) {
|
|
|
std::u16string res;
|
|
|
while (x > 0) {
|
|
|
- res += u'0' + short(x % 10);
|
|
|
+ res += u'0' + (x % 10);
|
|
|
x /= 10ll;
|
|
|
}
|
|
|
std::reverse(res.begin(), res.end());
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+long long from_utf16(const std::u16string &num) {
|
|
|
+ long long res = 0;
|
|
|
+ for (auto c : num) {
|
|
|
+ res = res * 10ll + (c - u'0');
|
|
|
+ }
|
|
|
+ std::cout << "fragment_id: " << res << std::endl;
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+std::string argumentsFromUtf16(const std::u16string &args) {
|
|
|
+ std::string res;
|
|
|
+
|
|
|
+ size_t pointer = 0;
|
|
|
+ while (pointer < args.length()) {
|
|
|
+ size_t pointer1 = args.find(u'-', pointer);
|
|
|
+ if (pointer1 == std::u16string::npos)
|
|
|
+ pointer1 = args.length();
|
|
|
+ if (!res.empty())
|
|
|
+ res += "-";
|
|
|
+ res += std::to_string(from_utf16(args.substr(pointer, pointer1 - pointer)));
|
|
|
+ pointer = pointer1 + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> codecvt;
|
|
|
+ std::cout << "Arguments old: "<< codecvt.to_bytes(args) << '\n' ;
|
|
|
+ std::cout << "Arguments new: "<< res << '\n' ;
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
namespace LOTRO_DAT {
|
|
|
TextSubfile::TextSubfile() = default;
|
|
|
|
|
@@ -84,18 +114,13 @@ namespace LOTRO_DAT {
|
|
|
}
|
|
|
|
|
|
BinaryData TextSubfile::MakeForImport(const BinaryData &old_data, const SubfileData &data) {
|
|
|
- BinaryData new_data;
|
|
|
-
|
|
|
- // Creating map for fast access to patch fragment by it's id
|
|
|
- std::unordered_map<long long, long long> fragment_vector_dictionary;
|
|
|
-
|
|
|
- std::cerr << "Fragments for " << file_id() << std::endl;
|
|
|
- for (int i = 0; i < FileFragments.size(); i++)
|
|
|
- fragment_vector_dictionary[FileFragments[i].options["gid"].as<long long>()] = i;
|
|
|
+ std::unordered_map<long long, SubfileData> patch_fragments = ParsePatchFragments(data);
|
|
|
+ std::cout << "Made fragments. Fragments are: " << std::flush;
|
|
|
+ for (auto &i : patch_fragments)
|
|
|
+ std::cout << i.first << " " << std::flush;
|
|
|
+ std::cout << std::endl;
|
|
|
|
|
|
- for (auto i : fragment_vector_dictionary)
|
|
|
- std::cerr << i.first << " ";
|
|
|
- std::cerr << std::endl;
|
|
|
+ BinaryData new_data;
|
|
|
|
|
|
if (file_size() <= 10 + 8) // File is empty, nothing to do;
|
|
|
return old_data;
|
|
@@ -118,22 +143,115 @@ namespace LOTRO_DAT {
|
|
|
|
|
|
new_data = new_data + old_data.CutData(offset - 8, offset);
|
|
|
|
|
|
- if (fragment_vector_dictionary.count(fragment_id) == 0) {
|
|
|
+ if (patch_fragments.count(fragment_id) == 0) {
|
|
|
std::cerr << "Omg, what..? " << file_id() << " " << fragment_id << " is not in patch? " << std::endl;
|
|
|
- new_data = new_data + GetPieceData(old_data, offset); // Retrieving old pieces
|
|
|
- new_data = new_data + GetArgumentReferenceData(old_data, offset); // Retrieving old references
|
|
|
- new_data = new_data + GetArgumentStringsData(old_data, offset); // Retrieving old ref_strings
|
|
|
+ try {
|
|
|
+ // Retrieving old pieces
|
|
|
+ new_data = new_data + GetPieceData(old_data, offset);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.\n", e.what());
|
|
|
+ fprintf(stderr, "ERROR TextSubfile::MakeForImport() - unable to get piece data for file_id %lld and fragment_id %lld", file_id(), fragment_id);
|
|
|
+ throw DatException("Bad TextSubfile::MakeForImport()", IMPORT_EXCEPTION);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // Retrieving old references
|
|
|
+ new_data = new_data + GetArgumentReferenceData(old_data, offset);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.\n", e.what());
|
|
|
+ fprintf(stderr, "ERROR TextSubfile::MakeForImport() - unable to get argument reference data for file_id %lld and fragment_id %lld", file_id(), fragment_id);
|
|
|
+ throw DatException("Bad TextSubfile::MakeForImport()", IMPORT_EXCEPTION);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // Retrieving old ref_strings
|
|
|
+ new_data = new_data + GetArgumentStringsData(old_data, offset);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.\n", e.what());
|
|
|
+ fprintf(stderr, "ERROR TextSubfile::MakeForImport() - unable to get argument string for file_id %lld and fragment_id %lld", file_id(), fragment_id);
|
|
|
+ throw DatException("Bad TextSubfile::MakeForImport()", IMPORT_EXCEPTION);
|
|
|
+ }
|
|
|
+
|
|
|
} else {
|
|
|
- SubfileData fragment_data = FileFragments[fragment_vector_dictionary[fragment_id]];
|
|
|
- new_data = new_data + BuildPieces(old_data, fragment_data, offset); // Making and adding new pieces
|
|
|
- new_data = new_data + BuildArgumentReferences(old_data, fragment_data, offset); // Making and adding new references
|
|
|
- new_data = new_data + BuildArgumentStrings(old_data, fragment_data, offset); // Making and adding new strings
|
|
|
+ try {
|
|
|
+ // Making and adding new pieces
|
|
|
+ new_data = new_data + BuildPieces(old_data, patch_fragments[fragment_id], offset);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.\n", e.what());
|
|
|
+ fprintf(stderr, "ERROR TextSubfile::MakeForImport() - unable to build piece data for file_id %lld and fragment_id %lld", file_id(), fragment_id);
|
|
|
+ throw DatException("Bad TextSubfile::MakeForImport()", IMPORT_EXCEPTION);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // Making and adding new references
|
|
|
+ new_data = new_data + BuildArgumentReferences(old_data, patch_fragments[fragment_id], offset);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.\n", e.what());
|
|
|
+ fprintf(stderr, "ERROR TextSubfile::MakeForImport() - unable to build argument references data for file_id %lld and fragment_id %lld", file_id(), fragment_id);
|
|
|
+ throw DatException("Bad TextSubfile::MakeForImport()", IMPORT_EXCEPTION);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // Making and adding new strings
|
|
|
+ new_data = new_data + BuildArgumentStrings(old_data, patch_fragments[fragment_id], offset);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.\n", e.what());
|
|
|
+ fprintf(stderr, "ERROR TextSubfile::MakeForImport() - unable to build argument strings data for file_id %lld and fragment_id %lld", file_id(), fragment_id);
|
|
|
+ throw DatException("Bad TextSubfile::MakeForImport()", IMPORT_EXCEPTION);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
new_data = new_data + old_data.CutData(offset); // Adding elapsed file data
|
|
|
return new_data;
|
|
|
}
|
|
|
|
|
|
+ std::unordered_map<long long, SubfileData> TextSubfile::ParsePatchFragments(const SubfileData &data) {
|
|
|
+ std::unordered_map<long long, SubfileData> res;
|
|
|
+ std::u16string text = data.text_data;
|
|
|
+
|
|
|
+ size_t pointer = 0;
|
|
|
+ while (pointer < text.length()) {
|
|
|
+ // Parsing fragment_id
|
|
|
+ size_t pointer1 = text.find(u":::", pointer);
|
|
|
+ if (pointer1 == std::u16string::npos)
|
|
|
+ throw DatException("Bad TextSubfile::ParsePatchFragments() - Unable to parse fragment id! Cannot find '...' divider");
|
|
|
+ long long fragment_id = from_utf16(text.substr(pointer, pointer1 - pointer));
|
|
|
+ pointer = pointer1 + 3;
|
|
|
+ res[fragment_id] = SubfileData();
|
|
|
+ res[fragment_id].options["gid"] = fragment_id;
|
|
|
+
|
|
|
+ // Parsing arguments
|
|
|
+ pointer1 = text.find(u":::", pointer);
|
|
|
+ if (pointer1 == std::u16string::npos)
|
|
|
+ throw DatException("Bad TextSubfile::ParsePatchFragments() - Unable to parse arguments! Cannot find '...' divider");
|
|
|
+ std::u16string arguments = text.substr(pointer, pointer1 - pointer);
|
|
|
+ pointer = pointer1 + 3;
|
|
|
+ if (arguments.length() > 0) {
|
|
|
+ res[fragment_id].options["args"] = argumentsFromUtf16(arguments);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Parsing text
|
|
|
+ pointer1 = text.find(u"|||", pointer);
|
|
|
+ if (pointer1 == std::u16string::npos)
|
|
|
+ pointer1 = text.length();
|
|
|
+ std::u16string text_data = text.substr(pointer, pointer1 - pointer);
|
|
|
+ pointer = pointer1 + 3;
|
|
|
+ res[fragment_id].text_data = text_data;
|
|
|
+
|
|
|
+
|
|
|
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> codecvt;
|
|
|
+ std::cout << "Fragment id: " << res[fragment_id].options["gid"].as<long long>() << "\n";
|
|
|
+ if (res[fragment_id].options["args"])
|
|
|
+ std::cout << "Args: " << res[fragment_id].options["args"].as<std::string>() << "\n";
|
|
|
+ else
|
|
|
+ std::cout << "Args: none \n";
|
|
|
+ std::cout << "Text: " << codecvt.to_bytes(res[fragment_id].text_data) << '\n' ;
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Make pieces/arguments/argument strings functions
|
|
|
+
|
|
|
std::vector<std::u16string> TextSubfile::MakePieces(const BinaryData &data, long long &offset) {
|
|
|
long long num_pieces = data.ToNumber<4>(offset);
|
|
|
offset += 4;
|
|
@@ -202,14 +320,25 @@ namespace LOTRO_DAT {
|
|
|
return arg_strings;
|
|
|
}
|
|
|
|
|
|
+ // Build pieces/arguments/argument strings functions from fragment SubfileData
|
|
|
+
|
|
|
BinaryData TextSubfile::BuildPieces(const BinaryData &data, const SubfileData &new_data, long long &offset) {
|
|
|
- // Moving &offset pointer in &data
|
|
|
- GetPieceData(data, offset);
|
|
|
+ try {
|
|
|
+ // Moving &offset pointer in &data
|
|
|
+ GetPieceData(data, offset);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.\n", e.what());
|
|
|
+ fprintf(stderr, "ERROR TextSubfile::BuildPieces() - unable to get piece data for file_id %lld", file_id());
|
|
|
+ throw DatException("Bad TextSubfile::BuildPieces()", IMPORT_EXCEPTION);
|
|
|
+ }
|
|
|
|
|
|
// Deleting '[' and ']' brackets
|
|
|
std::u16string text_data = new_data.text_data.substr(1, new_data.text_data.size() - 2);
|
|
|
std::vector<std::u16string> pieces;
|
|
|
|
|
|
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> codecvt;
|
|
|
+ std::cout << "AAAAA0: " << codecvt.to_bytes(text_data) << '\n' ;
|
|
|
+
|
|
|
const std::u16string DNT = u"<--DO_NOT_TOUCH!-->";
|
|
|
size_t prev = 0;
|
|
|
size_t next = text_data.find(DNT, prev);
|
|
@@ -223,6 +352,8 @@ namespace LOTRO_DAT {
|
|
|
std::u16string piece = text_data.substr(prev);
|
|
|
pieces.push_back(piece);
|
|
|
|
|
|
+ std::cout << "AAAAA: " << codecvt.to_bytes(piece) << '\n' ;
|
|
|
+
|
|
|
// Building BinaryData from pieces
|
|
|
BinaryData result;
|
|
|
BinaryData temp_data(4);
|
|
@@ -272,6 +403,8 @@ namespace LOTRO_DAT {
|
|
|
next = args_list.find('-', prev);
|
|
|
}
|
|
|
std::string argument = args_list.substr(prev);
|
|
|
+ std::cout << "DDD: Argument is " << argument << std::endl;
|
|
|
+ std::cout << "DDD: Arguments are" << new_data.options["args"].as<std::string>() << std::endl;
|
|
|
arguments.push_back(std::stoll(argument));
|
|
|
|
|
|
BinaryData result;
|
|
@@ -290,6 +423,8 @@ namespace LOTRO_DAT {
|
|
|
return GetArgumentStringsData(data, offset);
|
|
|
}
|
|
|
|
|
|
+ // Get BinaryData contents of pieces/arguments/argument strings
|
|
|
+
|
|
|
BinaryData TextSubfile::GetPieceData(const BinaryData &data, long long &offset) const {
|
|
|
long long old_offset = offset;
|
|
|
|
|
@@ -305,6 +440,7 @@ namespace LOTRO_DAT {
|
|
|
offset += 1;
|
|
|
offset += piece_size * 2;
|
|
|
}
|
|
|
+ std::cout << "DDDDDDDDDDDD: " << old_offset << " " << offset << std::endl;
|
|
|
return data.CutData(old_offset, offset);
|
|
|
}
|
|
|
|