Created
December 12, 2017 21:33
-
-
Save SReject/c2e054bd40eda6e13b1a99d3a7bce704 to your computer and use it in GitHub Desktop.
Exposes factoryidle.com's main game instance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Factoryidle Game Instance Exposer | |
// @namespace SReject/FactoryIdle/Exposer | |
// @version 0.0.1 | |
// @description Exposes factoryidle.com's Game instance | |
// @author SReject | |
// @match http*://factoryidle.com/ | |
// @match http*://www.factoryidle.com/ | |
// @run-at document-start | |
// ==/UserScript== | |
/* | |
To reference the main game instance | |
you can reference the created global object: | |
MainInstance | |
or require() it as you would a typical requirejs module: | |
require(["mainGameInstance"], function (mainGameInstance) { | |
console.log(mainGameInstance); | |
}); | |
*/ | |
(function() { | |
const FI_SCRIPT = 'http://factoryidle.com/app.js'; | |
// modifies factoryidle.com/app.js game script to expose | |
const loadModifiedScript = () => { | |
fetch(FI_SCRIPT).then((response) => { | |
return response.text(); | |
}).then((res) => { | |
// Add declarations for requirejs, require, define and MainInstance | |
// to the start of the script | |
let modifiedScript = 'var requirejs,require,define,MainInstance;'; | |
// Remove the internal declarations of requirejs, require, and | |
// define to make them globally available | |
modifiedScript += res.replace(/var\s+requirejs,\s*require,\s*define\s*;/, ''); | |
// Remove the internal declaration of MainInstance to make it | |
// globally available | |
modifiedScript = modifiedScript.replace(/var MainInstance,/, 'var '); | |
// Add the game's main instance(MainInstance) as a requirejs module | |
modifiedScript = modifiedScript.replace(/(define\("app",[^;]*;)/, '$1define(\'mainGameInstance\',()=>MainInstance);'); | |
// Create a new script node | |
// add the modified script as its source | |
let node = document.createElement('script'); | |
node.appendChild(document.createTextNode(modifiedScript)); | |
// if the page has finished initial loading (document.head is | |
// available), append the modified script to document.head | |
if (document.readyState === "interactive" || document.readyState === "complete") { | |
document.head.appendChild(node); | |
// otherwise, wait for the page to finish initial loading then append | |
// modified script to document head | |
} else { | |
document.addEventListener('DOMContentLoaded', function handler() { | |
document.removeEventListener('DOMContentLoaded', handler); | |
document.head.appendChild(node); | |
}); | |
} | |
}); | |
}; | |
// (Chrome) Stop factoryidle's app.js from loading | |
// Chrome doesn't support the beforescriptexecute event, so trap the loading | |
// of the game script using MutationObserver | |
if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { | |
// create a new MutationObserver | |
const observer = new MutationObserver((mutations) => { | |
// loop over the list of mutations that occured | |
for (let mutation of mutations) { | |
// if the mutation in question is a list of nodes added to the document | |
if (mutation.type === 'childList' && mutation.addedNodes && mutation.addedNodes.length) { | |
// loop over each node added | |
Array.from(mutation.addedNodes).find((node) => { | |
// If the node added was not the game script, ignore it | |
if (node.tagName === undefined) return false; | |
if (String(node.tagName).toLowerCase() !== 'script') return false; | |
if (String(node.src).toLowerCase() !== FI_SCRIPT) return false; | |
// if the node is the game script, disconnect the observer | |
// and reset the node's src property so the game script | |
// isn't executed | |
observer.disconnect(); | |
node.src = ''; | |
// Attempt to load the modified script | |
loadModifiedScript(); | |
}); | |
} | |
} | |
}); | |
// watch for ONLY nodes to be added/removed | |
observer.observe(document.documentElement, { | |
childList: true, | |
subtree: true, | |
attributes: false, | |
characterData: false | |
}); | |
// (firefox) Stop factoryidle's app.js load via beforescriptexecute event | |
} else { | |
// listen for the document to emit beforescriptexecute events | |
document.addEventListener('beforescriptexecute', function handler(evt) { | |
// check that the script is the game's script | |
if (evt.target.src == FI_SCRIPT) { | |
// prevent the script from executing | |
evt.preventDefault(); | |
// remove the listener | |
document.removeEventListener('beforescriptexecute', handler); | |
// attempt to load the modified script | |
loadModifiedScript(); | |
} | |
}, true) | |
} | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment