BonkLIB

BonkAPI + BonkHUD

  1. // ==UserScript==
  2. // @name BonkLIB
  3. // @version 1.1.3
  4. // @author FeiFei + Clarifi + BoZhi
  5. // @namespace https://github.com/FeiFei-GH/BonkLIB
  6. // @description BonkAPI + BonkHUD
  7. // @license MIT
  8. // @match https://bonk.io/gameframe-release.html
  9. // @run-at document-start
  10. // @grant none
  11. // ==/UserScript==
  12. /*
  13. Usable with:
  14. https://greasyfork.org/en/scripts/433861-code-injector-bonk-io
  15. */
  16.  
  17. // ! Compitable with Bonk Version 49
  18. window.bonkLIB = {};
  19. bonkLIB.version = "1.1.3";
  20.  
  21. window.bonkAPI = {};
  22.  
  23. /**
  24. * Contains data of a single player
  25. *
  26. * @typedef {object} Player
  27. * @property {string} peerID - Peer ID of player
  28. * @property {string} userName - Username of player
  29. * @property {number} level - Level of player
  30. * @property {boolean} guest - Is guest
  31. * @property {number} team - Integer of what team from 0 to 5
  32. * @property {boolean} ready - Is ready
  33. * @property {boolean} tabbed - Is tabbed
  34. * @property {JSON} avatar - Skin data
  35. */
  36.  
  37. /**
  38. * Contains data of a single friend
  39. *
  40. * @typedef {object} Friend
  41. * @property {string} userName - Username of friend
  42. * @property {string} roomID - Room ID of the lobby that the friend is in
  43. */
  44.  
  45. // *Global Variables
  46. bonkAPI.currentPlayers = []; //List of user IDs of players in the lobby
  47. bonkAPI.playerList = []; // History list of players in the room
  48. bonkAPI.myID = -1; // Client's ID
  49. bonkAPI.myToken = -1; // Client's token
  50. bonkAPI.hostID = -1; // Host's ID
  51.  
  52. bonkAPI.isLoggingIn = false;
  53.  
  54. // MGF vars
  55. bonkAPI.bonkWSS = 0;
  56. bonkAPI.originalSend = window.WebSocket.prototype.send;
  57. bonkAPI.originalRequestAnimationFrame = window.requestAnimationFrame;
  58. bonkAPI.originalDrawShape = 0;
  59. bonkAPI.pixiCtx = 0;
  60. bonkAPI.pixiStage = 0;
  61. bonkAPI.parentDraw = 0;
  62. bonkAPI.originalXMLOpen = window.XMLHttpRequest.prototype.open;
  63. bonkAPI.originalXMLSend = window.XMLHttpRequest.prototype.send;
  64. window.bonkHUD = {};
  65.  
  66. bonkHUD.windowHold = [];
  67. bonkHUD.settingsHold = [];
  68.  
  69. //! not used but will be
  70. // *Style Store
  71. bonkHUD.styleHold = {};
  72.  
  73. //! styles added do not include color, to be added/changed by user
  74. //! some innercss using these classes still has not been deleted(will do it)
  75. bonkHUD.bonkHUDCSS = document.createElement("style");
  76.  
  77. bonkHUD.bonkHUDCSS.innerHTML = `
  78. .bonkhud-settings-row {
  79. border-bottom: 1px solid;
  80. padding: 10px;
  81. }
  82. .bonkhud-settings-label {
  83. font-size: 0.9rem;
  84. font-weight: bold;
  85. }
  86. .bonkhud-window-container {
  87. position: fixed;
  88. min-width: 5rem;
  89. font-family: "futurept_b1";
  90. border-radius: 8px;
  91. z-index: 9990;
  92. }
  93. .bonkhud-header-button {
  94. position: absolute;
  95. top: 3px;
  96. width: 25px;
  97. height: 25px;
  98. border-radius: 3px;
  99. }
  100. .bonkhud-scrollbar-kit::-webkit-scrollbar {
  101. display: none;
  102. }
  103. .bonkhud-scrollbar-other {
  104. scrollbar-width: none;
  105. }
  106. .bonkhud-resizer {
  107. width: 10px;
  108. height: 10px;
  109. background: transparent;
  110. position: absolute;
  111. }
  112. .bonkhud-resizer.north-west {
  113. top: -5px;
  114. left: -5px;
  115. cursor: nwse-resize;
  116. }
  117. .bonkhud-resizer.north-east {
  118. top: -5px;
  119. right: -5px;
  120. cursor: nesw-resize;
  121. }
  122. .bonkhud-resizer.south-east {
  123. bottom: -5px;
  124. right: -5px;
  125. cursor: nwse-resize;
  126. }
  127. .bonkhud-resizer.south-west {
  128. bottom: -5px;
  129. left: -5px;
  130. cursor: nesw-resize;
  131. }
  132. `;
  133.  
  134. document.getElementsByTagName("head")[0].appendChild(bonkHUD.bonkHUDCSS);
  135.  
  136.  
  137. /**
  138. * Sends message in game's public chat.
  139. * @function chat
  140. * @param {string} message - The message.
  141. */
  142. bonkAPI.chat = function (message) {
  143. bonkAPI.sendPacket('42[10,{"message":' + JSON.stringify(message) + "}]");
  144. };
  145.  
  146. /**
  147. * Defaults to banning the player with the given ID.
  148. * @function banPlayerByID
  149. * @param {number} id - ID of the player to be kicked/banned
  150. * @param {boolean} kick - Whether player should be kicked or banned, defaults to false (banned)
  151. */
  152. bonkAPI.banPlayerByID = function (id, kick = false) {
  153. bonkAPI.sendPacket('42[9,{"banshortid":' + id + ',"kickonly":' + kick + "}]");
  154. };
  155.  
  156. /**
  157. * Gets all online friends.
  158. * @function getOnlineFriendList
  159. * @param {function} callback - Callback function
  160. * @returns {Array.<Friend>} Array of {@linkcode Friend} objects
  161. */
  162. bonkAPI.getOnlineFriendList = function (callback) {
  163. let req = new window.XMLHttpRequest();
  164. req.onreadystatechange = () => {
  165. if (req.readyState == 4) {
  166. let friends = [];
  167. let data = JSON.parse(req.response)["friends"];
  168. for (let i = 0; i < data.length; i++) {
  169. let rid = data[i]["roomid"];
  170. if (rid != null) {
  171. friends.push({ userName: data[i]["name"], roomID: rid });
  172. }
  173. }
  174. callback(friends);
  175. }
  176. };
  177. try {
  178. req.open("POST", "https://bonk2.io/scripts/friends.php");
  179. req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
  180. //! maybe make a function to automatically build this stuff, but not necessary and probably worse
  181. req.send("token=" + bonkAPI.myToken + "&task=getfriends");
  182. } catch (e) {
  183. console.log(e);
  184. callback([]);
  185. }
  186. };
  187.  
  188. /**
  189. * Adds a listener to {@linkcode EventHandler} to call the method.
  190. * @function addEventListener
  191. * @param {string} event - The event that is listened for
  192. * @param {function(object)} method - Method that is called when event is fired
  193. * @param {*} [scope] - Defaults to window
  194. * @param {*} [context] - Defaults to nothing
  195. */
  196. bonkAPI.addEventListener = function (event, method, scope, context) {
  197. bonkAPI.events.addEventListener(event, method, scope, context);
  198. };
  199.  
  200. /**
  201. * Returns the entire list of {@linkcode Player} objects that have joined
  202. * since you have.
  203. * @function getPlayerList
  204. * @returns {Array.<Player>} Array of {@linkcode Player} objects
  205. */
  206. bonkAPI.getPlayerList = function () {
  207. // *Returns a copy of bonkAPI.playerList
  208. return bonkAPI.playerList;
  209. };
  210.  
  211. /**
  212. * Returns list of {@linkcode Player} objects in the lobby at time this
  213. * function was called.
  214. * @function getPlayerLobbyList
  215. * @returns {Array.<Player>} Array of {@linkcode Player} objects
  216. */
  217. bonkAPI.getPlayerLobbyList = function () {
  218. //! i want to make more playerlobby functions but dk what to name
  219. //! or whether to join it with the other functions but add an arguement
  220. //! to specify which to use
  221. let list = [];
  222. bonkAPI.currentPlayers.forEach((index) => {
  223. list.push(bonkAPI.playerList[index]);
  224. });
  225. return list;
  226. }
  227.  
  228. /**
  229. * Returns list of user IDs in the lobby at time this
  230. * function was called.
  231. * @function getPlayersInLobbyID
  232. * @returns {Array.<Player>} Array of {@linkcode Player} objects
  233. */
  234. bonkAPI.getPlayersInLobbyID = function () {
  235. return bonkAPI.currentPlayers;
  236. }
  237.  
  238. /**
  239. * Returns the amount of players that have been in the lobby.
  240. * @function getPlayerListLength
  241. * @returns {number} Length of the player list
  242. */
  243. bonkAPI.getPlayerListLength = function () {
  244. return bonkAPI.playerList.length;
  245. };
  246.  
  247. /**
  248. * Returns the {@linkcode Player} object of the ID or name given.
  249. * @function getPlayer
  250. * @param {*} ref - Either ID of the player or name of the player
  251. * @returns {Player} Player object
  252. */
  253. bonkAPI.getPlayer = function (ref) {
  254. if (typeof ref === "number") {
  255. if (ref < 0 || ref >= bonkAPI.playerList.length) {
  256. return null;
  257. }
  258. return bonkAPI.playerList[ref];
  259. } else if (typeof ref === "string") {
  260. for (let i = 0; i < bonkAPI.playerList.length; i++) {
  261. if (bonkAPI.playerList[i] != null && ref == bonkAPI.playerList[i].userName) {
  262. return bonkAPI.playerList[i];
  263. }
  264. }
  265. return null;
  266. } else {
  267. return null;
  268. }
  269. };
  270.  
  271. /**
  272. * Returns the {@linkcode Player} object of the ID given.
  273. * @function getPlayerByID
  274. * @param {number} id - ID of the player that is being looked for
  275. * @returns {Player} Player object
  276. */
  277. bonkAPI.getPlayerByID = function (id) {
  278. if (id < 0 || id >= bonkAPI.playerList.length) {
  279. return null;
  280. }
  281. return bonkAPI.playerList[id];
  282. };
  283.  
  284. /**
  285. * Returns the {@linkcode Player} object of the name given.
  286. * @function getPlayerByName
  287. * @param {string} name - Name of the player that is being looked for
  288. * @returns {Player} Player object
  289. */
  290. bonkAPI.getPlayerByName = function (name) {
  291. for (let i = 0; i < bonkAPI.playerList.length; i++) {
  292. if (bonkAPI.playerList[i] != null && name == bonkAPI.playerList[i].userName) {
  293. return bonkAPI.playerList[i];
  294. }
  295. }
  296. return null;
  297. };
  298.  
  299. /**
  300. * Returns the name of the player of the ID given.
  301. * @function getPlayerNameByID
  302. * @param id - ID of the player to get the name of
  303. * @returns {string} Name of player
  304. */
  305. bonkAPI.getPlayerNameByID = function (id) {
  306. if (id < 0 || id >= bonkAPI.playerList.length) {
  307. return "";
  308. }
  309. return bonkAPI.playerList[id].userName;
  310. };
  311.  
  312. /**
  313. * Returns the user ID of the player with the given name.
  314. * @function getPlayerIDByName
  315. * @param {string} name - Name of player to get ID of
  316. * @returns {number} ID of player
  317. */
  318. bonkAPI.getPlayerIDByName = function (name) {
  319. for (let i = 0; i < bonkAPI.playerList.length; i++) {
  320. if (bonkAPI.playerList[i] != null && name == bonkAPI.playerList[i].userName) {
  321. return i;
  322. }
  323. }
  324. return -1;
  325. };
  326.  
  327. /**
  328. * Returns a list of {@linkcode Player} objects that are in the specified
  329. * team.
  330. * @function getPlayersByTeam
  331. * @param {number} team - Team of the player, from 0 to 5
  332. * @returns {Array.<Player>} List of {@linkcode Player} objects
  333. */
  334. bonkAPI.getPlayersByTeam = function (team) {
  335. var teamList = [];
  336. for (let i = 0; i < bonkAPI.playerList.length; i++) {
  337. if (team == bonkAPI.playerList[i].team) {
  338. teamList.push({ userID: i, userData: bonkAPI.playerList[i] });
  339. }
  340. }
  341. return teamList;
  342. };
  343.  
  344. /**
  345. * Returns your own player ID.
  346. * @function getMyID
  347. * @returns {number} ID of the user
  348. */
  349. bonkAPI.getMyID = function () {
  350. return bonkAPI.myID;
  351. };
  352.  
  353. /**
  354. * Returns the player ID of the host.
  355. * @function getHostID
  356. * @returns {number} ID of the host
  357. */
  358. bonkAPI.getHostID = function () {
  359. return bonkAPI.hostID;
  360. };
  361.  
  362. /**
  363. * Returns whether the capzone can be capped
  364. * without ending game or desyncing
  365. * @function safeToCap
  366. * @returns {boolean} Whether it is safe to cap
  367. */
  368. bonkAPI.safeToCap = function () {
  369. if(bonkAPI.currentPlayers.length == 1) {
  370. return true;
  371. }
  372. let t = bonkAPI.playerList[bonkAPI.currentPlayers[0]].team;
  373. for(let i = 1; i < bonkAPI.currentPlayers.length; i++) {
  374. if(t != bonkAPI.playerList[bonkAPI.currentPlayers[i]].team && 0 != bonkAPI.playerList[bonkAPI.currentPlayers[i]].team) {
  375. return false;
  376. }
  377. }
  378. return true;
  379. }
  380.  
  381. /**
  382. * Returns whether the game is running after
  383. * you have first joined a lobby.
  384. * @function isInGame
  385. * @returns {boolean} Whether in game or not
  386. */
  387. bonkAPI.isInGame = function () {
  388. let renderer = document.getElementById("gamerenderer");
  389. return renderer.style.visibility == "inherit";
  390. }
  391. window.WebSocket.prototype.send = function (args) {
  392. if (this.url.includes("socket.io/?EIO=3&transport=websocket&sid=")) {
  393. if (!this.injectedAPI) {
  394. // initialize overriding receive listener (only run once)
  395. bonkAPI.bonkWSS = this;
  396. this.injectedAPI = true;
  397. var originalReceive = this.onmessage;
  398. // This function intercepts incoming packets
  399. this.onmessage = function (args) {
  400. // &Receiving incoming packets
  401. if(args.data.substring(0, 3) == "42[") {
  402. newArgs = JSON.parse(args.data.substring(2));
  403. // !All function names follow verb_noun[verb] format
  404. switch (parseInt(newArgs[0])) {
  405. case 1: //*Update other players' pings
  406. newArgs = bonkAPI.receive_PingUpdate(newArgs);
  407. break;
  408. case 2: // *UNKNOWN, received after sending create room packet
  409. newArgs = bonkAPI.receive_Unknow2(newArgs);
  410. break;
  411. case 3: // *Room Join
  412. newArgs = bonkAPI.receive_RoomJoin(newArgs);
  413. break;
  414. case 4: // *Player Join
  415. newArgs = bonkAPI.receive_PlayerJoin(newArgs);
  416. break;
  417. case 5: // *Player Leave
  418. newArgs = bonkAPI.receive_PlayerLeave(newArgs);
  419. break;
  420. case 6: // *Host Leave
  421. newArgs = bonkAPI.receive_HostLeave(newArgs);
  422. break;
  423. case 7: // *Receive Inputs
  424. newArgs = bonkAPI.receive_Inputs(newArgs);
  425. break;
  426. case 8: // *Ready Change
  427. newArgs = bonkAPI.receive_ReadyChange(newArgs);
  428. break;
  429. case 13: // *Game End
  430. newArgs = bonkAPI.receive_GameEnd(newArgs);
  431. break;
  432. case 15: // *Game Start
  433. newArgs = bonkAPI.receive_GameStart(newArgs);
  434. break;
  435. case 16: // *Error
  436. newArgs = bonkAPI.receive_Error(newArgs);
  437. break;
  438. case 18: // *Team Change
  439. newArgs = bonkAPI.receive_TeamChange(newArgs);
  440. break;
  441. case 19: // *Teamlock Toggle
  442. newArgs = bonkAPI.receive_TeamLockToggle(newArgs);
  443. break;
  444. case 20: // *Chat Message
  445. newArgs = bonkAPI.receive_ChatMessage(newArgs);
  446. break;
  447. case 21: // *Initial Data
  448. newArgs = bonkAPI.receive_InitialData(newArgs);
  449. break;
  450. case 24: // *Kicked
  451. newArgs = bonkAPI.receive_PlayerKick(newArgs);
  452. break;
  453. case 26: // *Change Mode
  454. newArgs = bonkAPI.receive_ModeChange(newArgs);
  455. break;
  456. case 27: // *Change Rounds
  457. newArgs = bonkAPI.receive_RoundsChange(newArgs);
  458. break;
  459. case 29: // *Map Switch
  460. newArgs = bonkAPI.receive_MapSwitch(newArgs);
  461. break;
  462. case 32: // *inactive?
  463. newArgs = bonkAPI.receive_Inactive(newArgs);
  464. break;
  465. case 33: // *Map Suggest
  466. newArgs = bonkAPI.receive_MapSuggest(newArgs);
  467. break;
  468. case 34: // *Map Suggest Client
  469. newArgs = bonkAPI.receive_MapSuggestClient(newArgs);
  470. break;
  471. case 36: // *Player Balance Change
  472. newArgs = bonkAPI.receive_PlayerBalance(newArgs);
  473. break;
  474. case 40: // *Save Replay
  475. newArgs = bonkAPI.receive_ReplaySave(newArgs);
  476. break;
  477. case 41: // *New Host
  478. newArgs = bonkAPI.receive_NewHost(newArgs);
  479. break;
  480. case 42: // *Friend Req
  481. newArgs = bonkAPI.receive_FriendRequest(newArgs);
  482. break;
  483. case 43: // *Game Starting Countdown
  484. newArgs = bonkAPI.receive_CountdownStart(newArgs);
  485. break;
  486. case 44: // *Abort Countdown
  487. newArgs = bonkAPI.receive_CountdownAbort(newArgs);
  488. break;
  489. case 45: // *Player Leveled Up
  490. newArgs = bonkAPI.receive_PlayerLevelUp(newArgs);
  491. break;
  492. case 46: // *Local Gained XP
  493. newArgs = bonkAPI.receive_LocalXPGain(newArgs);
  494. break;
  495. case 48:
  496. newArgs = bonkAPI.receive_gameState(newArgs);
  497. break;
  498. case 49: // *Created Room Share Link
  499. newArgs = bonkAPI.receive_RoomShareLink(newArgs);
  500. break;
  501. case 52: // *Tabbed
  502. newArgs = bonkAPI.receive_Tabbed(newArgs);
  503. break;
  504. case 58: // *Room Name Update
  505. newArgs = bonkAPI.receive_RoomName(newArgs);
  506. break;
  507. case 59: // *Room Password Update
  508. newArgs = bonkAPI.receive_RoomPassword(newArgs);
  509. break;
  510. }
  511. args.data = 42 + JSON.stringify(newArgs);
  512. }
  513. return originalReceive.call(this, args);
  514. };
  515.  
  516. var originalClose = this.onclose;
  517. this.onclose = function () {
  518. bonkAPI.bonkWSS = 0;
  519. return originalClose.call(this);
  520. };
  521. } else {
  522. // !All function names follow verb_noun[verb] format
  523. if(args.substring(0, 3) == "42[") {
  524. args = JSON.parse(args.substring(2));
  525. // &Sending outgoing packets
  526. switch (parseInt(args[0])) {
  527. case 4: // *Send Inputs
  528. args = bonkAPI.send_Inputs(args);
  529. break;
  530. case 5: // *Trigger Start
  531. args = bonkAPI.send_GameStart(args);
  532. break;
  533. case 6: // *Change Own Team
  534. args = bonkAPI.send_TeamChange(args);
  535. break;
  536. case 7: // *Team Lock
  537. args = bonkAPI.send_TeamLock(args);
  538. break;
  539. case 9: // *Kick/Ban Player
  540. args = bonkAPI.send_PlayerKickBan(args);
  541. break;
  542. case 10: // *Chat Message
  543. args = bonkAPI.send_ChatMessage(args);
  544. break;
  545. case 11: // *Inform In Lobby
  546. args = bonkAPI.send_LobbyInform(args);
  547. break;
  548. case 12: // *Create Room
  549. args = bonkAPI.send_RoomCreate(args);
  550. break;
  551. case 13: // *Room Join Information
  552. args = bonkAPI.send_RoomJoin(args);
  553. break;
  554. case 14: // *Return To Lobby
  555. args = bonkAPI.send_LobbyReturn(args);
  556. break;
  557. case 16: // *Set Ready
  558. args = bonkAPI.send_Ready(args);
  559. break;
  560. case 17: // *All Ready Reset
  561. args = bonkAPI.send_AllReadyReset(args);
  562. break;
  563. case 19: // *Send Map Reorder
  564. args = bonkAPI.send_MapReorder(args);
  565. break;
  566. case 20: // *Send Mode
  567. args = bonkAPI.send_ModeChange(args);
  568. break;
  569. case 21: // *Send WL (Rounds)
  570. args = bonkAPI.send_RoundsChange(args);
  571. break;
  572. case 22: // *Send Map Delete
  573. args = bonkAPI.send_MapDelete(args);
  574. break;
  575. case 23: // *Send Map Switch
  576. args = bonkAPI.send_MapSwitch(args);
  577. break;
  578. case 26: // *Change Other Team
  579. args = bonkAPI.send_OtherTeamChange(args);
  580. break;
  581. case 27: // *Send Map Suggest
  582. args = bonkAPI.send_MapSuggest(args);
  583. break;
  584. case 29: // *Send Balance
  585. args = bonkAPI.send_Balance(args);
  586. break;
  587. case 32: // *Send Team Settings Change
  588. args = bonkAPI.send_TeamSetting(args);
  589. break;
  590. case 33: // *Send Arm Record
  591. args = bonkAPI.send_ArmRecord(args);
  592. break;
  593. case 34: // *Send Host Change
  594. args = bonkAPI.send_HostChange(args);
  595. break;
  596. case 35: // *Send Friended
  597. args = bonkAPI.send_Friended(args);
  598. break;
  599. case 36: // *Send Start Countdown
  600. args = bonkAPI.send_CountdownStart(args);
  601. break;
  602. case 37: // *Send Abort Countdown
  603. args = bonkAPI.send_CountdownAbort(args);
  604. break;
  605. case 38: // *Send Req XP
  606. args = bonkAPI.send_XPRequest(args);
  607. break;
  608. case 39: // *Send Map Vote
  609. args = bonkAPI.send_MapVote(args);
  610. break;
  611. case 40: // *Inform In Game
  612. args = bonkAPI.send_InGameInform(args);
  613. break;
  614. case 41: // *Get Pre Vote
  615. args = bonkAPI.send_PreVoteGet(args);
  616. break;
  617. case 44: // *Tabbed
  618. args = bonkAPI.send_Tabbed(args);
  619. break;
  620. case 50: // *Send No Host Swap
  621. args = bonkAPI.send_NoHostSwap(args);
  622. break;
  623. }
  624. args = 42 + JSON.stringify(args);
  625. }
  626. }
  627. }
  628.  
  629. return bonkAPI.originalSend.call(this, args);
  630. };
  631. /**
  632. * @class EventHandler
  633. * @classdesc Stores functions and events and can fire events with data.
  634. * This class is already instantiated onto bonkAPI so if you dont need your
  635. * own event handler, ignore this class.
  636. * @hideconstructor
  637. */
  638. bonkAPI.EventHandler;
  639. (bonkAPI.EventHandler = function () {
  640. this.hasEvent = [];
  641. }).prototype = {
  642. /**
  643. * Begins to listen for the given event to call the method later.
  644. * @method
  645. * @memberof EventHandler
  646. * @param {string} event - Event that is listened for
  647. * @param {function(object)} method - Function that is called
  648. * @param {*} [scope] - Where the function should be called from, defaults to window
  649. * @param {*} [context] - defaults to nothing
  650. */
  651. addEventListener: function (event, method, scope, context) {
  652. var listeners, handlers;
  653. if (!(listeners = this.listeners)) {
  654. listeners = this.listeners = {};
  655. }
  656.  
  657. if (!(handlers = listeners[event])) {
  658. handlers = listeners[event] = [];
  659. this.hasEvent[event] = true;
  660. }
  661.  
  662. scope = scope ? scope : window;
  663. handlers.push({
  664. method: method,
  665. scope: scope,
  666. context: context ? context : scope,
  667. });
  668. },
  669.  
  670. /**
  671. * Fires the event given to call the methods linked to that event.
  672. * @method
  673. * @memberof EventHandler
  674. * @param {string} event - Event that is being fired
  675. * @param {object} data - Data sent along with the event
  676. * @param {*} [context]
  677. */
  678. fireEvent: function (event, data, context) {
  679. var listeners, handlers, handler, l, scope;
  680. if (!(listeners = this.listeners)) {
  681. return;
  682. }
  683. if (!(handlers = listeners[event])) {
  684. return;
  685. }
  686. l = handlers.length;
  687. for (let i = 0; i < l; i++) {
  688. handler = handlers[i];
  689. if (typeof context !== "undefined" && context !== handler.context) {
  690. continue;
  691. }
  692. handler.method.call(handler.scope, data);
  693. }
  694. },
  695. };
  696.  
  697. //initialize
  698. bonkAPI.events = new bonkAPI.EventHandler();
  699.  
  700. /**
  701. * Triggered when recieving ping updates.
  702. * @function receive_PingUpdate
  703. * @fires pingUpdate
  704. * @param {JSON} args - Packet received by websocket.
  705. * @returns {JSON} arguements
  706. */
  707. bonkAPI.receive_PingUpdate = function (args) {
  708. let pingList = args[1];
  709. let ehcoTo = args[2];
  710.  
  711. /**
  712. * When the user receives ping update.
  713. * @event pingUpdate
  714. * @type {object}
  715. * @property {object} pingList - Other players' ping
  716. * @property {number} echoTo - The ID of the player to echo to
  717. */
  718. if (bonkAPI.events.hasEvent["pingUpdate"]) {
  719. var sendObj = {
  720. pingList: pingList,
  721. ehcoTo: ehcoTo,
  722. };
  723. bonkAPI.events.fireEvent("pingUpdate", sendObj);
  724. }
  725.  
  726. return args;
  727. };
  728.  
  729. bonkAPI.receive_Unknow2 = function (args) {
  730. // TODO: Finish implement of function
  731.  
  732. return args;
  733. };
  734.  
  735. /**
  736. * Triggered when the user joins a lobby.
  737. * @function receive_RoomJoin
  738. * @fires joinRoom
  739. * @fires playerChange
  740. * @param {JSON} args - Packet received by websocket.
  741. * @returns {JSON} arguements
  742. */
  743. bonkAPI.receive_RoomJoin = function (args) {
  744. bonkAPI.playerList = [];
  745. bonkAPI.myID = args[1];
  746. bonkAPI.hostID = args[2];
  747.  
  748. for (let i = 0; i < bonkAPI.currentPlayers.length; i++) {
  749. /**
  750. * When a player leaves or joins.
  751. * @event playerChange
  752. * @type {object}
  753. * @property {number} userID - ID of the player who joined or left
  754. * @property {object} userData - Data of the player who joined or left
  755. * @property {boolean} hasLeft - Whether the player joined or left
  756. */
  757. if (bonkAPI.events.hasEvent["playerChange"]) {
  758. var sendObj = { userID: bonkAPI.currentPlayers[i], userData: bonkAPI.playerList[bonkAPI.currentPlayers[i]], hasLeft: true };
  759. bonkAPI.events.fireEvent("playerChange", sendObj);
  760. }
  761. }
  762. bonkAPI.currentPlayers = [];
  763.  
  764. for (let i = 0; i < args[3].length; i++) {
  765. bonkAPI.playerList[i] = args[3][i];
  766. if (args[3][i] != null) {
  767. bonkAPI.currentPlayers.push(i);
  768.  
  769. /**
  770. * When a player leaves or joins.
  771. * @event playerChange
  772. * @type {object}
  773. * @property {number} userID - ID of the player who joined or left
  774. * @property {object} userData - Data of the player who joined or left
  775. * @property {boolean} hasLeft - Whether the player joined or left
  776. */
  777. if (bonkAPI.events.hasEvent["playerChange"]) {
  778. var sendObj = { userID: args[1], userData: bonkAPI.playerList[args[1]], hasLeft: false };
  779. bonkAPI.events.fireEvent("playerChange", sendObj);
  780. }
  781. }
  782. }
  783. /**
  784. * When the user joins a lobby.
  785. * @event joinRoom
  786. * @type {object}
  787. * @property {number} hostID - ID of the host
  788. * @property {Array.<Player>} userData - List of players currently in the room
  789. * @property {*} roomID - ID of the lobby joined
  790. * @property {string} bypass
  791. */
  792. if (bonkAPI.events.hasEvent["joinRoom"]) {
  793. var sendObj = {
  794. hostID: args[2],
  795. userData: bonkAPI.playerList, // !May or may not be immutable
  796. roomID: args[6],
  797. bypass: args[7],
  798. };
  799. bonkAPI.events.fireEvent("joinRoom", sendObj);
  800. }
  801.  
  802. /**
  803. * When a player leaves or joins.
  804. * @event playerChange
  805. * @type {object}
  806. * @property {number} userID - ID of the player who joined or left
  807. * @property {object} userData - Data of the player who joined or left
  808. * @property {boolean} hasLeft - Whether the player joined or left
  809. */
  810. if (bonkAPI.events.hasEvent["playerChange"]) {
  811. var sendObj = { userID: args[1], userData: bonkAPI.playerList[args[1]], hasLeft: false };
  812. bonkAPI.events.fireEvent("playerChange", sendObj);
  813. }
  814.  
  815. return args;
  816. };
  817.  
  818. /**
  819. * Triggered when a player joins the lobby.
  820. * @function receive_PlayerJoin
  821. * @fires userJoin
  822. * @fires playerChange
  823. * @param {JSON} args - Packet received by websocket.
  824. * @returns {JSON} arguements
  825. */
  826. bonkAPI.receive_PlayerJoin = function (args) {
  827. bonkAPI.playerList[args[1]] = {
  828. peerId: args[2],
  829. userName: args[3],
  830. guest: args[4],
  831. level: args[5],
  832. team: args[6],
  833. ready: false,
  834. tabbed: false,
  835. avatar: args[7],
  836. };
  837. bonkAPI.currentPlayers.push(args[1]);
  838.  
  839. //? can:
  840. //? - send the bonkAPI.playerList as data
  841. //? - send the new player object as data
  842. //? - send nothing and let the user access bonkAPI.playerList
  843. /**
  844. * When another player joins the lobby.
  845. * @event userJoin
  846. * @type {object}
  847. * @property {number} userID - ID of the player joined
  848. * @property {Player} userData - {@linkcode Player} object data of the player that joined
  849. */
  850. if (bonkAPI.events.hasEvent["userJoin"]) {
  851. var sendObj = { userID: args[1], userData: bonkAPI.playerList[args[1]] };
  852. bonkAPI.events.fireEvent("userJoin", sendObj);
  853. }
  854.  
  855. /**
  856. * When a player leaves or joins.
  857. * @event playerChange
  858. * @type {object}
  859. * @property {number} userID - ID of the player who joined or left
  860. * @property {object} userData - Data of the player who joined or left
  861. * @property {boolean} hasLeft - Whether the player joined or left
  862. */
  863. if (bonkAPI.events.hasEvent["playerChange"]) {
  864. var sendObj = { userID: args[1], userData: bonkAPI.playerList[args[1]], hasLeft: false };
  865. bonkAPI.events.fireEvent("playerChange", sendObj);
  866. }
  867.  
  868. return args;
  869. };
  870.  
  871. /**
  872. * Triggered when a player leaves the lobby.
  873. * @function receive_PlayerLeave
  874. * @fires userLeave
  875. * @fires playerChange
  876. * @param {JSON} args - Packet received by websocket.
  877. * @returns {JSON} arguements
  878. */
  879. bonkAPI.receive_PlayerLeave = function (args) {
  880. // Remove player from current players
  881. bonkAPI.currentPlayers.forEach((n, i) => {
  882. if (n == args[1]) {
  883. bonkAPI.currentPlayers.splice(i, 1);
  884. }
  885. });
  886.  
  887. /**
  888. * When another player leaves the lobby.
  889. * @event userLeave
  890. * @type {object}
  891. * @property {number} userID - ID of the player left
  892. * @property {Player} userData - {@linkcode Player} object data of the player that left
  893. */
  894. if (bonkAPI.events.hasEvent["userLeave"]) {
  895. var sendObj = { userID: args[1], userData: bonkAPI.playerList[args[1]] };
  896. bonkAPI.events.fireEvent("userLeave", sendObj);
  897. }
  898.  
  899. /**
  900. * When a player leaves or joins.
  901. * @event playerChange
  902. * @type {object}
  903. * @property {number} userID - ID of the player who joined or left
  904. * @property {object} userData - Data of the player who joined or left
  905. * @property {boolean} hasLeft - Whether the player joined or left
  906. */
  907. if (bonkAPI.events.hasEvent["playerChange"]) {
  908. var sendObj = { userID: args[1], userData: bonkAPI.playerList[args[1]], hasLeft: true };
  909. bonkAPI.events.fireEvent("playerChange", sendObj);
  910. }
  911.  
  912. return args;
  913. };
  914.  
  915. /**
  916. * Triggered when the host has left.
  917. * @function receive_HostLeave
  918. * @fires hostChange
  919. * @fires userLeave
  920. * @fires playerChange
  921. * @param {JSON} args - Packet received by websocket.
  922. * @returns {JSON} arguements
  923. */
  924. bonkAPI.receive_HostLeave = function (args) {
  925. let lastHostID = bonkAPI.hostID;
  926. bonkAPI.hostID = args[2];
  927.  
  928. // Remove player from current players
  929. bonkAPI.currentPlayers.forEach((n, i) => {
  930. if (n == lastHostID) {
  931. bonkAPI.currentPlayers.splice(i, 1);
  932. }
  933. });
  934.  
  935. /**
  936. * When the host changes.
  937. * @event hostChange
  938. * @type {object}
  939. * @property {number} userID - ID of the new host
  940. */
  941. //Using hostChange to use for multiple cases
  942. if (bonkAPI.events.hasEvent["hostChange"]) {
  943. var sendObj = { userID: args[1] };
  944. bonkAPI.events.fireEvent("hostChange", sendObj);
  945. }
  946.  
  947. /**
  948. * When another player leaves the lobby.
  949. * @event userLeave
  950. * @type {object}
  951. * @property {number} userID - ID of the player left
  952. * @property {Player} userData - {@linkcode Player} object data of the player that left
  953. */
  954. if (bonkAPI.events.hasEvent["userLeave"]) {
  955. var sendObj = { userID: lastHostID, userData: bonkAPI.playerList[lastHostID] };
  956. bonkAPI.events.fireEvent("userLeave", sendObj);
  957. }
  958.  
  959. /**
  960. * When a player leaves or joins.
  961. * @event playerChange
  962. * @type {object}
  963. * @property {number} userID - ID of the player who joined or left
  964. * @property {object} userData - Data of the player who joined or left
  965. * @property {boolean} hasLeft - Whether the player joined or left
  966. */
  967. if (bonkAPI.events.hasEvent["playerChange"]) {
  968. var sendObj = { userID: lastHostID, userData: bonkAPI.playerList[lastHostID], hasLeft: true };
  969. bonkAPI.events.fireEvent("playerChange", sendObj);
  970. }
  971.  
  972. return args;
  973. };
  974.  
  975. /**
  976. * Triggered when a player sends an input.
  977. * @function receive_Inputs
  978. * @fires gameInputs
  979. * @param {JSON} args - Packet received by websocket.
  980. * @returns {JSON} arguements
  981. */
  982. bonkAPI.receive_Inputs = function (args) {
  983. /*
  984. * Maybe we could have different event names like
  985. * "receiveRawInput" and "receiveInput" which send
  986. * different data, the second could have booleans
  987. * representing the inputs, the other is binary
  988. */
  989. /**
  990. * When inputs are received from other players.
  991. * @event gameInputs
  992. * @type {object}
  993. * @property {number} userID - ID of the player who inputted
  994. * @property {number} rawInput - Input of the player in the form of 6 bits
  995. * @property {number} frame - Frame when input happened
  996. * @property {number} sequence - The total amount of inputs by that player
  997. */
  998. if (bonkAPI.events.hasEvent["gameInputs"]) {
  999. var sendObj = {
  1000. userID: args[1],
  1001. rawInput: args[2]["i"],
  1002. frame: args[2]["f"],
  1003. sequence: args[2]["c"],
  1004. };
  1005. bonkAPI.events.fireEvent("gameInputs", sendObj);
  1006. } //example
  1007. /*if(bonkAPI.bonkAPI.events.hasEvent["receiveRawInput"]) {
  1008. obj here
  1009. bonkAPI.bonkAPI.events.fireEvent("receiveRawInput", sendObj);
  1010. }
  1011. */
  1012.  
  1013. return args;
  1014. };
  1015.  
  1016. bonkAPI.receive_ReadyChange = function (args) {
  1017. // TODO: Finish implement of function
  1018.  
  1019. return args;
  1020. };
  1021.  
  1022. bonkAPI.receive_GameEnd = function (args) {
  1023. // TODO: Finish implement of function
  1024.  
  1025. return args;
  1026. };
  1027.  
  1028. //! Detects when match starts!!!
  1029. /**
  1030. * Triggered when the game starts.
  1031. * @function receive_GameStart
  1032. * @fires gameStart
  1033. * @param {JSON} args - Packet received by websocket.
  1034. * @returns {JSON} arguements
  1035. */
  1036. bonkAPI.receive_GameStart = function (args) {
  1037. /**
  1038. * When game has started
  1039. * @event gameStart
  1040. * @type {object}
  1041. * @property {string} mapData - Encoded map data, must decode it to use
  1042. * @property {object} startData - Extra game specific data
  1043. */
  1044. if (bonkAPI.events.hasEvent["gameStart"] && bonkAPI.myID != bonkAPI.hostID) {
  1045. //! change name of mapdata since it is not map data, probably gamestate
  1046. //! do the same in triggerstart
  1047. var sendObj = {
  1048. mapData: bonkAPI.ISdecode(args[2]),
  1049. startData: args[3],
  1050. };
  1051. bonkAPI.events.fireEvent("gameStart", sendObj);
  1052. }
  1053.  
  1054. return args;
  1055. };
  1056.  
  1057. bonkAPI.receive_Error = function (args) {
  1058. // TODO: Finish implement of function
  1059.  
  1060. return args;
  1061. };
  1062.  
  1063. /**
  1064. * Triggered when a player changes team.
  1065. * @function receive_TeamChange
  1066. * @fires teamChange
  1067. * @param {JSON} args - Packet received by websocket.
  1068. * @returns {JSON} arguements
  1069. */
  1070. bonkAPI.receive_TeamChange = function (args) {
  1071. bonkAPI.playerList[parseInt(args[1])].team = args[2];
  1072.  
  1073. /**
  1074. * When a player has changed teams.
  1075. * @event teamChange
  1076. * @type {object}
  1077. * @property {number} userID - Player who changed teams
  1078. * @property {number} team - The new team, represented from 0 to 5
  1079. */
  1080. if (bonkAPI.events.hasEvent["teamChange"]) {
  1081. var sendObj = { userID: args[1], team: args[2] };
  1082. bonkAPI.events.fireEvent("teamChange", sendObj);
  1083. }
  1084.  
  1085. return args;
  1086. };
  1087.  
  1088. bonkAPI.receive_TeamLockToggle = function (args) {
  1089. // TODO: Finish implement of function
  1090.  
  1091. return args;
  1092. };
  1093.  
  1094. /**
  1095. * Triggered when received a message.
  1096. * @function receive_ChatMessage
  1097. * @fires chatIn
  1098. * @param {JSON} args - Packet received by websocket.
  1099. * @returns {JSON} arguements
  1100. */
  1101. bonkAPI.receive_ChatMessage = function (args) {
  1102. let chatUserID = args[1];
  1103. let chatMessage = args[2];
  1104.  
  1105. /**
  1106. * When the user has received a message.
  1107. * @event chatIn
  1108. * @type {object}
  1109. * @property {number} userID - Player who chatted
  1110. * @property {string} message - The message received
  1111. */
  1112. if (bonkAPI.events.hasEvent["chatIn"]) {
  1113. var sendObj = { userID: chatUserID, message: chatMessage };
  1114. bonkAPI.events.fireEvent("chatIn", sendObj);
  1115. }
  1116.  
  1117. return args;
  1118. };
  1119.  
  1120. /**
  1121. * Data given by host after join.
  1122. * @function receive_InitialData
  1123. * @fires modeChange
  1124. * @param {JSON} args - Packet received by websocket.
  1125. * @returns {JSON} arguements
  1126. */
  1127. bonkAPI.receive_InitialData = function (args) {
  1128. /**
  1129. * When the mode has changed.
  1130. * @event modeChange
  1131. * @type {object}
  1132. * @property {string} mode - Short string representing the new mode
  1133. */
  1134. if (bonkAPI.events.hasEvent["modeChange"]) {
  1135. var sendObj = { mode: args[1]["mo"] };
  1136. bonkAPI.events.fireEvent("modeChange", sendObj);
  1137. }
  1138.  
  1139. return args;
  1140. };
  1141.  
  1142. bonkAPI.receive_PlayerKick = function (args) {
  1143. // TODO: Finish implement of function
  1144.  
  1145. return args;
  1146. };
  1147.  
  1148. /**
  1149. * Triggered when the mode changes.
  1150. * @function receive_ModeChange
  1151. * @fires modeChange
  1152. * @param {JSON} args - Packet received by websocket.
  1153. * @returns {JSON} arguements
  1154. */
  1155. bonkAPI.receive_ModeChange = function (args) {
  1156. // *Maybe change raw arguement to full mode name or numbers
  1157. /**
  1158. * When the mode has changed.
  1159. * @event modeChange
  1160. * @type {object}
  1161. * @property {string} mode - Short string representing the new mode
  1162. */
  1163. if (bonkAPI.events.hasEvent["modeChange"]) {
  1164. var sendObj = { mode: args[1] };
  1165. bonkAPI.events.fireEvent("modeChange", sendObj);
  1166. }
  1167.  
  1168. return args;
  1169. };
  1170.  
  1171. bonkAPI.receive_RoundsChange = function (args) {
  1172. // TODO: Finish implement of function
  1173.  
  1174. return args;
  1175. };
  1176.  
  1177. /**
  1178. * Triggered when map has changed.
  1179. * @function receive_MapSwitch
  1180. * @fires mapSwitch
  1181. * @param {JSON} args - Packet received by websocket.
  1182. * @returns {JSON} arguements
  1183. */
  1184. bonkAPI.receive_MapSwitch = function (args) {
  1185. // *Using mapSwitch to stick with other bonkAPI.events using "change"
  1186. /**
  1187. * When the map has changed.
  1188. * @event mapSwitch
  1189. * @type {object}
  1190. * @property {string} mapData - String with the data of the map
  1191. */
  1192. if (bonkAPI.events.hasEvent["mapSwitch"]) {
  1193. var sendObj = { mapData: args[1] };
  1194. bonkAPI.events.fireEvent("mapSwitch", sendObj);
  1195. }
  1196.  
  1197. return args;
  1198. };
  1199.  
  1200. bonkAPI.receive_Inactive = function (args) {
  1201. // TODO: Finish implement of function
  1202.  
  1203. return args;
  1204. };
  1205.  
  1206. bonkAPI.receive_MapSuggest = function (args) {
  1207. // TODO: Finish implement of function
  1208.  
  1209. return args;
  1210. };
  1211.  
  1212. bonkAPI.receive_MapSuggestClient = function (args) {
  1213. // TODO: Finish implement of function
  1214.  
  1215. return args;
  1216. };
  1217.  
  1218. bonkAPI.receive_PlayerBalance = function (args) {
  1219. // TODO: Finish implement of function
  1220.  
  1221. return args;
  1222. };
  1223.  
  1224. bonkAPI.receive_ReplaySave = function (args) {
  1225. // TODO: Finish implement of function
  1226.  
  1227. return args;
  1228. };
  1229.  
  1230. /**
  1231. * Triggered when there is a new host.
  1232. * @function receive_NewHost
  1233. * @fires hostChange
  1234. * @param {JSON} args - Packet received by websocket.
  1235. * @returns {JSON} arguements
  1236. */
  1237. bonkAPI.receive_NewHost = function (args) {
  1238. bonkAPI.hostID = args[1]["newHost"];
  1239.  
  1240. /**
  1241. * When the host changes.
  1242. * @event hostChange
  1243. * @type {object}
  1244. * @property {number} userID - ID of the new host
  1245. */
  1246. if (bonkAPI.events.hasEvent["hostChange"]) {
  1247. var sendObj = { userID: args[1]["newHost"] };
  1248. bonkAPI.events.fireEvent("hostChange", sendObj);
  1249. }
  1250.  
  1251. return args;
  1252. };
  1253.  
  1254. /**
  1255. * Triggered when the user receives a friend request.
  1256. * @function receive_FriendReq
  1257. * @fires receivedFriend
  1258. * @param {JSON} args - Packet received by websocket.
  1259. * @returns {JSON} arguements
  1260. */
  1261. bonkAPI.receive_FriendRequest = function (args) {
  1262. /**
  1263. * When the the user has been friended.
  1264. * @event receivedFriend
  1265. * @type {object}
  1266. * @property {number} userID - ID of the player who friended you
  1267. */
  1268. if (bonkAPI.events.hasEvent["receivedFriend"]) {
  1269. var sendObj = { userID: args[1] };
  1270. bonkAPI.events.fireEvent("receivedFriend", sendObj);
  1271. }
  1272.  
  1273. return args;
  1274. };
  1275.  
  1276. bonkAPI.receive_CountdownStart = function (args) {
  1277. // TODO: Finish implement of function
  1278.  
  1279. return args;
  1280. };
  1281.  
  1282. bonkAPI.receive_CountdownAbort = function (args) {
  1283. // TODO: Finish implement of function
  1284.  
  1285. return args;
  1286. };
  1287.  
  1288. bonkAPI.receive_PlayerLevelUp = function (args) {
  1289. // TODO: Finish implement of function
  1290.  
  1291. return args;
  1292. };
  1293.  
  1294. bonkAPI.receive_LocalXPGain = function (args) {
  1295. // TODO: Finish implement of function
  1296.  
  1297. return args;
  1298. };
  1299.  
  1300. /**
  1301. * Triggers after joining a room and the
  1302. * game state is sent.
  1303. * @function receive_gameState
  1304. * @fires modeChange
  1305. * @fires gameStart
  1306. * @param {JSON} args - Packet received by websocket.
  1307. * @returns {JSON} arguements
  1308. */
  1309. bonkAPI.receive_gameState = function (args) {
  1310. //! also needs to fire something to do with gamestate
  1311. /**
  1312. * When the mode has changed.
  1313. * @event modeChange
  1314. * @type {object}
  1315. * @property {string} mode - Short string representing the new mode
  1316. */
  1317. if (bonkAPI.events.hasEvent["modeChange"]) {
  1318. var sendObj = { mode: args[1]["gs"]["mo"] };
  1319. bonkAPI.events.fireEvent("modeChange", sendObj);
  1320. }
  1321.  
  1322. /**
  1323. * When game has started
  1324. * @event gameStart
  1325. * @type {object}
  1326. * @property {string} mapData - Encoded map data, must decode it to use
  1327. * @property {object} startData - Extra game specific data
  1328. */
  1329. if (bonkAPI.events.hasEvent["gameStart"]) {
  1330. //! change name of mapdata since it is not map data, probably gamestate
  1331. //! do the same in triggerstart
  1332. var sendObj = {
  1333. mapData: bonkAPI.decodeMap(args[1]["gs"]["map"]),
  1334. startData: args[3],
  1335. };
  1336. bonkAPI.events.fireEvent("gameStart", sendObj);
  1337. }
  1338. return args;
  1339. };
  1340.  
  1341. bonkAPI.receive_RoomShareLink = function (args) {
  1342. // TODO: Finish implement of function
  1343.  
  1344. return args;
  1345. };
  1346.  
  1347. bonkAPI.receive_Tabbed = function (args) {
  1348. // TODO: Finish implement of function
  1349.  
  1350. return args;
  1351. };
  1352.  
  1353. bonkAPI.receive_RoomName = function (args) {
  1354. // TODO: Finish implement of function
  1355.  
  1356. return args;
  1357. };
  1358.  
  1359. bonkAPI.receive_RoomPassword = function (args) {
  1360. // TODO: Finish implement of function
  1361.  
  1362. return args;
  1363. };
  1364. /**
  1365. * Called when sending inputs out.
  1366. * @function send_Inputs
  1367. * @param {JSON} args - Packet received by websocket.
  1368. * @returns {JSON} arguements
  1369. */
  1370. bonkAPI.send_Inputs = function (args) {
  1371. /**
  1372. * When inputs are received from other players.
  1373. * @event gameInputs
  1374. * @type {object}
  1375. * @property {number} userID - ID of the player who inputted
  1376. * @property {number} rawInput - Input of the player in the form of 6 bits
  1377. * @property {number} frame - Frame when input happened
  1378. * @property {number} sequence - The total amount of inputs by that player
  1379. */
  1380. if (bonkAPI.events.hasEvent["gameInputs"]) {
  1381. var sendObj = {
  1382. userID: bonkAPI.myID,
  1383. rawInput: args[1]["i"],
  1384. frame: args[1]["f"],
  1385. sequence: args[1]["c"],
  1386. };
  1387. bonkAPI.events.fireEvent("gameInputs", sendObj);
  1388. }
  1389.  
  1390. return args;
  1391. };
  1392.  
  1393. /**
  1394. * Called when started the game.
  1395. * @function send_GameStart
  1396. * @param {JSON} args - Packet received by websocket.
  1397. * @returns {JSON} arguements
  1398. */
  1399. bonkAPI.send_GameStart = function (args) {
  1400. /**
  1401. * When game has started
  1402. * @event gameStart
  1403. * @type {object}
  1404. * @property {string} mapData - Encoded map data, must decode it to use
  1405. * @property {object} startData - Extra game specific data
  1406. */
  1407. if (bonkAPI.events.hasEvent["gameStart"]) {
  1408. //! do something to mapData so it will encode it
  1409. //! then assign it back to the args
  1410. var sendObj = {
  1411. mapData: bonkAPI.ISdecode(args[1]["is"]),
  1412. startData: args[1]["gs"],
  1413. };
  1414. bonkAPI.events.fireEvent("gameStart", sendObj);
  1415.  
  1416. //!possibly temporary
  1417. //allows start packet to be edited
  1418. args[1]["is"] = bonkAPI.ISencode(sendObj.mapData);
  1419. }
  1420.  
  1421. return args;
  1422. };
  1423.  
  1424. bonkAPI.send_TeamChange = function (args) {
  1425. // TODO: Finish implement of function
  1426.  
  1427. return args;
  1428. };
  1429.  
  1430. bonkAPI.send_TeamLock = function (args) {
  1431. // TODO: Finish implement of function
  1432.  
  1433. return args;
  1434. };
  1435.  
  1436. bonkAPI.send_PlayerKickBan = function (args) {
  1437. // TODO: Finish implement of function
  1438.  
  1439. return args;
  1440. };
  1441.  
  1442. bonkAPI.send_ChatMessage = function (args) {
  1443. // TODO: Finish implement of function
  1444.  
  1445. return args;
  1446. };
  1447.  
  1448. bonkAPI.send_LobbyInform = function (args) {
  1449. // TODO: Finish implement of function
  1450.  
  1451. return args;
  1452. };
  1453.  
  1454. /**
  1455. * Called when created a room.
  1456. * @function send_RoomCreate
  1457. * @fires createRoom
  1458. * @fires playerChange
  1459. * @param {JSON} args - Packet received by websocket.
  1460. * @returns {JSON} arguements
  1461. */
  1462. bonkAPI.send_RoomCreate = function (args) {
  1463. bonkAPI.playerList = [];
  1464.  
  1465. for (let i = 0; i < bonkAPI.currentPlayers.length; i++) {
  1466. /**
  1467. * When a player leaves or joins.
  1468. * @event playerChange
  1469. * @type {object}
  1470. * @property {number} userID - ID of the player who joined or left
  1471. * @property {object} userData - Data of the player who joined or left
  1472. * @property {boolean} hasLeft - Whether the player joined or left
  1473. */
  1474. if (bonkAPI.events.hasEvent["playerChange"]) {
  1475. var sendObj = { userID: bonkAPI.currentPlayers[i], userData: bonkAPI.playerList[bonkAPI.currentPlayers[i]], hasLeft: true };
  1476. bonkAPI.events.fireEvent("playerChange", sendObj);
  1477. }
  1478. }
  1479. bonkAPI.currentPlayers = [];
  1480.  
  1481. bonkAPI.playerList[0] = {
  1482. peerId: args[1]["peerID"],
  1483. userName: document.getElementById("pretty_top_name").textContent,
  1484. level:
  1485. document.getElementById("pretty_top_level").textContent == "Guest"
  1486. ? 0
  1487. : parseInt(document.getElementById("pretty_top_level").textContent.substring(3)),
  1488. guest: typeof args[1].token == "undefined",
  1489. team: 1,
  1490. ready: false,
  1491. tabbed: false,
  1492. avatar: args[1]["avatar"],
  1493. };
  1494. bonkAPI.currentPlayers.push(0);
  1495.  
  1496. bonkAPI.myID = 0;
  1497. bonkAPI.hostID = 0;
  1498.  
  1499. /**
  1500. * When you create a room.
  1501. * @event createRoom
  1502. * @type {object}
  1503. * @property {number} userID - ID of you
  1504. * @property {object} userData - Your player data
  1505. */
  1506. if (bonkAPI.events.hasEvent["createRoom"]) {
  1507. var sendObj = { userID: 0, userData: bonkAPI.playerList[0] };
  1508. bonkAPI.events.fireEvent("createRoom", sendObj);
  1509. }
  1510.  
  1511. /**
  1512. * When a player leaves or joins.
  1513. * @event playerChange
  1514. * @type {object}
  1515. * @property {number} userID - ID of the player who joined or left
  1516. * @property {object} userData - Data of the player who joined or left
  1517. * @property {boolean} hasLeft - Whether the player joined or left
  1518. */
  1519. if (bonkAPI.events.hasEvent["playerChange"]) {
  1520. var sendObj = { userID: 0, userData: bonkAPI.playerList[0], hasLeft: false };
  1521. bonkAPI.events.fireEvent("playerChange", sendObj);
  1522. }
  1523.  
  1524. return args;
  1525. };
  1526.  
  1527. /**
  1528. * Called as to send inital user data when joining a room.
  1529. * @function send_RoomJoin
  1530. * @fires roomJoin
  1531. * @param {JSON} args - Packet received by websocket.
  1532. * @returns {JSON} arguements
  1533. */
  1534. bonkAPI.send_RoomJoin = function (args) {
  1535. //! DONT KNOW WHAT TO DO FOR NAMING
  1536. //! Possibly get rid of XMLhttp thing since this gives the login token
  1537. /**
  1538. * When inputs are received from other players.
  1539. * @event roomJoin
  1540. * @type {object}
  1541. * @property {string} password - Room password
  1542. * @property {object} avatar - User's avatar
  1543. * @property {string} token - Login token
  1544. */
  1545. if (bonkAPI.events.hasEvent["roomJoin"]) {
  1546. var sendObj = {
  1547. password: args[1]["roomPassword"],
  1548. avatar: args[1]["avatar"],
  1549. token: args[1]["token"] ? args[1]["token"] : null,
  1550. };
  1551. bonkAPI.events.fireEvent("roomJoin", sendObj);
  1552. }
  1553.  
  1554. return args;
  1555. };
  1556.  
  1557. bonkAPI.send_LobbyReturn = function (args) {
  1558. // TODO: Finish implement of function
  1559.  
  1560. return args;
  1561. };
  1562.  
  1563. bonkAPI.send_Ready = function (args) {
  1564. // TODO: Finish implement of function
  1565.  
  1566. return args;
  1567. };
  1568.  
  1569. bonkAPI.send_AllReadyReset = function (args) {
  1570. // TODO: Finish implement of function
  1571.  
  1572. return args;
  1573. };
  1574.  
  1575. bonkAPI.send_MapReorder = function (args) {
  1576. // TODO: Finish implement of function
  1577.  
  1578. return args;
  1579. };
  1580.  
  1581. /**
  1582. * When you change modes.
  1583. * @function send_ModeChange
  1584. * @fires modeChange
  1585. * @param {JSON} args - Packet received by websocket.
  1586. * @returns {JSON} arguements
  1587. */
  1588. bonkAPI.send_ModeChange = function (args) {
  1589. // TODO: Finish implement of function
  1590. /**
  1591. * When the mode has changed.
  1592. * @event modeChange
  1593. * @type {object}
  1594. * @property {string} mode - Short string representing the new mode
  1595. */
  1596. if (bonkAPI.events.hasEvent["modeChange"]) {
  1597. var sendObj = { mode: args[1]["mo"] };
  1598. bonkAPI.events.fireEvent("modeChange", sendObj);
  1599. }
  1600.  
  1601. return args;
  1602. };
  1603.  
  1604. bonkAPI.send_RoundsChange = function (args) {
  1605. // TODO: Finish implement of function
  1606.  
  1607. return args;
  1608. };
  1609.  
  1610. bonkAPI.send_MapDelete = function (args) {
  1611. // TODO: Finish implement of function
  1612.  
  1613. return args;
  1614. };
  1615.  
  1616. /**
  1617. * Called when user changes map.
  1618. * @function send_MapSwitch
  1619. * @param {JSON} args - Packet received by websocket.
  1620. * @returns {JSON} arguements
  1621. */
  1622. bonkAPI.send_MapSwitch = function (args) {
  1623. // *Using mapSwitch to stick with other bonkAPI.events using "change"
  1624. /**
  1625. * When the map has changed.
  1626. * @event mapSwitch
  1627. * @type {object}
  1628. * @property {string} mapData - String with the data of the map
  1629. */
  1630. if (bonkAPI.events.hasEvent["mapSwitch"]) {
  1631. var sendObj = { mapData: args[1]["m"] };
  1632. bonkAPI.events.fireEvent("mapSwitch", sendObj);
  1633. }
  1634. return args;
  1635. };
  1636.  
  1637. bonkAPI.send_OtherTeamChange = function (args) {
  1638. // TODO: Finish implement of function
  1639.  
  1640. return args;
  1641. };
  1642.  
  1643. bonkAPI.send_MapSuggest = function (args) {
  1644. // TODO: Finish implement of function
  1645.  
  1646. return args;
  1647. };
  1648.  
  1649. bonkAPI.send_Balance = function (args) {
  1650. // TODO: Finish implement of function
  1651.  
  1652. return args;
  1653. };
  1654.  
  1655. bonkAPI.send_TeamSetting = function (args) {
  1656. // TODO: Finish implement of function
  1657.  
  1658. return args;
  1659. };
  1660.  
  1661. bonkAPI.send_ArmRecord = function (args) {
  1662. // TODO: Finish implement of function
  1663.  
  1664. return args;
  1665. };
  1666.  
  1667. bonkAPI.send_HostChange = function (args) {
  1668. // TODO: Finish implement of function
  1669.  
  1670. return args;
  1671. };
  1672.  
  1673. bonkAPI.send_Friended = function (args) {
  1674. // TODO: Finish implement of function
  1675.  
  1676. return args;
  1677. };
  1678.  
  1679. bonkAPI.send_CountdownStart = function (args) {
  1680. // TODO: Finish implement of function
  1681.  
  1682. return args;
  1683. };
  1684.  
  1685. bonkAPI.send_CountdownAbort = function (args) {
  1686. // TODO: Finish implement of function
  1687.  
  1688. return args;
  1689. };
  1690.  
  1691. bonkAPI.send_XPRequest = function (args) {
  1692. // TODO: Finish implement of function
  1693.  
  1694. return args;
  1695. };
  1696.  
  1697. bonkAPI.send_MapVote = function (args) {
  1698. // TODO: Finish implement of function
  1699.  
  1700. return args;
  1701. };
  1702.  
  1703. bonkAPI.send_InGameInform = function (args) {
  1704. // TODO: Finish implement of function
  1705.  
  1706. return args;
  1707. };
  1708.  
  1709. bonkAPI.send_PreVoteGet = function (args) {
  1710. // TODO: Finish implement of function
  1711.  
  1712. return args;
  1713. };
  1714.  
  1715. bonkAPI.send_Tabbed = function (args) {
  1716. // TODO: Finish implement of function
  1717.  
  1718. return args;
  1719. };
  1720.  
  1721. bonkAPI.send_NoHostSwap = function (args) {
  1722. // TODO: Finish implement of function
  1723.  
  1724. return args;
  1725. };
  1726. window.XMLHttpRequest.prototype.open = function (_, url) {
  1727. if (url.includes("scripts/login_legacy")) {
  1728. bonkAPI.isLoggingIn = true;
  1729. }
  1730. //? Could check for other post requests but not necessary
  1731.  
  1732. bonkAPI.originalXMLOpen.call(this, ...arguments);
  1733. };
  1734. window.XMLHttpRequest.prototype.send = function (data) {
  1735. if (bonkAPI.isLoggingIn) {
  1736. this.onreadystatechange = function () {
  1737. if (this.readyState == 4) {
  1738. bonkAPI.myToken = JSON.parse(this.response)["token"];
  1739. }
  1740. };
  1741. bonkAPI.isLoggingIn = false;
  1742. }
  1743. bonkAPI.originalXMLSend.call(this, ...arguments);
  1744. };
  1745. // *Injecting code into src
  1746. bonkAPI.injector = function (src) {
  1747. let newSrc = src;
  1748.  
  1749. //! Inject capZoneEvent fire
  1750. let orgCode = `K$h[9]=K$h[0][0][K$h[2][138]]()[K$h[2][115]];`;
  1751. let newCode = `
  1752. K$h[9]=K$h[0][0][K$h[2][138]]()[K$h[2][115]];
  1753. bonkAPI_capZoneEventTry: try {
  1754. // Initialize
  1755. let inputState = z0M[0][0];
  1756. let currentFrame = inputState.rl;
  1757. let playerID = K$h[0][0].m_userData.arrayID;
  1758. let capID = K$h[1];
  1759. let sendObj = { capID: capID, playerID: playerID, currentFrame: currentFrame };
  1760. if (window.bonkAPI.events.hasEvent["capZoneEvent"]) {
  1761. window.bonkAPI.events.fireEvent("capZoneEvent", sendObj);
  1762. }
  1763. } catch(err) {
  1764. console.error("ERROR: capZoneEvent");
  1765. console.error(err);
  1766. }`;
  1767.  
  1768. newSrc = newSrc.replace(orgCode, newCode);
  1769.  
  1770. //! Inject stepEvent fire
  1771. orgCode = `return z0M[720];`;
  1772. newCode = `
  1773. bonkAPI_stepEventTry: try {
  1774. let inputStateClone = JSON.parse(JSON.stringify(z0M[0][0]));
  1775. let currentFrame = inputStateClone.rl;
  1776. let gameStateClone = JSON.parse(JSON.stringify(z0M[720]));
  1777. let sendObj = { inputState: inputStateClone, gameState: gameStateClone, currentFrame: currentFrame };
  1778. if (window.bonkAPI.events.hasEvent["stepEvent"]) {
  1779. window.bonkAPI.events.fireEvent("stepEvent", sendObj);
  1780. }
  1781. } catch(err) {
  1782. console.error("ERROR: stepEvent");
  1783. console.error(err);
  1784. }
  1785. return z0M[720];`;
  1786.  
  1787. newSrc = newSrc.replace(orgCode, newCode);
  1788.  
  1789. //! Inject frameIncEvent fire
  1790. //TODO: update to bonk 49
  1791. orgCode = `Y3z[8]++;`;
  1792. newCode = `
  1793. Y3z[8]++;
  1794. bonkAPI_frameIncEventTry: try {
  1795. if (window.bonkAPI.events.hasEvent["frameIncEvent"]) {
  1796. var sendObj = { frame: Y3z[8], gameStates: o3x[7] };
  1797. window.bonkAPI.events.fireEvent("frameIncEvent", sendObj);
  1798. }
  1799. } catch(err) {
  1800. console.error("ERROR: frameIncEvent");
  1801. console.error(err);
  1802. }`;
  1803.  
  1804. // newSrc = newSrc.replace(orgCode, newCode);
  1805. return newSrc;
  1806. };
  1807.  
  1808. // Compatibility with Excigma's code injector userscript
  1809. if (!window.bonkCodeInjectors) window.bonkCodeInjectors = [];
  1810. window.bonkCodeInjectors.push((bonkCode) => {
  1811. try {
  1812. return bonkAPI.injector(bonkCode);
  1813. } catch (error) {
  1814. alert(`Injecting failed, BonkAPI may lose some functionality. This may be due to an update by Chaz.`);
  1815. throw error;
  1816. }
  1817. });
  1818. // TODO: these could be dangerous, maybe add some sanitization
  1819. // *Send a packet to server
  1820. /**
  1821. * Sends the given packet to bonk servers.
  1822. * @function bonkAPI.sendPacket
  1823. * @param {string} packet - Packet to send to bonk
  1824. */
  1825. bonkAPI.sendPacket = function (packet) {
  1826. if (bonkAPI.bonkWSS != 0) {
  1827. bonkAPI.bonkWSS.send(packet);
  1828. }
  1829. };
  1830.  
  1831. // *Make client receive a packet
  1832. /**
  1833. * Makes your client receive the given packet.
  1834. * @function bonkAPI.receivePacket
  1835. * @param {string} packet - Packet that is received
  1836. */
  1837. bonkAPI.receivePacket = function (packet) {
  1838. if (bonkAPI.bonkWSS != 0) {
  1839. bonkAPI.bonkWSS.onmessage({ data: packet });
  1840. }
  1841. };
  1842. bonkHUD.createWindow = function (windowName, windowContent, opts = {}) {
  1843. //* leaving this for backwards compatability fr
  1844. let id = "bonkHUD_window_" + windowName;
  1845. let modVersion = "1.0.0";
  1846. if(opts.hasOwnProperty("windowId")) {
  1847. id = opts.windowId
  1848. }
  1849. if(opts.hasOwnProperty("modVersion")) {
  1850. modVersion = opts.modVersion
  1851. }
  1852. if(opts.hasOwnProperty("bonkLIBVersion")) {
  1853. if(opts.bonkLIBVersion != bonkLIB.version) {
  1854. if(typeof opts.bonkLIBVersion === 'string') {
  1855. if(opts.bonkLIBVersion.substring(0, opts.bonkLIBVersion.lastIndexOf(".")) != bonkLIB.version.substring(0, bonkLIB.version.lastIndexOf(".")))
  1856. alert(windowName + " may not be compatible with current version of BonkLIB ("+opts.bonkLIBVersion+" =/= "+bonkLIB.version+")");
  1857. console.log(windowName + " may not be compatible with current version of BonkLIB ("+opts.bonkLIBVersion+" =/= "+bonkLIB.version+")");
  1858. }
  1859. else {
  1860. alert("Version is incompatible, please check with mod maker to fix");
  1861. }
  1862. }
  1863. }
  1864. //! ignoring for now
  1865. /*if(opts.hasOwnProperty("bonkVersion")) {
  1866. }*/
  1867. let idCounter = 0
  1868. while(document.getElementById(id) != null) {
  1869. id = "bonkHUD_window_" + windowName + idCounter
  1870. idCounter++
  1871. }
  1872.  
  1873. //(name, id, recVersion, bodyHTML, settingElement = 0) {
  1874. let ind = bonkHUD.settingsHold.length;
  1875. bonkHUD.settingsHold.push(id)
  1876. bonkHUD.windowHold[ind] = { id: id };
  1877. bonkHUD.windowHold[ind] = bonkHUD.getUISetting(ind)
  1878.  
  1879. // Create Settings controller
  1880. let fullSettingsDiv = document.createElement("div");
  1881. bonkHUD.createWindowControl(ind, fullSettingsDiv);
  1882. if(opts.hasOwnProperty("settingsContent")) {
  1883. bonkHUD.createSettingsControl(opts.settingsContent, fullSettingsDiv);
  1884. }
  1885. bonkHUD.createMenuHeader(windowName, fullSettingsDiv, modVersion);
  1886.  
  1887. //! POSSIBLY MOVE EVERYTHING ABOVE TO createMod TO MAKE CLEANER BUT NOT BACKWARDS COMPATIBLE
  1888. // Create the main container 'dragItem'
  1889. let dragItem = document.createElement("div");
  1890. dragItem.classList.add("bonkhud-window-container");
  1891. dragItem.classList.add("bonkhud-background-color");
  1892. dragItem.classList.add("windowShadow");
  1893. dragItem.id = id + "-drag";
  1894. dragItem.style.overflowX = "hidden";
  1895. dragItem.style.overflowY = "hidden";
  1896. dragItem.style.bottom = bonkHUD.windowHold[ind].bottom; //top ? top : "0";
  1897. dragItem.style.right = bonkHUD.windowHold[ind].right; //left ? left : "0";
  1898. dragItem.style.width = bonkHUD.windowHold[ind].width; //width ? width : "172";
  1899. dragItem.style.height = bonkHUD.windowHold[ind].height; //height ? height : minHeight;
  1900. //dragItem.style.minHeight = minHeight; // Minimum height to prevent deformation
  1901. dragItem.style.display = bonkHUD.windowHold[ind].display;
  1902. dragItem.style.visibility = "visible";
  1903. dragItem.style.opacity = bonkHUD.windowHold[ind].opacity;
  1904.  
  1905. let dragNW = document.createElement("div");
  1906. dragNW.classList.add("bonkhud-resizer");
  1907. dragNW.classList.add("north-west");
  1908.  
  1909. let dragNE = document.createElement("div");
  1910. dragNE.classList.add("bonkhud-resizer");
  1911. dragNE.classList.add("north-east");
  1912.  
  1913. let dragSE = document.createElement("div");
  1914. dragSE.classList.add("bonkhud-resizer");
  1915. dragSE.classList.add("south-east");
  1916.  
  1917. let dragSW = document.createElement("div");
  1918. dragSW.classList.add("bonkhud-resizer");
  1919. dragSW.classList.add("south-west");
  1920.  
  1921. // Create the header
  1922. let header = document.createElement("div");
  1923. header.classList.add("bonkhud-drag-header");
  1924. header.classList.add("newbonklobby_boxtop");
  1925. header.classList.add("newbonklobby_boxtop_classic");
  1926. header.classList.add("bonkhud-header-color");
  1927. header.style.borderRadius = "0px";
  1928. header.style.visibility = "visible";
  1929.  
  1930. // Create the title span
  1931. let title = document.createElement("span");
  1932. title.classList.add("bonkhud-drag-header");
  1933. title.classList.add("bonkhud-title-color");
  1934. title.textContent = windowName;
  1935. title.style.flexGrow = "1";
  1936. title.style.textAlign = "center";
  1937.  
  1938. // Create the resize button
  1939. let openCloseButton = document.createElement("div");
  1940. openCloseButton.classList.add("bonkhud-header-button");
  1941. openCloseButton.classList.add("bonkhud-title-color");
  1942. openCloseButton.classList.add("bonkhud-resize");
  1943. openCloseButton.innerText = "△"; // Use an appropriate icon or text
  1944. openCloseButton.style.fontSize = "15px";
  1945. openCloseButton.style.lineHeight = "25px";
  1946. openCloseButton.style.textIndent = "5px";
  1947. openCloseButton.style.cursor = "cell";
  1948.  
  1949. let closeButton = document.createElement("div");
  1950. closeButton.classList.add("bonkhud-header-button");
  1951. closeButton.classList.add("bonkhud-title-color");
  1952. closeButton.innerText = "_"; // Use an appropriate icon or text
  1953. closeButton.style.lineHeight = "9px";
  1954. closeButton.style.right = "3px";
  1955. closeButton.style.cursor = "pointer";
  1956.  
  1957. // Append the title and resize button to the header
  1958. header.appendChild(title);
  1959. header.appendChild(openCloseButton);
  1960. header.appendChild(closeButton);
  1961.  
  1962. // Append the header to the dragItem
  1963. dragItem.appendChild(dragNW);
  1964. dragItem.appendChild(dragNE);
  1965. dragItem.appendChild(dragSE);
  1966. dragItem.appendChild(dragSW);
  1967. dragItem.appendChild(header);
  1968.  
  1969. // Create the key table
  1970. windowContent.id = id;
  1971. windowContent.classList.add("bonkhud-text-color");
  1972. windowContent.classList.add("bonkhud-scrollbar-kit");
  1973. windowContent.classList.add("bonkhud-scrollbar-other");
  1974. windowContent.style.overflowY = "scroll";
  1975. windowContent.style.padding = "5px";
  1976. windowContent.style.width = "calc(100% - 10px)";
  1977. windowContent.style.height = "calc(100% - 42px)"; // Adjusted height for header
  1978.  
  1979. // Append the content to the dragItem
  1980. dragItem.appendChild(windowContent);
  1981.  
  1982. // Append the dragItem to the body of the page
  1983. document.body.appendChild(dragItem);
  1984.  
  1985. closeButton.addEventListener('click', (e) => {
  1986. dragItem.style.display = "none";
  1987. let visCheck = document.getElementById(id + "-visibility-check");
  1988. visCheck.checked = false;
  1989. bonkHUD.windowHold[ind].display = dragItem.style.display;
  1990. bonkHUD.saveUISetting(ind);
  1991. });
  1992.  
  1993. // Add event listeners for dragging
  1994. dragItem.addEventListener('mousedown', (e) => bonkHUD.dragStart(e, dragItem, ind));
  1995.  
  1996. // Add event listeners for resizing
  1997. openCloseButton.addEventListener('mousedown', (e) => {
  1998. if(openCloseButton.innerText == "△") {
  1999. dragItem.style.visibility = "hidden";
  2000. header.style.borderRadius = "8px";
  2001. openCloseButton.innerText = "▽";
  2002. } else {
  2003. dragItem.style.visibility = "visible";
  2004. header.style.borderRadius = "0px";
  2005. openCloseButton.innerText = "△";
  2006. }
  2007. });
  2008. dragNW.addEventListener('mousedown', (e) => bonkHUD.startResizing(e, dragItem, "nw", ind));
  2009. dragNE.addEventListener('mousedown', (e) => bonkHUD.startResizing(e, dragItem, "ne", ind));
  2010. dragSE.addEventListener('mousedown', (e) => bonkHUD.startResizing(e, dragItem, "se", ind));
  2011. dragSW.addEventListener('mousedown', (e) => bonkHUD.startResizing(e, dragItem, "sw", ind));
  2012.  
  2013. bonkHUD.updateStyleSettings(); //! probably slow but it works, its not like someone will have 100's of windows
  2014.  
  2015. return ind;
  2016. };
  2017.  
  2018. bonkHUD.createMod = function (modName, opts = {}) {
  2019. if(opts.hasOwnProperty("bonkLIBVersion")) {
  2020. if(opts.bonkLIBVersion != bonkLIB.version) {
  2021. if(typeof opts.bonkLIBVersion === 'string') {
  2022. if(opts.bonkLIBVersion.substring(0, opts.bonkLIBVersion.lastIndexOf(".")) != bonkLIB.version.substring(0, bonkLIB.version.lastIndexOf(".")))
  2023. alert(windowName + " may not be compatible with current version of BonkLIB ("+opts.bonkLIBVersion+" =/= "+bonkLIB.version+")");
  2024. console.log(windowName + " may not be compatible with current version of BonkLIB ("+opts.bonkLIBVersion+" =/= "+bonkLIB.version+")");
  2025. }
  2026. else {
  2027. alert("Version is incompatible, please check with mod maker to fix");
  2028. }
  2029. }
  2030. }
  2031.  
  2032. if(opts.hasOwnProperty("noWindow") && opts.noWindow) {
  2033. let id = modName;
  2034. let modVersion = "1.0.0";
  2035. if(opts.hasOwnProperty("modVersion")) {
  2036. modVersion = opts.modVersion;
  2037. }
  2038.  
  2039. let ind = bonkHUD.settingsHold.length;
  2040. bonkHUD.settingsHold.push(id)
  2041.  
  2042. // Create Settings controller
  2043. let fullSettingsDiv = document.createElement("div");
  2044. if(opts.hasOwnProperty("settingsContent")) {
  2045. bonkHUD.createSettingsControl(opts.settingsContent, fullSettingsDiv);
  2046. }
  2047. bonkHUD.createMenuHeader(modName, fullSettingsDiv, modVersion);
  2048. return ind;
  2049. } else {
  2050. if(opts.hasOwnProperty("windowContent")) {
  2051. return bonkHUD.createWindow(modName, opts.windowContent, opts);
  2052. }
  2053. }
  2054. };
  2055. bonkHUD.dragStart = function (e, dragItem, ind) {
  2056. bonkHUD.focusWindow(dragItem);
  2057. // Prevents dragging from starting on the opacity slider
  2058. if (e.target.classList.contains("bonkhud-drag-header") && !e.target.classList.contains("bonkhud-resize")) {
  2059. let startX = e.clientX;
  2060. let startY = e.clientY;
  2061. let startRight = parseInt(window.getComputedStyle(dragItem).right, 10);
  2062. let startBottom = parseInt(window.getComputedStyle(dragItem).bottom, 10);
  2063. const boundDragMove = bonkHUD.dragMove.bind(null, startX, startY, startRight, startBottom, dragItem);
  2064. document.addEventListener('mousemove', boundDragMove);
  2065. document.addEventListener('mouseup', () => bonkHUD.dragEnd(boundDragMove, dragItem, ind), { once: true });
  2066. }
  2067. };
  2068.  
  2069. bonkHUD.dragMove = function (startX, startY, startRight, startBottom, dragItem, e) {
  2070. let w = parseFloat(window.getComputedStyle(dragItem).width) / 2;
  2071. let h = parseFloat(window.getComputedStyle(dragItem).height) / 2;
  2072. let moveX = bonkHUD.clamp(startRight + startX - e.clientX, -w, window.innerWidth - w);
  2073. let moveY = bonkHUD.clamp(startBottom + startY - e.clientY, -h, window.innerHeight - h * 2 + 15);
  2074. dragItem.style.right = bonkHUD.pxTorem(moveX) + "rem";
  2075. dragItem.style.bottom = bonkHUD.pxTorem(moveY) + "rem";
  2076. };
  2077.  
  2078. bonkHUD.dragEnd = function (dragMoveFn, dragItem, ind) {
  2079. document.removeEventListener('mousemove', dragMoveFn);
  2080. bonkHUD.windowHold[ind].width = dragItem.style.width;
  2081. bonkHUD.windowHold[ind].height = dragItem.style.height;
  2082. bonkHUD.windowHold[ind].bottom = dragItem.style.bottom;
  2083. bonkHUD.windowHold[ind].right = dragItem.style.right;
  2084. bonkHUD.saveUISetting(ind);
  2085. };
  2086. // !Right now only useful for mods that have a setting that **only**
  2087. // !needs to be read from
  2088.  
  2089. bonkHUD.saveModSetting = function (ind, obj) {
  2090. let save_id = 'bonkHUD_Mod_Setting_' + bonkHUD.settingsHold[ind];
  2091. localStorage.setItem(save_id, JSON.stringify(obj));
  2092. };
  2093.  
  2094. bonkHUD.getModSetting = function (ind) {
  2095. let save_id = 'bonkHUD_Mod_Setting_' + bonkHUD.settingsHold[ind];
  2096. let setting = JSON.parse(localStorage.getItem(save_id));
  2097. if (!setting) {
  2098. // !let mod maker handle it
  2099. return null;
  2100. }
  2101. return setting;
  2102. };
  2103.  
  2104. /*bonkHUD.loadModSetting = function (id) {
  2105. let windowElement = document.getElementById(id + "-drag");
  2106. if (windowElement) {
  2107. Object.assign(windowElement.style, bonkHUD.getUISetting(id));
  2108. } else {
  2109. console.log(`bonkHUD.loadModSetting: Window element not found for id: ${id}. Please ensure the window has been created.`);
  2110. }
  2111. };*/
  2112.  
  2113. bonkHUD.resetModSetting = function (ind) {
  2114. try {
  2115. let save_id = 'bonkHUD_Mod_Setting_' + bonkHUD.settingsHold[ind];
  2116. localStorage.removeItem(save_id);
  2117. //Object.assign(windowElement.style, bonkHUD.getUISetting(id));
  2118. } catch(er) {
  2119. console.log(`bonkHUD.resetModSetting: Settings for ${bonkHUD.settingsHold[ind]} were not found.`);
  2120. }
  2121. };
  2122.  
  2123. bonkHUD.createSettingsControl = function (settingsElement, element) {
  2124. element.appendChild(settingsElement)
  2125. //bonkHUD.settingsHold[ind].settings.appendChild(settingsElement);
  2126. };
  2127. // Function to start resizing the UI
  2128. bonkHUD.startResizing = function (e, dragItem, dir, ind) {
  2129. e.stopPropagation(); // Prevent triggering dragStart for dragItem
  2130.  
  2131. let startX = e.clientX;
  2132. let startY = e.clientY;
  2133. let windowX = parseInt(window.getComputedStyle(dragItem).right, 10);
  2134. let windowY = parseInt(window.getComputedStyle(dragItem).bottom, 10);
  2135. let startWidth = parseInt(window.getComputedStyle(dragItem).width, 10);
  2136. let startHeight = parseInt(window.getComputedStyle(dragItem).height, 10);
  2137.  
  2138. function doResize(e) {
  2139. bonkHUD.resizeMove(e, startX, startY, windowX, windowY, startWidth, startHeight, dragItem, dir);
  2140. }
  2141.  
  2142. function stopResizing() {
  2143. bonkHUD.resizeEnd(doResize, dragItem, ind);
  2144. }
  2145.  
  2146. document.addEventListener('mousemove', doResize);
  2147. document.addEventListener('mouseup', stopResizing, { once: true });
  2148. };
  2149.  
  2150. // Function to handle the resize event
  2151. bonkHUD.resizeMove = function (e, startX, startY, windowX, windowY, startWidth, startHeight, dragItem, dir) {
  2152. let newWidth = 0;
  2153. let newHeight = 0;
  2154. if(dir == "nw") {
  2155. newWidth = startWidth - (e.clientX - startX);
  2156. newHeight = startHeight - (e.clientY - startY);
  2157. dragItem.style.height = bonkHUD.pxTorem(Math.max(30, newHeight)) + 'rem';
  2158. dragItem.style.width = bonkHUD.pxTorem(Math.max(154, newWidth)) + 'rem';
  2159. } else if(dir == "sw") {
  2160. newWidth = startWidth - (e.clientX - startX);
  2161. newHeight = startHeight + (e.clientY - startY);
  2162. dragItem.style.height = bonkHUD.pxTorem(Math.max(30, newHeight)) + 'rem';
  2163. dragItem.style.bottom = bonkHUD.pxTorem(windowY - (newHeight < 30 ? 30 - startHeight : e.clientY - startY)) + 'rem';
  2164. dragItem.style.width = bonkHUD.pxTorem(Math.max(154, newWidth)) + 'rem';
  2165. } else if(dir == "ne") {
  2166. newWidth = startWidth + (e.clientX - startX);
  2167. newHeight = startHeight - (e.clientY - startY);
  2168. dragItem.style.height = bonkHUD.pxTorem(Math.max(30, newHeight)) + 'rem';
  2169. dragItem.style.width = bonkHUD.pxTorem(Math.max(154, newWidth)) + 'rem';
  2170. dragItem.style.right = bonkHUD.pxTorem(windowX - (newWidth < 154 ? 154 - startWidth : e.clientX - startX)) + 'rem';
  2171. } else {
  2172. newWidth = startWidth + (e.clientX - startX);
  2173. newHeight = startHeight + (e.clientY - startY);
  2174. dragItem.style.height = bonkHUD.pxTorem(Math.max(30, newHeight)) + 'rem';
  2175. dragItem.style.bottom = bonkHUD.pxTorem(windowY - (newHeight < 30 ? 30 - startHeight : e.clientY - startY)) + 'rem';
  2176. dragItem.style.width = bonkHUD.pxTorem(Math.max(154, newWidth)) + 'rem';
  2177. dragItem.style.right = bonkHUD.pxTorem(windowX - (newWidth < 154 ? 154 - startWidth : e.clientX - startX)) + 'rem';
  2178. }
  2179. };
  2180.  
  2181. // Function to stop the resize event
  2182. bonkHUD.resizeEnd = function (resizeMoveFn, dragItem, ind) {
  2183. document.removeEventListener('mousemove', resizeMoveFn);
  2184. //let ind = bonkHUD.getWindowIndexByID(dragItem.id.substring(0, dragItem.id.length - 5));
  2185. bonkHUD.windowHold[ind].width = dragItem.style.width;
  2186. bonkHUD.windowHold[ind].height = dragItem.style.height;
  2187. bonkHUD.windowHold[ind].bottom = dragItem.style.bottom;
  2188. bonkHUD.windowHold[ind].right = dragItem.style.right;
  2189. bonkHUD.saveUISetting(ind);
  2190. };
  2191. bonkHUD.saveStyleSettings = function () {
  2192. localStorage.setItem('bonkHUD_Style_Settings', JSON.stringify(bonkHUD.styleHold));
  2193. };
  2194.  
  2195. bonkHUD.exportStyleSettings = function() {
  2196. let exportStyleHold = [];
  2197. for(let prop in bonkHUD.styleHold) {
  2198. exportStyleHold.push(bonkHUD.styleHold[prop].color);
  2199. }
  2200. let out = JSON.stringify(exportStyleHold);
  2201. let save = new File([out], "bonkHUDStyle-" + Date.now() + ".style", {type: 'text/plain',});
  2202.  
  2203. let url = URL.createObjectURL(save);
  2204. let link = document.createElement("a");
  2205. link.href = url;
  2206. link.download = save.name;
  2207. document.body.appendChild(link);
  2208. link.click();
  2209.  
  2210. document.body.removeChild(link);
  2211. window.URL.revokeObjectURL(url);
  2212. }
  2213.  
  2214. bonkHUD.importStyleSettings = function(event) {
  2215. if(!event || !event.target || !event.target.files || event.target.files.length === 0) {
  2216. return;
  2217. }
  2218. let fileReader = new FileReader();
  2219. fileReader.addEventListener("load", (e) => {
  2220. let tempStyleHold = {};
  2221. try {
  2222. let temp = JSON.parse(e.target.result);
  2223. let i = 0;
  2224. for(let prop in bonkHUD.styleHold) {
  2225. tempStyleHold[prop] = {};
  2226. tempStyleHold[prop].class = bonkHUD.styleHold[prop].class;
  2227. tempStyleHold[prop].css = bonkHUD.styleHold[prop].css;
  2228. if(typeof temp[i] == "string" && temp[i].charAt(0) === "#" && !isNaN(Number("0x" + temp[i].substring(1, 7)))) {
  2229. tempStyleHold[prop].color = temp[i];
  2230. } else {
  2231. throw new Error("Incorrect style input");
  2232. }
  2233. i++;
  2234. }
  2235. bonkHUD.loadStyleSettings(tempStyleHold);
  2236. bonkHUD.updateStyleSettings();
  2237. bonkHUD.saveStyleSettings();
  2238. } catch (er) {
  2239. alert(er);
  2240. }
  2241. }, false);
  2242. //let file = event.target.files[0];
  2243. fileReader.readAsText(event.target.files[0]);
  2244. }
  2245.  
  2246. bonkHUD.loadStyleSettings = function (settings) {
  2247. if(!settings) {
  2248. settings = JSON.parse(localStorage.getItem('bonkHUD_Style_Settings'));
  2249. }
  2250. if (settings) {
  2251. bonkHUD.styleHold = {};
  2252. for (let prop in settings) {
  2253. bonkHUD.styleHold[prop] = settings[prop];
  2254. }
  2255. }
  2256. else {
  2257. bonkHUD.resetStyleSettings();
  2258. }
  2259. };
  2260.  
  2261. bonkHUD.resetStyleSettings = function () {
  2262. localStorage.removeItem('bonkHUD_Style_Settings');
  2263. //Add bonkhud to key for class name
  2264. bonkHUD.styleHold = {
  2265. backgroundColor: {class:"bonkhud-background-color", css:"background-color", color:"#cfd8cd"},
  2266. borderColor: {class:"bonkhud-border-color", css:"border-color", color:"#b4b8ae"},
  2267. headerColor: {class:"bonkhud-header-color", css:"background-color", color:"#009688"},
  2268. titleColor: {class:"bonkhud-title-color", css:"color", color:"#ffffff"},
  2269. textColor: {class:"bonkhud-text-color", css:"color", color:"#000000"},
  2270. secondaryTextColor: {class:"bonkhud-secondary-text-color", css:"color", color:"#505050"},
  2271. buttonColor: {class:"bonkhud-button-color", css:"background-color", color:"#bcc4bb"},
  2272. buttonColorHover: {class:"bonkhud-button-color-hover", css:"background-color", color:"#acb9ad"},
  2273. };
  2274. };
  2275.  
  2276. bonkHUD.updateStyleSettings = function () {
  2277. for(let prop in bonkHUD.styleHold) {
  2278. try {
  2279. let colorEdit = document.getElementById("bonkhud-" + prop + "-edit");
  2280. colorEdit.value = bonkHUD.styleHold[prop].color;
  2281. } catch (er) {
  2282. console.log("Element bonkhud-" + prop + "-edit does not exist");
  2283. }
  2284.  
  2285. if(prop == "buttonColorHover")
  2286. continue;
  2287. else if(prop == "headerColor") {
  2288. let elements = document.getElementsByClassName(bonkHUD.styleHold[prop].class);
  2289. for (let j = 0; j < elements.length; j++) {
  2290. elements[j].style.setProperty(bonkHUD.styleHold[prop].css, bonkHUD.styleHold[prop].color, "important");
  2291. }
  2292. continue;
  2293. }
  2294. else {
  2295. let elements = document.getElementsByClassName(bonkHUD.styleHold[prop].class);
  2296. for (let j = 0; j < elements.length; j++) {
  2297. elements[j].style.setProperty(bonkHUD.styleHold[prop].css, bonkHUD.styleHold[prop].color);
  2298. }
  2299. }
  2300. }
  2301. };
  2302. bonkHUD.saveUISetting = function (ind) {
  2303. let save_id = 'bonkHUD_Setting_' + bonkHUD.windowHold[ind].id;
  2304. localStorage.setItem(save_id, JSON.stringify(bonkHUD.windowHold[ind]));
  2305. };
  2306.  
  2307. bonkHUD.getUISetting = function (ind) {
  2308. let save_id = 'bonkHUD_Setting_' + bonkHUD.windowHold[ind].id;
  2309. let setting = JSON.parse(localStorage.getItem(save_id));
  2310. if (!setting) {
  2311. setting = {
  2312. id: bonkHUD.windowHold[ind].id,
  2313. width: "154px",
  2314. height: "100px",
  2315. bottom: "0rem",
  2316. right: "0rem",
  2317. opacity: "1",
  2318. display: "block",
  2319. }
  2320. }
  2321. return setting;
  2322. };
  2323.  
  2324. bonkHUD.loadUISetting = function (ind) {
  2325. let windowElement = document.getElementById(bonkHUD.windowHold[ind].id + "-drag");
  2326. if (windowElement) {
  2327. Object.assign(windowElement.style, bonkHUD.getUISetting(ind));
  2328. } else {
  2329. console.log(`bonkHUD.loadUISetting: Window element not found for id: ${bonkHUD.windowHold[ind].id}. Please ensure the window has been created.`);
  2330. }
  2331. };
  2332.  
  2333. bonkHUD.resetUISetting = function (ind) {
  2334. let windowElement = document.getElementById(bonkHUD.windowHold[ind].id + "-drag");
  2335. if (windowElement) {
  2336. let save_id = 'bonkHUD_Setting_' + bonkHUD.windowHold[ind].id;
  2337. localStorage.removeItem(save_id);
  2338. Object.assign(windowElement.style, bonkHUD.getUISetting(ind));
  2339. } else {
  2340. console.log(`bonkHUD.resetUISetting: Window element not found for id: ${bonkHUD.windowHold[ind].id}. Please ensure the window has been created.`);
  2341. }
  2342. };
  2343. //! Eventually change ID to Id
  2344. bonkHUD.getWindowIndexByID = function (id) {
  2345. for (let i = 0; i < bonkHUD.windowHold.length; i++) {
  2346. if (bonkHUD.windowHold[i].id == id) {
  2347. return i;
  2348. }
  2349. }
  2350. return -1;
  2351. };
  2352.  
  2353. bonkHUD.getWindowIdByIndex = function (ind) {
  2354. return bonkHUD.windowHold[ind].id
  2355. }
  2356.  
  2357. bonkHUD.getElementByIndex = function (ind) {
  2358. return document.getElementById(bonkHUD.windowHold[ind].id)
  2359. }
  2360.  
  2361. bonkHUD.clamp = function (val, min, max) {
  2362. //? supposedly faster than Math.max/min
  2363. if (val > min) {
  2364. if (val < max) {
  2365. return val;
  2366. }
  2367. else {
  2368. return max;
  2369. }
  2370. }
  2371. return min;
  2372. };
  2373.  
  2374. bonkHUD.pxTorem = function (px) {
  2375. return px / parseFloat(getComputedStyle(document.documentElement).fontSize);
  2376. };
  2377.  
  2378. bonkHUD.remTopx = function (rem) {
  2379. return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
  2380. };
  2381. bonkHUD.generateButton = function (name) {
  2382. let newButton = document.createElement("div");
  2383. newButton.classList.add("bonkhud-button-color");
  2384. newButton.classList.add("bonkhud-text-color");
  2385. newButton.style.cursor = "pointer";
  2386. newButton.style.borderRadius = "3px";
  2387. newButton.style.textAlign = "center";
  2388. newButton.style.backgroundColor = bonkHUD.styleHold.buttonColor.color;
  2389. newButton.innerText = name;
  2390.  
  2391. newButton.addEventListener('mouseover', (e) => {
  2392. e.target.style.backgroundColor = bonkHUD.styleHold.buttonColorHover.color;
  2393. });
  2394. newButton.addEventListener('mouseleave', (e) => {
  2395. e.target.style.backgroundColor = bonkHUD.styleHold.buttonColor.color;
  2396. });
  2397. return newButton;
  2398. }
  2399.  
  2400. bonkHUD.generateSection = function () {
  2401. let sliderRow = document.createElement("div");
  2402. sliderRow.classList.add("bonkhud-settings-row");
  2403. sliderRow.classList.add("bonkhud-border-color");
  2404. return sliderRow;
  2405. }
  2406. bonkHUD.initialize = function () {
  2407. //bonkHUD.stylesheet = document.createElement("style");
  2408. let settingsMenu = document.createElement("div");
  2409. settingsMenu.id = "bonkhud-settings";
  2410. settingsMenu.classList.add("bonkhud-background-color");
  2411. settingsMenu.classList.add("windowShadow");
  2412. settingsMenu.style.position = "absolute";
  2413. settingsMenu.style.top = "0";
  2414. settingsMenu.style.left = "0";
  2415. settingsMenu.style.right = "0";
  2416. settingsMenu.style.bottom = "0";
  2417. settingsMenu.style.width = "60%";//bonkHUD.pxTorem(450) + "rem";
  2418. settingsMenu.style.height = "75%";//bonkHUD.pxTorem(385) + "rem";
  2419. settingsMenu.style.fontFamily = "futurept_b1";
  2420. settingsMenu.style.margin = "auto";
  2421. settingsMenu.style.borderRadius = "8px";
  2422. //settingsMenu.style.outline = "3000px solid rgba(0,0,0,0.30)";
  2423. settingsMenu.style.pointerEvents = "auto";
  2424. settingsMenu.style.zIndex = "9992";
  2425. settingsMenu.style.visibility = "hidden";
  2426.  
  2427. // Create the header
  2428. let header = document.createElement("div");
  2429. header.classList.add("newbonklobby_boxtop");
  2430. header.classList.add("newbonklobby_boxtop_classic");
  2431. header.classList.add("bonkhud-header-color");
  2432.  
  2433. // Create the title span
  2434. let title = document.createElement("span");
  2435. title.classList.add("bonkhud-title-color");
  2436. title.textContent = "BonkHUD Settings";
  2437. title.style.flexGrow = "1";
  2438. title.style.textAlign = "center";
  2439.  
  2440. let closeButton = document.createElement("div");
  2441. closeButton.classList.add("bonkhud-header-button");
  2442. closeButton.classList.add("bonkhud-title-color");
  2443. closeButton.innerText = "_"; // Use an appropriate icon or text
  2444. closeButton.style.lineHeight = "9px";
  2445. closeButton.style.right = "3px";
  2446. closeButton.style.cursor = "pointer";
  2447.  
  2448. let containerContainer = document.createElement("div");
  2449. containerContainer.classList.add("bonkhud-text-color");
  2450. containerContainer.style.overflowX = "hidden";
  2451. containerContainer.style.overflowY = "hidden";
  2452. containerContainer.style.display = "flex";
  2453. containerContainer.style.width = "100%";
  2454. containerContainer.style.height = "calc(100% - 32px)"; // Adjusted height for header
  2455.  
  2456. let windowSettingsContainer = document.createElement("div");
  2457. windowSettingsContainer.id = "bonkhud-window-settings-container";
  2458. windowSettingsContainer.classList.add("bonkhud-border-color");
  2459. windowSettingsContainer.classList.add("bonkhud-scrollbar-kit");
  2460. windowSettingsContainer.classList.add("bonkhud-scrollbar-other");
  2461. windowSettingsContainer.style.width = "35%";
  2462. windowSettingsContainer.style.overflowY = "scroll";
  2463. windowSettingsContainer.style.height = "100%";
  2464. windowSettingsContainer.style.borderRight = "1px solid";
  2465.  
  2466. let settingsContainer = document.createElement("div");
  2467. settingsContainer.classList.add("bonkhud-scrollbar-kit");
  2468. settingsContainer.classList.add("bonkhud-scrollbar-other");
  2469. settingsContainer.id = "bonkhud-settings-container";
  2470. settingsContainer.style.overflowY = "scroll";
  2471. settingsContainer.style.width = "65%";
  2472. settingsContainer.style.float = "right";
  2473. settingsContainer.style.height = "100%";
  2474.  
  2475. // Create holder for mainSettings and styleSettings
  2476. let generalSettingsDiv = document.createElement("div");
  2477.  
  2478. let mainSettingsDiv = document.createElement("div");
  2479. mainSettingsDiv.classList.add("bonkhud-border-color")
  2480. mainSettingsDiv.classList.add("bonkhud-settings-row");
  2481.  
  2482. let mainSettingsHeading = document.createElement("div");
  2483. mainSettingsHeading.classList.add("bonkhud-text-color");
  2484. mainSettingsHeading.style.fontSize = "1.2rem";
  2485. mainSettingsHeading.style.marginBottom = "5px";
  2486. mainSettingsHeading.textContent = "Main Settings";
  2487.  
  2488. let mainSettingsAdHideLabel = document.createElement("label");
  2489. mainSettingsAdHideLabel.classList.add("bonkhud-text-color");
  2490. mainSettingsAdHideLabel.classList.add("bonkhud-settings-label");
  2491. mainSettingsAdHideLabel.style.marginRight = "5px";
  2492. mainSettingsAdHideLabel.innerText = "Hide Ads";
  2493.  
  2494. let mainSettingsAdHide = document.createElement("input");
  2495. mainSettingsAdHide.type = "checkbox";
  2496. mainSettingsAdHide.checked = false;
  2497.  
  2498. let styleResetDiv = document.createElement("div");
  2499. styleResetDiv.style.marginTop = "5px";
  2500.  
  2501. let styleResetLabel = document.createElement("label");
  2502. styleResetLabel.classList.add("bonkhud-text-color");
  2503. styleResetLabel.classList.add("bonkhud-settings-label");
  2504. styleResetLabel.style.marginRight = "5px";
  2505. styleResetLabel.innerText = "Reset Style";
  2506.  
  2507. let styleResetButton = bonkHUD.generateButton("Reset");
  2508. styleResetButton.style.paddingLeft = "5px";
  2509. styleResetButton.style.paddingRight = "5px";
  2510. styleResetButton.style.display = "inline-block";
  2511.  
  2512. let styleExportDiv = document.createElement("div");
  2513. styleExportDiv.style.marginTop = "5px";
  2514.  
  2515. let styleExportLabel = document.createElement("label");
  2516. styleExportLabel.classList.add("bonkhud-text-color");
  2517. styleExportLabel.classList.add("bonkhud-settings-label");
  2518. styleExportLabel.style.marginRight = "5px";
  2519. styleExportLabel.innerText = "Export Style";
  2520.  
  2521. let styleExportButton = bonkHUD.generateButton("Export");
  2522. styleExportButton.style.paddingLeft = "5px";
  2523. styleExportButton.style.paddingRight = "5px";
  2524. styleExportButton.style.display = "inline-block";
  2525.  
  2526. let styleImportDiv = document.createElement("div");
  2527. styleImportDiv.style.marginTop = "5px";
  2528.  
  2529. let styleImportLabel = document.createElement("label");
  2530. styleImportLabel.classList.add("bonkhud-text-color");
  2531. styleImportLabel.classList.add("bonkhud-settings-label");
  2532. styleImportLabel.style.marginRight = "5px";
  2533. styleImportLabel.innerText = "Import Style";
  2534.  
  2535. let styleImportButton = bonkHUD.generateButton("Import");
  2536. styleImportButton.style.paddingLeft = "5px";
  2537. styleImportButton.style.paddingRight = "5px";
  2538. styleImportButton.style.display = "inline-block";
  2539.  
  2540. let styleImportInput = document.createElement("input");
  2541. styleImportInput.setAttribute("type", "file");
  2542. styleImportInput.setAttribute("accept", ".style");
  2543. styleImportInput.setAttribute("multiple", "");
  2544. styleImportInput.setAttribute("onChange", "bonkHUD.importStyleSettings(event);this.value=null");
  2545. styleImportInput.style.display = "none";
  2546.  
  2547. let styleSettingsDiv = document.createElement("div");
  2548. styleSettingsDiv.classList.add("bonkhud-border-color")
  2549. styleSettingsDiv.classList.add("bonkhud-settings-row");
  2550.  
  2551. let styleSettingsHeading = document.createElement("div");
  2552. styleSettingsHeading.classList.add("bonkhud-text-color");
  2553. styleSettingsHeading.style.fontSize = "1.2rem";
  2554. styleSettingsHeading.style.marginBottom = "5px";
  2555. styleSettingsHeading.textContent = "Style Settings";
  2556.  
  2557. mainSettingsDiv.appendChild(mainSettingsHeading);
  2558. mainSettingsDiv.appendChild(mainSettingsAdHideLabel);
  2559. mainSettingsDiv.appendChild(mainSettingsAdHide);
  2560.  
  2561. // Append children of style settings to rows
  2562. styleResetDiv.appendChild(styleResetLabel);
  2563. styleResetDiv.appendChild(styleResetButton);
  2564. styleExportDiv.appendChild(styleExportLabel);
  2565. styleExportDiv.appendChild(styleExportButton);
  2566. styleImportDiv.appendChild(styleImportLabel);
  2567. styleImportDiv.appendChild(styleImportButton);
  2568. styleImportDiv.appendChild(styleImportInput);
  2569.  
  2570. styleSettingsDiv.appendChild(styleSettingsHeading);
  2571. styleSettingsDiv.appendChild(styleResetDiv);
  2572. styleSettingsDiv.appendChild(styleExportDiv)
  2573. styleSettingsDiv.appendChild(styleImportDiv);
  2574.  
  2575. let holdLeft = document.createElement("div");
  2576. holdLeft.style.display = "flex";
  2577. holdLeft.style.alignContent = "center";
  2578.  
  2579. let opacityLabel = document.createElement("label");
  2580. opacityLabel.classList.add("bonkhud-settings-label");
  2581. opacityLabel.textContent = "Opacity";
  2582.  
  2583. let opacitySlider = document.createElement("input");
  2584. opacitySlider.type = "range"; // Slider type for range selection
  2585. opacitySlider.min = "0.1"; // Minimum opacity value
  2586. opacitySlider.max = "1"; // Maximum opacity value (fully opaque)
  2587. opacitySlider.step = "0.05"; // Incremental steps for opacity adjustment
  2588. opacitySlider.value = "1"; // Default value set to fully opaque
  2589. opacitySlider.style.minWidth = "20px";
  2590. opacitySlider.style.flexGrow = "1"; // Width adjusted for the label
  2591.  
  2592. holdLeft.appendChild(opacityLabel);
  2593. holdLeft.appendChild(opacitySlider);
  2594.  
  2595. styleSettingsDiv.appendChild(holdLeft);
  2596.  
  2597. for (let prop in bonkHUD.styleHold) {
  2598. let colorDiv = document.createElement("div");
  2599. colorDiv.style.marginTop="5px";
  2600.  
  2601. let colorLabel = document.createElement("label");
  2602. colorLabel.classList.add("bonkhud-text-color");
  2603. colorLabel.classList.add("bonkhud-settings-label");
  2604. colorLabel.style.marginRight = "10px";
  2605. colorLabel.innerText = bonkHUD.styleHold[prop].class;
  2606.  
  2607. let colorEdit = document.createElement("input");
  2608. colorEdit.setAttribute('type', 'color');
  2609. colorEdit.id = "bonkhud-" + prop + "-edit";
  2610. colorEdit.value = bonkHUD.styleHold[prop].color;
  2611. colorEdit.style.display = "inline-block";
  2612.  
  2613. colorDiv.appendChild(colorLabel);
  2614. colorDiv.appendChild(colorEdit);
  2615.  
  2616. styleSettingsDiv.appendChild(colorDiv);
  2617. colorEdit.addEventListener('change', (e) => {
  2618. bonkHUD.styleHold[prop].color = e.target.value;
  2619. bonkHUD.saveStyleSettings();
  2620. bonkHUD.updateStyleSettings();
  2621. });
  2622. }
  2623.  
  2624. let topBarButtons = document.querySelectorAll("#pretty_top_bar > .niceborderleft");
  2625. //Create element in top bar
  2626. let topBarOption = document.createElement("div");
  2627. topBarOption.style.width = "58px";
  2628. topBarOption.style.height = "34px";
  2629. topBarOption.style.backgroundRepeat = "no-repeat";
  2630. topBarOption.style.backgroundPosition = "center";
  2631. topBarOption.style.position = "absolute";
  2632. topBarOption.style.right = topBarButtons.length * 58 + 1 + "px";
  2633. topBarOption.style.top = "0";
  2634. topBarOption.style.visibility = "visible";
  2635. topBarOption.style.borderBottom = "2px solid transparent";
  2636. topBarOption.style.lineHeight = "34px";
  2637. topBarOption.style.textAlign = "center";
  2638. topBarOption.style.fontFamily = "futurept_b1";
  2639. topBarOption.style.color = "#ffffff";
  2640. topBarOption.classList.add("niceborderleft");
  2641. topBarOption.classList.add("pretty_top_button");
  2642.  
  2643. let topBarIcon = document.createElement("span");
  2644. topBarIcon.innerText = "HUD";
  2645.  
  2646. // Append Header
  2647. header.appendChild(title);
  2648. header.appendChild(closeButton)
  2649.  
  2650. // Append everything to main container (HUD window)
  2651. containerContainer.appendChild(windowSettingsContainer);
  2652. containerContainer.appendChild(settingsContainer);
  2653.  
  2654. settingsMenu.appendChild(header);
  2655. settingsMenu.appendChild(containerContainer);
  2656. topBarOption.appendChild(topBarIcon);
  2657.  
  2658. document.getElementById('prettymenu').appendChild(settingsMenu);
  2659. //Place it before help button
  2660. document.getElementById('pretty_top_bar').appendChild(topBarOption);
  2661.  
  2662. // Add settings
  2663. bonkHUD.createSettingsControl(mainSettingsDiv, generalSettingsDiv);
  2664. bonkHUD.createSettingsControl(styleSettingsDiv, generalSettingsDiv);
  2665. bonkHUD.createMenuHeader("General", generalSettingsDiv);
  2666.  
  2667. let ind = bonkHUD.settingsHold.length;
  2668. bonkHUD.settingsHold.push("bonkhud-main-mod-setting");
  2669. let settings = { hideAds: false, opacity: "1"};
  2670. let tempSettings = bonkHUD.getModSetting(ind);
  2671. if (tempSettings != null) {
  2672. settings = tempSettings;
  2673. // Could bring into one function then call it
  2674. mainSettingsAdHide.checked = settings.hideAds;
  2675. let ad1 = window.top.document.getElementById('adboxverticalCurse');
  2676. let ad2 = window.top.document.getElementById('adboxverticalleftCurse');
  2677. if (settings.hideAds) {
  2678. ad1.style.display = "none";
  2679. ad2.style.display = "none";
  2680. } else {
  2681. ad1.style.display = "block";
  2682. ad2.style.display = "block";
  2683. }
  2684.  
  2685. opacitySlider.value = settings.opacity;
  2686. settingsMenu.style.opacity = settings.opacity;
  2687. }
  2688.  
  2689. opacitySlider.oninput = function () {
  2690. settingsMenu.style.opacity = this.value;
  2691. settings.opacity = this.value;
  2692. bonkHUD.saveModSetting(ind, settings);
  2693. };
  2694.  
  2695. mainSettingsAdHide.oninput = function () {
  2696. settings.hideAds = this.checked;
  2697. let ad1 = window.top.document.getElementById('adboxverticalCurse');
  2698. let ad2 = window.top.document.getElementById('adboxverticalleftCurse');
  2699. if (settings.hideAds) {
  2700. ad1.style.display = "none";
  2701. ad2.style.display = "none";
  2702. } else {
  2703. ad1.style.display = "block";
  2704. ad2.style.display = "block";
  2705. }
  2706. bonkHUD.saveModSetting(ind, settings);
  2707. }
  2708.  
  2709. // Make menu to control opacity + visibility visible
  2710. closeButton.addEventListener('click', (e) => {
  2711. settingsMenu.style.visibility = "hidden";
  2712. })
  2713. topBarOption.addEventListener('click', (e) => {
  2714. if (settingsMenu.style.visibility == "hidden") {
  2715. settingsMenu.style.visibility = "visible";
  2716. }
  2717. else {
  2718. settingsMenu.style.visibility = "hidden";
  2719. }
  2720. });
  2721. styleResetButton.addEventListener('click', (e) => {
  2722. bonkHUD.resetStyleSettings();
  2723. bonkHUD.updateStyleSettings();
  2724. });
  2725. styleExportButton.addEventListener('click', (e) => {
  2726. bonkHUD.updateStyleSettings();
  2727. bonkHUD.exportStyleSettings();
  2728. });
  2729. styleImportButton.addEventListener('click', (e) => {
  2730. styleImportInput.click();
  2731. });
  2732. };
  2733. bonkHUD.createMenuHeader = function (name, settingsContent, recVersion = -1) {
  2734. // Create container for the opacity controls with initial styles
  2735. let sliderRow = bonkHUD.generateSection();
  2736.  
  2737. // Add a title to the slider row for visual clarity
  2738. let sliderTitle = document.createElement("div");
  2739. if (recVersion === -1) {
  2740. sliderTitle.textContent = name;
  2741. } else {
  2742. sliderTitle.textContent = name + " ("+recVersion+")";
  2743. }
  2744. sliderTitle.style.marginBottom = "5px";
  2745. sliderTitle.style.fontSize = "1.2rem"; // Text size for readability
  2746. sliderTitle.style.fontWeight = "bold"; // Make the title text bold
  2747. sliderRow.appendChild(sliderTitle); // Insert the title into the slider container
  2748.  
  2749. //open settings in
  2750. settingsContent.prepend(sliderRow.cloneNode(true));
  2751. settingsContent.classList.add("bonkhud-mod-setting-menu");
  2752. settingsContent.style.display = "none";
  2753. document.getElementById("bonkhud-settings-container").appendChild(settingsContent);
  2754.  
  2755. sliderRow.addEventListener("click", (e) => {
  2756. let menus = document.getElementsByClassName("bonkhud-mod-setting-menu");
  2757. // Could make this without for loop but would need to store last menu
  2758. for (let i = 0; i < menus.length; i++) {
  2759. menus[i].style.display = "none";
  2760. }
  2761. settingsContent.style.display = "block";
  2762.  
  2763. let titles = document.getElementById("bonkhud-window-settings-container").children;
  2764. for (let i = 0; i < titles.length; i++) {
  2765. titles[i].children[0].style.color = bonkHUD.styleHold.textColor.color;
  2766. }
  2767. sliderTitle.style.color = bonkHUD.styleHold.secondaryTextColor.color;
  2768. });
  2769.  
  2770. document.getElementById("bonkhud-window-settings-container").appendChild(sliderRow);
  2771. }
  2772.  
  2773. bonkHUD.createWindowControl = function (ind, element) {
  2774. let sliderRow = bonkHUD.generateSection();
  2775.  
  2776. let holdLeft = document.createElement("div");
  2777. holdLeft.style.display = "flex";
  2778. holdLeft.style.alignContent = "center";
  2779.  
  2780. // Create a label for the opacity slider for accessibility
  2781. let opacityLabel = document.createElement("label");
  2782. opacityLabel.classList.add("bonkhud-settings-label");
  2783. opacityLabel.textContent = "Opacity";
  2784. holdLeft.appendChild(opacityLabel); // Add the label to the slider container
  2785.  
  2786. // Create the opacity slider input, configuring its range and appearance
  2787. let opacitySlider = document.createElement("input");
  2788. opacitySlider.type = "range"; // Slider type for range selection
  2789. opacitySlider.min = "0.1"; // Minimum opacity value
  2790. opacitySlider.max = "1"; // Maximum opacity value (fully opaque)
  2791. opacitySlider.step = "0.05"; // Incremental steps for opacity adjustment
  2792. opacitySlider.value = bonkHUD.windowHold[ind].opacity; // Default value set to fully opaque
  2793. opacitySlider.style.minWidth = "20px";
  2794. opacitySlider.style.flexGrow = "1"; // Width adjusted for the label
  2795. opacitySlider.oninput = function () {
  2796. let control = document.getElementById(bonkHUD.windowHold[ind].id + "-drag"); // Update the UI opacity in real-time;
  2797. control.style.opacity = this.value;
  2798. bonkHUD.windowHold[ind].opacity = control.style.opacity;
  2799. bonkHUD.saveUISetting(ind);
  2800. };
  2801. holdLeft.appendChild(opacitySlider); // Place the slider into the slider container
  2802.  
  2803. let holdRight = document.createElement("div");
  2804. let visibilityLabel = document.createElement("label");
  2805. visibilityLabel.classList.add("bonkhud-settings-label");
  2806. visibilityLabel.textContent = "Visible";
  2807. visibilityLabel.style.marginRight = "5px"; // Space between label and slider
  2808. visibilityLabel.style.display = "inline-block"; // Allows margin-top adjustment
  2809. visibilityLabel.style.verticalAlign = "middle";
  2810. holdRight.appendChild(visibilityLabel);
  2811.  
  2812. let visiblityCheck = document.createElement("input");
  2813. visiblityCheck.id = bonkHUD.windowHold[ind].id + "-visibility-check";
  2814. visiblityCheck.type = "checkbox"; // Slider type for range selection
  2815. if (bonkHUD.windowHold[ind].display == "block") {
  2816. visiblityCheck.checked = true;
  2817. }
  2818. else {
  2819. visiblityCheck.checked = false;
  2820. }
  2821. visiblityCheck.style.display = "inline-block"; // Allows margin-top adjustment
  2822. visiblityCheck.style.verticalAlign = "middle";
  2823. visiblityCheck.oninput = function () {
  2824. let control = document.getElementById(bonkHUD.windowHold[ind].id + "-drag"); // Update the UI opacity in real-time;
  2825. control.style.display = this.checked ? "block" : "none";
  2826. bonkHUD.windowHold[ind].display = control.style.display;
  2827. bonkHUD.saveUISetting(ind);
  2828. };
  2829. holdRight.appendChild(visiblityCheck); // Place the slider into the slider container
  2830.  
  2831. let windowResetButton = bonkHUD.generateButton("Reset");
  2832. windowResetButton.style.paddingLeft = "5px";
  2833. windowResetButton.style.paddingRight = "5px";
  2834. windowResetButton.style.display = "inline-block";
  2835. windowResetButton.addEventListener('click', (e) => {
  2836. bonkHUD.resetUISetting(ind);
  2837. bonkHUD.loadUISetting(ind);
  2838. });
  2839.  
  2840. sliderRow.appendChild(holdLeft);
  2841. sliderRow.appendChild(holdRight);
  2842. sliderRow.appendChild(windowResetButton);
  2843.  
  2844. element.appendChild(sliderRow);
  2845. //bonkHUD.settingsHold[ind].settings.appendChild(sliderRow);
  2846. };
  2847.  
  2848. bonkHUD.focusWindow = function (focusItem) {
  2849. let elements = document.getElementsByClassName("bonkhud-window-container");
  2850. focusItem.style.zIndex = "9991";
  2851. for (let i = 0; i < elements.length; i++) {
  2852. if (focusItem.id != elements[i].id) {
  2853. elements[i].style.zIndex = "9990";
  2854. }
  2855. }
  2856. };
  2857.  
  2858. //!------------------Load Complete Detection------------------
  2859. bonkLIB.onLoaded = () => {
  2860. bonkAPI.originalDrawShape = window.PIXI.Graphics.prototype.drawShape;
  2861. bonkAPI.pixiCtx = new window.PIXI.Container();
  2862.  
  2863. // !Map Decoder
  2864. bonkAPI.LZString = window.LZString;
  2865. bonkAPI.PSON = window.dcodeIO.PSON;
  2866. bonkAPI.bytebuffer = window.dcodeIO.ByteBuffer;
  2867. bonkAPI.textdecoder = new window.TextDecoder();
  2868. bonkAPI.textencoder = new window.TextEncoder();
  2869. bonkAPI.ISpsonpair = new window.dcodeIO.PSON.StaticPair([
  2870. "physics",
  2871. "shapes",
  2872. "fixtures",
  2873. "bodies",
  2874. "bro",
  2875. "joints",
  2876. "ppm",
  2877. "lights",
  2878. "spawns",
  2879. "lasers",
  2880. "capZones",
  2881. "type",
  2882. "w",
  2883. "h",
  2884. "c",
  2885. "a",
  2886. "v",
  2887. "l",
  2888. "s",
  2889. "sh",
  2890. "fr",
  2891. "re",
  2892. "de",
  2893. "sn",
  2894. "fc",
  2895. "fm",
  2896. "f",
  2897. "d",
  2898. "n",
  2899. "bg",
  2900. "lv",
  2901. "av",
  2902. "ld",
  2903. "ad",
  2904. "fr",
  2905. "bu",
  2906. "cf",
  2907. "rv",
  2908. "p",
  2909. "d",
  2910. "bf",
  2911. "ba",
  2912. "bb",
  2913. "aa",
  2914. "ab",
  2915. "axa",
  2916. "dr",
  2917. "em",
  2918. "mmt",
  2919. "mms",
  2920. "ms",
  2921. "ut",
  2922. "lt",
  2923. "New body",
  2924. "Box Shape",
  2925. "Circle Shape",
  2926. "Polygon Shape",
  2927. "EdgeChain Shape",
  2928. "priority",
  2929. "Light",
  2930. "Laser",
  2931. "Cap Zone",
  2932. "BG Shape",
  2933. "Background Layer",
  2934. "Rotate Joint",
  2935. "Slider Joint",
  2936. "Rod Joint",
  2937. "Gear Joint",
  2938. 65535,
  2939. 16777215,
  2940. ]);
  2941.  
  2942.  
  2943. class bonkAPI_bytebuffer {
  2944. constructor() {
  2945. var g1d = [arguments];
  2946. this.index = 0;
  2947. this.buffer = new ArrayBuffer(100*1024);
  2948. this.view = new DataView(this.buffer);
  2949. this.implicitClassAliasArray = [];
  2950. this.implicitStringArray = [];
  2951. this.bodgeCaptureZoneDataIdentifierArray = [];
  2952. }
  2953.  
  2954. readByte() {
  2955. var N0H = [arguments];
  2956. N0H[4] = this.view.getUint8(this.index);
  2957. this.index += 1;
  2958. return N0H[4];
  2959. }
  2960. writeByte(z0w) {
  2961. var v8$ = [arguments];
  2962. this.view.setUint8(this.index, v8$[0][0]);
  2963. this.index += 1;
  2964. }
  2965. readInt() {
  2966. var A71 = [arguments];
  2967. A71[6] = this.view.getInt32(this.index);
  2968. this.index += 4;
  2969. return A71[6];
  2970. }
  2971. writeInt(W6i) {
  2972. var p5u = [arguments];
  2973. this.view.setInt32(this.index, p5u[0][0]);
  2974. this.index += 4;
  2975. }
  2976. readShort() {
  2977. var R1R = [arguments];
  2978. R1R[9] = this.view.getInt16(this.index);
  2979. this.index += 2;
  2980. return R1R[9];
  2981. }
  2982. writeShort(H8B) {
  2983. var d_3 = [arguments];
  2984. this.view.setInt16(this.index, d_3[0][0]);
  2985. this.index += 2;
  2986. }
  2987. readUint() {
  2988. var W2$ = [arguments];
  2989. W2$[8] = this.view.getUint32(this.index);
  2990. this.index += 4;
  2991. return W2$[8];
  2992. }
  2993. writeUint(B2X) {
  2994. var f8B = [arguments];
  2995. this.view.setUint32(this.index, f8B[0][0]);
  2996. this.index += 4;
  2997. }
  2998. readBoolean() {
  2999. var h6P = [arguments];
  3000. h6P[6] = this.readByte();
  3001. return h6P[6] == 1;
  3002. }
  3003. writeBoolean(Y3I) {
  3004. var l79 = [arguments];
  3005. if (l79[0][0]) {
  3006. this.writeByte(1);
  3007. } else {
  3008. this.writeByte(0);
  3009. }
  3010. }
  3011. readDouble() {
  3012. var V60 = [arguments];
  3013. V60[4] = this.view.getFloat64(this.index);
  3014. this.index += 8;
  3015. return V60[4];
  3016. }
  3017. writeDouble(z4Z) {
  3018. var O41 = [arguments];
  3019. this.view.setFloat64(this.index, O41[0][0]);
  3020. this.index += 8;
  3021. }
  3022. readFloat() {
  3023. var I0l = [arguments];
  3024. I0l[5] = this.view.getFloat32(this.index);
  3025. this.index += 4;
  3026. return I0l[5];
  3027. }
  3028. writeFloat(y4B) {
  3029. var B0v = [arguments];
  3030. this.view.setFloat32(this.index, B0v[0][0]);
  3031. this.index += 4;
  3032. }
  3033. readUTF() {
  3034. var d6I = [arguments];
  3035. d6I[8] = this.readByte();
  3036. d6I[7] = this.readByte();
  3037. d6I[9] = d6I[8] * 256 + d6I[7];
  3038. d6I[1] = new Uint8Array(d6I[9]);
  3039. for (d6I[6] = 0; d6I[6] < d6I[9]; d6I[6]++) {
  3040. d6I[1][d6I[6]] = this.readByte();
  3041. }
  3042. return bonkAPI.textdecoder.decode(d6I[1]);
  3043. }
  3044. writeUTF(L3Z) {
  3045. var Z75 = [arguments];
  3046. Z75[4] = bonkAPI.textencoder.encode(Z75[0][0]);
  3047. Z75[3] = Z75[4].length;
  3048. Z75[5] = Math.floor(Z75[3]/256);
  3049. Z75[8] = Z75[3] % 256;
  3050. this.writeByte(Z75[5]);
  3051. this.writeByte(Z75[8]);
  3052. Z75[7] = this;
  3053. Z75[4].forEach(I_O);
  3054. function I_O(s0Q, H4K, j$o) {
  3055. var N0o = [arguments];
  3056. Z75[7].writeByte(N0o[0][0]);
  3057. }
  3058. }
  3059. toBase64() {
  3060. var P4$ = [arguments];
  3061. P4$[4] = "";
  3062. P4$[9] = new Uint8Array(this.buffer);
  3063. P4$[8] = this.index;
  3064. for (P4$[7] = 0; P4$[7] < P4$[8]; P4$[7]++) {
  3065. P4$[4] += String.fromCharCode(P4$[9][P4$[7]]);
  3066. }
  3067. return window.btoa(P4$[4]);
  3068. }
  3069. fromBase64(W69, A8Q) {
  3070. var o0n = [arguments];
  3071. o0n[8] = window.pako;
  3072. o0n[6] = window.atob(o0n[0][0]);
  3073. o0n[9] = o0n[6].length;
  3074. o0n[4] = new Uint8Array(o0n[9]);
  3075. for (o0n[1] = 0; o0n[1] < o0n[9]; o0n[1]++) {
  3076. o0n[4][o0n[1]] = o0n[6].charCodeAt(o0n[1]);
  3077. }
  3078. if (o0n[0][1] === true) {
  3079. o0n[5] = o0n[8].inflate(o0n[4]);
  3080. o0n[4] = o0n[5];
  3081. }
  3082. this.buffer = o0n[4].buffer.slice(
  3083. o0n[4].byteOffset,
  3084. o0n[4].byteLength + o0n[4].byteOffset
  3085. );
  3086. this.view = new DataView(this.buffer);
  3087. this.index = 0;
  3088. }
  3089. }
  3090. bonkAPI.ISdecode = function (rawdata) {
  3091. rawdata_caseflipped = "";
  3092. for (i = 0; i < rawdata.length; i++) {
  3093. if (i <= 100 && rawdata.charAt(i) === rawdata.charAt(i).toLowerCase()) {
  3094. rawdata_caseflipped += rawdata.charAt(i).toUpperCase();
  3095. } else if (i <= 100 && rawdata.charAt(i) === rawdata.charAt(i).toUpperCase()) {
  3096. rawdata_caseflipped += rawdata.charAt(i).toLowerCase();
  3097. } else {
  3098. rawdata_caseflipped += rawdata.charAt(i);
  3099. }
  3100. }
  3101.  
  3102. data_deLZd = bonkAPI.LZString.decompressFromEncodedURIComponent(rawdata_caseflipped);
  3103. databuffer = bonkAPI.bytebuffer.fromBase64(data_deLZd);
  3104. data = bonkAPI.ISpsonpair.decode(databuffer.buffer);
  3105. return data;
  3106. };
  3107.  
  3108. bonkAPI.ISencode = function (obj) {
  3109. data = bonkAPI.ISpsonpair.encode(obj);
  3110. b64 = data.toBase64();
  3111. lzd = bonkAPI.LZString.compressToEncodedURIComponent(b64);
  3112.  
  3113. caseflipped = "";
  3114. for (i = 0; i < lzd.length; i++) {
  3115. if (i <= 100 && lzd.charAt(i) === lzd.charAt(i).toLowerCase()) {
  3116. caseflipped += lzd.charAt(i).toUpperCase();
  3117. } else if (i <= 100 && lzd.charAt(i) === lzd.charAt(i).toUpperCase()) {
  3118. caseflipped += lzd.charAt(i).toLowerCase();
  3119. } else {
  3120. caseflipped += lzd.charAt(i);
  3121. }
  3122. }
  3123.  
  3124. return caseflipped;
  3125. };
  3126.  
  3127. bonkAPI.decodeIS = function (x) {
  3128. return bonkAPI.ISdecode(x);
  3129. };
  3130. bonkAPI.encodeIS = function (x) {
  3131. return bonkAPI.ISencode(x);
  3132. };
  3133.  
  3134. bonkAPI.encodeMap = function (W2A) {
  3135. var M3n = [arguments];
  3136. M3n[1] = new bonkAPI_bytebuffer();
  3137. M3n[9] = M3n[0][0].physics;
  3138. M3n[0][0].v = 15;
  3139. M3n[1].writeShort(M3n[0][0].v);
  3140. M3n[1].writeBoolean(M3n[0][0].s.re);
  3141. M3n[1].writeBoolean(M3n[0][0].s.nc);
  3142. M3n[1].writeShort(M3n[0][0].s.pq);
  3143. M3n[1].writeFloat(M3n[0][0].s.gd);
  3144. M3n[1].writeBoolean(M3n[0][0].s.fl);
  3145. M3n[1].writeUTF(M3n[0][0].m.rxn);
  3146. M3n[1].writeUTF(M3n[0][0].m.rxa);
  3147. M3n[1].writeUint(M3n[0][0].m.rxid);
  3148. M3n[1].writeShort(M3n[0][0].m.rxdb);
  3149. M3n[1].writeUTF(M3n[0][0].m.n);
  3150. M3n[1].writeUTF(M3n[0][0].m.a);
  3151. M3n[1].writeUint(M3n[0][0].m.vu);
  3152. M3n[1].writeUint(M3n[0][0].m.vd);
  3153. M3n[1].writeShort(M3n[0][0].m.cr.length);
  3154. for (M3n[84] = 0; M3n[84] < M3n[0][0].m.cr.length; M3n[84]++) {
  3155. M3n[1].writeUTF(M3n[0][0].m.cr[M3n[84]]);
  3156. }
  3157. M3n[1].writeUTF(M3n[0][0].m.mo);
  3158. M3n[1].writeInt(M3n[0][0].m.dbid);
  3159. M3n[1].writeBoolean(M3n[0][0].m.pub);
  3160. M3n[1].writeInt(M3n[0][0].m.dbv);
  3161. M3n[1].writeShort(M3n[9].ppm);
  3162. M3n[1].writeShort(M3n[9].bro.length);
  3163. for (M3n[17] = 0; M3n[17] < M3n[9].bro.length; M3n[17]++) {
  3164. M3n[1].writeShort(M3n[9].bro[M3n[17]]);
  3165. }
  3166. M3n[1].writeShort(M3n[9].shapes.length);
  3167. for (M3n[80] = 0; M3n[80] < M3n[9].shapes.length; M3n[80]++) {
  3168. M3n[2] = M3n[9].shapes[M3n[80]];
  3169. if (M3n[2].type == "bx") {
  3170. M3n[1].writeShort(1);
  3171. M3n[1].writeDouble(M3n[2].w);
  3172. M3n[1].writeDouble(M3n[2].h);
  3173. M3n[1].writeDouble(M3n[2].c[0]);
  3174. M3n[1].writeDouble(M3n[2].c[1]);
  3175. M3n[1].writeDouble(M3n[2].a);
  3176. M3n[1].writeBoolean(M3n[2].sk);
  3177. }
  3178. if (M3n[2].type == "ci") {
  3179. M3n[1].writeShort(2);
  3180. M3n[1].writeDouble(M3n[2].r);
  3181. M3n[1].writeDouble(M3n[2].c[0]);
  3182. M3n[1].writeDouble(M3n[2].c[1]);
  3183. M3n[1].writeBoolean(M3n[2].sk);
  3184. }
  3185. if (M3n[2].type == "po") {
  3186. M3n[1].writeShort(3);
  3187. M3n[1].writeDouble(M3n[2].s);
  3188. M3n[1].writeDouble(M3n[2].a);
  3189. M3n[1].writeDouble(M3n[2].c[0]);
  3190. M3n[1].writeDouble(M3n[2].c[1]);
  3191. M3n[1].writeShort(M3n[2].v.length);
  3192. for (M3n[61] = 0; M3n[61] < M3n[2].v.length; M3n[61]++) {
  3193. M3n[1].writeDouble(M3n[2].v[M3n[61]][0]);
  3194. M3n[1].writeDouble(M3n[2].v[M3n[61]][1]);
  3195. }
  3196. }
  3197. }
  3198. M3n[1].writeShort(M3n[9].fixtures.length);
  3199. for (M3n[20] = 0; M3n[20] < M3n[9].fixtures.length; M3n[20]++) {
  3200. M3n[7] = M3n[9].fixtures[M3n[20]];
  3201. M3n[1].writeShort(M3n[7].sh);
  3202. M3n[1].writeUTF(M3n[7].n);
  3203. if (M3n[7].fr === null) {
  3204. M3n[1].writeDouble(Number.MAX_VALUE);
  3205. } else {
  3206. M3n[1].writeDouble(M3n[7].fr);
  3207. }
  3208. if (M3n[7].fp === null) {
  3209. M3n[1].writeShort(0);
  3210. }
  3211. if (M3n[7].fp === false) {
  3212. M3n[1].writeShort(1);
  3213. }
  3214. if (M3n[7].fp === true) {
  3215. M3n[1].writeShort(2);
  3216. }
  3217. if (M3n[7].re === null) {
  3218. M3n[1].writeDouble(Number.MAX_VALUE);
  3219. } else {
  3220. M3n[1].writeDouble(M3n[7].re);
  3221. }
  3222. if (M3n[7].de === null) {
  3223. M3n[1].writeDouble(Number.MAX_VALUE);
  3224. } else {
  3225. M3n[1].writeDouble(M3n[7].de);
  3226. }
  3227. M3n[1].writeUint(M3n[7].f);
  3228. M3n[1].writeBoolean(M3n[7].d);
  3229. M3n[1].writeBoolean(M3n[7].np);
  3230. M3n[1].writeBoolean(M3n[7].ng);
  3231. M3n[1].writeBoolean(M3n[7].ig);
  3232. }
  3233. M3n[1].writeShort(M3n[9].bodies.length);
  3234. for (M3n[37] = 0; M3n[37] < M3n[9].bodies.length; M3n[37]++) {
  3235. M3n[4] = M3n[9].bodies[M3n[37]];
  3236. M3n[1].writeUTF(M3n[4].type);
  3237. M3n[1].writeUTF(M3n[4].n);
  3238. M3n[1].writeDouble(M3n[4].p[0]);
  3239. M3n[1].writeDouble(M3n[4].p[1]);
  3240. M3n[1].writeDouble(M3n[4].a);
  3241. M3n[1].writeDouble(M3n[4].fric);
  3242. M3n[1].writeBoolean(M3n[4].fricp);
  3243. M3n[1].writeDouble(M3n[4].re);
  3244. M3n[1].writeDouble(M3n[4].de);
  3245. M3n[1].writeDouble(M3n[4].lv[0]);
  3246. M3n[1].writeDouble(M3n[4].lv[1]);
  3247. M3n[1].writeDouble(M3n[4].av);
  3248. M3n[1].writeDouble(M3n[4].ld);
  3249. M3n[1].writeDouble(M3n[4].ad);
  3250. M3n[1].writeBoolean(M3n[4].fr);
  3251. M3n[1].writeBoolean(M3n[4].bu);
  3252. M3n[1].writeDouble(M3n[4].cf.x);
  3253. M3n[1].writeDouble(M3n[4].cf.y);
  3254. M3n[1].writeDouble(M3n[4].cf.ct);
  3255. M3n[1].writeBoolean(M3n[4].cf.w);
  3256. M3n[1].writeShort(M3n[4].f_c);
  3257. M3n[1].writeBoolean(M3n[4].f_1);
  3258. M3n[1].writeBoolean(M3n[4].f_2);
  3259. M3n[1].writeBoolean(M3n[4].f_3);
  3260. M3n[1].writeBoolean(M3n[4].f_4);
  3261. M3n[1].writeBoolean(M3n[4].f_p);
  3262. M3n[1].writeBoolean(M3n[4].fz.on);
  3263. if (M3n[4].fz.on) {
  3264. M3n[1].writeDouble(M3n[4].fz.x);
  3265. M3n[1].writeDouble(M3n[4].fz.y);
  3266. M3n[1].writeBoolean(M3n[4].fz.d);
  3267. M3n[1].writeBoolean(M3n[4].fz.p);
  3268. M3n[1].writeBoolean(M3n[4].fz.a);
  3269. M3n[1].writeShort(M3n[4].fz.t);
  3270. +M3n[1].writeDouble(M3n[4].fz.cf);
  3271. }
  3272. M3n[1].writeShort(M3n[4].fx.length);
  3273. for (M3n[28] = 0; M3n[28] < M3n[4].fx.length; M3n[28]++) {
  3274. M3n[1].writeShort(M3n[4].fx[M3n[28]]);
  3275. }
  3276. }
  3277. M3n[1].writeShort(M3n[0][0].spawns.length);
  3278. for (M3n[30] = 0; M3n[30] < M3n[0][0].spawns.length; M3n[30]++) {
  3279. M3n[6] = M3n[0][0].spawns[M3n[30]];
  3280. M3n[1].writeDouble(M3n[6].x);
  3281. M3n[1].writeDouble(M3n[6].y);
  3282. M3n[1].writeDouble(M3n[6].xv);
  3283. M3n[1].writeDouble(M3n[6].yv);
  3284. M3n[1].writeShort(M3n[6].priority);
  3285. M3n[1].writeBoolean(M3n[6].r);
  3286. M3n[1].writeBoolean(M3n[6].f);
  3287. M3n[1].writeBoolean(M3n[6].b);
  3288. M3n[1].writeBoolean(M3n[6].gr);
  3289. M3n[1].writeBoolean(M3n[6].ye);
  3290. M3n[1].writeUTF(M3n[6].n);
  3291. }
  3292. M3n[1].writeShort(M3n[0][0].capZones.length);
  3293. for (M3n[74] = 0; M3n[74] < M3n[0][0].capZones.length; M3n[74]++) {
  3294. M3n[3] = M3n[0][0].capZones[M3n[74]];
  3295. M3n[1].writeUTF(M3n[3].n);
  3296. M3n[1].writeDouble(M3n[3].l);
  3297. M3n[1].writeShort(M3n[3].i);
  3298. M3n[1].writeShort(M3n[3].ty);
  3299. }
  3300. M3n[1].writeShort(M3n[9].joints.length);
  3301. for (M3n[89] = 0; M3n[89] < M3n[9].joints.length; M3n[89]++) {
  3302. M3n[5] = M3n[9].joints[M3n[89]];
  3303. if (M3n[5].type == "rv") {
  3304. M3n[1].writeShort(1);
  3305. M3n[1].writeDouble(M3n[5].d.la);
  3306. M3n[1].writeDouble(M3n[5].d.ua);
  3307. M3n[1].writeDouble(M3n[5].d.mmt);
  3308. M3n[1].writeDouble(M3n[5].d.ms);
  3309. M3n[1].writeBoolean(M3n[5].d.el);
  3310. M3n[1].writeBoolean(M3n[5].d.em);
  3311. M3n[1].writeDouble(M3n[5].aa[0]);
  3312. M3n[1].writeDouble(M3n[5].aa[1]);
  3313. }
  3314. if (M3n[5].type == "d") {
  3315. M3n[1].writeShort(2);
  3316. M3n[1].writeDouble(M3n[5].d.fh);
  3317. M3n[1].writeDouble(M3n[5].d.dr);
  3318. M3n[1].writeDouble(M3n[5].aa[0]);
  3319. M3n[1].writeDouble(M3n[5].aa[1]);
  3320. M3n[1].writeDouble(M3n[5].ab[0]);
  3321. M3n[1].writeDouble(M3n[5].ab[1]);
  3322. }
  3323. if (M3n[5].type == "lpj") {
  3324. M3n[1].writeShort(3);
  3325. M3n[1].writeDouble(M3n[5].pax);
  3326. M3n[1].writeDouble(M3n[5].pay);
  3327. M3n[1].writeDouble(M3n[5].pa);
  3328. M3n[1].writeDouble(M3n[5].pf);
  3329. M3n[1].writeDouble(M3n[5].pl);
  3330. M3n[1].writeDouble(M3n[5].pu);
  3331. M3n[1].writeDouble(M3n[5].plen);
  3332. M3n[1].writeDouble(M3n[5].pms);
  3333. }
  3334. if (M3n[5].type == "lsj") {
  3335. M3n[1].writeShort(4);
  3336. M3n[1].writeDouble(M3n[5].sax);
  3337. M3n[1].writeDouble(M3n[5].say);
  3338. M3n[1].writeDouble(M3n[5].sf);
  3339. M3n[1].writeDouble(M3n[5].slen);
  3340. }
  3341. if (M3n[5].type == "g") {
  3342. M3n[1].writeShort(5);
  3343. M3n[1].writeUTF(M3n[5].n);
  3344. M3n[1].writeShort(M3n[5].ja);
  3345. M3n[1].writeShort(M3n[5].jb);
  3346. M3n[1].writeDouble(M3n[5].r);
  3347. }
  3348. if (M3n[5].type != "g") {
  3349. M3n[1].writeShort(M3n[5].ba);
  3350. M3n[1].writeShort(M3n[5].bb);
  3351. M3n[1].writeBoolean(M3n[5].d.cc);
  3352. M3n[1].writeDouble(M3n[5].d.bf);
  3353. M3n[1].writeBoolean(M3n[5].d.dl);
  3354. }
  3355. }
  3356. M3n[32] = M3n[1].toBase64();
  3357. M3n[77] = LZString.compressToEncodedURIComponent(M3n[32]);
  3358. return M3n[77];
  3359. };
  3360.  
  3361. bonkAPI.decodeMap = function (map) {
  3362. var F5W = [arguments];
  3363. var b64mapdata = LZString.decompressFromEncodedURIComponent(map);
  3364. var binaryReader = new bonkAPI_bytebuffer();
  3365. binaryReader.fromBase64(b64mapdata, false);
  3366. map = {
  3367. v: 1,
  3368. s: { re: false, nc: false, pq: 1, gd: 25, fl: false },
  3369. physics: { shapes: [], fixtures: [], bodies: [], bro: [], joints: [], ppm: 12 },
  3370. spawns: [],
  3371. capZones: [],
  3372. m: {
  3373. a: "noauthor",
  3374. n: "noname",
  3375. dbv: 2,
  3376. dbid: -1,
  3377. authid: -1,
  3378. date: "",
  3379. rxid: 0,
  3380. rxn: "",
  3381. rxa: "",
  3382. rxdb: 1,
  3383. cr: [],
  3384. pub: false,
  3385. mo: "",
  3386. },
  3387. };
  3388. map.physics = map.physics;
  3389. map.v = binaryReader.readShort();
  3390. if (map.v > 15) {
  3391. throw new Error("Future map version, please refresh page");
  3392. }
  3393. map.s.re = binaryReader.readBoolean();
  3394. map.s.nc = binaryReader.readBoolean();
  3395. if (map.v >= 3) {
  3396. map.s.pq = binaryReader.readShort();
  3397. }
  3398. if (map.v >= 4 && map.v <= 12) {
  3399. map.s.gd = binaryReader.readShort();
  3400. } else if (map.v >= 13) {
  3401. map.s.gd = binaryReader.readFloat();
  3402. }
  3403. if (map.v >= 9) {
  3404. map.s.fl = binaryReader.readBoolean();
  3405. }
  3406. map.m.rxn = binaryReader.readUTF();
  3407. map.m.rxa = binaryReader.readUTF();
  3408. map.m.rxid = binaryReader.readUint();
  3409. map.m.rxdb = binaryReader.readShort();
  3410. map.m.n = binaryReader.readUTF();
  3411. map.m.a = binaryReader.readUTF();
  3412. if (map.v >= 10) {
  3413. map.m.vu = binaryReader.readUint();
  3414. map.m.vd = binaryReader.readUint();
  3415. }
  3416. if (map.v >= 4) {
  3417. F5W[7] = binaryReader.readShort();
  3418. for (F5W[83] = 0; F5W[83] < F5W[7]; F5W[83]++) {
  3419. map.m.cr.push(binaryReader.readUTF());
  3420. }
  3421. }
  3422. if (map.v >= 5) {
  3423. map.m.mo = binaryReader.readUTF();
  3424. map.m.dbid = binaryReader.readInt();
  3425. }
  3426. if (map.v >= 7) {
  3427. map.m.pub = binaryReader.readBoolean();
  3428. }
  3429. if (map.v >= 8) {
  3430. map.m.dbv = binaryReader.readInt();
  3431. }
  3432. map.physics.ppm = binaryReader.readShort();
  3433. F5W[4] = binaryReader.readShort();
  3434. for (F5W[15] = 0; F5W[15] < F5W[4]; F5W[15]++) {
  3435. map.physics.bro[F5W[15]] = binaryReader.readShort();
  3436. }
  3437. F5W[6] = binaryReader.readShort();
  3438. for (F5W[28] = 0; F5W[28] < F5W[6]; F5W[28]++) {
  3439. F5W[5] = binaryReader.readShort();
  3440. if (F5W[5] == 1) {
  3441. map.physics.shapes[F5W[28]] = { type: "bx", w: 10, h: 40, c: [0, 0], a: 0.0, sk: false };
  3442. map.physics.shapes[F5W[28]].w = binaryReader.readDouble();
  3443. map.physics.shapes[F5W[28]].h = binaryReader.readDouble();
  3444. map.physics.shapes[F5W[28]].c = [binaryReader.readDouble(), binaryReader.readDouble()];
  3445. map.physics.shapes[F5W[28]].a = binaryReader.readDouble();
  3446. map.physics.shapes[F5W[28]].sk = binaryReader.readBoolean();
  3447. }
  3448. if (F5W[5] == 2) {
  3449. map.physics.shapes[F5W[28]] = { type: "ci", r: 25, c: [0, 0], sk: false };
  3450. map.physics.shapes[F5W[28]].r = binaryReader.readDouble();
  3451. map.physics.shapes[F5W[28]].c = [binaryReader.readDouble(), binaryReader.readDouble()];
  3452. map.physics.shapes[F5W[28]].sk = binaryReader.readBoolean();
  3453. }
  3454. if (F5W[5] == 3) {
  3455. map.physics.shapes[F5W[28]] = { type: "po", v: [], s: 1, a: 0, c: [0, 0] };
  3456. map.physics.shapes[F5W[28]].s = binaryReader.readDouble();
  3457. map.physics.shapes[F5W[28]].a = binaryReader.readDouble();
  3458. map.physics.shapes[F5W[28]].c = [binaryReader.readDouble(), binaryReader.readDouble()];
  3459. F5W[74] = binaryReader.readShort();
  3460. map.physics.shapes[F5W[28]].v = [];
  3461. for (F5W[27] = 0; F5W[27] < F5W[74]; F5W[27]++) {
  3462. map.physics.shapes[F5W[28]].v.push([
  3463. binaryReader.readDouble(),
  3464. binaryReader.readDouble(),
  3465. ]);
  3466. }
  3467. }
  3468. }
  3469. F5W[71] = binaryReader.readShort();
  3470. for (F5W[17] = 0; F5W[17] < F5W[71]; F5W[17]++) {
  3471. map.physics.fixtures[F5W[17]] = {
  3472. sh: 0,
  3473. n: "Def Fix",
  3474. fr: 0.3,
  3475. fp: null,
  3476. re: 0.8,
  3477. de: 0.3,
  3478. f: 0x4f7cac,
  3479. d: false,
  3480. np: false,
  3481. ng: false,
  3482. };
  3483. map.physics.fixtures[F5W[17]].sh = binaryReader.readShort();
  3484. map.physics.fixtures[F5W[17]].n = binaryReader.readUTF();
  3485. map.physics.fixtures[F5W[17]].fr = binaryReader.readDouble();
  3486. if (map.physics.fixtures[F5W[17]].fr == Number.MAX_VALUE) {
  3487. map.physics.fixtures[F5W[17]].fr = null;
  3488. }
  3489. F5W[12] = binaryReader.readShort();
  3490. if (F5W[12] == 0) {
  3491. map.physics.fixtures[F5W[17]].fp = null;
  3492. }
  3493. if (F5W[12] == 1) {
  3494. map.physics.fixtures[F5W[17]].fp = false;
  3495. }
  3496. if (F5W[12] == 2) {
  3497. map.physics.fixtures[F5W[17]].fp = true;
  3498. }
  3499. map.physics.fixtures[F5W[17]].re = binaryReader.readDouble();
  3500. if (map.physics.fixtures[F5W[17]].re == Number.MAX_VALUE) {
  3501. map.physics.fixtures[F5W[17]].re = null;
  3502. }
  3503. map.physics.fixtures[F5W[17]].de = binaryReader.readDouble();
  3504. if (map.physics.fixtures[F5W[17]].de == Number.MAX_VALUE) {
  3505. map.physics.fixtures[F5W[17]].de = null;
  3506. }
  3507. map.physics.fixtures[F5W[17]].f = binaryReader.readUint();
  3508. map.physics.fixtures[F5W[17]].d = binaryReader.readBoolean();
  3509. map.physics.fixtures[F5W[17]].np = binaryReader.readBoolean();
  3510. if (map.v >= 11) {
  3511. map.physics.fixtures[F5W[17]].ng = binaryReader.readBoolean();
  3512. }
  3513. if (map.v >= 12) {
  3514. map.physics.fixtures[F5W[17]].ig = binaryReader.readBoolean();
  3515. }
  3516. }
  3517. F5W[63] = binaryReader.readShort();
  3518. for (F5W[52] = 0; F5W[52] < F5W[63]; F5W[52]++) {
  3519. map.physics.bodies[F5W[52]] = {
  3520. type: "s",
  3521. n: "Unnamed",
  3522. p: [0, 0],
  3523. a: 0,
  3524. fric: 0.3,
  3525. fricp: false,
  3526. re: 0.8,
  3527. de: 0.3,
  3528. lv: [0, 0],
  3529. av: 0,
  3530. ld: 0,
  3531. ad: 0,
  3532. fr: false,
  3533. bu: false,
  3534. cf: { x: 0, y: 0, w: true, ct: 0 },
  3535. fx: [],
  3536. f_c: 1,
  3537. f_p: true,
  3538. f_1: true,
  3539. f_2: true,
  3540. f_3: true,
  3541. f_4: true,
  3542. fz: { on: false, x: 0, y: 0, d: true, p: true, a: true, t: 0, cf: 0 },
  3543. };
  3544. map.physics.bodies[F5W[52]].type = binaryReader.readUTF();
  3545. map.physics.bodies[F5W[52]].n = binaryReader.readUTF();
  3546. map.physics.bodies[F5W[52]].p = [binaryReader.readDouble(), binaryReader.readDouble()];
  3547. map.physics.bodies[F5W[52]].a = binaryReader.readDouble();
  3548. map.physics.bodies[F5W[52]].fric = binaryReader.readDouble();
  3549. map.physics.bodies[F5W[52]].fricp = binaryReader.readBoolean();
  3550. map.physics.bodies[F5W[52]].re = binaryReader.readDouble();
  3551. map.physics.bodies[F5W[52]].de = binaryReader.readDouble();
  3552. map.physics.bodies[F5W[52]].lv = [binaryReader.readDouble(), binaryReader.readDouble()];
  3553. map.physics.bodies[F5W[52]].av = binaryReader.readDouble();
  3554. map.physics.bodies[F5W[52]].ld = binaryReader.readDouble();
  3555. map.physics.bodies[F5W[52]].ad = binaryReader.readDouble();
  3556. map.physics.bodies[F5W[52]].fr = binaryReader.readBoolean();
  3557. map.physics.bodies[F5W[52]].bu = binaryReader.readBoolean();
  3558. map.physics.bodies[F5W[52]].cf.x = binaryReader.readDouble();
  3559. map.physics.bodies[F5W[52]].cf.y = binaryReader.readDouble();
  3560. map.physics.bodies[F5W[52]].cf.ct = binaryReader.readDouble();
  3561. map.physics.bodies[F5W[52]].cf.w = binaryReader.readBoolean();
  3562. map.physics.bodies[F5W[52]].f_c = binaryReader.readShort();
  3563. map.physics.bodies[F5W[52]].f_1 = binaryReader.readBoolean();
  3564. map.physics.bodies[F5W[52]].f_2 = binaryReader.readBoolean();
  3565. map.physics.bodies[F5W[52]].f_3 = binaryReader.readBoolean();
  3566. map.physics.bodies[F5W[52]].f_4 = binaryReader.readBoolean();
  3567. if (map.v >= 2) {
  3568. map.physics.bodies[F5W[52]].f_p = binaryReader.readBoolean();
  3569. }
  3570. if (map.v >= 14) {
  3571. map.physics.bodies[F5W[52]].fz.on = binaryReader.readBoolean();
  3572. if (map.physics.bodies[F5W[52]].fz.on) {
  3573. map.physics.bodies[F5W[52]].fz.x = binaryReader.readDouble();
  3574. map.physics.bodies[F5W[52]].fz.y = binaryReader.readDouble();
  3575. map.physics.bodies[F5W[52]].fz.d = binaryReader.readBoolean();
  3576. map.physics.bodies[F5W[52]].fz.p = binaryReader.readBoolean();
  3577. map.physics.bodies[F5W[52]].fz.a = binaryReader.readBoolean();
  3578. if (map.v >= 15) {
  3579. map.physics.bodies[F5W[52]].t = binaryReader.readShort();
  3580. map.physics.bodies[F5W[52]].cf = binaryReader.readDouble();
  3581. }
  3582. }
  3583. }
  3584. F5W[88] = binaryReader.readShort();
  3585. for (F5W[65] = 0; F5W[65] < F5W[88]; F5W[65]++) {
  3586. map.physics.bodies[F5W[52]].fx.push(binaryReader.readShort());
  3587. }
  3588. }
  3589. F5W[97] = binaryReader.readShort();
  3590. for (F5W[41] = 0; F5W[41] < F5W[97]; F5W[41]++) {
  3591. map.spawns[F5W[41]] = {
  3592. x: 400,
  3593. y: 300,
  3594. xv: 0,
  3595. yv: 0,
  3596. priority: 5,
  3597. r: true,
  3598. f: true,
  3599. b: true,
  3600. gr: false,
  3601. ye: false,
  3602. n: "Spawn",
  3603. };
  3604. F5W[35] = map.spawns[F5W[41]];
  3605. F5W[35].x = binaryReader.readDouble();
  3606. F5W[35].y = binaryReader.readDouble();
  3607. F5W[35].xv = binaryReader.readDouble();
  3608. F5W[35].yv = binaryReader.readDouble();
  3609. F5W[35].priority = binaryReader.readShort();
  3610. F5W[35].r = binaryReader.readBoolean();
  3611. F5W[35].f = binaryReader.readBoolean();
  3612. F5W[35].b = binaryReader.readBoolean();
  3613. F5W[35].gr = binaryReader.readBoolean();
  3614. F5W[35].ye = binaryReader.readBoolean();
  3615. F5W[35].n = binaryReader.readUTF();
  3616. }
  3617. F5W[16] = binaryReader.readShort();
  3618. for (F5W[25] = 0; F5W[25] < F5W[16]; F5W[25]++) {
  3619. map.capZones[F5W[25]] = { n: "Cap Zone", ty: 1, l: 10, i: -1 };
  3620. map.capZones[F5W[25]].n = binaryReader.readUTF();
  3621. map.capZones[F5W[25]].l = binaryReader.readDouble();
  3622. map.capZones[F5W[25]].i = binaryReader.readShort();
  3623. if (map.v >= 6) {
  3624. map.capZones[F5W[25]].ty = binaryReader.readShort();
  3625. }
  3626. }
  3627. F5W[98] = binaryReader.readShort();
  3628. for (F5W[19] = 0; F5W[19] < F5W[98]; F5W[19]++) {
  3629. F5W[31] = binaryReader.readShort();
  3630. if (F5W[31] == 1) {
  3631. map.physics.joints[F5W[19]] = {
  3632. type: "rv",
  3633. d: { la: 0, ua: 0, mmt: 0, ms: 0, el: false, em: false, cc: false, bf: 0, dl: true },
  3634. aa: [0, 0],
  3635. };
  3636. F5W[20] = map.physics.joints[F5W[19]];
  3637. F5W[20].d.la = binaryReader.readDouble();
  3638. F5W[20].d.ua = binaryReader.readDouble();
  3639. F5W[20].d.mmt = binaryReader.readDouble();
  3640. F5W[20].d.ms = binaryReader.readDouble();
  3641. F5W[20].d.el = binaryReader.readBoolean();
  3642. F5W[20].d.em = binaryReader.readBoolean();
  3643. F5W[20].aa = [binaryReader.readDouble(), binaryReader.readDouble()];
  3644. }
  3645. if (F5W[31] == 2) {
  3646. map.physics.joints[F5W[19]] = {
  3647. type: "d",
  3648. d: { fh: 0, dr: 0, cc: false, bf: 0, dl: true },
  3649. aa: [0, 0],
  3650. ab: [0, 0],
  3651. };
  3652. F5W[87] = map.physics.joints[F5W[19]];
  3653. F5W[87].d.fh = binaryReader.readDouble();
  3654. F5W[87].d.dr = binaryReader.readDouble();
  3655. F5W[87].aa = [binaryReader.readDouble(), binaryReader.readDouble()];
  3656. F5W[87].ab = [binaryReader.readDouble(), binaryReader.readDouble()];
  3657. }
  3658. if (F5W[31] == 3) {
  3659. map.physics.joints[F5W[19]] = {
  3660. type: "lpj",
  3661. d: { cc: false, bf: 0, dl: true },
  3662. pax: 0,
  3663. pay: 0,
  3664. pa: 0,
  3665. pf: 0,
  3666. pl: 0,
  3667. pu: 0,
  3668. plen: 0,
  3669. pms: 0,
  3670. };
  3671. F5W[90] = map.physics.joints[F5W[19]];
  3672. F5W[90].pax = binaryReader.readDouble();
  3673. F5W[90].pay = binaryReader.readDouble();
  3674. F5W[90].pa = binaryReader.readDouble();
  3675. F5W[90].pf = binaryReader.readDouble();
  3676. F5W[90].pl = binaryReader.readDouble();
  3677. F5W[90].pu = binaryReader.readDouble();
  3678. F5W[90].plen = binaryReader.readDouble();
  3679. F5W[90].pms = binaryReader.readDouble();
  3680. }
  3681. if (F5W[31] == 4) {
  3682. map.physics.joints[F5W[19]] = {
  3683. type: "lsj",
  3684. d: { cc: false, bf: 0, dl: true },
  3685. sax: 0,
  3686. say: 0,
  3687. sf: 0,
  3688. slen: 0,
  3689. };
  3690. F5W[44] = map.physics.joints[F5W[19]];
  3691. F5W[44].sax = binaryReader.readDouble();
  3692. F5W[44].say = binaryReader.readDouble();
  3693. F5W[44].sf = binaryReader.readDouble();
  3694. F5W[44].slen = binaryReader.readDouble();
  3695. }
  3696. if (F5W[31] == 5) {
  3697. map.physics.joints[F5W[19]] = { type: "g", n: "", ja: -1, jb: -1, r: 1 };
  3698. F5W[91] = map.physics.joints[F5W[19]];
  3699. F5W[91].n = binaryReader.readUTF();
  3700. F5W[91].ja = binaryReader.readShort();
  3701. F5W[91].jb = binaryReader.readShort();
  3702. F5W[91].r = binaryReader.readDouble();
  3703. }
  3704. if (F5W[31] != 5) {
  3705. map.physics.joints[F5W[19]].ba = binaryReader.readShort();
  3706. map.physics.joints[F5W[19]].bb = binaryReader.readShort();
  3707. map.physics.joints[F5W[19]].d.cc = binaryReader.readBoolean();
  3708. map.physics.joints[F5W[19]].d.bf = binaryReader.readDouble();
  3709. map.physics.joints[F5W[19]].d.dl = binaryReader.readBoolean();
  3710. }
  3711. }
  3712. return map;
  3713. };
  3714. window.PIXI.Graphics.prototype.drawShape = function(...args) {
  3715. //! testing whether cap can be easily found in drawShape
  3716. //! in drawCircle, capzone has attribute 'cap: "bet"' inside fill_outline
  3717. //console.log([...args]);
  3718. let draw = this;
  3719. setTimeout(function(){
  3720. if(draw.parent) {
  3721. bonkAPI.parentDraw = draw.parent;
  3722. while(bonkAPI.parentDraw.parent != null) {
  3723. bonkAPI.parentDraw = bonkAPI.parentDraw.parent;
  3724. }
  3725. }
  3726. }, 0);
  3727. return bonkAPI.originalDrawShape.call(this, ...args);
  3728. }
  3729. window.requestAnimationFrame = function(...args) {
  3730. //console.log(bonkAPI.isInGame());
  3731. if(bonkAPI.isInGame()) {
  3732. let canv = 0;
  3733. for(let i = 0; i < document.getElementById("gamerenderer").children.length; i++) {
  3734. if(document.getElementById("gamerenderer").children[i].constructor.name == "HTMLCanvasElement"){
  3735. canv = document.getElementById("gamerenderer").children[i];
  3736. break;
  3737. }
  3738. }
  3739. //console.log(bonkAPI.parentDraw);
  3740. if(canv != 0 && bonkAPI.parentDraw) {
  3741. //! might do something might not
  3742. while(bonkAPI.parentDraw.parent != null) {
  3743. bonkAPI.parentDraw = bonkAPI.parentDraw.parent;
  3744. }
  3745. /**
  3746. * When a new frame is rendered when in game. It is recomended
  3747. * to not create new graphics or clear graphics every frame if
  3748. * possible.
  3749. * @event graphicsUpdate
  3750. * @type {object}
  3751. * @property {string} container - PIXI container to hold PIXI graphics.
  3752. * @property {number} width - Width of main screen
  3753. * @property {number} height - Height of main screen
  3754. */
  3755. if(bonkAPI.events.hasEvent["graphicsUpdate"]) {
  3756. let w = parseInt(canv.style.width);
  3757. let h = parseInt(canv.style.height);
  3758. //bonkAPI.pixiCtx.x = w / 2;
  3759. //bonkAPI.pixiCtx.y = h / 2;
  3760. bonkAPI.pixiStage = 0;
  3761. for(let i = 0; i < bonkAPI.parentDraw.children.length; i++){
  3762. if(bonkAPI.parentDraw.children[i].constructor.name == "e"){
  3763. //console.log(bonkAPI.parentDraw);
  3764. bonkAPI.pixiStage = bonkAPI.parentDraw.children[i];
  3765. break;
  3766. }
  3767. }
  3768. let sendObj = {
  3769. container: bonkAPI.pixiCtx,
  3770. width: w,
  3771. height: h,
  3772. };
  3773. bonkAPI.events.fireEvent("graphicsUpdate", sendObj);
  3774. if(bonkAPI.pixiStage != 0 && !bonkAPI.pixiStage.children.includes(bonkAPI.pixiCtx)) {
  3775. bonkAPI.pixiStage.addChild(bonkAPI.pixiCtx);
  3776. }
  3777. }
  3778. }
  3779. }
  3780. return bonkAPI.originalRequestAnimationFrame.call(this,...args);
  3781. }
  3782.  
  3783. /**
  3784. * When the map has changed.
  3785. * @event mapSwitch
  3786. * @type {object}
  3787. * @property {PIXI} pixi - PIXI class in order to create graphics and containers.
  3788. * @property {string} container - PIXI container to hold PIXI graphics.
  3789. */
  3790. if(bonkAPI.events.hasEvent["graphicsReady"]) {
  3791. let sendObj = {
  3792. pixi: window.PIXI,
  3793. container: bonkAPI.pixiCtx,
  3794. }
  3795. bonkAPI.events.fireEvent("graphicsReady", sendObj);
  3796. }
  3797. bonkHUD.loadStyleSettings();
  3798. bonkHUD.initialize();
  3799. bonkHUD.updateStyleSettings();
  3800. };
  3801.  
  3802. bonkLIB.checkDocumentReady = () => {
  3803. if (document.readyState === "complete" || document.readyState === "interactive") {
  3804. bonkLIB.onLoaded();
  3805. } else {
  3806. document.addEventListener("DOMContentLoaded", function () {
  3807. bonkLIB.onLoaded();
  3808. });
  3809. }
  3810. };
  3811.  
  3812. // Call the function to check document readiness
  3813. bonkLIB.checkDocumentReady();
  3814.