Source: Engines/Wine/QuickScript/Steam Script/script.js

const QuickScript = include("engines.wine.quick_script.quick_script");
const Downloader = include("utils.functions.net.download");
const Wine = include("engines.wine.engine.object");
const { cat, fileExists, writeToFile, createTempFile } = include("utils.functions.filesystem.files");

const Luna = include("engines.wine.verbs.luna");
const Corefonts = include("engines.wine.verbs.corefonts");
const OverrideDLL = include("engines.wine.plugins.override_dll");
const WindowsVersion = include("engines.wine.plugins.windows_version");

const Thread = Java.type("java.lang.Thread");

module.default = class SteamScript extends QuickScript {
    constructor() {
        super();

        this._executable = "steam.exe";
        this._category = "Games";
        this._gameOverlay = true;
    }

    appId(appId) {
        this._appId = appId;
        return this;
    }

    gameOverlay(gameOverlay) {
        // get
        if (arguments.length == 0) {
            return this._gameOverlay;
        }

        // set
        this._gameOverlay = gameOverlay;
        return this;
    }

    manifest(wine) {
        if (!this._manifest) {
            // cache manifest path (will not change during the installation)
            this._manifest = `${wine.prefixDirectory()}/drive_c/${wine.programFiles()}/Steam/steamapps/appmanifest_${
                this._appId
            }.acf`;
        }

        return this._manifest;
    }

    /**
     * Checks whether the software download has started
     *
     * @param {Wine} wine The wine engine object
     * @returns {boolean} True if the download has started, false otherwise
     */
    downloadStarted(wine) {
        if (fileExists(this.manifest(wine))) {
            const manifest = cat(this.manifest(wine));
            const state = parseInt(manifest.match(/"StateFlags"\s+"(\d+)"/)[1], 10);

            return state == 1026 || state == 1042 || state == 1062 || state == 1030;
        } else {
            return false;
        }
    }

    /**
     * Checks whether the software download has finished.
     * To get a valid result with this method `downloadStarted(wine)` needs to return `true` first
     *
     * @param {Wine} wine The wine engine object
     * @returns {boolean} True if the download has finished, false otherwise
     */
    downloadFinished(wine) {
        // check if download already finished (download folder has been deleted)
        if (fileExists(this.manifest(wine))) {
            const manifest = cat(this.manifest(wine));
            const state = parseInt(manifest.match(/"StateFlags"\s+"(\d+)"/)[1], 10);

            return state != 1026 && state != 1042 && state != 1062 && state != 1030;
        } else {
            return false;
        }
    }

    configVdf(wine) {
        if (!this._configVdf) {
            // cache config.vdf path (will not change during the installation)
            this._configVdf = `${wine.prefixDirectory()}/drive_c/${wine.programFiles()}/Steam/config/config.vdf`;
        }

        return this._configVdf;
    }

    // Fix for the "content server unavailable" error (Wine bug 45329)
    fixCertificateIssue(wine) {
        const steamConfigFile = this.configVdf(wine);
        const steamConfig = cat(steamConfigFile);
        const cmPos = steamConfig.indexOf(`"CM"`);
        const csConfig = `"CS" "valve511.steamcontent.com;valve501.steamcontent.com;valve517.steamcontent.com;valve557.steamcontent.com;valve513.steamcontent.com;valve535.steamcontent.com;valve546.steamcontent.com;valve538.steamcontent.com;valve536.steamcontent.com;valve530.steamcontent.com;valve559.steamcontent.com;valve545.steamcontent.com;valve518.steamcontent.com;valve548.steamcontent.com;valve555.steamcontent.com;valve556.steamcontent.com;valve506.steamcontent.com;valve544.steamcontent.com;valve525.steamcontent.com;valve567.steamcontent.com;valve521.steamcontent.com;valve510.steamcontent.com;valve542.steamcontent.com;valve519.steamcontent.com;valve526.steamcontent.com;valve504.steamcontent.com;valve500.steamcontent.com;valve554.steamcontent.com;valve562.steamcontent.com;valve524.steamcontent.com;valve502.steamcontent.com;valve505.steamcontent.com;valve547.steamcontent.com;valve560.steamcontent.com;valve503.steamcontent.com;valve507.steamcontent.com;valve553.steamcontent.com;valve520.steamcontent.com;valve550.steamcontent.com;valve531.steamcontent.com;valve558.steamcontent.com;valve552.steamcontent.com;valve563.steamcontent.com;valve540.steamcontent.com;valve541.steamcontent.com;valve537.steamcontent.com;valve528.steamcontent.com;valve523.steamcontent.com;valve512.steamcontent.com;valve532.steamcontent.com;valve561.steamcontent.com;valve549.steamcontent.com;valve522.steamcontent.com;valve514.steamcontent.com;valve551.steamcontent.com;valve564.steamcontent.com;valve543.steamcontent.com;valve565.steamcontent.com;valve529.steamcontent.com;valve539.steamcontent.com;valve566.steamcontent.com;valve165.steamcontent.com;valve959.steamcontent.com;valve164.steamcontent.com;valve1611.steamcontent.com;valve1601.steamcontent.com;valve1617.steamcontent.com;valve1603.steamcontent.com;valve1602.steamcontent.com;valve1610.steamcontent.com;valve1615.steamcontent.com;valve909.steamcontent.com;valve900.steamcontent.com;valve905.steamcontent.com;valve954.steamcontent.com;valve955.steamcontent.com;valve1612.steamcontent.com;valve1607.steamcontent.com;valve1608.steamcontent.com;valve1618.steamcontent.com;valve1619.steamcontent.com;valve1606.steamcontent.com;valve1605.steamcontent.com;valve1609.steamcontent.com;valve907.steamcontent.com;valve901.steamcontent.com;valve902.steamcontent.com;valve1604.steamcontent.com;valve908.steamcontent.com;valve950.steamcontent.com;valve957.steamcontent.com;valve903.steamcontent.com;valve1614.steamcontent.com;valve904.steamcontent.com;valve952.steamcontent.com;valve1616.steamcontent.com;valve1613.steamcontent.com;valve958.steamcontent.com;valve956.steamcontent.com;valve906.steamcontent.com"\n`;
        const newSteamConfig = steamConfig.slice(0, cmPos) + csConfig + steamConfig.slice(cmPos);

        writeToFile(steamConfigFile, newSteamConfig);
    }

    go() {
        // default application homepage if not specified
        if (!this._applicationHomepage) {
            this._applicationHomepage = `https://store.steampowered.com/app/${this._appId}`;
        }

        // default executable args if not specified
        if (!this._executableArgs) {
            this._executableArgs = ["-no-cef-sandbox", "-silent", "-applaunch", `${this._appId}`];
        }

        const setupWizard = SetupWizard(InstallationType.APPS, this._name, this.miniature());

        setupWizard.presentation(this._name, this._editor, this._applicationHomepage, this._author);

        this._determineWineVersion(setupWizard);

        const tempFile = createTempFile("exe");

        new Downloader()
            .wizard(setupWizard)
            .url("https://steamcdn-a.akamaihd.net/client/installer/SteamSetup.exe")
            .checksum("1e5598f2de49fed2e81f3dd8630c7346a2b89487")
            .to(tempFile)
            .get();

        const wine = new Wine()
            .wizard(setupWizard)
            .prefix(this._name, this._wineDistribution, this._wineArchitecture, this._wineVersion);

        new Luna(wine).go();
        new Corefonts(wine).go();

        // Steam must be started once such that config.vdf is created (see fixCertificateIssue())
        setupWizard.wait(
            tr(
                'Please follow the steps of the Steam setup. Then, wait until Steam is updated, log in and finally close Steam completely so the installation of "{0}" can continue.',
                this._name
            )
        );
        wine.run(tempFile, [], null, false, true);

        // Fix for Uplay games that are executed on steam
        new WindowsVersion(wine)
            .withApplicationWindowsVersion("upc.exe", "winvista")
            .withApplicationWindowsVersion("UbisoftGameLauncher.exe", "winvista")
            .go();

        // ensure that Steam is running (user might have unchecked "run Steam after installation finished")
        wine.runInsidePrefix(`${wine.programFiles()}/Steam/steam.exe`, ["steam://nav/games"], false);

        // wait until config.vdf exists
        while (!fileExists(this.configVdf(wine))) {
            Thread.sleep(1000);
        }

        // wait until Steam and Wine are closed
        wine.wait();

        this.fixCertificateIssue(wine);

        // Steam installation has finished
        setupWizard.wait(tr("Please wait..."));

        this._preInstall(wine, setupWizard);

        // back to generic wait (might have been changed in preInstall)
        setupWizard.wait(tr("Please wait..."));

        wine.runInsidePrefix(`${wine.programFiles()}/Steam/steam.exe`, [`steam://install/${this._appId}`], false);

        setupWizard.wait(tr("Please wait until Steam has finished the download..."));

        // wait until download started
        while (!this.downloadStarted(wine)) {
            Thread.sleep(100);
        }

        // make sure download is finished
        while (!this.downloadFinished(wine)) {
            Thread.sleep(1000);
        }

        // close Steam
        wine.runInsidePrefix(`${wine.programFiles()}/Steam/steam.exe`, "-shutdown", true);

        // back to generic wait
        setupWizard.wait(tr("Please wait..."));

        // create shortcut after installation (if executable is specified, it does not exist earlier)
        this._createShortcut(wine.prefix());

        this._postInstall(wine, setupWizard);

        // deactivate game overlay if desired
        if (!this._gameOverlay) {
            new OverrideDLL(wine).withMode("", ["gameoverlayrenderer"]).go();
        }

        // back to generic wait (might have been changed in postInstall)
        setupWizard.wait(tr("Please wait..."));

        setupWizard.close();
    }
};