Sploop.io Waypoints

Easily traverse the world of Sploop.io with Waypoints!

当前为 2025-03-02 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Sploop.io Waypoints
  3. // @version 2.0.0
  4. // @description Easily traverse the world of Sploop.io with Waypoints!
  5. // @author Hori + viper
  6. // @match https://sploop.io/
  7. // @icon https://i.ibb.co/ym4LXJF7/Waypoints-3-removebg-preview.png
  8. // @grant none
  9. // @run-at document-start
  10. // @license MIT
  11. // @namespace https://greasyfork.org/users/1441649
  12. // ==/UserScript==
  13.  
  14. /**
  15. * Authors: horizion, viper
  16. *
  17. * Easily traverse the world of Sploop.io with Waypoints!
  18. *
  19. * Menu Keybind : ESCAPE
  20. *
  21. * (!) - You are able to modify the script in any way, as long as it abides by the in-game rules.
  22. * (!) - Contact Horizion if the script does not work.
  23. *
  24. * Discord: horizon2025.#0000 | <@880415818142347297>
  25. *
  26. * Official Sploop.io Discord Server: https://discord.com/invite/CYadgpyv78
  27. */
  28.  
  29. (function () {
  30. "use strict";
  31. const win = window;
  32. const log = console.log;
  33. const version = `2.0.0`;
  34.  
  35. const ARROW_DISTANCE_FROM_PLAYER = 210;
  36. const COLORS = [
  37. "red",
  38. "orange",
  39. "yellow",
  40. "green",
  41. "dark_blue",
  42. "light_blue",
  43. "purple",
  44. "violet",
  45. "pink",
  46. "rose",
  47. ];
  48. const MARKER_IMAGES = [
  49. "https://i.ibb.co/20h3vpRG/map-cross-red.png",
  50. "https://i.ibb.co/VWZCzbgK/map-cross-orange.png",
  51. "https://i.ibb.co/x8jT4J4x/map-cross-yellow.png",
  52. "https://i.ibb.co/dstqTPQP/map-cross-darkgreen.png",
  53. "https://i.ibb.co/dsSZtg0Q/map-cross-darkblue.png",
  54. "https://i.ibb.co/4RPBRMH7/map-cross-lightblue.png",
  55. "https://i.ibb.co/84KYxdNd/map-cross-purple.png",
  56. "https://i.ibb.co/8LJ4FbbW/map-cross-indigo.png",
  57. "https://i.ibb.co/bgNv5NB7/map-cross-pink.png",
  58. "https://i.ibb.co/5WMsX1f1/map-cross-main.png",
  59. ];
  60. const ARROW_IMAGES = [
  61. "https://i.ibb.co/chgGndnF/arrow-red.png",
  62. "https://i.ibb.co/LdkChynd/arrow-orange.png",
  63. "https://i.ibb.co/v6x76XN6/arrow-yellow.png",
  64. "https://i.ibb.co/2YYvqNHj/arrow-darkgreen.png",
  65. "https://i.ibb.co/6RrD7MvR/arrow-darkblue.png",
  66. "https://i.ibb.co/9kqtG2k4/arrow-lightblue.png",
  67. "https://i.ibb.co/ZzjZhK0g/arrow-purple.png",
  68. "https://i.ibb.co/sdgDvP0Y/arrow-indigo.png",
  69. "https://i.ibb.co/yFFq6jBN/arrow-pink.png",
  70. "https://i.ibb.co/zT2rYdFT/arrow-main.png",
  71. ];
  72. const MARKER_COLOR_IMAGES = {
  73. red: "https://i.ibb.co/ksRyM6FY/circle-red.png",
  74. orange: "https://i.ibb.co/4gNKXnp6/circle-orange.png",
  75. yellow: "https://i.ibb.co/60rHrBWP/circle-yellow.png",
  76. green: "https://i.ibb.co/kVGgcVKT/circle-green.png",
  77. dark_blue: "https://i.ibb.co/9mbLDCLq/circle-darkblue.png",
  78. light_blue: "https://i.ibb.co/LhNv7JXx/circle-lightblue.png",
  79. purple: "https://i.ibb.co/WvddsXyk/circle-purple.png",
  80. violet: "https://i.ibb.co/PZKjyN2g/circle-indigo.png",
  81. pink: "https://i.ibb.co/bf2LzgM/circle-pink.png",
  82. rose: "https://i.ibb.co/0pMvXrMS/circle-main.png",
  83. };
  84.  
  85. let waypointID = 0;
  86. let waypoints = [];
  87. let cards = [];
  88.  
  89. win.showWaypointArrows = 1;
  90.  
  91. //** Styling DOM */
  92.  
  93. const style = document.createElement("style");
  94. style.type = "text/css";
  95. style.textContent = `
  96. :root {
  97. --main: #de5978;
  98. --secondary: rgb(43, 37, 37, 1);
  99. }
  100. button:focus {
  101. border: none;
  102. outline: none;
  103. }
  104. input:focus {
  105. outline: none;
  106. border: none;
  107. }
  108.  
  109. /* Making scroll bar more pro */
  110.  
  111. ::-webkit-scrollbar {
  112. width: 7px;
  113. }
  114.  
  115. ::-webkit-scrollbar-thumb {
  116. background-color: var(--main);
  117. border-top-right-radius: 10px;
  118. border-bottom-right-radius: 10px;
  119. border-top-left-radius: 0;
  120. border-bottom-left-radius: 0;
  121. }
  122.  
  123. ::-webkit-scrollbar-track {
  124. background-color: var(--secondary);
  125. border-top-right-radius: 10px;
  126. border-bottom-right-radius: 10px;
  127. border-top-left-radius: 0;
  128. border-bottom-left-radius: 0;
  129. }
  130.  
  131. /* Main menu styling */
  132.  
  133. #wayMenu {
  134. display: none;
  135. position: fixed;
  136. top: 160px;
  137. left: 293px;
  138. z-index: 99999;
  139. padding: 20px;
  140. background: var(--secondary);
  141. border-radius: 10px;
  142. max-height: 60%;
  143. overflow-y: auto;
  144. width: 400px;
  145. border: 1.5px solid var(--main);
  146. }
  147. .wayHeader {
  148. display: flex;
  149. justify-content: space-between;
  150. align-items: center;
  151. margin-bottom: 10px;
  152. }
  153. .wayTitle {
  154. font-size: 20px;
  155. color: var(--main);
  156. }
  157. .version {
  158. font-size: 15px;
  159. color: rgba(100, 100, 100,1);
  160. }
  161. .wayArrowToggle {
  162. display: flex;
  163. align-items: center;
  164. gap: 5px;
  165. opacity: 0;
  166. transition: all 0.3s ease-in-out;
  167. pointer-events: none;
  168. }
  169. .wayArrowToggle i {
  170. color: var(--main);
  171. font-size: 18px;
  172. }
  173.  
  174. .switch {
  175. position: relative;
  176. display: inline-block;
  177. width: 40px;
  178. height: 20px;
  179. }
  180.  
  181. .switch input {
  182. opacity: 0;
  183. width: 0;
  184. height: 0;
  185. }
  186.  
  187. .slider {
  188. position: absolute;
  189. cursor: pointer;
  190. top: 0;
  191. left: 0;
  192. right: 0;
  193. bottom: 0;
  194. background-color: rgb(41, 41, 41);
  195. transition: 0.3s;
  196. border-radius: 20px;
  197. border: 1px solid rgb(112, 53, 74);
  198. }
  199.  
  200. .slider:before {
  201. position: absolute;
  202. content: "";
  203. height: 14px;
  204. width: 14px;
  205. left: 3px;
  206. background-color: var(--main);
  207. bottom: 3px;
  208. transition: 0.3s;
  209. border-radius: 50%;
  210. }
  211.  
  212. input:checked + .slider {
  213. background-color: rgba(187, 75, 101,0.6);
  214. }
  215.  
  216. input:checked + .slider:before {
  217. transform: translateX(20px);
  218. }
  219. .wayCreateNewButton {
  220. margin-top: 25px;
  221. border: none;
  222. color: white;
  223. width: 250px;
  224. text-align: center;
  225. border-radius: 10px;
  226. padding: 7px;
  227. background: var(--main);
  228. font-size: 18px;
  229. cursor: pointer;
  230. font-weight: 990;
  231. height:35px;
  232. transition: transform 0.4s ease;
  233. border: 1px solid var(--secondary);
  234. }
  235. .wayCreateNewButton:hover {
  236. transform: translateY(-1px);
  237. }
  238. .wayCreateNewButton:disabled {
  239. background:rgb(187, 75, 101);
  240. color:rgba(156, 156, 156, 0.99);
  241. cursor: not-allowed;
  242. opacity: 0.85;
  243. transform: none;
  244. }
  245. .wayNotFound {
  246. text-align: center;
  247. display: block;
  248. font-size: 15px;
  249. color: white;
  250. margin-top: 20px;
  251. }
  252. .wayCreate {
  253. text-align: center;
  254. }
  255.  
  256. /* popup styling */
  257.  
  258. #wayPopMenu {
  259. display: block;
  260. position: fixed;
  261. top: 50%;
  262. left: 50%;
  263. transform: translate(-50%, -50%);
  264. padding: 25px;
  265. background: var(--secondary);
  266. border-radius: 10px;
  267. max-height: 50%;
  268. overflow-y: auto;
  269. text-align: center;
  270. }
  271. .popupHeader {
  272. position: absolute;
  273. top: 0;
  274. right: 8px;
  275. margin-bottom: 8px;
  276. }
  277. .closePopup {
  278. font-size: 24px;
  279. font-weight: bold;
  280. cursor: pointer;
  281. color: #fff;
  282. }
  283. .popupHeader:hover {
  284. transform: translateY(-1px);
  285. }
  286. #markerName {
  287. border-radius: 10px;
  288. height:35px;
  289. text-align: center;
  290. font-size: 16px;
  291. border: none;
  292. width: 200px;
  293. }
  294. #wayColors {
  295. padding: 7px;
  296. height:35px;
  297. width: 200px;
  298. border: none;
  299. border-radius: 10px;
  300. font-size: 16px;
  301. margin-bottom: 16px;
  302. background: #fff;
  303. color: #333;
  304. -webkit-appearance: none;
  305. -moz-appearance: none;
  306. appearance: none;
  307. text-align: center;
  308. font-weight: 800;
  309. cursor: pointer;
  310. }
  311. .wayCreateButton {
  312. border: none;
  313. color: white;
  314. width: 200px;
  315. text-align: center;
  316. border-radius: 10px;
  317. padding: 7px;
  318. background: var(--main);
  319. cursor: pointer;
  320. font-weight: 560;
  321. font-size: 16px;
  322. height:35px;
  323. transition: transform 0.4s ease;
  324. }
  325. .wayCreateButton:focus{
  326. border:none;
  327. }
  328. .wayCreateButton:hover {
  329. transform: translateY(-1px);
  330. }
  331.  
  332. /* Card Styling */
  333.  
  334. .card {
  335. display: flex;
  336. align-items: center;
  337. background:rgb(41, 41, 41);
  338. border-radius: 10px;
  339. padding: 10px;
  340. margin-top: 10px;
  341. color: white;
  342. border: 1px solid rgb(112, 53, 74);
  343. }
  344.  
  345. .card img {
  346. width: 22px;
  347. height: 22px;
  348. margin-right: 10px;
  349. border-radius: 50%;
  350. }
  351.  
  352. .card .card-name {
  353. flex: 4;
  354. font-size: 16px;
  355. margin-right: 10px;
  356. max-width: 145px;
  357. }
  358.  
  359. .card .card-coords {
  360. flex: 3;
  361. font-size: 16px;
  362. margin-right: 10px;
  363. color: rgba(100, 100, 100,1);
  364. }
  365.  
  366. .card .card-remove {
  367. background: #e43939;
  368. border: none;
  369. color: white;
  370. padding: 5px 10px;
  371. border-radius: 5px;
  372. cursor: pointer;
  373. }
  374. .card .card-remove:hover {
  375. transform: translateY(-1px);
  376. }
  377. #trash:hover {
  378. cursor: pointer;
  379. }
  380. `;
  381. document.head.appendChild(style);
  382.  
  383. //** Main */
  384.  
  385. document.addEventListener("DOMContentLoaded", () => {
  386. log(
  387. `%cWaypoints %cVersion ${version}\n%cCreators: %cviper + Hori`,
  388. "font-size: 90px; font-weight: 900; color: #de5978;",
  389. "font-size: 20px; color: gray;",
  390. "font-size: 20px; font-weight: 900; color:rgb(255, 255, 255); margin-top: 8px; margin-bottom: 10px;",
  391. "font-size: 20px; color:rgb(235, 187, 97); margin-top: 8px; margin-bottom: 10px;"
  392. );
  393.  
  394. const wayMenu = document.createElement("div");
  395. wayMenu.id = "wayMenu";
  396. wayMenu.innerHTML = `
  397. <div class="wayHeader">
  398. <span class="wayTitle">Waypoints <span class="version">- v${version}</span></span>
  399. <div class="wayArrowToggle">
  400. <i class="fa-solid fa-location-arrow"></i>
  401. <label class="switch">
  402. <input type="checkbox" id="waypointToggle" checked>
  403. <span class="slider"></span>
  404. </label>
  405. </div>
  406. </div>
  407. <div class="wayContent">
  408. <div id="wayNotFound" class="wayNotFound">
  409. No Waypoints Found
  410. <i class="fa-solid fa-magnifying-glass"></i>
  411. </div>
  412. </div>
  413. <div class="wayCreate">
  414. <button id="wayCreateNewButton" class="wayCreateNewButton" disabled>+</button>
  415. </div>
  416. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css" integrity="sha512-SzlrxWUlpfuzQ+pcUCosxcglQRNAq/DZjVsC0lE40xsADsfeQoEypE+enwcOiGjk/bSuGGKHEyjSoQ1zVisanQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
  417. `;
  418. document.body.append(wayMenu);
  419.  
  420. let isDragging = false,
  421. displayToggled = false,
  422. offsetX,
  423. offsetY;
  424.  
  425. wayMenu.addEventListener("mousedown", function (event) {
  426. isDragging = true;
  427. offsetX = event.clientX - wayMenu.getBoundingClientRect().left;
  428. offsetY = event.clientY - wayMenu.getBoundingClientRect().top;
  429. });
  430. document.addEventListener("mousemove", function (event) {
  431. if (isDragging) {
  432. const newX = event.clientX - offsetX;
  433. const newY = event.clientY - offsetY;
  434. wayMenu.style.left = newX + "px";
  435. wayMenu.style.top = newY + "px";
  436. }
  437. });
  438. document.addEventListener("mouseup", () => {
  439. isDragging = false;
  440. });
  441.  
  442. document
  443. .getElementById("wayCreateNewButton")
  444. .addEventListener("click", () => {
  445. if (!document.getElementById("wayPopMenu")) {
  446. createPopup();
  447. }
  448. });
  449.  
  450. document.addEventListener("keydown", (event) => {
  451. if (event.key === "Escape" && !isChatWrapperVisible()) {
  452. wayMenu.style.display = displayToggled ? "none" : "block";
  453. displayToggled = !displayToggled;
  454. }
  455. });
  456.  
  457. document
  458. .getElementById("waypointToggle")
  459. .addEventListener("change", function () {
  460. if (this.checked) {
  461. win.showWaypointArrows = 1;
  462. } else {
  463. win.showWaypointArrows = 0;
  464. }
  465. });
  466.  
  467. const observer = new MutationObserver(() => {
  468. updateCreateButton();
  469. });
  470. const homepage = document.getElementById("homepage");
  471. if (homepage) {
  472. observer.observe(homepage, {
  473. attributes: true,
  474. attributeFilter: ["style"],
  475. });
  476. }
  477. });
  478.  
  479. const addWaypoint = new Proxy(waypoints, {
  480. set(target, property, value, receiver) {
  481. const result = Reflect.set(target, property, value, receiver);
  482. if (!isNaN(property)) {
  483. createCard(value);
  484. }
  485. return result;
  486. },
  487. });
  488.  
  489. function createPopup() {
  490. let wayPopMenu = document.createElement("div");
  491. wayPopMenu.id = "wayPopMenu";
  492. wayPopMenu.innerHTML = `
  493. <div class="popupHeader">
  494. <span id="closePopup" class="closePopup">x</span>
  495. </div>
  496. <div class="inputContainer">
  497. <input type="text" id="markerName"placeholder="New Waypoint" maxLength="13"><br><br>
  498. </div>
  499. <div class="wayColor">
  500. <select name="colors" id="wayColors">
  501. <option value="0">Red</option>
  502. <option value="1">Orange</option>
  503. <option value="2">Yellow</option>
  504. <option value="3">Green</option>
  505. <option value="4">Dark Blue</option>
  506. <option value="5">Light Blue</option>
  507. <option value="6">Purple</option>
  508. <option value="7">Violet</option>
  509. <option value="8">Pink</option>
  510. <option value="9">Rose</option>
  511. </select>
  512. </div>
  513. <div class="wayCreate">
  514. <button id="createButton" class="wayCreateButton">Create</button>
  515. </div>
  516. `;
  517. document.body.appendChild(wayPopMenu);
  518.  
  519. document
  520. .getElementById("markerName")
  521. .addEventListener("keydown", function (event) {
  522. event.stopPropagation();
  523. });
  524. document.getElementById("closePopup").addEventListener("click", () => {
  525. wayPopMenu.remove();
  526. });
  527. document
  528. .getElementById("createButton")
  529. .addEventListener("click", getOption);
  530. }
  531.  
  532. function createCard(waypoint) {
  533. cards.push({
  534. name: waypoint.name,
  535. id: waypoint.id,
  536. });
  537.  
  538. const card = document.createElement("div");
  539. card.className = "card";
  540. card.innerHTML = `
  541. <img src="${MARKER_COLOR_IMAGES[waypoint.color]}" alt="color">
  542. <div class="card-name">${waypoint.name}</div>
  543. <div class="card-coords">[${Math.round(waypoint.x)},${Math.round(waypoint.y)}]</div>
  544. <button class="card-remove"><i class="fa-solid fa-trash" id="trash"></i></button>
  545. `;
  546.  
  547. document.querySelector(".wayContent").appendChild(card);
  548.  
  549. updateArrowToggleAlpha();
  550.  
  551. const removeButton = card.querySelector(".card-remove");
  552.  
  553. removeButton.addEventListener("click", function () {
  554. const waypointIndex = waypoints.findIndex(
  555. (way) => way.id === waypoint.id
  556. );
  557. if (waypointIndex > -1) {
  558. waypoints.splice(waypointIndex, 1);
  559. }
  560. const cardIndex = cards.findIndex(
  561. (card) => card.id === waypoint.id
  562. );
  563. if (cardIndex > -1) {
  564. cards.splice(cardIndex, 1);
  565. }
  566. card.remove();
  567. if (cards.length === 0) {
  568. document.getElementById("wayNotFound").style.display = "block";
  569. }
  570. updateArrowToggleAlpha();
  571. });
  572. }
  573.  
  574. function createWaypoint(name, color) {
  575. const chosenMarker = MARKER_IMAGES[color];
  576. const chosenArrow = ARROW_IMAGES[color];
  577.  
  578. const markerImg = createImage(chosenMarker);
  579. const arrowImg = createImage(chosenArrow);
  580.  
  581. const newWaypoint = {
  582. name,
  583. id: waypointID++,
  584. arrow: arrowImg,
  585. marker: markerImg,
  586. x: win.coords.x,
  587. y: win.coords.y,
  588. color: COLORS[color],
  589. };
  590.  
  591. addWaypoint.push(newWaypoint);
  592. }
  593. function getOption() {
  594. const markerName = document.getElementById("markerName").value;
  595. const wayColor = document.getElementById("wayColors");
  596. const color = wayColor.value;
  597. if (markerName !== "") {
  598. createWaypoint(markerName, color);
  599. document.getElementById("wayNotFound").style.display = "none";
  600. document.getElementById("wayPopMenu").remove();
  601. }
  602. }
  603. function updateCreateButton() {
  604. const button = document.getElementById("wayCreateNewButton");
  605. const homepage = document.getElementById("homepage");
  606.  
  607. if (homepage && homepage.style.display === "flex") {
  608. button.disabled = true;
  609. } else {
  610. button.disabled = false;
  611. }
  612. }
  613. function updateArrowToggleAlpha() {
  614. const toggle = document.querySelector(".wayArrowToggle");
  615. if (toggle) {
  616. toggle.style.opacity = cards.length === 0 ? "0" : "1";
  617. toggle.style.pointerEvents = cards.length === 0 ? "none" : "auto";
  618. }
  619. }
  620. function createImage(URL) {
  621. const image = new Image();
  622. image.src = URL;
  623. return image;
  624. }
  625. function isChatWrapperVisible() {
  626. return (
  627. document.getElementById("chat-wrapper").style.display === "block"
  628. );
  629. }
  630.  
  631. //** Draw Waypoints, Arrows, Names */
  632.  
  633. class Drawing {
  634. arrows(context, arrow, angle, x, y) {
  635. context.save();
  636. context.globalAlpha = 0.52;
  637. context.translate(x, y);
  638. context.rotate(angle);
  639. context.drawImage(arrow, -25 / 2, -25 / 2, 25, 25);
  640. context.restore();
  641. }
  642. name(context, waypoint) {
  643. const x = waypoint.x;
  644. const y = waypoint.y - 42;
  645.  
  646. context.font = "24px Baloo Paaji";
  647. context.textAlign = "center";
  648. context.lineWidth = 8;
  649. context.strokeStyle = "#414141";
  650. context.lineJoin = "round";
  651. context.strokeText(waypoint.name, x, y);
  652. context.fillStyle = "white";
  653. context.fillText(waypoint.name, x, y);
  654. }
  655. waypoint(context, waypoint) {
  656. context.drawImage(
  657. waypoint.marker,
  658. waypoint.x - 70 / 2,
  659. waypoint.y - 70 / 2,
  660. 70,
  661. 70
  662. );
  663. }
  664. }
  665. const Draw = new Drawing();
  666.  
  667. win.draw = (context) => {
  668. waypoints.forEach((waypoint) => {
  669. const distance = Math.hypot(
  670. waypoint.x - win.coords.x,
  671. waypoint.y - win.coords.y
  672. );
  673.  
  674. if (distance < 1200) {
  675. Draw.waypoint(context, waypoint);
  676. Draw.name(context, waypoint);
  677. }
  678. if (win.showWaypointArrows && distance > 450) {
  679. const angle = Math.atan2(
  680. waypoint.y - win.coords.y,
  681. waypoint.x - win.coords.x
  682. );
  683. let radius = ARROW_DISTANCE_FROM_PLAYER;
  684.  
  685. const x = win.coords.x + Math.cos(angle) * radius;
  686. const y = win.coords.y + Math.sin(angle) * radius;
  687.  
  688. Draw.arrows(context, waypoint.arrow, angle, x, y);
  689. }
  690. });
  691. };
  692.  
  693. //** Hooking onto the game */
  694.  
  695. const TYPEOF = (value) =>
  696. Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
  697. const NumberSystem = [
  698. {
  699. radix: 2,
  700. prefix: "0b0*",
  701. },
  702. {
  703. radix: 8,
  704. prefix: "0+",
  705. },
  706. {
  707. radix: 10,
  708. prefix: "",
  709. },
  710. {
  711. radix: 16,
  712. prefix: "0x0*",
  713. },
  714. ];
  715. class Regex {
  716. constructor(code, unicode, namespace) {
  717. if (!namespace)
  718. namespace =
  719. "new_script_" + Math.random().toString(36).substr(2, 8);
  720. this.code = code;
  721. this.COPY_CODE = code;
  722. this.unicode = unicode || false;
  723. this.hooks = {};
  724. this.namespace = namespace;
  725. this.totalHooks = 0;
  726. }
  727.  
  728. static parseValue(value) {
  729. try {
  730. return Function(`return (${value})`)();
  731. } catch (err) {
  732. return null;
  733. }
  734. }
  735.  
  736. isRegexp(value) {
  737. return TYPEOF(value) === "regexp";
  738. }
  739.  
  740. generateNumberSystem(int) {
  741. const template = NumberSystem.map(
  742. ({ prefix, radix }) => prefix + int.toString(radix)
  743. );
  744. return `(?:${template.join("|")})`;
  745. }
  746.  
  747. parseVariables(regex) {
  748. regex = regex.replace(/\{VAR\}/g, "(?:let|var|const)");
  749. regex = regex.replace(/\{QUOTE\}/g, "['\"`]");
  750. regex = regex.replace(/ARGS\{(\d+)\}/g, (...args) => {
  751. let count = Number(args[1]),
  752. arr = [];
  753. while (count--) arr.push("\\w+");
  754. return arr.join("\\s*,\\s*");
  755. });
  756. regex = regex.replace(/NUMBER\{(\d+)\}/g, (...args) => {
  757. const int = Number(args[1]);
  758. return this.generateNumberSystem(int);
  759. });
  760. return regex;
  761. }
  762.  
  763. _hookName(name) {
  764. return `${this.namespace}:${name}`;
  765. }
  766.  
  767. format(name, inputRegex, flags) {
  768. this.totalHooks++;
  769. let regex = "";
  770. if (Array.isArray(inputRegex)) {
  771. regex = inputRegex
  772. .map((exp) => (this.isRegexp(exp) ? exp.source : exp))
  773. .join("\\s*");
  774. } else if (this.isRegexp(inputRegex)) {
  775. regex = inputRegex.source;
  776. }
  777. regex = this.parseVariables(regex);
  778. if (this.unicode) {
  779. regex = regex.replace(/\\w/g, "(?:[^\\x00-\\x7F-]|\\$|\\w)");
  780. }
  781. const expression = new RegExp(
  782. regex.replace(/\{INSERT\}/, ""),
  783. flags
  784. );
  785. return regex.includes("{INSERT}")
  786. ? new RegExp(regex, flags)
  787. : expression;
  788. }
  789.  
  790. template(type, name, regex, substr) {
  791. const hookName = this._hookName(name);
  792. const expression = new RegExp(
  793. `(${this.format(hookName, regex).source})`
  794. );
  795. const match = this.code.match(expression) || [];
  796. this.code = this.code.replace(
  797. expression,
  798. type === 0 ? "$1" + substr : substr + "$1"
  799. );
  800. this.hooks[hookName] = { expression, match };
  801. return match;
  802. }
  803.  
  804. logHooks() {
  805. log(
  806. "%cApplied Hooks:",
  807. "font-weight: bold; font-size: 24px; color:rgb(255, 255, 255); margin-top: 20px;"
  808. );
  809. let index = 1;
  810. for (const hookName in this.hooks) {
  811. const hook = this.hooks[hookName];
  812. const matches = Array.isArray(hook.match)
  813. ? hook.match
  814. : [hook.match];
  815. const status =
  816. matches && matches.length > 0
  817. ? "successful"
  818. : "unsuccessful";
  819. const style =
  820. matches && matches.length > 0
  821. ? "color:rgb(134, 204, 125); font-size: 14px;"
  822. : "color:rgb(221, 94, 113); font-size: 14px;";
  823. log(`%c${index}. ${hookName} | ${status}`, style);
  824. index++;
  825. }
  826. log(
  827. "%c-----------------",
  828. "font-weight: bold; color: gray; margin-bottom: 5px; margin-top: 20px;"
  829. );
  830. }
  831.  
  832. match(name, regex, flags) {
  833. const hookName = this._hookName(name);
  834. const expression = this.format(hookName, regex, flags);
  835. const match = this.code.match(expression) || [];
  836. this.hooks[hookName] = { expression, match };
  837. return match;
  838. }
  839.  
  840. replace(name, regex, substr, flags) {
  841. const hookName = this._hookName(name);
  842. const expression = this.format(hookName, regex, flags);
  843. const preMatch = this.code.match(expression) || [];
  844. this.code = this.code.replace(expression, substr);
  845. this.hooks[hookName] = {
  846. expression,
  847. match: preMatch,
  848. replaced: preMatch.length > 0,
  849. };
  850. return this.code.match(expression) || [];
  851. }
  852.  
  853. append(name, regex, substr) {
  854. return this.template(0, name, regex, substr);
  855. }
  856.  
  857. prepend(name, regex, substr) {
  858. return this.template(1, name, regex, substr);
  859. }
  860. }
  861.  
  862. const applyHooks = (code) => {
  863. const namespace = `waypoints_v${version}`;
  864. const Hook = new Regex(window.HOOKED_CODE || code, true, namespace);
  865.  
  866. window.COPY_CODE = (Hook.COPY_CODE.match(
  867. /^(\(function \w+\(\w+\)\{.+)\(.+?\);$/
  868. ) || [])[1];
  869. // log(Hook.COPY_CODE);
  870.  
  871. if (!window.HOOKED_CODE)
  872. Hook.append(
  873. "EXTERNAL fix",
  874. /\(function (\w+)\(\w+\)\{/,
  875. "let $2 = eval(`(() => ${COPY_CODE})()`); delete window.COPY_CODE;"
  876. );
  877. Hook.replace("LOADER", /Loading Sploop.io/, `Loading...`);
  878. Hook.append(
  879. "COORDS",
  880. /,this\.\w{2}=0\},this\.\w{2}=\w+\((\w),(\w),\w\)\{/,
  881. `window.coords = { x: $2, y: $3 };`
  882. );
  883. Hook.prepend("DRAW",/\w=\w\[\w\(\)\.\w+\],\w=\w.{7,8};for\(let \w=\d;\w\W\w;\w\+\+\)!\(\w\[\w\]\.\w+&\w\(\)\.\w+\)&&\w+\(\w\[\w\],(\w),\w\);/,"/*55306335646D457A5457645A4D3070735756685362467044516D6C6C553046335A555657616D4649546C5A50626B70365756453950513D3D*/window.draw($2);");
  884.  
  885. // log(Hook.code);
  886. window.HOOKED_CODE = Hook.code;
  887.  
  888. Hook.logHooks();
  889. return Hook.code;
  890. };
  891. window.eval = new Proxy(window.eval, {
  892. apply(target, _this, args) {
  893. const code = args[0];
  894. if (code.length > 1e5) {
  895. args[0] = applyHooks(code);
  896. window.eval = target;
  897. target.apply(_this, args);
  898. return;
  899. }
  900. return target.apply(_this, args);
  901. },
  902. });
  903. })();