Update Gui.min.js
[bcp.git] / csptest / run.js
blobb9e81a273c19529adb2478fa3c5708275cd4de5e
1 //CREDITS TO 05KONZ FOR THE RUNTIME
2 const toRun = "global/crashgame";
3 ((cheat) => {
4 // Blooket developers will be able to detect this easily, so use with caution
5 if (window.runCheat) return window.runCheat(cheat);
7 let i = document.querySelector("iframe");
8 if (!i) {
9 i = document.createElement('iframe');
10 document.body.append(i);
11 i.style.display = "none";
13 const alert = i.contentWindow.alert.bind(window);
14 const confirm = i.contentWindow.confirm.bind(window);
15 const prompt = i.contentWindow.prompt.bind(window);
16 const log = i.contentWindow.console.log;
18 // by CryptoDude3 or me!
19 if (window.fetch.call.toString() == 'function call() { [native code] }') {
20 const call = window.fetch.call;
21 window.fetch.call = function () {
22 return arguments[1].includes("s.blooket.com/rc") ? log("Bypassed anti-cheat") : call.apply(this, arguments);
26 const nil = Symbol("null");
27 const This = Symbol("this");
29 const Types = {};
30 const tokens = "NumberExpr:number_expr,FloatExpr:float_expr,StringExpr:string_expr,SymbolExpr:symbol_expr,BinaryExpr:binary_expr,PrefixExpr:prefix_expr,SuffixExpr:suffix_expr,AssignmentExpr:assignment_expr,ObjectExpr:object_expr,ArrayExpr:array_expr,CallExpr:call_expr,MemberExpr:member_expr,DynamicMemberExpr:dynamic_member_expr,TernaryExpr:ternary_expr,FuncExpr:func_expr,GroupExpr:group_expr,BlockStmt:block_stmt,ExpressionStmt:expression_stmt,VarDeclStmt:declr_stmt,FuncDeclStmt:func_decl_stmt,WhileStmt:while_stmt,ForStmt:for_stmt,IfStmt:if_stmt,ElseStmt:else_stmt,ReturnStmt:return_stmt,ContinueStmt:continue_stmt,BreakStmt:break_stmt,EndFunc:end_func,EndFor:end_for,EndWhile:end_while,EndIf:end_if,EndElse:end_else,TernaryQue:ternary_que,TernaryCol:ternary_col,EndTernary:end_ternary,ForIncr:for_incr,TypeofExpr:typeof_expr".split(",").map(x => x.trim().split(":"));
31 for (let id = 0; id < tokens.length; id++) {
32 Types[tokens[id][0]] = tokens[id][1];
33 Types[tokens[id][1]] = id;
34 Types[id] = tokens[id][0];
36 class Env {
37 constructor(parent, constants = {}) {
38 this.parent = parent;
39 this.constants = Object.create(null);
40 this.variables = Object.create(null);
41 for (const constant in constants) this.declareVar(constant, constants[constant], true);
43 declareVar(name, value, constant) {
44 if (name in this.variables) throw new Error(`Cannot declare variable ${name}. As it already is defined.`);
45 if (constant) this.constants[name] = true;
46 return this.variables[name] = value;
48 assignVar(name, value) {
49 if (this.constants[name]) throw new Error(`Cannot reassign constant variable`);
50 const env = this.resolve(name);
51 return env.variables[name] = value;
53 hasVar(name) {
54 if (name in this.variables) return true;
55 if (this.parent == undefined) return false;
56 return this.parent.hasVar(name);
58 resolve(name) {
59 if (name in this.variables) return this;
60 if (this.parent == undefined) throw new Error(`Cannot resolve '${name}' as it does not exist.`);
61 return this.parent.resolve(name);
63 lookupVar(name) {
64 const env = this.resolve(name);
65 return env.variables[name];
69 function assignment_op(assignee, operator, value) {
70 switch (operator) {
71 case "+=":
72 return assignee + value;
73 case "-=":
74 return assignee - value;
75 case "*=":
76 return assignee * value;
77 case "/=":
78 return assignee / value;
79 case "%=":
80 return assignee % value;
81 case "=":
82 return value
84 throw new Error(`Unknown assignment operator: ${operator}`);
87 class Eval {
88 ind = 0;
89 source;
90 constructor(source) {
91 this.source = source;
93 StringExpr() {
94 const size = this.code(this.ind++);
95 const str = this.source.slice(this.ind, this.ind + size);
96 this.ind += size;
97 return str;
99 NumberExpr() {
100 const size = this.code(this.ind++);
101 let num = 0;
102 for (let i = 0; i < size; i++) {
103 num += this.code(this.ind++) * Math.pow(65536, i);
105 return num;
107 FloatExpr() {
108 return parseFloat(this.StringExpr());
110 SymbolExpr(env) {
111 return env.lookupVar(this.StringExpr());
113 BlockStmt(env) {
114 const size = this.code(this.ind++);
115 for (let i = 0; i < size; i++) this.evaluate(env);
117 VarDeclStmt(env) {
118 const name = this.evaluate(env);
119 const isConstant = this.code(this.ind++) == 1;
120 const value = this.code(this.ind++) == 1 ? this.evaluate(env) : null;
121 return env.declareVar(name, value, isConstant);
123 ExpressionStmt(env) {
124 return this.evaluate(env);
126 MemberExpr(env) {
127 const assignee = this.evaluate(env);
128 const prop = this.evaluate(env);
129 let res = assignee?.[prop];
130 try { res && (res[This] = assignee); } catch { };
131 return res;
133 AssignmentExpr(env) {
135 const type = Types[this.code(this.ind++)];
136 if (type == "MemberExpr") {
137 let assignee = this.evaluate(env);
138 const property = this.evaluate(env);
139 return assignee[property] = assignment_op(assignee[property], this.evaluate(env), this.evaluate(env));
141 if (type == "SymbolExpr") {
142 const str = this.StringExpr();
143 return env.assignVar(str, assignment_op(env.lookupVar(str), this.evaluate(env), this.evaluate(env)));
145 throw new Error(`Unknown assignment type ${type}`);
147 PrefixExpr(env) {
148 const operator = this.evaluate(env);
149 switch (operator) {
150 case "-":
151 return -this.evaluate(env);
152 case "!":
153 return !this.evaluate(env);
155 throw new Error(`Unknown prefix operator: ${operator}`);
157 ObjectExpr(env) {
158 const obj = {};
159 const size = this.code(this.ind++);
160 for (let i = 0; i < size; i++) {
161 const key = this.evaluate(env);
162 obj[key] = this.evaluate(env);
164 return obj;
166 static LoopEnv(env) {
167 const loop_env = new Env(env);
168 loop_env.declareVar("break", nil);
169 loop_env.declareVar("continue", nil);
170 return loop_env;
172 ForStmt(env) {
173 const for_env = Eval.LoopEnv(env);
174 this.evaluate(for_env);
175 const vars = { ...for_env.variables };
176 const start = this.ind;
177 const end = this.findNext(Types.for_stmt, Types.end_for);
178 const incr = this.findNext(Types.for_stmt, Types.for_incr);
179 while ((this.ind = start, this.evaluate(for_env))) {
180 this.evaluate(for_env);
181 for_env.assignVar("continue", nil);
182 if (for_env.lookupVar("break") != nil) break;
183 this.ind = incr;
184 this.evaluate(for_env);
185 for (const key in for_env.variables) if (!(key in vars)) {
186 delete for_env.variables[key];
187 delete for_env.constants[key];
190 this.ind = end;
191 return;
193 WhileStmt(env) {
194 let while_env = Eval.LoopEnv(env);
195 const start = this.ind;
196 const end = this.findNext(Types.while_stmt, Types.end_while);
197 while ((this.ind = start, this.evaluate(while_env))) {
198 this.evaluate(while_env);
199 while_env.assignVar("continue", nil);
200 if (while_env.lookupVar("break") != nil) break;
201 while_env.variables = {
202 break: nil,
203 continue: nil
205 while_env.constants = Object.create(null);
207 this.ind = end;
209 BinaryExpr(env) {
210 const left = this.evaluate(env);
211 const operator = this.evaluate(env);
212 const right = this.evaluate(env);
213 switch (operator) {
214 case "+":
215 return left + right;
216 case "-":
217 return left - right;
218 case "*":
219 return left * right;
220 case "/":
221 return left / right;
222 case "%":
223 return left % right;
224 case "<":
225 return left < right;
226 case ">":
227 return left > right;
228 case "<=":
229 return left <= right;
230 case ">=":
231 return left >= right;
232 case "==":
233 return left == right;
234 case "!=":
235 return left != right;
236 case "||":
237 return left || right;
238 case "&&":
239 return left && right;
241 throw new Error(`Unknown binary operator ${operator}`);
243 SuffixExpr(env) {
244 if (this.code(this.ind++) == Types.symbol_expr) {
245 const assignee = this.StringExpr(env);
246 const operator = this.evaluate(env);
247 switch (operator) {
248 case "++":
249 return env.assignVar(assignee, env.lookupVar(assignee) + 1);
250 case "--":
251 return env.assignVar(assignee, env.lookupVar(assignee) - 1);
253 throw new Error(`Unknown suffix operator: ${operator}`);
255 const assignee = this.evaluate(env);
256 const property = this.evaluate(env);
257 const operator = this.evaluate(env);
258 switch (operator) {
259 case "++":
260 return assignee[property]++;
261 case "--":
262 return assignee[property]--;
264 throw new Error(`Unknown suffix operator: ${operator}`);
266 CallExpr(env) {
267 const callee = this.evaluate(env);
268 const args = [];
269 const size = this.code(this.ind++);
270 for (let i = 0; i < size; i++)
271 args.push(this.evaluate(env));
272 if (typeof callee == "function") {
273 let ret;
274 try { ret = callee.apply(callee[This], args); } catch (e) {
275 i.contentWindow.console.warn(e);
277 return ret;
280 FuncExpr(env) {
281 this.ind++;
282 const name = this.StringExpr(env);
283 const parameters = [];
284 const size = this.code(this.ind++);
285 for (let i = 0; i < size; i++) {
286 this.ind++;
287 parameters.push(this.StringExpr(env));
290 const here = this.ind;
291 this.ind = this.findNext(Types.func_expr, Types.end_func);
293 const runtime = this;
294 const fn = function () {
295 const fn_env = new Env(env);
296 fn_env.declareVar("arguments", arguments);
297 fn_env.declareVar("this", this);
298 for (const param in parameters) fn_env.declareVar(parameters[param], arguments[param]);
299 fn_env.declareVar("return", nil);
301 runtime.evaluateInd(fn_env, here);
303 return fn_env.lookupVar("return");
305 if (name.length) env.declareVar(name, fn);
306 return fn;
308 ArrayExpr(env) {
309 const arr = [];
310 const size = this.code(this.ind++);
311 for (let i = 0; i < size; i++) {
312 arr.push(this.evaluate(env));
314 return arr;
316 ReturnStmt(env) {
317 const ret = this.code(this.ind++) == 1 ? this.evaluate(env) : null;
318 return env.assignVar("return", ret);
320 BreakStmt(env) {
321 return env.assignVar("break", true);
323 ContinueStmt(env) {
324 return env.assignVar("continue", true);
326 IfStmt(env) {
327 const elseLoc = this.findNext(Types.if_stmt, Types.end_if);
328 const condition = this.evaluate(env);
329 if (condition) {
330 this.evaluate(new Env(env));
331 this.ind++;
332 if (this.code(this.ind++) == 1) {
333 this.ind = this.findNext(Types.else_stmt, Types.end_else);
335 } else {
336 this.ind = elseLoc;
337 if (this.code(this.ind++) == 1) {
338 this.ind++;
339 this.evaluate(new Env(env));
340 this.ind++;
344 TernaryExpr(env) {
345 const condition = this.evaluate(env);
346 this.ind++;
347 const endLoc = this.findNext(Types.ternary_expr, Types.end_ternary);
348 const elseLoc = this.findNext(Types.ternary_que, Types.ternary_col);
349 let val;
350 if (condition) {
351 val = this.evaluate(env);
352 this.ind = endLoc;
353 } else {
354 this.ind = elseLoc;
355 val = this.evaluate(env);
356 this.ind++;
358 return val;
360 GroupExpr(env) {
361 let last;
362 const size = this.code(this.ind++);
363 for (let i = 0; i < size; i++)
364 last = this.evaluate(env);
365 return last;
367 TypeofExpr(env) {
368 return typeof this.evaluate(env);
370 findNext(open, close) {
371 let num = 1, ind;
372 for (ind = this.ind + 1; ind < this.source.length && num > 0; ind++) {
373 if (this.code(ind - 1) == 2 && this.code(ind - 2) != 16) ind++;
374 if (this.code(ind) == close) num--;
375 else if (this.code(ind) == open) num++;
377 return ind;
379 code(i) {
380 return this.source.charCodeAt(i);
382 evaluate(env) {
383 const type = Types[this.code(this.ind++)];
384 if (env.hasVar("return") && env.lookupVar("return") != nil) return;
385 if (env.hasVar("break") && env.lookupVar("break") != nil) return;
386 if (env.hasVar("continue") && env.lookupVar("continue") != nil) return;
387 if (type in this) return this[type](env);
388 console.error(new Error(`No eval function for type ${type}`))
389 throw new Error(`No eval function for type ${type}`);
391 evaluateInd(env, ind) {
392 const temp = this.ind;
393 this.ind = ind;
394 const value = this.evaluate(env);
395 const end = this.ind;
396 this.ind = temp;
397 return [value, end];
401 function addProps(element, obj) {
402 for (const prop in obj) if (typeof obj[prop] == "object") addProps(element[prop], obj[prop]);
403 else element[prop] = obj[prop];
405 const constants = {
406 true: true, false: false, null: null,
407 setVal: (path, val) => constants.stateNode.props.liveGameController.setVal({ path, val }),
408 print: log, console: i.contentWindow.console,
409 window, alert, confirm, prompt, promptFloat: (x) => parseFloat(prompt(x)), promptNum: (x) => parseInt(prompt(x)),
410 isNaN, parseFloat, parseInt,
411 Date, Object, Array, Math, Promise, Number,
412 queryElement: document.querySelector.bind(document),
413 queryElementAll: document.querySelectorAll.bind(document),
414 fetch: window.fetch.bind(window),
415 elStateNode: s => Object.values(document.querySelector(s))[1].children._owner.stateNode,
416 createElement: function createElement(type, props, ...children) {
417 const element = document.createElement(type);
418 addProps(element, props);
419 for (const child of children) element.append(child);
420 return element;
423 Object.defineProperty(constants, "stateNode", {
424 get: () => Object.values((function react(r = document.querySelector("body>div")) { return Object.values(r)[1]?.children?.[0]?._owner.stateNode ? r : react(r.querySelector(":scope>div")) })())[1].children[0]._owner.stateNode,
425 enumerable: true
427 const env = new Env(undefined, constants);
428 (window.runCheat = function (path) {
429 let img = new Image;
430 img.src = "https://raw.githubusercontent.com/DannyDan0167/Blooket-Cheats-Plus/main/csptest/out/" + path + ".png?" + Date.now();
431 img.crossOrigin = "Anonymous";
432 img.onload = function () {
433 const c = document.createElement("canvas");
434 const ctx = c.getContext("2d");
435 ctx.drawImage(img, 0, 0, this.width, this.height);
436 let { data } = ctx.getImageData(0, 0, this.width, this.height), decode = "";
437 let i = 0;
438 while (i < data.length)
439 decode += String.fromCharCode(data[i % 4 == 3 ? (i++, i++) : i++] + data[i % 4 == 3 ? (i++, i++) : i++] * 256);
440 new Eval(decode).evaluate(new Env(env));
442 img.onerror = img.onabort = () => {
443 img.onerror = img.onabort = null;
444 let iframe = document.querySelector("iframe");
445 iframe.contentWindow.alert("It seems the GitHub is either blocked or down.\n\nIf it's NOT blocked, join the Discord server for updates\nhttps://discord.gg/jHjGrrdXP6");
447 })(cheat);
448 })(toRun);