From f0140ee56b37ff1e68a6bf0e9fdd0d1ece14bcf1 Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Sun, 28 Jul 2024 23:07:54 -0400 Subject: [PATCH] Allow using custom authlib-injector JAR Signed-off-by: Evan Goode --- launcher/LaunchController.cpp | 10 ++++-- launcher/minecraft/Agent.h | 5 +++ launcher/minecraft/MinecraftInstance.h | 3 -- launcher/minecraft/PackProfile.cpp | 50 +++++++++++++++++++++++++- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 2f4c264c7..951d74a9e 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -146,9 +146,15 @@ void LaunchController::login() if (m_accountToUse->usesCustomApiServers()) { MinecraftInstancePtr inst = std::dynamic_pointer_cast(m_instance); - const auto& authlibInjectorVersion = inst->getPackProfile()->getComponentVersion("moe.yushi.authlibinjector"); + bool authlibInjectorInstalled = false; + const auto& agents = inst->getPackProfile()->getProfile()->getAgents(); + for (const auto& agent : agents) { + if (agent->library()->artifactPrefix() == "moe.yushi:authlibinjector") { + authlibInjectorInstalled = true; + } + } - if (authlibInjectorVersion == "") { + if (!authlibInjectorInstalled) { // Account uses custom API servers, but authlib-injector is missing int globalMissingBehavior = APPLICATION->settings()->get("MissingAuthlibInjectorBehavior").toInt(); diff --git a/launcher/minecraft/Agent.h b/launcher/minecraft/Agent.h index bc385a74e..565e33d52 100644 --- a/launcher/minecraft/Agent.h +++ b/launcher/minecraft/Agent.h @@ -1,9 +1,14 @@ #pragma once #include +#include #include "Library.h" +static const std::unordered_set MANAGED_AGENTS = { "moe.yushi:authlibinjector" }; +static const std::map AGENT_CLASS_TO_MANAGED_AGENT = { { "moe.yushi.authlibinjector.Premain", + "moe.yushi:authlibinjector" } }; + class Agent; using AgentPtr = std::shared_ptr; diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 3e2e5ce99..1de7d56aa 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -38,13 +38,10 @@ #include #include #include -#include #include "BaseInstance.h" #include "minecraft/launch/MinecraftServerTarget.h" #include "minecraft/mod/Mod.h" -const std::unordered_set MANAGED_AGENTS = { "moe.yushi:authlibinjector" }; - class ModFolderModel; class ResourceFolderModel; class ResourcePackFolderModel; diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index e49761d62..42804cbd0 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -40,6 +40,9 @@ #include "Application.h" #include +#include +#include +#include #include #include #include @@ -49,10 +52,12 @@ #include #include #include +#include #include "Exception.h" #include "FileSystem.h" #include "Json.h" +#include "Manifest.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/OneSixVersionFormat.h" #include "minecraft/ProfileUtils.h" @@ -874,6 +879,30 @@ bool PackProfile::installCustomJar_internal(QString filepath) return true; } +std::optional getJarManifest(const QFileInfo& fileinfo) +{ + QuaZip zip(fileinfo.filePath()); + if (!zip.open(QuaZip::mdUnzip)) { + return std::nullopt; + } + + std::optional manifest; + QuaZipFile file(&zip); + if (zip.setCurrentFile("META-INF/MANIFEST.MF") && file.open(QIODevice::ReadOnly)) { + try { + const auto& file_bytes = file.readAll(); + std::string file_contents(file_bytes.constData(), file_bytes.size()); + std::istringstream iss{ file_contents }; + manifest = Manifest(iss, fileinfo.fileName().toStdString()); + } catch (std::exception& ex) { + qDebug() << "Error parsing META/MANIFEST.MF inside " << fileinfo.path() << ":" << ex.what(); + } + file.close(); + } + zip.close(); + return manifest; +} + bool PackProfile::installAgents_internal(QStringList filepaths) { // FIXME code duplication @@ -903,7 +932,26 @@ bool PackProfile::installAgents_internal(QStringList filepaths) auto agent = std::make_shared(); - agent->setRawName("custom.agents:" + id + ":1"); + QString rawName = "custom.agents:" + id + ":1"; + + auto manifest = getJarManifest(sourceInfo); + if (manifest.has_value()) { + const auto& attrs = manifest->getMainAttributes(); + + if (auto ac = attrs.find("Agent-Class"); ac != attrs.end()) { + const auto& agentClass = ac->second; + if (auto ma = AGENT_CLASS_TO_MANAGED_AGENT.find(agentClass); ma != AGENT_CLASS_TO_MANAGED_AGENT.end()) { + const auto& artifactPrefix = QString::fromStdString(ma->second); + QString version = "1"; + if (auto iv = attrs.find("Implementation-Version"); iv != attrs.end()) { + version = QString::fromStdString(iv->second); + } + rawName = artifactPrefix + ":" + version; + } + } + } + + agent->setRawName(rawName); agent->setFilename(targetBaseName); agent->setDisplayName(sourceInfo.completeBaseName()); agent->setHint("local");