Waypoints [Sploop.io]

Easily traverse the world of Sploop.io with Waypoints!

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

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址