您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds support for Faust mods
// ==UserScript== // @name FaustCore // @version 2025-02-21 // @description Adds support for Faust mods // @author Faust // @match https://esonline.su/ // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net // @grant none // @namespace https://gf.qytechs.cn/users/1437749 // ==/UserScript== (function() { "use strict"; var MessageReason; (function (MessageReason) { MessageReason.user_join = "userJoin"; MessageReason.user_leave = "userLeave"; MessageReason.node_data = "nodeData"; MessageReason.time_update = "serverTimecode"; MessageReason.client_move = "clientMove"; })(MessageReason || (MessageReason = {})); function getScreenResolution() { const resolutions = [ [1920, 1080], [1792, 1008], [1664, 936], [1536, 864], [1408, 792], [1280, 720], [1152, 648], [1024, 576], [896, 504], [768, 432], [640, 360], [512, 288], [384, 216], ]; const screen_width = window.innerWidth; const screen_height = window.innerHeight; let selected_resolution; for (let index in resolutions) { let resolution = resolutions[index]; if (resolution[0] <= screen_width && resolution[1] <= screen_height) { selected_resolution = resolution; break; } } if (!selected_resolution) { console.error("screen too small " + screen_width + "x" + screen_height); selected_resolution = resolutions[resolutions.length - 1]; } return selected_resolution; } function display_notification(text) { const elements = document.querySelectorAll("#notify"); if (elements.length > 0 && elements[0].parentElement) { elements[0].parentElement.removeChild(elements[0]); } const text_bubble = document.createElement("div"); text_bubble.id = "notify"; text_bubble.innerHTML = text; text_bubble.style.animationName = "hide"; text_bubble.style.animationDelay = "2s"; text_bubble.style.animationDuration = "0.5s"; text_bubble.style.animationFillMode = "forwards"; text_bubble.style.zIndex = "9999"; document.body.appendChild(text_bubble); text_bubble.addEventListener("animationend", () => { text_bubble.remove(); }); } class AbstractMenuItem { constructor() { this.is_added = false; this.is_hidden = false; this.main_div = document.createElement("div"); } addElement() { if (this.is_added) { return; } this.main_div = this.composeMainDiv(); document.body.appendChild(this.main_div); this.is_added = true; } removeElement() { if (!this.is_added) { return; } this.main_div.remove(); this.is_added = false; } hideElement() { if (!this.is_added) { return; } this.main_div.style.display = "none"; this.is_hidden = true; } unhideElement() { if (!this.is_added) { return; } this.main_div.style.display = "block"; this.is_hidden = false; } isShown() { return this.is_added; } isHidden() { return this.is_hidden; } } class MenuButtonsFactory { static buildButton(text, on_click) { const button = document.createElement("button"); button.style.borderRadius = "10px"; button.style.border = "2px solid rgba(3, 55, 170, 0.8)"; button.style.backgroundColor = "rgba(3, 55, 170, 0.8)"; button.style.color = "white"; button.style.padding = "5px 10px"; button.style.fontSize = "14px"; button.innerText = text; button.addEventListener("mouseenter", () => { button.style.backgroundColor = "white"; button.style.color = "rgba(3, 55, 170, 0.8)"; }); button.addEventListener("mouseleave", () => { button.style.backgroundColor = "rgba(3, 55, 170, 0.8)"; button.style.color = "white"; }); button.addEventListener("mousedown", on_click); return button; } } class TweakMenu extends AbstractMenuItem { constructor() { super(); } getScrollableArea(screen_height) { const scrollableDiv = document.createElement("div"); scrollableDiv.style.height = (screen_height / 3).toString() + "px"; scrollableDiv.style.overflow = "auto"; scrollableDiv.style.border = "1px solid #ccc"; scrollableDiv.style.padding = "10px"; scrollableDiv.style.backgroundColor = "rgba(0, 0, 0, 0.1)"; scrollableDiv.style.borderRadius = "10px"; scrollableDiv.style.marginBottom = "20px"; return scrollableDiv; } getTweakNameColor(tweak) { if (tweak.isEnabled()) { return "green"; } return "white"; } buildDivUponTweak() { const result = []; for (let iter = 0; iter < loaded_tweaks.length; iter++) { const entry = document.createElement("div"); entry.style.display = "flex"; entry.style.flexDirection = "row"; entry.style.alignItems = "center"; entry.style.justifyContent = "flex-start"; entry.style.borderRadius = "6px"; entry.style.border = "2px solid rgba(230, 224, 203, 0.6)"; const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.id = loaded_tweaks[iter].getTweakName(); checkbox.style.marginLeft = "10px"; checkbox.style.marginRight = "10px"; checkbox.checked = loaded_tweaks[iter].isEnabled(); checkbox.addEventListener("change", (event) => { const target = event.target; target.checked ? loaded_tweaks[iter].enable() : loaded_tweaks[iter].disable(); }); const label = document.createElement("label"); label.htmlFor = checkbox.id; label.innerText = checkbox.id; label.style.fontSize = "21px"; label.style.color = this.getTweakNameColor(loaded_tweaks[iter]); entry.appendChild(checkbox); entry.appendChild(label); result.push(entry); } return result; } composeMainDiv() { const result = document.createElement("div"); // resizing const resolution = getScreenResolution(); result.style.position = "fixed"; result.style.width = (resolution[0] / 2.5).toString() + "px"; result.style.height = "fit-content"; // Centering block result.style.top = "50%"; result.style.left = "50%"; result.style.transform = "translate(-50%, -50%)"; // Cosmetics result.style.padding = "20px"; result.style.backgroundColor = "rgba(0, 0, 0, 0.75)"; // transparent black result.style.borderRadius = "10px"; result.style.textAlign = "center"; result.style.backdropFilter = "blur(5px)"; result.style.zIndex = "9999"; const window_name = document.createElement("h2"); window_name.style.color = "white"; window_name.style.marginBottom = "20px"; window_name.innerText = "Меню твиков"; // TODO: add macros for resolution results (or even better, return a struct) const scroll_area = this.getScrollableArea(resolution[1]); const div_tweaks = this.buildDivUponTweak(); for (let iter = 0; iter < div_tweaks.length; iter++) { scroll_area.appendChild(div_tweaks[iter]); } result.appendChild(window_name); result.appendChild(scroll_area); result.appendChild(MenuButtonsFactory.buildButton("Close", () => this.removeElement())); return result; } } class GratitudeMenu extends AbstractMenuItem { constructor() { super(); } getScrollableArea(screen_height) { const scrollableDiv = document.createElement("div"); scrollableDiv.style.height = (screen_height / 4).toString() + "px"; scrollableDiv.style.overflow = "auto"; scrollableDiv.style.border = "1px solid #ccc"; scrollableDiv.style.padding = "10px"; scrollableDiv.style.backgroundColor = "rgba(0, 0, 0, 0.1)"; scrollableDiv.style.borderRadius = "10px"; scrollableDiv.style.marginBottom = "20px"; return scrollableDiv; } composeMainDiv() { const result = document.createElement("div"); // resizing const resolution = getScreenResolution(); result.style.position = "fixed"; result.style.width = (resolution[0] / 3).toString() + "px"; result.style.height = "fit-content"; // Centering block result.style.top = "50%"; result.style.left = "50%"; result.style.transform = "translate(-50%, -50%)"; // Cosmetics result.style.padding = "20px"; result.style.backgroundColor = "rgba(0, 0, 0, 0.75)"; // transparent black result.style.borderRadius = "10px"; result.style.textAlign = "center"; result.style.backdropFilter = "blur(5px)"; result.style.zIndex = "9999"; const window_name = document.createElement("h2"); window_name.style.color = "white"; window_name.style.marginBottom = "20px"; window_name.innerText = "Благодарности"; const scroll_area = this.getScrollableArea(resolution[1]); const gratitude_block = document.createElement("div"); gratitude_block.style.color = "white"; gratitude_block.style.fontSize = "16px"; gratitude_block.innerText = "Спасибо тебе, игрок, за то что даёшь проекту шанс на жизнь.\nТак же спасибо ребятами ждущим альфа-тест сюжетного твика. Ваша поддержка заставляла проект жить.\n\n Спасибо, TRIOLA.\nСпасибо, makter."; result.appendChild(window_name); result.appendChild(scroll_area); scroll_area.appendChild(gratitude_block); result.appendChild(MenuButtonsFactory.buildButton("Close", () => this.removeElement())); return result; } } /// <reference path="./menu_interface.ts" /> /// <reference path="../menu_button_factory.ts" /> /// <reference path="./tweaks_menu.ts" /> /// <reference path="./gratitude_menu.ts" /> class FaustCoreMenu extends AbstractMenuItem { constructor() { super(); this.tweak_menu = new TweakMenu(); this.gratitude_menu = new GratitudeMenu(); } composeMainDiv() { const result = document.createElement("div"); // positioning result.style.position = "absolute"; result.style.left = "50%"; result.style.top = "5%"; result.style.transform = "translate(-50%, -50%)"; // reshaping result.style.width = "fit-content"; result.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; result.style.color = "white"; result.style.zIndex = "9990"; result.style.borderRadius = "10px"; result.style.textAlign = "center"; result.style.backdropFilter = "blur(5px)"; // element positioning result.style.display = "flex"; result.style.flexDirection = "row"; result.style.alignItems = "center"; result.style.justifyContent = "flex-start"; result.style.gap = "20px"; result.style.padding = "10px"; const window_name = document.createElement("h2"); window_name.style.fontWeight = "bold"; window_name.style.color = "white"; window_name.innerText = "Faust Core"; result.appendChild(window_name); result.appendChild(MenuButtonsFactory.buildButton("Твики", () => this.tweak_menu.addElement())); result.appendChild(MenuButtonsFactory.buildButton("?", () => this.gratitude_menu.addElement())); return result; } } /// <reference path="./menu_windows/faust_core_menu.ts" /> class Application { constructor() { this.fcore_menu = new FaustCoreMenu(); this.fcore_menu.addElement(); } } const app = new Application(); const OriginalWebSocket = window.WebSocket; // backup original websocket var WebsocketListeners; (function (WebsocketListeners) { let receive_listeners = new Map(); let send_listeners = new Map(); function addReceiveListener(listener) { if (receive_listeners.has(listener.getTweakName())) { return false; } receive_listeners.set(listener.getTweakName(), listener); return true; } WebsocketListeners.addReceiveListener = addReceiveListener; function removeReceiveListener(tweak_name) { if (typeof tweak_name !== "string") { tweak_name = tweak_name.getTweakName(); } receive_listeners.delete(tweak_name); } WebsocketListeners.removeReceiveListener = removeReceiveListener; function addSendListener(listener) { if (send_listeners.has(listener.getTweakName())) { return false; } send_listeners.set(listener.getTweakName(), listener); return true; } WebsocketListeners.addSendListener = addSendListener; function removeSendListener(tweak_name) { if (typeof tweak_name !== "string") { tweak_name = tweak_name.getTweakName(); } send_listeners.delete(tweak_name); } WebsocketListeners.removeSendListener = removeSendListener; function triggerReceiveListener(data) { for (let [_, value] of receive_listeners) { value.processReceivedWebsocketMessage(data); } } WebsocketListeners.triggerReceiveListener = triggerReceiveListener; function triggerSendListener(data) { for (let [_, value] of send_listeners) { value.processSendedWebsocketMessage(data); } } WebsocketListeners.triggerSendListener = triggerSendListener; })(WebsocketListeners || (WebsocketListeners = {})); class PatchedWebSocket extends OriginalWebSocket { constructor(url, protocols) { super(url, protocols); // redefining send method const originalSend = this.send; this.send = (data) => { originalSend.call(this, data); WebsocketListeners.triggerSendListener(data); }; // redefining accept method this.addEventListener("message", (event) => { WebsocketListeners.triggerReceiveListener(event.data); }); } } // Redefining global websocket with Faust patch window.WebSocket = PatchedWebSocket; Object.defineProperties(window.WebSocket, { CONNECTING: { value: OriginalWebSocket.CONNECTING }, OPEN: { value: OriginalWebSocket.OPEN }, CLOSING: { value: OriginalWebSocket.CLOSING }, CLOSED: { value: OriginalWebSocket.CLOSED }, }); const loaded_tweaks = []; class Tweaks { constructor() { loaded_tweaks.push(this); } getTweakName() { return this.name; } isServerSide() { return this.sever_side; } isEnabled() { return this.is_enabled; } } /// <reference path="./tweak_interface.ts" /> class PlayerLister extends Tweaks { constructor() { super(); this.name = "Отображать меню с игроками на локации"; this.sever_side = false; this.is_enabled = false; // Init main div this.main_div = this.initPlayerListBlock(); this.main_div.style.display = "none"; // Hiding window document.body.appendChild(this.main_div); // sub div will remain empty this.player_list_div = document.createElement("div"); this.player_list_div.style.padding = "20px"; this.main_div.appendChild(this.player_list_div); this.is_dragging = false; this.offset_x = 0; this.offset_y = 0; this.players_on_location = new Map(); } enable() { this.is_enabled = true; this.main_div.style.display = "block"; WebsocketListeners.addReceiveListener(this); display_notification("Для обновления списка перезайдите на локацию."); } disable() { this.is_enabled = false; this.main_div.style.display = "none"; WebsocketListeners.removeReceiveListener(this); // Clearing info this.players_on_location.clear(); this.updatePlayerList(); } /** * @brief Parses user json entry from websocket * * @param user json info * @return PlayerInfo: parsed data */ parseSocketUserData(user) { const result = { id: user.id, name: user.name, color: user.color, }; return result; } processReceivedWebsocketMessage(websocket_event_data) { try { const parsedData = JSON.parse(websocket_event_data); switch (parsedData.reason) { case MessageReason.user_join: const user = this.parseSocketUserData(parsedData.user); this.players_on_location.set(user.id, user); break; case MessageReason.node_data: this.players_on_location.clear(); const users = parsedData.users; if (!Array.isArray(users)) { return; } users.forEach((user) => { user = this.parseSocketUserData(user); this.players_on_location.set(user.id, user); }); break; case MessageReason.user_leave: this.players_on_location.delete(parsedData.id); break; default: return; } this.updatePlayerList(); } catch (error) { console.error(error); } } processSendedWebsocketMessage(websocket_event_data) { } updatePlayerList() { this.player_list_div.innerHTML = ""; // Clearing list for (const [key, value] of this.players_on_location) { const player_entry = document.createElement("p"); player_entry.style.color = "#" + value.color; player_entry.innerText = key.toString() + " " + value.name; // player_entry.style.marginLeft = "10px"; this.player_list_div.appendChild(player_entry); } } initPlayerListBlock() { const movableDiv = document.createElement("div"); movableDiv.style.position = "fixed"; movableDiv.style.top = "100px"; movableDiv.style.left = "100px"; movableDiv.style.width = "fit-content"; movableDiv.style.height = "fit-content"; movableDiv.style.backdropFilter = "blur(5px)"; movableDiv.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; movableDiv.style.cursor = "grab"; movableDiv.style.borderRadius = "10px"; movableDiv.style.zIndex = "9990"; const window_name = document.createElement("h3"); window_name.style.color = "white"; window_name.innerText = "На локации:"; window_name.style.marginLeft = "5px"; window_name.style.marginRight = "5px"; window_name.style.marginTop = "5px"; movableDiv.appendChild(window_name); // Enabling element moving movableDiv.addEventListener("mousedown", (event) => { this.is_dragging = true; this.offset_x = event.clientX - movableDiv.getBoundingClientRect().left; this.offset_y = event.clientY - movableDiv.getBoundingClientRect().top; // removing selection while holding event.preventDefault(); }); document.addEventListener("mousemove", (event) => { if (this.is_dragging) { movableDiv.style.left = `${event.clientX - this.offset_x}px`; movableDiv.style.top = `${event.clientY - this.offset_y}px`; } }); document.addEventListener("mouseup", () => { this.is_dragging = false; }); // Adding element to page document.body.appendChild(movableDiv); return movableDiv; } } //TODO: must be a better way of doing this const player_lister_tweak = new PlayerLister(); //# sourceMappingURL=main.js.map })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址