Shell Shockers Model Injector: Barclay's

Import whatever model URLs you need - template and example code

目前為 2025-02-08 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Shell Shockers Model Injector: Barclay's
// @namespace    https://github.com/onlypuppy7/BarclaysShellShockers/
// @license      GPL-3.0
// @version      1.0.3
// @author       onlypuppy7
// @description  Import whatever model URLs you need - template and example code
// @match        https://shellshock.io/*
// @grant        none
// @run-at       document-start
// @icon         https://github.com/onlypuppy7/BarclaysShellShockers/blob/main/logo.png?raw=true
// @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
// ==/UserScript==

//This script is based off LibertyMutual by onlypuppy7
//This script is more of a template than a functioning tool. If you're modifying this, you can add a GUI to start!

const objectModelURLs = [
    "https://cdn.onlypuppy7.online/eggtest.glb",
    "https://cdn.onlypuppy7.online/guntest3.glb"
    //put model urls here. glb format ONLY.
    //put replacements for anything EXCEPT maps here (eg egg (hats), guns, etc)
];

const mapModelURLs = [
    //these models are loaded in a different sequence, currently only consisting of ["map"]
    //so to ensure the correct order, put any models that overwrite map models here
    //same format as objects.
];

(function () {
    // crackedshell is a script executor for chromebooks
    let crackedShell = typeof $WEBSOCKET !== 'undefined';

    let originalReplace = String.prototype.replace;

    String.prototype.originalReplace = function() {
        return originalReplace.apply(this, arguments);
    };

    //Credit for script injection code: AI. ChatGPT prompt: "tampermonkey script. how can i make it grab a javascript file as it's loaded. if it detects the javascript file, make it apply modifications to it via regex? using XMLHttpRequest"
    //Credit for idea to use XMLHttpRequest: A3+++
    const originalXHROpen = XMLHttpRequest.prototype.open;
    const originalXHRGetResponse = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response');
    let shellshockjs
    XMLHttpRequest.prototype.open = function(...args) {
        const url = args[1];
        if (url && url.includes("js/shellshock.js")) {
            shellshockjs = this;
        };
        originalXHROpen.apply(this, args);
    };
    Object.defineProperty(XMLHttpRequest.prototype, 'response', {
        get: function() {
            if (this===shellshockjs) {
                return applyBarclays(originalXHRGetResponse.get.call(this));
            };
            return originalXHRGetResponse.get.call(this);
        }
    });
    //VAR STUFF
    let F=[];
    let H={};
    let functionNames=[];

    //scrambled... geddit????
    const getScrambled=function(){return Array.from({length: 10}, () => String.fromCharCode(97 + Math.floor(Math.random() * 26))).join('')}
    const createAnonFunction=function(name,func){
        const funcName=getScrambled();
        window[funcName]=func;
        F[name]=window[funcName];
        functionNames[name]=funcName
    };
    const findKeyWithProperty = function(obj, propertyToFind) {
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (key === propertyToFind) {
                    return [key];
                } else if (
                    typeof obj[key] === 'object' &&
                    obj[key] !== null &&
                    obj[key].hasOwnProperty(propertyToFind)
                ) {
                    return key;
                };
            };
        };
        // Property not found
        return null;
    };
    const fetchTextContent = function(url) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, false); // Make the request synchronous
        xhr.send();
        if (xhr.status === 200) {
            return xhr.responseText;
        } else {
            console.error("Error fetching text content. Status:", xhr.status);
            return null;
        };
    };

    const applyBarclays = function(js) {
        // support crackedshell's harsh rewriting system
        // more info @ https://github.com/VillainsRule/CrackedShell
        let clientKeyJS = js;
        if (crackedShell) clientKeyJS = fetchTextContent('/js/shellshock.og.js');

        let hash = CryptoJS.SHA256(clientKeyJS).toString(CryptoJS.enc.Hex);
        let clientKeys;
        onlineClientKeys = fetchTextContent("https://raw.githubusercontent.com/StateFarmNetwork/client-keys/main/barclays_latest.json"); //credit: me :D

        if (onlineClientKeys == "value_undefined" || onlineClientKeys == null) {
            let userInput = prompt('Valid keys could not be retrieved online. Enter keys if you have them. Join the SFNetwork Discord server to generate keys! https://discord.gg/HYJG3jXVJF', '');
            if (userInput !== null && userInput !== '') {
                alert('Aight, let\'s try this. If it is invalid, it will just crash.');
                clientKeys = JSON.parse(userInput);
            } else {
                alert('You did not enter anything, this is gonna crash lmao.');
            };
        } else {
            clientKeys = JSON.parse(onlineClientKeys);
        };

        H = clientKeys.vars;
        console.log(H);

        let injectionString="";
        
        const modifyJS = function(find,replace) {
            let oldJS = js;
            js = js.originalReplace(find,replace);
            if (oldJS !== js) {
                console.log("%cReplacement successful! Injected code: "+replace, 'color: green; font-weight: bold; font-size: 0.6em; text-decoration: italic;');
            } else {
                console.log("%cReplacement failed! Attempted to replace "+find+" with: "+replace, 'color: red; font-weight: bold; font-size: 0.6em; text-decoration: italic;');
            };
        };

        console.log('%cATTEMPTING TO START BARCLAYS', 'color: magenta; font-weight: bold; font-size: 1.5em; text-decoration: underline;');
        const variableNameRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; //prevent adding spooky code
        for (let name in H) {
            deobf = H[name];
            if (variableNameRegex.test(deobf)) {
                injectionString = `${injectionString}${name}: (() => { try { return ${deobf}; } catch (error) { return "value_undefined"; } })(),`;
            } else {
                alert("Message from the Barclays Devs: WARNING! The keys inputted contain non-variable characters! There is a possibility that this could run code unintended by the Barclays team, although possibly there is also a mistake. Do NOT proceed with using this, and report to the Barclays developers what is printed in the console.");
                console.log("REPORT THIS IN THE DISCORD SERVER:", clientKeys);
                const crashplease = "balls";
                crashplease = "balls2";
            };
        };
        console.log(injectionString);
        //ingame loop
        modifyJS(H.SCENE+'.render',`window["${functionNames.retrieveFunctions}"]({${injectionString}},true)||${H.SCENE}.render`);

        //adding ours to the list
        let regex = `${H.loadMeshes}\\\([a-zA-Z$_,]+\\\)\\\{`;
        let match = new RegExp(regex).exec(js);
        console.log("loadMeshes regex", regex, match);
        modifyJS(match[0],match[0]+`window["${functionNames.BARCLAYS}"](arguments);window.ballsMaterial=o;`);
        //setting it to "" where it applies
        modifyJS(`addTask\(\);!`,`addTask\(\);[${H.rootUrl},${H.meshPath}]=window["${functionNames.setRootUrl}"](${H.rootUrl}, ${H.meshIdx}, ${H.meshPath}, arguments);console.log([${H.rootUrl},${H.meshPath}]);!`);
        //logging extra models? (pointless)
        // modifyJS(`;if("__root__"`,`;if (window["${functionNames.meshOnSuccess}"](${H.meshOnSuccess})) continue;if("__root__"`);

        modifyJS(`,m\.isPickable`,`,window["${functionNames.meshOnSuccess}"](${H.meshOnSuccess}),m\.isPickable`);

        modifyJS("Not playing in iframe", "BARCLAYS ACTIVE!");
        // console.log(js);
        return js;
    };

    let meshNames = [];
    let loadedMeshes = [];

    createAnonFunction("retrieveFunctions", function(vars) {
        ss = vars;
        ss.SCENE.getMaterialByName("standard").alphaMode = 0;
    });
    createAnonFunction("BARCLAYS", function(args) {
        let scene = args[0];

        window.SCENE = scene;
        scene.getMaterialByName("standard").alphaMode = 0;

        meshNames = args[1];
        loadedMeshes = [];
        window.globalArgs = args;

        function addMesh(meshName, array) {
            // meshName = meshName.includes(".") ? meshName.substring(0, meshName.lastIndexOf(".")) : meshName;
            array.unshift(meshName);
        };
        
        if (meshNames.includes("map")) {
            mapModelURLs.forEach(item => addMesh(item, meshNames));
        } else {
            objectModelURLs.forEach(item => addMesh(item, meshNames));
        };

        console.log("BARCLAYS: BARCLAYS", meshNames);
    });

    createAnonFunction("setRootUrl", function(rootUrl, meshIdx, meshPath, args) {
        let meshName = meshNames[meshIdx];

        if (meshName.includes("://")) rootUrl = "";

        function removeGLBExtension(fileName) {
            const regex = /(\.[a-z0-9]+)\.glb(\?.*)?$/i;
            return fileName.replace(regex, '$1$2');
        };

        meshPath = removeGLBExtension(meshPath);

        console.log("BARCLAYS: setRootUrl", rootUrl, meshIdx, meshPath, meshName);
        
        return [rootUrl, meshPath];
    });

    createAnonFunction("meshOnSuccess", function(mesh2) {
        console.log(mesh2.name, mesh2.material.alphaMode);
        
        mesh2.material.alphaMode = 0;

        // let meshExists = loadedMeshes.includes(mesh2.name);

        // if (meshExists) console.log("BARCLAYS: mesh already exists:", mesh2.name);
        // else loadedMeshes.push(mesh2.name);
        
        // return meshExists;
    });
})();