Advertisement
Guest User

Untitled

a guest
Dec 6th, 2019
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. let indicateMyCells = true;
  2. (function(wHandle, wjQuery) {
  3.     var CONNECTION_URL = "127.0.0.1:443", // Default Connection
  4.         SKIN_URL = "./skins/"; // Skin Directory
  5.  
  6.     wHandle.setserver = function(arg) {
  7.         if (arg != CONNECTION_URL) {
  8.             CONNECTION_URL = arg;
  9.             showConnecting();
  10.         }
  11.     };
  12.  
  13.     var touchX, touchY,
  14.         touchable = 'createTouch' in document,
  15.         touches = [];
  16.  
  17.     var leftTouchID = -1,
  18.         leftTouchPos = new Vector2(0, 0),
  19.         leftTouchStartPos = new Vector2(0, 0),
  20.         leftVector = new Vector2(0, 0);
  21.  
  22.     var useHttps = "https:" == wHandle.location.protocol;
  23.  
  24.     function gameLoop() {
  25.         ma = true;
  26.         document.getElementById("canvas").focus();
  27.         var isTyping = false;
  28.         var chattxt;
  29.         mainCanvas = nCanvas = document.getElementById("canvas");
  30.         ctx = mainCanvas.getContext("2d");
  31.  
  32.         mainCanvas.onmousemove = function(event) {
  33.             rawMouseX = event.clientX;
  34.             rawMouseY = event.clientY;
  35.             mouseCoordinateChange()
  36.         };
  37.  
  38.         if (touchable) {
  39.             mainCanvas.addEventListener('touchstart', onTouchStart, false);
  40.             mainCanvas.addEventListener('touchmove', onTouchMove, false);
  41.             mainCanvas.addEventListener('touchend', onTouchEnd, false);
  42.         }
  43.  
  44.         mainCanvas.onmouseup = function() {};
  45.         if (/firefox/i.test(navigator.userAgent)) {
  46.             document.addEventListener("DOMMouseScroll", handleWheel, false);
  47.         } else {
  48.             document.body.onmousewheel = handleWheel;
  49.         }
  50.  
  51.         mainCanvas.onfocus = function() {
  52.             isTyping = false;
  53.         };
  54.  
  55.         document.getElementById("chat_textbox").onblur = function() {
  56.             isTyping = false;
  57.         };
  58.  
  59.  
  60.         document.getElementById("chat_textbox").onfocus = function() {
  61.             isTyping = true;
  62.         };
  63.  
  64.         var spacePressed = false,
  65.             qPressed = false,
  66.             ePressed = false,
  67.             rPressed = false,
  68.             tPressed = false,
  69.             pPressed = false,
  70.             wPressed = false;
  71.         wHandle.onkeydown = function(event) {
  72.             switch (event.keyCode) {
  73.                 case 13: // enter
  74.                     if (isTyping || hideChat) {
  75.                         isTyping = false;
  76.                         document.getElementById("chat_textbox").blur();
  77.                         chattxt = document.getElementById("chat_textbox").value;
  78.                         if (chattxt.length > 0) sendChat(chattxt);
  79.                         document.getElementById("chat_textbox").value = "";
  80.                     } else {
  81.                         if (!hasOverlay) {
  82.                             document.getElementById("chat_textbox").focus();
  83.                             isTyping = true;
  84.                         }
  85.                     }
  86.                     break;
  87.                 case 32: // space
  88.                     if ((!spacePressed) && (!isTyping)) {
  89.                         sendMouseMove();
  90.                         sendUint8(17);
  91.                         spacePressed = true;
  92.                     }
  93.                     break;
  94.                 case 87: // W
  95.                     if ((!wPressed) && (!isTyping)) {
  96.                         sendMouseMove();
  97.                         sendUint8(21);
  98.                         wPressed = true;
  99.                     }
  100.                     break;
  101.                 case 81: // Q
  102.                     if ((!qPressed) && (!isTyping)) {
  103.                         sendUint8(18);
  104.                         qPressed = true;
  105.                     }
  106.                     break;
  107.                 case 69: // E
  108.                     if (!ePressed && (!isTyping)) {
  109.                         sendMouseMove();
  110.                         sendUint8(22);
  111.                     }
  112.                     break;
  113.                 case 82: // R
  114.                     if (!rPressed && (!isTyping)) {
  115.                         sendMouseMove();
  116.                         sendUint8(23);
  117.                         if (!rMacro) rPressed = true;
  118.                     }
  119.                     break;
  120.                 case 84: // T
  121.                     if (!tPressed && (!isTyping)) {
  122.                         sendMouseMove();
  123.                         sendUint8(24);
  124.                         tPressed = true;
  125.                     }
  126.                     break;
  127.                 case 80: // P
  128.                     if (!pPressed && (!isTyping)) {
  129.                         sendMouseMove();
  130.                         sendUint8(25);
  131.                         pPressed = true;
  132.                     }
  133.                     break;
  134.                 case 27: // esc
  135.                     showOverlays(true);
  136.                     break;
  137.             }
  138.         };
  139.         wHandle.onkeyup = function(event) {
  140.             switch (event.keyCode) {
  141.                 case 32: // space
  142.                     spacePressed = false;
  143.                     break;
  144.                 case 87: // W
  145.                     wPressed = false;
  146.                     break;
  147.                 case 81: // Q
  148.                     if (qPressed) {
  149.                         sendUint8(19);
  150.                         qPressed = false;
  151.                     }
  152.                     break;
  153.                 case 69:
  154.                     ePressed = false;
  155.                     break;
  156.                 case 82:
  157.                     rPressed = false;
  158.                     break;
  159.                 case 84:
  160.                     tPressed = false;
  161.                     break;
  162.                 case 80:
  163.                     pPressed = false;
  164.                     break;
  165.             }
  166.         };
  167.         wHandle.onblur = function() {
  168.             sendUint8(19);
  169.             wPressed = spacePressed = qPressed = ePressed = rPressed = tPressed = pPressed = false
  170.         };
  171.  
  172.         wHandle.onresize = canvasResize;
  173.         canvasResize();
  174.         if (wHandle.requestAnimationFrame) {
  175.             wHandle.requestAnimationFrame(redrawGameScene);
  176.         } else {
  177.             setInterval(drawGameScene, 1E3 / 60);
  178.         }
  179.         setInterval(sendMouseMove, 40);
  180.  
  181.         null == ws && showConnecting();
  182.         wjQuery("#overlays").show();
  183.     }
  184.  
  185.     function onTouchStart(e) {
  186.         for (var i = 0; i < e.changedTouches.length; i++) {
  187.             var touch = e.changedTouches[i];
  188.             if ((leftTouchID < 0) && (touch.clientX < canvasWidth / 2)) {
  189.                 leftTouchID = touch.identifier;
  190.                 leftTouchStartPos.reset(touch.clientX, touch.clientY);
  191.                 leftTouchPos.copyFrom(leftTouchStartPos);
  192.                 leftVector.reset(0, 0);
  193.             }
  194.  
  195.             var size = ~~(canvasWidth / 7);
  196.             if ((touch.clientX > canvasWidth - size) && (touch.clientY > canvasHeight - size)) {
  197.                 sendMouseMove();
  198.                 sendUint8(17); // split
  199.             }
  200.  
  201.             if ((touch.clientX > canvasWidth - size) && (touch.clientY > canvasHeight - 2 * size - 10) && (touch.clientY < canvasHeight - size - 10)) {
  202.                 sendMouseMove();
  203.                 sendUint8(21); // eject
  204.             }
  205.         }
  206.         touches = e.touches;
  207.     }
  208.  
  209.     function onTouchMove(e) {
  210.         e.preventDefault();
  211.         for (var i = 0; i < e.changedTouches.length; i++) {
  212.             var touch = e.changedTouches[i];
  213.             if (leftTouchID == touch.identifier) {
  214.                 leftTouchPos.reset(touch.clientX, touch.clientY);
  215.                 leftVector.copyFrom(leftTouchPos);
  216.                 leftVector.minusEq(leftTouchStartPos);
  217.                 rawMouseX = leftVector.x * 3 + canvasWidth / 2;
  218.                 rawMouseY = leftVector.y * 3 + canvasHeight / 2;
  219.                 mouseCoordinateChange();
  220.                 sendMouseMove();
  221.             }
  222.         }
  223.         touches = e.touches;
  224.     }
  225.  
  226.     function onTouchEnd(e) {
  227.         touches = e.touches;
  228.         for (var i = 0; i < e.changedTouches.length; i++) {
  229.             var touch = e.changedTouches[i];
  230.             if (leftTouchID == touch.identifier) {
  231.                 leftTouchID = -1;
  232.                 leftVector.reset(0, 0);
  233.                 break;
  234.             }
  235.         }
  236.     }
  237.  
  238.     function handleWheel(event) {
  239.         zoom *= Math.pow(.9, event.wheelDelta / -120 || event.detail || 0);
  240.         1 > zoom && (zoom = 1);
  241.         zoom > 4 / viewZoom && (zoom = 4 / viewZoom)
  242.     }
  243.  
  244.     function buildQTree() {
  245.         if (.4 > viewZoom) qTree = null;
  246.         else {
  247.             var a = Number.POSITIVE_INFINITY,
  248.                 b = Number.POSITIVE_INFINITY,
  249.                 c = Number.NEGATIVE_INFINITY,
  250.                 d = Number.NEGATIVE_INFINITY,
  251.                 e = 0;
  252.             for (var i = 0; i < nodelist.length; i++) {
  253.                 var node = nodelist[i];
  254.                 if (node.shouldRender() && !node.prepareData && 20 < node.size * viewZoom) {
  255.                     e = Math.max(node.size, e);
  256.                     a = Math.min(node.x, a);
  257.                     b = Math.min(node.y, b);
  258.                     c = Math.max(node.x, c);
  259.                     d = Math.max(node.y, d);
  260.                 }
  261.             }
  262.             qTree = Quad.init({
  263.                 minX: a - (e + 100),
  264.                 minY: b - (e + 100),
  265.                 maxX: c + (e + 100),
  266.                 maxY: d + (e + 100),
  267.                 maxChildren: 2,
  268.                 maxDepth: 4
  269.             });
  270.             for (i = 0; i < nodelist.length; i++) {
  271.                 node = nodelist[i];
  272.                 if (node.shouldRender() && !(20 >= node.size * viewZoom)) {
  273.                     for (a = 0; a < node.points.length; ++a) {
  274.                         b = node.points[a].x;
  275.                         c = node.points[a].y;
  276.                         b < nodeX - canvasWidth / 2 / viewZoom || c < nodeY - canvasHeight / 2 / viewZoom || b > nodeX + canvasWidth / 2 / viewZoom || c > nodeY + canvasHeight / 2 / viewZoom || qTree.insert(node.points[a]);
  277.                     }
  278.                 }
  279.             }
  280.         }
  281.     }
  282.  
  283.     function mouseCoordinateChange() {
  284.         X = (rawMouseX - canvasWidth / 2) / viewZoom + nodeX;
  285.         Y = (rawMouseY - canvasHeight / 2) / viewZoom + nodeY
  286.     }
  287.  
  288.     function hideOverlays() {
  289.         hasOverlay = false;
  290.         wjQuery("#overlays").hide();
  291.     }
  292.  
  293.     function showOverlays(arg) {
  294.         hasOverlay = true;
  295.         userNickName = null;
  296.         wjQuery("#overlays").fadeIn(arg ? 200 : 3E3);
  297.     }
  298.  
  299.     function showConnecting() {
  300.         if (ma) {
  301.             wjQuery("#connecting").show();
  302.             wsConnect((useHttps ? "wss://" : "ws://") + CONNECTION_URL)
  303.         }
  304.     }
  305.  
  306.     function wsConnect(wsUrl) {
  307.         if (ws) {
  308.             ws.onopen = null;
  309.             ws.onmessage = null;
  310.             ws.onclose = null;
  311.             try {
  312.                 ws.close()
  313.             } catch (b) {}
  314.             ws = null
  315.         }
  316.         var c = CONNECTION_URL;
  317.         wsUrl = (useHttps ? "wss://" : "ws://") + c;
  318.         nodesOnScreen = [];
  319.         playerCells = [];
  320.         nodes = {};
  321.         nodelist = [];
  322.         Cells = [];
  323.         leaderBoard = [];
  324.         mainCanvas = teamScores = null;
  325.         userScore = 0;
  326.         log.info("Connecting to " + wsUrl + "..");
  327.         ws = new WebSocket(wsUrl);
  328.         ws.binaryType = "arraybuffer";
  329.         ws.onopen = onWsOpen;
  330.         ws.onmessage = onWsMessage;
  331.         ws.onclose = onWsClose;
  332.     }
  333.  
  334.     function prepareData(a) {
  335.         return new DataView(new ArrayBuffer(a))
  336.     }
  337.  
  338.     function wsSend(a) {
  339.         ws.send(a.buffer)
  340.     }
  341.  
  342.     function onWsOpen() {
  343.         var msg;
  344.         delay = 500;
  345.         wjQuery("#connecting").hide();
  346.         msg = prepareData(5);
  347.         msg.setUint8(0, 254);
  348.         msg.setUint32(1, 5, true); // Protocol 5
  349.         wsSend(msg);
  350.         msg = prepareData(5);
  351.         msg.setUint8(0, 255);
  352.         msg.setUint32(1, 0, true);
  353.         wsSend(msg);
  354.         sendNickName();
  355.         log.info("Connection successful!")
  356.     }
  357.  
  358.     function onWsClose() {
  359.         setTimeout(showConnecting, delay);
  360.         delay *= 1.5;
  361.     }
  362.  
  363.     function onWsMessage(msg) {
  364.         handleWsMessage(new DataView(msg.data));
  365.     }
  366.  
  367.     function handleWsMessage(msg) {
  368.         function getString() {
  369.             var text = '',
  370.                 char;
  371.             while ((char = msg.getUint16(offset, true)) != 0) {
  372.                 offset += 2;
  373.                 text += String.fromCharCode(char);
  374.             }
  375.             offset += 2;
  376.             return text;
  377.         }
  378.  
  379.         var offset = 0,
  380.             setCustomLB = false;
  381.         240 == msg.getUint8(offset) && (offset += 5);
  382.         switch (msg.getUint8(offset++)) {
  383.             case 16: // update nodes
  384.                 updateNodes(msg, offset);
  385.                 break;
  386.             case 17: // update position
  387.                 posX = msg.getFloat32(offset, true);
  388.                 offset += 4;
  389.                 posY = msg.getFloat32(offset, true);
  390.                 offset += 4;
  391.                 posSize = msg.getFloat32(offset, true);
  392.                 offset += 4;
  393.                 break;
  394.             case 20: // clear nodes
  395.                 playerCells = [];
  396.                 nodesOnScreen = [];
  397.                 break;
  398.             case 21: // draw line
  399.                 lineX = msg.getInt16(offset, true);
  400.                 offset += 2;
  401.                 lineY = msg.getInt16(offset, true);
  402.                 offset += 2;
  403.                 if (!drawLine) {
  404.                     drawLine = true;
  405.                     drawLineX = lineX;
  406.                     drawLineY = lineY;
  407.                 }
  408.                 break;
  409.             case 32: // add node
  410.                 nodesOnScreen.push(msg.getUint32(offset, true));
  411.                 offset += 4;
  412.                 break;
  413.             case 48: // update leaderboard (custom text)
  414.                 setCustomLB = true;
  415.                 noRanking = true;
  416.                 break;
  417.             case 49: // update leaderboard (ffa)
  418.                 if (!setCustomLB) {
  419.                     noRanking = false;
  420.                 }
  421.                 teamScores = null;
  422.                 var LBplayerNum = msg.getUint32(offset, true);
  423.                 offset += 4;
  424.                 leaderBoard = [];
  425.                 for (i = 0; i < LBplayerNum; ++i) {
  426.                     var nodeId = msg.getUint32(offset, true);
  427.                     offset += 4;
  428.                     leaderBoard.push({
  429.                         id: nodeId,
  430.                         name: getString()
  431.                     })
  432.                 }
  433.                 drawLeaderBoard();
  434.                 break;
  435.             case 50: // update leaderboard (teams)
  436.                 teamScores = [];
  437.                 var LBteamNum = msg.getUint32(offset, true);
  438.                 offset += 4;
  439.                 for (var i = 0; i < LBteamNum; ++i) {
  440.                     teamScores.push(msg.getFloat32(offset, true));
  441.                     offset += 4;
  442.                 }
  443.                 drawLeaderBoard();
  444.                 break;
  445.             case 64: // set border
  446.                 leftPos = msg.getFloat64(offset, true);
  447.                 offset += 8;
  448.                 topPos = msg.getFloat64(offset, true);
  449.                 offset += 8;
  450.                 rightPos = msg.getFloat64(offset, true);
  451.                 offset += 8;
  452.                 bottomPos = msg.getFloat64(offset, true);
  453.                 offset += 8;
  454.                 posX = (rightPos + leftPos) / 2;
  455.                 posY = (bottomPos + topPos) / 2;
  456.                 posSize = 1;
  457.                 if (0 == playerCells.length) {
  458.                     nodeX = posX;
  459.                     nodeY = posY;
  460.                     viewZoom = posSize;
  461.                 }
  462.                 break;
  463.             case 99:
  464.                 addChat(msg, offset);
  465.                 break;
  466.         }
  467.     }
  468.  
  469.     function addChat(view, offset) {
  470.         function getString() {
  471.             var text = '',
  472.                 char;
  473.             while ((char = view.getUint16(offset, true)) != 0) {
  474.                 offset += 2;
  475.                 text += String.fromCharCode(char);
  476.             }
  477.             offset += 2;
  478.             return text;
  479.         }
  480.  
  481.         var flags = view.getUint8(offset++);
  482.        
  483.         if (flags & 0x80) {
  484.             // SERVER Message
  485.         }
  486.  
  487.         if (flags & 0x40) {
  488.             // ADMIN Message
  489.         }
  490.  
  491.         if (flags & 0x20) {
  492.             // MOD Message
  493.         }
  494.  
  495.         var r = view.getUint8(offset++),
  496.             g = view.getUint8(offset++),
  497.             b = view.getUint8(offset++),
  498.             color = (r << 16 | g << 8 | b).toString(16);
  499.         while (color.length < 6) {
  500.             color = '0' + color;
  501.         }
  502.         color = '#' + color;
  503.         chatBoard.push({
  504.             "name": getString(),
  505.             "color": color,
  506.             "message": getString(),
  507.             "time": Date.now()
  508.         });
  509.         drawChatBoard();
  510.     }
  511.  
  512.     function drawChatBoard() {
  513.         if (hideChat)  {
  514.             chatCanvas = null;
  515.             return;
  516.         }
  517.         chatCanvas = document.createElement("canvas");
  518.         var ctx = chatCanvas.getContext("2d");
  519.         var scaleFactor = Math.min(Math.max(canvasWidth / 1200, 0.75), 1); //scale factor = 0.75 to 1
  520.         chatCanvas.width = 1E3 * scaleFactor;
  521.         chatCanvas.height = 550 * scaleFactor;
  522.         ctx.scale(scaleFactor, scaleFactor);
  523.         var nowtime = Date.now();
  524.         var lasttime = 0;
  525.         if (chatBoard.length >= 1)
  526.             lasttime = chatBoard[chatBoard.length - 1].time;
  527.         else return;
  528.         var deltat = nowtime - lasttime;
  529.         ctx.globalAlpha = 0.8 * Math.exp(-deltat / 25000);
  530.  
  531.         var len = chatBoard.length;
  532.         var from = len - 15;
  533.         if (from < 0) from = 0;
  534.         for (var i = 0; i < (len - from); i++) {
  535.             var chatName = new UText(18, chatBoard[i + from].color);
  536.             chatName.setValue(chatBoard[i + from].name);
  537.             var width = chatName.getWidth();
  538.             var a = chatName.render();
  539.             ctx.drawImage(a, 15, chatCanvas.height / scaleFactor - 24 * (len - i - from));
  540.  
  541.             var chatText = new UText(18, '#666666');
  542.             chatText.setValue(':' + chatBoard[i + from].message);
  543.             a = chatText.render();
  544.             ctx.drawImage(a, 15 + width * 1.8, chatCanvas.height / scaleFactor - 24 * (len - from - i));
  545.         }
  546.     }
  547.  
  548.  
  549.     function updateNodes(view, offset) {
  550.         timestamp = +new Date;
  551.         var code = Math.random();
  552.         ua = false;
  553.         var queueLength = view.getUint16(offset, true);
  554.         offset += 2;
  555.  
  556.         for (i = 0; i < queueLength; ++i) {
  557.             var killer = nodes[view.getUint32(offset, true)],
  558.                 killedNode = nodes[view.getUint32(offset + 4, true)];
  559.             offset += 8;
  560.             if (killer && killedNode) {
  561.                 killedNode.destroy();
  562.                 killedNode.ox = killedNode.x;
  563.                 killedNode.oy = killedNode.y;
  564.                 killedNode.oSize = killedNode.size;
  565.                 killedNode.nx = killer.x;
  566.                 killedNode.ny = killer.y;
  567.                 killedNode.nSize = killedNode.size;
  568.                 killedNode.updateTime = timestamp;
  569.             }
  570.         }
  571.  
  572.         for (var i = 0;;) {
  573.             var nodeid = view.getUint32(offset, true);
  574.             offset += 4;
  575.             if (0 == nodeid) break;
  576.             ++i;
  577.  
  578.             var size, posY, posX = view.getInt32(offset, true);
  579.             offset += 4;
  580.             posY = view.getInt32(offset, true);
  581.             offset += 4;
  582.             size = view.getInt16(offset, true);
  583.             offset += 2;
  584.  
  585.             for (var r = view.getUint8(offset++), g = view.getUint8(offset++), b = view.getUint8(offset++),
  586.                     color = (r << 16 | g << 8 | b).toString(16); 6 > color.length;) color = "0" + color;
  587.             var colorstr = "#" + color,
  588.                 flags = view.getUint8(offset++),
  589.                 flagVirus = !!(flags & 0x01),
  590.                 flagEjected = !!(flags & 0x20),
  591.                 flagAgitated = !!(flags & 0x10),
  592.                 _skin = "";
  593.  
  594.             flags & 2 && (offset += 4);
  595.  
  596.             if (flags & 4) {
  597.                 for (;;) { // skin name
  598.                     t = view.getUint8(offset, true) & 0x7F;
  599.                     offset += 1;
  600.                     if (0 == t) break;
  601.                     _skin += String.fromCharCode(t);
  602.                 }
  603.             }
  604.  
  605.             for (var char, name = "";;) { // nick name
  606.                 char = view.getUint16(offset, true);
  607.                 offset += 2;
  608.                 if (0 == char) break;
  609.                 name += String.fromCharCode(char);
  610.             }
  611.  
  612.             var node = null;
  613.             if (nodes.hasOwnProperty(nodeid)) {
  614.                 node = nodes[nodeid];
  615.                 node.updatePos();
  616.                 node.ox = node.x;
  617.                 node.oy = node.y;
  618.                 node.oSize = node.size;
  619.                 node.color = colorstr;
  620.             } else {
  621.                 node = new Cell(nodeid, posX, posY, size, colorstr, name, _skin);
  622.                 nodelist.push(node);
  623.                 nodes[nodeid] = node;
  624.                 node.ka = posX;
  625.                 node.la = posY;
  626.             }
  627.             node.isVirus = flagVirus;
  628.             node.isEjected = flagEjected;
  629.             node.isAgitated = flagAgitated;
  630.             node.nx = posX;
  631.             node.ny = posY;
  632.             node.setSize(size);
  633.             node.updateCode = code;
  634.             node.updateTime = timestamp;
  635.             node.flag = flags;
  636.             name && node.setName(name);
  637.             if (-1 != nodesOnScreen.indexOf(nodeid) && -1 == playerCells.indexOf(node)) {
  638.                 document.getElementById("overlays").style.display = "none";
  639.                 playerCells.push(node);
  640.                 if (1 == playerCells.length) {
  641.                     nodeX = node.x;
  642.                     nodeY = node.y;
  643.                 }
  644.             }
  645.         }
  646.         queueLength = view.getUint32(offset, true);
  647.         offset += 4;
  648.         for (i = 0; i < queueLength; i++) {
  649.             var nodeId = view.getUint32(offset, true);
  650.             offset += 4;
  651.             node = nodes[nodeId];
  652.             null != node && node.destroy();
  653.         }
  654.         ua && 0 == playerCells.length && showOverlays(false)
  655.     }
  656.  
  657.     function sendMouseMove() {
  658.         var msg;
  659.         if (wsIsOpen()) {
  660.             msg = rawMouseX - canvasWidth / 2;
  661.             var b = rawMouseY - canvasHeight / 2;
  662.             if (64 <= msg * msg + b * b && !(.01 > Math.abs(oldX - X) && .01 > Math.abs(oldY - Y))) {
  663.                 oldX = X;
  664.                 oldY = Y;
  665.                 msg = prepareData(21);
  666.                 msg.setUint8(0, 16);
  667.                 msg.setFloat64(1, X, true);
  668.                 msg.setFloat64(9, Y, true);
  669.                 msg.setUint32(17, 0, true);
  670.                 wsSend(msg);
  671.             }
  672.         }
  673.     }
  674.  
  675.     function sendNickName() {
  676.         if (wsIsOpen() && null != userNickName) {
  677.             var msg = prepareData(1 + 2 * userNickName.length);
  678.             msg.setUint8(0, 0);
  679.             for (var i = 0; i < userNickName.length; ++i) msg.setUint16(1 + 2 * i, userNickName.charCodeAt(i), true);
  680.             wsSend(msg)
  681.         }
  682.     }
  683.  
  684.     function sendChat(str) {
  685.         if (wsIsOpen() && (str.length < 200) && (str.length > 0) && !hideChat) {
  686.             var msg = prepareData(2 + 2 * str.length);
  687.             var offset = 0;
  688.             msg.setUint8(offset++, 99);
  689.             msg.setUint8(offset++, 0); // flags (0 for now)
  690.             for (var i = 0; i < str.length; ++i) {
  691.                 msg.setUint16(offset, str.charCodeAt(i), true);
  692.                 offset += 2;
  693.             }
  694.  
  695.             wsSend(msg);
  696.         }
  697.     }
  698.  
  699.     function wsIsOpen() {
  700.         return null != ws && ws.readyState == ws.OPEN
  701.     }
  702.  
  703.     function sendUint8(a) {
  704.         if (wsIsOpen()) {
  705.             var msg = prepareData(1);
  706.             msg.setUint8(0, a);
  707.             wsSend(msg)
  708.         }
  709.     }
  710.  
  711.     function redrawGameScene() {
  712.         drawGameScene();
  713.         wHandle.requestAnimationFrame(redrawGameScene)
  714.     }
  715.  
  716.     function canvasResize() {
  717.         window.scrollTo(0, 0);
  718.         canvasWidth = wHandle.innerWidth;
  719.         canvasHeight = wHandle.innerHeight;
  720.         nCanvas.width = canvasWidth;
  721.         nCanvas.height = canvasHeight;
  722.         drawGameScene()
  723.     }
  724.  
  725.     function viewRange() {
  726.         var ratio;
  727.         ratio = Math.max(canvasHeight / 1080, canvasWidth / 1920);
  728.         return ratio * zoom;
  729.     }
  730.  
  731.     function calcViewZoom() {
  732.         if (0 != playerCells.length) {
  733.             for (var newViewZoom = 0, i = 0; i < playerCells.length; i++) newViewZoom += playerCells[i].size;
  734.             newViewZoom = Math.pow(Math.min(64 / newViewZoom, 1), .4) * viewRange();
  735.             viewZoom = (9 * viewZoom + newViewZoom) / 10;
  736.         }
  737.     }
  738.  
  739.     function drawGameScene() {
  740.         var a, oldtime = Date.now();
  741.         ++cb;
  742.         timestamp = oldtime;
  743.         if (0 < playerCells.length) {
  744.             calcViewZoom();
  745.             var c = a = 0;
  746.             for (var d = 0; d < playerCells.length; d++) {
  747.                 playerCells[d].updatePos();
  748.                 a += playerCells[d].x / playerCells.length;
  749.                 c += playerCells[d].y / playerCells.length;
  750.             }
  751.             posX = a;
  752.             posY = c;
  753.             posSize = viewZoom;
  754.             nodeX = (nodeX + a) / 2;
  755.             nodeY = (nodeY + c) / 2
  756.         } else {
  757.             nodeX = (29 * nodeX + posX) / 30;
  758.             nodeY = (29 * nodeY + posY) / 30;
  759.             viewZoom = (9 * viewZoom + posSize * viewRange()) / 10;
  760.         }
  761.         buildQTree();
  762.         mouseCoordinateChange();
  763.         xa || ctx.clearRect(0, 0, canvasWidth, canvasHeight);
  764.         if (xa) {
  765.             if (showDarkTheme) {
  766.                 ctx.fillStyle = '#111111';
  767.                 ctx.globalAlpha = .05;
  768.                 ctx.fillRect(0, 0, canvasWidth, canvasHeight);
  769.                 ctx.globalAlpha = 1;
  770.             } else {
  771.                 ctx.fillStyle = '#F2FBFF';
  772.                 ctx.globalAlpha = .05;
  773.                 ctx.fillRect(0, 0, canvasWidth, canvasHeight);
  774.                 ctx.globalAlpha = 1;
  775.             }
  776.         } else {
  777.             drawGrid();
  778.         }
  779.         nodelist.sort(function(a, b) {
  780.             return a.size === b.size ? a.id - b.id : a.size - b.size
  781.         });
  782.         ctx.save();
  783.         ctx.translate(canvasWidth / 2, canvasHeight / 2);
  784.         ctx.scale(viewZoom, viewZoom);
  785.         ctx.translate(-nodeX, -nodeY);
  786.         for (d = 0; d < Cells.length; d++) Cells[d].drawOneCell(ctx);
  787.  
  788.         for (d = 0; d < nodelist.length; d++) nodelist[d].drawOneCell(ctx);
  789.         if (drawLine) {
  790.             drawLineX = (3 * drawLineX + lineX) /
  791.                 4;
  792.             drawLineY = (3 * drawLineY + lineY) / 4;
  793.             ctx.save();
  794.             ctx.strokeStyle = "#FFAAAA";
  795.             ctx.lineWidth = 10;
  796.             ctx.lineCap = "round";
  797.             ctx.lineJoin = "round";
  798.             ctx.globalAlpha = .5;
  799.             ctx.beginPath();
  800.             for (d = 0; d < playerCells.length; d++) {
  801.                 ctx.moveTo(playerCells[d].x, playerCells[d].y);
  802.                 ctx.lineTo(drawLineX, drawLineY);
  803.             }
  804.             ctx.stroke();
  805.             ctx.restore()
  806.         }
  807.         ctx.restore();
  808.         lbCanvas && lbCanvas.width && ctx.drawImage(lbCanvas, canvasWidth - lbCanvas.width - 10, 10); // draw Leader Board
  809.         if (chatCanvas != null) ctx.drawImage(chatCanvas, 0, canvasHeight - chatCanvas.height - 50); // draw Leader Board
  810.  
  811.         userScore = Math.max(userScore, calcUserScore());
  812.         if (0 != userScore) {
  813.             if (null == scoreText) {
  814.                 scoreText = new UText(24, '#FFFFFF');
  815.             }
  816.             scoreText.setValue('Score: ' + ~~(userScore / 100));
  817.             c = scoreText.render();
  818.             a = c.width;
  819.             ctx.globalAlpha = .2;
  820.             ctx.fillStyle = '#000000';
  821.             ctx.fillRect(10, 10, a + 10, 34); //canvasHeight - 10 - 24 - 10
  822.             ctx.globalAlpha = 1;
  823.             ctx.drawImage(c, 15, 15); //canvasHeight - 10 - 24 - 5
  824.         }
  825.         drawSplitIcon(ctx);
  826.  
  827.         drawTouch(ctx);
  828.         //drawChatBoard();
  829.         var deltatime = Date.now() - oldtime;
  830.         deltatime > 1E3 / 60 ? z -= .01 : deltatime < 1E3 / 65 && (z += .01);
  831.         .4 > z && (z = .4);
  832.         1 < z && (z = 1)
  833.     }
  834.  
  835.     function drawTouch(ctx) {
  836.         ctx.save();
  837.         if (touchable) {
  838.             for (var i = 0; i < touches.length; i++) {
  839.                 var touch = touches[i];
  840.                 if (touch.identifier == leftTouchID) {
  841.                     ctx.beginPath();
  842.                     ctx.strokeStyle = "#0096ff";
  843.                     ctx.lineWidth = 6;
  844.                     ctx.arc(leftTouchStartPos.x, leftTouchStartPos.y, 40, 0, Math.PI * 2, true);
  845.                     ctx.stroke();
  846.                     ctx.beginPath();
  847.                     ctx.strokeStyle = "#0096ff";
  848.                     ctx.lineWidth = 2;
  849.                     ctx.arc(leftTouchStartPos.x, leftTouchStartPos.y, 60, 0, Math.PI * 2, true);
  850.                     ctx.stroke();
  851.                     ctx.beginPath();
  852.                     ctx.strokeStyle = "#0096ff";
  853.                     ctx.arc(leftTouchPos.x, leftTouchPos.y, 40, 0, Math.PI * 2, true);
  854.                     ctx.stroke();
  855.                 } else {
  856.                     ctx.beginPath();
  857.                     ctx.beginPath();
  858.                     ctx.strokeStyle = "#0096ff";
  859.                     ctx.lineWidth = "6";
  860.                     ctx.arc(touch.clientX, touch.clientY, 40, 0, Math.PI * 2, true);
  861.                     ctx.stroke();
  862.                 }
  863.             }
  864.         }
  865.         ctx.restore();
  866.     }
  867.  
  868.     function drawGrid() {
  869.         ctx.fillStyle = showDarkTheme ? "#111111" : "#F2FBFF";
  870.         ctx.fillRect(0, 0, canvasWidth, canvasHeight);
  871.         ctx.save();
  872.         ctx.strokeStyle = showDarkTheme ? "#AAAAAA" : "#000000";
  873.         ctx.globalAlpha = .2;
  874.         ctx.scale(viewZoom, viewZoom);
  875.         var a = canvasWidth / viewZoom,
  876.             b = canvasHeight / viewZoom;
  877.         for (var c = -.5 + (-nodeX + a / 2) % 50; c < a; c += 50) {
  878.             ctx.moveTo(c, 0);
  879.             ctx.lineTo(c, b);
  880.         }
  881.         ctx.stroke();
  882.         ctx.beginPath();
  883.         for (c = -.5 + (-nodeY + b / 2) % 50; c < b; c += 50) {
  884.             ctx.moveTo(0, c);
  885.             ctx.lineTo(a, c);
  886.         }
  887.         ctx.stroke()
  888.         ctx.restore()
  889.     }
  890.  
  891.     function drawSplitIcon(ctx) {
  892.         if (isTouchStart && splitIcon.width) {
  893.             var size = ~~(canvasWidth / 7);
  894.             ctx.drawImage(splitIcon, canvasWidth - size, canvasHeight - size, size, size);
  895.         }
  896.  
  897.         if (isTouchStart && splitIcon.width) {
  898.             var size = ~~(canvasWidth / 7);
  899.             ctx.drawImage(ejectIcon, canvasWidth - size, canvasHeight - 2 * size - 10, size, size);
  900.         }
  901.     }
  902.  
  903.     function calcUserScore() {
  904.         for (var score = 0, i = 0; i < playerCells.length; i++) score += playerCells[i].nSize * playerCells[i].nSize;
  905.         return score
  906.     }
  907.  
  908.     function drawLeaderBoard() {
  909.         lbCanvas = null;
  910.         var drawTeam = null != teamScores;
  911.         if (drawTeam || 0 != leaderBoard.length)
  912.             if (drawTeam || showName) {
  913.                 lbCanvas = document.createElement("canvas");
  914.                 var ctx = lbCanvas.getContext("2d"),
  915.                     boardLength = 60;
  916.                 boardLength = !drawTeam ? boardLength + 24 * leaderBoard.length : boardLength + 180;
  917.                 var scaleFactor = Math.min(0.22 * canvasHeight, Math.min(200, .3 * canvasWidth)) * 0.005;
  918.                 lbCanvas.width = 200 * scaleFactor;
  919.                 lbCanvas.height = boardLength * scaleFactor;
  920.  
  921.                 ctx.scale(scaleFactor, scaleFactor);
  922.                 ctx.globalAlpha = .4;
  923.                 ctx.fillStyle = "#000000";
  924.                 ctx.fillRect(0, 0, 200, boardLength);
  925.  
  926.                 ctx.globalAlpha = 1;
  927.                 ctx.fillStyle = "#FFFFFF";
  928.                 var c = "Leaderboard";
  929.                 ctx.font = "30px Ubuntu";
  930.                 ctx.fillText(c, 100 - ctx.measureText(c).width * 0.5, 40);
  931.                 var b, l;
  932.                 if (!drawTeam) {
  933.                     for (ctx.font = "20px Ubuntu", b = 0, l = leaderBoard.length; b < l; ++b) {
  934.                         c = leaderBoard[b].name || "An unnamed cell";
  935.                         if (!showName) {
  936.                             (c = "An unnamed cell");
  937.                         }
  938.                         var me = -1 != nodesOnScreen.indexOf(leaderBoard[b].id);
  939.                         if (me) playerCells[0].name && (c = playerCells[0].name);
  940.                         me ? ctx.fillStyle = "#FFAAAA" : ctx.fillStyle = "#FFFFFF";
  941.                         if (!noRanking) c = b + 1 + ". " + c;
  942.                         var start = (ctx.measureText(c).width > 200) ? 2 : 100 - ctx.measureText(c).width * 0.5;
  943.                         ctx.fillText(c, start, 70 + 24 * b);
  944.                     }
  945.                 } else {
  946.                     for (b = c = 0; b < teamScores.length; ++b) {
  947.                         var d = c + teamScores[b] * Math.PI * 2;
  948.                         ctx.fillStyle = teamColor[b + 1];
  949.                         ctx.beginPath();
  950.                         ctx.moveTo(100, 140);
  951.                         ctx.arc(100, 140, 80, c, d, false);
  952.                         ctx.fill();
  953.                         c = d
  954.                     }
  955.                 }
  956.             }
  957.     }
  958.  
  959.     function Cell(uid, ux, uy, usize, ucolor, uname, a) {
  960.         this.id = uid;
  961.         this.ox = this.x = ux;
  962.         this.oy = this.y = uy;
  963.         this.oSize = this.size = usize;
  964.         this.color = ucolor;
  965.         this.points = [];
  966.         this.pointsAcc = [];
  967.         this.createPoints();
  968.         this.setName(uname)
  969.         this._skin = a;
  970.     }
  971.  
  972.     function UText(usize, ucolor, ustroke, ustrokecolor) {
  973.         usize && (this._size = usize);
  974.         ucolor && (this._color = ucolor);
  975.         this._stroke = !!ustroke;
  976.         ustrokecolor && (this._strokeColor = ustrokecolor)
  977.     }
  978.  
  979.  
  980.     var localProtocol = wHandle.location.protocol,
  981.         localProtocolHttps = "https:" == localProtocol;
  982.     var nCanvas, ctx, mainCanvas, lbCanvas, chatCanvas, canvasWidth, canvasHeight, qTree = null,
  983.         ws = null,
  984.         nodeX = 0,
  985.         nodeY = 0,
  986.         nodesOnScreen = [],
  987.         playerCells = [],
  988.         nodes = {},
  989.         nodelist = [],
  990.         Cells = [],
  991.         leaderBoard = [],
  992.         chatBoard = [],
  993.         rawMouseX = 0,
  994.         rawMouseY = 0,
  995.         X = -1,
  996.         Y = -1,
  997.         cb = 0,
  998.         timestamp = 0,
  999.         userNickName = null,
  1000.         leftPos = 0,
  1001.         topPos = 0,
  1002.         rightPos = 1E4,
  1003.         bottomPos = 1E4,
  1004.         viewZoom = 1,
  1005.         showSkin = true,
  1006.         showName = true,
  1007.         showColor = false,
  1008.         ua = false,
  1009.         userScore = 0,
  1010.         showDarkTheme = false,
  1011.         showMass = false,
  1012.         hideChat = false,
  1013.         smoothRender = .4,
  1014.         posX = nodeX = ~~((leftPos + rightPos) / 2),
  1015.         posY = nodeY = ~~((topPos + bottomPos) / 2),
  1016.         posSize = 1,
  1017.         teamScores = null,
  1018.         ma = false,
  1019.         hasOverlay = true,
  1020.         drawLine = false,
  1021.         lineX = 0,
  1022.         lineY = 0,
  1023.         drawLineX = 0,
  1024.         drawLineY = 0,
  1025.         Ra = 0,
  1026.         teamColor = ["#333333", "#FF3333", "#33FF33", "#3333FF"],
  1027.         xa = false,
  1028.         zoom = 1,
  1029.         isTouchStart = "ontouchstart" in wHandle && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
  1030.         splitIcon = new Image,
  1031.         ejectIcon = new Image,
  1032.         noRanking = false;
  1033.     splitIcon.src = "assets/img/split.png";
  1034.     ejectIcon.src = "assets/img/feed.png";
  1035.     var wCanvas = document.createElement("canvas");
  1036.     var playerStat = null;
  1037.     wHandle.isSpectating = false;
  1038.     wHandle.setNick = function(arg) {
  1039.         hideOverlays();
  1040.         userNickName = arg;
  1041.         sendNickName();
  1042.         userScore = 0
  1043.     };
  1044.     wHandle.setSkins = function(arg) {
  1045.         showSkin = arg
  1046.     };
  1047.     wHandle.setNames = function(arg) {
  1048.         showName = arg
  1049.     };
  1050.     wHandle.setDarkTheme = function(arg) {
  1051.         showDarkTheme = arg
  1052.     };
  1053.     wHandle.setColors = function(arg) {
  1054.         showColor = arg
  1055.     };
  1056.     wHandle.setShowMass = function(arg) {
  1057.         showMass = arg
  1058.     };
  1059.     wHandle.setSmooth = function(arg) {
  1060.         smoothRender = arg ? 2 : .4
  1061.     };
  1062.     wHandle.setChatHide = function(arg) {
  1063.         hideChat = arg;
  1064.         if (hideChat) {
  1065.             wjQuery('#chat_textbox').hide();
  1066.         } else {
  1067.             wjQuery('#chat_textbox').show();
  1068.         }
  1069.     }
  1070.     wHandle.spectate = function() {
  1071.         userNickName = null;
  1072.         wHandle.isSpectating = true;
  1073.         sendUint8(1);
  1074.         hideOverlays()
  1075.     };
  1076.     wHandle.setAcid = function(arg) {
  1077.         xa = arg
  1078.     };
  1079.     wHandle.openSkinsList = function(arg) {
  1080.         if ($('#inPageModalTitle').text() != "Skins") {
  1081.             $.get('include/gallery.php').then(function(data) {
  1082.                 $('#inPageModalTitle').text("Skins");
  1083.                 $('#inPageModalBody').html(data);
  1084.             });
  1085.         }
  1086.     };
  1087.  
  1088.     if (null != wHandle.localStorage) {
  1089.         wjQuery(window).load(function() {
  1090.             wjQuery(".save").each(function() {
  1091.                 var id = $(this).data("box-id");
  1092.                 var value = wHandle.localStorage.getItem("checkbox-" + id);
  1093.                 if (value && value == "true" && 0 != id) {
  1094.                     $(this).prop("checked", "true");
  1095.                     $(this).trigger("change");
  1096.                 } else if (id == 0 && value != null) {
  1097.                     $(this).val(value);
  1098.                 }
  1099.             });
  1100.             wjQuery(".save").change(function() {
  1101.                 var id = $(this).data('box-id');
  1102.                 var value = (id == 0) ? $(this).val() : $(this).prop('checked');
  1103.                 wHandle.localStorage.setItem("checkbox-" + id, value);
  1104.             });
  1105.         });
  1106.         if (null == wHandle.localStorage.AB8) {
  1107.             wHandle.localStorage.AB8 = ~~(100 * Math.random());
  1108.         }
  1109.     }
  1110.  
  1111.     setTimeout(function() {}, 3E5);
  1112.     var T = {
  1113.         ZW: "EU-London"
  1114.     };
  1115.     wHandle.connect = wsConnect;
  1116.  
  1117.     var data = {
  1118.         "action": "test"
  1119.     };
  1120.     wjQuery.ajax({
  1121.         type: "POST",
  1122.         dataType: "json",
  1123.         url: "checkdir.php",
  1124.         data: data,
  1125.         success: function(data) {
  1126.             response = JSON.parse(data["names"]);
  1127.             for (var i = 0; i < response.length; i++) {
  1128.                 if (-1 == knownNameDict.indexOf(response[i])) {
  1129.                     knownNameDict.push(response[i]);
  1130.                 }
  1131.             }
  1132.         }
  1133.     });
  1134.  
  1135.     var delay = 500,
  1136.         oldX = -1,
  1137.         oldY = -1,
  1138.         Canvas = null,
  1139.         z = 1,
  1140.         scoreText = null,
  1141.         skins = {},
  1142.         knownNameDict = "".split(";"),
  1143.         knownNameDict_noDisp = [],
  1144.         ib = ["_canvas'blob"];
  1145.     Cell.prototype = {
  1146.         id: 0,
  1147.         points: null,
  1148.         pointsAcc: null,
  1149.         name: null,
  1150.         nameCache: null,
  1151.         sizeCache: null,
  1152.         x: 0,
  1153.         y: 0,
  1154.         size: 0,
  1155.         ox: 0,
  1156.         oy: 0,
  1157.         oSize: 0,
  1158.         nx: 0,
  1159.         ny: 0,
  1160.         nSize: 0,
  1161.         flag: 0,
  1162.         updateTime: 0,
  1163.         updateCode: 0,
  1164.         drawTime: 0,
  1165.         destroyed: false,
  1166.         isVirus: false,
  1167.         isEjected: false,
  1168.         isAgitated: false,
  1169.         wasSimpleDrawing: true,
  1170.         destroy: function() {
  1171.             var tmp;
  1172.             for (tmp = 0, len = nodelist.length; tmp < len; tmp++)
  1173.                 if (nodelist[tmp] === this) {
  1174.                     nodelist.splice(tmp, 1);
  1175.                     break
  1176.                 }
  1177.             delete nodes[this.id];
  1178.             tmp = playerCells.indexOf(this);
  1179.             if (-1 != tmp) {
  1180.                 ua = true;
  1181.                 playerCells.splice(tmp, 1);
  1182.             }
  1183.             tmp = nodesOnScreen.indexOf(this.id);
  1184.             if (-1 != tmp) nodesOnScreen.splice(tmp, 1);
  1185.             this.destroyed = true;
  1186.             Cells.push(this)
  1187.         },
  1188.         getNameSize: function() {
  1189.             return Math.max(~~(.3 * this.size), 24)
  1190.         },
  1191.         setName: function(a) {
  1192.             this.name = a;
  1193.             if (null == this.nameCache) {
  1194.                 this.nameCache = new UText(this.getNameSize(), "#FFFFFF", true, "#000000");
  1195.                 this.nameCache.setValue(this.name);
  1196.             } else {
  1197.                 this.nameCache.setSize(this.getNameSize());
  1198.                 this.nameCache.setValue(this.name);
  1199.             }
  1200.         },
  1201.         setSize: function(a) {
  1202.             this.nSize = a;
  1203.             var m = ~~(this.size * this.size * 0.01);
  1204.             if (null === this.sizeCache)
  1205.                 this.sizeCache = new UText(this.getNameSize() * 0.5, "#FFFFFF", true, "#000000");
  1206.             else this.sizeCache.setSize(this.getNameSize() * 0.5);
  1207.         },
  1208.         createPoints: function() {
  1209.             for (var samplenum = this.getNumPoints(); this.points.length > samplenum;) {
  1210.                 var rand = ~~(Math.random() * this.points.length);
  1211.                 this.points.splice(rand, 1);
  1212.                 this.pointsAcc.splice(rand, 1)
  1213.             }
  1214.             if (0 == this.points.length && 0 < samplenum) {
  1215.                 this.points.push({
  1216.                     ref: this,
  1217.                     size: this.size,
  1218.                     x: this.x,
  1219.                     y: this.y
  1220.                 });
  1221.                 this.pointsAcc.push(Math.random() - .5);
  1222.             }
  1223.             while (this.points.length < samplenum) {
  1224.                 var rand2 = ~~(Math.random() * this.points.length),
  1225.                     point = this.points[rand2];
  1226.                 this.points.splice(rand2, 0, {
  1227.                     ref: this,
  1228.                     size: point.size,
  1229.                     x: point.x,
  1230.                     y: point.y
  1231.                 });
  1232.                 this.pointsAcc.splice(rand2, 0, this.pointsAcc[rand2])
  1233.             }
  1234.         },
  1235.         getNumPoints: function() {
  1236.             if (0 == this.id) return 16;
  1237.             var a = 10;
  1238.             if (20 > this.size) a = 0;
  1239.             if (this.isVirus) a = 30;
  1240.             var b = this.size;
  1241.             if (!this.isVirus)(b *= viewZoom);
  1242.             b *= z;
  1243.             if (this.flag & 32)(b *= .25);
  1244.             return ~~Math.max(b, a);
  1245.         },
  1246.         movePoints: function() {
  1247.             this.createPoints();
  1248.             for (var points = this.points, pointsacc = this.pointsAcc, numpoints = points.length, i = 0; i < numpoints; ++i) {
  1249.                 var pos1 = pointsacc[(i - 1 + numpoints) % numpoints],
  1250.                     pos2 = pointsacc[(i + 1) % numpoints];
  1251.                 pointsacc[i] += (Math.random() - .5) * (this.isAgitated ? 3 : 1);
  1252.                 pointsacc[i] *= .7;
  1253.                 10 < pointsacc[i] && (pointsacc[i] = 10); -
  1254.                 10 > pointsacc[i] && (pointsacc[i] = -10);
  1255.                 pointsacc[i] = (pos1 + pos2 + 8 * pointsacc[i]) / 10
  1256.             }
  1257.             for (var ref = this, isvirus = this.isVirus ? 0 : (this.id / 1E3 + timestamp / 1E4) % (2 * Math.PI), j = 0; j < numpoints; ++j) {
  1258.                 var f = points[j].size,
  1259.                     e = points[(j - 1 + numpoints) % numpoints].size,
  1260.                     m = points[(j + 1) % numpoints].size;
  1261.                 if (15 < this.size && null != qTree && 20 < this.size * viewZoom && 0 != this.id) {
  1262.                     var l = false,
  1263.                         n = points[j].x,
  1264.                         q = points[j].y;
  1265.                     qTree.retrieve2(n - 5, q - 5, 10, 10, function(a) {
  1266.                         if (a.ref != ref && 25 > (n - a.x) * (n - a.x) + (q - a.y) * (q - a.y)) {
  1267.                             l = true;
  1268.                         }
  1269.                     });
  1270.                     if (!l && points[j].x < leftPos || points[j].y < topPos || points[j].x > rightPos || points[j].y > bottomPos) {
  1271.                         l = true;
  1272.                     }
  1273.                     if (l) {
  1274.                         if (0 < pointsacc[j]) {
  1275.                             (pointsacc[j] = 0);
  1276.                         }
  1277.                         pointsacc[j] -= 1;
  1278.                     }
  1279.                 }
  1280.                 f += pointsacc[j];
  1281.                 0 > f && (f = 0);
  1282.                 f = this.isAgitated ? (19 * f + this.size) / 20 : (12 * f + this.size) / 13;
  1283.                 points[j].size = (e + m + 8 * f) / 10;
  1284.                 e = 2 * Math.PI / numpoints;
  1285.                 m = this.points[j].size;
  1286.                 this.isVirus && 0 == j % 2 && (m += 5);
  1287.                 points[j].x = this.x + Math.cos(e * j + isvirus) * m;
  1288.                 points[j].y = this.y + Math.sin(e * j + isvirus) * m
  1289.             }
  1290.         },
  1291.         updatePos: function() {
  1292.             if (0 == this.id) return 1;
  1293.             var a;
  1294.             a = (timestamp - this.updateTime) / 120;
  1295.             a = 0 > a ? 0 : 1 < a ? 1 : a;
  1296.             var b = 0 > a ? 0 : 1 < a ? 1 : a;
  1297.             this.getNameSize();
  1298.             if (this.destroyed && 1 <= b) {
  1299.                 var c = Cells.indexOf(this); -
  1300.                 1 != c && Cells.splice(c, 1)
  1301.             }
  1302.             this.x = a * (this.nx - this.ox) + this.ox;
  1303.             this.y = a * (this.ny - this.oy) + this.oy;
  1304.             this.size = b * (this.nSize - this.oSize) + this.oSize;
  1305.             return b;
  1306.         },
  1307.         shouldRender: function() {
  1308.             if (0 == this.id) {
  1309.                 return true
  1310.             } else {
  1311.                 return !(this.x + this.size + 40 < nodeX - canvasWidth / 2 / viewZoom || this.y + this.size + 40 < nodeY - canvasHeight / 2 / viewZoom || this.x - this.size - 40 > nodeX + canvasWidth / 2 / viewZoom || this.y - this.size - 40 > nodeY + canvasHeight / 2 / viewZoom);
  1312.             }
  1313.         },
  1314.         getStrokeColor: function() {
  1315.             var r = (~~(parseInt(this.color.substr(1, 2), 16) * 0.9)).toString(16),
  1316.                 g = (~~(parseInt(this.color.substr(3, 2), 16) * 0.9)).toString(16),
  1317.                 b = (~~(parseInt(this.color.substr(5, 2), 16) * 0.9)).toString(16);
  1318.             if (r.length == 1) r = "0" + r;
  1319.             if (g.length == 1) g = "0" + g;
  1320.             if (b.length == 1) b = "0" + b;
  1321.             return "#" + r + g + b;
  1322.         },
  1323.         drawOneCell: function(ctx) {
  1324.             if (this.shouldRender()) {
  1325.                 var b = (0 != this.id && !this.isVirus && !this.isAgitated && smoothRender > viewZoom);
  1326.                 if (10 > this.getNumPoints()) b = true;
  1327.                 if (this.wasSimpleDrawing && !b)
  1328.                     for (var c = 0; c < this.points.length; c++) this.points[c].size = this.size;
  1329.                 var bigPointSize = this.size;
  1330.                 if(!this.wasSimpleDrawing) {
  1331.                     for (var c = 0; c < this.points.length; c++) bigPointSize = Math.max(this.points[c].size, bigPointSize);
  1332.                 }
  1333.                 this.wasSimpleDrawing = b;
  1334.                 ctx.save();
  1335.                 this.drawTime = timestamp;
  1336.                 c = this.updatePos();
  1337.                 this.destroyed && (ctx.globalAlpha *= 1 - c);
  1338.                 ctx.lineWidth = 10;
  1339.                 ctx.lineCap = "round";
  1340.                 ctx.lineJoin = this.isVirus ? "miter" : "round";
  1341.                 if (indicateMyCells.value && -1 != q.indexOf(this)) {
  1342.                     var myCell = myCells[this.id];
  1343.                     ctx.beginPath();
  1344.                     ctx.arc(this.x, this.y, this.size + 5 + 6, 0, 2 * Math.PI, false);
  1345.                     ctx.closePath();
  1346.                     ctx.lineWidth = 4;
  1347.                     ctx.stroke();
  1348.                     ctx.beginPath();
  1349.                     ctx.arc(this.x, this.y, this.size + 5 + 4, 0, 2 * Math.PI, false);
  1350.                     ctx.closePath();
  1351.                     ctx.strokeStyle = myCell.controlId == currentControlId ? 'rgb(240,236,0)' : 'rgb(185, 185, 185)';
  1352.                     ctx.lineWidth = 2;
  1353.                     ctx.stroke();
  1354.                     ctx.lineWidth = 10;
  1355.                 }
  1356.                 if (showColor) {
  1357.                     ctx.fillStyle = "#FFFFFF";
  1358.                     ctx.strokeStyle = "#AAAAAA";
  1359.                 } else {
  1360.                     ctx.fillStyle = this.color;
  1361.                     if (b) ctx.strokeStyle = this.getStrokeColor();
  1362.                     else ctx.strokeStyle = this.color;
  1363.                 }
  1364.                 ctx.beginPath();
  1365.                 if (b) {
  1366.                     var lw = this.size * 0.03;
  1367.                     ctx.lineWidth = lw;
  1368.                     ctx.arc(this.x, this.y, this.size - lw * 0.5 + 5, 0, 2 * Math.PI, false);
  1369.                     ctx.stroke();
  1370.                 } else {
  1371.                     this.movePoints();
  1372.                     ctx.beginPath();
  1373.                     var d = this.getNumPoints();
  1374.                     ctx.moveTo(this.points[0].x, this.points[0].y);
  1375.                     for (c = 1; c <= d; ++c) {
  1376.                         var e = c % d;
  1377.                         ctx.lineTo(this.points[e].x, this.points[e].y); //Draw circle of cell
  1378.                     }
  1379.                 }
  1380.                 ctx.closePath();
  1381.                 var skinName = this.name.toLowerCase();
  1382.  
  1383.                 // Load Premium skin if we have one set
  1384.                 if (typeof this._skin != 'undefined' && this._skin != '') {
  1385.                     if (this._skin[0] == '%') {
  1386.                         skinName = this._skin.substring(1);
  1387.                     }
  1388.                 }
  1389.  
  1390.                 if (showSkin && skinName != '' && -1 != knownNameDict.indexOf(skinName)) {
  1391.                     if (!skins.hasOwnProperty(skinName)) {
  1392.                         skins[skinName] = new Image;
  1393.                         skins[skinName].src = SKIN_URL + skinName + '.png';
  1394.                     }
  1395.                     if (0 != skins[skinName].width && skins[skinName].complete) {
  1396.                         c = skins[skinName];
  1397.                     } else {
  1398.                         c = null;
  1399.                     }
  1400.                 } else {
  1401.                     c = null;
  1402.                 }
  1403.                 b || ctx.stroke();
  1404.                 ctx.fill(); //Draw cell content
  1405.                 if (c) {
  1406.                     ctx.save();
  1407.                     ctx.clip();
  1408.                     //Draw skin
  1409.                     ctx.drawImage(c, this.x - bigPointSize, this.y - bigPointSize, 2 * bigPointSize, 2 * bigPointSize);
  1410.                     ctx.restore();
  1411.                 }
  1412.                 if ((showColor || 15 < this.size) && !b) {
  1413.                     ctx.strokeStyle = '#000000';
  1414.                     ctx.globalAlpha *= .1;
  1415.                     ctx.stroke();
  1416.                 }
  1417.                 ctx.globalAlpha = 1;
  1418.                 c = -1 != playerCells.indexOf(this);
  1419.                 var ncache;
  1420.                 //draw name
  1421.                 if (0 != this.id) {
  1422.                     var x = ~~this.x,
  1423.                         y = ~~this.y,
  1424.                         nz = this.getNameSize(),
  1425.                         ratio = Math.ceil(10 * viewZoom) * 0.1,
  1426.                         ratD = 1 / ratio;
  1427.                     if ((showName || c) && this.name && this.nameCache && (null == e || -1 == knownNameDict_noDisp.indexOf(skinName))) {
  1428.                         ncache = this.nameCache;
  1429.                         ncache.setValue(this.name);
  1430.                         ncache.setSize(nz);
  1431.                         ncache.setScale(ratio);
  1432.                         var rnchache = ncache.render(),
  1433.                             m = ~~(rnchache.width * ratD),
  1434.                             h = ~~(rnchache.height * ratD);
  1435.                         ctx.drawImage(rnchache, x - ~~(m * 0.5), y - ~~(h * 0.5), m, h);
  1436.                         b += rnchache.height * 0.5 * ratio + 4;
  1437.                     }
  1438.  
  1439.                     //draw mass
  1440.                     if (showMass && (c || 0 == playerCells.length && (!this.isVirus || this.isAgitated) && 20 < this.size)) {
  1441.                         var m = ~~(this.size * this.size * 0.01);
  1442.                         c = this.sizeCache;
  1443.                         c.setValue(m);
  1444.                         c.setScale(ratio);
  1445.                         e = c.render();
  1446.                         m = ~~(e.width * ratD);
  1447.                         h = ~~(e.height * ratD);
  1448.                         var g = this.name ? y + ~~(h * 0.7) : y - ~~(h * 0.5);
  1449.                         ctx.drawImage(e, x - ~~(m * 0.5), g, m, h);
  1450.                     }
  1451.                 }
  1452.                 ctx.restore();
  1453.             }
  1454.         }
  1455.     };
  1456.     UText.prototype = {
  1457.         _value: "",
  1458.         _color: "#000000",
  1459.         _stroke: false,
  1460.         _strokeColor: "#000000",
  1461.         _size: 16,
  1462.         _canvas: null,
  1463.         _ctx: null,
  1464.         _dirty: false,
  1465.         _scale: 1,
  1466.         setSize: function(a) {
  1467.             if (this._size != a) {
  1468.                 this._size = a;
  1469.                 this._dirty = true;
  1470.             }
  1471.         },
  1472.         setScale: function(a) {
  1473.             if (this._scale != a) {
  1474.                 this._scale = a;
  1475.                 this._dirty = true;
  1476.             }
  1477.         },
  1478.         setStrokeColor: function(a) {
  1479.             if (this._strokeColor != a) {
  1480.                 this._strokeColor = a;
  1481.                 this._dirty = true;
  1482.             }
  1483.         },
  1484.         setValue: function(a) {
  1485.             if (a != this._value) {
  1486.                 this._value = a;
  1487.                 this._dirty = true;
  1488.             }
  1489.         },
  1490.         render: function() {
  1491.             if (null == this._canvas) {
  1492.                 this._canvas = document.createElement("canvas");
  1493.                 this._ctx = this._canvas.getContext("2d");
  1494.             }
  1495.             if (this._dirty) {
  1496.                 this._dirty = false;
  1497.                 var canvas = this._canvas,
  1498.                     ctx = this._ctx,
  1499.                     value = this._value,
  1500.                     scale = this._scale,
  1501.                     fontsize = this._size,
  1502.                     font = fontsize + 'px Ubuntu';
  1503.                 ctx.font = font;
  1504.                 var h = ~~(.2 * fontsize),
  1505.                     wd = fontsize * 0.1;
  1506.                 var h2 = h * 0.5;
  1507.                 canvas.width = ctx.measureText(value).width * scale + 3;
  1508.                 canvas.height = (fontsize + h) * scale;
  1509.                 ctx.font = font;
  1510.                 ctx.globalAlpha = 1;
  1511.                 ctx.lineWidth = wd;
  1512.                 ctx.strokeStyle = this._strokeColor;
  1513.                 ctx.fillStyle = this._color;
  1514.                 ctx.scale(scale, scale);
  1515.                 this._stroke && ctx.strokeText(value, 0, fontsize - h2);
  1516.                 ctx.fillText(value, 0, fontsize - h2);
  1517.             }
  1518.             return this._canvas
  1519.         },
  1520.         getWidth: function() {
  1521.             return (ctx.measureText(this._value).width + 6);
  1522.         }
  1523.     };
  1524.     Date.now || (Date.now = function() {
  1525.         return (new Date).getTime()
  1526.     });
  1527.     var Quad = {
  1528.         init: function(args) {
  1529.             function Node(x, y, w, h, depth) {
  1530.                 this.x = x;
  1531.                 this.y = y;
  1532.                 this.w = w;
  1533.                 this.h = h;
  1534.                 this.depth = depth;
  1535.                 this.items = [];
  1536.                 this.nodes = []
  1537.             }
  1538.  
  1539.             var c = args.maxChildren || 2,
  1540.                 d = args.maxDepth || 4;
  1541.             Node.prototype = {
  1542.                 x: 0,
  1543.                 y: 0,
  1544.                 w: 0,
  1545.                 h: 0,
  1546.                 depth: 0,
  1547.                 items: null,
  1548.                 nodes: null,
  1549.                 exists: function(selector) {
  1550.                     for (var i = 0; i < this.items.length; ++i) {
  1551.                         var item = this.items[i];
  1552.                         if (item.x >= selector.x && item.y >= selector.y && item.x < selector.x + selector.w && item.y < selector.y + selector.h) return true
  1553.                     }
  1554.                     if (0 != this.nodes.length) {
  1555.                         var self = this;
  1556.                         return this.findOverlappingNodes(selector, function(dir) {
  1557.                             return self.nodes[dir].exists(selector)
  1558.                         })
  1559.                     }
  1560.                     return false;
  1561.                 },
  1562.                 retrieve: function(item, callback) {
  1563.                     for (var i = 0; i < this.items.length; ++i) callback(this.items[i]);
  1564.                     if (0 != this.nodes.length) {
  1565.                         var self = this;
  1566.                         this.findOverlappingNodes(item, function(dir) {
  1567.                             self.nodes[dir].retrieve(item, callback)
  1568.                         })
  1569.                     }
  1570.                 },
  1571.                 insert: function(a) {
  1572.                     if (0 != this.nodes.length) {
  1573.                         this.nodes[this.findInsertNode(a)].insert(a);
  1574.                     } else {
  1575.                         if (this.items.length >= c && this.depth < d) {
  1576.                             this.devide();
  1577.                             this.nodes[this.findInsertNode(a)].insert(a);
  1578.                         } else {
  1579.                             this.items.push(a);
  1580.                         }
  1581.                     }
  1582.                 },
  1583.                 findInsertNode: function(a) {
  1584.                     return a.x < this.x + this.w / 2 ? a.y < this.y + this.h / 2 ? 0 : 2 : a.y < this.y + this.h / 2 ? 1 : 3
  1585.                 },
  1586.                 findOverlappingNodes: function(a, b) {
  1587.                     return a.x < this.x + this.w / 2 && (a.y < this.y + this.h / 2 && b(0) || a.y >= this.y + this.h / 2 && b(2)) || a.x >= this.x + this.w / 2 && (a.y < this.y + this.h / 2 && b(1) || a.y >= this.y + this.h / 2 && b(3)) ? true : false
  1588.                 },
  1589.                 devide: function() {
  1590.                     var a = this.depth + 1,
  1591.                         c = this.w / 2,
  1592.                         d = this.h / 2;
  1593.                     this.nodes.push(new Node(this.x, this.y, c, d, a));
  1594.                     this.nodes.push(new Node(this.x + c, this.y, c, d, a));
  1595.                     this.nodes.push(new Node(this.x, this.y + d, c, d, a));
  1596.                     this.nodes.push(new Node(this.x + c, this.y + d, c, d, a));
  1597.                     a = this.items;
  1598.                     this.items = [];
  1599.                     for (c = 0; c < a.length; c++) this.insert(a[c])
  1600.                 },
  1601.                 clear: function() {
  1602.                     for (var a = 0; a < this.nodes.length; a++) this.nodes[a].clear();
  1603.                     this.items.length = 0;
  1604.                     this.nodes.length = 0
  1605.                 }
  1606.             };
  1607.             var internalSelector = {
  1608.                 x: 0,
  1609.                 y: 0,
  1610.                 w: 0,
  1611.                 h: 0
  1612.             };
  1613.             return {
  1614.                 root: new Node(args.minX, args.minY, args.maxX - args.minX, args.maxY - args.minY, 0),
  1615.                 insert: function(a) {
  1616.                     this.root.insert(a)
  1617.                 },
  1618.                 retrieve: function(a, b) {
  1619.                     this.root.retrieve(a, b)
  1620.                 },
  1621.                 retrieve2: function(a, b, c, d, callback) {
  1622.                     internalSelector.x = a;
  1623.                     internalSelector.y = b;
  1624.                     internalSelector.w = c;
  1625.                     internalSelector.h = d;
  1626.                     this.root.retrieve(internalSelector, callback)
  1627.                 },
  1628.                 exists: function(a) {
  1629.                     return this.root.exists(a)
  1630.                 },
  1631.                 clear: function() {
  1632.                     this.root.clear()
  1633.                 }
  1634.             }
  1635.         }
  1636.     };
  1637.     wjQuery(function() {
  1638.         function renderFavicon() {
  1639.             if (0 < playerCells.length) {
  1640.                 redCell.color = playerCells[0].color;
  1641.                 redCell.setName(playerCells[0].name);
  1642.             }
  1643.             ctx.clearRect(0, 0, 32, 32);
  1644.             ctx.save();
  1645.             ctx.translate(16, 16);
  1646.             ctx.scale(.4, .4);
  1647.             redCell.drawOneCell(ctx);
  1648.             ctx.restore();
  1649.             var favicon = document.getElementById("favicon"),
  1650.                 oldfavicon = favicon.cloneNode(true);
  1651.             oldfavicon.setAttribute("href", favCanvas.toDataURL("image/png"));
  1652.             favicon.parentNode.replaceChild(oldfavicon, favicon)
  1653.         }
  1654.  
  1655.         var redCell = new Cell(0, 0, 0, 32, "#ED1C24", ""),
  1656.             favCanvas = document.createElement("canvas");
  1657.         favCanvas.width = 32;
  1658.         favCanvas.height = 32;
  1659.         var ctx = favCanvas.getContext("2d");
  1660.         renderFavicon();
  1661.  
  1662.         // Causes stuttering..
  1663.         //setInterval(renderFavicon, 1E3);
  1664.  
  1665.         setInterval(drawChatBoard, 1E3);
  1666.     });
  1667.     wHandle.onload = gameLoop
  1668. })(window, window.jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement