The Gaming Guru Community Script

A Community Script for Krunker

  1. // ==UserScript==
  2. // @name The Gaming Guru Community Script
  3. // @namespace https://skidlamer.github.io/
  4. // @version 0.1
  5. // @description A Community Script for Krunker
  6. // @author The Gaming Guru Community
  7. // @iconURL https://cdn.discordapp.com/icons/692606346645733396/2c8c01e76973634afcaec17d22ba5e80.webp?size=128
  8. // @match *://krunker.io/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function(script, state) {
  13. 'use strict';
  14.  
  15. const states = {
  16. updating:"GAME UPDATING\n",
  17. disconect:"DISCONNECTED\n",
  18. connecting:"CONNECTING...\n",
  19. ready:"CLICK TO PLAY\n",
  20. }
  21.  
  22. var me;
  23. var GUI;
  24. var showMenu = true;
  25. var menuDirty = true;
  26. var features = [];
  27. var updatedFeat = new Map();
  28. var players = new Map();
  29. var vars = new Map();
  30. var downKeys = new Set();
  31.  
  32. let setVars = function() {
  33. vars.set("isYou", {regex:/this\['\w+']=k,this\['(\w+)']=w,this\['\w+']=!0x0/,pos:1})
  34. vars.set("inView", {regex:/if\(!\w+\['(\w+)']\)continue/,pos:1})
  35. for (const [name, object] of vars.entries()) {
  36. let result = object.regex.exec(script);
  37. if ( result ) {
  38. object.val = result[object.pos];
  39. console.log("found: ", name, " at ", result.index, " value: ", object.val);
  40. } else {
  41. object.val = null;
  42. alert("Failed to find ", name);
  43. }
  44. }
  45. }
  46.  
  47. let decodeText = function(str, array, xor) {
  48. for (var i = 0, il = array.byteLength; i < il; i ++) {
  49. str += String.fromCharCode(array.getUint8(i) ^ xor);
  50. }
  51. try {
  52. return decodeURIComponent( escape( str ) );
  53. } catch ( e ) {
  54. return str;
  55. }
  56. }
  57.  
  58. let getVersion = function() {
  59. const elems = document.getElementsByClassName('terms');
  60. const version = elems[elems.length - 1].innerText;
  61. return version;
  62. }
  63.  
  64. let saveAs = function(name, data) {
  65. let blob = new Blob([data], {type: 'text/plain'});
  66. let el = window.document.createElement("a");
  67. el.href = window.URL.createObjectURL(blob);
  68. el.download = name;
  69. document.body.appendChild(el);
  70. el.click();
  71. document.body.removeChild(el);
  72. }
  73.  
  74. let isDefined = function(object) {
  75. return void 0 !== object;
  76. }
  77.  
  78. let isType = function(item, type) {
  79. return typeof item === type;
  80. }
  81.  
  82. let addObserver = function(elm, check, callback, onshow = true) {
  83. return new MutationObserver((mutationsList, observer) => {
  84. if (check == 'src' || onshow && mutationsList[0].target.style.display == 'block' || !onshow) {
  85. callback(mutationsList[0].target);
  86. }
  87. }).observe(elm, check == 'childList' ? {
  88. childList: true
  89. } : {
  90. attributes: true,
  91. attributeFilter: [check]
  92. });
  93. }
  94.  
  95. let addListener = function(elm, type, callback = null) {
  96. if (!isDefined(elm)) { alert("Failed creating " + type + "listener"); return }
  97. elm.addEventListener(type, event => callback(event));
  98. }
  99.  
  100. //Storage
  101. let canStore = (typeof(Storage) !== "undefined");
  102. let saveVal = function(name, val) {
  103. if (canStore) localStorage.setItem(name, val);
  104. }
  105. let deleteVal = function(name) {
  106. if (canStore) localStorage.removeItem(name);
  107. }
  108. let getSavedVal = function(name) {
  109. if (canStore) return localStorage.getItem(name);
  110. return null;
  111. }
  112.  
  113. //Features
  114. let newFeature = (name, keyBind, array, myFunction = null) => {
  115. const cStruct = (...keys) => ((...v) => keys.reduce((o, k, i) => {
  116. o[k] = v[i];
  117. return o
  118. }, {}));
  119. let item = [];
  120. const myStruct = cStruct('name', 'key', 'value', 'valueStr', 'container', 'myFunction')
  121. const value = parseInt(getSavedVal("utilities_" + name) || 0);
  122. const feature = myStruct(name, keyBind, value, array.length ? array[value] : '', array, myFunction);
  123. if (array.length || myFunction) features.push(feature);
  124. item.push(feature);
  125. return item;
  126. }
  127.  
  128. let getFeature = (name) => {
  129. for (const feature of features) {
  130. if (feature.name.toLowerCase() === name.toLowerCase()) {
  131. return feature;
  132. }
  133. }
  134. return null;
  135. }
  136.  
  137. let onUpdated = (feature) => {
  138. window.SOUND.play('tick_0', 0.1);
  139. if (feature.container.length) {
  140. feature.value += 1;
  141. if (feature.value > feature.container.length - 1) {
  142. feature.value = 0;
  143. }
  144. feature.valueStr = feature.container[feature.value];
  145. saveVal("utilities_" + feature.name, feature.value);
  146. }
  147. if (feature.container.length == 2 && feature.container[0] == 'Off' && feature.container[1] == 'On') {
  148. console.debug(feature.name, " is now ", feature.valueStr);
  149. }
  150.  
  151. if (!updatedFeat.has(feature.name)) {
  152. console.debug(feature.name, " - Update Pending ")
  153. updatedFeat.set(feature.name, feature);
  154. }
  155.  
  156. menuDirty = true;
  157. }
  158.  
  159. // keyDown
  160. let keyDown = (key) => downKeys.has(key)
  161.  
  162. // onTick Function
  163. let onTick = function(game, delta) {
  164. if (!isDefined(me) || !me || !me.active) return;
  165.  
  166. const featureBhop = getFeature('Bhop');
  167. if (isDefined(featureBhop) && featureBhop.value) {
  168. if (keyDown("Space") || featureBhop.value !== 2 && featureBhop.value !== 4) {
  169. game.controls.keys[game.controls.jumpKey] ^= 1;
  170. game.controls.keys[game.controls.crouchKey] = (me.yVel < -0.04 && me.canSlide) && featureBhop.value !== 1 && featureBhop.value !== 2 ? 1 : 0;
  171. }
  172.  
  173. }
  174. }
  175.  
  176. // onInitialize
  177. let initialize = function() {
  178.  
  179. //Add Features
  180. newFeature('ESP', "5", ['Off', 'On']);
  181. newFeature('Bhop', "6", ['Off', 'Auto Jump', 'Key Jump', 'Auto Slide', 'Key Slide']);
  182.  
  183. // GameState
  184. addObserver(window.instructionHolder, 'style', (target) => {
  185. state = target.innerText;
  186. if (state.includes(states.updating)) {
  187. alert(state);
  188. location.reload();
  189. }
  190. else console.log(state)
  191. });
  192.  
  193. // GUI Init
  194. GUI = document.getElementById("myGUI");
  195. if (GUI == null) {
  196. GUI = document.createElement('div');
  197. GUI.id = "myGUI";
  198. GUI.style = "float:left;width:100%;background-color: rgba(0,0,0,0.25);border-radius:5%;text-align:right;line-height:0.8;margin-top:5%;";
  199. }
  200.  
  201.  
  202. // Input/output
  203. let mouseDownL = false, mouseDownM = false, mouseDownR = false;
  204.  
  205. addListener(document, "keyup", event => {
  206. if (downKeys.has(event.code)) downKeys.delete(event.code)
  207. })
  208.  
  209. addListener(document, "keydown", event => {
  210. if ('INPUT' == document.activeElement.tagName || !window.endUI && window.endUI.style.display) return;
  211. switch (event.code) {
  212. case 'F1':
  213. showMenu ^= 1;
  214. window.SOUND.play('tick_0', 0.1);
  215. menuDirty = showMenu;
  216. break;
  217. case 'F2':
  218. saveAs("game_" + getVersion() + ".js", script);
  219. break;
  220. default:
  221. if (!downKeys.has(event.code)) downKeys.add(event.code);
  222. for (const feature of features) {
  223. if (feature && "Digit" + feature.key == event.code) {
  224. if (feature.container.length) onUpdated(feature);
  225. else if (typeof feature.myFunction === "function") feature.myFunction();
  226. }
  227. }
  228. break;
  229. }
  230.  
  231. })
  232.  
  233. addListener(document, "mousedown", event =>{
  234. const Left=0, Middle=1, Right=2;
  235. switch(event.button) {
  236. case Left: mouseDownL = true; break;
  237. case Middle: mouseDownM = true; break;
  238. case Right: mouseDownR = true; break;
  239. default: break;
  240. }
  241. });
  242.  
  243. addListener(document, "mouseup", event =>{
  244. const Left=0, Middle=1, Right=2;
  245. switch(event.button) {
  246. case Left: mouseDownL = false; break;
  247. case Middle: mouseDownM = false; break;
  248. case Right: mouseDownR = false; break;
  249. default: break;
  250. }
  251. });
  252.  
  253. //Hook Array
  254. Array.prototype.push = new Proxy(Array.prototype.push, {
  255. apply: function(target, that, [item, ...sub]) {
  256. if (!state) return target.apply(that, [item, ...sub]);
  257. let size = target.apply(that, [item, ...sub]);
  258. if (item instanceof Object && item.isPlayer) {
  259. players.set(size - 1, item);
  260. }
  261. return size;
  262. }
  263. })
  264.  
  265. //Hook Frame
  266. window.requestAnimationFrame = new Proxy(window.requestAnimationFrame, {
  267. apply: function(target, that, args) {
  268. for (let [key, player] of players) {
  269. if (player && player.active) {
  270. if (player[vars.get("isYou").val]) {
  271. me = player;
  272. if (!player.update.proxy) {
  273. player.update = new Proxy(player.update, {
  274. apply: function(target, that, [game, delta]) {
  275. that.update.proxy = true;
  276. onTick(game, delta);
  277. return target.apply(that, [game, delta]);
  278. }
  279. })
  280. }
  281. else {
  282. const topLeft = document.getElementById("topLeftHolder");
  283. if (topLeft && GUI) {
  284. if (!topLeft.contains(GUI)) {
  285. topLeft.appendChild(GUI);
  286. } else if (showMenu) {
  287. if (menuDirty) {
  288. menuDirty = false;
  289. GUI.innerHTML = "<br><h4 style='text-align:center;color:#1E90FF;'>Community Skid</h4><hr>";
  290. for (const feature of features) {
  291. GUI.innerHTML += `<h5><span style='float:left;margin-left:10%;color:rgba(255,193,72,255)'>${feature.key}</span> <span style='float:left;margin-left:10%;color:rgba(255,255,255,255)'>${feature.name}</span> <span style=float:all;margin-right:10%;margin-left:10%;color:${feature.valueStr == "On" ? "#B2F252" : feature.valueStr == "Off" ? "#FF4444" : "#999EA5"};'>${feature.valueStr}</span></h5>`;
  292. }
  293. GUI.innerHTML += "<br>";
  294. }
  295. } else if (GUI.innerHTML) GUI.innerHTML = null;
  296. }
  297. for (let[name, feature] of updatedFeat) {
  298. updatedFeat.delete(name);
  299. }
  300. }
  301. }
  302. else {
  303. const featureESP = getFeature('ESP');
  304. if (isDefined(featureESP) && featureESP) {
  305. player[vars.get("inView").val] = featureESP.value;
  306. }
  307. }
  308. }
  309. }
  310. return target.apply(that, args);
  311. }
  312. })
  313. }
  314.  
  315. // Hook Promise Respose to buff
  316. Response.prototype.arrayBuffer = new Proxy(Response.prototype.arrayBuffer, {
  317. apply: function(target, that, args) {
  318. const returnValue = target.apply(that, args);
  319. returnValue.then(buffer => {
  320. script = decodeText("", new DataView(buffer), 0x69);
  321. setVars();
  322. initialize();
  323. });
  324. return returnValue;
  325. }
  326. })
  327.  
  328. })("", null);