Greasy Fork 支持简体中文。

RBDB

RocketBall Decoder Buffer

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/448028/1071803/RBDB.js

  1. // ==UserScript==
  2. // @name RBDB
  3. // @version 1.0
  4. // @author 0vC4
  5. // @description RocketBall Decoder Buffer
  6. // @namespace https://greasyfork.org/users/670183-exnonull
  7. // @license MIT
  8. // ==/UserScript==
  9.  
  10. const RBScheme = {
  11. pos: [
  12. [13, 'x', 'f32'],
  13. [21, 'y', 'f32'],
  14. ],
  15. object: [
  16. [10, 'pos', 'pos'],
  17. [16, 'type', 'objectType'],
  18. [24, 'playerId', 'int7'],
  19. [37, 'angle', 'f32'],
  20. [42, 'speed', 'pos'],
  21. ],
  22. entity: [
  23. [8, 'objectId', 'int7'],
  24. [18, 'data', 'object'],
  25. ],
  26. entities: [
  27. [10, 'item', 'entity'],
  28. ],
  29. user: [
  30. [8, 'playerId', 'int7'],
  31. [18, 'username', 'string'],
  32. [24, 'goals', 'int7'],
  33. [32, 'assists', 'int7'],
  34. [40, 'team', 'teamName'],
  35. [48, 'car', 'int7'],
  36. [56, 'bot', 'int7'],
  37. [64, 'exp', 'int7'],
  38. ],
  39. users: [
  40. [10, 'item', 'user'],
  41. ],
  42.  
  43. team: [
  44. [8, 'name', 'teamName'],
  45. [16, 'goals', 'int7'],
  46. ],
  47. round: [
  48. [13, 'time', 'f32'],
  49. [18, 'red', 'team'],
  50. [18, 'blue', 'team'],
  51. [18, 'spectator', 'team'],
  52. [24, 'magic', 'int7'],
  53. ],
  54.  
  55. finish: [
  56. [10, 'authToken', 'string'],
  57. [34, 'username', 'string'],
  58. [40, 'goals', 'int7'],
  59. [48, 'assists', 'int7'],
  60. [56, 'wins', 'int7'],
  61. [72, 'lost', 'int7'],
  62. [80, 'spareExp', 'int7'],
  63. [88, 'exp', 'int7'],
  64. ],
  65. };
  66.  
  67. class ReadBuffer {
  68. offset = 0
  69. buffer = []
  70. finished = false
  71. constructor(packet) {
  72. this.buffer = [...packet];
  73. this.offset = 0
  74. }
  75.  
  76. next(size=1) {
  77. let offset = this.offset;
  78. this.offset += size;
  79. if (this.offset == this.buffer.length) this.finished = true;
  80. return offset;
  81. }
  82.  
  83. get skip8() {
  84. this.u8;
  85. return this;
  86. }
  87. get skip16() {
  88. this.u16;
  89. return this;
  90. }
  91. get skip32() {
  92. this.u32;
  93. return this;
  94. }
  95. get skip64() {
  96. this.u64;
  97. return this;
  98. }
  99. get skip7() {
  100. this.int7;
  101. return this;
  102. }
  103. get skipString() {
  104. this.string;
  105. return this;
  106. }
  107.  
  108. get u8() {
  109. return new Uint8Array([this.buffer[this.next()]])[0];
  110. }
  111. get u16() {
  112. return new Uint16Array(new Uint8Array(this.buffer.slice(this.next(2), this.offset)).buffer)[0];
  113. }
  114. get u32() {
  115. return new Uint32Array(new Uint8Array(this.buffer.slice(this.next(4), this.offset)).buffer)[0];
  116. }
  117. get u64() {
  118. return new BigUint64Array(new Uint8Array(this.buffer.slice(this.next(8), this.offset)).buffer)[0];
  119. }
  120.  
  121. get s8() {
  122. return new Int8Array([this.buffer[this.next()]])[0];
  123. }
  124. get s16() {
  125. return new Int16Array(new Uint8Array(this.buffer.slice(this.next(2), this.offset)).buffer)[0];
  126. }
  127. get s32() {
  128. return new Int32Array(new Uint8Array(this.buffer.slice(this.next(4), this.offset)).buffer)[0];
  129. }
  130. get s64() {
  131. return new BigInt64Array(new Uint8Array(this.buffer.slice(this.next(8), this.offset)).buffer)[0];
  132. }
  133.  
  134. get f32() {
  135. return new Float32Array(new Uint8Array(this.buffer.slice(this.next(4), this.offset)).buffer)[0];
  136. }
  137. get f64() {
  138. return new Float64Array(new Uint8Array(this.buffer.slice(this.next(8), this.offset)).buffer)[0];
  139. }
  140.  
  141. get int7() {
  142. let offset = 0;
  143. let num = 0;
  144. while (offset != 0b100011) {
  145. let byte = this.buffer[this.offset + offset/7];
  146. num |= (byte&0x7f)<<offset;
  147. offset += 7;
  148. if ((byte&0x80) == 0) {
  149. this.next(offset/7);
  150. return num;
  151. }
  152. }
  153. this.next(offset/7);
  154. return num;
  155. }
  156. get array() {
  157. return new Uint8Array(this.buffer.slice(this.next(this.buffer.length-this.offset), this.offset));
  158. }
  159. get array7() {
  160. const offset = this.next(this.int7);
  161. return new Uint8Array(this.buffer.slice(offset, this.offset));
  162. }
  163. get string() {
  164. return new TextDecoder().decode(this.array7);
  165. }
  166.  
  167.  
  168.  
  169. // custom types
  170.  
  171. read(scheme) {
  172. const buffer = new ReadBuffer(this.array7);
  173. if (buffer.buffer.length == 0) return {};
  174.  
  175. const data = {};
  176. const skip = [];
  177. while (!buffer.finished) {
  178. const slotId = buffer.u8;
  179. try {
  180. const [id, key, type] = RBScheme[scheme].find(([id], i) => {
  181. if (id == slotId && !skip.includes(i)) {
  182. skip.push(i);
  183. return true;
  184. }
  185. });
  186. data[key] = buffer[type];
  187. } catch (e) {
  188. console.log(scheme, buffer.buffer+'', buffer.offset, slotId, RBScheme[scheme]);
  189. throw e;
  190. }
  191. }
  192.  
  193. return data;
  194. }
  195. readArray(scheme) {
  196. const buffer = new ReadBuffer(this.array7);
  197. if (buffer.buffer.length == 0) return [];
  198.  
  199. const data = [];
  200. while (!buffer.finished)
  201. data.push(buffer.skip8.read(RBScheme[scheme][0][2]));
  202.  
  203. return data;
  204. }
  205.  
  206. get pos() {
  207. const data = this.read('pos');
  208. if (!data.x) data.x = 0;
  209. if (!data.y) data.y = 0;
  210. return data;
  211. }
  212. get object() {
  213. return this.read('object');
  214. }
  215. get entity() {
  216. return this.read('entity');
  217. }
  218. get entities() {
  219. return this.readArray('entities');
  220. }
  221.  
  222. get user() {
  223. return this.read('user');
  224. }
  225. get users() {
  226. return this.readArray('users');
  227. }
  228.  
  229.  
  230. get objectType() {
  231. return ['player', 'ball', 'magic', 'magic2', 'boost'][this.int7];
  232. }
  233. get teamName() {
  234. return ['red', 'blue', 'spectator'][this.int7];
  235. }
  236. get team() {
  237. const data = this.read('team');
  238. if (!data.name) data.name = 'red';
  239. if (!data.goals) data.goals = 0;
  240. return data;
  241. }
  242. get round() {
  243. return this.read('round');
  244. }
  245.  
  246. get finish() {
  247. return this.read('finish');
  248. }
  249. }
  250.  
  251. class WriteBuffer {
  252. offset = 0
  253. buffer = []
  254. constructor(buffer = []) {
  255. this.buffer = [...buffer];
  256. this.offset = buffer.length;
  257. }
  258.  
  259. u8(...nums) {
  260. for (let byte of new Uint8Array([...nums]))
  261. this.buffer[this.offset++] = byte;
  262. return this;
  263. }
  264. u16(...nums) {
  265. for (let byte of new Uint8Array(new Uint16Array([...nums]).buffer))
  266. this.buffer[this.offset++] = byte;
  267. return this;
  268. }
  269. u32(...nums) {
  270. for (let byte of new Uint8Array(new Uint32Array([...nums]).buffer))
  271. this.buffer[this.offset++] = byte;
  272. return this;
  273. }
  274. u64(...nums) {
  275. for (let byte of new Uint8Array(new BigUint64Array([...nums]).buffer))
  276. this.buffer[this.offset++] = byte;
  277. return this;
  278. }
  279.  
  280. s8(...nums) {
  281. for (let byte of new Uint8Array([...nums]))
  282. this.buffer[this.offset++] = byte;
  283. return this;
  284. }
  285. s16(...nums) {
  286. for (let byte of new Uint8Array(new Int16Array([...nums]).buffer))
  287. this.buffer[this.offset++] = byte;
  288. return this;
  289. }
  290. s32(...nums) {
  291. for (let byte of new Uint8Array(new Int32Array([...nums]).buffer))
  292. this.buffer[this.offset++] = byte;
  293. return this;
  294. }
  295. s64(...nums) {
  296. for (let byte of new Uint8Array(new BigInt64Array([...nums]).buffer))
  297. this.buffer[this.offset++] = byte;
  298. return this;
  299. }
  300.  
  301. f32(...nums) {
  302. for (let byte of new Uint8Array(new Float32Array([...nums]).buffer))
  303. this.buffer[this.offset++] = byte;
  304. return this;
  305. }
  306. f64(...nums) {
  307. for (let byte of new Uint8Array(new Float64Array([...nums]).buffer))
  308. this.buffer[this.offset++] = byte;
  309. return this;
  310. }
  311.  
  312. int7(...nums) {
  313. const bytes = [];
  314.  
  315. for (let num of nums) {
  316. while(num >= 0x80) {
  317. bytes.push((num|0x80)%0x100);
  318. num >>= 7;
  319. }
  320. bytes.push(num%0x100);
  321. }
  322.  
  323. for (let byte of bytes)
  324. this.buffer[this.offset++] = byte;
  325.  
  326. return this;
  327. }
  328. array(...arrays) {
  329. for (let array of arrays)
  330. for (let byte of array)
  331. this.buffer[this.offset++] = new Uint8Array([byte])[0];
  332. return this;
  333. }
  334. array7(...arrays) {
  335. for (let array of arrays) {
  336. this.int7(array.length);
  337. for (let byte of array)
  338. this.buffer[this.offset++] = new Uint8Array([byte])[0];
  339. }
  340. return this;
  341. }
  342. string(...strs) {
  343. for (let str of strs) this.array7(new TextEncoder().encode(str));
  344. return this;
  345. }
  346.  
  347.  
  348.  
  349. // custom types
  350.  
  351. write(scheme, ...items) {
  352.  
  353. for (let item of items) {
  354. const buffer = new WriteBuffer();
  355.  
  356. for (let k in item) {
  357. try {
  358. const [id, key, type] = RBScheme[scheme].find(([id, key]) => key == k);
  359. buffer.u8(id);
  360. buffer[type](item[k]);
  361. } catch (e) {
  362. console.log(scheme, items, item, k, RBScheme[scheme], buffer.buffer+'');
  363. throw e;
  364. }
  365. }
  366.  
  367. this.int7(buffer.buffer.length).array(buffer.buffer);
  368. }
  369.  
  370. return this;
  371. }
  372. writeArray(scheme, ...itemLists) {
  373.  
  374. for (let itemList of itemLists) {
  375. const buffer = new WriteBuffer();
  376. for (let items of itemList)
  377. buffer.int7(10).write(RBScheme[scheme][0][2], items);
  378. this.int7(10, buffer.buffer.length).array(buffer.buffer);
  379. }
  380.  
  381. return this;
  382. }
  383.  
  384. pos(...items) {
  385. return this.write('pos', ...items);
  386. }
  387. object(...items) {
  388. return this.write('object', ...items);
  389. }
  390. entity(...items) {
  391. return this.write('entity', ...items);
  392. }
  393. entities(...itemLists) {
  394. return this.writeArray('entities', ...itemLists);
  395. }
  396.  
  397. user(...items) {
  398. return this.write('user', ...items);
  399. }
  400. users(...itemLists) {
  401. return this.writeArray('users', ...itemLists);
  402. }
  403.  
  404. objectType(name) {
  405. this.buffer[this.offset++] = ['player', 'ball', 'magic', 'magic2', 'boost'].indexOf(name);
  406. return this;
  407. }
  408. teamName(name) {
  409. this.buffer[this.offset++] = ['red', 'blue', 'spectator'].indexOf(name);
  410. return this;
  411. }
  412. team(...items) {
  413. return this.write('team', ...items);
  414. }
  415. round(...items) {
  416. return this.write('round', ...items);
  417. }
  418.  
  419. finish(...items) {
  420. return this.write('finish', ...items);
  421. }
  422. }
  423. // 0vC4#7152