// ==UserScript==
// @name cursors.io 300 bots hack
// @namespace http://tampermonkey.net/
// @version 0.7
// @description try to take over the world!
// @author You
// @match http://cursors.io/
// @match http://kursors.io/
// @match http://cursors.io/?editor
// @grant none
// ==/UserScript==
(function() {
'use strict';
"use strict"
// Beta client for the Zursor Master project
// Please do not paste this script itself into tampermonkey or cursors.io, instead please use the tampermonkey extension that I have provided here: https://pastebin.com/krbGjJ9v
// Especially since this script is still in development, the tampermonkey extension provided is automatically updated
// update as of oct. 13, 2020: Script has been updated to avoid any CORB/CORS errors. Change the __ip variable to the new server ip when it updates. Get the server ip by going to the 'Network' tab in inspect element, go to the 'WS' tab, and refresh the page. DM me on discord at 8y8x#5342 if the script should be updated
window.zM = {};
window.zMDK = {};
async function wait(ms = 1000) {
setTimeout(()=>{return new Promise(async resolve => resolve());},ms);
}
window.D = document;
let __ip = '128.199.12.58';
(async function(styles, init, cfg, dependencies, elements) {
zM.dependenciesLoaded = 0b000000;
zM.version = '0.2';
zM.cfg = cfg.raw;
zM.createConfig = cfg.createConfig;
zM.saveConfig = cfg.saveConfig;
zM.getConfig = cfg.getConfig;
zM.returnAfterUndeployed = false;
zM.antiIdle = true;
// load developer kit for plugins
// it isn't exactly done yet, I plan to only do it once I'm mostly done the whole script- and it's stable and everything
/**
* Tools for modifying the localStorage configuration
*
* .generate() - creates a default config, returns the result. Optionally, you can put the object pointer as a parameter.
* .save() - saves the parameter provided. Returns true/false dependant if errors occur.
* .get() - returns the saved config. Optionally, you can put the object pointer as a parameter.
*/
zMDK.config = {
generate: cfg.createConfig,
save: cfg.saveConfig,
get: cfg.getConfig
}
// some useful shortcuts
window.head = D.head,
window.body = D.body;
// disable all elements on page
var temp = [];
temp = body.getElementsByTagName('*');
for (var i = 0; i < temp.length; ++i) temp[i].style.display = 'none';
// delete all header elements
head.innerHTML = '<title>Loading...</title>';
// add a container
temp = D.createElement('div');
temp.style.cssText = 'background:linear-gradient(45deg, rgba(33,33,33,1) 0%, rgba(66,66,66,1) 100%);position:fixed;top:0px;left:0px;width:100vw;height:100vh;';
temp.id = 'zM-container'
body.appendChild(temp);
zM.el = zMDK.elements = {};
zM.el.container = temp;
zM.fleet = [];
zM.fSel = NaN; // NaN for news
temp = styles();
zM.el.style = {
fleetTopbarContainer: temp[0]
}
zM.pos = {
mouseX: 400,
mouseY: 300,
lastMouseX: 400,
lastMouseY: 300
}
zM.useWallhack = true;
zM.ease = function(n, o, upd) {
var dist = n - o,
prog = (Date.now() - upd) / 100,
maxMin = Math.min(Math.max(0, prog), 1);
return o + (maxMin ** 2 * (3 - 2 * maxMin)) * dist;
}
zM.isLoading = false;
zM.game = {
m28nCursorsIP: `${__ip}:2828`
}
zM.asyncWaitUntil = async function(toEval) {
return new Promise(resolve => {
var temp = setInterval(()=>{if (eval(toEval)) resolve(), clearInterval(temp);},1);
});
}
zM.origin = (location.hostname === 'cursors.io' || location.href.startsWith('file:///')) ? 'cursors' : location.hostname === 'kursors.io' ? 'kursors' : 'localhost';
zM.movement = 1;
// I decided to load the loading bars before the loading API therefore it works for when the script is starting first
var temp = [D.createElement('div'), D.createElement('div'), D.createElement('div'), D.createElement('div')];
temp[0].className = 'zM-loading-outer';
zM.el.container.appendChild(temp[0]);
temp[1].className = 'zM-loading-title';
temp[0].appendChild(temp[1]);
temp[1].textContent = 'Loading...'
temp[2].className = 'zM-loading-bar-outer';
temp[0].appendChild(temp[2]);
temp[3].className = 'zM-loading-bar-fill';
temp[2].appendChild(temp[3]);
zM.el.loadingOuter = temp.shift();
zM.el.loadingTitle = temp.shift();
zM.el.loadingBarFill = temp.pop();
// loading bar API
zM.setLoadingWidth = function(width = 50) {
zM.el.loadingBarFill.style.width = 'calc(' + width + '%' + ' - 10px)';
}
zM.showLoading = function() {
zM.el.loadingOuter.style.display = 'block';
D.getElementsByTagName('title')[0].textContent = 'Loading...';
}
zM.hideLoading = function() {
zM.el.loadingOuter.style.display = 'none';
D.getElementsByTagName('title')[0].textContent = 'zM / No fleets yet';
}
zM.setLoadingTitle = function(title) {
zM.el.loadingTitle.textContent = title;
}
zM.clickQueue = 0;
zM.updateTabs = function() { // updates fleet tabs
zM.el.fleetTopbarOuter.innerHTML = '';
zM.el.fleetTopbarContainer.innerHTML = '';
zM.el.fleetTopbarOuter.appendChild(zM.el.fleetTopbarContainer);
zM.el.fleetTopbarOuter.appendChild(zM.el.fleetTopbarAdd);
zM.el.fleetTopbarAdd.appendChild(zM.el.fleetTopbarAddImg);
zM.el.fleetTopbarOuter.appendChild(zM.el.fleetTopbarHint);
for (var i = 0; i < zM.fleet.length; ++i) {
var f = zM.fleet[i];
zM.fleet[i].el.container.style.display = 'none';
zM.el.fleetTopbarContainer.innerHTML += `<div style="position: absolute; top: 0px; left: ${100/zM.fleet.length*i}%; width: ${100/zM.fleet.length}%; height: 35px; border-right: 1px solid #fffc; background-color: ${i === zM.fSel ? '#fff3' : '#fff0'};transition: 0.3s;"><div style="position: absolute; top: 0px; left: 0px; width: 100%; height: 35px; background-color: #0000; transition: 0.3s;" onmouseenter="this.style.backgroundColor = '#0003';" onmouseout="this.style.backgroundColor = '#0000'" onclick="zM.fSel = ${i}; zM.updateTabs()"><div style="color:#fffc;font-family:\'Nova Flat\',Montserrat,sans-serif;font-weight:300;padding:8px;pointer-events:none;white-space:nowrap;overflow-x:hidden;user-select:none;">${zM.fSel === i ? '(Selected)' : ''} #${i} / (${f.botsOpened}/${f.maxBots}) / ${f.name}</div></div></div>`;
}
zM.fleet[zM.fSel].updateTabs();
}
zM.createFleet = function(ip, port, ipv6, startbots, maxbots, name) {
var nF;
var temp2 = function() {
clearInterval(temp[2]);
clearInterval(temp[3]);
clearInterval(temp[4]);
zM.setLoadingWidth(0);
zM.setLoadingTitle('Server isn\'t a valid cursors.io server.');
nF.bots.forEach(X => X.socket.close());
setTimeout(zM.hideLoading, 2000);
};
var temp = [
setInterval(() => {
if (!zM.isLoading) clearInterval(temp[0]), zM.isLoading = true, temp[1]();
}, 50),
function() {
zM.el.fleetTopbarHint.style.display = 'none';
zM.el.fleetPromptOuter.style.display = 'none';
zM.setLoadingWidth(0);
zM.setLoadingTitle('Creating fleet object...');
zM.showLoading();
nF = new zM.Fleet(ip, port, ipv6, startbots, maxbots, name);
zM.fSel = zM.fleet.push(nF) - 1;
nF.createGUI(zM.el.container)
temp[2] = setInterval(() => {
zM.setLoadingTitle('Connecting bots ('+nF.botsOpened+'/'+startbots+')');
zM.setLoadingWidth(100/startbots*nF.botsPinged);
if (nF.verified === false) temp2();
else if (startbots <= nF.botsPinged) {
clearInterval(temp[2]);
setTimeout(async ()=>{
zM.isLoading = false;
zM.hideLoading(),
zM.updateTabs(),
zM.el.game.style.display = 'block';
await zM.asyncWaitUntil('!(Date.now() % 50)');
nF.startTickLoop();
}, 800);
}
}, 50);
}
]
}
// get IP
if (window.m28n) {
m28n.findServerPreference('cursors', (err, end ) => {
if (err) {
console.error(err);
} else {
zM.game.m28nCursorsIP = (end.ipv4 || ('[' + end.ipv6 + ']')) + ':2828';
}
});
}
zM.clog = [
//
//
// Beta v0.2
//
// VVVVVVVVV
{
type: 'title',
msg: 'Beta v0.2'
},
{
type: 'desc',
msg: 'I added several new improvements, mostly to the GUI, a full list is below:<br><br>'
},
{
type: 'desc',
msg: '• Added a changelog and a little information thingy at the bottom right. I plan to make it contain more information soon'
},
{
type: 'desc',
msg: '• Cursor movements are now synchronized, they should no longer split up'
},
{
type: 'desc',
msg: '• Script now loads the Nova Flat font used'
},
];
//dependencies.forEach(i => zM.el.container.appendChild(temp = D.createElement('script'), temp.src = 'http://pastebin.com/raw/'+i, temp));
dependencies.forEach(eval);
zM.setLoadingWidth(0);
zM.showLoading();
zM.setLoadingTitle('Loading dependencies...');
temp = setInterval(() => {
if (zM.dependenciesLoaded == 0b111111) {
zM.setLoadingWidth(100);
clearInterval(temp);
elements.forEach(i => i(zM.el.container));
head.getElementsByTagName('title')[0].textContent = 'zM / No fleets yet' // run all element functions
setTimeout(zM.hideLoading,800);
} else {
var done = 0;
for (var i = 0; i < temp.length; ++i) {
done += (zM.dependenciesLoaded & 2**i) ? 1 : 0;
}
zM.setLoadingWidth((100 / 16 * done) | 0);
}
}, 50);
init();
})(
function() { // add <style>
var out = [];
var temp = [ // fleet topbar
'.zM-' + 'fleet-topbar-outer {',
' position: fixed; top: 0px; left: 0px;',
' width: 100vw; height: 35px;',
' background-color: rgba(0,0,0,.2);',
'}',
'',
'.zM-' + 'fleet-topbar-container {',
' position: fixed; top: 0px; left: 0px;',
' width: calc(100vw - 45px); height: 35px;',
'}',
'',
'.zM-' + 'fleet-topbar-tab {',
' display: inline-block;',
'}',
'',
'.zM-' + 'fleet-topbar-add {',
' position: fixed; top: 0px; right: 0px;',
' width: 45px; height: 35px;',
' background-color: rgba(0,0,0,.0);',
' transition: 0.3s;',
' cursor: pointer; user-select: none;',
'}',
'',
'.zM-' + 'fleet-topbar-add:hover {',
' background-color: rgba(0,0,0,.2)',
'}',
'',
'.zM-' + 'fleet-topbar-hint {',
' color: rgba(255, 255, 255, .3);',
' text-align: right; font-family: Montserrat, sans-serif;',
' font-weight: 200; font-size: 14px;',
' padding-right: 55px;',
' padding-top: 8px; user-select: none;',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
// --------------------------------------------------------
var temp = [ // fleet prompt
'.zM-' + 'fleet-prompt-outer {',
' position: fixed; top: 85px; left: 50px;',
' width: calc( 100vw - 100px ); height: calc( 100vh - 135px );',
' background-color: #0003; display: none; border-radius: 20px; z-index: 5000;',
'}',
'',
'.zM-' + 'fleet-prompt-container {',
' position: fixed; top: 85px; left: calc( 50vw - 300px );',
' width: 600px; height: calc( 100vh - 135px );',
'}',
'',
'.zM-' + 'fleet-prompt-title {',
' text-align: center; font-family: \'Nova Flat\', Montserrat, sans-serif; font-weight: 300;',
' color: rgba(255, 255, 255, .8); font-size: 24px; padding-top: 10px; user-select: none;',
'}',
'',
'.zM-' + 'fleet-prompt-entry {',
' width: 580px; height: 50px; ',
' background-color: rgba(0, 0, 0, .1);',
' border-radius: 10px;',
' margin-left: 10px; margin-top: 10px;',
'}',
'',
'.zM-' + 'fleet-prompt-opt {',
' text-align: right; color: rgba(255, 255, 255, .5); font-family: \'Nova Flat\', Montserrat, sans-serif;',
' font-weight: 300; font-size: 14px;',
' padding-right: 20px; padding-top: 16px; width: 280px; display: inline-block; user-select: none;',
'}',
'',
'.zM-' + 'fleet-prompt-create {',
'position: absolute; bottom: 10px; left: 95px;',
'width: 200px; height: 20px;',
'background-color: #0c6; font-family: \'Nova Flat\', Montserrat, sans-serif;',
'font-size: 16px; font-weight: 300; color: #0008; text-align: center;',
'border-top-left-radius: 10px; border-bottom-left-radius: 10px; user-select: none; cursor: pointer;',
'}',
'',
'.zM-' + 'fleet-prompt-cancel {',
'position: absolute; bottom: 10px; left: 305px;',
'width: 200px; height: 20px;',
'background-color: #666; font-family: \'Nova Flat\', Montserrat, sans-serif;',
'font-size: 16px; font-weight: 300; color: #0008; text-align: center;',
'border-top-right-radius: 10px; border-bottom-right-radius: 10px; user-select: none; cursor: pointer;',
'}',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
// --------------------------------------------------------
var temp = [ // loading bar stuff
'.zM-' + 'loading-outer {',
'position: fixed; top: 0px; left: 0px;',
'width: 100vw; height: 100vh; background: linear-gradient(45deg, rgba(33,33,33,1) 0%, rgba(66,66,66,1) 100%);',
'z-index: 50000; display: none;',
'}',
'',
'.zM-' + 'loading-title {',
'position: fixed; top: calc(50vh - 32px); left: 50vw;',
'color: #fffb; font-family: Montserrat, sans-serif; font-weight: 300; font-size: 24px;',
'transform: translateX(-50%); z-index: 50001; user-select: none;',
'}',
'',
'.zM-' + 'loading-bar-outer {',
'position: fixed; top: 50vh; left: calc(50vw - 200px);',
'width: 400px; height: 30px; background-color: #0003; border-radius: 15px;',
'}',
'',
'.zM-' + 'loading-bar-fill {',
'width: 0%; height: 20px; background-color: #3c5; border-radius: 10px; margin: 5px; transition: 0.5s;',
'}',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
// --------------------------------------------------------
var temp = [ // fleet page
'.zM-' + 'fleet-gui-container {',
'position: fixed; top: 35px; left: 0px; width: 100vw; height: calc(100vh - 35px); z-index:1000;',
'}',
'',
'.zM-' + 'fleet-gui-topbarOuter {',
'position: fixed; top: 35px; left: 0px; width: 100vw; height: 35px; background-color: #0002; z-index:1001;',
'}',
'',
'.zM-' + 'fleet-gui-topbar {',
'position: fixed; top: 35px; left: 0px; width: calc(100vw - 45px); height: 35px; z-index:1002;',
'}',
'',
'.zM-' + 'fleet-gui-tabNew {',
'position: fixed; top: 35px; right: 0px; width: 45px; height: 35px; background-color: #0000; transition: 0.3s; z-index:1003; cursor: pointer;',
'}',
'',
'.zM-' + 'fleet-gui-tabNew:hover {',
' background-color: rgba(0,0,0,.2)',
'}',
'',
'.zM-' + 'fleet-gui-tabNewImg {',
'position: fixed; top: 35px; right: 0px; width: 45px; height: 35px; pointer-events: none; z-index:1004; user-select:none;',
'}',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
// --------------------------------------------------------
var temp = [ // news page
'.zM-' + 'news-outer {',
'position: fixed; top: 35px; left: 0px; width: 100vw; height: calc(100vh - 35px); z-index: 9000;',
'}',
'',
'.zM-' + 'news-container {',
'position: absolute; top: calc(50vh - 190px); left: calc(50vw - 500px); width: 1000px; height: 380px; z-index 9001;',
'}',
'',
'.zM-' + 'news-page-top {',
'z-index: 9002;',
'width: 1000px; margin-left: 0px; margin-bottom: 10px; height: 120px; background-color: #0003; border-top-left-radius: 75px; border-top-right-radius: 75px;',
'}',
'',
'.zM-' + 'news-page-mid {',
'z-index: 9002;',
'width: 1000px; margin-left: 0px; margin-bottom: 10px; height: 120px; background-color: #0003',
'}',
'',
'.zM-' + 'news-page-bottom {',
'z-index: 9002;',
'width: 1000px; margin-left: 0px; margin-bottom: 10px; height: 120px; background-color: #0003; border-bottom-left-radius: 75px; border-bottom-right-radius: 75px;',
'}',
'',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
// --------------------------------------------------------
var temp = [ // game
'.zM-' + 'game {',
'position: fixed; top: 80px; left: 10px; width: 800px; height: 600px; background-color: #fff; z-index: 9000; display: none; cursor: none;',
'}',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
// --------------------------------------------------------
var temp = [ // bottom-right info area
'.zM-' + 'info-outer {',
'position: fixed; bottom: 10px; right: 10px; width: 200px; height: 40px; background-color: #0003; border-radius: 20px; z-index: 20000;',
'}',
'',
'.zM-' + 'info-ver {',
'position: absolute; top: 10px; left: 10px; font-family: Montserrat, sans-serif; color: #fff8; user-select: none; z-index: 20001;',
'}',
'',
'.zM-' + 'info-clog-button-outer {',
'position: absolute; top: 5px; right: 5px; width: 120px; height: 30px; background-color: #0003; user-select: none; z-index: 20002; border-radius: 15px; cursor: pointer;',
'}',
'',
'.zM-' + 'info-clog-button {',
'position: absolute; top: 8px; left: 12px; font-size: 12px; color: #fff8; user-select: none; z-index: 20003; pointer-events: none; font-family: Montserrat;',
'}',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
// --------------------------------------------------------
var temp = [ // changelog area
'.zM-' + 'clog-outer {',
'position: fixed; top: 0px; left: 0px; width: 100vw; height: 100vh; background:linear-gradient(45deg, rgba(33,33,33,1) 0%, rgba(66,66,66,1) 100%); z-index: 15000; display: none;',
'}',
'',
'.zM-' + 'clog-container {',
'position: fixed; top: 50px; left: calc(50vw - 400px); width: 800px; height: calc(100vh - 100px); background-color: #0003; border-radius: 50px; z-index: 15001;',
'}',
'',
'.zM-' + 'clog-title {',
'color: #fffc; font-family: Montserrat; font-weight: 300; font-size: 36px; z-index: 15002; margin-bottom: 20px; margin-left: 30px; margin-top: 30px; user-select: none;',
'}',
'',
'.zM-' + 'clog-desc {',
'color: #fff8; font-family: Montserrat; font-weight: 400; font-size: 14px; z-index: 15002; margin-bottom: 10px; margin-left: 30px; user-select: none;',
'}',
'',
'.zM-' + 'clog-close {',
'position: fixed; top: 0px; right: 0px; width: 45px; height: 35px; cursor: pointer; user-select: none;',
'}',
'',
D.createElement('style')
];
// adds style element to "out"
out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
for (var i = 0; i < out.length; ++i) head.appendChild(out[i]);
return out;
},
function() { // initialize, start different tasks
zM.promptFleet = function() {
if (isNaN(zM.fSel)) {
zM.el.newsOuter.style.display = 'none';
} else {
var temp = parseInt(zM.fSel);
var f = zM.fleet[temp];
if (f) {
f.el.container.style.display = 'none';
}
}
zM.el.game.style.display = 'none';
zM.el.fleetPromptOuter.style.display = 'block';
}
zM.zWs = new WebSocket('ws://localhost:2882');
},
(function(cfg) { // loads configuration
function createConfig(x) { // "x" is a pointer to the variable to change
if (!x.keybinds) {
x.keybinds = []
}
return x;
}
function saveConfig(x) {
try {
var out = JSON.stringify(x);
localStorage.setItem('zM', btoa(out));
return true;
} catch(err) {
switch (true) {
case err instanceof TypeError: {
console.error('[CFG Loader] Error with saving the configuration');
}
default: { // other unhandled errors
console.error('[CFG Loader] Error with loading the configuration: Unhandled error occured');
}
}
console.debug(err);
return false;
}
}
function getConfig(x) {
try {
var out = localStorage.getItem('zM'); // null
if (!out) throw 'Undefined storage';
out = atob(out); // DOMException errors
out = JSON.parse(out); // SyntaxErrors
if (x) x = out;
return out;
} catch(err) {
switch (true) {
case err instanceof DOMException: { // atob error, invalid configuration
console.error('[CFG Loader] Error with loading the configuration: Configuration was incorrectly saved');
} break;
case err instanceof SyntaxError: { // JSON errors return syntax errors for some reason
console.error('[CFG Loader] Error with loading the configuration: Configuration is not an object');
} break;
default: { // other unhandled errors
console.error('[CFG Loader] Error with loading the configuration: Unhandled error occured');
}
}
console.debug(err);
if (x) x = {};
return null;
}
}
if (cfg === null) { // if the localstorage has been erased or script has never been used before
cfg = {};
createConfig(cfg);
} else {
try {
cfg = getConfig(cfg);
if (!cfg) saveConfig((createConfig(cfg), cfg));
} catch(err) {
switch (true) {
case err instanceof DOMException: { // atob error, invalid configuration
console.error('[CFG Loader] Error with loading the configuration: Configuration was incorrectly saved');
} break;
case err instanceof SyntaxError: { // JSON errors return syntax errors for some reason
console.error('[CFG Loader] Error with loading the configuration: Configuration is not an object');
} break;
default: { // other unhandled errors
console.error('[CFG Loader] Error with loading the configuration: Unhandled error occured');
}
}
console.debug(err);
// technically these functions don't need to be placed in each other, they use pointers anyway
cfg = {};
saveConfig(createConfig(cfg));
}
}
return {
raw: cfg,
getConfig: getConfig,
saveConfig: saveConfig,
createConfig: createConfig
}
})(localStorage.getItem('zM')),
// ---
// list of dependencies (pastebin) below
// edit as of oct. 13, 2020: pastebin now uses CORS and doesn't allow requests, so the scripts are now embedded here instead
// ---
[
/* zM external images */
`zM.dependenciesLoaded |= 0b000001;
window.zMIMG = {
add: {img:null,uri:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAjCAYAAAAAEIPqAAAAc0lEQVRYR+2VSQoAIAwDzf8fXRE8FqF1ozCetYQxSdUKHhXU3BD96tcgDekFAeyBPX7aw8xM0lEbHh3mwUH0pAJp7EF7OARGQ2QXS6YOCSJBJIjBxLHGWeNBy+xev97TuwK994i+QRXSr6hCGtJBAiUrrwPx1zwkY3UoxAAAAABJRU5ErkJggg=="},
close: {img:null,uri:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAjCAYAAAAAEIPqAAAAu0lEQVRYR+2VUQrAIAxD7f0P7fBDGLLZtKSCkP0a18czbtYufOxC5iboU6cm0zK9MaB6qB6qx6kOVJvuvXczgy91NL/yw4M8wSgImtvNo0GPIR6Qt+6JmetU6B04C3jMoEN/gTOBy6Df4GzgUmik42iHy74e64un4WtMr6BscPpF/ANkglOhPTBvHe04DRoFQnPlf8QoSDR/7OuBHnUmR6tHZnh2j6Cz5qL7ZDpqLJuX6ay56D6ZjhrL5h8i/mQkg2UCqwAAAABJRU5ErkJggg=="},
cursor: {img:null,uri:"data:image/png;base64,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"},
public: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABrElEQVRIS7WWvU7DQBCEZw3hR6KhAImSnpqSiseghzcCet4OBSEh8R8bjb3jrM4kurOTk1Z27OSb3XN21oYtLtsiG//B47VmingE6TwVlECxUATynPELYM8zJjCN7GIivALA+PZfHwGoPRZ+lFCWgOCE7gDYNbP35qEGbttbxwAIZjU/pQIRPgMwM7O3Fs7VCZx6NayoSEBwZk34PoBXPDZ4vgFOnnqBMwAfLpItEOF8iAcAXgRn2lMEUvghgHmETxHIgo8VyIaPESiClwoUw0sERsFzBbLg7d9x1Vo22qf3AbuZXdgM4FVVzev7RdtESYY93szQNJ1JhnNaxVfo4npt5qGBrt1j6DMKdiphDHYvg+e0CX5nmLmZzeUtdlcxwysvkzCWLIfkkdckom1ZDVeHOvjS/ZxQlSy47FiOKaGVe955S7cu3N8JYzYpXN5OEW2VwIMHunRF4JzeHrIWXNsSh0YUaaGKgZ/7iKP1coDwyyqbAn3JyT8znbPt58Ek8oyZNe+p5EmTiCDNUA4OBtdGZqgmfzwSvpHpH7do4+8t8fls5Y1rjTuNu/UHX28RMaWkZ08AAAAASUVORK5CYII='},
movement: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABr0lEQVRIS7WWzU7CUBCFz1TxJ3HjxsSle9cuXfkowL5Pwh6eEWNiIv5BzYE5dWjF3NuWJpNeSvnOzC1zpoYjHnZENv6Cx2tVH/EI0ropKIFsoQjkmvEN4MwzJrAZycVEeAGA8em/vgKw8Vj7WUJJAoITegLg1MzeNpMJbD4n4BoAwazmK1cgwkcARmb2SjgPF7jxalhRloDgzJrwcwAv1XQKzGZAWUrgFsDKRZIFIpwP8QLAcw1n+j0EmvBLAMs9eA+BNHhHgXR4B4E8eKZAPjxDoBs8USANXpYH2z002rv3AbuZtlG14EVRLNfj8a6J9jOsBcwMVbUzybCmVXyELt78n/lvAz25x9BnFOxUwhjsXgbXtAne087czJbylmKxYIaPXiZhLFkOyTOvSUTbchiuDnXwg/s5oSpZcNmxHFNCB/d86y2+uffu74QxmyZc3k4RbZXArQdauyKAO3p7yFpwbUscGlFkC1W0/NxHHK2XA4Q3q2wK1CU3/pvNObv93JpEnjGz5ncqudckIkgzlIODwWOQGarJH8+EDzL94xYN/t4Sn89R3riS3kVybvoBL+YcMQOUqAIAAAAASUVORK5CYII='},
local: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABrklEQVRIS7WWvU7DQBCEZw3hR6KhCBIlPTUlFY9BD28E9Hk7ZISExH9sNGbH2dgY3dmJpZUvif3N7jk7a8MWD9siG3/B43f1FPEI0rorKIFsoQjkmvENYM8zJrAbycVEeAGA8el3HwGoPJZ+llCSgOCE7gDYNbPX6r6G3TT3HwMgmNV85QpE+AzAzMxeCOfhAideDSvKEhCcWRO+D+C5fgBw/Qgs5hI4BfDmIskCEc6HeADgqYUz/QkCXfghgHINPkEgDT5SIB0+QiAPnimQD88QGAdPFEiDL+aD7R4a7d37gN1M26h78KIoyuVd9dtE6xm2AmaGuvYuXq1pFR+hi6v/M1810JV7DH1GwU4ljMHuZXBNm+A1/czNrJS3FLdNhpdeJmEsWQ7JM7+TiLZlGK4OdfCF+zmhKllw2bEcU0KDe954i2/uufs7YcymC5e3U0RbJXDvgbauCOCM3h6yFlzbEodGFGmgip6f+4ij9XKA8GKVTYG25M5/sztnm8+9SeQZM2v+ppInTSKCNEM5OBg8NjJDNfnjmfCNTP+4RRt/b4nPZytvXEnvIjkX/QBfbxExMnV8VAAAAABJRU5ErkJggg=='},
follow: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABwklEQVRIS7WWS07DQBBEawzhE7FBgkgs2bMBJJasWHAQYM9JWAcukkvAPfgEISGFf4zK6YpaY4xm4sRSy5PEedU9dlc7YIFHWCAbf8H9d2UbcQ/SOhaUQLaQB3LN+AawYhkTGEdyMR5eAGB82r83AIwtfuwsoSQBwQldArAcQhidPxzgevuWgE0ABLOar1wBD+8A6IQQXgnnYQI9q4YVZQkIzqwJXwXwcvF4iKutAS6fTiWwA+DNRJIFPJw3cQ3As+DMvo1ADF8HMPTwNgJJ8FkFkuGzCGTBcwWy4TkCM8FTBRrh/e4Ao+6ky/k4Nh2u0d6tD9jNtI2yBi+KYnh2v181UZThlB9CQFlOTNKtaRUfrovH/26La6AT8xj6jIKdShiD3cvgmjbBa+qZhxCG8pab3h0zPLYyCWPJckie+Z1EtC3NcHWogY/MzwlVyYLLjuWYEmrc88pbbHP3zN8JYzYxXN5OEW2VwLUbOnVFALv0dpe14NoWPzS8SAVV1PzcRhytlwOEF6tsCkxLjh7NeM5Wn2uTyDJm1vxNJbeaRARphnJwMHjMZYZq8vsz4XOZ/n6L5v7e4u/PQt64kt5Fci76BTTHKDGf8J1/AAAAAElFTkSuQmCC'},
admin: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAAB80lEQVRIS7WWuW7CUBBF7zghi5QmBZFSUlpKaaVMlc+ghvwDNXXKADWf494fgYgiRSIrftF1ZuDhBdkslkbez515z++OBUfc5IhslMH9a24fcR9kx3lBE2gs5AN5zPgFcKYZE5iP2sX48AAA41vfvgKQaix1b0K1BAxO6AmAUxFZpCMH6WfvXwMgmNX8NBXw4S0ALRF5J5ybCtxoNayokYDBmTXh5wDe3BhAdwZM2yZwC+BDRWoL+HBO4gWA1xWc6e8hkIdfApi7uAeEw/WkJQNINOF5owrqwYndQWAL/BnAYvOTayhQCo/jGGEYln7LSZIgiqJaQ1QK78UOw3J2JjhIgEmUvbp1DnaC1xWoBWemVZtWwIX2qeuAq5m24QrwIAjm6csSs+4/rj0F0N80ShGBc7qK18e0ii9vFaelmWPsMrgHflSPoc9YcKUSxuDqZfCYNsFnipmLyNyNWBUgTwEzfNAyCWPJ5pDc85qJ2LBUw7lCmbmC79XPCbWSDW52bI5pQpVjnnmLTt6d+jthzCYPN2+niA2VgQsTunJFAB16u5e1wW1Y/Kbhi2RQi4Kfa4uj9bKB8GErmwKrknOfZr7PZueFTqQZM2ves5L36kQEWQ9l42BwO0gPtc7v7wk/SPf3h+jg/y3+/Bzlj6vanXa88we7KRoxQlE4ggAAAABJRU5ErkJggg=='}
}
for (var i in zMIMG) {
if (zMIMG.hasOwnProperty(i)) {
zMIMG[i].img = new Image();
zMIMG[i].img.src = zMIMG[i].uri;
}
}`,
/* zM fleet class */
`zM.dependenciesLoaded |= 0b000010;
zM.Fleet = class {
constructor (ip, port, ipv6, maxbots, startbots, name) {
console.log(startbots);
this.ip = ip;
this.port = port;
this.maxBots = maxbots;
this.startBots = startbots;
this.name = name;
this.ipv6 = ipv6;
this.cSel = 0;
this.wsIp = 'ws://' + (this.ipv6?'['+this.ip+']':this.ip) + ':' + this.port;
this.bots = [];
this.ids = [];
this.botsPinged = 0;
this.botsOpened = 0;
this.botsIds = 0;
this.botsLevels = 0;
this.botsBusy = 0;
this.botsDeployed = 0;
this.botsUpdated = 0;
this.verified = true;
this.isHelping = false;
this.el = {};
this.helpers = [];
var extF = this;
this.helpIndex = 0;
this.helpLoop = setInterval(()=>{
++this.helpIndex;
if (this.isHelping && this.helpers.length > 0) {
for (var i = 0; i < this.helpers.length; ++i) {
this.helpers[i].toHelp = [];
this.helpers[i].helping = true;
if (this.helpers[i].socket.readyState != 1) this.helpers.splice(i--, 1);
}
var todo = [];
var obj = this.bots[this.cSel].obj;
for (var i = 0; i < obj.length; ++i) {
if (obj[i].type === 4) todo.push(obj[i]);
}
var amount = todo.length / this.helpers.length;
var j = 0;
var count = amount;
for (var i = 0; i < this.helpers.length; ++i) {
for (; j < count | 0; ++j) {
var obj = todo[j];
var moves = zM.path(this.helpers[i].realX, this.helpers[i].realY, obj.x + (obj.w>>1), obj.y + (obj.h>>1), this.helpers[i].obj, this.helpers[i].grid);
if ((this.helpers[i].realX === obj.x + (obj.w>>1) && this.helpers[i].realY === obj.y + (obj.h>>1)) ? true : moves.length > 1) this.helpers[i].toHelp.push(todo[j]);
}
count += amount;
}
var f = this;
if (this.isHelping) for (var j = 0; j < this.helpers.length; ++j) {
var index = this.helpIndex % this.helpers[j].toHelp.length;
if (isNaN(index)) index = this.helpIndex % this.helpers[0].toHelp.length; // has nothing to do, copy off other bots
if (isNaN(index)) index = 0; // still undefined, no buttons at all
console.log(j, this.helpers[j]);
console.log(index, this.helpers[j].toHelp[index]);
if (this.helpers[j].toHelp.length <= index) continue;
var moves = zM.path(this.helpers[j].realX, this.helpers[j].realY, this.helpers[j].toHelp[index].x + (this.helpers[j].toHelp[index].w>>1), this.helpers[j].toHelp[index].y + (this.helpers[j].toHelp[index].h>>1), this.helpers[j].obj, this.helpers[j].grid);
moves.forEach(Y => {
zM.packet.moveSocket([this.helpers[j].socket], Y[0], Y[1], [this.helpers[j]]);
});
for (var k = 0; k < 10; ++k) zM.packet.clickSocket([this.helpers[j].socket], this.helpers[j].toHelp[index].x + (this.helpers[j].toHelp[index].w>>1), this.helpers[j].toHelp[index].y + (this.helpers[j].toHelp[index].h>>1), [this.helpers[j]])
}
}
},300);
this.elTemplate = {
tab: '<div style="width: '
}
setTimeout(()=>{for (var i = 0; i < startbots; ++i) this.bots.push(new zM.Bot(this));},300);
}
createGUI(c) {
var temp = this.el = {
container: D.createElement('div'),
topbarOuter: D.createElement('div'),
topbar: D.createElement('div'),
tabNew: D.createElement('div'),
tabNewImg: D.createElement('img')
}
temp.container.className = 'zM-fleet-gui-container';
c.appendChild(temp.container);
temp.topbarOuter.className = 'zM-fleet-gui-topbarOuter';
temp.container.appendChild(temp.topbarOuter);
temp.topbar.className = 'zM-fleet-gui-topbar';
temp.topbarOuter.appendChild(temp.topbar);
temp.tabNew.className = 'zM-fleet-gui-tabNew';
temp.topbarOuter.appendChild(temp.tabNew);
temp.tabNewImg.className = 'zM-fleet-gui-tabNewImg';
temp.tabNewImg.src = zMIMG.add.uri;
temp.tabNew.appendChild(temp.tabNewImg);
temp.tabNew.addEventListener('click', ev => {
this.bots.push(new zM.Bot(this));
});
this.updateTabs();
}
updateTabs() {
this.el.container.style.display = 'block';
this.el.topbar.innerHTML = '';
this.el.topbarOuter.appendChild(this.el.tabNew);
this.el.tabNew.appendChild(this.el.tabNewImg);
var nb = [];
for (var i = 0; i < this.bots.length; ++i) {
if (this.bots[i].socket.readyState == 1) nb.push(this.bots[i]);
}
for (var i = 0; i < nb.length; ++i) {
var b = nb[i];
this.el.topbar.innerHTML += \`<div style="position: absolute; top: 0px; left: \${100/nb.length*i}%; width: \${100/nb.length}%; height: 35px; border-right: 1px solid #fffc; background-color: \${i === this.cSel ? '#fff3' : '#fff0'};transition: 0.3s;"><div style="position: absolute; top: 0px; left: 0px; width: 100%; height: 35px; background-color: #0000; transition: 0.3s;" onmouseenter="this.style.backgroundColor = '#0003';" onmouseout="this.style.backgroundColor = '#0000'" onclick="zM.fleet[zM.fSel].cSel = \${i}; zM.fleet[zM.fSel].updateTabs()"><div style="color:#fffc;font-family:\'Nova Flat\',Montserrat,sans-serif;font-weight:300;padding:8px;pointer-events:none;white-space:nowrap;overflow-x:hidden;user-select:none;">\${eval(\`zM.fleet[zM.fSel].cSel === \${i} ? '(Selected)' : ''\`)} #\${i} / ID \${b.id} / LVL \${b.level}</div></div></div>\`;
}
}
/* depreciated, only solves for selected bot
startTickLoop() {
this.tickLoop = setInterval(()=>{
var b = this.bots[this.cSel];
var toMove = [];
for (var i = 0; i < this.bots.length; ++i) {
if (this.bots[i].level === b.level) if (zM.useWallhack) toMove.push(this.bots[i].socket);
}
if (zM.useWallhack) {
var moves = zM.path(b.realX, b.realY, zM.pos.mouseX>>1, zM.pos.mouseY>>1, b.obj);
moves.forEach(Y => {
zM.packet.moveSocket(toMove, Y[0], Y[1]);
});
} else {
zM.packet.moveSocket(toMove, zM.pos.mouseX>>1, zM.pos.mouseY>>1);
}
for (;-1<zM.clickQueue;--zM.clickQueue) zM.packet.clickSocket(toMove, zM.pos.mouseX>>1, zM.pos.mouseY>>1);
if (zM.drawing) zM.packet.drawSocket(toMove, zM.pos.lastMouseX>>1, zM.pos.lastMouseY>>1, zM.pos.mouseX>>1, zM.pos.mouseY>>1);
zM.pos.lastMouseX = zM.pos.mouseX;
zM.pos.lastMouseY = zM.pos.mouseY;
}, 50);
}*/
// alternative, solves for each bot- causes lots of lag without grid
startTickLoop() {
this.tickLoop = setInterval(()=>{
for (var i = 0; i < zM.fleet.length; ++i) {
if (zM.fleet[i] === this) break;
}
if (i !== zM.fSel) return;
var b = this.bots[this.cSel];
var toMoveSocket = [];
var toMove = [];
for (var i = 0; i < this.bots.length; ++i) {
// disconnect after 90 min of AFK, should bypass any bans from AFKing
if (Date.now() - this.bots[i].packets.lastSent > 5400000) this.bots[i].socket.close();
if (
this.bots[i].level === b.level &&
!this.bots[i].helping && !this.bots[i].deployed
) toMove.push(this.bots[i]), toMoveSocket.push(this.bots[i].socket);
}
if (zM.movement) {
if (zM.useWallhack) {
// solve first
toMove.forEach(X => {
// random here is anti-idle disconnect
if (!(X.realX === zM.pos.mouseX>>1 && X.realY === zM.pos.mouseY>>1) || (Math.random() >= 0.99 && zM.antiIdle)) {
var moves = zM.path(X.realX, X.realY, zM.pos.mouseX>>1, zM.pos.mouseY>>1, b.obj, b.grid);
X.toDo = moves;
X.realX = zM.pos.mouseX>>1;
X.realY = zM.pos.mouseY>>1;
}
});
// then send packets synchronized, all together
var count = 0;
for (var i = 0; i < toMove.length; ++i) count = Math.max(count, toMove[i].toDo.length);
for (var i = 0; i < count; ++i) {
toMove.forEach(X => {
if (i >= X.toDo.length) return;
zM.packet.moveSocket([X.socket], X.toDo[i][0], X.toDo[i][1], [X]);
});
}
} else {
zM.packet.moveSocket(toMoveSocket, zM.pos.mouseX>>1, zM.pos.mouseY>>1, toMove);
}
} else {
if (zM.clickQueue >= 1) {
toMove.forEach(X => {
var moves = zM.path(X.realX, X.realY, zM.pos.mouseX>>1, zM.pos.mouseY>>1, b.obj, b.grid);
moves.forEach(Y => {
zM.packet.moveSocket([X.socket], Y[0], Y[1], [X]);
});
});
}
if (zM.antiIdle) {
toMove.forEach(X => {
// random here is anti-idle disconnect, if movement is disabled.
if (Date.now() - X.packets.lastSent > 10000) zM.packet.moveSocket([X.socket], X.realX, X.realY, [X]);
});
}
}
for (;0<zM.clickQueue;--zM.clickQueue) zM.packet.clickSocket(toMoveSocket, zM.pos.mouseX>>1, zM.pos.mouseY>>1, toMove);
if (zM.drawing && zM.movement) zM.packet.drawSocket(toMoveSocket, zM.pos.lastMouseX>>1, zM.pos.lastMouseY>>1, zM.pos.mouseX>>1, zM.pos.mouseY>>1, toMove);
zM.pos.lastMouseX = zM.pos.mouseX;
zM.pos.lastMouseY = zM.pos.mouseY;
}, 50);
}
}`,
/* zM bot class */
`zM.dependenciesLoaded |= 0b000100
zM.Bot = class {
constructor (fleet) {
this.fleet = fleet;
this.socket = new WebSocket(this.fleet.wsIp);
this.socket.binaryType = 'arraybuffer';
this.opened = false;
this.isOpen = false;
this.level = -1;
this.id = -1;
this.obj = [];
this.players = [];
this.clicks = [];
this.drawings = [];
this.realX = 400;
this.realY = 300;
this.local = 0;
this.packets = {
receivedTotal: 0,
sentTotal: 0,
receivedPS: 0,
sentPS: 0
}
this.toHelp = [];
this.toDo = [];
this.timestampStart = 0;
this.helping = false;
this.deployed = false;
this.prevLevels = [];
this.socket.addEventListener('open', () => {
++this.fleet.botsOpened;
this.opened = true;
this.isOpen = true;
++this.fleet.botsPinged;
zM.updateTabs();
});
this.socket.addEventListener('close', () => {
if (this.opened) {
--this.fleet.botsOpened;
var i = this.fleet.ids.indexOf(this.id);
if (i != -1) this.fleet.ids.splice(i, 1);
}
else ++this.fleet.botsPinged;
this.isOpen = false;
for (var i = 0; i < this.fleet.bots.length; ++i) if (this.fleet.bots[i] == this) { console.log('y'); this.fleet.bots.splice(i,1); break; }
zM.updateTabs();
});
this.socket.addEventListener('message', ev => {
var buf = ev.data,
dat = new DataView(buf);
++this.packets.receivedTotal;
++this.packets.receivedPS;
setTimeout(()=>{--this.packets.receivedPS},1000);
var type = dat.getUint8(0);
if (type === 0) this.id = dat.getUint32(1, 1), ++this.fleet.botsIds, this.fleet.ids.push(this.id);
else if (type === 1) {
var out = zM.parse.cursors(buf, 1);
this.local = out.shift();
var players = out.shift();
var idsHere = [];
// create players for all new ids
for (var i = 0; i < players.length; ++i) {
if (players[i].id === this.id) this.realX = players[i].x, this.realY = players[i].y;
var index = -1;
for (var j = 0; j < this.players.length; ++j) {
if (this.players[j].id === players[i].id) {index = j; break;}
}
if (index === -1) this.players.push({
x: players[i].x,
y: players[i].y,
lastUpdate: Date.now(),
ox: players[i].x,
oy: players[i].y,
id: players[i].id
});
}
for (var i = 0; i < players.length; ++i) {
for (var j = 0; j < this.players.length; ++j) {
if (this.players[j].id === players[i].id) {
this.players[j].ox = zM.ease(this.players[j].x, this.players[j].ox, this.players[j].lastUpdate);
this.players[j].oy = zM.ease(this.players[j].y, this.players[j].oy, this.players[j].lastUpdate);
this.players[j].x = players[i].x;
this.players[j].y = players[i].y;
this.players[j].lastUpdate = Date.now();
idsHere.push(players[i].id);
}
}
}
var nPl = [];
for (var i = 0; i < idsHere.length; ++i) {
for (var j = 0; j < this.players.length; ++j) {
if (idsHere[i] === this.players[j].id) nPl.push(this.players[j]);
}
}
this.players = nPl;
var off = out.shift();
out = zM.parse.clicks(buf, off);
for (;0 < out[0].length;) {
this.clicks.push(out[0].shift());
}
off = out.pop();
out = zM.parse.remove(buf, off);
for (var i = 0; i < out[0].length; ++i) {
for (var j = 0; j < this.obj.length; ++j) {
if (this.obj[j].id === out[0][i]) {this.obj.splice(j, 1); break;}
}
}
off = out.pop();
out = zM.parse.objects(buf, off);
var obj = zM.parse.objData(out.shift());
for (var i = 0; i < obj.length; ++i) {
var index = -1;
for (var j = 0; j < this.obj.length; ++j) {
if (this.obj[j].id === obj[i].id) {index = j; break;};
}
if (index === -1) this.obj.push(obj[i]);
else this.obj[j] = obj[i];
}
off = out.pop();
out = zM.parse.drawing(buf, off);
for (var i = 0; i < out[0].length; ++i) {
var todo = out[0][i];
this.drawings.push(todo);
}
this.online = dat.getUint32(dat.byteLength-4, true);
} else if (type === 4) {
if (this.level === -1) ++this.fleet.botsLevels;
this.drawings = [];
this.realX = dat.getUint16(1, true);
this.realY = dat.getUint16(3, true);
var objdata = zM.parse.objects(buf, 5);
this.obj = zM.parse.objData(objdata[0]);
var grid = 100;
for (var i = 0; i < this.obj.length; ++i) {
if (grid <= 1) {grid = 1; break;}
if (this.obj[i].type === 1) if (
(this.obj[i].x/grid|0) != (this.obj[i].x/grid) ||
(this.obj[i].y/grid|0) != (this.obj[i].y/grid) ||
(this.obj[i].w/grid|0) != (this.obj[i].w/grid) ||
(this.obj[i].h/grid|0) != (this.obj[i].h/grid)
) --grid, i = -1;
}
this.grid = grid;
var compare = [];
for (var i = 0; i < this.obj.length; ++i) {
var o = this.obj[i];
if (o.type === 0) {
compare.push({
x: o.x,
y: o.y,
size: o.size,
content: o.content
});
} else if (o.type === 1) {
if (o.color === '#000000') compare.push({
x: o.x,
y: o.y,
w: o.w,
h: o.h
});
} else if (o.type === 2) {
compare.push({
x: o.x,
y: o.y,
w: o.w,
h: o.h,
isBad: o.isBad
});
} else {
compare.push({
x: o.x,
y: o.y,
w: o.w,
h: o.h,
color: o.color
});
}
}
compare = JSON.stringify(compare);
var i = this.prevLevels.indexOf(compare);
if (i != -1) this.level = i;
else ++this.level, this.prevLevels.push(compare);
this.fleet.updateTabs();
} else if (type === 5) {
this.realX = dat.getUint16(1, true);
this.realY = dat.getUint16(3, true);
}
});
}
}`,
`zM.dependenciesLoaded |= 0b001000;
let ctx;
zM.reqLoad = function() {
zM.r = {
fps: 0,
hudText: function(text, x, y, subLength = 0, color = '#fff') {
ctx.font = '12px "Nova Flat"';
ctx.globalAlpha = .5;
ctx.lineWidth = 3;
ctx.strokeStyle = '#000';
ctx.strokeText(text, x-ctx.measureText(text).width*subLength, y);
ctx.globalAlpha = 1;
ctx.fillStyle = color;
ctx.fillText(text, x-ctx.measureText(text).width*subLength, y);
},
infLvl: 5
}
ctx = zM.el.game.getContext('2d');
}
zM.reqDo = function() {
ctx.clearRect(0, 0, 800, 600);
if (isNaN(zM.fSel)) {
ctx.font = '60px "Nova Flat"';
ctx.fillStyle = '#000';
var t = 'No fleet selected';
ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
} else if (!zM.fleet[zM.fSel]) {
ctx.font = '60px "Nova Flat"';
ctx.fillStyle = '#000';
var t = 'Undefined fleet selected';
ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
} else if (!zM.fleet[zM.fSel].bots[zM.fleet[zM.fSel].cSel]) { // you can get this if the bot no longer exists (or an invalid bot selected state)
ctx.font = '60px "Nova Flat"';
ctx.fillStyle = '#000';
var t = 'Lost connection to server';
ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
} else {
var b = zM.fleet[zM.fSel].bots[zM.fleet[zM.fSel].cSel];
if (b.socket.readyState == WebSocket.CONNECTING) {
ctx.font = '60px "Nova Flat"';
ctx.fillStyle = '#000';
var t = 'Connecting';
ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
} else { // we don't need to handle closed states, the bot will be gone
for (var i = 0; i < b.obj.length; ++i) {
var o = b.obj[i];
switch (o.type) {
case 0:
ctx.globalAlpha = 1;
ctx.font = o.size + 'px "Nova Flat"';
ctx.fillStyle = '#000';
var x = o.x*2;
if (o.isCentered) x -= ctx.measureText(o.content).width/2;
ctx.fillText(o.content, x, o.y*2);
break;
case 1:
ctx.globalAlpha = 1;
ctx.fillStyle = o.color;
ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
ctx.globalAlpha = .2;
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.strokeRect(o.x*2+1, o.y*2+1, o.w*2-2, o.h*2-2);
break;
case 2:
ctx.globalAlpha = .2;
ctx.fillStyle = o.isBad?'#f00':'#0f0';
ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
break;
case 3:
ctx.globalAlpha = .2;
ctx.fillStyle = o.color;
ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
ctx.font = '24px "Nova Flat"';
ctx.fillStyle = '#000';
ctx.globalAlpha = .5;
ctx.fillText(o.count, o.x*2 + o.w - ctx.measureText(o.count).width/2, o.y*2+o.h+9);
break;
case 4:
ctx.globalAlpha = 1;
ctx.fillStyle = o.color;
ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
ctx.globalAlpha = .2;
ctx.fillStyle = '#000';
ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
ctx.globalAlpha = 1;
ctx.fillStyle = o.color;
ctx.fillRect(o.x*2+8, o.y*2+8, o.w*2-16, o.h*2-16);
var l = Date.now() - o.lastClickAt > 150 ? 8 : 16;
ctx.globalAlpha = .2;
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
ctx.beginPath(),
ctx.moveTo(o.x*2+1, o.y*2+1),
ctx.lineTo(o.x*2+o.w*2-2, o.y*2+1),
ctx.lineTo(o.x*2+o.w*2-2, o.y*2+o.h*2-2),
ctx.lineTo(o.x*2+1, o.y*2+o.h*2-2),
ctx.lineTo(o.x*2+1, o.y*2+1);
ctx.lineTo(o.x*2+1+l, o.y*2+1+l);
ctx.moveTo(o.x*2+o.w*2-2, o.y*2+1),
ctx.lineTo(o.x*2+o.w*2-2-l, o.y*2+1+l);
ctx.moveTo(o.x*2+o.w*2-2, o.y*2+o.h*2-2);
ctx.lineTo(o.x*2+o.w*2-2-l, o.y*2+o.h*2-2-l);
ctx.moveTo(o.x*2+1, o.y*2+o.h*2-2),
ctx.lineTo(o.x*2+1+l, o.y*2+o.h*2-2-l);
ctx.moveTo(o.x*2+l, o.y*2+l),
ctx.lineTo(o.x*2+o.w*2-l, o.y*2+l),
ctx.lineTo(o.x*2+o.w*2-l, o.y*2+o.h*2-l),
ctx.lineTo(o.x*2+l, o.y*2+o.h*2-l),
ctx.lineTo(o.x*2+l, o.y*2+l);
ctx.stroke();
ctx.fillStyle = '#000';
ctx.globalAlpha = .5;
ctx.font = '24px "Nova Flat"';
ctx.fillText(o.count, o.x*2 + o.w - ctx.measureText(o.count).width/2, o.y*2+o.h+9);
}
}
ctx.strokeStyle = '#000';
ctx.lineWidth = 1.5;
for (var i = 0; i < b.clicks.length; ++i) {
if (typeof b.clicks[i] === 'object') {
if (Date.now() - b.clicks[i].time > 500) b.clicks.splice(i--, 1);
else {
ctx.beginPath(),
ctx.globalAlpha = .5 - (Date.now() - b.clicks[i].time)/1000;
var radius = (Date.now() - b.clicks[i].time)/20;
if (radius < 0.1) radius = 0.1 // Anti-crash failsafe
ctx.arc(b.clicks[i].x*2, b.clicks[i].y*2, radius, 0, 2*Math.PI);
ctx.stroke();
}
}
}
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.globalAlpha = .3;
for (var i = 0; i < b.drawings.length; ++i) {
if (typeof b.drawings[i] === 'object') {
if (Date.now() - b.drawings[i].time > 10000) b.drawings.splice(i--, 1);
else {
ctx.beginPath(),
ctx.moveTo(b.drawings[i].x*2, b.drawings[i].y*2);
ctx.lineTo(b.drawings[i].x2*2, b.drawings[i].y2*2);
ctx.stroke();
}
}
}
ctx.globalAlpha = 1;
ctx.font = '12px "Nova Flat"';
for (var i = 0; i < b.players.length; ++i) {
var img;
if (zM.fleet[zM.fSel].ids.indexOf(b.players[i].id) != -1) {
for (var j = 0; i < zM.fleet[zM.fSel].bots.length; ++j) {
if (zM.fleet[zM.fSel].bots[j]) if (zM.fleet[zM.fSel].bots[j].id == b.players[i].id) break;
}
if (j < zM.fleet[zM.fSel].bots.length) {
if (zM.fleet[zM.fSel].bots[j].helping || zM.fleet[zM.fSel].bots[j].deployed) img = zMIMG.movement.img;
else img = zMIMG.local.img;
} else img = zMIMG.local.img;
} else img = zMIMG.cursor.img;
var x = zM.ease(b.players[i].x, b.players[i].ox, b.players[i].lastUpdate)*2;
var y = zM.ease(b.players[i].y, b.players[i].oy, b.players[i].lastUpdate)*2;
ctx.drawImage(img, x-4, y-5);
x += 5;
y-= 2;
if (x + ctx.measureText(\`\${b.players[i].id}\`).width > 790) x = 790 - ctx.measureText(\`\${b.players[i].id}\`).width;
if (y - 12 < 10) y = 22;
zM.r.hudText(\`\${b.players[i].id}\`, x, y);
}
switch (zM.r.infLvl) {
case 5:
zM.r.hudText(\`Received (tp/ps) \${b.packets.receivedTotal} / \${b.packets.receivedPS}\`, 790, 22, 1);
zM.r.hudText(\`Sent (tp/ps) \${b.packets.sentTotal} / \${b.packets.sentPS}\`, 790, 36, 1);
case 4:
case 3:
case 2:
zM.r.hudText(\`Level \${b.level}\`, 10, 36);
case 1:
zM.r.hudText(
b.local < 30 ? 'Use shift+click to draw ('+b.local+' > 0)' :
b.local < 100 ? 'Too many cursors, drawing is disabled ('+b.local+' > 30)' :
b.local < 1010 ? 'Too many cursors, not all cursors are shown ('+b.local+' > 100)' :
'Use shift+click to draw ('+b.local+' > 1010)'
, 10, 590);
zM.r.hudText(\`\${b.online} players online\`, 790, 590, 1);
case 0:
}
}
}
if (zM.r.infLvl >= 2) zM.r.hudText('FPS ' + zM.r.fps,10,22);
ctx.fillStyle = zM.movement?'#ff0':'#f00';
ctx.globalAlpha = 0.3;
ctx.beginPath();
ctx.moveTo(zM.pos.mouseX+3, zM.pos.mouseY+6);
ctx.arc(zM.pos.mouseX+3, zM.pos.mouseY+6, 20, 0, 2*Math.PI);
ctx.fill();
ctx.globalAlpha = 1;
ctx.drawImage(zMIMG.cursor.img, zM.pos.mouseX-4, zM.pos.mouseY-5);
zM.reqAfter();
}
zM.reqAfter = function() {
++zM.r.fps;
requestAnimationFrame(zM.reqDo);
setTimeout(()=>{--zM.r.fps},1000);
}`,
/* zM packet parsing */
`zM.dependenciesLoaded |= 0b010000;
zM.parse = {
/**
* Returns an array as [local, players, offset]
*/
cursors: function(buffer, offset) {
var dat = new DataView(buffer);
var local = dat.getUint16(offset, true);
offset += 2;
var players = [];
for (var i = 0; i < local; ++i) {
players.push({
id: dat.getUint32(offset, true),
x: dat.getUint16(offset + 4, true),
y: dat.getUint16(offset + 6, true),
});
offset += 8;
}
return [local, players, offset];
},
/**
* Returns an array as [clicks, offset]
*/
clicks: function(buffer, offset) {
var dat = new DataView(buffer);
var count = dat.getUint16(offset, true);
var clicks = [];
offset += 2;
for (var i = 0; i < count; ++i) {
clicks.push({
x: dat.getUint16(offset, true),
y: dat.getUint16(offset + 2, true),
time: Date.now()
});
offset += 4;
}
return [clicks, offset];
},
/**
* Returns an array as [clicks, offset]
*/
drawing: function(buffer, offset) {
var dat = new DataView(buffer);
var count = dat.getUint16(offset, true);
var drawings = [];
offset += 2;
for (var i = 0; i < count; ++i) {
drawings.push({
x: dat.getUint16(offset, true),
y: dat.getUint16(offset + 2, true),
x2: dat.getUint16(offset + 4, true),
y2: dat.getUint16(offset + 6, true),
time: Date.now()
});
offset += 8;
}
return [drawings, offset];
},
/**
* Returns an array as [ids, offset]
*/
remove: function(buffer, offset) {
var dat = new DataView(buffer);
var count = dat.getUint16(offset, true);
var ids = [];
offset += 2;
for (var i = 0; i < count; ++i) {
ids.push(dat.getUint32(offset, true));
offset += 4;
}
return [ids, offset];
},
/**
* Parses objdata (string) and outputs as objects.
*/
objData: function(objdata) {
var obj = objdata;
var nObj = [];
for (var i = 0; i < obj.length; ++i) {
var nO = {};
obj[i] = obj[i].split(/\\.+/g);
nO.id = parseInt(obj[i].shift());
var type = obj[i].shift();
switch (type) {
case '0':
nO.type = 0;
nO.x = parseInt(obj[i].shift());
nO.y = parseInt(obj[i].shift());
nO.size = parseInt(obj[i].shift());
nO.isCentered = obj[i].shift() === 'false'?false:true;
nO.content = obj[i].join('');
break;
case '1':
nO.type = 1;
nO.x = parseInt(obj[i].shift());
nO.y = parseInt(obj[i].shift());
nO.w = parseInt(obj[i].shift());
nO.h = parseInt(obj[i].shift());
nO.color = obj[i].shift();
break;
case '2':
nO.type = 2;
nO.x = parseInt(obj[i].shift());
nO.y = parseInt(obj[i].shift());
nO.w = parseInt(obj[i].shift());
nO.h = parseInt(obj[i].shift());
nO.isBad = obj[i].shift()==='false'?false:true;
break;
case '3':
nO.type = 3;
nO.x = parseInt(obj[i].shift());
nO.y = parseInt(obj[i].shift());
nO.w = parseInt(obj[i].shift());
nO.h = parseInt(obj[i].shift());
nO.count = parseInt(obj[i].shift());
nO.color = obj[i].shift();
break;
case '4':
nO.type = 4;
nO.x = parseInt(obj[i].shift());
nO.y = parseInt(obj[i].shift());
nO.w = parseInt(obj[i].shift());
nO.h = parseInt(obj[i].shift());
nO.count = parseInt(obj[i].shift());
nO.color = obj[i].shift();
nO.lastClickAt = 0;
break;
}
nObj.push(nO);
}
return nObj;
},
/**
* Returns an array as [objdata, offset]
* objdata is required to be further parsed with zM.parse.objData()
*/
objects: function(buffer, offset) {
var dat = new DataView(buffer);
var count = dat.getUint16(offset, true);
var objdata = [];
offset += 2;
for (var i = 0; i < count; ++i) {
var id = dat.getUint32(offset, true);
offset += 4;
var type = dat.getUint8(offset);
var objdat = id+'.';
++offset;
switch (type) {
case 0:
objdat += '0.';
objdat += \`\${dat.getUint16(offset, true)}.\`;
objdat += \`\${dat.getUint16(offset+2, true)}.\`;
objdat += \`\${dat.getUint8(offset+4)}.\`;
objdat += \`\${!!dat.getUint8(offset+5)}.\`;
offset += 5;
for (;1;) if (dat.getUint8(++offset) != 0) objdat += String.fromCharCode(dat.getUint8(offset));
else break;
++offset;
break;
case 1:
objdat += '1.';
objdat += \`\${dat.getUint16(offset, true)}.\`;
objdat += \`\${dat.getUint16(offset+2, true)}.\`;
objdat += \`\${dat.getUint16(offset+4, true)}.\`;
objdat += \`\${dat.getUint16(offset+6, true)}.\`;
var color = dat.getUint32(offset+8, true).toString(16);
for (; color.length < 6;) color = '0' + color;
objdat += '#' + color + '.';
offset += 12;
break;
case 2:
objdat += '2.';
objdat += \`\${dat.getUint16(offset, true)}.\`;
objdat += \`\${dat.getUint16(offset+2, true)}.\`;
objdat += \`\${dat.getUint16(offset+4, true)}.\`;
objdat += \`\${dat.getUint16(offset+6, true)}.\`;
objdat += \`\${!!dat.getUint8(offset+8)}.\`;
offset += 9;
break;
case 3:
objdat += '3.';
objdat += \`\${dat.getUint16(offset, true)}.\`;
objdat += \`\${dat.getUint16(offset+2, true)}.\`;
objdat += \`\${dat.getUint16(offset+4, true)}.\`;
objdat += \`\${dat.getUint16(offset+6, true)}.\`;
objdat += \`\${dat.getUint16(offset+8, true)}.\`;
var color = dat.getUint32(offset+10, true).toString(16);
for (; color.length < 6;) color = '0' + color;
objdat += '#' + color + '.';
offset += 14;
break;
case 4:
objdat += '4.';
objdat += \`\${dat.getUint16(offset, true)}.\`;
objdat += \`\${dat.getUint16(offset+2, true)}.\`;
objdat += \`\${dat.getUint16(offset+4, true)}.\`;
objdat += \`\${dat.getUint16(offset+6, true)}.\`;
objdat += \`\${dat.getUint16(offset+8, true)}.\`;
var color = dat.getUint32(offset+10, true).toString(16);
for (; color.length < 6;) color = '0' + color;
objdat += '#' + color + '.';
offset += 14;
break;
}
objdata.push(objdat);
}
return [objdata, offset];
}
}
zM.packet = {
/**
*
* @param {array} sockets Array of sockets to move
*/
moveSocket(sockets, x, y, bots) {
var buf = new ArrayBuffer(9),
dat = new DataView(buf);
dat.setUint8(0, 1);
dat.setUint16(1, x, true);
dat.setUint16(3, y, true);
dat.setUint32(5, -1, true);
sockets.forEach(X => typeof X.send === 'function' && X.send(buf));
bots.forEach(X => {
++X.packets.sentTotal;
++X.packets.sentPS;
setTimeout(()=>{--X.packets.sentPS},1000);
X.packets.lastSent = Date.now();
});
},
/**
*
* @param {array} sockets Array of sockets to click with
*/
clickSocket(sockets, x, y, bots) {
var buf = new ArrayBuffer(9),
dat = new DataView(buf);
dat.setUint8(0, 2);
dat.setUint16(1, x, true);
dat.setUint16(3, y, true);
dat.setUint32(5, -1, true);
sockets.forEach(X => typeof X.send === 'function' && X.send(buf));
bots.forEach(X => {
++X.packets.sentTotal;
++X.packets.sentPS;
setTimeout(()=>{--X.packets.sentPS},1000);
X.packets.lastSent = Date.now();
});
},
/**
*
* @param {array} sockets Array of sockets to draw with
*/
drawSocket(sockets, x, y, x2, y2, bots) {
var buf = new ArrayBuffer(9),
dat = new DataView(buf);
dat.setUint8(0, 3);
dat.setUint16(1, x, true);
dat.setUint16(3, y, true);
dat.setUint16(5, x2, true);
dat.setUint16(7, y2, true);
sockets.forEach(X => typeof X.send === 'function' && (X.send(buf)));
bots.forEach(X => {
++X.packets.sentTotal;
++X.packets.sentPS;
setTimeout(()=>{--X.packets.sentPS},1000);
X.packets.lastSent = Date.now();
});
}
}`,
/* zM Pathfinder */
`zM.dependenciesLoaded |= 0b100000;
var visit = [];
zM.dos = function(dx, dy, items, gridSpace) {
var gridX = 400/gridSpace,
gridY = 300/gridSpace;
var grid = [];
visit = [];
for (var i = 0; i < gridY; i++) {
grid[i] = [];
visit[i] = [];
for (var j = 0; j < gridX; j++) grid[i][j] = 0, visit[i][j] = 0;
}
items.forEach(function(d) {
if (d.type === 1) {
for (var i = 0; i < d.h; i+=gridSpace) {
for (var j = 0; j < d.w; j+=gridSpace) {
grid[(d.y+i)/gridSpace][(d.x+j)/gridSpace] = 3;
}
}
}
});
var bfs = [[dx,dy]],
bfs2 = [];
while (bfs.length) {
bfs.forEach(function(dat) {
var x = dat[0],
y = dat[1];
if (grid[y][x] == 3) return;
grid[y][x] = 3;
for (var X = x + 1; X < gridX && !(grid[y][X] & 1); X++) {
grid[y][X] |= 1;
if (!visit[y][X]) {
visit[y][X] = [x, y], bfs2.push([X, y]);
}
}
for (var X = x - 1; X >= 0 && !(grid[y][X] & 1); X--) {
grid[y][X] |= 1;
if (!visit[y][X]) {
visit[y][X] = [x, y], bfs2.push([X, y]);
}
}
for (var Y = y + 1; Y < gridY && !(grid[Y][x] & 2); Y++) {
grid[Y][x] |= 2;
if (!visit[Y][x]) {
visit[Y][x] = [x, y], bfs2.push([x, Y]);
}
}
for (var Y = y - 1; Y >= 0 && !(grid[Y][x] & 2); Y--) {
grid[Y][x] |= 2;
if (!visit[Y][x]) {
visit[Y][x] = [x, y], bfs2.push([x, Y]);
}
}
});
bfs = bfs2;
bfs2 = [];
}
}
zM.path = function(ox, oy, dx, dy, items, grid) {
var rdx = dx, rdy = dy;
ox /= grid;
oy /= grid;
dx /= grid;
dy /= grid;
ox |= 0;
oy |= 0;
dx |= 0;
dy |= 0;
var mov = [];
if (!(ox == dx && oy == dy)) {
zM.dos(ox,oy,items,grid);
var xy2 = [dx,dy];
while (visit[xy2[1]][xy2[0]]) {
mov.push(xy2);
xy2 = visit[xy2[1]][xy2[0]];
}
mov.reverse();
}
for (var i = 0; i < mov.length; ++i) {
mov[i][0] *= grid;
mov[i][0] += grid/2;
mov[i][1] *= grid;
mov[i][1] += grid/2;
}
mov.push([rdx, rdy]);
return mov;
}`
],
// ---
// add elements from functions below:
// ---
[
function(c) {
var temp = [D.createElement('link')];
temp[0].href = 'https://fonts.googleapis.com/css?family=Montserrat:100,200,300,400';
temp[0].rel = 'stylesheet';
head.appendChild(temp[0]);
temp[1] = D.createElement('link');
temp[1].href = 'https://fonts.googleapis.com/css?family=Nova+Flat&display=swap';
temp[1].rel = 'stylesheet';
head.appendChild(temp[1]);
},
function(c) { // news area (null fleet selected)
var temp = [D.createElement('div')];
temp[0].className = 'zM-news-outer';
temp[1] = D.createElement('div');
temp[1].className = 'zM-news-container';
temp[0].appendChild(temp[1]);
temp[2] = D.createElement('div');
temp[2].className = 'zM-news-page-top';
temp[1].appendChild(temp[2]);
temp[3] = D.createElement('div');
temp[3].className = 'zM-news-page-mid';
temp[1].appendChild(temp[3]);
temp[4] = D.createElement('div');
temp[4].className = 'zM-news-page-bottom';
temp[1].appendChild(temp[4]);
zM.el.newsOuter = temp[0];
zM.el.newsPageTop = temp[2];
zM.el.newsPageMid = temp[3];
zM.el.newsPageBottom = temp[4];
c.appendChild(temp[0]);
},
function(c) { // fleet prompt
var temp = [D.createElement('div')];
temp[0].className = 'zM-fleet-prompt-outer';
temp[1] = D.createElement('div');
temp[1].className = 'zM-fleet-prompt-container';
temp[0].appendChild(temp[1]);
temp[2] = D.createElement('div');
temp[2].className = 'zM-fleet-prompt-title';
temp[2].textContent = 'Create new fleet';
temp[1].appendChild(temp[2]);
temp[3] = D.createElement('div');
temp[3].className = 'zM-fleet-prompt-entry';
temp[1].appendChild(temp[3]);
temp[4] = D.createElement('div');
temp[4].className = 'zM-fleet-prompt-opt';
temp[4].textContent = 'Use premade IPs'
temp[3].appendChild(temp[4]);
temp[5] = D.createElement('input');
temp[5].type = 'checkbox';
temp[5].checked = true;
temp[5].addEventListener('change', () => {
if (temp[5].checked) {
temp[6].style.display = 'block';
temp[10].style.display = 'none';
temp[13].style.display = 'none';
temp[16].style.display = 'none';
if (temp[12].value + ':' + temp[15].value === `${ip}:2828`) temp[8].value = "0";
else if (temp[12].value + ':' + temp[15].value === 'kursors.io/ws:8080') temp[8].value = "1";
else if (temp[12].value + ':' + temp[15].value === 'localhost:9004') temp[8].value = "2";
} else {
temp[6].style.display = 'none';
temp[10].style.display = 'block';
temp[13].style.display = 'block';
temp[16].style.display = 'block';
// set input values
switch (temp[8].value) {
case "0": {
temp[12].value = __ip;
temp[15].value = '2828';
break;
}
case "1": {
temp[12].value = 'kursors.io/ws';
temp[15].value = '8080';
break;
}
case "2": {
temp[12].value = 'localhost';
temp[15].value = '9004';
break;
}
}
temp[18].checked = false;
}
})
temp[3].appendChild(temp[5]);
temp[6] = D.createElement('div');
temp[6].className = 'zM-fleet-prompt-entry';
temp[1].appendChild(temp[6]);
temp[7] = D.createElement('div');
temp[7].className = 'zM-fleet-prompt-opt';
temp[7].textContent = 'Select an IP to connect to:'
temp[6].appendChild(temp[7]);
// dropdown
temp[8] = D.createElement('select');
temp[8].style.outline = 'none';
temp[6].appendChild(temp[8]);
temp[9] = [D.createElement('option'), D.createElement('option'), D.createElement('option')];
temp[9][0].value = "0";
temp[9][0].textContent = `cursors.io ${__ip}:2828)`;
temp[9][1].value = "1";
temp[9][1].textContent = 'kursors.io (kursors.io/ws:8080)';
temp[9][2].value = "2";
temp[9][2].textContent = 'local server (localhost:9004)';
temp[9].forEach(X => temp[8].appendChild(X));
temp[10] = D.createElement('div');
temp[10].className = 'zM-fleet-prompt-entry';
temp[10].style.display = 'none';
temp[1].appendChild(temp[10]);
temp[11] = D.createElement('div');
temp[11].className = 'zM-fleet-prompt-opt';
temp[11].textContent = 'IP address:'
temp[10].appendChild(temp[11]);
temp[12] = D.createElement('input');
temp[12].type = 'text';
temp[12].style.outline = 'none';
temp[12].width = 200;
temp[10].appendChild(temp[12]);
temp[13] = D.createElement('div');
temp[13].className = 'zM-fleet-prompt-entry';
temp[13].style.display = 'none';
temp[1].appendChild(temp[13]);
temp[14] = D.createElement('div');
temp[14].className = 'zM-fleet-prompt-opt';
temp[14].textContent = 'Port:'
temp[13].appendChild(temp[14]);
temp[15] = D.createElement('input');
temp[15].type = 'text';
temp[15].style.outline = 'none';
temp[15].width = 200;
temp[13].appendChild(temp[15]);
temp[16] = D.createElement('div');
temp[16].className = 'zM-fleet-prompt-entry';
temp[16].style.display = 'none';
temp[1].appendChild(temp[16]);
temp[17] = D.createElement('div');
temp[17].className = 'zM-fleet-prompt-opt';
temp[17].textContent = 'Using IPv6:'
temp[16].appendChild(temp[17]);
temp[18] = D.createElement('input');
temp[18].type = 'checkbox';
temp[18].style.outline = 'none';
temp[16].appendChild(temp[18]);
// max bots
temp[19] = D.createElement('div');
temp[19].className = 'zM-fleet-prompt-entry';
temp[1].appendChild(temp[19]);
temp[20] = D.createElement('div');
temp[20].className = 'zM-fleet-prompt-opt';
temp[20].textContent = 'Maximum bots to this fleet:';
temp[19].appendChild(temp[20]);
temp[21] = D.createElement('input');
temp[21].type = 'number';
temp[19].appendChild(temp[21]);
temp[21].addEventListener('change', ev => {
var num = Math.min(100, Math.max(parseInt(temp[21].value), 0));
if (isNaN(num)) num = 3;
temp[21].value = num;
});
if (zM.origin === 'cursors') temp[21].value = 3;
else temp[21].value = 20;
// start bots
temp[22] = D.createElement('div');
temp[22].className = 'zM-fleet-prompt-entry';
temp[1].appendChild(temp[22]);
temp[23] = D.createElement('div');
temp[23].className = 'zM-fleet-prompt-opt';
temp[23].textContent = 'Start with # bots:';
temp[22].appendChild(temp[23]);
temp[24] = D.createElement('input');
temp[24].type = 'number';
temp[22].appendChild(temp[24]);
temp[24].addEventListener('change', ev => {
var num = Math.min(100, Math.max(parseInt(temp[24].value), 0));
if (isNaN(num)) num = 3;
temp[24].value = num;
});
if (zM.origin === 'cursors') temp[24].value = 3;
else temp[24].value = 20;
// zursor username
temp[25] = D.createElement('div');
temp[25].className = 'zM-fleet-prompt-entry';
temp[1].appendChild(temp[25]);
temp[26] = D.createElement('div');
temp[26].className = 'zM-fleet-prompt-opt';
temp[26].textContent = 'Fleet name (public):';
temp[25].appendChild(temp[26]);
temp[27] = D.createElement('input');
temp[27].type = 'text';
temp[25].appendChild(temp[27]);
// confirmation buttons
temp[28] = D.createElement('div');
temp[28].className = 'zM-fleet-prompt-create';
temp[28].textContent = 'Create fleet';
temp[1].appendChild(temp[28]);
temp[29] = D.createElement('div');
temp[29].className = 'zM-fleet-prompt-cancel';
temp[29].textContent = 'Cancel';
temp[1].appendChild(temp[29]);
temp[29].addEventListener('click', ev => {
temp[0].style.display = 'none';
if (isNaN(zM.fSel)) zM.el.newsOuter.style.display = 'block';
else zM.updateTabs();
});
temp[28].addEventListener('click', () => {
var ip, port, ipv6 = false;
if (!temp[5].checked) ip = temp[12].value, port = temp[15].value, ipv6 = temp[18].checked;
else {
switch (temp[8].value) {
case "0": ip = __ip; port = '2828'; break;
case "1": ip = 'kursors.io/ws'; port = '8080'; break;
default: ip = 'localhost'; port = '9004'; break;
}
}
var maxBots = parseInt(temp[21].value),
startBots = parseInt(temp[24].value);
var name = temp[27].value;
if (name.length === 0) name = 'Unnamed fleet';
zM.createFleet(ip, port, ipv6, maxBots, startBots, name);
});
// give temp to zM.el
zM.el.fleetPromptOuter = temp[0];
zM.el.fleetPromptContainer = temp[1];
c.appendChild(temp[0]);
},
function(c) { // fleet topbar
var temp = [D.createElement('div')];
temp[0].className = 'zM-fleet-topbar-outer';
c.appendChild(temp[0]);
temp[4] = D.createElement('div');
temp[4].className = 'zM-fleet-topbar-container';
temp[0].appendChild(temp[4]);
temp[1] = D.createElement('div');
temp[1].className = 'zM-fleet-topbar-add';
temp[4].appendChild(temp[1]);
temp[1].addEventListener('click', ev => {
zM.promptFleet();
});
temp[2] = D.createElement('img');
temp[2].src = zMIMG.add.uri;
temp[2].width = 45, temp[2].height = 35, temp[2].style.cssText = 'position:absolute;top:0px;left:0px;opacity:0.8;'
temp[1].appendChild(temp[2]);
temp[3] = D.createElement('div');
temp[3].className = 'zM-fleet-topbar-hint';
temp[3].textContent = 'Add fleet here to start playing';
temp[0].appendChild(temp[3]);
// give temp to zM.el
zM.el.fleetTopbarOuter = temp.shift();
zM.el.fleetTopbarContainer = temp.pop();
zM.el.fleetTopbarAdd = temp.shift();
zM.el.fleetTopbarAddImg = temp.shift();
zM.el.fleetTopbarHint = temp.shift();
},
function(c) {
var temp = document.createElement('canvas');
temp.className = 'zM-game';
temp.width = 800;
temp.height = 600;
c.appendChild(temp);
temp.addEventListener('mousemove', ev => {
zM.pos.mouseX = ev.offsetX;
zM.pos.mouseY = ev.offsetY;
});
temp.addEventListener('mousedown', ev => {
if (ev.shiftKey || ev.ctrlKey) zM.drawing = true;
else {
++zM.clickQueue;
}
});
temp.addEventListener('mouseup', ev => {
zM.drawing = false;
});
addEventListener('keydown', ev => {
if (isNaN(zM.fSel)) return;
console.log(ev.key);
switch (ev.key) {
// all possible keys that can be drawn
case 'A':
case 'a':case 'B':case 'b':case 'C':case 'c':
case 'D':case 'd':case 'E':case 'e':case 'F':
case 'f':case 'G':case 'g':case 'H':case 'h':
case 'I':case 'i':case 'J':case 'j':case 'K':
case 'k':case 'L':case 'l':case 'M':case 'm':
case 'N':case 'n':case 'O':case 'o':case 'P':
case 'p':case 'Q':case 'q':case 'R':case 'r':
case 'S':case 's':case 'T':case 't':case 'U':
case 'u':case 'V':case 'v':case 'W':case 'w':
case 'X':case 'x':case 'Y':case 'y':case 'Z':
case 'z':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':
case '0':case '!':case '@':case '#':case '$':
case '%':case '^':case '&':case '*':case '(':
case ')':case '`':case '~':case '-':case '_':
case '=':case '+':case '[':case ']':case '{':
case '}':case '\\':case '|':case ';':case ':':
case '\'':case '"':case '.':case ',':case '<':
case '>':case '/':case '?':
case '¡':
case '¢':case '£':case '¤':case '¥':case '¦':
case '§':case '¨':case '©':case 'ª':case '«':
case '¬':case '®':case '¯':case '°':case '±':
case '²':case '³':case '´':case 'µ':case '¶':
case '·':case '¸':case '¹':case 'º':case '»':
case '¼':case '½':case '¾':case '¿':
case 'À':
case 'Á':case 'Â':case 'Ã':case 'Ä':case 'Å':
case 'Æ':case 'Ç':case 'È':case 'É':case 'Ê':
case 'Ë':case 'Ì':case 'Í':case 'Î':case 'Ï':
case 'Ð':case 'Ñ':case 'Ò':case 'Ó':case 'Ô':
case 'Õ':case 'Ö':case 'Ø':case 'Ù':case 'Ú':
case 'Û':case 'Ü':case 'Ý':case 'Þ':case 'ß':
case 'à':case 'á':case 'â':case 'ã':case 'ä':
case 'å':case 'æ':case 'ç':case 'è':case 'é':
case 'ê':case 'ë':case 'ì':case 'í':case 'î':
case 'ï':case 'ð':case 'ñ':case 'ò':case 'ó':
case 'ô':case 'õ':case 'ö':case 'ø':case 'ù':
case 'ú':case 'û':case 'ü':case 'ý':case 'þ':
case 'ÿ':
//zM.fleet[zM.fSel].
break;
case 'F1':
ev.preventDefault();
zM.movement ^= 1;
break;
case 'F2':
var f = zM.fleet[zM.fSel];
ev.preventDefault();
var i = 0;
for (; i < f.bots.length; ++i) {
if (f.bots[i]) if (!f.bots[i].deployed && !f.bots[i].helping && i !== f.cSel && f.bots[i].level === f.bots[f.cSel].level) break;
}
if (f.bots[i]) {
var b = f.bots[i];
b.deployed = true;
}
break;
case 'F3':
var f = zM.fleet[zM.fSel];
ev.preventDefault();
var i = 0;
for (; i < f.bots.length; ++i) {
if (f.bots[i]) if (f.bots[i].deployed && f.bots[i].level === f.bots[f.cSel].level) break;
}
if (i < f.bots.length) {
var b = f.bots[i];
var s = f.bots[f.cSel];
b.deployed = false;
if (zM.returnAfterUndeployed) {
var moves = zM.path(b.realX, b.realY, s.realX, s.realY, b.obj, b.grid);
moves.forEach(Y => {
zM.packet.moveSocket([b.socket], Y[0], Y[1], [b]);
});
}
}
break;
case 'F4':
ev.preventDefault();
var f = zM.fleet[zM.fSel];
if (f.isHelping) break;
f.isHelping = true;
var helpers = [];
for (var i = 0; i < f.bots.length; ++i) {
console.log(!f.bots[i].helping && !f.bots[i].deployed && i !== f.cSel && f.bots[i].level === f.bots[f.cSel].level);
console.log('1 ' + !f.bots[i].helping);
console.log('2 ' + !f.bots[i].deployed);
console.log('3 ' + (i !== f.cSel));
console.log('4 ' + (f.bots[i].level === f.bots[f.cSel].level));
if (f.bots[i]) if (!f.bots[i].helping && !f.bots[i].deployed && i !== f.cSel && f.bots[i].level === f.bots[f.cSel].level) helpers.push(f.bots[i]);
}
f.helpers = helpers;
break;
case 'F5':
ev.preventDefault();
for (var i = 0; i < zM.fleet[zM.fSel].helpers.length; ++i) {
zM.fleet[zM.fSel].helpers[i].helping = false;
}
zM.fleet[zM.fSel].helpers = [];
zM.fleet[zM.fSel].isHelping = false;
break;
}
});
zM.el.game = temp;
zM.reqLoad();
zM.reqDo();
},
function(c) {
var temp = [D.createElement('div')];
temp[0].className = 'zM-info-outer';
c.appendChild(temp[0]);
temp[1] = D.createElement('div');
temp[1].className = 'zM-info-ver';
temp[1].textContent = 'v' + zM.version;
temp[0].appendChild(temp[1]);
temp[2] = D.createElement('div');
temp[2].className = 'zM-info-clog-button-outer';
temp[0].appendChild(temp[2]);
temp[3] = D.createElement('div');
temp[3].className = 'zM-info-clog-button';
temp[3].textContent = 'view changelog';
temp[2].appendChild(temp[3]);
temp[4] = D.createElement('div');
temp[4].className = 'zM-clog-outer';
c.appendChild(temp[4]);
temp[5] = D.createElement('div');
temp[5].className = 'zM-clog-container';
temp[4].appendChild(temp[5]);
temp[6] = D.createElement('div');
temp[6].className = 'zM-clog-close';
temp[4].appendChild(temp[6]);
temp[7] = D.createElement('img');
temp[7].src = zMIMG.close.uri;
temp[6].appendChild(temp[7]);
zM.el.clogOuter = temp[4];
zM.el.clogContainer = temp[5];
temp[2].addEventListener('click', ev => {
zM.el.clogOuter.style.display = 'block';
});
temp[6].addEventListener('click', ev => {
zM.el.clogOuter.style.display = 'none';
});
var out = [];
for (var i = 0; i < zM.clog.length; ++i) {
var temp = D.createElement('div');
if (zM.clog[i].type === 'title') {
temp.className = 'zM-clog-title';
temp.innerHTML = zM.clog[i].msg;
out.push(temp);
} else {
temp.className = 'zM-clog-desc';
temp.innerHTML = zM.clog[i].msg;
out.push(temp);
}
}
out.forEach(X => zM.el.clogContainer.appendChild(X));
}
]
);
})();