您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Simple in-game chat application. Not as advantageous as using discord, a voice chat or playing in the same room, but still you can talk with your friends, you may talk with strangers, and it doesn't add lag to the game. When someone also have this extension, you will recognize them because of their blue name. You can speak with your teammates in the squad panel, in game, and they will receive your message even if you are out of their range or dead. Useful if you want to encourage them!
当前为
// ==UserScript== // @name Florr.io Chat with other Players // @description Simple in-game chat application. Not as advantageous as using discord, a voice chat or playing in the same room, but still you can talk with your friends, you may talk with strangers, and it doesn't add lag to the game. When someone also have this extension, you will recognize them because of their blue name. You can speak with your teammates in the squad panel, in game, and they will receive your message even if you are out of their range or dead. Useful if you want to encourage them! // @author Hirosoiko // @version 1.0 // @match *://florr.io/* // @run-at document-start // @require https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.1/socket.io.js // @grant unsafeWindow // @namespace none // ==/UserScript== let socket = io("https://florr-chat.glitch.me", { transports: ["websocket"] }); if (localStorage.florrio_nickname == "") { localStorage.florrio_nickname = "Chat User " + Math.floor(Math.random()*(999 - 100 + 1) + 100); } const latency = 100; const maxNameLength = 13; const namesColor = "#00ffff"; const msgRectColor = "#00000080"; const msgStrokeStyle = "#000000"; const msgFillStyle = "#ffffff"; const msgFadeMs = 125; const flowerMsgWidth = 300; const menuMsgWidth = 129; const delimiterChar = "-"; const inGameMsgOffset = 20; const inGameMsgFontSize = 20; const proxyId = 1234567890; let usualFlowerScale; let canvas; let inMenu = true; let alive = false; let aliveTO; let name = localStorage.florrio_nickname = localStorage.florrio_nickname.trim(); let currentPlayers = []; let pCurrentPlayers = currentPlayers; let notPlayers = []; let chatPlayers = []; let update = true; let wave = 0; let squad = ""; let squadTO; let messages = {}; let hideYou = false; let hideReady = []; let textInput; document.addEventListener("DOMContentLoaded", function() { canvas = document.getElementById("canvas"); textInput = document.createElement("input"); textInput.style = `display: none; position: absolute; left: 0; right: 0; top: ${unsafeWindow.innerHeight*5/8}px; margin-left: auto; margin-right: auto; width: 200px; height: 20px; border-radius: 25px; background-color: rgba(0, 0, 0, 0.1); outline: none; font-family: 'Ubuntu'; color: white;`; textInput.maxLength = 100; document.body.appendChild(textInput); textInput.addEventListener("blur", function() { this.style.display = "none"; }); }); const proxy = new Proxy(EventTarget.prototype.addEventListener, { set: (target, key, value) => { return true; }, get: (target, key) => { if (key !== "__isProxy") { return target[key]; } return true; }, apply(target, thisArg, args) { if (args[0] === 'noProxy') { if (target.__isProxy) { return Reflect.apply(target, thisArg, args); } else { return Reflect.apply(target, thisArg, args.slice(1)); } } if (args[2] == 0) { if (args[0] == "keydown" || args[0] == "keypress") { const temp = args[1]; args[1] = function (d) { if (d.target != textInput) { if (d.keyCode == 13 && args[0] != "keypress" && chatPlayers.length != 0) { if (textInput.style.display == "none") { textInput.style.display = "block"; setTimeout(() => textInput.focus(), 0); } } else { temp(d); } } else { if (args[0] != "keypress") { if (d.keyCode == 65 && (d.metaKey || d.ctrlKey)) { textInput.select(); } if (d.keyCode == 13) { if (textInput.style.display != "none") { textInput.style.display = "none"; if (!!textInput.value) { socket.emit("message", textInput.value); textInput.value = ""; } } } } } }; } } return Reflect.apply(...arguments); } }); EventTarget.prototype.addEventListener = proxy; function arraysEqual(a, b) { if (a === b) return true; if (a == null || b == null) return false; if (a.length !== b.length) return false; for (let i = 0; i < a.length; ++i) { if (a[i] !== b[i]) return false; } return true; } socket.on("notPlayers", (arr) => { notPlayers = [arr[0], new RegExp(arr[1])]; socket.emit("name", name); socket.emit("partyPlayers", currentPlayers); socket.emit("wave", wave); socket.emit("squad", squad); }); socket.on("chatPlayers", (arr) => { chatPlayers = arr; }); function msgPendingTime(message) { return Math.max(message.length*200, 2000); } function timeNowMs() { return new Date().getTime(); } socket.on("message", (arr) => { if (!!messages[arr[0]]) { clearTimeout(messages[arr[0]][2]); } if (arr[0] == name && hideYou) { hideYou = false; } messages[arr[0]] = [ arr[1], timeNowMs(), setTimeout(function() { if (arr[0] == name && hideYou) { hideYou = false; } delete messages[arr[0]]; }, msgPendingTime(arr[1])), true ]; }); socket.on("duplicate", (n) => { if (inMenu) { alert(`The name "${n}" already exists, you may change your name to enable the chat`); } }); socket.on("unnamed", () => { alert(`You need to have a name to enable the chat`); }); socket.on("invalid", (n) => { alert(`The name "${n}" isn't accepted by the script, you may change your name to enable the chat`); }); function updateInfo() { setTimeout(function() { update = false; if (!arraysEqual(currentPlayers, pCurrentPlayers)) { socket.emit("partyPlayers", currentPlayers); } pCurrentPlayers = currentPlayers; currentPlayers = []; setTimeout(function() { update = true; if (name != localStorage.florrio_nickname) { name = localStorage.florrio_nickname = localStorage.florrio_nickname.trim(); socket.emit("name", name); } updateInfo(); }, 1000); }, latency); } updateInfo(); function maxOcc(array) { if (array.length == 0) { return null; } let modeMap = {}; let maxEl = array[0]; let maxCount = 1; for(let i = 0; i < array.length; i++) { const el = array[i]; if (modeMap[el] == null) { modeMap[el] = 1; } else { modeMap[el]++; } if (modeMap[el] > maxCount) { maxEl = el; maxCount = modeMap[el]; } else if (modeMap[el] == maxCount && maxEl > el) { maxEl = el; } } return maxEl; } var flowerScales = []; function updateFlowerScale(scale) { flowerScales.push(scale); if (flowerScales.length > 6) { flowerScales.shift(); } return maxOcc(flowerScales); } function roundRect(ctx, x, y, width, height, radius = 5, fill = false, stroke = true) { if (typeof radius === 'number') { radius = {tl: radius, tr: radius, br: radius, bl: radius}; } else { radius = {...{tl: 0, tr: 0, br: 0, bl: 0}, ...radius}; } ctx.beginPath(); ctx.moveTo(x + radius.tl, y); ctx.lineTo(x + width - radius.tr, y); ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr); ctx.lineTo(x + width, y + height - radius.br); ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height); ctx.lineTo(x + radius.bl, y + height); ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl); ctx.lineTo(x, y + radius.tl); ctx.quadraticCurveTo(x, y, x + radius.tl, y); ctx.closePath(); if (fill) { ctx.fill(); } if (stroke) { ctx.stroke(); } } const canvasCtx = !!unsafeWindow.OffscreenCanvasRenderingContext2D ? "OffscreenCanvasRenderingContext2D" : !!unsafeWindow.CanvasRenderingContext2D ? "CanvasRenderingContext2D" : ""; if (!!canvasCtx) { const fillTextProxy = new Proxy(unsafeWindow[canvasCtx].prototype.fillText, { get: (target, key) => { if (key !== "__isProxy") { return target[key]; } return true; }, set: (target, key, value) => { return true; }, apply(target, ctx, args) { const text = args[0]; if (text === 'noProxy') { if (target.__isProxy) { return Reflect.apply(target, ctx, args); } else { return Reflect.apply(target, ctx, args.slice(1)); } } if (args[3] != proxyId) { if (!inMenu && text == "A mysterious entity" && ctx.font == "24px Ubuntu") { inMenu = true; messages = {} currentPlayers = []; wave = 0; socket.emit("wave", wave); } if (text == "[1]" && ctx.font == "14px Ubuntu") { if (inMenu) { inMenu = false; if (squad != "") { squad = ""; socket.emit("squad", squad); } for (let uName in messages) { if (Array.isArray(messages[uName][0])) { messages[uName][0] = messages[uName][0][1]; messages[uName][3] = true; messages[uName][4] = null; } } } if (!alive) { alive = true; } if (!!aliveTO) { clearTimeout(aliveTO); } aliveTO = setTimeout(function() { alive = false; }, latency); } if (/^Wave [1-9][0-9]*$/.test(text) && ctx.font == "16px Ubuntu" && wave != Number(text.match(/[1-9][0-9]*/)[0])) { wave = Number(text.match(/[1-9][0-9]*/)[0]); socket.emit("wave", wave); } if (!inMenu && text.length <= maxNameLength) { if (ctx.font == "18px Ubuntu" && notPlayers.length != 0 && !notPlayers[0].includes(text) && !notPlayers[1].test(text)) { if (!currentPlayers.includes(text)) { currentPlayers.push(text); } if (chatPlayers.includes(text)) { ctx.fillStyle = namesColor; } for (let uName in messages) { if (text == uName && (text != name || !inMenu && !alive) && messages[uName][3] && !messages[uName][4]) { messages[uName][4] = ctx.getTransform(); break; } } } else if (text == "[1]" && ctx.font == "14px Ubuntu" || !inMenu && !alive && /^Wave [1-9][0-9]*$/.test(text) && ctx.font == "16px Ubuntu") { ctx.strokeText(text, 0, 0, proxyId); ctx.fillText(text, 0, 0, proxyId); for (let uName in messages) { if (messages[uName][3] && !!messages[uName][4] && (uName != name || !inMenu && !alive) && chatPlayers.includes(uName)) { ctx.save(); ctx.setTransform(messages[uName][4]); const fontSize = inGameMsgFontSize; ctx.font = fontSize + "px Ubuntu"; const borderSpace = fontSize; const message = Array.isArray(messages[uName][0]) ? messages[uName][0][1] : messages[uName][0]; const width = ctx.measureText(message).width + borderSpace; const height = fontSize + borderSpace; const offsetX = 110; const offsetY = - fontSize; ctx.globalAlpha = Math.max(0, Math.min((timeNowMs() - messages[uName][1])/msgFadeMs, 1, Math.min(((msgPendingTime(message)) - (timeNowMs() - messages[uName][1])), msgFadeMs)/msgFadeMs)); ctx.fillStyle = msgRectColor; roundRect(ctx, offsetX - borderSpace/2, - height - offsetY, width, height, 5, true, false); ctx.strokeStyle = msgStrokeStyle; ctx.fillStyle = msgFillStyle; ctx.textAlign = "left"; ctx.strokeText(message, offsetX, - height - offsetY + fontSize, proxyId); ctx.fillText(message, offsetX, - height - offsetY + fontSize, proxyId); ctx.restore(); } } return; } } } return Reflect.apply(...arguments); } }); unsafeWindow[canvasCtx].prototype.fillText = fillTextProxy; } else { alert(`Your browser doesn't support the script "Florr.io Chat with other Players", you may consider switching browser for browsers like Chrome, Opera or Firefox to make it work`); } const canvasProxy = new Proxy(unsafeWindow.HTMLCanvasElement.prototype.getContext, { get: (target, key) => { if (key !== "__isProxy") { return target[key]; } return true; }, set: (target, key, value) => { return true; }, apply(target, thisArg, args) { const ctx = Reflect.apply(...arguments); const prototype = Object.getPrototypeOf(ctx); const descriptors = Object.getOwnPropertyDescriptors(prototype); Object.defineProperties(prototype, { strokeText: { value(text, x, y, maxWidth) { if (maxWidth != proxyId) { if (inMenu && text.length <= maxNameLength) { if (ctx.font == "16px Ubuntu" && text == "(you)" && hideYou || ctx.font == "20px Ubuntu" && text == "Ready" && hideReady.includes(ctx.getTransform().e.toFixed(3))) { return; } else if (ctx.font == "16px Ubuntu" && notPlayers.length != 0 && !notPlayers[0].includes(text) && !notPlayers[1].test(text) && !/^[a-z0-9]{12}$/.test(text) && (text != "(you)" || hideYou)) { text = text.trim(); } for (let uName in messages) { if (text == uName) { if (messages[uName][0][0].length >= 4) { return; } break; } } } } return descriptors.strokeText.value.call(this, text, x, y, maxWidth); } }, fillText: { value(text, x, y, maxWidth) { if (maxWidth != proxyId) { if (inMenu && /^Code: [a-z0-9]{3}-[a-z0-9]{6}$/.test(text)) { if (squad != text) { squad = text; socket.emit("squad", squad); } if (!!squadTO) { clearTimeout(squadTO); } squadTO = setTimeout(function() { squad = ""; socket.emit("squad",squad); }, latency); } if (text.length <= maxNameLength) { if (!inMenu) { if (ctx.font == "24px Ubuntu" && notPlayers.length != 0 && !notPlayers[0].includes(text) && !notPlayers[1].test(text) && text.trim() != name) { text = text.trim(); if (chatPlayers.includes(text)) { ctx.fillStyle = namesColor; } const gT = ctx.getTransform(); const flowerScale = updateFlowerScale(gT.d); if (usualFlowerScale != flowerScale) { usualFlowerScale = flowerScale; } for (let uName in messages) { if (text == uName) { if (alive) { messages[uName][6] = gT; if (!!messages[uName][7]) { clearTimeout(messages[uName][7]); } messages[uName][7] = setTimeout(function(n) { if (!!messages[n]) { messages[n][6] = null; } }, latency, uName); } else { ctx.save(); const fontSize = inGameMsgFontSize; ctx.font = fontSize + "px Ubuntu"; let width = flowerMsgWidth; const borderSpace = fontSize; let splitText; if (!Array.isArray(messages[uName][0])) { const message = messages[uName][0].split(/( )/); splitText = [""]; for (let i = 0; i < message.length; i++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i]).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i]; } else if (ctx.measureText(message[i]).width < width - borderSpace && splitText[splitText.length - 1] !== "") { splitText.push(message[i]); } else { if (splitText[splitText.length - 1] !== "") { splitText.push(""); } for (let j = 0; j < message[i].length; j++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i][j] + delimiterChar).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i][j]; } else { splitText[splitText.length - 1] = splitText[splitText.length - 1] + delimiterChar; splitText.push(message[i][j]); } } } } messages[uName][0] = [splitText, messages[uName][0]]; } else { splitText = messages[uName][0][0]; } if (splitText.length == 1) { width = ctx.measureText(splitText[0]).width + borderSpace; } const textInterSpace = fontSize/5; const height = fontSize*splitText.length + borderSpace + splitText.length*textInterSpace; const offset = inGameMsgOffset; ctx.globalAlpha = Math.max(0, Math.min((timeNowMs() - messages[uName][1])/msgFadeMs, 1, Math.min(((msgPendingTime(messages[uName][0][1])) - (timeNowMs() - messages[uName][1])), msgFadeMs)/msgFadeMs)); ctx.fillStyle = msgRectColor; roundRect(ctx, - width/2, - height - offset, width, height, 5, true, false); if (!messages[uName][3] && (gT.e - (width/2 - width)*gT.a < 0 || gT.e - (width/2)*gT.a > canvas.width || gT.f - (height + offset - height)*gT.d < 0 || gT.f - (height + offset)*gT.d > canvas.height)) { messages[uName][3] = true; } else if (messages[uName][3] && !(gT.e - (width/2 - width)*gT.a < 0 || gT.e - (width/2)*gT.a > canvas.width || gT.f - (height + offset - height)*gT.d < 0 || gT.f - (height + offset)*gT.d > canvas.height)) { messages[uName][3] = false; if (!!messages[uName][5]) { clearTimeout(messages[uName][5]); } messages[uName][5] = setTimeout(function(n) { if (!!messages[n]) { messages[n][3] = true; } }, latency, uName); if (!!messages[uName][4]) { messages[uName][4] = null; } } ctx.strokeStyle = msgStrokeStyle; ctx.fillStyle = msgFillStyle; ctx.textAlign = "center"; for (let i = 0; i < splitText.length; i++) { ctx.strokeText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1) - textInterSpace/2, proxyId); ctx.fillText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1) - textInterSpace/2, proxyId); } ctx.restore(); } break; } } } } else if (inMenu) { const gT = ctx.getTransform(); if (ctx.font == "20px Ubuntu" && text == "Ready" && hideReady.includes(gT.e.toFixed(3))) { return; } if (ctx.font == "16px Ubuntu" && notPlayers.length != 0 && !notPlayers[0].includes(text) && !notPlayers[1].test(text) && !/^[a-z0-9]{12}$/.test(text) && (text != "(you)" || hideYou)) { if (text == "(you)" && hideYou) { return; } text = text.trim(); if (!currentPlayers.includes(text)) { currentPlayers.push(text); } if (chatPlayers.includes(text)) { ctx.fillStyle = namesColor; } for (let uName in messages) { if (text == uName) { const fontSize = Number(ctx.font.match(/\d+/)[0]); let width = menuMsgWidth; const borderSpace = fontSize; let splitText; if (!Array.isArray(messages[uName][0])) { const message = messages[uName][0].split(/( )/); splitText = [""]; for (let i = 0; i < message.length; i++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i]).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i]; } else if (ctx.measureText(message[i]).width < width - borderSpace && splitText[splitText.length - 1] !== "") { splitText.push(message[i]); } else { if (splitText[splitText.length - 1] !== "") { splitText.push(""); } for (let j = 0; j < message[i].length; j++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i][j] + delimiterChar).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i][j]; } else { splitText[splitText.length - 1] = splitText[splitText.length - 1] + delimiterChar; splitText.push(message[i][j]); } } } } if (splitText.length >= 4) { splitText.unshift(text + ":"); } messages[uName][0] = [splitText, messages[uName][0]]; } else { splitText = messages[uName][0][0]; } if (uName == name && splitText.length > 1 && !hideYou) { hideYou = true; } if (!hideReady.includes(gT.e.toFixed(3))) { hideReady.push(gT.e.toFixed(3)); setTimeout(function() { hideReady.shift(); }, msgPendingTime(messages[uName][0][1]) - (timeNowMs() - messages[uName][1])); } if (splitText.length == 1) { width = ctx.measureText(splitText[0]).width + borderSpace; } const textInterSpace = fontSize/5; const height = fontSize*splitText.length + borderSpace + 3 + splitText.length*textInterSpace; const offset = Math.max(-50-height/2, -103); ctx.save(); ctx.globalAlpha = Math.max(0, Math.min((timeNowMs() - messages[uName][1])/msgFadeMs, 1, Math.min(msgPendingTime(messages[uName][0][1]) - (timeNowMs() - messages[uName][1]), msgFadeMs)/msgFadeMs)); ctx.fillStyle = msgRectColor; roundRect(ctx, - width/2, - height - offset, width, height, 5, true, false); ctx.strokeStyle = msgStrokeStyle; for (let i = 0; i < splitText.length; i++) { if (i == 0 && splitText.length >= 4) { ctx.fillStyle = namesColor; } else if (ctx.fillStyle != msgFillStyle) { ctx.fillStyle = msgFillStyle; } ctx.strokeText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1), proxyId); ctx.fillText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1), proxyId); } ctx.restore(); if (splitText.length >= 4 && gT.a != 1) { return; } break; } } } } } } return descriptors.fillText.value.call(this, text, x, y, maxWidth); } }, arc: { value(x, y, r, s, e, c) { if (alive) { const gT = ctx.getTransform(); const radius = 25; const xCenter = canvas.width/2; const yCenter = canvas.height/2; if (e == 2*Math.PI && gT.e > xCenter - radius/2 && gT.e < xCenter + radius/2 && gT.f > yCenter - radius/2 && gT.f < yCenter + radius/2 && r == radius && gT.b == 0 && gT.c == 0 && ctx.globalAlpha == 1) { ctx.save(); for (let uName in messages) { if (!!messages[uName][6]) { ctx.setTransform(messages[uName][6]); const gT = messages[uName][6]; const fontSize = inGameMsgFontSize; ctx.font = fontSize + "px Ubuntu"; let width = flowerMsgWidth; const borderSpace = fontSize; let splitText; if (!Array.isArray(messages[uName][0])) { const message = messages[uName][0].split(/( )/); splitText = [""]; for (let i = 0; i < message.length; i++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i]).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i]; } else if (ctx.measureText(message[i]).width < width - borderSpace && splitText[splitText.length - 1] !== "") { splitText.push(message[i]); } else { if (splitText[splitText.length - 1] !== "") { splitText.push(""); } for (let j = 0; j < message[i].length; j++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i][j] + delimiterChar).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i][j]; } else { splitText[splitText.length - 1] = splitText[splitText.length - 1] + delimiterChar; splitText.push(message[i][j]); } } } } messages[uName][0] = [splitText, messages[uName][0]]; } else { splitText = messages[uName][0][0]; } if (splitText.length == 1) { width = ctx.measureText(splitText[0]).width + borderSpace; } const textInterSpace = fontSize/5; const height = fontSize*splitText.length + borderSpace + splitText.length*textInterSpace; const offset = inGameMsgOffset; ctx.globalAlpha = Math.max(0, Math.min((timeNowMs() - messages[uName][1])/msgFadeMs, 1, Math.min(((msgPendingTime(messages[uName][0][1])) - (timeNowMs() - messages[uName][1])), msgFadeMs)/msgFadeMs)); ctx.fillStyle = msgRectColor; roundRect(ctx, - width/2, - height - offset, width, height, 5, true, false); if (!messages[uName][3] && (gT.e - (width/2 - width)*gT.a < 0 || gT.e - (width/2)*gT.a > canvas.width || gT.f - (height + offset - height)*gT.d < 0 || gT.f - (height + offset)*gT.d > canvas.height)) { messages[uName][3] = true; } else if (messages[uName][3] && !(gT.e - (width/2 - width)*gT.a < 0 || gT.e - (width/2)*gT.a > canvas.width || gT.f - (height + offset - height)*gT.d < 0 || gT.f - (height + offset)*gT.d > canvas.height)) { messages[uName][3] = false; if (!!messages[uName][5]) { clearTimeout(messages[uName][5]); } messages[uName][5] = setTimeout(function(n) { if (!!messages[n]) { messages[n][3] = true; } }, latency, uName); if (!!messages[uName][4]) { messages[uName][4] = null; } } ctx.strokeStyle = msgStrokeStyle; ctx.fillStyle = msgFillStyle; ctx.textAlign = "center"; for (let i = 0; i < splitText.length; i++) { ctx.strokeText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1) + 5, proxyId); ctx.fillText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1) + 5, proxyId); } } } ctx.restore(); if (!!messages[name]) { ctx.save(); const rScaling = gT.d/unsafeWindow.devicePixelRatio; ctx.setTransform(usualFlowerScale, gT.b, gT.c, usualFlowerScale, gT.e, gT.f); const fontSize = inGameMsgFontSize; ctx.font = fontSize + "px Ubuntu"; let width = flowerMsgWidth; const borderSpace = fontSize; let splitText; if (!Array.isArray(messages[name][0])) { const message = messages[name][0].split(/( )/); splitText = [""]; for (let i = 0; i < message.length; i++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i]).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i]; } else if (ctx.measureText(message[i]).width < width - borderSpace && splitText[splitText.length - 1] !== "") { splitText.push(message[i]); } else { if (splitText[splitText.length - 1] !== "") { splitText.push(""); } for (let j = 0; j < message[i].length; j++) { if (ctx.measureText(splitText[splitText.length - 1] + message[i][j] + delimiterChar).width < width - borderSpace) { splitText[splitText.length - 1] = splitText[splitText.length - 1] + message[i][j]; } else { splitText[splitText.length - 1] = splitText[splitText.length - 1] + delimiterChar; splitText.push(message[i][j]); } } } } messages[name][0] = [splitText, messages[name][0]]; } else { splitText = messages[name][0][0]; } if (splitText.length == 1) { width = ctx.measureText(splitText[0]).width + borderSpace; } const textInterSpace = fontSize/5; const height = fontSize*splitText.length + borderSpace + splitText.length*textInterSpace; const offset = radius*rScaling*2 + inGameMsgOffset + 10; ctx.globalAlpha = Math.max(0, Math.min((timeNowMs() - messages[name][1])/msgFadeMs, 1, Math.min(((msgPendingTime(messages[name][0][1])) - (timeNowMs() - messages[name][1])), msgFadeMs)/msgFadeMs)); ctx.fillStyle = msgRectColor; roundRect(ctx, - width/2, - height - offset, width, height, 5, true, false); ctx.strokeStyle = msgStrokeStyle; ctx.fillStyle = msgFillStyle; ctx.textAlign = "center"; for (let i = 0; i < splitText.length; i++) { ctx.strokeText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1) + 5, proxyId); ctx.fillText(splitText[i], 0, - height - offset + (fontSize + textInterSpace)*(i + 1) + 5, proxyId); } ctx.restore(); } ctx.beginPath(); ctx.closePath(); } } return descriptors.arc.value.call(this, x, y, r, s, e, c); } } }); return ctx; } }); unsafeWindow.HTMLCanvasElement.prototype.getContext = canvasProxy;
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址