I'm working on a single-player browser-based RPG in my free time. I do allow for saving the user's game on the server, but the game is largely going to run locally and I therefore acknowledge that it is impossible to outright prevent a user from cheating in a myriad of ways.
I'm just looking at the idea of a "dookie" achievement for editing the game data, and was wondering if this solution is in any way viable?
if (Reflect.set.toString() !== 'function set() { [native code] }') {
throw new TypeError('Missing native Reflect.set');
}
if (Error.constructor.toString() !== 'function Function() { [native code] }') {
throw new TypeError('Missing native Error constructor');
}
if (Proxy.constructor.toString() !== 'function Function() { [native code] }') {
throw new TypeError('Missing native Proxy constructor');
}
function setTrap(target, _1, _2, receiver) {
const res = Reflect.set(...arguments);
const stack = new Error().stack.split('\n');
if (stack.length >= 2 && stack[1].indexOf('<anonymous>') >= 0) {
Reflect.set(target, 'cheated', true, receiver);
}
return res;
}
const myData = new Proxy({
data1: valueA,
data2: valueB,
data3: valueC,
// ...
}, {set: setTrap});
If the user edits myData
in the browser console, their changes will remain, but myData
will also get cheated: true
after whatever change they make. Assuming setTrap
is defined in a local scope, circumventing this would require editing the actual code loaded by the browser rather than simply editing a value in the console, and minified & packed JS would make that a more frustrating task than most would bother with, I think.
This would let someone who derives enjoyment from cheating do so without additional difficulties on their part, while letting me offer them a mild rebuke with a dookie achievement for cheating.
Of course, a determined cheater could prevent the game from sending the cheating marker to the server when saving the game. Even trying to alert the server from within the setTrap
function could be easily defeated by simply cutting off the web connection while cheating, but this idea is more of a wagging finger than an attempt at preventing any cheating from occurring.
But my question is this: have I missed anything obvious with this idea? Is there a better way to write my conditional (I admit, I came up with it after just a few minutes messing around in Chrome, so it may not work the same in Firefox or something)?