Skip to content

Instantly share code, notes, and snippets.

@SReject
Created December 12, 2017 21:33
Show Gist options
  • Save SReject/c2e054bd40eda6e13b1a99d3a7bce704 to your computer and use it in GitHub Desktop.
Save SReject/c2e054bd40eda6e13b1a99d3a7bce704 to your computer and use it in GitHub Desktop.
Exposes factoryidle.com's main game instance
// ==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