Lightbourn

Getting PolyMC to download "blocked" Minecraft mod packs

I had the urge to play modded Minecraft again and happened across some information that Curseforge has been trying to block 3rd party launchers from downloading "disabled" mods (creators can explicitly disallow downloads not from the website or the 1st party launcher).

Being one who does not enjoy having software forced upon, I went searching for a workaround but could only find one that was already removed. Thus, I hacked together a patch for PolyMC myself.

Here are the steps to do it yourself; you need to be able to build PolyMC yourself and operate a git repo both of which are described on PolyMC's build instructions.

  1. Set up PolyMC's build environment
  2. Edit /launcher/modplatform/flame/FileResolvingTask.cpp:
    @@ -42,6 +42,12 @@ void Flame::FileResolvingTask::netJobFinished()
            out.parseFromObject(Json::requireObject(file));
         } catch (const JSONValidationError& e) {
             qDebug() << "Blocked mod on curseforge" << out.fileName;
    +
    +            out.url = QUrl(QString("https://media.forgecdn.net/files/%1/%2/%3")
    +                .arg(QString::number(QString::number(out.fileId).leftRef(4).toInt())
    +                ,QString::number(QString::number(out.fileId).rightRef(3).toInt())
    +                ,QUrl::toPercentEncoding(out.fileName)), QUrl::TolerantMode);
    +
             auto hash = out.hash;
             if(!hash.isEmpty()) {
                 auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash);
  3. Edit /launcher/modplatform/flame/FlameModIndex.cpp:
    @@ -56,7 +56,14 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
            file.fileId = Json::requireInteger(obj, "id");
            file.date = Json::requireString(obj, "fileDate");
            file.version = Json::requireString(obj, "displayName");
    -        file.downloadUrl = Json::requireString(obj, "downloadUrl");
    +        file.downloadUrl = Json::ensureString(obj, "downloadUrl", "");
    +        if (file.downloadUrl.isEmpty()) {
    +            file.downloadUrl = QString("https://media.forgecdn.net/files/%1/%2/%3")
    +                .arg(QString::number(QString::number(file.fileId.toInt()).leftRef(4).toInt())
    +                ,QString::number(QString::number(file.fileId.toInt()).rightRef(3).toInt())
    +                ,QUrl::toPercentEncoding(file.fileName));
    +        }
    +
            file.fileName = Json::requireString(obj, "fileName");
    
            unsortedVersions.append(file);
  4. Edit /launcher/modplatform/flame/FlamePackIndex.cpp:
    @@ -67,10 +67,14 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr)
            file.version = Json::requireString(version, "displayName");
            file.downloadUrl = Json::ensureString(version, "downloadUrl");
    
    -        // only add if we have a download URL (third party distribution is enabled)
    -        if (!file.downloadUrl.isEmpty()) {
    -            unsortedVersions.append(file);
    +        if (file.downloadUrl.isEmpty()) {
    +            file.downloadUrl = QString("https://media.forgecdn.net/files/%1/%2/%3")
    +                .arg(QString::number(QString::number(file.fileId).leftRef(4).toInt())
    +                ,QString::number(QString::number(file.fileId).rightRef(3).toInt())
    +                ,QUrl::toPercentEncoding(Json::requireString(version, "fileName")));
            }
    +
    +        unsortedVersions.append(file);
        }
    
        auto orderSortPredicate = [](const IndexedVersion& a, const IndexedVersion& b) -> bool { return a.fileId > b.fileId; };
  5. Build and install.

With these changes you should be able to download mods which have disallowed third party launchers. It will still warn you about manually downloading these mods, but the program will do it anyways.

Alternatively, you can download the exe I built and place it in a PolyMC 1.3.1 directory


Unity 3D il2cpp GameAssembly.dll Crash

I've been having constant issues with Unity games that make use of the il2cpp plugin. Every single Unity game crashes when it tries to load up the "main" scene, and I've found that they all have the same solution. The solution involves editing the game's GameAssembly.dll file, so make a backup before you do anything.

  1. When the game crashes, open the more info section, verify that the module name is "GameAssembly.dll" and the exception code is "c0000005," and find the "Exception Offset."
  2. Open the GameAssembly.dll file in a hex editor (e.g. HxD).
  3. Go to the offset noted in the first step. You should find the values 48 8B 01 at the cursor.
  4. Replace 48 8B 01 with 90 90 90.
  5. look ahead a dozen or so bytes for the value FF 10.
  6. Replace FF 10 with 90 90.
  7. Save the file.

The game should run fine now, but you may need to do multiple iterations before it stops crashing completely. That is to say, the offset will change but the machine code will be the same.

I haven't found out why Unity crashes here with 100% reliability, and I haven't looked into why the offending code exists (it loads a function pointer from a pointer and calls it), but I've used this fix on a couple games so far and I haven't noticed any ill side effects. Whatever its purpose is, it's unrelated to the function of the game.


Noita Salakieli File Editor

Here's a tool I made that can open, edit, and save *.salakieli files from the game Noita. I was trying to find out more information on the 9 eye arrays by reverse engineering Noita's executable. I still haven't found anything, but I made this as it was something I was investigating, and I'm sure someone will find it useful.

I added the key and Iv values in the code, but the tool doesn't do anything with the two in-memory encrypted alchemy lists (the plain text looks something like "blood|blood_fungus|acid") which use them as I don't think they ever get saved to disk. They probably have something to do with fungal shifts, but that's pure speculation on my part.