// ==UserScript== // @name 替换API返回坐标(支持上传TXT坐标文件并持久化) // @namespace https://ff14risingstones.web.sdo.com/ // @version 0.0.1 // @description 拦截接口返回数据,并将其中的 x,y 坐标替换为自定义坐标。支持上传 TXT 坐标文件并保存到 localStorage,刷新页面后依然有效 // @author Cindy-Master // @match https://ff14risingstones.web.sdo.com/* // @grant none // @run-at document-start // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; let customCoords = []; const STORAGE_KEY = "customCoords"; function loadCoordsFromStorage() { const stored = localStorage.getItem(STORAGE_KEY); if (stored) { try { customCoords = JSON.parse(stored); } catch (e) { console.error("读取持久化坐标失败:", e); customCoords = []; } } } loadCoordsFromStorage(); function createUI() { const container = document.createElement("div"); container.style.position = "fixed"; container.style.top = "10px"; container.style.right = "10px"; container.style.zIndex = "9999"; container.style.background = "rgba(255,255,255,0.9)"; container.style.padding = "10px"; container.style.border = "1px solid #ccc"; container.style.fontSize = "12px"; container.style.color = "#333"; container.style.fontFamily = "Arial, sans-serif"; container.innerHTML = `
上传坐标文件(TXT):
格式示例:
Contour 1:
(110, 182)

Contour 2:
(108, 181)

GitHub:https://github.com/Cindy-Master/FFXIV-StoneDeathPos `; document.body.appendChild(container); updateStatus(); document.getElementById("coordsFile").addEventListener("change", handleFileSelect); } function updateStatus() { const statusEl = document.getElementById("coordsStatus"); if (statusEl) { statusEl.innerText = `当前加载坐标:${customCoords.length}个`; } } function handleFileSelect(event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const text = e.target.result; parseCoords(text); }; reader.readAsText(file); } function parseCoords(text) { const lines = text.split(/\r?\n/); const coords = []; const regex = /^\(\s*([\d.]+)\s*,\s*([\d.]+)\s*\)$/; for (let line of lines) { line = line.trim(); const match = line.match(regex); if (match) { coords.push({ point_x: match[1], point_y: match[2] }); } } customCoords = coords; // 保存到 localStorage localStorage.setItem(STORAGE_KEY, JSON.stringify(customCoords)); updateStatus(); console.log("上传并保存的坐标数据:", customCoords); } window.addEventListener("DOMContentLoaded", createUI); const originalOpen = XMLHttpRequest.prototype.open; const originalSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function(method, url) { this._url = url; return originalOpen.apply(this, arguments); }; XMLHttpRequest.prototype.send = function() { if (this._url && this._url.includes("gaoNanDeadPoint5")) { this.addEventListener("readystatechange", function() { if (this.readyState === 4 && this.status === 200) { try { let dataObj = JSON.parse(this.responseText); if (customCoords.length > 0 && dataObj && Array.isArray(dataObj.data)) { dataObj.data = customCoords.map((coord, index) => { const origItem = dataObj.data[index] || {}; return Object.assign({}, origItem, { point_x: coord.point_x, point_y: coord.point_y }); }); } Object.defineProperty(this, "response", { get: function() { return JSON.stringify(dataObj); } }); Object.defineProperty(this, "responseText", { get: function() { return JSON.stringify(dataObj); } }); } catch (err) { console.error("修改 API 返回数据失败:", err); } } }); } return originalSend.apply(this, arguments); }; })();