Last active
October 1, 2019 13:50
-
-
Save manciuszz/3da7acbc1d2893a3346a82890430d4bf to your computer and use it in GitHub Desktop.
Emscripten's WebAssembly games non-intrusive auto-clicker by hijacking "JSEvents" object event handlers via browser debugger.
This file contains 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
{ // For copy/paste purpose... | |
/* Usually, in most emscripten games "JSEvents" interface is private, therefore we expose it to global scope by using debugger (i.e Developer Tools)... */ | |
if (false) { | |
/* Note: unityWebView.game.Module could be named differently (based on a game), for example like "gameInstance.Module" etc.. */ | |
// Copy this to the debugger and execute to stop at the breakpoint, where we will expose "JSEvents" to global scope. | |
debug(unityWebView.game.Module.SetFullscreen); | |
unityWebView.game.Module.SetFullscreen(); | |
undebug(unityWebView.game.Module.SetFullscreen); | |
//window.JSEvents = JSEvents; // expose this... | |
} | |
} | |
// after successful JSEvents exposure, simply execute the code below which will take advantage of JSEvents to emulate mouse clicks on pre-programmed positions at custom period of time. | |
var findHandler = (function() { | |
let handlerMap = {}; | |
for(let handlerId in JSEvents.eventHandlers) { | |
let handler = JSEvents.eventHandlers[handlerId]; | |
handlerMap[handler.eventTypeString] = handlerId; | |
} | |
return function(handlerType) { | |
return { handlerId: handlerMap[handlerType], handler: JSEvents.eventHandlers[handlerMap[handlerType]] }; | |
}; | |
})(); | |
var removeHandler = function(handlerType) { | |
let eventHandler = findHandler(handlerType); | |
if (eventHandler.handler) | |
JSEvents._removeHandler(eventHandler.handlerId); | |
}; | |
var autoClick = (function() { | |
let mouseMoveHandler = findHandler("mousemove").handler; | |
let mouseDownHandler = findHandler("mousedown").handler; | |
let mouseUpHandler = findHandler("mouseup").handler; | |
let target = unityWebView.game.Module.ctx.canvas; | |
let mouseEvent = { | |
"screenX": 0, | |
"screenY": 0, | |
"clientX": 0, | |
"clientY": 0, | |
"ctrlKey": false, | |
"shiftKey": false, | |
"altKey": false, | |
"metaKey": false, | |
"button": 0, | |
"buttons": 0, | |
"movementX": 0, | |
"movementY": 0, | |
}; | |
return function(x, y) { | |
mouseEvent.screenX = mouseEvent.clientX = x; | |
mouseEvent.screenY = mouseEvent.clientY = y; | |
JSEvents.fillMouseEventData(JSEvents.mouseEvent, mouseEvent, target); | |
unityWebView.game.Module["dynCall_iiii"](mouseMoveHandler.callbackfunc, 8, JSEvents.mouseEvent, 0); | |
unityWebView.game.Module["dynCall_iiii"](mouseDownHandler.callbackfunc, 5, JSEvents.mouseEvent, 0); | |
unityWebView.game.Module["dynCall_iiii"](mouseUpHandler.callbackfunc, 6, JSEvents.mouseEvent, 0); | |
}; | |
})(); | |
var bounds = { width: unityWebView.game.Module.canvas.width, height: unityWebView.game.Module.canvas.height }; | |
var autoClicker = { | |
interval: 85, | |
timerId: autoClicker && autoClicker.timerId, | |
timeoutClick: function(id, x, y, interval) { | |
autoClicker[id] = autoClicker[id] || setTimeout(function() { | |
autoClick(x, y); | |
autoClicker[id] = null; | |
}, interval); | |
}, | |
init: function() { | |
removeHandler("blur"); | |
clearInterval(autoClicker.timerId); | |
autoClicker.timerId = setInterval(function() { | |
/* Auto-Clicking positions goes here... */ | |
autoClick(bounds.width - 135, bounds.height - 278); | |
autoClicker.timeoutClick("autoProgress_start", bounds.width + 105, bounds.height - 351, autoClicker.interval / 5); | |
autoClicker.timeoutClick("autoProgress_next/finish", bounds.width + 116, bounds.height - 351, autoClicker.interval / 4); | |
autoClicker.timeoutClick("level_up_Mizuki", bounds.width - 470, bounds.height - 527, autoClicker.interval / 3); | |
autoClicker.timeoutClick("level_up_Bunny", bounds.width - 470, bounds.height - 418, autoClicker.interval / 2); | |
autoClicker.timeoutClick("level_up_Estelle", bounds.width - 470, bounds.height - 312, autoClicker.interval / 1); | |
// autoClicker.timeoutClick("level_up_Megane", bounds.width - 470, bounds.height - 205, autoClicker.interval / 3); | |
// autoClicker.timeoutClick("level_up_Angela", bounds.width - 470, bounds.height - 96, autoClicker.interval / 2); | |
// autoClicker.timeoutClick("level_up_Lyrsa", bounds.width - 470, bounds.height + 12, autoClicker.interval / 1); | |
autoClicker.timeoutClick("autoSkill_NeptunesTouch", bounds.width - 97, bounds.height - 15, 58 * 1000); | |
autoClicker.timeoutClick("autoSkill_ExitingFlirt", bounds.width - 28, bounds.height - 15, 59 * 1000); | |
autoClicker.timeoutClick("autoSkill_ManlySweat", bounds.width + 34, bounds.height - 15, 61 * 1000); | |
autoClicker.timeoutClick("autoBonusClaimer", bounds.width + 210, bounds.height - 165, 30 * 1000); | |
}, autoClicker.interval); | |
} | |
}; | |
/* Toggle ON/OFF Switch via 'Spacebar' and custom active zone */ | |
var toggleState = true; | |
if (typeof printMousePos !== "undefined") | |
document.removeEventListener("click", printMousePos); | |
if (typeof activeZone !== "undefined") | |
document.removeEventListener("mousemove", activeZone); | |
if (typeof toggleButton !== "undefined") | |
document.removeEventListener("keyup", toggleButton); | |
var printMousePos = function(mouseEvt) { | |
console.log(`${mouseEvt.clientX}, ${mouseEvt.clientY}`); | |
console.log(`autoClick(bounds.width - ${bounds.width - mouseEvt.clientX}, bounds.height - ${bounds.height - mouseEvt.clientY});`); | |
}; | |
var activeZone = function(evt) { | |
if (!toggleState) | |
return false; | |
if (evt.clientX < bounds.width / 1.5) { | |
if (autoClicker.timerId) { | |
clearInterval(autoClicker.timerId); | |
autoClicker.timerId = null; | |
console.log("[ActionZone] AutoClicker OFF!"); | |
} | |
} else if (autoClicker.timerId == null) { | |
autoClicker.init(); | |
console.log("[ActionZone] AutoClicker ON!"); | |
} | |
}; | |
var toggleButton = function(evt) { | |
if (evt.keyCode == 32) { | |
toggleState = !toggleState; | |
if (toggleState && autoClicker.timerId == null) { | |
autoClicker.init(); | |
console.log("[KeyPress] AutoClicker ON!"); | |
} else { | |
clearInterval(autoClicker.timerId); | |
autoClicker.timerId = null; | |
console.log("[KeyPress] AutoClicker OFF!"); | |
} | |
} | |
}; | |
document.addEventListener("click", printMousePos); | |
document.addEventListener("mousemove", activeZone); | |
document.addEventListener("keyup", toggleButton); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment