let area = document.querySelector('#grid'); let group = document.querySelector('#group'); let mpos = [window.innerWidth / 2, window.innerHeight / 2]; let translate = ""; let width = 0; let height = 0; let center = [0, 0]; let lastPos = [0, 0]; let isMouse = false; let zoom = 0.8; genTrans(); function mouseMove(e) { lastPos = [e.clientX, e.clientY]; if (!isMouse) return; mpos[0] += e.clientX - center[0]; mpos[1] += e.clientY - center[1]; center = lastPos; genTrans(); } function mouseUp(e) { isMouse = false; } function mouseDown(e) { isMouse = true; center = [e.clientX, e.clientY]; } function wheel(e) { mpos[0] -= lastPos[0]; mpos[1] -= lastPos[1]; mpos[0] *= 1.005 ** -e.deltaY; mpos[1] *= 1.005 ** -e.deltaY; mpos[0] += lastPos[0]; mpos[1] += lastPos[1]; zoom *= 1.005 ** -e.deltaY; genTrans(); } function genTrans() { group.setAttribute('transform', `translate(${mpos[0]},${mpos[1]}), scale(${zoom},${zoom})`); } window.onwheel = wheel; window.onmousemove = mouseMove; window.onmouseup = mouseUp; window.onmousedown = mouseDown; window.ondblclick = doubleClick; let tiles = {}; let colors = { '!nobody': 'rgb(255,255,255)' }; let amounts = { '!nobody': -1 }; let areas = {}; function doubleClick(e) { if (!token) { window.location.href = 'https://nbg.dervland.net/login.php?next=' + encodeURIComponent(window.location.href); } let data = e.target.id.split('|').pop(); data = data.split('_'); if (e.target.id.startsWith('grid-claimed')) { socket.emit('conquer', { x: data[0], y: data[1] }) } else if (e.target.id.startsWith('grid-select')) { socket.emit('claim', { x: data[0], y: data[1] }) } } function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); } function renderRect(x, y, h, w) { let elem = document.createElementNS("http://www.w3.org/2000/svg", 'rect'); elem.setAttribute('x', x); elem.setAttribute('y', y); elem.setAttribute('width', w); elem.setAttribute('height', h); elem.setAttribute('fill', 'white'); elem.setAttribute('stroke', 'black'); elem.setAttribute('stroke-width', '3.5'); group.appendChild(elem); return elem; } function renderSelect(key, val) { let elem = renderRect(key[0] * 125, key[1] * 125, 125, 125); elem.id = `grid-select|${key[0]}_${key[1]}`; } function renderClaimed(key, val, data2) { for (let i in val.data) { if (i.startsWith('_')) continue; let space = val.data[i]; let innerGroup = (space != '!nobody') ? [...document.querySelectorAll(`g`)].filter(x => x.id == space)[0] : false; let userData = data2[`_user_${space}`]; colors[space] = userData ? userData.color : colors[space]; if (space == '!nobody') { colors[space] = 'rgb(255,255,255)'; } if (!colors[space]) { colors[space] = `hsl(${Math.random() * 360}deg,${Math.random() * 30 + 65}%,${Math.random() * 30 + 60}%)` } if (!amounts[space]) { amounts[space] = 0; areas[space] = []; } let x = i % 5; let y = Math.floor(i / 5); if (areas[space]) { let x2 = key[0] * 125 + x * 25; let y2 = key[1] * 125 + y * 25; let filter = areas[space].filter((a) => { return a.findIndex(([x, y]) => Math.abs(x2 - x) + Math.abs(y2 - y) < 2 * 25) != -1 }); let noFilter = areas[space].filter((a) => { return a.findIndex(([x, y]) => Math.abs(x2 - x) + Math.abs(y2 - y) < 2 * 25) == -1 }); areas[space] = []; areas[space].push(...noFilter); filter = [filter.flat(1)]; areas[space].push(...(filter)); if (filter.length == 0) { areas[space].push([[x2, y2]]); } else { areas[space][areas[space].length - 1].push([x2, y2]); } } amounts[space]++; if (!innerGroup && space != '!nobody') { let elem = document.createElementNS("http://www.w3.org/2000/svg", 'g'); elem.id = space; group.appendChild(elem); innerGroup = elem; } let elem = renderRect(key[0] * 125 + x * 25, key[1] * 125 + y * 25, 25, 25); if (innerGroup) innerGroup.appendChild(elem); elem.setAttribute('fill', colors[space]); elem.id = `grid-claimed|${key[0] * 5 + x}_${key[1] * 5 + y}`; } } let biggestBox = (thing) => { let xVal = thing.map(x => Math.min(...x.map(y => y[0]))); let yVal = thing.map(x => Math.min(...x.map(y => y[1]))); let wVal = thing.map(x => Math.max(...x.map(y => y[0])) - Math.min(...x.map(y => y[0]))); let hVal = thing.map(x => Math.max(...x.map(y => y[1])) - Math.min(...x.map(y => y[1]))); let sVal = thing.map(x => (Math.max(...x.map(y => y[0])) - Math.min(...x.map(y => y[0]))) * ((Math.max(...x.map(y => y[1])) - Math.min(...x.map(y => y[1]))))); let i = sVal.indexOf(Math.max(...sVal)); return { x: xVal[i], y: yVal[i], width: wVal[i] + 25, height: hVal[i] + 25 } } const socket = io(host); socket.emit('area', { area: 'grid' }); var token = getCookie('token'); var noauth = false; setTimeout(() => { if (token && window.location.search != '') window.location.href = '/'; socket.emit('join', { token }); }, 800); socket.on('data', (data) => { if (data == 'noauth') { noauth = true; } group.innerHTML = ''; for (let key in data) { let val = data[key]; let keyDecomp = key.split(','); if (val.type == 'select') { renderSelect(keyDecomp, val); } else if (val.type == 'claimed') { renderClaimed(keyDecomp, val, data); } } let groups = document.querySelectorAll(`g g`); for (let group of groups) { let box = biggestBox(areas[group.id]) let id = group.id; let elem = document.createElementNS("http://www.w3.org/2000/svg", 'text'); elem.setAttribute("x", box.x + box.width / 2); elem.setAttribute("y", box.y + box.height / 2 - box.width / 4); elem.setAttribute("font-size", box.width / 8 + "px"); elem.setAttribute("stroke", "white"); elem.setAttribute("stroke-width", box.width / 35) elem.setAttribute("paint-order", "stroke") elem.setAttribute('text-anchor', 'middle') let lines = [id, amounts[id]]; for (let line of lines) { let tspan = document.createElementNS("http://www.w3.org/2000/svg", 'tspan'); tspan.textContent = line; tspan.setAttribute('x', box.x + box.width / 2); tspan.setAttribute('dy', box.width / 6); elem.appendChild(tspan); } document.querySelector('svg > g').appendChild(elem); amounts[id] = 0; } }) let cooldown = 0; let lastTurn = 'nobody'; socket.on('cooldown', (cooldownIn) => { cooldown = cooldownIn; }) socket.on('turn', (cooldownIn) => { lastTurn = cooldownIn; }) setInterval(() => { let distance = new Date(cooldown) - new Date(); if (distance < 0) { document.querySelector('.info').textContent = `The next turn is now, last turn was by ${lastTurn || 'nobody'}`; } else { document.querySelector('.info').textContent = `The next turn is in ${Math.floor(distance / 1000)} seconds, last turn was by ${lastTurn || 'nobody'}`; } }, 100); document.querySelector('#color').onchange = (e) => { socket.emit('color', e.target.value) }