#include "FTBInstanceProvider.h" #include #include #include #include #include #include #include "Env.h" #include "LegacyFTBInstance.h" #include "OneSixFTBInstance.h" inline uint qHash(FTBRecord record) { return qHash(record.instanceDir); } FTBInstanceProvider::FTBInstanceProvider(SettingsObjectPtr settings) : BaseInstanceProvider(settings) { // nil } QList FTBInstanceProvider::discoverInstances() { // nothing to load when we don't have if (m_globalSettings->get("TrackFTBInstances").toBool() != true) { return {}; } m_records.clear(); discoverFTBEntries(); return m_records.keys(); } InstancePtr FTBInstanceProvider::loadInstance(const InstanceId& id) { // process the records we acquired. auto iter = m_records.find(id); if(iter == m_records.end()) { qWarning() << "Cannot load instance" << id << "without a record"; return nullptr; } auto & record = m_records[id]; qDebug() << "Loading FTB instance from " << record.instanceDir; QString iconKey = record.iconKey; auto icons = ENV.icons(); if(icons) { icons->addIcon(iconKey, iconKey, FS::PathCombine(record.templateDir, record.logo), IconType::Transient); } auto settingsFilePath = FS::PathCombine(record.instanceDir, "instance.cfg"); qDebug() << "ICON get!"; if (QFileInfo(settingsFilePath).exists()) { auto instPtr = loadInstance(record); if (!instPtr) { qWarning() << "Couldn't load instance config:" << settingsFilePath; if(!QFile::remove(settingsFilePath)) { qWarning() << "Couldn't remove broken instance config!"; return nullptr; } // failed to load, but removed the poisonous file } else { return InstancePtr(instPtr); } } auto instPtr = createInstance(record); if (!instPtr) { qWarning() << "Couldn't create FTB instance!"; return nullptr; } return InstancePtr(instPtr); } void FTBInstanceProvider::discoverFTBEntries() { QDir dir = QDir(m_globalSettings->get("FTBLauncherLocal").toString()); QDir dataDir = QDir(m_globalSettings->get("FTBRoot").toString()); if (!dataDir.exists()) { qDebug() << "The FTB directory specified does not exist. Please check your settings"; return; } else if (!dir.exists()) { qDebug() << "The FTB launcher data directory specified does not exist. Please check " "your settings"; return; } dir.cd("ModPacks"); auto allFiles = dir.entryList(QDir::Readable | QDir::Files, QDir::Name); for (auto filename : allFiles) { if (!filename.endsWith(".xml")) continue; auto fpath = dir.absoluteFilePath(filename); QFile f(fpath); qDebug() << "Discovering FTB instances -- " << fpath; if (!f.open(QFile::ReadOnly)) continue; // read the FTB packs XML. QXmlStreamReader reader(&f); while (!reader.atEnd()) { switch (reader.readNext()) { case QXmlStreamReader::StartElement: { if (reader.name() == "modpack") { QXmlStreamAttributes attrs = reader.attributes(); FTBRecord record; record.dirName = attrs.value("dir").toString(); record.instanceDir = dataDir.absoluteFilePath(record.dirName); record.templateDir = dir.absoluteFilePath(record.dirName); QDir test(record.instanceDir); qDebug() << dataDir.absolutePath() << record.instanceDir << record.dirName; if (!test.exists()) continue; record.name = attrs.value("name").toString(); record.logo = attrs.value("logo").toString(); QString logo = record.logo; record.iconKey = logo.remove(QRegularExpression("\\..*")); auto customVersions = attrs.value("customMCVersions"); if (!customVersions.isNull()) { QMap versionMatcher; QString customVersionsStr = customVersions.toString(); QStringList list = customVersionsStr.split(';'); for (auto item : list) { auto segment = item.split('^'); if (segment.size() != 2) { qCritical() << "FTB: Segment of size < 2 in " << customVersionsStr; continue; } versionMatcher[segment[0]] = segment[1]; } auto actualVersion = attrs.value("version").toString(); if (versionMatcher.contains(actualVersion)) { record.mcVersion = versionMatcher[actualVersion]; } else { record.mcVersion = attrs.value("mcVersion").toString(); } } else { record.mcVersion = attrs.value("mcVersion").toString(); } record.description = attrs.value("description").toString(); auto id = "FTB/" + record.dirName; m_records[id] = record; } break; } case QXmlStreamReader::EndElement: break; case QXmlStreamReader::Characters: break; default: break; } } f.close(); } } InstancePtr FTBInstanceProvider::loadInstance(const FTBRecord & record) const { InstancePtr inst; auto m_settings = std::make_shared(FS::PathCombine(record.instanceDir, "instance.cfg")); m_settings->registerSetting("InstanceType", "Legacy"); qDebug() << "Loading existing " << record.name; QString inst_type = m_settings->get("InstanceType").toString(); if (inst_type == "LegacyFTB") { inst.reset(new LegacyFTBInstance(m_globalSettings, m_settings, record.instanceDir)); } else if (inst_type == "OneSixFTB") { inst.reset(new OneSixFTBInstance(m_globalSettings, m_settings, record.instanceDir)); } else { return nullptr; } qDebug() << "Construction " << record.instanceDir; SettingsObject::Lock lock(inst->settings()); inst->init(); qDebug() << "Init " << record.instanceDir; inst->setGroupInitial("FTB"); /** * FIXME: this does not respect the user's preferences. BUT, it would work nicely with the planned pack support * -> instead of changing the user values, change pack values (defaults you can look at and revert to) */ /* inst->setName(record.name); inst->setIconKey(record.iconKey); inst->setNotes(record.description); */ if (inst->intendedVersionId() != record.mcVersion) { inst->setIntendedVersionId(record.mcVersion); } qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot(); return inst; } InstancePtr FTBInstanceProvider::createInstance(const FTBRecord & record) const { QDir rootDir(record.instanceDir); InstancePtr inst; qDebug() << "Converting " << record.name << " as new."; if (!rootDir.exists() && !rootDir.mkpath(".")) { qCritical() << "Can't create instance folder" << record.instanceDir; return nullptr; } auto m_settings = std::make_shared(FS::PathCombine(record.instanceDir, "instance.cfg")); m_settings->registerSetting("InstanceType", "Legacy"); // all legacy versions are built in. therefore we can do this even if we don't have ALL the versions Mojang has on their servers. m_settings->set("InstanceType", "OneSixFTB"); inst.reset(new OneSixFTBInstance(m_globalSettings, m_settings, record.instanceDir)); // initialize { SettingsObject::Lock lock(inst->settings()); inst->setIntendedVersionId(record.mcVersion); inst->init(); inst->setGroupInitial("FTB"); inst->setName(record.name); inst->setIconKey(record.iconKey); inst->setNotes(record.description); } return inst; }