Use https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en to install these 2 scripts.
Right click a target square to queue your currently selected unit along the shortest path to the target.
Use https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en to install these 2 scripts.
Right click a target square to queue your currently selected unit along the shortest path to the target.
| // ==UserScript== | |
| // @name Squarecraft | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.1 | |
| // @description try to take over the world! | |
| // @author Steven Hao | |
| // @match http://squarecraft.io/ | |
| // @grant none | |
| // ==/UserScript== | |
| if (typeof wsurl === 'undefined') { | |
| var wsurl = "ws://squarecraft.io:5000/ffa" | |
| } | |
| function getWebSocket() { | |
| if (!window.websockets) return; | |
| if (!(wsurl in window.websockets)) return; | |
| return window.websockets[wsurl]; | |
| } | |
| if (typeof attached === 'undefined') { | |
| var attached, ws, state, secret, registeredWebsocketListener, registeredClickListeners; | |
| } | |
| function attach() { | |
| if (attached) return; | |
| ws = getWebSocket(); | |
| if (!ws) return; | |
| attached = true; | |
| ws.addEventListener('message', event => { | |
| const data = JSON.parse(event.data); | |
| if (data.event === 'connected') { | |
| secret = data.secret; | |
| } else if (data.event === 'update') { | |
| state = data.state; | |
| } | |
| }); | |
| } | |
| function registerWebsocketListener() { | |
| if (registeredWebsocketListener) return; | |
| if (!window.onWebsocket) return; | |
| registeredWebsocketListener = true; | |
| window.onWebsocket((websocket) => { | |
| attach(); | |
| }); | |
| } | |
| setInterval(registerWebsocketListener, 500); | |
| function getUnitId({x, y}) { | |
| if (!attached) return; | |
| return state.squares[y][x] && state.squares[y][x].unit && state.squares[y][x].unit.id; | |
| } | |
| function getDirection({x: fx, y: fy}, {x: tx, y: ty}) { | |
| if (fx === tx) { | |
| if (fy < ty) return 'move_down'; | |
| return 'move_up'; | |
| } | |
| if (fx < tx) return 'move_left'; | |
| return 'move_right'; | |
| } | |
| function makeMove(from, to, unitId) { | |
| const ws = getWebSocket(); | |
| if (!ws) { | |
| return false; | |
| } | |
| const action = getDirection(from, to); | |
| let move = { | |
| action: action, | |
| source: [from.y, from.x], | |
| target: [to.y, to.x], | |
| unitId: unitId | |
| }; | |
| const event = 'move'; | |
| console.log('makeMove', secret, move, event); | |
| ws.send(JSON.stringify({ | |
| secret, | |
| move, | |
| event, | |
| })); | |
| } | |
| function getXY(el) { | |
| const x = parseInt(el.getAttribute('x')); | |
| const y = parseInt(el.getAttribute('y')); | |
| return { x, y }; | |
| } | |
| function getEl({ x, y }) { | |
| return document.querySelector(`.square[x="${x}"][y="${y}"]`); | |
| } | |
| function getGrid() { | |
| const res = []; | |
| document.querySelectorAll('.square').forEach(el => { | |
| const walkable = el.style.backgroundColor !== 'white'; | |
| const empty = (el.style.backgroundColor === 'black' || el.style.backgroundColor === 'gray' || el.style.backgroundColor === 'rgb(80, 80, 80)') && !el.style.opacity; | |
| const { x, y } = getXY(el); | |
| if (!res[x]) res[x] = []; | |
| res[x][y] = { | |
| walkable, | |
| empty, | |
| }; | |
| }); | |
| return res; | |
| } | |
| function getEmptyNeighbors({x, y}, grid) { | |
| return [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]] | |
| .filter(([nx, ny]) => grid[nx] && grid[nx][ny] && grid[nx][ny].walkable) | |
| .map(([nx, ny]) => ({ x: nx, y: ny})); | |
| } | |
| function getPath(start, end, grid) { | |
| const trace = []; | |
| const queue = [start]; | |
| trace[start.x] = []; | |
| trace[start.x][start.y] = -1; | |
| while (queue.length > 0) { | |
| const cur = queue.shift(); | |
| if (cur.x === end.x && cur.y === end.y) break; | |
| const neighbors = getEmptyNeighbors(cur, grid); | |
| console.log('neighbors=', neighbors); | |
| neighbors.forEach(neighbor => { | |
| if (!trace[neighbor.x]) trace[neighbor.x] = []; | |
| if (trace[neighbor.x][neighbor.y]) return; | |
| console.log('trace', neighbor, cur); | |
| trace[neighbor.x][neighbor.y] = cur; | |
| queue.push(neighbor); | |
| }); | |
| } | |
| if (trace[end.x][end.y]) { | |
| let cur = end; | |
| const path = []; | |
| while (cur !== -1) { | |
| path.unshift(cur); | |
| cur = trace[cur.x][cur.y]; | |
| } | |
| return path; | |
| } | |
| } | |
| function registerClickListeners() { | |
| if (registeredClickListeners) return; | |
| if (!document.querySelector('.square')) return; | |
| registeredClickListeners = true; | |
| document.querySelectorAll('.square').forEach(el => { | |
| // let newElement = el.cloneNode(true); | |
| // el.parentNode.replaceChild(newElement, el); | |
| // el = newElement; | |
| if (el.marked) return; | |
| el.marked = true; | |
| el.addEventListener('contextmenu', (ev) => { | |
| ev.preventDefault(); | |
| const ws = getWebSocket(); | |
| if (!ws) { | |
| console.log('no websocket'); | |
| return; | |
| } | |
| if (!attached) { | |
| console.log('not attached'); | |
| return; | |
| } | |
| const to = getXY(el); | |
| const from = getXY(document.querySelector('.highlighted')); | |
| const grid = getGrid(); | |
| const path = getPath(from, to, grid); | |
| const unitId = getUnitId(from); | |
| if (!unitId) { | |
| console.log('no unitId'); | |
| return; | |
| } | |
| if (!path) { | |
| console.log('no path'); | |
| return; | |
| } | |
| console.log('PATH', path); | |
| path.forEach((cur, i) => { | |
| if (i === path.length - 1) return; | |
| const nxt = path[i + 1]; | |
| makeMove(cur, nxt, unitId); | |
| }); | |
| }); | |
| }) | |
| } | |
| setInterval(registerClickListeners, 500); | 
| // ==UserScript== | |
| // @name Websocket Connector | |
| // @namespace http://tampermonkey.net/ | |
| // @version 0.1 | |
| // @description try to take over the world! | |
| // @author Steven Hao | |
| // @match * | |
| // @grant none | |
| // ==/UserScript== | |
| (function() { | |
| var oldWebSocket = WebSocket; | |
| window.websockets = {}; | |
| var cbks = []; | |
| window.onWebsocket = function(cbk) { | |
| cbks.push(cbk); | |
| } | |
| WebSocket = function(...args) { | |
| var res = new oldWebSocket(...args); | |
| window.websockets[res.url] = res; | |
| cbks.forEach(cbk => { | |
| cbk(res); | |
| }); | |
| return res; | |
| } | |
| WebSocket.prototype = oldWebSocket.prototype; | |
| }()); |