// ==UserScript== // @name Io Record // @namespace http://tampermonkey.net/ // @version 0.0.8 // @author Big watermelon // @description This script is in beta testing !! Record any io game (agma.io only for now) // @match *://agma.io/* // @license All Rights Reserved // @icon data:image/png;base64,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 // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @run-at document-start // @downloadURL none // ==/UserScript== /* Copyright © 2024 Big watermelon. All Rights Reserved. This work is proprietary and may not be copied, distributed, or modified without explicit permission. */ // FIXIT: no death screen // FIXIT: gets disconnected when close window (function() { 'use strict'; if (unsafeWindow.top !== unsafeWindow.self || document.querySelector('title')?.textContent?.includes('Just a moment')) return; const settings = { toggleKey: 'm', toggleMouseLock: '"', recordAnimations: false, recordLeaderboard: false, recordMovingBorders: true, autoStopAfter: 0, // seconds fetchChangeLog: true }; function serializeArray(recordData) { return recordData.map(frame => Math.round(frame.offset) + ':' + btoa(String.fromCharCode(...new Uint8Array(frame.data)))).join("|"); } function deserializeString(recordData) { return recordData.split("|").map(frame => { const [offset, base64Data] = frame.split(":"); const binaryString = atob(base64Data); const buffer = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) buffer[i] = binaryString.charCodeAt(i); return { id: buffer[0], offset: Number(offset), data: buffer.buffer }; }); } const savedRecords = GM_getValue('records', []), toggleMouseCode = JSON.parse(localStorage.hotkeys).C.c; const MANDATORY_PACKETS = [10, 11, 12, 20, 32, 33, 48, 49, 50, 65, 66], CLEAR_ALL = { data: new Uint8Array([20]).buffer }, FAKE_CELL_UPDATE = { data: new Uint8Array([10, 0, 0, 0, 0, 0, 0]).buffer }; savedRecords.forEach(record => record.data = deserializeString(record.data)) let currentRecord = null, clipPlayer = null, start, recordButton, isPaused = true, viewedRecord = null, isMouseLocked = false, wsOnmessage, frameIndex = 0, menuDom = document.createElement('html'); menuDom.innerHTML = ` Io Record
${savedRecords.map(record => '' + record.name + '').join('')}

0s

`; const clipsList = menuDom.lastElementChild.firstElementChild; const [previousFrameButton, playButton, pauseButton, nextFrameButton, downloadButton, timeControlInput, timeText] = menuDom.querySelectorAll('svg, input, p'); playButton.onclick = pauseButton.onclick = () => { if (viewedRecord == null) return; if (isPaused) { isPaused = false; goto(); } else { isPaused = true; } updateButtonsStyle(); }; previousFrameButton.onclick = () => { // This feature is glitchy /* if (viewedRecord == null || !frameIndex) return; isPaused = true; const recordData = savedRecords[viewedRecord].data; let current; do { wsOnmessage(current = recordData[frameIndex--]); } while (frameIndex && current.id != 10); updateButtonsStyle(); timeText.innerText = Math.round((timeControlInput.max - (timeControlInput.value = recordData[frameIndex].offset)) / 1000) + 's'; */ }; nextFrameButton.onclick = () => { const recordData = savedRecords[viewedRecord].data; if (viewedRecord == null || frameIndex >= recordData.length) return; isPaused = true; let current; do { wsOnmessage(current = recordData[frameIndex++]); } while (frameIndex <= recordData.length && current.id != 10); updateButtonsStyle(); timeText.innerText = Math.round((timeControlInput.max - (timeControlInput.value = recordData[frameIndex].offset)) / 1000) + 's'; }; timeControlInput.onchange = () => { if (viewedRecord == null) return; timeText.innerText = Math.round((timeControlInput.max - timeControlInput.value) / 1000) + 's'; const recordData = savedRecords[viewedRecord].data; isPaused = true; frameIndex = 0; wsOnmessage(CLEAR_ALL); let current; do { wsOnmessage(current = recordData[frameIndex++]); } while (current.offset < timeControlInput.value); isPaused = true; updateButtonsStyle(); }; clipsList.onclick = ({ target }) => { const clips = Array.from(clipsList.children); const i = clips.indexOf(target); isPaused = true; if (viewedRecord != null) clips[viewedRecord].style.border = ''; if (target.tagName != 'SPAN' || viewedRecord == i) { viewedRecord = null; return; } frameIndex = 0; wsOnmessage(CLEAR_ALL); target.style.border = '1px solid white'; const recordData = savedRecords[viewedRecord = i].data; timeControlInput.max = recordData[recordData.length - 1].offset; timeControlInput.value = 0; timeText.innerText = Math.round(timeControlInput.max / 1000) + 's'; }; const dropZone = menuDom.lastElementChild; dropZone.ondragenter = dropZone.ondragover = dropZone.ondragleave = event => event.preventDefault(); dropZone.addEventListener('drop', event => { event.preventDefault(); const file = event.dataTransfer.files[0]; if (file) { const reader = new FileReader(); reader.onload = e => { const d = new Date(); savedRecords.push({ name: file.name, data: deserializeString(e.target.result) }); const span = document.createElement('span'); span.innerText = file.name; clipsList.appendChild(span); }; reader.readAsText(file); } }); downloadButton.addEventListener('click', () => viewedRecord != null && unsafeWindow.open( URL.createObjectURL(new Blob([serializeArray(savedRecords[viewedRecord].data)], { type: 'text/plain' })))); unsafeWindow.addEventListener('keyup', event => { event.stopPropagation(); event.preventDefault(); if (event.key == settings.toggleKey && event.ctrlKey) { if (currentRecord) { endCurrentRecord(); } else { const d = new Date(); savedRecords.push(currentRecord = { name: `Clip ${d.getFullYear()}-${d.getMonth()}-${d.getDate()}_${d.getHours()}-${d.getMinutes()}-${d.getSeconds()}`, data: [] /* , game: 'agma.io' */ }); settings.autoStopAfter && setTimeout(endCurrentRecord, settings.autoStopAfter * 1000); start = performance.now(); recordButton.firstElementChild.style.color = 'red'; } } else if (event.key == settings.toggleMouseLock) { isMouseLocked = !isMouseLocked; unsafeWindow[isMouseLocked ? 'onkeydown' : 'onkeyup']({ keyCode: toggleMouseCode }); } }); function endCurrentRecord() { if (!currentRecord) return; recordButton.firstElementChild.style.color = ''; const span = document.createElement('span'); span.innerText = currentRecord.name; clipsList.appendChild(span); currentRecord = null; } function updateButtonsStyle() { if (isPaused) { recordButton.firstElementChild.style.color = ''; pauseButton.style.display = 'none'; playButton.style.display = 'block'; } else { recordButton.firstElementChild.style.color = 'green'; playButton.style.display = 'none'; pauseButton.style.display = 'block'; } } function recordPacket(message) { const data = new DataView(message.data); const id = data.getUint8(0); if ( id == 11 && data.byteLength == 3 || id == 12 && data.byteLength == 5 ) return; if (viewedRecord != null) { if (id == 10) return isPaused && wsOnmessage(FAKE_CELL_UPDATE); else if (id == 11 || id == 12) return; } wsOnmessage(message); if ( currentRecord && viewedRecord == null && (settings.recordAnimations || id != 33) && (settings.recordLeaderboard || id < 48 && id > 50) && (settings.recordMovingBorders || id != 65 && id != 66) && MANDATORY_PACKETS.includes(id) ) currentRecord.data.push({ id, data: message.data, offset: message.timeStamp - start }); } function goto() { if (viewedRecord == null) return; if (!frameIndex) wsOnmessage(CLEAR_ALL); const recordData = savedRecords[viewedRecord].data; const current = recordData[frameIndex++]; timeText.innerText = Math.round((timeControlInput.max - (timeControlInput.value = current.offset)) / 1000) + 's'; MANDATORY_PACKETS.includes(current.id) && wsOnmessage(current); // prevents XSS -> forbids unallowed packets if (isPaused) return; if (recordData[frameIndex]) setTimeout(goto, recordData[frameIndex].offset - current.offset); else setTimeout(() => { frameIndex = 0; wsOnmessage(CLEAR_ALL); isPaused = true; updateButtonsStyle(); }, 10); } const originalDefineProperty = unsafeWindow.Object.defineProperty; unsafeWindow.Object.defineProperty = function(obj, prop, descriptor) { if (obj instanceof WebSocket && obj.url.includes('.agma.io')) { obj.addEventListener('message', recordPacket); originalDefineProperty(obj, 'onmessage', { set: function(onmessage) { wsOnmessage = onmessage; }, get: function() { return wsOnmessage; } }); } return originalDefineProperty(obj, prop, descriptor); } originalDefineProperty(unsafeWindow, 'onblur', { set: () => 0 }); // prevents mouse lock to be reset const originalSend = unsafeWindow.WebSocket.prototype.send; unsafeWindow.WebSocket.prototype.send = function() { if (viewedRecord != null) return; return originalSend.apply(this, arguments); } let loaded = false; unsafeWindow.addEventListener('load', () => { if (loaded || typeof swal == 'undefined') return; loaded = true; if (settings.fetchChangeLog) { try { const xhr = new XMLHttpRequest(); xhr.open('GET', 'https://api.github.com/repos/Grosse-pasteque/io-record/contents/CHANGELOG', true); xhr.setRequestHeader('Accept', 'application/json'); xhr.setRequestHeader('Authorization', 'Bearer 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'); xhr.setRequestHeader('X-GitHub-Api-Version', '2022-11-28'); xhr.onreadystatechange = function () { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { const changelog = atob(JSON.parse(xhr.responseText).content); if (changelog[0] != GM_getValue('changelog', '0')) { GM_setValue('changelog', changelog[0]) swal({ title: '', text: changelog.slice(1), html: true }) } } else { console.error('Error:', xhr.status, xhr.statusText); } } }; xhr.send(); } catch (e) { console.error("IO-Record, couldn't fetch CHANGELOG:", e); } } recordButton = document.createElement('div'); recordButton.id = 'recordButton'; recordButton.className = 'btn'; recordButton.style = 'right: 220px;'; recordButton.title = `Press <${settings.toggleKey.toUpperCase()}> to record.`; recordButton.innerHTML = ''; recordButton.onclick = function() { if (clipPlayer && !clipPlayer.closed) return clipPlayer.focus(); clipPlayer = unsafeWindow.open('', 'subWindow', 'width=300,height=400'); if (!clipPlayer) return; clipPlayer.document.open(); clipPlayer.document.appendChild(clipPlayer.document.adoptNode(menuDom)); clipPlayer.document.close(); clipPlayer.addEventListener('unload', () => { viewedRecord = null; isPaused = true; updateButtonsStyle(); menuDom = clipPlayer.document.documentElement; clipPlayer = null; }); clipPlayer.focus(); } document.body.appendChild(recordButton); const style = document.createElement('style'); style.innerHTML = ` #recordButton { transition: color .2s; position: absolute; top: 10px; background: #373737; padding: 7px; z-index: 135; opacity: .7; } #recordButton:hover { color: #eee; opacity: 1; } `; document.head.appendChild(style); const contextSpectate = document.getElementById("contextSpectate") const contextHidePlayer = document.createElement('li'); contextHidePlayer.id = 'contextHidePlayer'; contextHidePlayer.className = 'contextmenu-item enabled'; contextHidePlayer.style = 'display: none;'; contextHidePlayer.innerHTML = '

Hide player

'; contextSpectate.parentElement.insertBefore(contextHidePlayer, contextSpectate); const originalCss = $.prototype.css; $.prototype.css = function() { if (this.selector == '#btnFriends') recordButton.style.right = parseInt(arguments[1]) + 46 + 'px'; return originalCss.apply(this, arguments) }; setInterval(() => document.body.onmousemove({}), 250000); // anti afk to prevent FIXIT N°2 }); unsafeWindow.onbeforeunload = () => { clipPlayer?.close(); // GM_setValue('settings', settings); savedRecords.forEach(record => record.data = serializeArray(record.data)) GM_setValue('records', savedRecords); }; console.log(`%cIo %cRecord %c- ${GM_info?.script?.version} Loaded`, 'font-weight: bold; font-size: 14pt; color: red;', 'font-weight: bold; font-size: 14pt; color: white;', 'font-weight: bold; font-size: 14pt; color: black;' ); })();