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; | |
}()); |