Browse Source

extract lod

Laserlicht 1 year ago
parent
commit
0e500efe5a

+ 68 - 12
launcher/modManager/chroniclesextractor.cpp

@@ -12,6 +12,7 @@
 #include "chroniclesextractor.h"
 
 #include "../../lib/VCMIDirs.h"
+#include "../../lib/filesystem/CArchiveLoader.h"
 
 #ifdef ENABLE_INNOEXTRACT
 #include "cli/extract.hpp"
@@ -60,16 +61,6 @@ int ChroniclesExtractor::getChronicleNo(QFile & file)
 	}
 
 	QByteArray dataBegin = file.read(1'000'000);
-	const std::map<int, QByteArray> chronicles = {
-		{1, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Warlords of the Wasteland"), 90}},
-		{2, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Conquest of the Underworld"), 92}},
-		{3, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Masters of the Elements"), 86}},
-		{4, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Clash of the Dragons"), 80}},
-		{5, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - The World Tree"), 68}},
-		{6, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - The Fiery Moon"), 68}},
-		{7, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Revolt of the Beastmasters"), 92}},
-		{8, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - The Sword of Frost"), 76}}
-	};
 	int chronicle = 0;
 	for (const auto& kv : chronicles) {
 		if(dataBegin.contains(kv.second))
@@ -142,6 +133,69 @@ bool ChroniclesExtractor::extractGogInstaller(QString file)
 #endif
 }
 
+void ChroniclesExtractor::createBaseMod()
+{
+	QDir dir(pathToQString(VCMIDirs::get().userDataPath() / "Mods"));
+	dir.mkdir("chronicles");
+	dir.cd("chronicles");
+	dir.mkdir("Mods");
+
+	QJsonObject mod
+	{
+		{ "modType", "Extension" },
+		{ "name", "Heroes Chronicles" },
+		{ "description", "" },
+		{ "author", "3DO" },
+		{ "version", "1.0" },
+	};
+
+	QFile jsonFile(dir.filePath("mod.json"));
+    jsonFile.open(QFile::WriteOnly);
+    jsonFile.write(QJsonDocument(mod).toJson());
+}
+
+void ChroniclesExtractor::createChronicleMod(int no)
+{
+	QDir dir(pathToQString(VCMIDirs::get().userDataPath() / "Mods" / "chronicles" / "Mods"));
+	dir.mkdir("chronicles_" + QString::number(no));
+	dir.cd("chronicles_" + QString::number(no));
+
+	QJsonObject mod
+	{
+		{ "modType", "Extension" },
+		{ "name", "Heroes Chronicles - " + QString::number(no) },
+		{ "description", "" },
+		{ "author", "3DO" },
+		{ "version", "1.0" },
+	};
+
+	QFile jsonFile(dir.filePath("mod.json"));
+    jsonFile.open(QFile::WriteOnly);
+    jsonFile.write(QJsonDocument(mod).toJson());
+
+	dir.mkdir("Data");
+	dir.mkdir("Sprites");
+	extractFiles(no);
+}
+
+void ChroniclesExtractor::extractFiles(int no)
+{
+	QByteArray tmpChronicles = chronicles.at(no);
+	tmpChronicles.replace('\0', "");
+
+	QDir tmpDir = tempDir.filePath(tempDir.entryList({"app"}, QDir::Filter::Dirs).front());
+	tmpDir.setPath(tmpDir.filePath(tmpDir.entryList({QString(tmpChronicles)}, QDir::Filter::Dirs).front()));
+	tmpDir.setPath(tmpDir.filePath(tmpDir.entryList({"data"}, QDir::Filter::Dirs).front()));
+	QDir outDirData(pathToQString(VCMIDirs::get().userDataPath() / "Mods" / "chronicles" / "Mods" / ("chronicles_" + std::to_string(no)) / "Data"));
+	QDir outDirSprites(pathToQString(VCMIDirs::get().userDataPath() / "Mods" / "chronicles" / "Mods" / ("chronicles_" + std::to_string(no)) / "Sprites"));
+
+	CArchiveLoader archive("", tmpDir.filePath("xBitmap.lod").toStdString(), false);
+	for(auto & entry : archive.getEntries())
+		archive.extractToFolder(outDirData.absolutePath().toStdString(), "", entry.second, true);
+	for(auto & entry : outDirData.entryList())
+		outDirData.rename(entry, "Hc" + QString::number(no) + "_" + entry);
+}
+
 void ChroniclesExtractor::installChronicles(QStringList exe)
 {
 	extractionFile = -1;
@@ -160,8 +214,10 @@ void ChroniclesExtractor::installChronicles(QStringList exe)
 
 		if(!extractGogInstaller(f))
 			continue;
+		
+		createBaseMod();
+		createChronicleMod(chronicleNo);
 
-		if(!handleTempDir(false))
-			continue;
+		handleTempDir(false);
 	}
 }

+ 14 - 0
launcher/modManager/chroniclesextractor.h

@@ -25,6 +25,20 @@ class ChroniclesExtractor : public QObject
 	bool handleTempDir(bool create);
 	int getChronicleNo(QFile & file);
 	bool extractGogInstaller(QString filePath);
+	void createBaseMod();
+	void createChronicleMod(int no);
+	void extractFiles(int no);
+
+	const std::map<int, QByteArray> chronicles = {
+		{1, QByteArray{reinterpret_cast<const char*>(u"Warlords of the Wasteland"), 50}},
+		{2, QByteArray{reinterpret_cast<const char*>(u"Conquest of the Underworld"), 52}},
+		{3, QByteArray{reinterpret_cast<const char*>(u"Masters of the Elements"), 46}},
+		{4, QByteArray{reinterpret_cast<const char*>(u"Clash of the Dragons"), 40}},
+		{5, QByteArray{reinterpret_cast<const char*>(u"The World Tree"), 28}},
+		{6, QByteArray{reinterpret_cast<const char*>(u"The Fiery Moon"), 28}},
+		{7, QByteArray{reinterpret_cast<const char*>(u"Revolt of the Beastmasters"), 52}},
+		{8, QByteArray{reinterpret_cast<const char*>(u"The Sword of Frost"), 36}}
+	};
 public:
 	void installChronicles(QStringList exe);
 

+ 9 - 2
launcher/modManager/cmodlistview_moc.cpp

@@ -30,6 +30,7 @@
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/texts/Languages.h"
 #include "../../lib/modding/CModVersion.h"
+#include "../../lib/filesystem/Filesystem.h"
 
 static double mbToBytes(double mb)
 {
@@ -838,8 +839,14 @@ void CModListView::installFiles(QStringList files)
 
 	if(!exe.empty())
 	{
-		ChroniclesExtractor ce(this);
-		ce.installChronicles(exe, [](float progress) { });
+		ChroniclesExtractor ce(this, [](float progress) { });
+		ce.installChronicles(exe);
+
+		//update
+		CResourceHandler::get("initial")->updateFilteredFiles([](const std::string &){ return true; });
+		manager->loadMods();
+		modModel->reloadRepositories();
+		emit modsChanged();
 	}
 
 	if(!images.empty())

+ 11 - 6
lib/filesystem/CArchiveLoader.cpp

@@ -197,6 +197,11 @@ std::string CArchiveLoader::getMountPoint() const
 	return mountPoint;
 }
 
+std::unordered_map<ResourcePath, ArchiveEntry> CArchiveLoader::getEntries() const
+{
+	return entries;
+}
+
 std::unordered_set<ResourcePath> CArchiveLoader::getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const
 {
 	std::unordered_set<ResourcePath> foundID;
@@ -209,7 +214,7 @@ std::unordered_set<ResourcePath> CArchiveLoader::getFilteredFiles(std::function<
 	return foundID;
 }
 
-void CArchiveLoader::extractToFolder(const std::string & outputSubFolder, CInputStream & fileStream, const ArchiveEntry & entry) const
+void CArchiveLoader::extractToFolder(const std::string & outputSubFolder, CInputStream & fileStream, const ArchiveEntry & entry, bool absolute) const
 {
 	si64 currentPosition = fileStream.tell(); // save filestream position
 
@@ -217,7 +222,7 @@ void CArchiveLoader::extractToFolder(const std::string & outputSubFolder, CInput
 	fileStream.seek(entry.offset);
 	fileStream.read(data.data(), entry.fullSize);
 
-	boost::filesystem::path extractedFilePath = createExtractedFilePath(outputSubFolder, entry.name);
+	boost::filesystem::path extractedFilePath = createExtractedFilePath(outputSubFolder, entry.name , absolute);
 
 	// writeToOutputFile
 	std::ofstream out(extractedFilePath.string(), std::ofstream::binary);
@@ -227,17 +232,17 @@ void CArchiveLoader::extractToFolder(const std::string & outputSubFolder, CInput
 	fileStream.seek(currentPosition); // restore filestream position
 }
 
-void CArchiveLoader::extractToFolder(const std::string & outputSubFolder, const std::string & mountPoint, ArchiveEntry entry) const
+void CArchiveLoader::extractToFolder(const std::string & outputSubFolder, const std::string & mountPoint, ArchiveEntry entry, bool absolute) const
 {
 	std::unique_ptr<CInputStream> inputStream = load(ResourcePath(mountPoint + entry.name));
 
 	entry.offset = 0;
-	extractToFolder(outputSubFolder, *inputStream, entry);
+	extractToFolder(outputSubFolder, *inputStream, entry, absolute);
 }
 
-boost::filesystem::path createExtractedFilePath(const std::string & outputSubFolder, const std::string & entryName)
+boost::filesystem::path createExtractedFilePath(const std::string & outputSubFolder, const std::string & entryName, bool absolute)
 {
-	boost::filesystem::path extractionFolderPath = VCMIDirs::get().userExtractedPath() / outputSubFolder;
+	boost::filesystem::path extractionFolderPath = absolute ? outputSubFolder : VCMIDirs::get().userExtractedPath() / outputSubFolder;
 	boost::filesystem::path extractedFilePath = extractionFolderPath / entryName;
 
 	boost::filesystem::create_directories(extractionFolderPath);

+ 4 - 3
lib/filesystem/CArchiveLoader.h

@@ -63,12 +63,13 @@ public:
 	std::unique_ptr<CInputStream> load(const ResourcePath & resourceName) const override;
 	bool existsResource(const ResourcePath & resourceName) const override;
 	std::string getMountPoint() const override;
+	std::unordered_map<ResourcePath, ArchiveEntry> getEntries() const;
 	void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override {}
 	std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override;
 	/** Extracts one archive entry to the specified subfolder. Used for Video and Sound */
-	void extractToFolder(const std::string & outputSubFolder, CInputStream & fileStream, const ArchiveEntry & entry) const;
+	void extractToFolder(const std::string & outputSubFolder, CInputStream & fileStream, const ArchiveEntry & entry, bool absolute = false) const;
 	/** Extracts one archive entry to the specified subfolder. Used for Images, Sprites, etc */
-	void extractToFolder(const std::string & outputSubFolder, const std::string & mountPoint, ArchiveEntry entry) const;
+	void extractToFolder(const std::string & outputSubFolder, const std::string & mountPoint, ArchiveEntry entry, bool absolute = false) const;
 
 private:
 	/**
@@ -105,6 +106,6 @@ private:
 };
 
 /** Constructs the file path for the extracted file. Creates the subfolder hierarchy aswell **/
-boost::filesystem::path createExtractedFilePath(const std::string & outputSubFolder, const std::string & entryName);
+boost::filesystem::path createExtractedFilePath(const std::string & outputSubFolder, const std::string & entryName, bool absolute);
 
 VCMI_LIB_NAMESPACE_END