您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Enhanced drawing cheat menu for Drawaria with modern floating UI
// ==UserScript== // @name Drawaria Multidrawing Mode Full! // @namespace http://tampermonkey.net/ // @version 1.1 // @description Enhanced drawing cheat menu for Drawaria with modern floating UI // @author YouTubeDrawaria // @license MIT // @include https://drawaria.online* // @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online // @require https://cdn.tailwindcss.com // ==/UserScript== (function() { 'use strict'; // DOM Utilities const EL = (sel) => document.querySelector(sel); const ELL = (sel) => document.querySelectorAll(sel); // Drawing Tools State let drawing_active = false; let previewCanvas = document.createElement('canvas'); let originalCanvas = EL('#canvas'); let data; let cw, ch; let executionLine = []; let drawMode = 'zigzag'; // 'normal', 'spiral', 'wave', or 'zigzag' // Room & Socket Control window.myRoom = {}; window.sockets = []; const originalSend = WebSocket.prototype.send; WebSocket.prototype.send = function(...args) { if (window.sockets.indexOf(this) === -1) { window.sockets.push(this); if (window.sockets.indexOf(this) === 0) { this.addEventListener('message', (event) => { let message = String(event.data); if (message.startsWith('42')) { let payload = JSON.parse(message.slice(2)); if (payload[0] === 'bc_uc_freedrawsession_changedroom') { window.myRoom.players = payload[3]; } if (payload[0] === 'mc_roomplayerschange') { window.myRoom.players = payload[3]; } } else if (message.startsWith('41')) { // Handle disconnect } else if (message.startsWith('430')) { let configs = JSON.parse(message.slice(3))[0]; window.myRoom.players = configs.players; window.myRoom.id = configs.roomid; } }); } } return originalSend.call(this, ...args); }; // Create Floating Menu function createFloatingMenu() { const menu = document.createElement('div'); menu.id = 'cheat-menu'; menu.className = 'fixed top-20 right-4 w-80 bg-gray-800 text-white rounded-lg shadow-xl z-50 p-4 max-h-[80vh] overflow-y-auto'; menu.innerHTML = ` <div class="flex justify-between items-center mb-4"> <h2 class="text-lg font-bold">Drawaria Multidrawing Mode Full!</h2> <button id="toggle-menu" class="text-gray-400 hover:text-white"> <i class='bx bx-x'></i> </button> </div> <div id="cheat-content" class="space-y-4"> <div> <label class="block text-sm font-medium">Image Upload</label> <input type="file" id="IPutImage" class="w-full bg-gray-700 rounded p-2 text-sm"> </div> <div> <label class="block text-sm font-medium">Bot Name</label> <input type="text" id="inputName" placeholder="Bot Name" class="w-full bg-gray-700 rounded p-2 text-sm"> </div> <div class="grid grid-cols-3 gap-2"> <button id="botJoin" class="bg-blue-600 hover:bg-blue-700 rounded p-2 text-sm flex items-center justify-center"><i class='bx bx-user-plus mr-1'></i>Join</button> <button id="botLeave" class="bg-red-600 hover:bg-red-700 rounded p-2 text-sm flex items-center justify-center"><i class='bx bx-user-minus mr-1'></i>Leave</button> <button id="canvasClear" class="bg-gray-600 hover:bg-gray-700 rounded p-2 text-sm flex items-center justify-center"><i class='bx bxs-eraser mr-1'></i>Clear</button> </div> <div> <label class="block text-sm font-medium">Drawing Controls</label> <div class="grid grid-cols-2 gap-2"> <div> <label class="text-xs">Image Size</label> <input type="number" id="engine_imagesize" min="1" max="10" value="4" class="w-full bg-gray-700 rounded p-1 text-sm"> </div> <div> <label class="text-xs">Brush Size</label> <input type="number" id="engine_brushsize" min="2" max="20" value="4" class="w-full bg-gray-700 rounded p-1 text-sm"> </div> <div> <label class="text-xs">Pixel Distance</label> <input type="number" id="engine_pixelsize" min="2" max="20" value="2" class="w-full bg-gray-700 rounded p-1 text-sm"> </div> <div> <label class="text-xs">Offset X</label> <input type="number" id="engine_offset_x" min="0" max="100" value="0" class="w-full bg-gray-700 rounded p-1 text-sm"> </div> <div> <label class="text-xs">Offset Y</label> <input type="number" id="engine_offset_y" min="0" max="100" value="0" class="w-full bg-gray-700 rounded p-1 text-sm"> </div> </div> </div> <div> <label class="block text-sm font-medium">Draw Mode</label> <div class="grid grid-cols-3 gap-2"> <button id="setZigzagMode" class="bg-green-600 hover:bg-green-700 rounded p-2 text-sm flex items-center justify-center active-mode"><i class='bx bx-zigzag mr-1'></i>Zigzag</button> <button id="setWaveMode" class="bg-blue-600 hover:bg-blue-700 rounded p-2 text-sm flex items-center justify-center"><i class='bx bx-wave mr-1'></i>Wave</button> <button id="setSpiralMode" class="bg-purple-600 hover:bg-purple-700 rounded p-2 text-sm flex items-center justify-center"><i class='bx bx-spiral mr-1'></i>Spiral</button> </div> </div> <div class="grid grid-cols-2 gap-2"> <button id="botStartDrawing" class="bg-green-600 hover:bg-green-700 rounded p-2 text-sm flex items-center justify-center"><i class='bx bx-play-circle mr-1'></i>Start</button> <button id="botStopDrawing" class="bg-red-600 hover:bg-red-700 rounded p-2 text-sm flex items-center justify-center"><i class='bx bx-stop-circle mr-1'></i>Stop</button> </div> </div> `; document.body.appendChild(menu); // Make menu draggable let isDragging = false; let currentX, currentY, initialX, initialY; const header = menu.querySelector('div:first-child'); header.addEventListener('mousedown', (e) => { initialX = e.clientX - currentX; initialY = e.clientY - currentY; isDragging = true; }); document.addEventListener('mousemove', (e) => { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; menu.style.left = currentX + 'px'; menu.style.top = currentY + 'px'; menu.style.right = 'auto'; } }); document.addEventListener('mouseup', () => { isDragging = false; }); // Toggle menu visibility const toggleBtn = EL('#toggle-menu'); const content = EL('#cheat-content'); toggleBtn.addEventListener('click', () => { content.classList.toggle('hidden'); toggleBtn.innerHTML = content.classList.contains('hidden') ? `<i class='bx bx-menu'></i>` : `<i class='bx bx-x'></i>`; }); // Initialize position currentX = window.innerWidth - menu.offsetWidth - 16; currentY = 80; menu.style.left = currentX + 'px'; menu.style.top = currentY + 'px'; } // Add Boxicons function addBoxIcons() { const link = document.createElement('link'); link.href = 'https://unpkg.com/[email protected]/css/boxicons.min.css'; link.rel = 'stylesheet'; document.head.appendChild(link); } // Image Loader function setupImageLoader() { EL('#IPutImage').addEventListener('change', function() { if (!this.files || !this.files[0]) return; const FR = new FileReader(); FR.addEventListener('load', (evt) => { loadImage(evt.target.result); }); FR.readAsDataURL(this.files[0]); }); } // Bot Controls function setupBotControls() { EL('#botJoin').addEventListener('click', () => { window['___BOT'].room.join(EL('#invurl')?.value || null); }); EL('#botLeave').addEventListener('click', () => { window['___BOT'].conn.socket.close(); }); EL('#canvasClear').addEventListener('click', () => { window['___BOT'].action.DrawLine(50, 50, 50, 50, 2000); }); } // Drawing Controls function setupDrawingControls() { EL('#setZigzagMode').addEventListener('click', function() { drawMode = 'zigzag'; updateModeButtons(this); }); EL('#setWaveMode').addEventListener('click', function() { drawMode = 'wave'; updateModeButtons(this); }); EL('#setSpiralMode').addEventListener('click', function() { drawMode = 'spiral'; updateModeButtons(this); }); EL('#botStopDrawing').addEventListener('click', () => { drawing_active = false; }); EL('#botStartDrawing').addEventListener('click', () => { let size = parseInt(EL('#engine_imagesize').value); let modifier = parseInt(EL('#engine_pixelsize').value); let thickness = parseInt(EL('#engine_brushsize').value); let offset = { x: parseInt(EL('#engine_offset_x').value), y: parseInt(EL('#engine_offset_y').value), }; drawImage(size, modifier, thickness, offset); execute(window['___BOT'].conn.socket); }); function updateModeButtons(activeButton) { const buttons = ['setZigzagMode', 'setWaveMode', 'setSpiralMode']; buttons.forEach(id => { const btn = EL(`#${id}`); btn.classList.toggle('bg-green-600', btn === activeButton); btn.classList.toggle('bg-blue-600', btn !== activeButton && id === 'setWaveMode'); btn.classList.toggle('bg-purple-600', btn !== activeButton && id === 'setSpiralMode'); btn.classList.toggle('hover:bg-green-700', btn === activeButton); btn.classList.toggle('hover:bg-blue-700', btn !== activeButton && id === 'setWaveMode'); btn.classList.toggle('hover:bg-purple-700', btn !== activeButton && id === 'setSpiralMode'); }); } } // Image Processing function loadImage(url) { const img = new Image(); img.addEventListener('load', () => { previewCanvas.width = originalCanvas.width; previewCanvas.height = originalCanvas.height; cw = previewCanvas.width; ch = previewCanvas.height; const ctx = previewCanvas.getContext('2d'); let modifier = 1; if (img.width > previewCanvas.width) { modifier = previewCanvas.width / img.width; } else { modifier = previewCanvas.height / img.height; } ctx.drawImage(img, 0, 0, img.width * modifier, img.height * modifier); const imgData = ctx.getImageData(0, 0, cw, ch); data = imgData.data; ctx.clearRect(0, 0, cw, ch); console.debug('Image loaded'); }); img.crossOrigin = 'anonymous'; img.src = url; } // Drawing Modes function drawImage(size, modifier = 1, thickness = 5, offset = { x: 0, y: 0 }, ignorcolors = []) { executionLine = []; switch (drawMode) { case 'zigzag': drawZigzagImage(size, modifier, thickness, offset, ignorcolors); break; case 'wave': drawWaveImage(size, modifier, thickness, offset, ignorcolors); break; case 'spiral': drawSpiralImage(size, modifier, thickness, offset, ignorcolors); break; default: drawNormalImage(size, modifier, thickness, offset, ignorcolors); } console.debug('Drawing prepared'); } function drawZigzagImage(size, modifier, thickness, offset, ignorcolors) { const step = size * modifier; let goingRight = true; let lastPoint = null; for (let y = 0; y < ch; y += step) { if (goingRight) { for (let x = 0; x < cw; x += step) { processPixel(x, y); } } else { for (let x = cw - step; x >= 0; x -= step) { processPixel(x, y); } } goingRight = !goingRight; if (y + step < ch && lastPoint) { const nextY = y + step; const pixel = getPixelData(lastPoint.x, nextY, size, ignorcolors); if (pixel) { executionLine.push({ pos1: recalc([lastPoint.x, y], size, offset), pos2: recalc([lastPoint.x, nextY], size, offset), color: lastPoint.color, thickness: thickness }); } } } function processPixel(x, y) { const pixel = getPixelData(x, y, size, ignorcolors); if (pixel) { if (lastPoint) { executionLine.push({ pos1: recalc([lastPoint.x, lastPoint.y], size, offset), pos2: recalc([x, y], size, offset), color: lastPoint.color, thickness: thickness }); } lastPoint = { x, y, color: pixel.color }; } } } function drawWaveImage(size, modifier, thickness, offset, ignorcolors) { const amplitude = 50; const wavelength = 100; for (let x = 0; x < cw; x += size * modifier) { const waveY = ch / 2 + Math.sin(x / wavelength * Math.PI * 2) * amplitude; const y = Math.max(0, Math.min(ch - 1, Math.round(waveY))); const pixel = getPixelData(x, y, size, ignorcolors); if (pixel) { executionLine.push({ pos1: recalc([x, 0], size, offset), pos2: recalc([x, y], size, offset), color: pixel.color, thickness: thickness }); } } } function drawSpiralImage(size, modifier, thickness, offset, ignorcolors) { const centerX = cw / 2; const centerY = ch / 2; const maxRadius = Math.max(centerX, centerY); let radius = 0; let angle = 0; const angleStep = 0.1; const radiusStep = 0.5; while (radius < maxRadius) { const x = Math.round(centerX + radius * Math.cos(angle)); const y = Math.round(centerY + radius * Math.sin(angle)); if (x >= 0 && x < cw && y >= 0 && y < ch) { const pixel = getPixelData(x, y, size, ignorcolors); if (pixel) { executionLine.push({ pos1: recalc([x, y], size, offset), pos2: recalc([x, y], size, offset), color: pixel.color, thickness: thickness }); } } radius += radiusStep; angle += angleStep; } } function drawNormalImage(size, modifier, thickness, offset, ignorcolors) { for (let y = 0; y < ch; y += size * modifier) { let start = [0, y]; for (let x = 0; x < cw; x += size * modifier) { let end = [x, y]; const pixel = getPixelData(x, y, size, ignorcolors); if (pixel) { if (x < cw - 1) { const nextPixel = getPixelData(x + size * modifier, y, size, ignorcolors); if (!nextPixel || nextPixel.color !== pixel.color) { executionLine.push({ pos1: recalc(start, size, offset), pos2: recalc(end, size, offset), color: pixel.color, thickness: thickness, }); start = [x, y]; } } else { executionLine.push({ pos1: recalc(start, size, offset), pos2: recalc(end, size, offset), color: pixel.color, thickness: thickness, }); } } else { start = [x, y]; } } } } function getPixelData(x, y, size, ignorcolors = []) { const index = (y * cw + x) * 4; const a = data[index + 3]; if (a > 20) { const r = data[index]; const g = data[index + 1]; const b = data[index + 2]; const color = `rgb(${r},${g},${b})`; if (!ignorcolors.includes(color)) { return { x, y, color }; } } return null; } async function execute(socket) { drawing_active = true; for (let i = 0; i < executionLine.length; i++) { if (!drawing_active) return; let currentLine = executionLine[i]; let p1 = currentLine.pos1, p2 = currentLine.pos2, color = currentLine.color, thickness = currentLine.thickness; drawcmd(socket, p1, p2, color, thickness); // Fixed: changed colorE to color await delay(10); } function drawcmd(s, start, end, color, thickness) { s.send(`42["drawcmd",0,[${start[0]},${start[1]},${end[0]},${end[1]},false,${0 - thickness},"${color}",0,0,{}]]`); } } function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function recalc(value, size, offset) { return [(value[0] / (cw * size) + offset.x / 100).toFixed(4), (value[1] / (ch * size) + offset.y / 100).toFixed(4)]; } // Player and Connection Classes class Player { constructor(name = undefined) { this.name = name; this.sid1 = null; this.uid = ''; this.wt = ''; this.conn = new Connection(this); this.room = new Room(this.conn); this.action = new Actions(this.conn); } anonymize(name) { this.name = name; this.uid = undefined; this.wt = undefined; } } class Connection { constructor(player) { this.player = player; this.socket = null; } onopen() { this.Heartbeat(25000); } onclose() {} onerror() {} onmessage(event) { let message = String(event.data); if (message.startsWith('42')) { this.onbroadcast(message.slice(2)); } else if (message.startsWith('40')) { this.onrequest(); } else if (message.startsWith('41')) { this.player.room.join(this.player.room.id); } else if (message.startsWith('430')) { let configs = JSON.parse(message.slice(3))[0]; this.player.room.players = configs.players; this.player.room.id = configs.roomid; } } onbroadcast(payload) { payload = JSON.parse(payload); if (payload[0] === 'bc_uc_freedrawsession_changedroom') { this.player.room.players = payload[3]; this.player.room.id = payload[4]; } if (payload[0] === 'mc_roomplayerschange') { this.player.room.players = payload[3]; } } onrequest() {} open(url) { this.socket = new WebSocket(url); this.socket.onopen = this.onopen.bind(this); this.socket.onclose = this.onclose.bind(this); this.socket.onerror = this.onerror.bind(this); this.socket.onmessage = this.onmessage.bind(this); } close(code, reason) { this.socket.close(code, reason); } Heartbeat(interval) { setTimeout(() => { if (this.socket.readyState === this.socket.OPEN) { this.socket.send(2); this.Heartbeat(interval); } }, interval); } serverconnect(server, room) { if (!this.socket || this.socket.readyState !== this.socket.OPEN) { this.open(server); } else { this.socket.send(41); this.socket.send(40); } this.onrequest = () => { this.socket.send(room); }; } } class Room { constructor(conn) { this.conn = conn; this.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; this.players = []; } join(invitelink) { let gamemode = 2; let server = ''; if (invitelink === null) { this.id = null; server = 'sv3.'; } else { this.id = invitelink.startsWith('http') ? invitelink.split('/').pop() : invitelink; if (invitelink.endsWith('.3')) { server = 'sv3.'; gamemode = 2; } else if (invitelink.endsWith('.2')) { server = 'sv2.'; gamemode = 2; } else { server = ''; gamemode = 1; } } let serverurl = `wss://${server}drawaria.online/socket.io/?sid1=undefined&hostname=drawaria.online&EIO=3&transport=websocket`; let player = this.conn.player; let playerName = EL('#inputName').value; let connectstring = `420["startplay","${playerName}",${gamemode},"en",${nullify(this.id)},null,[null,"https://drawaria.online/",1000,1000,[${nullify(player.sid1)},${nullify(player.uid)},${nullify(player.wt)}],null]]`; this.conn.serverconnect(serverurl, connectstring); } next() { if (this.conn.socket.readyState !== this.conn.socket.OPEN) { this.join(null); } else { this.conn.socket.send('42["pgswtichroom"]'); } } } class Actions { constructor(conn) { this.conn = conn; } DrawLine(bx = 50, by = 50, ex = 50, ey = 50, thickness = 50, color = '#FFFFFF', algo = 0) { bx = bx / 100; by = by / 100; ex = ex / 100; ey = ey / 100; this.conn.socket.send(`42["drawcmd",0,[${bx},${by},${ex},${ey},true,${0 - thickness},"${color}",0,0,{"2":${algo},"3":0.5,"4":0.5}]]`); this.conn.socket.send(`42["drawcmd",0,[${bx},${by},${ex},${ey},false,${0 - thickness},"${color}",0,0,{"2":${algo},"3":0.5,"4":0.5}]]`); } } function nullify(value = null) { return value === null ? null : `"${value}"`; } // Initialize if (!EL('#cheat-menu')) { window['___BOT'] = new Player('ZigzagBot'); window['___ENGINE'] = { loadImage, drawImage }; addBoxIcons(); createFloatingMenu(); setupImageLoader(); setupBotControls(); setupDrawingControls(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址